代码调整

This commit is contained in:
李子铭 2025-03-21 17:41:36 +08:00
parent 4f71228ff1
commit 7abaf972a4
13 changed files with 589 additions and 387 deletions

View File

@ -3,6 +3,59 @@ syntax = "proto3";
package api.v1; package api.v1;
option go_package = "voucher/api/v1;v1"; option go_package = "voucher/api/v1;v1";
import "validate/validate.proto"; import "validate/validate.proto";
import "google/api/annotations.proto";
service Cmb {
rpc Order (CmbRequest) returns (CmbReply) {
option (google.api.http) = {
post: "/voucher/cmb/v1/order",
body: "*"
};
}
rpc Query (CmbRequest) returns (CmbReply) {
option (google.api.http) = {
post: "/voucher/cmb/v1/query",
body: "*"
};
}
rpc QueryProduct (CmbRequest) returns (CmbReply) {
option (google.api.http) = {
post: "/voucher/cmb/v1/product/query",
body: "*"
};
}
rpc OrderMock (CmbOrderRequest) returns (CmbRequest) {
option (google.api.http) = {
post: "/voucher/cmb/v1/orderMock",
body: "*"
};
}
rpc QueryMock (CmbQueryRequest) returns (CmbRequest) {
option (google.api.http) = {
post: "/voucher/cmb/v1/queryMock",
body: "*"
};
}
rpc QueryProductMock (CmbQueryProductRequest) returns (CmbRequest) {
option (google.api.http) = {
post: "/voucher/cmb/v1/product/queryMock",
body: "*"
};
}
rpc DecryptBody (EncryptBodyRequest) returns (DecryptBodyReply) {
option (google.api.http) = {
post: "/voucher/cmb/v1/decryptBody",
body: "*"
};
}
}
message CmbRequest { message CmbRequest {
// //
@ -94,7 +147,7 @@ message CmbQueryReply {
message CmbQueryProductRequest { message CmbQueryProductRequest {
// //
// //
string activityId = 9 [json_name = "activityId", (validate.rules).string = {min_len: 1,max_len: 32}]; string activityId = 9 [json_name = "activityId"];
} }
message CmbQueryProductReply { message CmbQueryProductReply {
// 1000 1001 // 1000 1001
@ -156,29 +209,9 @@ message CmbNotifyReply {
} }
message EncryptBody { message EncryptBodyRequest {
string encryptBody = 1 [json_name = "encryptBody"]; string encryptBody = 1 [json_name = "encryptBody"];
} }
message DecryptBody { message DecryptBodyReply {
string decryptBody = 1 [json_name = "decryptBody"]; string decryptBody = 1 [json_name = "decryptBody"];
}
message QueryWechatVoucherNotifyUrlRequest {
string mch_id = 1 [json_name = "mch_id"];
string mch_cert_no = 2 [json_name = "mch_cert_no"];
}
message QueryWechatVoucherNotifyUrlReply {
string url = 1 [json_name = "url"];
}
message SetWechatVoucherNotifyUrlRequest {
string mch_id = 1 [json_name = "mch_id"];
string mch_cert_no = 2 [json_name = "mch_cert_no"];
string url = 3 [json_name = "url"];
}
message SetWechatVoucherNotifyUrlReply {
string mch_id = 1 [json_name = "mch_id"];
string url = 2 [json_name = "url"];
string mch_cert_no = 3 [json_name = "mch_cert_no"];
} }

4
go.mod
View File

@ -28,6 +28,8 @@ require (
go.opentelemetry.io/otel/sdk v1.28.0 go.opentelemetry.io/otel/sdk v1.28.0
go.opentelemetry.io/otel/trace v1.28.0 go.opentelemetry.io/otel/trace v1.28.0
go.uber.org/automaxprocs v1.5.1 go.uber.org/automaxprocs v1.5.1
golang.org/x/time v0.5.0
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917
google.golang.org/protobuf v1.34.2 google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
gorm.io/driver/mysql v1.5.7 gorm.io/driver/mysql v1.5.7
@ -86,7 +88,7 @@ require (
golang.org/x/sys v0.30.0 // indirect golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0 // indirect golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.5.0 // indirect google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/grpc v1.61.1 // indirect google.golang.org/grpc v1.61.1 // indirect
gopkg.in/ini.v1 v1.42.0 // indirect gopkg.in/ini.v1 v1.42.0 // indirect

1
go.sum
View File

@ -129,7 +129,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=

View File

@ -6,6 +6,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
http2 "github.com/go-kratos/kratos/v2/transport/http"
"io"
"net/http" "net/http"
"net/url" "net/url"
"time" "time"
@ -28,6 +30,23 @@ func NewCmbMixRepoImpl(bc *conf.Bootstrap) mixrepos.CmbMixRepo {
return &CmbMixRepoImpl{bc: bc} return &CmbMixRepoImpl{bc: bc}
} }
func (c *CmbMixRepoImpl) recordBody(ctx context.Context) {
httpRequest, ok := http2.RequestFromServerContext(ctx)
if !ok {
log.Errorf("read body not ok")
return
}
bodyBytes, err := io.ReadAll(httpRequest.Body)
if err != nil {
log.Errorf("read body not ok, %v", err)
return
}
log.Errorf("body %v", string(bodyBytes))
}
func (s *CmbMixRepoImpl) OrderVerify(ctx context.Context, req *v1.CmbRequest) (*v1.CmbOrderRequest, error) { func (s *CmbMixRepoImpl) OrderVerify(ctx context.Context, req *v1.CmbRequest) (*v1.CmbOrderRequest, error) {
bizStr, err := s.Verify(ctx, req) bizStr, err := s.Verify(ctx, req)
@ -36,6 +55,7 @@ func (s *CmbMixRepoImpl) OrderVerify(ctx context.Context, req *v1.CmbRequest) (*
} }
if len(bizStr) == 0 { if len(bizStr) == 0 {
s.recordBody(ctx)
return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递") return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递")
} }
@ -59,6 +79,7 @@ func (s *CmbMixRepoImpl) QueryVerify(ctx context.Context, req *v1.CmbRequest) (*
} }
if len(bizStr) == 0 { if len(bizStr) == 0 {
s.recordBody(ctx)
return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递") return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递")
} }
@ -82,6 +103,7 @@ func (s *CmbMixRepoImpl) ProductQueryVerify(ctx context.Context, req *v1.CmbRequ
} }
if len(bizStr) == 0 { if len(bizStr) == 0 {
s.recordBody(ctx)
return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递") return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递")
} }

View File

@ -13,6 +13,7 @@ import (
"github.com/go-kratos/kratos/v2/transport/http" "github.com/go-kratos/kratos/v2/transport/http"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
http2 "net/http" http2 "net/http"
v1 "voucher/api/v1"
"voucher/internal/conf" "voucher/internal/conf"
log2 "voucher/internal/pkg/log" log2 "voucher/internal/pkg/log"
"voucher/internal/service" "voucher/internal/service"
@ -23,34 +24,21 @@ func NewHTTPServer(
c *conf.Bootstrap, c *conf.Bootstrap,
log *log.Helper, log *log.Helper,
accessLogger *log2.AccessLogger, accessLogger *log2.AccessLogger,
voucherService *service.VoucherService, cmb *service.CmbService,
) *http.Server { ) *http.Server {
//构建 server //构建 server
srv := buildHTTPServer(c, accessLogger, log) srv := buildHTTPServer(c, accessLogger, log)
r := srv.Route("/voucher") srv.Route("/").GET("ping", func(ctx http.Context) error {
r.GET("/ping", func(ctx http.Context) error {
return ctx.String(http2.StatusOK, "pong") return ctx.String(http2.StatusOK, "pong")
}) })
cmb := r.Group("/cmb") v1.RegisterCmbHTTPServer(srv, cmb)
v1 := cmb.Group("/v1") //v1.POST("/decryptBody", voucherService.DecryptBody)
//v1.POST("/queryWechatVoucherNotifyUrl", voucherService.QueryWechatVoucherNotifyUrl)
v1.POST("/orderMock", voucherService.CmbOrderMock) //v1.POST("/setWechatVoucherNotifyUrl", voucherService.SetWechatVoucherNotifyUrl)
v1.POST("/order", voucherService.CmbOrder) //v1.POST("/test", voucherService.Test)
v1.POST("/queryMock", voucherService.CmbQueryMock)
v1.POST("/query", voucherService.CmbQuery)
v1.POST("/product/queryMock", voucherService.CmbProductQueryMock)
v1.POST("/product/query", voucherService.CmbProductQuery)
v1.POST("/decryptBody", voucherService.DecryptBody)
v1.POST("/queryWechatVoucherNotifyUrl", voucherService.QueryWechatVoucherNotifyUrl)
v1.POST("/setWechatVoucherNotifyUrl", voucherService.SetWechatVoucherNotifyUrl)
v1.POST("/test", voucherService.Test)
return srv return srv
} }
@ -135,6 +123,7 @@ func responseEncoder(w http.ResponseWriter, r *http.Request, data interface{}) e
if data == nil { if data == nil {
return nil return nil
} }
codec, _ := http.CodecForRequest(r, "Accept") codec, _ := http.CodecForRequest(r, "Accept")
dataByte, err := codec.Marshal(data) dataByte, err := codec.Marshal(data)
if err != nil { if err != nil {
@ -142,7 +131,7 @@ func responseEncoder(w http.ResponseWriter, r *http.Request, data interface{}) e
} }
w.Header().Set("Content-Type", fmt.Sprintf("application/%s", codec.Name())) w.Header().Set("Content-Type", fmt.Sprintf("application/%s", codec.Name()))
_, err = w.Write([]byte(fmt.Sprintf(`{"code":%d,"data":%s,"message":"%s"}`, http2.StatusOK, string(dataByte), "成功"))) _, err = w.Write(dataByte)
return err return err
} }

