This commit is contained in:
ziming 2025-05-20 14:37:43 +08:00
parent 0a71346d3b
commit 6a3c0d44a6
12 changed files with 90 additions and 246 deletions

View File

@ -1 +0,0 @@
package biz

View File

@ -27,7 +27,7 @@ type BBToWechatRequest struct {
func (this *BBToWechatRequest) GetSynNotice() *SynNotice { func (this *BBToWechatRequest) GetSynNotice() *SynNotice {
return &SynNotice{ return &SynNotice{
OutBizBo: this.TransactionId, OutBizBo: this.TransactionId,
Type: SynNoticeTypeBBToWechat, Type: NoticeTypeBBToWechat,
BizContent: this, BizContent: this,
} }
} }

View File

@ -21,7 +21,7 @@ type CmbToBBRequest struct {
func (this *CmbToBBRequest) GetSynNotice() *SynNotice { func (this *CmbToBBRequest) GetSynNotice() *SynNotice {
return &SynNotice{ return &SynNotice{
OutBizBo: this.TransactionId, OutBizBo: this.TransactionId,
Type: SynNoticeTypeCmbToBB, Type: NoticeTypeCmbToBB,
BizContent: this, BizContent: this,
} }
} }

View File

@ -1,38 +1,38 @@
package kx package kx
type SynNoticeType uint8 type NoticeType uint8
const ( const (
SynNoticeTypeCmbToBB SynNoticeType = iota + 1 NoticeTypeCmbToBB NoticeType = iota + 1
SynNoticeTypeBBToWechat NoticeTypeBBToWechat
SynNoticeTypeWechatToBB NoticeTypeWechatToBB
) )
var SynNoticeTypeMap = map[SynNoticeType]string{ var SynNoticeTypeMap = map[NoticeType]string{
SynNoticeTypeCmbToBB: "招行请求蓝色兄弟", NoticeTypeCmbToBB: "招行请求蓝色兄弟",
SynNoticeTypeBBToWechat: "蓝色兄弟请求微信", NoticeTypeBBToWechat: "蓝色兄弟请求微信",
SynNoticeTypeWechatToBB: "微信请求蓝色兄弟", NoticeTypeWechatToBB: "微信请求蓝色兄弟",
} }
func (s SynNoticeType) GetText() string { func (s NoticeType) GetText() string {
if t, ok := SynNoticeTypeMap[s]; ok { if t, ok := SynNoticeTypeMap[s]; ok {
return t return t
} }
return "未知类型" return "未知类型"
} }
func (s SynNoticeType) GetValue() uint8 { func (s NoticeType) GetValue() uint8 {
return uint8(s) return uint8(s)
} }
func (s SynNoticeType) IsCmbToBB() bool { func (s NoticeType) IsCmbToBB() bool {
return s == SynNoticeTypeCmbToBB return s == NoticeTypeCmbToBB
} }
func (s SynNoticeType) IsBBToWechat() bool { func (s NoticeType) IsBBToWechat() bool {
return s == SynNoticeTypeBBToWechat return s == NoticeTypeBBToWechat
} }
func (s SynNoticeType) IsWechatToBB() bool { func (s NoticeType) IsWechatToBB() bool {
return s == SynNoticeTypeWechatToBB return s == NoticeTypeWechatToBB
} }

View File

@ -14,7 +14,7 @@ type SynApiInterface interface {
type SynNotice struct { type SynNotice struct {
OutBizBo string OutBizBo string
Type SynNoticeType Type NoticeType
BizContent SynApiInterface BizContent SynApiInterface
} }

View File

@ -33,7 +33,7 @@ type WechatToBBRequest struct {
func (this *WechatToBBRequest) GetSynNotice() *SynNotice { func (this *WechatToBBRequest) GetSynNotice() *SynNotice {
return &SynNotice{ return &SynNotice{
OutBizBo: this.OrderId, OutBizBo: this.OrderId,
Type: SynNoticeTypeBBToWechat, Type: NoticeTypeBBToWechat,
BizContent: this, BizContent: this,
} }
} }

View File

@ -9,18 +9,28 @@ import (
err2 "voucher/api/err" err2 "voucher/api/err"
v1 "voucher/api/v1" v1 "voucher/api/v1"
"voucher/internal/biz/bo" "voucher/internal/biz/bo"
"voucher/internal/biz/kx"
"voucher/internal/biz/vo" "voucher/internal/biz/vo"
) )
func (c *VoucherBiz) CmbOrder(ctx context.Context, request *v1.CmbRequest) (*v1.CmbReply, error) { func (v *VoucherBiz) CmbOrder(ctx context.Context, request *v1.CmbRequest) (*v1.CmbReply, error) {
order, err := c.cmbOrder(ctx, request) order, err := v.cmbOrder(ctx, request)
if err != nil { if err != nil {
return c.OrderFail(ctx, err) return v.OrderFail(ctx, err)
} }
return c.OrderSuccess(ctx, order.OrderNo) reply, err := v.OrderSuccess(ctx, order.OrderNo)
if err != nil {
return nil, err
}
// 通知kx
b, _ := json.Marshal(reply)
_ = v.bbToWx(ctx, order, string(b))
return reply, nil
} }
func (c *VoucherBiz) cmbOrder(ctx context.Context, request *v1.CmbRequest) (*bo.OrderBo, error) { func (c *VoucherBiz) cmbOrder(ctx context.Context, request *v1.CmbRequest) (*bo.OrderBo, error) {
@ -53,6 +63,11 @@ func (c *VoucherBiz) cmbOrder(ctx context.Context, request *v1.CmbRequest) (*bo.
func (v *VoucherBiz) Order(ctx context.Context, req *bo.OrderCreateReqBo, cmbReq *v1.CmbOrderRequest) (order *bo.OrderBo, err error) { func (v *VoucherBiz) Order(ctx context.Context, req *bo.OrderCreateReqBo, cmbReq *v1.CmbOrderRequest) (order *bo.OrderBo, err error) {
product, err3 := v.ProductRepo.GetByProductNo(ctx, req.ProductNo)
if err3 != nil {
return order, err3
}
order, err = v.OrderRepo.GetByOutBizNo(ctx, vo.OrderTypeCmb, req.OutBizNo) order, err = v.OrderRepo.GetByOutBizNo(ctx, vo.OrderTypeCmb, req.OutBizNo)
if err != nil && !err2.IsDbNotFound(err) { if err != nil && !err2.IsDbNotFound(err) {
@ -71,11 +86,6 @@ func (v *VoucherBiz) Order(ctx context.Context, req *bo.OrderCreateReqBo, cmbReq
return order, err return order, err
} }
product, err3 := v.ProductRepo.GetByProductNo(ctx, req.ProductNo)
if err3 != nil {
return order, err3
}
order, err = v.order(ctx, req, product, cmbReq) order, err = v.order(ctx, req, product, cmbReq)
if err != nil { if err != nil {
return order, err return order, err
@ -92,6 +102,7 @@ func (v *VoucherBiz) order(ctx context.Context, req *bo.OrderCreateReqBo, produc
} }
// 通知kx // 通知kx
_ = v.cmbToBB(ctx, cmbReq)
// 注册通知标签 order.MerchantNo 批次创建商户, order.BatchNo 商品批次号 // 注册通知标签 order.MerchantNo 批次创建商户, order.BatchNo 商品批次号
if err = v.registerNotifyTag(ctx, order.MerchantNo, order.BatchNo); err != nil { if err = v.registerNotifyTag(ctx, order.MerchantNo, order.BatchNo); err != nil {
@ -201,3 +212,41 @@ func (c *VoucherBiz) OrderFail(ctx context.Context, err error) (*v1.CmbReply, er
return c.GetResponse(ctx, replyBizContent) return c.GetResponse(ctx, replyBizContent)
} }
func (v *VoucherBiz) cmbToBB(ctx context.Context, cmbReq *v1.CmbOrderRequest) error {
req := &kx.CmbToBBRequest{
TransactionId: cmbReq.TransactionId,
ActivityId: cmbReq.ActivityId,
CmbUid: cmbReq.CmbUid,
CmbUidType: cmbReq.CmbUidType,
Timestamp: cmbReq.Timestamp,
AppId: cmbReq.AppId,
Attach: cmbReq.Attach,
}
return v.KxMixRepo.Request(ctx, req.GetSynNotice())
}
func (v *VoucherBiz) bbToWx(ctx context.Context, order *bo.OrderBo, cmbRes string) error {
wxRes, err := json.Marshal(map[string]string{"coupon_id": order.VoucherNo})
if err != nil {
return err
}
req := &kx.BBToWechatRequest{
StockId: order.BatchNo,
OutRequestNo: order.OrderNo,
AppId: order.AppID,
StockCreatorMhId: order.MerchantNo,
CouponValue: 0,
CouponMinimum: 0,
CouponId: order.VoucherNo,
WxRes: string(wxRes),
CmbRes: cmbRes,
TransactionId: order.OutBizNo,
}
return v.KxMixRepo.Request(ctx, req.GetSynNotice())
}

View File

@ -1,56 +0,0 @@
package syn_notice
import (
"encoding/json"
v1 "voucher/api/v1"
"voucher/internal/biz/bo"
)
// BBToWechatRequest 蓝色兄弟请求微信发券接口数据同步Api
type BBToWechatRequest struct {
// 微信为每个批次分配的唯一id
StockId string `protobuf:"bytes,9,opt,name=stockId,proto3" json:"stockId,omitempty"`
// 商户此次发放凭据号格式商户id+日期+流水号)
OutRequestNo string `protobuf:"bytes,10,opt,name=outRequestNo,proto3" json:"outRequestNo,omitempty"`
// 微信为发券方商户分配的公众账号ID
AppId string `protobuf:"bytes,11,opt,name=appId,proto3" json:"appId,omitempty"`
// 批次创建方商户号
StockCreatorMhId string `protobuf:"bytes,12,opt,name=stockCreatorMhId,json=stockCreatorMchid,proto3" json:"stockCreatorMhId,omitempty"`
// 券面额,单位:分
CouponValue int32 `protobuf:"bytes,13,opt,name=couponValue,proto3" json:"couponValue,omitempty"`
// 面额发券批次门槛,单位:分
CouponMinimum int32 `protobuf:"bytes,14,opt,name=couponMinimum,proto3" json:"couponMinimum,omitempty"`
// 微信为代金券唯一分配的id, 在微信请求失败时可能为空
CouponId string `protobuf:"bytes,15,opt,name=couponId,proto3" json:"couponId,omitempty"`
// 微信返回结果
WxRes string `protobuf:"bytes,16,opt,name=wxRes,proto3" json:"wxRes,omitempty"`
// 招行返回结果
CmbRes string `protobuf:"bytes,17,opt,name=cmbRes,proto3" json:"cmbRes,omitempty"`
// 招行此次请求的数据的唯一流水号
TransactionId string `protobuf:"bytes,18,opt,name=transactionId,proto3" json:"transactionId,omitempty"`
}
func (this *BBToWechatRequest) SetByMinimum(miniMum int32) {
this.CouponMinimum = miniMum
}
func (this *BBToWechatRequest) SetByOrder(order *bo.OrderBo) {
this.AppId = order.AppID
this.StockId = order.ProductNo
this.OutRequestNo = order.OrderNo
this.StockCreatorMhId = order.MerchantNo
this.CouponId = order.OrderNo
}
func (this *BBToWechatRequest) SetByCmbReply(req *v1.CmbReply) {
b, _ := json.Marshal(req)
this.CmbRes = string(b)
}
func (this *BBToWechatRequest) GetSynNotice() *SynNotice {
return &SynNotice{
OutBizBo: this.TransactionId,
Type: SynNoticeTypeBBToWechat,
BizContent: this,
}
}

View File

@ -1,41 +0,0 @@
package syn_notice
import (
v1 "voucher/api/v1"
)
// CmbToBBRequest 招行请求蓝色兄弟发券接口数据同步Api
type CmbToBBRequest struct {
// 唯一流水号
TransactionId string `protobuf:"bytes,9,opt,name=transactionId,proto3" json:"transactionId,omitempty"`
// 外部合作方权益批次号
ActivityId string `protobuf:"bytes,10,opt,name=activityId,proto3" json:"activityId,omitempty"`
// 招商银行用户号 用户标识比如手机号、支付宝openId
CmbUid string `protobuf:"bytes,11,opt,name=cmbUid,proto3" json:"cmbUid,omitempty"`
// 用户标识类型0-手机号1-支付宝openId
CmbUidType string `protobuf:"bytes,12,opt,name=cmbUidType,proto3" json:"cmbUidType,omitempty"`
// 时间戳长度为13位精度为毫秒
Timestamp string `protobuf:"bytes,13,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
// appId
AppId string `protobuf:"bytes,14,opt,name=appId,proto3" json:"appId,omitempty"`
// 补丁
Attach string `protobuf:"bytes,15,opt,name=attach,proto3" json:"attach,omitempty"`
}
func (this *CmbToBBRequest) SetByBiz(bizContent *v1.CmbOrderRequest) {
this.TransactionId = bizContent.TransactionId
this.ActivityId = bizContent.ActivityId
this.CmbUid = bizContent.CmbUid
this.CmbUidType = bizContent.CmbUidType
this.Timestamp = bizContent.Timestamp
this.AppId = bizContent.AppId
this.Attach = bizContent.Attach
}
func (this *CmbToBBRequest) GetSynNotice() *SynNotice {
return &SynNotice{
OutBizBo: this.TransactionId,
Type: SynNoticeTypeCmbToBB,
BizContent: this,
}
}

View File

@ -1,62 +0,0 @@
package syn_notice
import (
"context"
"encoding/json"
)
var _ SynApiInterface = (*CmbToBBRequest)(nil)
var _ SynApiInterface = (*BBToWechatRequest)(nil)
var _ SynApiInterface = (*WechatToBBRequest)(nil)
type SynApiInterface interface {
GetSynNotice() *SynNotice
}
type SynNotice struct {
OutBizBo string
Type SynNoticeType
BizContent SynApiInterface
}
func (this *SynNotice) Marshal() ([]byte, error) {
return json.Marshal(this)
}
// 上下文键类型,避免命名冲突
type contextKey string
const (
contextCMBToBBKey contextKey = "cmb_to_bb"
contextBBToWXKey contextKey = "bb_to_wx"
)
// SynApi 无状态服务
type SynApi struct{}
// NewSynApi 创建无状态的处理实例
func NewSynApi() *SynApi {
return &SynApi{}
}
// WithCmbTOBB 将 request 存入上下文
func (w *SynApi) WithCmbTOBB(ctx context.Context) context.Context {
return context.WithValue(ctx, contextCMBToBBKey, &CmbToBBRequest{})
}
// GetCmbToBB 从上下文中获取 request
func (w *SynApi) GetCmbToBB(ctx context.Context) (*CmbToBBRequest, bool) {
req, ok := ctx.Value(contextCMBToBBKey).(*CmbToBBRequest)
return req, ok
}
// WithBBToWX 将 request 存入上下文
func (w *SynApi) WithBBToWX(ctx context.Context) context.Context {
return context.WithValue(ctx, contextBBToWXKey, &BBToWechatRequest{})
}
// GetBBToWX 从上下文中获取 request
func (w *SynApi) GetBBToWX(ctx context.Context) (*BBToWechatRequest, bool) {
req, ok := ctx.Value(contextBBToWXKey).(*BBToWechatRequest)
return req, ok
}

View File

@ -1,43 +0,0 @@
package syn_notice
// WechatToBBRequest 微信回调蓝色兄弟接口数据同步Api
type WechatToBBRequest struct {
// 活动ID
ActivityId string `protobuf:"bytes,9,opt,name=activityId,proto3" json:"activityId,omitempty"`
// 活动名称
ActivityName string `protobuf:"bytes,10,opt,name=activityName,proto3" json:"activityName,omitempty"`
// 优惠券ID
VoucherId string `protobuf:"bytes,11,opt,name=voucherId,proto3" json:"voucherId,omitempty"`
// 领取用户ID
UserId string `protobuf:"bytes,12,opt,name=userId,proto3" json:"userId,omitempty"`
// 核销时间Unix时间戳毫秒
UseTime string `protobuf:"bytes,13,opt,name=useTime,proto3" json:"useTime,omitempty"`
// 核销金额(分)
UseAmount string `protobuf:"bytes,14,opt,name=useAmount,proto3" json:"useAmount,omitempty"`
// 券消息类型例如券核销V_USE,V_REFUND
BizType string `protobuf:"bytes,15,opt,name=bizType,proto3" json:"bizType,omitempty"`
// 退款时间Unix时间戳毫秒
RefundTime string `protobuf:"bytes,16,opt,name=refundTime,proto3" json:"refundTime,omitempty"`
// 退款金额(分)
RefundAmount string `protobuf:"bytes,17,opt,name=refundAmount,proto3" json:"refundAmount,omitempty"`
// 券状态可用ENABLED/不可用DISABLED
VoucherStatus string `protobuf:"bytes,18,opt,name=voucherStatus,proto3" json:"voucherStatus,omitempty"`
// 幂等ID
OrderId string `protobuf:"bytes,19,opt,name=orderId,proto3" json:"orderId,omitempty"`
// 支付宝交易号
TradeNo string `protobuf:"bytes,20,opt,name=tradeNo,proto3" json:"tradeNo,omitempty"`
// 券领取时间Unix时间戳毫秒
GmtVoucherCreate string `protobuf:"bytes,21,opt,name=gmtVoucherCreate,proto3" json:"gmtVoucherCreate,omitempty"`
}
func (this *WechatToBBRequest) SetByOrder() {
}
func (this *WechatToBBRequest) GetSynNotice() *SynNotice {
return &SynNotice{
OutBizBo: this.OrderId,
Type: SynNoticeTypeBBToWechat,
BizContent: this,
}
}

View File

@ -2,15 +2,11 @@ package mixrepoimpl
import ( import (
"context" "context"
"encoding/json"
"fmt"
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
"net/http" "net/http"
"time" "time"
v1 "voucher/api/v1"
"voucher/internal/biz/kx" "voucher/internal/biz/kx"
"voucher/internal/biz/mixrepos" "voucher/internal/biz/mixrepos"
"voucher/internal/biz/vo"
"voucher/internal/conf" "voucher/internal/conf"
"voucher/internal/pkg/request" "voucher/internal/pkg/request"
) )
@ -39,20 +35,22 @@ func (s *KxMixRepoImpl) Request(ctx context.Context, req *kx.SynNotice) error {
_, bodyBytes, err := request.Post(ctx, url, body, request.WithHeaders(h), request.WithTimeout(time.Second*20)) _, bodyBytes, err := request.Post(ctx, url, body, request.WithHeaders(h), request.WithTimeout(time.Second*20))
if err != nil { if err != nil {
log.Errorf("请求kx报错,url:%s,err:%v", url, err) log.Errorf("请求kx报错,url:%s,body:%s,err:%v", url, string(body), err)
return err return err
} }
var response *v1.CmbReply log.Warnf("请求kx,url:%s,reqBody:%s,respBody:%s", url, string(body), string(bodyBytes))
if err = json.Unmarshal(bodyBytes, &response); err != nil {
log.Errorf("请求kx返回数据解析报错:%s,url:%s,bodyBytes:%s", err.Error(), url, string(bodyBytes))
return err
}
if response.RespCode != vo.CmbResponseStatusSuccess.GetValue() { //var response *v1.CmbReply
log.Errorf("请求kx返回报错:msg:%s,url:%s,bodyBytes:%s", response.RespMsg, url, string(bodyBytes)) //if err = json.Unmarshal(bodyBytes, &response); err != nil {
return fmt.Errorf(response.RespMsg) // log.Errorf("请求kx返回数据解析报错:%s,url:%s,reqBody:%s,respBody:%s", err.Error(), url, string(bodyBytes))
} // return err
//}
//
//if response.RespCode != vo.CmbResponseStatusSuccess.GetValue() {
// log.Errorf("请求kx返回报错:msg:%s,url:%s,respBody:%s", response.RespMsg, url, string(bodyBytes))
// return fmt.Errorf(response.RespMsg)
//}
return nil return nil
} }