易支付对接new-api做适配器的思路

1 new-api点击支付时的逻辑流程

new-api 支付时调用接口/api/user/pay获取支付参数

2 /api/user/pay对应的路由通过api-router.go里获取到的信息是:selfRoute.POST(“/pay”, middleware.CriticalRateLimit(), controller.RequestEpay),所以对应的是topup.go里面的RequestEpay方法

3 请求参数
amount: parseInt(topUpCount),
payment_method: payWay,

4 响应值:

{
    "data": {
        "device": "pc",
        "money": "7.30",
        "name": "TUC1",
        "notify_url": "https://newapi.xxxx.cn/api/user/epay/notify",
        "out_trade_no": "USR1NO1LrJXr1776826739",
        "pid": "M190298627950",
        "return_url": "https://newapi.xxxx.cn/console/log",
        "sign": "b33f108eb641977842b1f112da0ab57d",
        "sign_type": "MD5",
        "type": "wxpay"
    },
    "message": "success",
    "url": "http://epay.xxxx.cn/fastpay-server/api/pay/S561169349150/submit.php"
}

5 new-apy加签名部分的代码如下:

uri, params, err := client.Purchase(&epay.PurchaseArgs{
		Type:           req.PaymentMethod,
		ServiceTradeNo: tradeNo,
		Name:           fmt.Sprintf("TUC%d", req.Amount),
		Money:          strconv.FormatFloat(payMoney, 'f', 2, 64),
		Device:         epay.PC,
		NotifyUrl:      notifyUrl,
		ReturnUrl:      returnUrl,
	})

其中epay对应的是:”github.com/Calcium-Ion/go-epay/epay” 对应的项目是:https://github.com/Calcium-Ion/go-epay

5.1 详细代码如下两块

代码块1 order.go

type PurchaseArgs struct {
	// 支付类型
	Type string
	// 商家订单号
	ServiceTradeNo string
	// 商品名称
	Name string
	// 金额
	Money string
	// 设备类型
	Device    DeviceType
	NotifyUrl *url.URL
	ReturnUrl *url.URL
}

const (
	PurchaseUrl = "/submit.php"
)

// Purchase 生成支付链接和参数
func (c *Client) Purchase(args *PurchaseArgs) (string, map[string]string, error) {
	// see https://payment.moe/doc.html
	requestParams := map[string]string{
		"pid":          c.Config.PartnerID,
		"type":         args.Type,
		"out_trade_no": args.ServiceTradeNo,
		"notify_url":   args.NotifyUrl.String(),
		"name":         args.Name,
		"money":        args.Money,
		"device":       string(args.Device),
		"sign_type":    "MD5",
		"return_url":   args.ReturnUrl.String(),
		"sign":         "",
	}

	u, err := url.Parse(c.BaseUrl.String())
	if err != nil {
		return "", nil, err
	}
	u.Path = path.Join(u.Path, PurchaseUrl)

	return u.String(), GenerateParams(requestParams, c.Config.Key), nil
}

代码块2. util.go

package epay

import (
	"crypto/md5"
	"fmt"
	"sort"
	"strings"

	"github.com/samber/lo"
)

// ParamsFilter 过滤参数,生成签名时需删除 “sign” 和 “sign_type” 参数
func ParamsFilter(params map[string]string) map[string]string {
	return lo.PickBy[string, string](params, func(key string, value string) bool {
		return !(key == "sign" || key == "sign_type" || value == "")
	})
}

// ParamsSort 对参数进行排序,返回排序后的 keys 和 values (go 中 map 为乱序)
func ParamsSort(params map[string]string) ([]string, []string) {
	keys := lo.Keys(params)
	sort.Strings(keys)

	values := lo.Map(keys, func(key string, i int) string {
		return params[key]
	})

	return keys, values
}

// CreateUrlString 生成待签名字符串, ["a", "b", "c"], ["d", "e", "f"] => "a=d&b=e&c=f"
func CreateUrlString(keys []string, values []string) string {
	urlString := ""
	for i, key := range keys {
		urlString += key + "=" + values[i] + "&"
	}
	// trim 掉最后的 &
	return strings.TrimSuffix(urlString, "&")
}

// MD5String 生成 加盐(商户 key) MD5 字符串
func MD5String(urlString string, key string) string {
	digest := md5.Sum([]byte(urlString + key))
	return fmt.Sprintf("%x", digest)
}

// GenerateParams 生成加签参数
func GenerateParams(params map[string]string, key string) map[string]string {
	filtered := ParamsFilter(params)
	keys, values := ParamsSort(filtered)
	sign := MD5String(CreateUrlString(keys, values), key)
	params["sign"] = sign
	params["sign_type"] = "MD5"
	return params
}

祝贺

剩下是适应接口 xxx/submit.php按照自己的需求去下适配器.

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注