hotgo/server/internal/library/payment/alipay/handle.go

196 lines
4.8 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 alipay
import (
"context"
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/alipay"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/model"
"hotgo/internal/model/input/payin"
)
func New(config *model.PayConfig) *aliPay {
return &aliPay{
config: config,
}
}
type aliPay struct {
config *model.PayConfig
}
// Refund 订单退款
func (h *aliPay) Refund(ctx context.Context, in payin.RefundInp) (res *payin.RefundModel, err error) {
client, err := GetClient(h.config)
if err != nil {
return
}
bm := make(gopay.BodyMap)
bm.Set("out_trade_no", in.Pay.OutTradeNo).
Set("refund_amount", in.RefundMoney).
Set("out_request_no", in.RefundSn).
Set("refund_reason", in.Remark)
refund, err := client.TradeRefund(ctx, bm)
if err != nil {
return
}
if refund.Response.FundChange != "Y" {
err = gerror.New("支付宝本次退款未发生资金变化!")
return
}
return
}
// Notify 异步通知
func (h *aliPay) Notify(ctx context.Context, in payin.NotifyInp) (res *payin.NotifyModel, err error) {
notifyReq, err := alipay.ParseNotifyToBodyMap(ghttp.RequestFromCtx(ctx).Request)
if err != nil {
return
}
// 支付宝异步通知验签(公钥证书模式)
ok, err := alipay.VerifySignWithCert(h.config.AliPayCertPublicKeyRSA2, notifyReq)
if err != nil {
return
}
if !ok {
err = gerror.New("支付宝验签不通过!")
return
}
var notify *NotifyRequest
if err = gconv.Scan(notifyReq, &notify); err != nil {
return
}
if notify == nil {
err = gerror.New("解析订单参数失败!")
return
}
if notify.TradeStatus != "TRADE_SUCCESS" {
err = gerror.New("非交易支付成功状态,无需处理!")
// 这里如果相对非交易支付成功状态进行处理,可自行调整此处逻辑
// ...
return
}
if notify.OutTradeNo == "" {
err = gerror.New("订单中没有找到商户单号!")
return
}
res = new(payin.NotifyModel)
res.TransactionId = notify.TradeNo
res.OutTradeNo = notify.OutTradeNo
res.PayAt = notify.GmtPayment
res.ActualAmount = gconv.Float64(notify.ReceiptAmount)
return
}
// CreateOrder 创建订单
func (h *aliPay) CreateOrder(ctx context.Context, in payin.CreateOrderInp) (res *payin.CreateOrderModel, err error) {
client, err := GetClient(h.config)
if err != nil {
return nil, err
}
// 设置回调地址
client.SetReturnUrl(in.Pay.ReturnUrl).SetNotifyUrl(in.Pay.NotifyUrl)
switch in.Pay.TradeType {
case consts.TradeTypeAliScan, consts.TradeTypeAliWeb:
return h.scan(ctx, in)
case consts.TradeTypeAliWap:
return h.wap(ctx, in)
default:
err = gerror.Newf("暂未支持的交易方式:%v", in.Pay.TradeType)
}
return
}
func GetClient(config *model.PayConfig) (client *alipay.Client, err error) {
client, err = alipay.NewClient(config.AliPayAppId, gfile.GetContents(config.AliPayPrivateKey), true)
if err != nil {
err = gerror.Newf("创建支付宝客户端失败:%+v", err.Error())
return
}
// 打开Debug开关输出日志默认关闭
if config.Debug {
client.DebugSwitch = gopay.DebugOn
}
client.SetLocation(alipay.LocationShanghai) // 设置时区,不设置或出错均为默认服务器时间
// 证书路径
err = client.SetCertSnByPath(config.AliPayAppCertPublicKey, config.AliPayRootCert, config.AliPayCertPublicKeyRSA2)
return
}
// scan 扫码支付
func (h *aliPay) scan(ctx context.Context, in payin.CreateOrderInp) (res *payin.CreateOrderModel, err error) {
client, err := GetClient(h.config)
if err != nil {
return nil, err
}
// 设置回调地址
client.SetReturnUrl(in.Pay.ReturnUrl).SetNotifyUrl(in.Pay.NotifyUrl)
bm := make(gopay.BodyMap)
bm.Set("subject", in.Pay.Subject).
Set("out_trade_no", in.Pay.OutTradeNo).
Set("total_amount", in.Pay.PayAmount)
payUrl, err := client.TradePagePay(ctx, bm)
if err != nil {
if bizErr, ok := alipay.IsBizError(err); ok {
return nil, bizErr
}
return nil, err
}
res = new(payin.CreateOrderModel)
res.TradeType = in.Pay.TradeType
res.PayURL = payUrl
res.OutTradeNo = in.Pay.OutTradeNo
return
}
func (h *aliPay) wap(ctx context.Context, in payin.CreateOrderInp) (res *payin.CreateOrderModel, err error) {
client, err := GetClient(h.config)
if err != nil {
return nil, err
}
// 设置回调地址
client.SetReturnUrl(in.Pay.ReturnUrl).SetNotifyUrl(in.Pay.NotifyUrl)
bm := make(gopay.BodyMap)
bm.Set("subject", in.Pay.Subject).
Set("out_trade_no", in.Pay.OutTradeNo).
Set("total_amount", in.Pay.PayAmount).
Set("product_code", "QUICK_WAP_WAY")
// 手机网站支付请求
payUrl, err := client.TradeWapPay(ctx, bm)
if err != nil {
return
}
res = new(payin.CreateOrderModel)
res.TradeType = in.Pay.TradeType
res.PayURL = payUrl
res.OutTradeNo = in.Pay.OutTradeNo
return
}