cmb
This commit is contained in:
parent
b4f92d78e6
commit
6b65f24fa5
|
|
@ -47,6 +47,10 @@ wechat:
|
||||||
mchCertificateSerialNumber: "4D081089DEB385316CBDCB55C070287E4920AC76"
|
mchCertificateSerialNumber: "4D081089DEB385316CBDCB55C070287E4920AC76"
|
||||||
|
|
||||||
cmb:
|
cmb:
|
||||||
|
sm2Prk: "" # 私钥 非对称加解密算法SM2 公钥长度为65字节,私钥长度为32字节。非对称密钥是基于国密推荐的椭圆曲线生成的,国密推荐曲线sm2p256v1
|
||||||
|
sm2Puk: "" # 公钥,给到招行密钥
|
||||||
|
sm4Key: "" # 对称加解密算法SM4 SM4/CBC/PKCS5Padding,密钥长度为16字节,明文长度不做要求,IV长度为16字节。
|
||||||
|
cmbSm2Puk: ""
|
||||||
mid: "d6fdd78b6fd13a808818286b9cad9687"
|
mid: "d6fdd78b6fd13a808818286b9cad9687"
|
||||||
aid: "5efaa21263b94f669a1c90ed0279df20"
|
aid: "5efaa21263b94f669a1c90ed0279df20"
|
||||||
notifyUrl: "https://gateway.dev.cdlsxd.cn/ymt/jd/v1/notify"
|
notifyUrl: "https://gateway.dev.cdlsxd.cn/ymt/jd/v1/notify"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ type OrderBo struct {
|
||||||
OrderNo string
|
OrderNo string
|
||||||
OutBizNo string
|
OutBizNo string
|
||||||
ProductNo string
|
ProductNo string
|
||||||
|
BatchNo string
|
||||||
Account string
|
Account string
|
||||||
Type vo.OrderType
|
Type vo.OrderType
|
||||||
AccountType vo.OrderAccountType
|
AccountType vo.OrderAccountType
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,11 @@ package biz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"gorm.io/gorm"
|
||||||
"time"
|
"time"
|
||||||
|
v1 "voucher/api/v1"
|
||||||
"voucher/internal/biz/bo"
|
"voucher/internal/biz/bo"
|
||||||
"voucher/internal/pkg/lock"
|
"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 {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,14 +45,26 @@ func (v *VoucherBiz) CmbOrder(ctx context.Context, req *bo.OrderCreateReqBo) (or
|
||||||
return
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !product.Channel.IsWeChat() {
|
||||||
|
return fmt.Errorf("只支持微信")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = v.WechatCpnRepo.QueryProduct(ctx, product.BatchNo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据构造返回
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ func (v *Cmb) create(ctx context.Context, order *bo.OrderBo) (*bo.OrderWechatBo,
|
||||||
AppID: order.AppID,
|
AppID: order.AppID,
|
||||||
StockCreatorMchid: order.MerchantNo,
|
StockCreatorMchid: order.MerchantNo,
|
||||||
OpenID: order.Account,
|
OpenID: order.Account,
|
||||||
StockID: order.ProductNo,
|
StockID: order.BatchNo,
|
||||||
Status: vo.OrderWechatStatusWait,
|
Status: vo.OrderWechatStatusWait,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,12 @@ package cmb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
"voucher/internal/biz/bo"
|
"voucher/internal/biz/bo"
|
||||||
"voucher/internal/biz/vo"
|
"voucher/internal/biz/vo"
|
||||||
"voucher/internal/pkg/uid"
|
"voucher/internal/pkg/uid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo) (orderNo string, err error) {
|
func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo, product *bo.ProductBo) (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
|
|
||||||
}
|
|
||||||
|
|
||||||
orderNo, err = v.GenerateMixRepo.GeneratorString(ctx, uid.Order)
|
orderNo, err = v.GenerateMixRepo.GeneratorString(ctx, uid.Order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -40,14 +22,14 @@ func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo) (orderNo stri
|
||||||
AppID: product.AppID,
|
AppID: product.AppID,
|
||||||
MerchantNo: product.MerchantNo,
|
MerchantNo: product.MerchantNo,
|
||||||
Channel: product.Channel,
|
Channel: product.Channel,
|
||||||
|
BatchNo: product.BatchNo,
|
||||||
NotifyUrl: v.bc.Cmb.NotifyUrl,
|
NotifyUrl: v.bc.Cmb.NotifyUrl,
|
||||||
AccountType: vo.OrderAccountTypeOpenId,
|
AccountType: vo.OrderAccountTypeOpenId,
|
||||||
Type: vo.OrderTypeCmb,
|
Type: vo.OrderTypeCmb,
|
||||||
Status: vo.OrderStatusWait,
|
Status: vo.OrderStatusWait,
|
||||||
}
|
}
|
||||||
|
|
||||||
order, err = v.OrderRepo.Create(ctx, o)
|
if _, err = v.OrderRepo.Create(ctx, o); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"voucher/internal/biz/cmb"
|
"voucher/internal/biz/cmb"
|
||||||
"voucher/internal/biz/mixrepos"
|
"voucher/internal/biz/mixrepos"
|
||||||
"voucher/internal/biz/repo"
|
"voucher/internal/biz/repo"
|
||||||
|
"voucher/internal/biz/wechatrepo"
|
||||||
"voucher/internal/conf"
|
"voucher/internal/conf"
|
||||||
"voucher/internal/data"
|
"voucher/internal/data"
|
||||||
)
|
)
|
||||||
|
|
@ -12,22 +13,28 @@ type VoucherBiz struct {
|
||||||
bc *conf.Bootstrap
|
bc *conf.Bootstrap
|
||||||
rdb *data.Rdb
|
rdb *data.Rdb
|
||||||
Cmb *cmb.Cmb
|
Cmb *cmb.Cmb
|
||||||
|
ProductRepo repo.ProductRepo
|
||||||
OrderRepo repo.OrderRepo
|
OrderRepo repo.OrderRepo
|
||||||
MqSendMixRepo mixrepos.MQSendMixRepo
|
MqSendMixRepo mixrepos.MQSendMixRepo
|
||||||
|
WechatCpnRepo wechatrepo.WechatCpnRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVoucherBiz(
|
func NewVoucherBiz(
|
||||||
bc *conf.Bootstrap,
|
bc *conf.Bootstrap,
|
||||||
rdb *data.Rdb,
|
rdb *data.Rdb,
|
||||||
Cmb *cmb.Cmb,
|
Cmb *cmb.Cmb,
|
||||||
|
ProductRepo repo.ProductRepo,
|
||||||
OrderRepo repo.OrderRepo,
|
OrderRepo repo.OrderRepo,
|
||||||
MqSendMixRepo mixrepos.MQSendMixRepo,
|
MqSendMixRepo mixrepos.MQSendMixRepo,
|
||||||
|
WechatCpnRepo wechatrepo.WechatCpnRepo,
|
||||||
) *VoucherBiz {
|
) *VoucherBiz {
|
||||||
return &VoucherBiz{
|
return &VoucherBiz{
|
||||||
bc: bc,
|
bc: bc,
|
||||||
rdb: rdb,
|
rdb: rdb,
|
||||||
Cmb: Cmb,
|
Cmb: Cmb,
|
||||||
|
ProductRepo: ProductRepo,
|
||||||
OrderRepo: OrderRepo,
|
OrderRepo: OrderRepo,
|
||||||
MqSendMixRepo: MqSendMixRepo,
|
MqSendMixRepo: MqSendMixRepo,
|
||||||
|
WechatCpnRepo: WechatCpnRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package wechatrepo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/wechatpay-apiv3/wechatpay-go/services/merchantexclusivecoupon"
|
||||||
"voucher/internal/biz/bo"
|
"voucher/internal/biz/bo"
|
||||||
"voucher/internal/biz/vo"
|
"voucher/internal/biz/vo"
|
||||||
)
|
)
|
||||||
|
|
@ -9,4 +10,5 @@ import (
|
||||||
type WechatCpnRepo interface {
|
type WechatCpnRepo interface {
|
||||||
Order(ctx context.Context, orderWechat *bo.OrderWechatBo) (couponId string, err error)
|
Order(ctx context.Context, orderWechat *bo.OrderWechatBo) (couponId string, err error)
|
||||||
Query(ctx context.Context, orderWechat *bo.OrderWechatBo) (vo.OrderWechatStatus, error)
|
Query(ctx context.Context, orderWechat *bo.OrderWechatBo) (vo.OrderWechatStatus, error)
|
||||||
|
QueryProduct(ctx context.Context, stockId string) (*merchantexclusivecoupon.StockGetResponse, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ type Order struct {
|
||||||
OrderNo string `gorm:"column:order_no;not null" json:"order_no"`
|
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"` // 外部交易号
|
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"` // 商品编号
|
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"` // 充值账号
|
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:手机号
|
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"`
|
Type uint8 `gorm:"column:type;not null;comment:1:招行" json:"type"`
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ func (p *OrderRepoImpl) Create(ctx context.Context, req *bo.OrderBo) (*bo.OrderB
|
||||||
OrderNo: req.OrderNo,
|
OrderNo: req.OrderNo,
|
||||||
OutBizNo: req.OutBizNo,
|
OutBizNo: req.OutBizNo,
|
||||||
ProductNo: req.ProductNo,
|
ProductNo: req.ProductNo,
|
||||||
|
BatchNo: req.BatchNo,
|
||||||
Account: req.Account,
|
Account: req.Account,
|
||||||
AccountType: req.AccountType.GetValue(),
|
AccountType: req.AccountType.GetValue(),
|
||||||
Status: vo.OrderStatusWait.GetValue(),
|
Status: vo.OrderStatusWait.GetValue(),
|
||||||
|
|
|
||||||
|
|
@ -90,26 +90,26 @@ func (c *CpnRepoImpl) Query(ctx context.Context, orderWechat *bo.OrderWechatBo)
|
||||||
return CpnStatus(*resp.Status).GetStatus()
|
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)
|
client, err := data.GetClient(ctx, c.Server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
svc := merchantexclusivecoupon.BusiFavorApiService{Client: client}
|
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 {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Response.StatusCode != CodeSuccess {
|
if result.Response.StatusCode != CodeSuccess {
|
||||||
err = fmt.Errorf("Query微信返回错误StatusCode[%d]Status[%s]", result.Response.StatusCode, result.Response.Status)
|
err = fmt.Errorf("查询活动微信返回错误StatusCode[%d]Status[%s]", result.Response.StatusCode, result.Response.Status)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CpnRepoImpl) Notify(ctx context.Context) error {
|
func (c *CpnRepoImpl) Notify(ctx context.Context) error {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func (o CpnStatus) GetText() string {
|
||||||
if msg, ok := CpnStatusTextMap[o]; !ok {
|
if msg, ok := CpnStatusTextMap[o]; !ok {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
return ""
|
return "未知"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o CpnStatus) GetStatus() (vo.OrderWechatStatus, error) {
|
func (o CpnStatus) GetStatus() (vo.OrderWechatStatus, error) {
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ func (s *VoucherService) cmbProductQuery(ctx http.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.VoucherBiz.CmbProductQuery(ctx, req.ActivityId)
|
||||||
// todo 签名验证
|
// todo 签名验证
|
||||||
|
|
||||||
rep := &v1.CmbQueryProductReply{}
|
rep := &v1.CmbQueryProductReply{}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue