f
This commit is contained in:
@@ -5,7 +5,7 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -28,6 +28,28 @@ type AliPayService struct {
|
||||
AlipayClientBak *alipay.Client // 仅用于 [2026-01-25 16:38:17, 2026-02-02 18:26) 区间内订单的退款
|
||||
}
|
||||
|
||||
// clientForMerchant 根据商户标识与订单时间选择对应的支付宝 client。
|
||||
// - merchant == "two" 且 Bak 存在:优先返回 Bak;
|
||||
// - merchant == "one" 或空:默认返回主商户;
|
||||
// - merchant 为空且 orderPayTime 落在备份时间区间:兼容老订单,走 Bak。
|
||||
func (a *AliPayService) clientForMerchant(merchant string, orderPayTime *time.Time) *alipay.Client {
|
||||
// 显式指定 two,则优先走 Bak
|
||||
if merchant == "two" && a.AlipayClientBak != nil {
|
||||
return a.AlipayClientBak
|
||||
}
|
||||
// 显式指定 one 或其他未知标识,一律走主商户
|
||||
if merchant == "one" || merchant == "" {
|
||||
// 对于老订单未写入 merchant 的情况,继续保留时间区间兜底逻辑
|
||||
if merchant == "" && orderPayTime != nil && a.AlipayClientBak != nil &&
|
||||
!orderPayTime.Before(AlipayBakRefundStart) && orderPayTime.Before(AlipayBakRefundEnd) {
|
||||
return a.AlipayClientBak
|
||||
}
|
||||
return a.AlipayClient
|
||||
}
|
||||
// 兜底:未知标识时仍走主商户,避免因为配置问题导致整体不可用
|
||||
return a.AlipayClient
|
||||
}
|
||||
|
||||
// NewAliPayService 是一个构造函数,用于初始化 AliPayService
|
||||
func NewAliPayService(c config.Config) *AliPayService {
|
||||
client, err := alipay.New(c.Alipay.AppID, c.Alipay.PrivateKey, c.Alipay.IsProduction)
|
||||
@@ -77,8 +99,8 @@ func NewAliPayService(c config.Config) *AliPayService {
|
||||
return svc
|
||||
}
|
||||
|
||||
func (a *AliPayService) CreateAlipayAppOrder(amount float64, subject string, outTradeNo string) (string, error) {
|
||||
client := a.AlipayClient
|
||||
func (a *AliPayService) CreateAlipayAppOrder(merchant string, amount float64, subject string, outTradeNo string) (string, error) {
|
||||
client := a.clientForMerchant(merchant, nil)
|
||||
totalAmount := lzUtils.ToAlipayAmount(amount)
|
||||
// 构造移动支付请求
|
||||
p := alipay.TradeAppPay{
|
||||
@@ -101,8 +123,8 @@ func (a *AliPayService) CreateAlipayAppOrder(amount float64, subject string, out
|
||||
}
|
||||
|
||||
// CreateAlipayH5Order 创建支付宝H5支付订单
|
||||
func (a *AliPayService) CreateAlipayH5Order(amount float64, subject string, outTradeNo string) (string, error) {
|
||||
client := a.AlipayClient
|
||||
func (a *AliPayService) CreateAlipayH5Order(merchant string, amount float64, subject string, outTradeNo string) (string, error) {
|
||||
client := a.clientForMerchant(merchant, nil)
|
||||
totalAmount := lzUtils.ToAlipayAmount(amount)
|
||||
// 构造H5支付请求
|
||||
p := alipay.TradeWapPay{
|
||||
@@ -124,8 +146,9 @@ func (a *AliPayService) CreateAlipayH5Order(amount float64, subject string, outT
|
||||
return payUrl.String(), nil
|
||||
}
|
||||
|
||||
// CreateAlipayOrder 根据平台类型创建支付宝支付订单
|
||||
func (a *AliPayService) CreateAlipayOrder(ctx context.Context, amount float64, subject string, outTradeNo string) (string, error) {
|
||||
// CreateAlipayOrder 根据平台类型和商户标识创建支付宝支付订单
|
||||
// merchant: 商户标识,目前约定 "one"=主商户, "two"=备商户
|
||||
func (a *AliPayService) CreateAlipayOrder(ctx context.Context, merchant string, amount float64, subject string, outTradeNo string) (string, error) {
|
||||
// 根据 ctx 中的 platform 判断平台
|
||||
platform, platformOk := ctx.Value("platform").(string)
|
||||
if !platformOk {
|
||||
@@ -134,23 +157,21 @@ func (a *AliPayService) CreateAlipayOrder(ctx context.Context, amount float64, s
|
||||
switch platform {
|
||||
case model.PlatformApp:
|
||||
// 调用App支付的创建方法
|
||||
return a.CreateAlipayAppOrder(amount, subject, outTradeNo)
|
||||
return a.CreateAlipayAppOrder(merchant, amount, subject, outTradeNo)
|
||||
case model.PlatformH5:
|
||||
// 调用H5支付的创建方法,并传入 returnUrl
|
||||
return a.CreateAlipayH5Order(amount, subject, outTradeNo)
|
||||
return a.CreateAlipayH5Order(merchant, amount, subject, outTradeNo)
|
||||
default:
|
||||
return "", fmt.Errorf("不支持的支付平台: %s", platform)
|
||||
}
|
||||
}
|
||||
|
||||
// AliRefund 发起支付宝退款。orderPayTime 为订单支付时间(或创建时间);仅当落在 [2026-01-25 16:38:17, 2026-02-02 18:26) 区间内时使用 bak 商户号,否则使用正式商户号;传 nil 则使用正式商户号。
|
||||
// AliRefund 发起支付宝退款。
|
||||
// merchant: 支付商户标识(one/two)。为空时按老逻辑仅在备份时间区间内使用 Bak。
|
||||
// orderPayTime 为订单支付时间(或创建时间);用于老订单按时间区间选择商户;传 nil 则忽略时间区间。
|
||||
// outRequestNo 为商户退款请求号,同一笔退款需唯一;传空则使用 "refund-"+outTradeNo,重试时建议传入唯一号避免支付宝报重复。
|
||||
func (a *AliPayService) AliRefund(ctx context.Context, outTradeNo string, refundAmount float64, orderPayTime *time.Time, outRequestNo string) (*alipay.TradeRefundRsp, error) {
|
||||
client := a.AlipayClient
|
||||
if orderPayTime != nil && a.AlipayClientBak != nil &&
|
||||
!orderPayTime.Before(AlipayBakRefundStart) && orderPayTime.Before(AlipayBakRefundEnd) {
|
||||
client = a.AlipayClientBak
|
||||
}
|
||||
func (a *AliPayService) AliRefund(ctx context.Context, merchant string, outTradeNo string, refundAmount float64, orderPayTime *time.Time, outRequestNo string) (*alipay.TradeRefundRsp, error) {
|
||||
client := a.clientForMerchant(merchant, orderPayTime)
|
||||
|
||||
if outRequestNo == "" {
|
||||
outRequestNo = fmt.Sprintf("refund-%s", outTradeNo)
|
||||
@@ -168,27 +189,26 @@ func (a *AliPayService) AliRefund(ctx context.Context, outTradeNo string, refund
|
||||
return refundResp, nil
|
||||
}
|
||||
|
||||
// HandleAliPaymentNotification 支付宝支付回调
|
||||
func (a *AliPayService) HandleAliPaymentNotification(r *http.Request) (*alipay.Notification, error) {
|
||||
// 解析表单
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("解析请求表单失败:%v", err)
|
||||
}
|
||||
// HandleAliPaymentNotification 支付宝支付回调验签。
|
||||
// 由上层根据 out_trade_no 查出订单并传入对应商户标识 merchant。
|
||||
func (a *AliPayService) HandleAliPaymentNotification(merchant string, form url.Values) (*alipay.Notification, error) {
|
||||
client := a.clientForMerchant(merchant, nil)
|
||||
// 解析并验证通知,DecodeNotification 会自动验证签名
|
||||
notification, err := a.AlipayClient.DecodeNotification(r.Form)
|
||||
notification, err := client.DecodeNotification(form)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("验证签名失败: %v", err)
|
||||
}
|
||||
return notification, nil
|
||||
}
|
||||
func (a *AliPayService) QueryOrderStatus(ctx context.Context, outTradeNo string) (*alipay.TradeQueryRsp, error) {
|
||||
// QueryOrderStatus 按商户标识查询支付宝订单状态
|
||||
func (a *AliPayService) QueryOrderStatus(ctx context.Context, merchant string, outTradeNo string) (*alipay.TradeQueryRsp, error) {
|
||||
client := a.clientForMerchant(merchant, nil)
|
||||
queryRequest := alipay.TradeQuery{
|
||||
OutTradeNo: outTradeNo,
|
||||
}
|
||||
|
||||
// 发起查询请求
|
||||
resp, err := a.AlipayClient.TradeQuery(ctx, queryRequest)
|
||||
resp, err := client.TradeQuery(ctx, queryRequest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询支付宝订单失败: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user