- go语言推荐使用第三方支付库 github.com/go-pay/gopay
- 说明
- 支付宝和应用都有公私钥,即2套,为什么是2套?
- 用户通过应用私钥加密发送消息给支付宝,支付宝通过应用公钥解密;
- 支付宝通过支付宝私钥加密发送消息给用户,用户通过支付宝公钥解密。
- 加签和验签
- sign生成规则:
- 发送给支付宝的所有参数、剔除sign、sign_type
- 按照参数字母顺序排序,且格式为key=value,参数之间使用&连接
- 使用对应的sign_type转换,如MD5
- 用户发送给支付宝的消息需要加签,即按照规则生成sign然后以参数sign传递过去,因为支付宝需要校验请求的正确性
- 支付宝回调的通知请求需要验签,因为用户也需要验证支付宝请求的正确性
- sign生成规则:
- 支付宝和应用都有公私钥,即2套,为什么是2套?
- 工具
- 沙箱工具及使用 https://opendocs.alipay.com/common/02kkv7
- 支付应用文档可参考请求和响应参数 https://opendocs.alipay.com/open/02e7gq?scene=20
- 支付宝开放平台
- 异步通知URL,需要能被外网访问的网络,可以使用免费内网穿透工具生成域名ngrok 官网甚至有使用介绍,方便快捷
- 代码(手机网页支付,手机上提前下载好沙箱版支付宝)
-
package main import ( "context" "errors" "fmt" "github.com/go-pay/gopay" "github.com/go-pay/gopay/alipay" "github.com/go-pay/gopay/pkg/xlog" "github.com/kataras/iris/v12" "net/url" ) //应用私钥 var privateKey = `` func main() { // 1初始化支付宝客户端 client, err := alipay.NewClient("appid", privateKey, false) if err != nil { xlog.Error(err) return } // 打开Debug开关,输出日志,默认关闭 //client.DebugSwitch = gopay.DebugOn // 设置支付宝请求 公共参数 client.SetLocation(alipay.LocationShanghai). // 设置时区,不设置或出错均为默认服务器时间 SetCharset(alipay.UTF8). // 设置字符编码,不设置默认 utf-8 SetSignType(alipay.RSA2). // 设置签名类型,不设置默认 RSA2 SetReturnUrl("https://127.0.0.1:80/return"). //跳转页面 SetNotifyUrl("https://本地地址80端口映射的域名/notify") // 异步通知URL 可被外网访问 post请求//.SetAppAuthToken() // 设置第三方应用授权 // 自动同步验签(只支持证书模式) // 传入 alipayCertPublicKey_RSA2.crt 内容 // client.AutoVerifySign([]byte(`-----BEGIN CERTIFICATE----- //-----END CERTIFICATE----- //`)) // 公钥证书模式,需要传入证书,证书路径 err = client.SetCertSnByPath("appCertPublicKey.crt", "alipayRootCert.crt", "alipayCertPublicKey_RSA2.crt") if err != nil { xlog.Error(err) return } // 2web服务器 app := iris.New() app.Get("/pay", func(ctx iris.Context) { //支付 Pay(context.Background(), client) }) app.Get("/return", func(ctx iris.Context) { //返回页 ReturnUrl(ctx) }) app.Post("/notify", func(ctx iris.Context) { //通知页 err = NotifyUrl(ctx) if err != nil { fmt.Println("通知页", err) } }) err = app.Run(iris.Addr(":80")) if err != nil { fmt.Println(err) return } } // Pay 手机网站支付 func Pay(ctx context.Context, client *alipay.Client) { //请求参数 bm := make(gopay.BodyMap) bm.Set("subject", "手机网站支付") bm.Set("out_trade_no", "LP20220628") //一个订单号只能支付一次 bm.Set("total_amount", "0.01") //1分钱 fmt.Println("body:", bm) //发送请求 payUrl, err := client.TradeWapPay(ctx, bm) //内部已经处理了签名 if err != nil { xlog.Error(err) return } //支付界面链接,直接粘贴到手机浏览器里即可支付 fmt.Println(payUrl) } // ReturnUrl 返回页 同步get,可在本机上测试 func ReturnUrl(ctx iris.Context) { ctx.WriteString("ReturnUrl success") } // NotifyUrl 通知页 异步post,必须外网可访问,必须返回success否则会一直通知 func NotifyUrl(ctx iris.Context) error { body, err := ctx.GetBody() if err != nil { fmt.Errorf("%v", err) return err } fmt.Println("body", string(body)) values, err := url.ParseQuery(string(body)) if err != nil { fmt.Errorf("%v", err) return err } datas, err := alipay.ParseNotifyByURLValues(values) //证书异步验签 if err != nil { fmt.Errorf("%v", err) return err } //验签 ok, err := alipay.VerifySignWithCert("alipayCertPublicKey_RSA2.crt", datas) if ok == false || err != nil { fmt.Errorf("%v", err) return errors.New("校验失败") } fmt.Println(datas) tradeStatus := datas.Get("trade_status") fmt.Printf(tradeStatus) //todo 处理业务逻辑 //交易状态 if tradeStatus == "TRADE_SUCCESS" { fmt.Println("交易成功") } else { fmt.Errorf("交易异常") } //返回success ctx.WriteString("success") return nil }
-
证书模式支付宝支付接口demo 沙箱
猜你喜欢
转载自blog.csdn.net/qq_37575994/article/details/125513319
今日推荐
周排行