This commit is contained in:
李子铭 2025-03-04 15:42:06 +08:00
parent dd27b4293c
commit ec182fabad
12 changed files with 139 additions and 97 deletions

View File

@ -9,21 +9,21 @@ import "validate/validate.proto";
message CmbOrderRequest { message CmbOrderRequest {
// //
// ID32 // ID32
string mid = 1 [json_name = "mid"]; string mid = 1 [json_name = "mid", (validate.rules).string = {min_len: 1,max_len: 32}];
// ID32 // ID32
string aid = 2 [json_name = "aid"]; string aid = 2 [json_name = "aid", (validate.rules).string = {min_len: 1,max_len: 32}];
// yyyyMMddHHmmss // yyyyMMddHHmmss
string date = 3 [json_name = "date"]; string date = 3 [json_name = "date", (validate.rules).string = {min_len: 14}];
// 32 // 32
string random = 4 [json_name = "random"]; string random = 4 [json_name = "random", (validate.rules).string = {min_len: 1,max_len: 32}];
// //
string keyAlias = 5 [json_name = "keyAlias"]; string keyAlias = 5 [json_name = "keyAlias", (validate.rules).string = {min_len: 2}];
// //
string cmbKeyAlias = 6 [json_name = "cmbKeyAlias"]; string cmbKeyAlias = 6 [json_name = "cmbKeyAlias", (validate.rules).string = {min_len: 2}];
// API的说明文档 // API的说明文档
string encryptBody = 7 [json_name = "encryptBody"]; string encryptBody = 7 [json_name = "encryptBody", (validate.rules).string = {min_len: 10}];
// //
string sign = 8 [json_name = "sign"]; string sign = 8 [json_name = "sign", (validate.rules).string = {min_len: 10}];
// //
// 14 // 14
@ -63,21 +63,21 @@ message CmbOrderReply {
message CmbQueryProductRequest { message CmbQueryProductRequest {
// //
// ID32 // ID32
string mid = 1 [json_name = "mid"]; string mid = 1 [json_name = "mid", (validate.rules).string = {min_len: 1,max_len: 32}];
// ID32 // ID32
string aid = 2 [json_name = "aid"]; string aid = 2 [json_name = "aid", (validate.rules).string = {min_len: 1,max_len: 32}];
// yyyyMMddHHmmss // yyyyMMddHHmmss
string date = 3 [json_name = "date"]; string date = 3 [json_name = "date", (validate.rules).string = {min_len: 14}];
// 32 // 32
string random = 4 [json_name = "random"]; string random = 4 [json_name = "random", (validate.rules).string = {min_len: 1,max_len: 32}];
// //
string keyAlias = 5 [json_name = "keyAlias"]; string keyAlias = 5 [json_name = "keyAlias", (validate.rules).string = {min_len: 2}];
// //
string cmbKeyAlias = 6 [json_name = "cmbKeyAlias"]; string cmbKeyAlias = 6 [json_name = "cmbKeyAlias", (validate.rules).string = {min_len: 2}];
// API的说明文档 // API的说明文档
string encryptBody = 7 [json_name = "encryptBody"]; string encryptBody = 7 [json_name = "encryptBody", (validate.rules).string = {min_len: 10}];
// //
string sign = 8 [json_name = "sign"]; string sign = 8 [json_name = "sign", (validate.rules).string = {min_len: 10}];
// //
// //

View File

@ -15,7 +15,6 @@ import (
"voucher/internal/data" "voucher/internal/data"
"voucher/internal/data/mixrepoimpl" "voucher/internal/data/mixrepoimpl"
"voucher/internal/data/repoimpl" "voucher/internal/data/repoimpl"
"voucher/internal/data/thirdrepoimpl"
"voucher/internal/data/wechatrepoimpl" "voucher/internal/data/wechatrepoimpl"
log2 "voucher/internal/pkg/log" log2 "voucher/internal/pkg/log"
"voucher/internal/server" "voucher/internal/server"
@ -31,7 +30,6 @@ func wireApp(*conf.Bootstrap, log.Logger, *log2.AccessLogger) (*kratos.App, func
biz.ProviderSetBiz, biz.ProviderSetBiz,
data.ProviderDataSet, data.ProviderDataSet,
repoimpl.ProviderRepoImplSet, repoimpl.ProviderRepoImplSet,
thirdrepoimpl.ProviderThirdRepositoryImplSet,
wechatrepoimpl.ProviderWechatReposImplSet, wechatrepoimpl.ProviderWechatReposImplSet,
mixrepoimpl.ProviderMixRepoImplSet, mixrepoimpl.ProviderMixRepoImplSet,
log2.NewLogHelper, log2.NewLogHelper,

View File

@ -9,12 +9,12 @@ package main
import ( import (
"github.com/go-kratos/kratos/v2" "github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
"voucher/internal/biz"
"voucher/internal/biz/cmb" "voucher/internal/biz/cmb"
"voucher/internal/conf" "voucher/internal/conf"
"voucher/internal/data" "voucher/internal/data"
"voucher/internal/data/mixrepoimpl" "voucher/internal/data/mixrepoimpl"
"voucher/internal/data/repoimpl" "voucher/internal/data/repoimpl"
"voucher/internal/data/thirdrepoimpl"
"voucher/internal/data/wechatrepoimpl" "voucher/internal/data/wechatrepoimpl"
log2 "voucher/internal/pkg/log" log2 "voucher/internal/pkg/log"
"voucher/internal/server" "voucher/internal/server"
@ -35,12 +35,13 @@ func wireApp(bootstrap *conf.Bootstrap, logger log.Logger, accessLogger *log2.Ac
return nil, nil, err return nil, nil, err
} }
orderRepo := repoimpl.NewOrderRepoImpl() orderRepo := repoimpl.NewOrderRepoImpl()
productRepo := repoimpl.NewProductRepoImpl()
rocketMQ, cleanup2, err := data.NewRocketMQ(bootstrap) rocketMQ, cleanup2, err := data.NewRocketMQ(bootstrap)
if err != nil { if err != nil {
cleanup() cleanup()
return nil, nil, err return nil, nil, err
} }
thirdMQSend := thirdrepoimpl.NewMQSendImpl(rocketMQ) mqSendMixRepo := mixrepoimpl.NewMQSendMixRepoImpl(rocketMQ)
wechatCpnRepo, err := wechatrepoimpl.NewCpnRepoImpl(bootstrap) wechatCpnRepo, err := wechatrepoimpl.NewCpnRepoImpl(bootstrap)
if err != nil { if err != nil {
cleanup2() cleanup2()
@ -48,8 +49,9 @@ func wireApp(bootstrap *conf.Bootstrap, logger log.Logger, accessLogger *log2.Ac
return nil, nil, err return nil, nil, err
} }
generateMixRepo := mixrepoimpl.NewGenerateMixRepoImpl(rdb) generateMixRepo := mixrepoimpl.NewGenerateMixRepoImpl(rdb)
voucherBiz := cmb.NewCmb(rdb, orderRepo, thirdMQSend, wechatCpnRepo, generateMixRepo) cmbCmb := cmb.NewCmb(rdb, orderRepo, productRepo, mqSendMixRepo, wechatCpnRepo, generateMixRepo)
voucherService := service.NewVoucherService(bootstrap, voucherBiz) voucherBiz := biz.NewVoucherBiz(rdb, cmbCmb, orderRepo)
voucherService := service.NewVoucherService(bootstrap, voucherBiz, cmbCmb)
httpServer := server.NewHTTPServer(bootstrap, helper, accessLogger, voucherService) httpServer := server.NewHTTPServer(bootstrap, helper, accessLogger, voucherService)
consumer := server.NewConsumer(helper, bootstrap, voucherService) consumer := server.NewConsumer(helper, bootstrap, voucherService)
app := newApp(logger, httpServer, consumer) app := newApp(logger, httpServer, consumer)

View File

@ -3,7 +3,6 @@ package cmb
import ( import (
"voucher/internal/biz/mixrepos" "voucher/internal/biz/mixrepos"
"voucher/internal/biz/repo" "voucher/internal/biz/repo"
"voucher/internal/biz/thirdrepo"
"voucher/internal/biz/wechatrepo" "voucher/internal/biz/wechatrepo"
"voucher/internal/data" "voucher/internal/data"
) )
@ -12,7 +11,7 @@ type Cmb struct {
rdb *data.Rdb rdb *data.Rdb
OrderRepo repo.OrderRepo OrderRepo repo.OrderRepo
ProductRepo repo.ProductRepo ProductRepo repo.ProductRepo
ThirdMQSend thirdrepo.ThirdMQSend ThirdMQSend mixrepos.MQSendMixRepo
WechatCpnRepo wechatrepo.WechatCpnRepo WechatCpnRepo wechatrepo.WechatCpnRepo
GenerateMixRepo mixrepos.GenerateMixRepo GenerateMixRepo mixrepos.GenerateMixRepo
} }
@ -21,7 +20,7 @@ func NewCmb(
rdb *data.Rdb, rdb *data.Rdb,
orderRepo repo.OrderRepo, orderRepo repo.OrderRepo,
ProductRepo repo.ProductRepo, ProductRepo repo.ProductRepo,
thirdMQSend thirdrepo.ThirdMQSend, thirdMQSend mixrepos.MQSendMixRepo,
WechatCpnRepo wechatrepo.WechatCpnRepo, WechatCpnRepo wechatrepo.WechatCpnRepo,
GenerateMixRepo mixrepos.GenerateMixRepo, GenerateMixRepo mixrepos.GenerateMixRepo,
) *Cmb { ) *Cmb {

View File

@ -4,5 +4,5 @@ import (
"github.com/google/wire" "github.com/google/wire"
) )
// ProviderSetCmb is biz providers. // ProviderSetCmb ProviderSetCmb is biz providers.
var ProviderSetCmb = wire.NewSet(NewCmb) var ProviderSetCmb = wire.NewSet(NewCmb)

View File

@ -12,48 +12,11 @@ import (
"voucher/internal/pkg/uid" "voucher/internal/pkg/uid"
) )
func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo) (reps *bo.OrderCreateRepBo, err error) { func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo) (orderNo string, err error) {
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 {
order, err := v.OrderRepo.GetByOutBizNo(ctx, req.OutBizNo) if orderNo, err = v.order(ctx, req); err != nil {
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
if order != nil {
// todo
return nil
}
product, err := v.ProductRepo.GetByPNO(ctx, req.ProductNo)
if err != nil {
return err
}
orderNo, err := v.GenerateMixRepo.GeneratorString(ctx, uid.Order)
if err != nil {
return err
}
o := &bo.OrderBo{
OrderNo: orderNo,
OutBizNo: req.OutBizNo,
ProductNo: req.ProductNo,
Account: req.Account,
AppID: product.AppID,
MerchantNo: product.MerchantNo,
Channel: product.Channel,
AccountType: vo.OrderAccountTypeOpenId,
Type: vo.OrderTypeCmb,
Status: vo.OrderStatusWait,
}
order, err = v.OrderRepo.Create(ctx, o)
if err != nil {
return err return err
} }
@ -63,6 +26,54 @@ func (v *Cmb) Order(ctx context.Context, req *bo.OrderCreateReqBo) (reps *bo.Ord
return return
} }
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
}
orderNo, err = v.GenerateMixRepo.GeneratorString(ctx, uid.Order)
if err != nil {
return
}
o := &bo.OrderBo{
OrderNo: orderNo,
OutBizNo: req.OutBizNo,
ProductNo: req.ProductNo,
Account: req.Account,
AppID: product.AppID,
MerchantNo: product.MerchantNo,
Channel: product.Channel,
AccountType: vo.OrderAccountTypeOpenId,
Type: vo.OrderTypeCmb,
Status: vo.OrderStatusWait,
}
order, err = v.OrderRepo.Create(ctx, o)
if err != nil {
return
}
//v.ThirdMQSend
return
}
func (v *Cmb) Query(ctx context.Context, req *bo.OrderCreateReqBo) (reps *bo.OrderCreateRepBo, err error) { func (v *Cmb) Query(ctx context.Context, req *bo.OrderCreateReqBo) (reps *bo.OrderCreateRepBo, err error) {
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 {

View File

@ -1,11 +1,11 @@
package thirdrepo package mixrepos
import ( import (
"context" "context"
"voucher/internal/pkg/mq" "voucher/internal/pkg/mq"
) )
type ThirdMQSend interface { type MQSendMixRepo interface {
// SendASync 异步发送消息出错会自动写日志errFn 中可以不用再写失败日志,可以处理一些数据纠正的操作等 // SendASync 异步发送消息出错会自动写日志errFn 中可以不用再写失败日志,可以处理一些数据纠正的操作等
SendASync(ctx context.Context, topicName string, body []byte, errFn func(error), sendOptions ...mq.SendOption) error SendASync(ctx context.Context, topicName string, body []byte, errFn func(error), sendOptions ...mq.SendOption) error

View File

@ -1,28 +1,28 @@
package thirdrepoimpl package mixrepoimpl
import ( import (
"context" "context"
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
"voucher/internal/biz/thirdrepo" "voucher/internal/biz/mixrepos"
"voucher/internal/data" "voucher/internal/data"
"voucher/internal/pkg/mq" "voucher/internal/pkg/mq"
) )
type ThirdMQSendImpl struct { type MQSendMixRepoImpl struct {
mq *data.RocketMQ mq *data.RocketMQ
} }
func NewMQSendImpl(mq *data.RocketMQ) thirdrepo.ThirdMQSend { func NewMQSendMixRepoImpl(mq *data.RocketMQ) mixrepos.MQSendMixRepo {
return &ThirdMQSendImpl{ return &MQSendMixRepoImpl{
mq: mq, mq: mq,
} }
} }
func (s *ThirdMQSendImpl) SendSync(ctx context.Context, topicName string, body []byte, sendOptions ...mq.SendOption) error { func (s *MQSendMixRepoImpl) SendSync(ctx context.Context, topicName string, body []byte, sendOptions ...mq.SendOption) error {
return s.mq.MqProducer.SendSync(ctx, topicName, body, sendOptions...) return s.mq.MqProducer.SendSync(ctx, topicName, body, sendOptions...)
} }
func (s *ThirdMQSendImpl) SendASync(ctx context.Context, topicName string, body []byte, errFn func(error), sendOptions ...mq.SendOption) error { func (s *MQSendMixRepoImpl) SendASync(ctx context.Context, topicName string, body []byte, errFn func(error), sendOptions ...mq.SendOption) error {
err := s.mq.MqProducer.SendAsync(ctx, topicName, body, func(err error) { err := s.mq.MqProducer.SendAsync(ctx, topicName, body, func(err error) {
if err == nil { if err == nil {
return return
@ -33,7 +33,7 @@ func (s *ThirdMQSendImpl) SendASync(ctx context.Context, topicName string, body
return err return err
} }
func (s *ThirdMQSendImpl) SendAsyncNotFn(ctx context.Context, topic string, body []byte, sendOptions ...mq.SendOption) error { func (s *MQSendMixRepoImpl) SendAsyncNotFn(ctx context.Context, topic string, body []byte, sendOptions ...mq.SendOption) error {
err := s.mq.MqProducer.SendAsync(ctx, topic, body, func(err error) { err := s.mq.MqProducer.SendAsync(ctx, topic, body, func(err error) {
if err == nil { if err == nil {
return return

View File

@ -5,4 +5,7 @@ import (
) )
// ProviderMixRepoImplSet is providers. // ProviderMixRepoImplSet is providers.
var ProviderMixRepoImplSet = wire.NewSet(NewGenerateMixRepoImpl) var ProviderMixRepoImplSet = wire.NewSet(
NewGenerateMixRepoImpl,
NewMQSendMixRepoImpl,
)

View File

@ -7,4 +7,5 @@ import (
// ProviderRepoImplSet is providers. // ProviderRepoImplSet is providers.
var ProviderRepoImplSet = wire.NewSet( var ProviderRepoImplSet = wire.NewSet(
NewOrderRepoImpl, NewOrderRepoImpl,
NewProductRepoImpl,
) )

View File

@ -1,10 +0,0 @@
package thirdrepoimpl
import (
"github.com/google/wire"
)
// ProviderThirdRepositoryImplSet is providers.
var ProviderThirdRepositoryImplSet = wire.NewSet(
NewMQSendImpl,
)

View File

@ -9,13 +9,42 @@ import (
func (s *VoucherService) CmbOrder(ctx http.Context) error { func (s *VoucherService) CmbOrder(ctx http.Context) error {
reply := &v1.CmbOrderReply{
RespCode: "",
RespMsg: "",
Date: "",
KeyAlias: "",
CmbKeyAlias: "",
EncryptBody: "",
Sign: "",
CodeNo: "",
}
orderNo, err := s.cmbOrder(ctx)
if err != nil {
reply.RespCode = "1001"
reply.RespMsg = err.Error()
} else {
reply.RespCode = "1000"
reply.RespMsg = "成功"
reply.CodeNo = orderNo
}
// todo 签名
reply.Sign = ""
return ctx.JSON(200, reply)
}
func (s *VoucherService) cmbOrder(ctx http.Context) (string, error) {
var req v1.CmbOrderRequest var req v1.CmbOrderRequest
if err := ctx.BindForm(&req); err != nil { if err := ctx.BindForm(&req); err != nil {
return err return "", err
} }
if err := req.Validate(); err != nil { if err := req.Validate(); err != nil {
return err return "", err
} }
// todo 签名验证 // todo 签名验证
@ -27,22 +56,29 @@ func (s *VoucherService) CmbOrder(ctx http.Context) error {
AccountType: vo.OrderAccountTypeOpenId, AccountType: vo.OrderAccountTypeOpenId,
} }
boRep, err := s.Cmb.Order(ctx, boReq) orderNo, err := s.Cmb.Order(ctx, boReq)
if err != nil { if err != nil {
return err return "", err
} }
rep := &v1.CmbOrderReply{ return orderNo, nil
RespCode: "",
RespMsg: "",
CodeNo: boRep.OrderNo,
}
return ctx.JSON(200, rep)
} }
func (s *VoucherService) CmbProductQuery(ctx http.Context) error { func (s *VoucherService) CmbProductQuery(ctx http.Context) error {
err := s.cmbProductQuery(ctx)
if err != nil {
return ctx.JSON(200, &v1.CmbOrderReply{
RespCode: "1001",
RespMsg: err.Error(),
})
}
return ctx.JSON(200, nil)
}
func (s *VoucherService) cmbProductQuery(ctx http.Context) error {
var req v1.CmbQueryProductRequest var req v1.CmbQueryProductRequest
if err := ctx.BindForm(&req); err != nil { if err := ctx.BindForm(&req); err != nil {
return err return err
@ -52,6 +88,8 @@ func (s *VoucherService) CmbProductQuery(ctx http.Context) error {
return err return err
} }
// todo 签名验证
rep := &v1.CmbQueryProductReply{} rep := &v1.CmbQueryProductReply{}
return ctx.JSON(200, rep) return ctx.JSON(200, rep)