微信相关能力

This commit is contained in:
2026-01-30 17:25:30 +08:00
parent 4856a88d41
commit bf591095a2
43 changed files with 4297 additions and 391 deletions

View File

@@ -14,6 +14,7 @@ import (
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/break/junhong_cmp_fiber/pkg/queue"
"github.com/break/junhong_cmp_fiber/pkg/utils"
"github.com/break/junhong_cmp_fiber/pkg/wechat"
"github.com/bytedance/sonic"
"go.uber.org/zap"
"gorm.io/gorm"
@@ -26,6 +27,7 @@ type Service struct {
walletStore *postgres.WalletStore
purchaseValidationService *purchase_validation.Service
allocationConfigStore *postgres.ShopSeriesAllocationConfigStore
wechatPayment wechat.PaymentServiceInterface
queueClient *queue.Client
logger *zap.Logger
}
@@ -37,6 +39,7 @@ func New(
walletStore *postgres.WalletStore,
purchaseValidationService *purchase_validation.Service,
allocationConfigStore *postgres.ShopSeriesAllocationConfigStore,
wechatPayment wechat.PaymentServiceInterface,
queueClient *queue.Client,
logger *zap.Logger,
) *Service {
@@ -47,6 +50,7 @@ func New(
walletStore: walletStore,
purchaseValidationService: purchaseValidationService,
allocationConfigStore: allocationConfigStore,
wechatPayment: wechatPayment,
queueClient: queueClient,
logger: logger,
}
@@ -529,3 +533,116 @@ func (s *Service) buildOrderResponse(order *model.Order, items []*model.OrderIte
UpdatedAt: order.UpdatedAt,
}
}
// WechatPayJSAPI 发起微信 JSAPI 支付
func (s *Service) WechatPayJSAPI(ctx context.Context, orderID uint, openID string, buyerType string, buyerID uint) (*dto.WechatPayJSAPIResponse, error) {
if s.wechatPayment == nil {
s.logger.Error("微信支付服务未配置")
return nil, errors.New(errors.CodeWechatPayFailed, "微信支付服务未配置")
}
order, err := s.orderStore.GetByID(ctx, orderID)
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, errors.New(errors.CodeNotFound, "订单不存在")
}
return nil, errors.Wrap(errors.CodeInternalError, err, "查询订单失败")
}
if order.BuyerType != buyerType || order.BuyerID != buyerID {
return nil, errors.New(errors.CodeForbidden, "无权操作此订单")
}
if order.PaymentStatus != model.PaymentStatusPending {
return nil, errors.New(errors.CodeInvalidStatus, "订单状态不允许支付")
}
items, err := s.orderItemStore.ListByOrderIDs(ctx, []uint{orderID})
if err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "查询订单明细失败")
}
description := "套餐购买"
if len(items) > 0 {
description = items[0].PackageName
}
result, err := s.wechatPayment.CreateJSAPIOrder(ctx, order.OrderNo, description, openID, int(order.TotalAmount))
if err != nil {
s.logger.Error("创建 JSAPI 支付失败",
zap.Uint("order_id", orderID),
zap.String("order_no", order.OrderNo),
zap.Error(err),
)
return nil, err
}
s.logger.Info("创建 JSAPI 支付成功",
zap.Uint("order_id", orderID),
zap.String("order_no", order.OrderNo),
zap.String("prepay_id", result.PrepayID),
)
payConfig, _ := result.PayConfig.(map[string]interface{})
return &dto.WechatPayJSAPIResponse{
PrepayID: result.PrepayID,
PayConfig: payConfig,
}, nil
}
// WechatPayH5 发起微信 H5 支付
func (s *Service) WechatPayH5(ctx context.Context, orderID uint, sceneInfo *dto.WechatH5SceneInfo, buyerType string, buyerID uint) (*dto.WechatPayH5Response, error) {
if s.wechatPayment == nil {
s.logger.Error("微信支付服务未配置")
return nil, errors.New(errors.CodeWechatPayFailed, "微信支付服务未配置")
}
order, err := s.orderStore.GetByID(ctx, orderID)
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, errors.New(errors.CodeNotFound, "订单不存在")
}
return nil, errors.Wrap(errors.CodeInternalError, err, "查询订单失败")
}
if order.BuyerType != buyerType || order.BuyerID != buyerID {
return nil, errors.New(errors.CodeForbidden, "无权操作此订单")
}
if order.PaymentStatus != model.PaymentStatusPending {
return nil, errors.New(errors.CodeInvalidStatus, "订单状态不允许支付")
}
items, err := s.orderItemStore.ListByOrderIDs(ctx, []uint{orderID})
if err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "查询订单明细失败")
}
description := "套餐购买"
if len(items) > 0 {
description = items[0].PackageName
}
h5SceneInfo := &wechat.H5SceneInfo{
PayerClientIP: sceneInfo.PayerClientIP,
H5Type: sceneInfo.H5Info.Type,
}
result, err := s.wechatPayment.CreateH5Order(ctx, order.OrderNo, description, int(order.TotalAmount), h5SceneInfo)
if err != nil {
s.logger.Error("创建 H5 支付失败",
zap.Uint("order_id", orderID),
zap.String("order_no", order.OrderNo),
zap.Error(err),
)
return nil, err
}
s.logger.Info("创建 H5 支付成功",
zap.Uint("order_id", orderID),
zap.String("order_no", order.OrderNo),
zap.String("h5_url", result.H5URL),
)
return &dto.WechatPayH5Response{
H5URL: result.H5URL,
}, nil
}

View File

@@ -126,7 +126,7 @@ func setupOrderTestEnv(t *testing.T) *testEnv {
purchaseValidationSvc := purchase_validation.New(tx, iotCardStore, deviceStore, packageStore, seriesAllocationStore)
logger := zap.NewNop()
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, nil, logger)
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, nil, nil, logger)
userCtx := middleware.SetUserContext(ctx, &middleware.UserContextInfo{
UserID: 1,
@@ -536,7 +536,7 @@ func TestOrderService_IdempotencyAndConcurrency(t *testing.T) {
purchaseValidationSvc := purchase_validation.New(tx, iotCardStore, deviceStore, packageStore, seriesAllocationStore)
logger := zap.NewNop()
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, nil, logger)
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, nil, nil, logger)
userCtx := middleware.SetUserContext(ctx, &middleware.UserContextInfo{
UserID: 1,