View File

@ -1,229 +1,57 @@
package service package service
import ( import (
"encoding/json" "context"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/transport/http" "github.com/robfig/cron"
"io"
err2 "voucher/api/err"
v1 "voucher/api/v1" v1 "voucher/api/v1"
"voucher/internal/biz"
"voucher/internal/biz/bo" "voucher/internal/biz/bo"
"voucher/internal/biz/mixrepos"
"voucher/internal/biz/vo" "voucher/internal/biz/vo"
"voucher/internal/biz/wechatrepo"
"voucher/internal/conf"
) )
func (s *VoucherService) buildCmbRequest(bodyBytes []byte) (*v1.CmbRequest, error) { var _ v1.CmbHTTPServer = (*CmbService)(nil)
var req *v1.CmbRequest type CmbService struct {
if err := json.Unmarshal(bodyBytes, &req); err != nil { bc *conf.Bootstrap
return nil, err2.ErrorCmbParamFail(err.Error()) cron *cron.Cron
} VoucherBiz *biz.VoucherBiz
CmbMixRepo mixrepos.CmbMixRepo
if err := req.Validate(); err != nil { WechatCpnRepo wechatrepo.WechatCpnRepo
return nil, err2.ErrorCmbParamFail(err.Error())
}
return req, nil
} }
func (s *VoucherService) CmbOrder(ctx http.Context) error { func NewCmbService(
bc *conf.Bootstrap,
var ( cron *cron.Cron,
reply *v1.CmbReply VoucherBiz *biz.VoucherBiz,
CmbMixRepo mixrepos.CmbMixRepo,
bizReply *v1.CmbOrderReply WechatCpnRepo wechatrepo.WechatCpnRepo,
) ) *CmbService {
return &CmbService{
orderNo, err := s.cmbOrder(ctx) bc: bc,
cron: cron,
if err != nil { VoucherBiz: VoucherBiz,
se := errors.FromError(err) CmbMixRepo: CmbMixRepo,
WechatCpnRepo: WechatCpnRepo,
if len(se.Reason) == 0 {
se.Reason = err2.CmbErr_CMB_UNKNOWN.String()
}
bizReply = &v1.CmbOrderReply{
RespCode: vo.CmbResponseStatusFail.GetValue(),
RespMsg: se.Message,
CodeNo: "",
ThirdErrCode: se.Reason,
}
log.Errorf("cmbOrder: %v", err)
} else {
bizReply = &v1.CmbOrderReply{
RespCode: vo.CmbResponseStatusSuccess.GetValue(),
RespMsg: "成功",
CodeNo: orderNo,
}
} }
}
replyBizContent, _ := json.Marshal(bizReply) func (c *CmbService) GetResponse(ctx context.Context, replyBizContent []byte) (*v1.CmbReply, error) {
xx := &bo.CmbResponseBo{
req := &bo.CmbResponseBo{
RespCode: vo.CmbResponseStatusSuccess.GetValue(), RespCode: vo.CmbResponseStatusSuccess.GetValue(),
RespMsg: "成功", RespMsg: "成功",
BizContent: string(replyBizContent), BizContent: string(replyBizContent),
} }
reply, err = s.CmbMixRepo.GetResponse(ctx, xx) reply, err := c.CmbMixRepo.GetResponse(ctx, req)
if err != nil {
log.Errorf("CmbOrder GetResponse: %v", err)
return ctx.JSON(400, err)
}
return ctx.JSON(200, reply)
}
func (v *VoucherService) cmbOrder(ctx http.Context) (string, error) {
bodyBytes, err := io.ReadAll(ctx.Request().Body)
if err != nil {
return "", err2.ErrorCmbParamFail(err.Error())
}
req, err := v.buildCmbRequest(bodyBytes)
if err != nil {
return "", err
}
bizContent, err := v.CmbMixRepo.OrderVerify(ctx, req)
if err != nil {
log.Errorf("cmbOrder body: %s", string(bodyBytes))
return "", err
}
boReq := &bo.OrderCreateReqBo{
OutBizNo: bizContent.TransactionId,
ProductNo: bizContent.ActivityId,
Account: bizContent.CmbUid,
AppID: bizContent.AppId,
Attach: bizContent.Attach,
AccountType: vo.OrderAccountTypeOpenId,
Type: vo.OrderTypeCmb,
NotifyUrl: v.bc.Cmb.NotifyUrl,
}
orderNo, err := v.VoucherBiz.CmbOrder(ctx, boReq)
if err != nil {
return "", err
}
return orderNo, nil
}
func (s *VoucherService) CmbProductQuery(ctx http.Context) error {
var (
reply *v1.CmbReply
bizReply *v1.CmbQueryProductReply
)
bizReply, err := s.cmbProductQuery(ctx)
if err != nil {
se := errors.FromError(err)
if len(se.Reason) == 0 {
se.Reason = err2.CmbErr_CMB_UNKNOWN.String()
}
bizReply = &v1.CmbQueryProductReply{
RespCode: vo.CmbResponseStatusFail.GetValue(),
RespMsg: se.Message,
ThirdErrCode: se.Reason,
}
log.Errorf("cmbProductQuery: %v", err)
}
replyBizContent, _ := json.Marshal(bizReply)
xx := &bo.CmbResponseBo{
RespCode: vo.CmbResponseStatusSuccess.GetValue(),
RespMsg: "成功",
BizContent: string(replyBizContent),
}
reply, err = s.CmbMixRepo.GetResponse(ctx, xx)
if err != nil {
log.Errorf("cmbProductQuery GetResponse: %v", err)
return ctx.JSON(400, err)
}
return ctx.JSON(200, reply)
}
func (v *VoucherService) cmbProductQuery(ctx http.Context) (*v1.CmbQueryProductReply, error) {
bodyBytes, err := io.ReadAll(ctx.Request().Body)
if err != nil {
return nil, err2.ErrorCmbParamFail(err.Error())
}
req, err := v.buildCmbRequest(bodyBytes)
if err != nil { if err != nil {
log.Errorf("build cmb response fail: %v", err)
return nil, err return nil, err
} }
bizContent, err := v.CmbMixRepo.ProductQueryVerify(ctx, req) return reply, nil
if err != nil {
log.Errorf("cmbProductQuery body: %s", string(bodyBytes))
return nil, err
}
return v.VoucherBiz.CmbProductQuery(ctx, bizContent.ActivityId)
}
func (s *VoucherService) CmbQuery(ctx http.Context) error {
var (
reply *v1.CmbReply
req = &bo.CmbResponseBo{}
)
bizReply, err := s.cmbQuery(ctx)
if err != nil {
req.RespCode = vo.CmbResponseStatusFail.GetValue()
req.RespMsg = err.Error()
req.BizContent = ""
log.Errorf("CmbQuery: %v", err)
} else {
replyBizContentBytes, _ := json.Marshal(bizReply)
req.RespCode = vo.CmbResponseStatusSuccess.GetValue()
req.RespMsg = "成功"
req.BizContent = string(replyBizContentBytes)
}
reply, err = s.CmbMixRepo.GetResponse(ctx, req)
if err != nil {
log.Errorf("cmbProductQuery GetResponse: %v", err)
return ctx.JSON(400, err)
}
return ctx.JSON(200, reply)
}
func (v *VoucherService) cmbQuery(ctx http.Context) (*v1.CmbQueryReply, error) {
bodyBytes, err := io.ReadAll(ctx.Request().Body)
if err != nil {
return nil, err2.ErrorCmbParamFail(err.Error())
}
req, err := v.buildCmbRequest(bodyBytes)
if err != nil {
return nil, err
}
bizContent, err := v.CmbMixRepo.QueryVerify(ctx, req)
if err != nil {
return nil, err
}
return v.VoucherBiz.CmbQuery(ctx, bizContent.CodeNo)
} }

