package alipaycli import ( "context" "fmt" "github.com/go-pay/gopay" "github.com/go-pay/gopay/alipay" "net/http" "service/bizcommon/util" "service/library/configcenter" "service/library/logger" "time" ) const ( DefaultOrderTimeoutSeconds = 900 // 默认订单超时时间,单位: s ) var defaultAlipayClient *AlipayClient func GetDefaultAlipayClient() *AlipayClient { return defaultAlipayClient } type AlipayClient struct { *alipay.Client } func Init(cfg *configcenter.AlipayClientConfig) (err error) { alipayCli, err := alipay.NewClient(cfg.Appid, cfg.PrivateKey, true) if err != nil { logger.Error("NewClient fail, cfg: %v, err: %v", util.ToJson(cfg), err) return } alipayCli.SetNotifyUrl(cfg.NotifyUrl) err = alipayCli.SetCertSnByPath( "/app/wishpal-ironfan/etc/mix/alipaycert/appCertPublicKey_2021004115647165.crt", "/app/wishpal-ironfan/etc/mix/alipaycert/alipayRootCert.crt", "/app/wishpal-ironfan/etc/mix/alipaycert/alipayCertPublicKey_RSA2.crt", ) if err != nil { logger.Error("SetCertSnByPath fail, cfg: %v, err: %v", util.ToJson(cfg), err) return } defaultAlipayClient = &AlipayClient{ Client: alipayCli, } return } // 解析回调参数 func (c *AlipayClient) ParseNotify(req *http.Request) (notify gopay.BodyMap, err error) { // 解析参数 notifyTmp, err := alipay.ParseNotifyToBodyMap(req) if err != nil { logger.Error("ParseNotifyToBodyMap fail, req: %v, err: %v", util.ToJson(req), err) return } logger.Info("Alipay ParseNotify, %v", util.ToJson(notifyTmp)) // 验签 ok, err := alipay.VerifySignWithCert("/app/wishpal-ironfan/etc/mix/alipaycert/alipayCertPublicKey_RSA2.crt", notifyTmp) if !ok { logger.Error("VerifySign fail, not ok, bm: %v", util.ToJson(notifyTmp)) return } notify = notifyTmp return } // 支付宝 app支付 type AppPayParam struct { OutTradeNo string // 商家订单id,我们自己的订单id Subject string // 主题 TotalAmount int64 // 金额,单位:分 TimeOutSeconds int // 订单有效时间,单位:秒 } func (c *AlipayClient) AppPay(ctx context.Context, param *AppPayParam) (alipayAppParamStr string, err error) { if param.TimeOutSeconds <= 0 { param.TimeOutSeconds = DefaultOrderTimeoutSeconds } bm := gopay.BodyMap{ "out_trade_no": param.OutTradeNo, "subject": param.Subject, "total_amount": fmt.Sprintf("%.2f", float64(param.TotalAmount)/100.0), "time_expire": time.Now().Add(time.Second * time.Duration(param.TimeOutSeconds)).Format("2006-01-02 15:04:05"), "notify_url": c.NotifyUrl, } alipayAppParamStr, err = c.TradeAppPay(ctx, bm) if err != nil { return } logger.Info("alipay TradeAppPay param: %v", alipayAppParamStr) return } // 支付宝 手机web支付 type WapPayParam struct { OutTradeNo string // 商家订单id,我们自己的订单id Subject string // 主题 TotalAmount int64 // 金额,单位:分 TimeOutSeconds int // 订单有效时间,单位:秒 ReturnUrl string // 支付宝return_url } func (c *AlipayClient) WapPay(ctx context.Context, param *WapPayParam) (alipayWapParamStr string, err error) { if param.TimeOutSeconds <= 0 { param.TimeOutSeconds = DefaultOrderTimeoutSeconds } bm := gopay.BodyMap{ "out_trade_no": param.OutTradeNo, "subject": param.Subject, "total_amount": fmt.Sprintf("%.2f", float64(param.TotalAmount)/100.0), "time_expire": time.Now().Add(time.Second * time.Duration(param.TimeOutSeconds)).Format("2006-01-02 15:04:05"), "notify_url": c.NotifyUrl, } if len(param.ReturnUrl) > 0 { bm["return_url"] = param.ReturnUrl } alipayWapParamStr, err = c.TradeWapPay(ctx, bm) if err != nil { return } logger.Info("alipay TradeWapPay param: %v", alipayWapParamStr) return } // 支付宝单笔转账 type UniTransferParam struct { OutBizNo string // 商家订单id,我们自己的订单id Amount int64 // 金额,单位:分 Title string // 转账业务的标题,用于在支付宝用户的账单里显示。 AlipayLoginId string // 支付宝登录账号 AlipayName string // 支付宝真实姓名 } func (c *AlipayClient) UniTransfer(ctx context.Context, param *UniTransferParam) (resp *alipay.FundTransUniTransferResponse, err error) { bm := gopay.BodyMap{ "out_biz_no": param.OutBizNo, "trans_amount": fmt.Sprintf("%.2f", float64(param.Amount)/100.0), "biz_scene": "DIRECT_TRANSFER", "product_code": "TRANS_ACCOUNT_NO_PWD", "order_title": param.Title, "payee_info": map[string]interface{}{ "identity": param.AlipayLoginId, "identity_type": "ALIPAY_LOGON_ID", "name": param.AlipayName, }, } resp, err = c.FundTransUniTransfer(ctx, bm) if err != nil { return } logger.Info("alipay UniTransfer param: %v, resp: %v", bm.JsonBody(), util.ToJson(resp)) return } // 订单查询 type QueryOrderParam struct { OutTradeNo string // 商家订单id,我们自己的订单id } func (c *AlipayClient) QueryOrder(ctx context.Context, param *QueryOrderParam) (resp *alipay.TradeQueryResponse, err error) { bm := gopay.BodyMap{ "out_trade_no": param.OutTradeNo, } resp, err = c.TradeQuery(ctx, bm) if err != nil { return } return }