PaymentCenter/app/third/paymentService/ali_service.go

274 lines
8.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package paymentService
import (
"PaymentCenter/app/third/paymentService/payCommon"
"context"
"errors"
"fmt"
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/alipay"
"github.com/qit-team/snow-core/log/logger"
"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", fmt.Sprintf(payCommon.ALI_NOTIFY_URL_TEST+"%d", payOrderRequest.PayChannelId)).
Set("notify_url", fmt.Sprintf(payCommon.ALI_NOTIFY_URL_PROD+"%d", payOrderRequest.PayChannelId))
aliRsp, err := aliClient.TradeWapPay(c, bm)
if err != nil {
logger.Error(c, "ALiH5PayInfo 发生错误", fmt.Sprintf("错误信息:%s", err.Error()))
if bizErr, ok := alipay.IsBizError(err); ok {
return "", bizErr
}
return "", err
}
return aliRsp, nil
}
// ALiCallBack 支付宝支付回调
func ALiCallBack(notifyReq gopay.BodyMap, aliConfig AliPay) error {
ok, err := alipay.VerifySignWithCert(aliConfig.AlipayPublicCert, notifyReq)
if !ok || err != nil {
return err
}
// todo 拼装数据触发下游回调,数据待定
return 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)
// 构建数据
outTradeNo, _ := strconv.Atoi(aliRsp.Response.OutTradeNo)
return PayOrderQueryInfo{
AppId: aliConfig.AppId,
OutTradeNo: int64(outTradeNo),
TransactionId: aliRsp.Response.TradeNo,
TradeState: tradeState,
TradeStateDesc: tradeStateDesc,
SuccessTime: aliRsp.Response.SendPayDate,
AmountTotal: int64(amountTotal * 100),
PayerTotal: int64(payerTotal * 100),
}, nil
}
// AliRefundOrder 支付宝退款申请
func AliRefundOrder(ctx context.Context, orderRefundRequest OrderRefundRequest) (OrderRefundInfo, error) {
// 初始化支付宝客户端
AliInitClient(orderRefundRequest.Ali)
// 获取支付宝客户端
aliClient, err := GetAliClient()
if err != nil {
fmt.Println("Failed to get client:", err)
return OrderRefundInfo{}, err
}
// 请求参数
bm := make(gopay.BodyMap)
bm.Set("out_trade_no", orderRefundRequest.OrderId).
Set("refund_amount", orderRefundRequest.RefundAmount).
Set("refund_reason", orderRefundRequest.RefundReason).
Set("out_request_no", orderRefundRequest.RefundOrderId)
// 发起退款请求
aliRsp, err := aliClient.TradeRefund(ctx, bm)
if err != nil {
logger.Error(ctx, "AliRefundOrder 发生错误", fmt.Sprintf("申请退款接口失败,错误信息:%s", err.Error()))
if bizErr, ok := alipay.IsBizError(err); ok {
return OrderRefundInfo{}, bizErr
}
return OrderRefundInfo{}, err
}
refundFee, _ := strconv.Atoi(aliRsp.Response.RefundFee)
outTradeNo, _ := strconv.Atoi(aliRsp.Response.OutTradeNo)
return OrderRefundInfo{
OutTradeNo: int64(outTradeNo),
TransactionId: aliRsp.Response.TradeNo,
RefundFee: int64(refundFee * 100),
RefundOrderId: orderRefundRequest.RefundOrderId,
RefundStatus: payCommon.PAY_REFUND_STATU_SUCCESS,
}, nil
}
// AliRefundOrderQuery 支付宝订单退款查询
func AliRefundOrderQuery(ctx context.Context, orderRefundQueryRequest OrderRefundQueryRequest) (OrderRefundInfo, error) {
// 初始化支付宝客户端
AliInitClient(orderRefundQueryRequest.Ali)
// 获取支付宝客户端
aliClient, err := GetAliClient()
if err != nil {
fmt.Println("Failed to get client:", err)
return OrderRefundInfo{}, err
}
// 请求参数
bm := make(gopay.BodyMap)
bm.Set("out_trade_no", orderRefundQueryRequest.OrderId).
Set("out_request_no", orderRefundQueryRequest.RefundOrderId).
Set("query_options", []string{"gmt_refund_pay"})
// 发起退款查询请求
aliRsp, err := aliClient.TradeFastPayRefundQuery(ctx, bm)
if err != nil {
if bizErr, ok := alipay.IsBizError(err); ok {
return OrderRefundInfo{}, bizErr
}
return OrderRefundInfo{}, err
}
refundFee, _ := strconv.Atoi(aliRsp.Response.RefundAmount)
outTradeNo, _ := strconv.Atoi(aliRsp.Response.OutTradeNo)
refundOrderId, _ := strconv.Atoi(aliRsp.Response.OutRequestNo)
return OrderRefundInfo{
OutTradeNo: int64(outTradeNo),
TransactionId: aliRsp.Response.TradeNo,
RefundFee: int64(refundFee * 100),
RefundOrderId: int64(refundOrderId),
RefundStatus: payCommon.PAY_REFUND_STATU_SUCCESS,
RefundSuccessTime: aliRsp.Response.GmtRefundPay,
}, nil
}
// AliCloseOrder 支付宝订单关闭
func AliCloseOrder(ctx context.Context, orderCloseRequest OrderCloseRequest) (OrderCloseInfo, error) {
// 初始化支付宝客户端
AliInitClient(orderCloseRequest.Ali)
// 获取支付宝客户端
aliClient, err := GetAliClient()
if err != nil {
fmt.Println("Failed to get client:", err)
return OrderCloseInfo{}, err
}
// 请求参数
bm := make(gopay.BodyMap)
bm.Set("out_trade_no", orderCloseRequest.OrderId)
// 关闭订单
aliRsp, err := aliClient.TradeClose(ctx, bm)
if err != nil {
logger.Error(ctx, "AliCloseOrder 发生错误", fmt.Sprintf("申请退款接口失败,错误信息:%s", err.Error()))
if bizErr, ok := alipay.IsBizError(err); ok {
return OrderCloseInfo{}, bizErr
}
return OrderCloseInfo{}, err
}
outTradeNo, _ := strconv.Atoi(aliRsp.Response.OutTradeNo)
return OrderCloseInfo{
OutTradeNo: int64(outTradeNo),
}, nil
}