View File

@ -1,162 +1,64 @@
package service package service
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/go-kratos/kratos/v2/transport/http"
"io"
v1 "voucher/api/v1" v1 "voucher/api/v1"
) )
func (s *VoucherService) CmbOrderMock(ctx http.Context) error { func (s *CmbService) OrderMock(ctx context.Context, request *v1.CmbOrderRequest) (*v1.CmbRequest, error) {
bodyBytes, err := io.ReadAll(ctx.Request().Body) bizJsonBytes, err := json.Marshal(request)
if err != nil { if err != nil {
return err return nil, err
}
var req *v1.CmbOrderRequest
if err = json.Unmarshal(bodyBytes, &req); err != nil {
return err
}
bizJsonBytes, err := json.Marshal(req)
if err != nil {
return err
} }
reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes)) reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes))
if err != nil { if err != nil {
return err return nil, err
} }
return ctx.JSON(200, reply) return reply, nil
} }
func (s *VoucherService) CmbQueryMock(ctx http.Context) error { func (s *CmbService) QueryMock(ctx context.Context, request *v1.CmbQueryRequest) (*v1.CmbRequest, error) {
bodyBytes, err := io.ReadAll(ctx.Request().Body) bizJsonBytes, err := json.Marshal(request)
if err != nil { if err != nil {
return err return nil, err
}
var req *v1.CmbQueryRequest
if err = json.Unmarshal(bodyBytes, &req); err != nil {
return err
}
bizJsonBytes, err := json.Marshal(req)
if err != nil {
return err
} }
reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes)) reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes))
if err != nil { if err != nil {
return err return nil, err
} }
return ctx.JSON(200, reply) return reply, nil
} }
func (s *VoucherService) CmbProductQueryMock(ctx http.Context) error { func (s *CmbService) QueryProductMock(ctx context.Context, request *v1.CmbQueryProductRequest) (*v1.CmbRequest, error) {
bodyBytes, err := io.ReadAll(ctx.Request().Body) bizJsonBytes, err := json.Marshal(request)
if err != nil { if err != nil {
return err return nil, err
}
var req *v1.CmbQueryProductRequest
if err = json.Unmarshal(bodyBytes, &req); err != nil {
return err
}
bizJsonBytes, err := json.Marshal(req)
if err != nil {
return err
} }
reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes)) reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes))
if err != nil { if err != nil {
return err return nil, err
} }
return ctx.JSON(200, reply) return reply, nil
} }
func (s *VoucherService) DecryptBody(ctx http.Context) error { func (s *CmbService) DecryptBody(ctx context.Context, request *v1.EncryptBodyRequest) (*v1.DecryptBodyReply, error) {
bodyBytes, err := io.ReadAll(ctx.Request().Body) decryptBody, err := s.CmbMixRepo.Decrypt(ctx, request.EncryptBody)
if err != nil { if err != nil {
return err return nil, err
} }
var req *v1.EncryptBody return &v1.DecryptBodyReply{
if err = json.Unmarshal(bodyBytes, &req); err != nil {
return err
}
decryptBody, err := s.CmbMixRepo.Decrypt(ctx, req.EncryptBody)
if err != nil {
return err
}
return ctx.JSON(200, &v1.DecryptBody{
DecryptBody: decryptBody, DecryptBody: decryptBody,
}) }, nil
}
func (s *VoucherService) QueryWechatVoucherNotifyUrl(ctx http.Context) error {
bodyBytes, err := io.ReadAll(ctx.Request().Body)
if err != nil {
return err
}
var req *v1.QueryWechatVoucherNotifyUrlRequest
if err = json.Unmarshal(bodyBytes, &req); err != nil {
return err
}
rep, err := s.VoucherBiz.WechatCpnRepo.QueryCallback(ctx)
if err != nil {
return err
}
return ctx.JSON(200, &v1.QueryWechatVoucherNotifyUrlReply{
Url: *rep.NotifyUrl,
})
}
func (s *VoucherService) SetWechatVoucherNotifyUrl(ctx http.Context) error {
//bodyBytes, err := io.ReadAll(ctx.Request().Body)
//if err != nil {
// return err
//}
//
//var req *v1.SetWechatVoucherNotifyUrlRequest
//if err = json.Unmarshal(bodyBytes, &req); err != nil {
// return err
//}
//
//rep, err := s.VoucherBiz.WechatCpnRepo.SetCallback(ctx, req.MchId, req.MchCertNo, req.Url)
//if err != nil {
// return err
//}
//
//return ctx.JSON(200, &v1.SetWechatVoucherNotifyUrlReply{
// MchId: req.MchId,
// Url: *rep.NotifyUrl,
//})
return nil
}
func (s *VoucherService) Test(ctx http.Context) error {
if err := s.VoucherBiz.ExecuteNotice(ctx); err != nil {
return err
}
return nil
} }

