150 lines
4.5 KiB
Go
150 lines
4.5 KiB
Go
package paymentService
|
||
|
||
import (
|
||
"PaymentCenter/app/third/paymentService/payCommon"
|
||
"context"
|
||
"errors"
|
||
"fmt"
|
||
"github.com/go-pay/gopay"
|
||
"github.com/go-pay/gopay/alipay"
|
||
"strconv"
|
||
"sync"
|
||
)
|
||
|
||
var (
|
||
aliClient *alipay.Client
|
||
aliClientErr error
|
||
aliOnce sync.Once
|
||
)
|
||
|
||
// AliInitClient 使用提供的支付请求参数初始化支付宝客户端
|
||
func AliInitClient(aliConfig AliPay) {
|
||
aliOnce.Do(func() {
|
||
// 初始化支付宝客户端
|
||
// appid:应用ID
|
||
// privateKey:应用私钥,支持PKCS1和PKCS8
|
||
// isProd:是否是正式环境,沙箱环境请选择新版沙箱应用。
|
||
aliClient, aliClientErr = alipay.NewClient(aliConfig.AppId, aliConfig.PrivateKey, true)
|
||
})
|
||
// 自定义配置http请求接收返回结果body大小,默认 10MB
|
||
aliClient.SetBodySize(10) // 没有特殊需求,可忽略此配置
|
||
|
||
// 打开Debug开关,输出日志,默认关闭
|
||
aliClient.DebugSwitch = gopay.DebugOn
|
||
|
||
// 设置支付宝请求 公共参数
|
||
// 注意:具体设置哪些参数,根据不同的方法而不同,此处列举出所有设置参数
|
||
aliClient.SetLocation(alipay.LocationShanghai). // 设置时区,不设置或出错均为默认服务器时间
|
||
SetCharset(alipay.UTF8). // 设置字符编码,不设置默认 utf-8
|
||
SetSignType(alipay.RSA2) // 设置签名类型,不设置默认 RSA2
|
||
|
||
// 自动同步验签(只支持证书模式)
|
||
// 传入 alipayPublicCert.crt 内容
|
||
aliClient.AutoVerifySign(aliConfig.AlipayPublicCert)
|
||
|
||
// 证书内容
|
||
aliClientErr = aliClient.SetCertSnByContent(aliConfig.AppPublicCert, aliConfig.AlipayRootCert, aliConfig.AlipayPublicCert)
|
||
}
|
||
|
||
// GetAliClient 获取已经初始化的支付宝客户端
|
||
func GetAliClient() (*alipay.Client, error) {
|
||
if aliClient == nil {
|
||
return nil, errors.New("client not initialized")
|
||
}
|
||
if aliClientErr != nil {
|
||
return nil, aliClientErr
|
||
}
|
||
return aliClient, nil
|
||
}
|
||
|
||
// ALiH5PayInfo 支付宝手机网站支付
|
||
func ALiH5PayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, error) {
|
||
// 初始化支付宝客户端
|
||
AliInitClient(payOrderRequest.Ali)
|
||
|
||
// 获取支付宝客户端
|
||
aliClient, err := GetAliClient()
|
||
if err != nil {
|
||
fmt.Println("Failed to get client:", err)
|
||
return "", err
|
||
}
|
||
// 初始化 BodyMap
|
||
amount := float64(payOrderRequest.Amount) / 100.0
|
||
|
||
bm := make(gopay.BodyMap)
|
||
bm.Set("out_trade_no", payOrderRequest.OrderId).
|
||
Set("total_amount", amount).
|
||
Set("subject", payOrderRequest.Description).
|
||
Set("notify_url", payCommon.ALI_NOTIFY_URL)
|
||
|
||
aliRsp, err := aliClient.TradeWapPay(c, bm)
|
||
if err != nil {
|
||
if bizErr, ok := alipay.IsBizError(err); ok {
|
||
return "", bizErr
|
||
}
|
||
return "", err
|
||
}
|
||
return aliRsp, nil
|
||
}
|
||
|
||
// ALiOrderQuery 查询支付宝订单
|
||
func ALiOrderQuery(ctx context.Context, aliConfig AliPay, OrderNo string) (PayOrderQueryInfo, error) {
|
||
// 初始化支付宝客户端
|
||
AliInitClient(aliConfig)
|
||
|
||
// 获取支付宝客户端
|
||
aliClient, err := GetAliClient()
|
||
if err != nil {
|
||
fmt.Println("Failed to get client:", err)
|
||
return PayOrderQueryInfo{}, err
|
||
}
|
||
// 请求参数
|
||
bm := make(gopay.BodyMap)
|
||
bm.Set("out_trade_no", OrderNo)
|
||
|
||
// 查询订单
|
||
aliRsp, err := aliClient.TradeQuery(ctx, bm)
|
||
if err != nil {
|
||
if bizErr, ok := alipay.IsBizError(err); ok {
|
||
return PayOrderQueryInfo{}, bizErr
|
||
}
|
||
return PayOrderQueryInfo{}, err
|
||
}
|
||
// 同步返回验签
|
||
ok, err := alipay.VerifySyncSignWithCert(aliConfig.AlipayPublicCert, aliRsp.SignData, aliRsp.Sign)
|
||
if err != nil || !ok {
|
||
return PayOrderQueryInfo{}, errors.New(fmt.Sprintf("验签失败,失败原因:%s", err.Error()))
|
||
}
|
||
|
||
// 映射交易状态
|
||
tradeState := ""
|
||
tradeStateDesc := ""
|
||
switch aliRsp.Response.TradeStatus {
|
||
case "TRADE_SUCCESS":
|
||
tradeState = "SUCCESS"
|
||
tradeStateDesc = "交易支付成功"
|
||
case "REFUND":
|
||
tradeState = "REFUND"
|
||
case "WAIT_BUYER_PAY":
|
||
tradeState = "NOTPAY"
|
||
tradeStateDesc = "交易创建,等待买家付款"
|
||
case "TRADE_CLOSED":
|
||
tradeState = "CLOSED"
|
||
tradeStateDesc = "未付款交易超时关闭,或支付完成后全额退款"
|
||
}
|
||
|
||
amountTotal, _ := strconv.Atoi(aliRsp.Response.TotalAmount)
|
||
payerTotal, _ := strconv.Atoi(aliRsp.Response.BuyerPayAmount)
|
||
// 构建数据
|
||
return PayOrderQueryInfo{
|
||
AppId: aliConfig.AppId,
|
||
OutTradeNo: aliRsp.Response.OutTradeNo,
|
||
TransactionId: aliRsp.Response.TradeNo,
|
||
TradeState: tradeState,
|
||
TradeStateDesc: tradeStateDesc,
|
||
SuccessTime: aliRsp.Response.SendPayDate,
|
||
AmountTotal: int64(amountTotal * 100),
|
||
PayerTotal: int64(payerTotal * 100),
|
||
}, nil
|
||
}
|