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", payCommon.ALI_NOTIFY_URL_TEST+payOrderRequest.Ali.AppId). Set("notify_url", payCommon.ALI_NOTIFY_URL_PROD+payOrderRequest.Ali.AppId) 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 }