From 7abaf972a4441b333608af3751db5892ba36d1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=AD=90=E9=93=AD?= Date: Fri, 21 Mar 2025 17:41:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/v1/cmb_cpn.proto | 79 ++++++--- go.mod | 4 +- go.sum | 1 - internal/data/mixrepoimpl/cmb.go | 22 +++ internal/server/http.go | 31 ++-- internal/service/cmb.go | 238 ++++----------------------- internal/service/cmb_mock.go | 140 +++------------- internal/service/cmb_order.go | 81 ++++++++++ internal/service/cmb_product.go | 56 +++++++ internal/service/cmb_query.go | 52 ++++++ internal/service/provider_set.go | 1 + internal/service/voucher.go | 30 ++-- third_party/swagger_ui/openapi.yaml | 241 +++++++++++++++++++++++++++- 13 files changed, 589 insertions(+), 387 deletions(-) create mode 100644 internal/service/cmb_order.go create mode 100644 internal/service/cmb_product.go create mode 100644 internal/service/cmb_query.go diff --git a/api/v1/cmb_cpn.proto b/api/v1/cmb_cpn.proto index 9bf79df..26a9543 100644 --- a/api/v1/cmb_cpn.proto +++ b/api/v1/cmb_cpn.proto @@ -3,6 +3,59 @@ syntax = "proto3"; package api.v1; option go_package = "voucher/api/v1;v1"; 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 { // 请求公共参数 @@ -94,7 +147,7 @@ message CmbQueryReply { 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 { // 接口调用返回码,1000 成功,1001 失败 @@ -156,29 +209,9 @@ message CmbNotifyReply { } -message EncryptBody { +message EncryptBodyRequest { string encryptBody = 1 [json_name = "encryptBody"]; } -message DecryptBody { +message DecryptBodyReply { 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"]; } \ No newline at end of file diff --git a/go.mod b/go.mod index 550aeb5..6b19700 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,8 @@ require ( go.opentelemetry.io/otel/sdk v1.28.0 go.opentelemetry.io/otel/trace v1.28.0 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 gopkg.in/yaml.v2 v2.4.0 gorm.io/driver/mysql v1.5.7 @@ -86,7 +88,7 @@ require ( golang.org/x/sys v0.30.0 // indirect golang.org/x/term v0.29.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/grpc v1.61.1 // indirect gopkg.in/ini.v1 v1.42.0 // indirect diff --git a/go.sum b/go.sum index 26e6c8d..22ebb29 100644 --- a/go.sum +++ b/go.sum @@ -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/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 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/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= diff --git a/internal/data/mixrepoimpl/cmb.go b/internal/data/mixrepoimpl/cmb.go index e615827..cc7a8b4 100644 --- a/internal/data/mixrepoimpl/cmb.go +++ b/internal/data/mixrepoimpl/cmb.go @@ -6,6 +6,8 @@ import ( "errors" "fmt" "github.com/go-kratos/kratos/v2/log" + http2 "github.com/go-kratos/kratos/v2/transport/http" + "io" "net/http" "net/url" "time" @@ -28,6 +30,23 @@ func NewCmbMixRepoImpl(bc *conf.Bootstrap) mixrepos.CmbMixRepo { 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) { bizStr, err := s.Verify(ctx, req) @@ -36,6 +55,7 @@ func (s *CmbMixRepoImpl) OrderVerify(ctx context.Context, req *v1.CmbRequest) (* } if len(bizStr) == 0 { + s.recordBody(ctx) return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递") } @@ -59,6 +79,7 @@ func (s *CmbMixRepoImpl) QueryVerify(ctx context.Context, req *v1.CmbRequest) (* } if len(bizStr) == 0 { + s.recordBody(ctx) return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递") } @@ -82,6 +103,7 @@ func (s *CmbMixRepoImpl) ProductQueryVerify(ctx context.Context, req *v1.CmbRequ } if len(bizStr) == 0 { + s.recordBody(ctx) return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递") } diff --git a/internal/server/http.go b/internal/server/http.go index 1cd1114..a499c19 100644 --- a/internal/server/http.go +++ b/internal/server/http.go @@ -13,6 +13,7 @@ import ( "github.com/go-kratos/kratos/v2/transport/http" "github.com/gorilla/handlers" http2 "net/http" + v1 "voucher/api/v1" "voucher/internal/conf" log2 "voucher/internal/pkg/log" "voucher/internal/service" @@ -23,34 +24,21 @@ func NewHTTPServer( c *conf.Bootstrap, log *log.Helper, accessLogger *log2.AccessLogger, - voucherService *service.VoucherService, + cmb *service.CmbService, ) *http.Server { //构建 server srv := buildHTTPServer(c, accessLogger, log) - r := srv.Route("/voucher") - - r.GET("/ping", func(ctx http.Context) error { + srv.Route("/").GET("ping", func(ctx http.Context) error { return ctx.String(http2.StatusOK, "pong") }) - cmb := r.Group("/cmb") + v1.RegisterCmbHTTPServer(srv, cmb) - v1 := cmb.Group("/v1") - - v1.POST("/orderMock", voucherService.CmbOrderMock) - v1.POST("/order", voucherService.CmbOrder) - - 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) + //v1.POST("/decryptBody", voucherService.DecryptBody) + //v1.POST("/queryWechatVoucherNotifyUrl", voucherService.QueryWechatVoucherNotifyUrl) + //v1.POST("/setWechatVoucherNotifyUrl", voucherService.SetWechatVoucherNotifyUrl) + //v1.POST("/test", voucherService.Test) return srv } @@ -135,6 +123,7 @@ func responseEncoder(w http.ResponseWriter, r *http.Request, data interface{}) e if data == nil { return nil } + codec, _ := http.CodecForRequest(r, "Accept") dataByte, err := codec.Marshal(data) 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())) - _, err = w.Write([]byte(fmt.Sprintf(`{"code":%d,"data":%s,"message":"%s"}`, http2.StatusOK, string(dataByte), "成功"))) + _, err = w.Write(dataByte) return err } diff --git a/internal/service/cmb.go b/internal/service/cmb.go index 4821e79..4a76c18 100644 --- a/internal/service/cmb.go +++ b/internal/service/cmb.go @@ -1,229 +1,57 @@ package service import ( - "encoding/json" - "github.com/go-kratos/kratos/v2/errors" + "context" "github.com/go-kratos/kratos/v2/log" - "github.com/go-kratos/kratos/v2/transport/http" - "io" - err2 "voucher/api/err" + "github.com/robfig/cron" v1 "voucher/api/v1" + "voucher/internal/biz" "voucher/internal/biz/bo" + "voucher/internal/biz/mixrepos" "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 - if err := json.Unmarshal(bodyBytes, &req); err != nil { - return nil, err2.ErrorCmbParamFail(err.Error()) - } - - if err := req.Validate(); err != nil { - return nil, err2.ErrorCmbParamFail(err.Error()) - } - - return req, nil +type CmbService struct { + bc *conf.Bootstrap + cron *cron.Cron + VoucherBiz *biz.VoucherBiz + CmbMixRepo mixrepos.CmbMixRepo + WechatCpnRepo wechatrepo.WechatCpnRepo } -func (s *VoucherService) CmbOrder(ctx http.Context) error { - - var ( - reply *v1.CmbReply - - bizReply *v1.CmbOrderReply - ) - - orderNo, err := s.cmbOrder(ctx) - - if err != nil { - 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, - } - - log.Errorf("cmbOrder: %v", err) - } else { - bizReply = &v1.CmbOrderReply{ - RespCode: vo.CmbResponseStatusSuccess.GetValue(), - RespMsg: "成功", - CodeNo: orderNo, - } +func NewCmbService( + bc *conf.Bootstrap, + cron *cron.Cron, + VoucherBiz *biz.VoucherBiz, + CmbMixRepo mixrepos.CmbMixRepo, + WechatCpnRepo wechatrepo.WechatCpnRepo, +) *CmbService { + return &CmbService{ + bc: bc, + cron: cron, + VoucherBiz: VoucherBiz, + CmbMixRepo: CmbMixRepo, + WechatCpnRepo: WechatCpnRepo, } +} - replyBizContent, _ := json.Marshal(bizReply) - xx := &bo.CmbResponseBo{ +func (c *CmbService) GetResponse(ctx context.Context, replyBizContent []byte) (*v1.CmbReply, error) { + + req := &bo.CmbResponseBo{ RespCode: vo.CmbResponseStatusSuccess.GetValue(), RespMsg: "成功", BizContent: string(replyBizContent), } - reply, err = s.CmbMixRepo.GetResponse(ctx, xx) - 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) + reply, err := c.CmbMixRepo.GetResponse(ctx, req) if err != nil { + log.Errorf("build cmb response fail: %v", err) return nil, err } - bizContent, err := v.CmbMixRepo.ProductQueryVerify(ctx, req) - 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) + return reply, nil } diff --git a/internal/service/cmb_mock.go b/internal/service/cmb_mock.go index 08cc1f8..4b71eaa 100644 --- a/internal/service/cmb_mock.go +++ b/internal/service/cmb_mock.go @@ -1,162 +1,64 @@ package service import ( + "context" "encoding/json" - "github.com/go-kratos/kratos/v2/transport/http" - "io" 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 { - return 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 + return nil, err } reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes)) 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 { - return 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 + return nil, err } reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes)) 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 { - return 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 + return nil, err } reply, err := s.CmbMixRepo.GetMockRequest(ctx, string(bizJsonBytes)) 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 { - return err + return nil, err } - var req *v1.EncryptBody - 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{ + return &v1.DecryptBodyReply{ DecryptBody: decryptBody, - }) -} - -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 + }, nil } diff --git a/internal/service/cmb_order.go b/internal/service/cmb_order.go new file mode 100644 index 0000000..e076c71 --- /dev/null +++ b/internal/service/cmb_order.go @@ -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 +} diff --git a/internal/service/cmb_product.go b/internal/service/cmb_product.go new file mode 100644 index 0000000..b172007 --- /dev/null +++ b/internal/service/cmb_product.go @@ -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) +} diff --git a/internal/service/cmb_query.go b/internal/service/cmb_query.go new file mode 100644 index 0000000..88577a9 --- /dev/null +++ b/internal/service/cmb_query.go @@ -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) +} diff --git a/internal/service/provider_set.go b/internal/service/provider_set.go index 99999d4..984a7a0 100644 --- a/internal/service/provider_set.go +++ b/internal/service/provider_set.go @@ -7,4 +7,5 @@ import ( // ProviderSetService is service providers. var ProviderSetService = wire.NewSet( NewVoucherService, + NewCmbService, ) diff --git a/internal/service/voucher.go b/internal/service/voucher.go index ed233c6..64b4c2b 100644 --- a/internal/service/voucher.go +++ b/internal/service/voucher.go @@ -1,33 +1,35 @@ package service import ( + "github.com/go-kratos/kratos/v2/transport/http" "github.com/robfig/cron" "voucher/internal/biz" - "voucher/internal/biz/mixrepos" - "voucher/internal/biz/wechatrepo" "voucher/internal/conf" ) type VoucherService struct { - bc *conf.Bootstrap - cron *cron.Cron - VoucherBiz *biz.VoucherBiz - CmbMixRepo mixrepos.CmbMixRepo - WechatCpnRepo wechatrepo.WechatCpnRepo + bc *conf.Bootstrap + cron *cron.Cron + VoucherBiz *biz.VoucherBiz } func NewVoucherService( bc *conf.Bootstrap, cron *cron.Cron, VoucherBiz *biz.VoucherBiz, - CmbMixRepo mixrepos.CmbMixRepo, - WechatCpnRepo wechatrepo.WechatCpnRepo, ) *VoucherService { return &VoucherService{ - bc: bc, - cron: cron, - VoucherBiz: VoucherBiz, - CmbMixRepo: CmbMixRepo, - WechatCpnRepo: WechatCpnRepo, + bc: bc, + cron: cron, + VoucherBiz: VoucherBiz, } } + +func (s *VoucherService) Test(ctx http.Context) error { + + if err := s.VoucherBiz.ExecuteNotice(ctx); err != nil { + return err + } + + return nil +} diff --git a/third_party/swagger_ui/openapi.yaml b/third_party/swagger_ui/openapi.yaml index f8f3735..c91552e 100644 --- a/third_party/swagger_ui/openapi.yaml +++ b/third_party/swagger_ui/openapi.yaml @@ -3,8 +3,243 @@ openapi: 3.0.3 info: - title: "" + title: Cmb API 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: - 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: |- + 请求公共参数 + 合作方唯一ID,32位定长 + aid: + type: string + description: 应用唯一ID,32位定长 + 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