From 6b65f24fa52859469f47bc2a281c7fd4cb1d4390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=AD=90=E9=93=AD?= Date: Wed, 5 Mar 2025 09:41:07 +0800 Subject: [PATCH] cmb --- configs/config.yaml | 4 ++ internal/biz/bo/order_bo.go | 1 + internal/biz/cmb.go | 43 ++++++++++++++++++++-- internal/biz/cmb/consume.go | 2 +- internal/biz/cmb/voucher.go | 24 ++---------- internal/biz/voucher.go | 7 ++++ internal/biz/wechatrepo/cpn.go | 2 + internal/data/model/order.gen.go | 1 + internal/data/repoimpl/order.go | 1 + internal/data/wechatrepoimpl/cpn.go | 14 +++---- internal/data/wechatrepoimpl/cpn_status.go | 2 +- internal/service/cmb.go | 1 + 12 files changed, 68 insertions(+), 34 deletions(-) diff --git a/configs/config.yaml b/configs/config.yaml index 3c80e36..8c7502f 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -47,6 +47,10 @@ wechat: mchCertificateSerialNumber: "4D081089DEB385316CBDCB55C070287E4920AC76" cmb: + sm2Prk: "" # 私钥 非对称加解密算法SM2 公钥长度为65字节,私钥长度为32字节。非对称密钥是基于国密推荐的椭圆曲线生成的,国密推荐曲线sm2p256v1 + sm2Puk: "" # 公钥,给到招行密钥 + sm4Key: "" # 对称加解密算法SM4 SM4/CBC/PKCS5Padding,密钥长度为16字节,明文长度不做要求,IV长度为16字节。 + cmbSm2Puk: "" mid: "d6fdd78b6fd13a808818286b9cad9687" aid: "5efaa21263b94f669a1c90ed0279df20" notifyUrl: "https://gateway.dev.cdlsxd.cn/ymt/jd/v1/notify" diff --git a/internal/biz/bo/order_bo.go b/internal/biz/bo/order_bo.go index 439e02e..cacc0b5 100644 --- a/internal/biz/bo/order_bo.go +++ b/internal/biz/bo/order_bo.go @@ -11,6 +11,7 @@ type OrderBo struct { OrderNo string OutBizNo string ProductNo string + BatchNo string Account string Type vo.OrderType AccountType vo.OrderAccountType diff --git a/internal/biz/cmb.go b/internal/biz/cmb.go index 5a4e2e1..a1e534c 100644 --- a/internal/biz/cmb.go +++ b/internal/biz/cmb.go @@ -2,8 +2,11 @@ package biz import ( "context" + "errors" "fmt" + "gorm.io/gorm" "time" + v1 "voucher/api/v1" "voucher/internal/biz/bo" "voucher/internal/pkg/lock" ) @@ -12,7 +15,27 @@ func (v *VoucherBiz) CmbOrder(ctx context.Context, req *bo.OrderCreateReqBo) (or err = lock.NewMutex(v.rdb.Rdb, time.Second*30).Lock(ctx, fmt.Sprintf("cmb_order_%s", req.OutBizNo), func(ctx context.Context) error { - if orderNo, err = v.Cmb.Order(ctx, req); err != nil { + order, err := v.OrderRepo.GetByOutBizNo(ctx, req.OutBizNo) + + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + return err + } + + if order != nil { + orderNo = order.OrderNo + return nil + } + + product, err := v.ProductRepo.GetByPNO(ctx, req.ProductNo) + if err != nil { + return err + } + + if !product.Channel.IsWeChat() { + return fmt.Errorf("只支持微信") + } + + if orderNo, err = v.Cmb.Order(ctx, req, product); err != nil { return err } @@ -22,14 +45,26 @@ func (v *VoucherBiz) CmbOrder(ctx context.Context, req *bo.OrderCreateReqBo) (or return } -func (v *VoucherBiz) CmbProductQuery(ctx context.Context, productNo string) (reps *bo.OrderCreateRepBo, err error) { +func (v *VoucherBiz) CmbProductQuery(ctx context.Context, productNo string) (reps *v1.CmbQueryProductReply, err error) { - err = lock.NewMutex(v.rdb.Rdb, time.Second*30).Lock(ctx, fmt.Sprintf("cmb_query_%s", productNo), func(ctx context.Context) error { + err = lock.NewMutex(v.rdb.Rdb, time.Second*30).Lock(ctx, fmt.Sprintf("cmb_product_query_%s", productNo), func(ctx context.Context) error { - if reps, err = v.Cmb.Query(ctx, productNo); err != nil { + product, err := v.ProductRepo.GetByPNO(ctx, productNo) + if err != nil { return err } + if !product.Channel.IsWeChat() { + return fmt.Errorf("只支持微信") + } + + _, err = v.WechatCpnRepo.QueryProduct(ctx, product.BatchNo) + if err != nil { + return err + } + + // 数据构造返回 + return nil }) diff --git a/internal/biz/cmb/consume.go b/internal/biz/cmb/consume.go index 2e7f06e..bbe7d77 100644 --- a/internal/biz/cmb/consume.go +++ b/internal/biz/cmb/consume.go @@ -49,7 +49,7 @@ func (v *Cmb) create(ctx context.Context, order *bo.OrderBo) (*bo.OrderWechatBo, AppID: order.AppID, StockCreatorMchid: order.MerchantNo, OpenID: order.Account, - StockID: order.ProductNo, + StockID: order.BatchNo, Status: vo.OrderWechatStatusWait, } diff --git a/internal/biz/cmb/voucher.go b/internal/biz/cmb/voucher.go index d218b72..5cc450d 100644 --- a/internal/biz/cmb/voucher.go +++ b/internal/biz/cmb/voucher.go @@ -2,30 +2,12 @@ package cmb import ( "context" - "github.com/pkg/errors" - "gorm.io/gorm" "voucher/internal/biz/bo" "voucher/internal/biz/vo" "voucher/internal/pkg/uid" ) -func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo) (orderNo string, err error) { - - order, err := v.OrderRepo.GetByOutBizNo(ctx, req.OutBizNo) - - if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { - return - } - - if order != nil { - orderNo = order.OrderNo - return - } - - product, err := v.ProductRepo.GetByPNO(ctx, req.ProductNo) - if err != nil { - return - } +func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo, product *bo.ProductBo) (orderNo string, err error) { orderNo, err = v.GenerateMixRepo.GeneratorString(ctx, uid.Order) if err != nil { @@ -40,14 +22,14 @@ func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo) (orderNo stri AppID: product.AppID, MerchantNo: product.MerchantNo, Channel: product.Channel, + BatchNo: product.BatchNo, NotifyUrl: v.bc.Cmb.NotifyUrl, AccountType: vo.OrderAccountTypeOpenId, Type: vo.OrderTypeCmb, Status: vo.OrderStatusWait, } - order, err = v.OrderRepo.Create(ctx, o) - if err != nil { + if _, err = v.OrderRepo.Create(ctx, o); err != nil { return } diff --git a/internal/biz/voucher.go b/internal/biz/voucher.go index 95fe67b..b1d46c8 100644 --- a/internal/biz/voucher.go +++ b/internal/biz/voucher.go @@ -4,6 +4,7 @@ import ( "voucher/internal/biz/cmb" "voucher/internal/biz/mixrepos" "voucher/internal/biz/repo" + "voucher/internal/biz/wechatrepo" "voucher/internal/conf" "voucher/internal/data" ) @@ -12,22 +13,28 @@ type VoucherBiz struct { bc *conf.Bootstrap rdb *data.Rdb Cmb *cmb.Cmb + ProductRepo repo.ProductRepo OrderRepo repo.OrderRepo MqSendMixRepo mixrepos.MQSendMixRepo + WechatCpnRepo wechatrepo.WechatCpnRepo } func NewVoucherBiz( bc *conf.Bootstrap, rdb *data.Rdb, Cmb *cmb.Cmb, + ProductRepo repo.ProductRepo, OrderRepo repo.OrderRepo, MqSendMixRepo mixrepos.MQSendMixRepo, + WechatCpnRepo wechatrepo.WechatCpnRepo, ) *VoucherBiz { return &VoucherBiz{ bc: bc, rdb: rdb, Cmb: Cmb, + ProductRepo: ProductRepo, OrderRepo: OrderRepo, MqSendMixRepo: MqSendMixRepo, + WechatCpnRepo: WechatCpnRepo, } } diff --git a/internal/biz/wechatrepo/cpn.go b/internal/biz/wechatrepo/cpn.go index 572992e..36e7751 100644 --- a/internal/biz/wechatrepo/cpn.go +++ b/internal/biz/wechatrepo/cpn.go @@ -2,6 +2,7 @@ package wechatrepo import ( "context" + "github.com/wechatpay-apiv3/wechatpay-go/services/merchantexclusivecoupon" "voucher/internal/biz/bo" "voucher/internal/biz/vo" ) @@ -9,4 +10,5 @@ import ( type WechatCpnRepo interface { Order(ctx context.Context, orderWechat *bo.OrderWechatBo) (couponId string, err error) Query(ctx context.Context, orderWechat *bo.OrderWechatBo) (vo.OrderWechatStatus, error) + QueryProduct(ctx context.Context, stockId string) (*merchantexclusivecoupon.StockGetResponse, error) } diff --git a/internal/data/model/order.gen.go b/internal/data/model/order.gen.go index 67e87ff..58947b0 100644 --- a/internal/data/model/order.gen.go +++ b/internal/data/model/order.gen.go @@ -16,6 +16,7 @@ type Order struct { OrderNo string `gorm:"column:order_no;not null" json:"order_no"` OutBizNo string `gorm:"column:out_biz_no;not null;comment:外部交易号" json:"out_biz_no"` // 外部交易号 ProductNo string `gorm:"column:product_no;not null;comment:商品编号" json:"product_no"` // 商品编号 + BatchNo string `gorm:"column:batch_no;not null;comment:立减金批次号" json:"batch_no"` // 立减金批次号 Account string `gorm:"column:account;not null;comment:充值账号" json:"account"` // 充值账号 AccountType uint8 `gorm:"column:account_type;not null;comment:1:oepnid/userid 2:手机号" json:"account_type"` // 1:oepnid/userid 2:手机号 Type uint8 `gorm:"column:type;not null;comment:1:招行" json:"type"` diff --git a/internal/data/repoimpl/order.go b/internal/data/repoimpl/order.go index 5c40cfd..193b6ee 100644 --- a/internal/data/repoimpl/order.go +++ b/internal/data/repoimpl/order.go @@ -33,6 +33,7 @@ func (p *OrderRepoImpl) Create(ctx context.Context, req *bo.OrderBo) (*bo.OrderB OrderNo: req.OrderNo, OutBizNo: req.OutBizNo, ProductNo: req.ProductNo, + BatchNo: req.BatchNo, Account: req.Account, AccountType: req.AccountType.GetValue(), Status: vo.OrderStatusWait.GetValue(), diff --git a/internal/data/wechatrepoimpl/cpn.go b/internal/data/wechatrepoimpl/cpn.go index 3fd2bcd..5410c6f 100644 --- a/internal/data/wechatrepoimpl/cpn.go +++ b/internal/data/wechatrepoimpl/cpn.go @@ -90,26 +90,26 @@ func (c *CpnRepoImpl) Query(ctx context.Context, orderWechat *bo.OrderWechatBo) return CpnStatus(*resp.Status).GetStatus() } -func (c *CpnRepoImpl) QueryProduct(ctx context.Context, stockId string) error { +func (c *CpnRepoImpl) QueryProduct(ctx context.Context, stockId string) (*merchantexclusivecoupon.StockGetResponse, error) { client, err := data.GetClient(ctx, c.Server) if err != nil { - return err + return nil, err } svc := merchantexclusivecoupon.BusiFavorApiService{Client: client} - _, result, err := svc.QueryStock(ctx, merchantexclusivecoupon.QueryStockRequest{StockId: core.String(stockId)}) + response, result, err := svc.QueryStock(ctx, merchantexclusivecoupon.QueryStockRequest{StockId: core.String(stockId)}) if err != nil { - return err + return nil, err } if result.Response.StatusCode != CodeSuccess { - err = fmt.Errorf("Query微信返回错误StatusCode[%d]Status[%s]", result.Response.StatusCode, result.Response.Status) - return err + err = fmt.Errorf("查询活动微信返回错误StatusCode[%d]Status[%s]", result.Response.StatusCode, result.Response.Status) + return nil, err } - return nil + return response, nil } func (c *CpnRepoImpl) Notify(ctx context.Context) error { diff --git a/internal/data/wechatrepoimpl/cpn_status.go b/internal/data/wechatrepoimpl/cpn_status.go index f2e1fc8..3a08076 100644 --- a/internal/data/wechatrepoimpl/cpn_status.go +++ b/internal/data/wechatrepoimpl/cpn_status.go @@ -31,7 +31,7 @@ func (o CpnStatus) GetText() string { if msg, ok := CpnStatusTextMap[o]; !ok { return msg } - return "" + return "未知" } func (o CpnStatus) GetStatus() (vo.OrderWechatStatus, error) { diff --git a/internal/service/cmb.go b/internal/service/cmb.go index e76ba6c..23f6506 100644 --- a/internal/service/cmb.go +++ b/internal/service/cmb.go @@ -92,6 +92,7 @@ func (s *VoucherService) cmbProductQuery(ctx http.Context) error { return err } + s.VoucherBiz.CmbProductQuery(ctx, req.ActivityId) // todo 签名验证 rep := &v1.CmbQueryProductReply{}