View File

@ -0,0 +1,81 @@
package service
import (
"context"
"encoding/json"
"github.com/go-kratos/kratos/v2/errors"
err2 "voucher/api/err"
v1 "voucher/api/v1"
"voucher/internal/biz/bo"
"voucher/internal/biz/vo"
)
func (c *CmbService) OrderSuccess(ctx context.Context, orderNo string) (*v1.CmbReply, error) {
bizReply := &v1.CmbOrderReply{
RespCode: vo.CmbResponseStatusSuccess.GetValue(),
RespMsg: "成功",
CodeNo: orderNo,
}
replyBizContent, _ := json.Marshal(bizReply)
return c.GetResponse(ctx, replyBizContent)
}
func (c *CmbService) OrderFail(ctx context.Context, err error) (*v1.CmbReply, error) {
se := errors.FromError(err)
if len(se.Reason) == 0 {
se.Reason = err2.CmbErr_CMB_UNKNOWN.String()
}
bizReply := &v1.CmbOrderReply{
RespCode: vo.CmbResponseStatusFail.GetValue(),
RespMsg: se.Message,
CodeNo: "",
ThirdErrCode: se.Reason,
}
replyBizContent, _ := json.Marshal(bizReply)
return c.GetResponse(ctx, replyBizContent)
}
func (c *CmbService) Order(ctx context.Context, request *v1.CmbRequest) (*v1.CmbReply, error) {
orderNo, err := c.order(ctx, request)
if err != nil {
return c.OrderFail(ctx, err)
}
return c.OrderSuccess(ctx, orderNo)
}
func (c *CmbService) order(ctx context.Context, request *v1.CmbRequest) (string, error) {
bizContent, err := c.CmbMixRepo.OrderVerify(ctx, request)
if err != nil {
return "", err
}
boReq := &bo.OrderCreateReqBo{
OutBizNo: bizContent.TransactionId,
ProductNo: bizContent.ActivityId,
Account: bizContent.CmbUid,
AppID: bizContent.AppId,
Attach: bizContent.Attach,
AccountType: vo.OrderAccountTypeOpenId,
Type: vo.OrderTypeCmb,
NotifyUrl: c.bc.Cmb.NotifyUrl,
}
orderNo, err := c.VoucherBiz.CmbOrder(ctx, boReq)
if err != nil {
return "", err
}
return orderNo, nil
}

