This commit is contained in:
sjk
2025-11-28 15:18:10 +08:00
parent ad4a600af9
commit 5683f35942
188 changed files with 53680 additions and 1062 deletions

View File

@@ -17,6 +17,7 @@ import (
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments/native"
"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
wechatutils "github.com/wechatpay-apiv3/wechatpay-go/utils"
)
@@ -25,6 +26,7 @@ type WeChatPayService struct {
config *config.WeChatPayConfig
client *core.Client
jsapiSvc *jsapi.JsapiApiService
nativeSvc *native.NativeApiService
refundSvc *refunddomestic.RefundsApiService
privateKey *rsa.PrivateKey
orderRepo *repository.OrderRepository
@@ -74,6 +76,9 @@ func NewWeChatPayService(cfg *config.WeChatPayConfig, orderRepo *repository.Orde
// 创建JSAPI服务
jsapiSvc := &jsapi.JsapiApiService{Client: client}
// 创建Native扫码支付服务
nativeSvc := &native.NativeApiService{Client: client}
// 创建退款服务
refundSvc := &refunddomestic.RefundsApiService{Client: client}
@@ -86,6 +91,7 @@ func NewWeChatPayService(cfg *config.WeChatPayConfig, orderRepo *repository.Orde
config: cfg,
client: client,
jsapiSvc: jsapiSvc,
nativeSvc: nativeSvc,
refundSvc: refundSvc,
privateKey: privateKey,
orderRepo: orderRepo,
@@ -174,6 +180,99 @@ func (s *WeChatPayService) CreateOrder(ctx context.Context, order *model.Order,
}, nil
}
// CreateNativeOrder 创建Native扫码支付订单用于PC端
func (s *WeChatPayService) CreateNativeOrder(ctx context.Context, order *model.Order) (*WeChatPayResponse, error) {
// 生成唯一的微信支付订单号
wechatOutTradeNo := utils.GenerateWechatOutTradeNo()
logger.Info("开始创建Native扫码支付订单",
"orderNo", order.OrderNo,
"wechatOutTradeNo", wechatOutTradeNo,
"totalAmount", order.TotalAmount,
"hasClient", s.client != nil)
// 更新订单的微信支付订单号
err := s.orderRepo.UpdateByOrderNo(order.OrderNo, map[string]interface{}{
"wechat_out_trade_no": wechatOutTradeNo,
"updated_at": time.Now(),
})
if err != nil {
logger.Error("更新订单微信支付订单号失败", "error", err, "orderNo", order.OrderNo)
return nil, fmt.Errorf("更新订单失败: %v", err)
}
// 如果没有客户端(开发环境),使用模拟数据
if s.client == nil {
logger.Warn("开发环境下使用模拟Native支付数据")
return s.createMockNativePayment(order)
}
// 构建Native预支付请求
req := native.PrepayRequest{
Appid: core.String(s.config.AppID),
Mchid: core.String(s.config.MchID),
Description: core.String(fmt.Sprintf("订单号: %s", order.OrderNo)),
OutTradeNo: core.String(wechatOutTradeNo),
NotifyUrl: core.String(s.config.NotifyURL),
Amount: &native.Amount{
Total: core.Int64(int64(order.TotalAmount)),
Currency: core.String("CNY"),
},
}
// 调用Native预支付API
resp, result, err := s.nativeSvc.Prepay(ctx, req)
if err != nil {
log.Printf("call Native Prepay err:%s", err)
logger.Error("创建Native支付订单失败", "error", err, "orderNo", order.OrderNo)
return nil, fmt.Errorf("创建Native支付订单失败: %v", err)
}
if result.Response.StatusCode != 200 {
log.Printf("Native Prepay status=%d", result.Response.StatusCode)
return nil, fmt.Errorf("Native预支付请求失败状态码: %d", result.Response.StatusCode)
}
log.Printf("Native Prepay success, code_url=%s", *resp.CodeUrl)
logger.Info("微信Native支付API响应",
"codeUrl", *resp.CodeUrl,
"orderNo", order.OrderNo)
return &WeChatPayResponse{
Code: 0,
Message: "success",
Data: map[string]interface{}{
"qrcode_url": *resp.CodeUrl,
"order_no": order.OrderNo,
"amount": order.TotalAmount,
},
}, nil
}
// createMockNativePayment 创建模拟Native支付数据开发环境使用
func (s *WeChatPayService) createMockNativePayment(order *model.Order) (*WeChatPayResponse, error) {
// 生成模拟的二维码URL
mockQRCodeURL := fmt.Sprintf("weixin://wxpay/bizpayurl?pr=mock_%s", utils.GenerateRandomString(10))
logger.Info("生成模拟Native支付参数",
"environment", s.config.Environment,
"qrcodeUrl", mockQRCodeURL,
"orderNo", order.OrderNo,
"totalAmount", order.TotalAmount)
return &WeChatPayResponse{
Code: 0,
Message: "模拟支付创建成功",
Data: map[string]interface{}{
"qrcode_url": mockQRCodeURL,
"order_no": order.OrderNo,
"amount": order.TotalAmount,
"sandbox": true,
"tips": "这是模拟环境的Native支付请使用测试接口模拟支付成功",
},
}, nil
}
// createMockPayment 创建模拟支付数据(沙盒环境使用)
func (s *WeChatPayService) createMockPayment(order *model.Order, openID string) (*WeChatPayResponse, error) {
mockPrepayID := fmt.Sprintf("wx%d%s", time.Now().Unix(), generateNonceStr()[:8])