147 lines
4.8 KiB
Go
147 lines
4.8 KiB
Go
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
|
//go:build plus
|
|
|
|
package payments
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models/accounts"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
|
"github.com/iwind/TeaGo/dbs"
|
|
"github.com/smartwalle/alipay/v3"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
type AlipayPayment struct {
|
|
}
|
|
|
|
func NewAlipayPayment() *AlipayPayment {
|
|
return &AlipayPayment{}
|
|
}
|
|
|
|
// GeneratePayURL 构造支付URL
|
|
func (this *AlipayPayment) GeneratePayURL(order *accounts.UserOrder, method *accounts.OrderMethod) (string, error) {
|
|
var params = &userconfigs.AlipayPayMethodParams{}
|
|
err := json.Unmarshal(method.Params, params)
|
|
if err != nil {
|
|
return "", errors.New("decode params: " + err.Error())
|
|
}
|
|
|
|
client, err := this.client(params)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var def = userconfigs.FindPresetPayMethodWithCode(userconfigs.PayMethodAlipay)
|
|
if def == nil {
|
|
return "", errors.New("can not find payment method")
|
|
}
|
|
|
|
// 用户节点访问地址
|
|
userNodeAddr, err := models.SharedUserNodeDAO.FindUserNodeAccessAddr(nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var p = alipay.TradeWapPay{}
|
|
p.NotifyURL = strings.ReplaceAll(def.NotifyURL, "${baseAddr}", userNodeAddr)
|
|
p.ReturnURL = userNodeAddr + "/finance/pay?code=" + order.Code
|
|
p.Subject = userconfigs.FindOrderTypeName(order.Type)
|
|
p.OutTradeNo = order.Code
|
|
p.TotalAmount = fmt.Sprintf("%.2f", order.Amount)
|
|
p.ProductCode = params.ProductCode
|
|
|
|
result, err := client.TradeWapPay(p)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return result.String(), nil
|
|
}
|
|
|
|
// Verify 校验订单
|
|
// "gmt_create=2022-09-28+08%3A39%3A15&charset=utf-8&seller_email=thpabq1166%40sandbox.com&subject=%E5%85%85%E5%80%BC&sign=PAu%2BDHv2EerXiE4fUTfwTXWL7g4N%2BVv2zBcr8jw%2FJd2ciNsDyayqMudSNcvDzWGPwIC6P0fFqGPuoA4jod3lbCXS0uPOWANfkG%2BOS8OAIweyeNwEz%2B6G6HjMIDvD07wNMe5NKOnNc82UXOY4sIYo%2Fgfbtgw96CdUWxvAjEWTNSld4YExUf6y%2BjHZqaU%2FijNIku4q3u2UsUxszf81q9HsgOVRXuk9BTjKcgK3Eqbf5LwSF2zFYXdmUSvbGJWzl6uIsWtZMeRfMmtkGZbNIqRMLDjb9QbMv2o4foWF9EoZ%2Bev3cjDkHrzJtcpyUEyf1QobqOhP%2FEZ0Hm0R4blscAt2qQ%3D%3D&buyer_id=2088622987776411&invoice_amount=0.01¬ify_id=2022092800222083918076410521014666&fund_bill_list=%5B%7B%22amount%22%3A%220.01%22%2C%22fundChannel%22%3A%22ALIPAYACCOUNT%22%7D%5D¬ify_type=trade_status_sync&trade_status=TRADE_SUCCESS&receipt_amount=0.01&buyer_pay_amount=0.01&app_id=2021000121667766&sign_type=RSA2&seller_id=2088621993221476&gmt_payment=2022-09-28+08%3A39%3A17¬ify_time=2022-09-28+08%3A39%3A19&version=1.0&out_trade_no=10001&total_amount=0.01&trade_no=2022092822001476410502203660&auth_app_id=2021000121667766&buyer_logon_id=phy***%40sandbox.com&point_amount=0.00"
|
|
func (this *AlipayPayment) Verify(formValues url.Values) (orderId int64, err error) {
|
|
var orderCode = formValues.Get("out_trade_no")
|
|
if len(orderCode) == 0 {
|
|
return 0, errors.New("'out_trade_no' required")
|
|
}
|
|
|
|
var tradeStatus = formValues.Get("trade_status")
|
|
if tradeStatus != "TRADE_SUCCESS" {
|
|
return 0, errors.New("failed to pay: trade status: " + tradeStatus)
|
|
}
|
|
|
|
var tx *dbs.Tx
|
|
order, err := accounts.SharedUserOrderDAO.FindUserOrderWithCode(tx, orderCode)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if order == nil {
|
|
return 0, errors.New("could not find order with code '" + orderCode + "'")
|
|
}
|
|
|
|
orderId = int64(order.Id)
|
|
|
|
method, err := accounts.SharedOrderMethodDAO.FindEnabledOrderMethod(tx, int64(order.MethodId))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if method == nil {
|
|
return 0, errors.New("can not find payment method")
|
|
}
|
|
|
|
if method.ParentCode != userconfigs.PayMethodAlipay {
|
|
return 0, errors.New("invalid method parent code '" + method.ParentCode + "', should be '" + userconfigs.PayMethodAlipay + "'")
|
|
}
|
|
|
|
var params = &userconfigs.AlipayPayMethodParams{}
|
|
err = json.Unmarshal(method.Params, params)
|
|
if err != nil {
|
|
return 0, errors.New("decode params: " + err.Error())
|
|
}
|
|
|
|
client, err := this.client(params)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
err = client.VerifySign(formValues)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取客户端
|
|
// TODO 考虑重用性
|
|
func (this *AlipayPayment) client(params *userconfigs.AlipayPayMethodParams) (*alipay.Client, error) {
|
|
client, err := alipay.New(params.AppId, params.PrivateKey, !params.IsSandbox)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = client.LoadAppCertPublicKey(params.AppPublicCert)
|
|
if err != nil {
|
|
return nil, errors.New("load app public cert failed: " + err.Error())
|
|
}
|
|
|
|
err = client.LoadAliPayRootCert(params.AlipayRootCert)
|
|
if err != nil {
|
|
return nil, errors.New("load alipay root cert failed: " + err.Error())
|
|
}
|
|
|
|
err = client.LoadAlipayCertPublicKey(params.AlipayPublicCert)
|
|
if err != nil {
|
|
return nil, errors.New("load alipay public cert failed: " + err.Error())
|
|
}
|
|
return client, nil
|
|
}
|