View File

@ -0,0 +1,56 @@
package service
import (
"context"
"encoding/json"
"github.com/go-kratos/kratos/v2/errors"
err2 "voucher/api/err"
v1 "voucher/api/v1"
"voucher/internal/biz/vo"
)
func (c *CmbService) QueryProductsuccess(ctx context.Context, bizReply *v1.CmbQueryProductReply) (*v1.CmbReply, error) {
replyBizContent, _ := json.Marshal(bizReply)
return c.GetResponse(ctx, replyBizContent)
}
func (c *CmbService) QueryProductFail(ctx context.Context, err error) (*v1.CmbReply, error) {
se := errors.FromError(err)
if len(se.Reason) == 0 {
se.Reason = err2.CmbErr_CMB_UNKNOWN.String()
}
bizReply := &v1.CmbQueryProductReply{
RespCode: vo.CmbResponseStatusFail.GetValue(),
RespMsg: se.Message,
ThirdErrCode: se.Reason,
}
replyBizContent, _ := json.Marshal(bizReply)
return c.GetResponse(ctx, replyBizContent)
}
func (c *CmbService) QueryProduct(ctx context.Context, request *v1.CmbRequest) (*v1.CmbReply, error) {
bizReply, err := c.qaueryProduct(ctx, request)
if err != nil {
return c.QueryProductFail(ctx, err)
}
return c.QueryProductsuccess(ctx, bizReply)
}
func (c *CmbService) qaueryProduct(ctx context.Context, request *v1.CmbRequest) (*v1.CmbQueryProductReply, error) {
bizContent, err := c.CmbMixRepo.ProductQueryVerify(ctx, request)
if err != nil {
return nil, err
}
return c.VoucherBiz.CmbProductQuery(ctx, bizContent.ActivityId)
}

