最近项目有支付需求,需要集成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
沙箱环境配置
-
登录自己账号进去之后点击沙箱应用,这里需要配置RSA2密钥,需要配置回调也可以在下面配置,其它地方不用管。
image-20200816143035914.png -
image-20200816143247929.png
-
打开支付宝开放平台开发助手,生成RSA2密钥
image-20200816143434957.png -
复制公钥到支付宝沙箱环境中,会同时生成一个支付宝公钥后面会用到
image-20200816143540678.png -
配置回调地址
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内支付,没有安装就跳转网页支付。