最近项目有支付需求,需要集成app内支付,而支付宝官方没有提供go的sdk,所以去github上找了一下第三方实现的sdk,这里记录一下流程。

下载sdk

启用 Go module 安装
go get github.com/smartwalle/alipay/v3
import github.com/smartwalle/alipay/v3
未启用 Go module 安装
go get github.com/smartwalle/alipay
import github.com/smartwalle/alipay

沙箱环境配置

  1. 登录自己账号进去之后点击沙箱应用,这里需要配置RSA2密钥,需要配置回调也可以在下面配置,其它地方不用管。

    image-20200816143035914.png
  2. image-20200816143247929.png
  3. 打开支付宝开放平台开发助手,生成RSA2密钥

    image-20200816143434957.png
  4. 复制公钥到支付宝沙箱环境中,会同时生成一个支付宝公钥后面会用到

    image-20200816143540678.png
  5. 配置回调地址

    image-20200816143631398.png

app内支付实现

这里主要讲解一下app内拉起支付宝控件支付,用户手机必须安装了支付宝。

系统实现的流程
var privateKey = "xxx"           // 这个地方填写之前生成的RSA2 私钥
var appId = "202100XXXXXX"       // 在沙箱环境第一个参数就是
// 创建支付宝客户端,沙箱环境下第三个参数填false,生产环境要换成true
var client, err = alipay.New(appId, privateKey, false)

// 如果涉及到资金的支出,必须用公钥证书模式,如果只涉及支付推荐使用普通公钥模式,也就是刚刚生成的RSA2密钥
/*  公钥证书模式
client.LoadAppPublicCertFromFile("appCertPublicKey_2017011104995404.crt") // 加载应用公钥证书
client.LoadAliPayRootCertFromFile("alipayRootCert.crt") // 加载支付宝根证书
client.LoadAliPayPublicCertFromFile("alipayCertPublicKey_RSA2.crt") // 加载支付宝公钥证书
*/
//普通公钥模式,加载支付宝公钥,在沙箱环境上传RSA2公钥后生成的支付宝公钥
client.LoadAliPayPublicKey("xxxxxx")

var p = alipay.TradeAppPay{}
p.NotifyURL = "http://xxx" //回调地址
p.Subject = "标题"
p.OutTradeNo = "传递一个唯一单号"    //自己生成一个唯一的交易单号
p.TotalAmount = "10.00"          //交易金额
values := url.Values{} //回调参数,这里只能这样写,要进行urlEncode才能传给支付宝
//需要回传的参数
values.Add("aaa", aaa)
values.Add("bbb", bbb)
p.PassbackParams = values.Encode()   //支付宝会把passback_params={aaa=aaa&bbb=bbb}发送到回调函数

//这里返回的url中会包含sign,直接返回给前端就ok
var url, err = client.TradeAppPay(p)
if err != nil {
 fmt.Println(err)
}

//支付宝回调,我这里使用的是echo框架
func AliPayNotify(c echo.Context) error {
    //支付宝会把交易状态放在trade_status参数中,具体有哪些交易状态码请查看 https://opendocs.alipay.com/apis
    tradeStatus := c.FormValue("trade_status")
    //交易关闭
    if tradeStatus == "TRADE_CLOSED" {
        log.Info("交易关闭...")
        return c.JSON(http.StatusOK, "success")
    }
    //交易成功
    if tradeStatus == "TRADE_SUCCESS" {
        param := c.FormValue("passback_params")     //param=“aaa=aaa&bbb=bbb”
        maps := str.UrlParamToMap(param)
        aaa := maps["aaa"]
        bbb := maps["bbb"]
        //交易信息,支付宝公共参数
        tradeNo := c.FormValue("trade_no")
        Amount := c.FormValue("total_amount")
        //自己的业务逻辑
        // TODO
        return c.JSON(http.StatusOK, "success")
    }
    return c.JSON(http.StatusOK, "fail")
}

//贴一下我自己手写的解析url参数
//url参数转换为map
func UrlParamToMap(param string) map[string]string {
    split := strings.Split(param, "&")
    maps := make(map[string]string)
    for _, v := range split {
        i := strings.Split(v, "=")
        maps[i[0]] = i[1]
    }
    return maps
}

app内支付和app网页支付其实差不多,可以做成用户安装了支付宝就拉起控件使用app内支付,没有安装就跳转网页支付。