View File

@ -0,0 +1,52 @@
package service
import (
"context"
"encoding/json"
"github.com/go-kratos/kratos/v2/errors"
err2 "voucher/api/err"
v1 "voucher/api/v1"
)
func (c *CmbService) QuerySuccess(ctx context.Context, bizReply *v1.CmbQueryReply) (*v1.CmbReply, error) {
replyBizContent, _ := json.Marshal(bizReply)
return c.GetResponse(ctx, replyBizContent)
}
func (c *CmbService) QueryFail(ctx context.Context, err error) (*v1.CmbReply, error) {
se := errors.FromError(err)
if len(se.Reason) == 0 {
se.Reason = err2.CmbErr_CMB_UNKNOWN.String()
}
bizReply := &v1.CmbQueryReply{}
replyBizContent, _ := json.Marshal(bizReply)
return c.GetResponse(ctx, replyBizContent)
}
func (c *CmbService) Query(ctx context.Context, request *v1.CmbRequest) (*v1.CmbReply, error) {
orderNo, err := c.query(ctx, request)
if err != nil {
return c.QueryFail(ctx, err)
}
return c.QuerySuccess(ctx, orderNo)
}
func (c *CmbService) query(ctx context.Context, request *v1.CmbRequest) (*v1.CmbQueryReply, error) {
bizContent, err := c.CmbMixRepo.QueryVerify(ctx, request)
if err != nil {
return nil, err
}
return c.VoucherBiz.CmbQuery(ctx, bizContent.CodeNo)
}

View File

@ -7,4 +7,5 @@ import (
// ProviderSetService is service providers. // ProviderSetService is service providers.
var ProviderSetService = wire.NewSet( var ProviderSetService = wire.NewSet(
NewVoucherService, NewVoucherService,
NewCmbService,
) )

View File

@ -1,33 +1,35 @@
package service package service
import ( import (
"github.com/go-kratos/kratos/v2/transport/http"
"github.com/robfig/cron" "github.com/robfig/cron"
"voucher/internal/biz" "voucher/internal/biz"
"voucher/internal/biz/mixrepos"
"voucher/internal/biz/wechatrepo"
"voucher/internal/conf" "voucher/internal/conf"
) )
type VoucherService struct { type VoucherService struct {
bc *conf.Bootstrap bc *conf.Bootstrap
cron *cron.Cron cron *cron.Cron
VoucherBiz *biz.VoucherBiz VoucherBiz *biz.VoucherBiz
CmbMixRepo mixrepos.CmbMixRepo
WechatCpnRepo wechatrepo.WechatCpnRepo
} }
func NewVoucherService( func NewVoucherService(
bc *conf.Bootstrap, bc *conf.Bootstrap,
cron *cron.Cron, cron *cron.Cron,
VoucherBiz *biz.VoucherBiz, VoucherBiz *biz.VoucherBiz,
CmbMixRepo mixrepos.CmbMixRepo,
WechatCpnRepo wechatrepo.WechatCpnRepo,
) *VoucherService { ) *VoucherService {
return &VoucherService{ return &VoucherService{
bc: bc, bc: bc,
cron: cron, cron: cron,
VoucherBiz: VoucherBiz, VoucherBiz: VoucherBiz,
CmbMixRepo: CmbMixRepo,
WechatCpnRepo: WechatCpnRepo,
} }
} }
func (s *VoucherService) Test(ctx http.Context) error {
if err := s.VoucherBiz.ExecuteNotice(ctx); err != nil {
return err
}
return nil
}

View File

@ -3,8 +3,243 @@
openapi: 3.0.3 openapi: 3.0.3
info: info:
title: "" title: Cmb API
version: 0.0.1 version: 0.0.1
paths: {} paths:
/voucher/cmb/v1/decryptBody:
post:
tags:
- Cmb
operationId: Cmb_DecryptBody
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.EncryptBodyRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.DecryptBodyReply'
/voucher/cmb/v1/order:
post:
tags:
- Cmb
operationId: Cmb_Order
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbReply'
/voucher/cmb/v1/orderMock:
post:
tags:
- Cmb
operationId: Cmb_OrderMock
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbOrderRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbRequest'
/voucher/cmb/v1/product/query:
post:
tags:
- Cmb
operationId: Cmb_QueryProduct
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbReply'
/voucher/cmb/v1/product/queryMock:
post:
tags:
- Cmb
operationId: Cmb_QueryProductMock
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbQueryProductRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbRequest'
/voucher/cmb/v1/query:
post:
tags:
- Cmb
operationId: Cmb_Query
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbReply'
/voucher/cmb/v1/queryMock:
post:
tags:
- Cmb
operationId: Cmb_QueryMock
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbQueryRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/api.v1.CmbRequest'
components: components:
schemas: {} schemas:
api.v1.CmbOrderRequest:
type: object
properties:
transactionId:
type: string
description: |-
业务参数
唯一流水号需支持14天内幂等
activityId:
type: string
description: 外部合作方权益批次号
cmbUid:
type: string
description: 招商银行用户号 用户标识比如手机号、支付宝openId
appId:
type: string
description: 应用id
cmbUidType:
type: string
description: 用户标识类型0-手机号1-支付宝openId
timestamp:
type: string
description: 时间戳长度为13位精度为毫秒
attach:
type: string
description: 拓展参数
api.v1.CmbQueryProductRequest:
type: object
properties:
activityId:
type: string
description: |-
业务参数
外部合作方权益批次号
api.v1.CmbQueryRequest:
type: object
properties:
codeNo:
type: string
description: |-
业务参数
外部合作方权益批次号
api.v1.CmbReply:
type: object
properties:
respCode:
type: string
description: |-
响应公共参数
接口调用返回码1000 成功1001 失败
respMsg:
type: string
description: 返回话术,失败信息落此字段
date:
type: string
description: 时间戳 yyyyMMddHHmmss
keyAlias:
type: string
description: 合作方密钥对别名
cmbKeyAlias:
type: string
description: 掌上生活密钥对别名
encryptBody:
type: string
description: 加密报文是否需要加密请查看各API的说明文档
sign:
type: string
description: 签名,具体详见签名规范
api.v1.CmbRequest:
type: object
properties:
mid:
type: string
description: |-
请求公共参数
合作方唯一ID32位定长
aid:
type: string
description: 应用唯一ID32位定长
date:
type: string
description: 时间戳 yyyyMMddHHmmss
random:
type: string
description: 随机字符串保证签名不可预测不长于32位
keyAlias:
type: string
description: 合作方密钥对别名
cmbKeyAlias:
type: string
description: 掌上生活密钥对别名
encryptBody:
type: string
description: 加密报文是否需要加密请查看各API的说明文档
sign:
type: string
description: 签名,具体详见签名规范
api.v1.DecryptBodyReply:
type: object
properties:
decryptBody:
type: string
api.v1.EncryptBodyRequest:
type: object
properties:
encryptBody:
type: string
tags:
- name: Cmb