• 三步实现支付宝支付【go语言 支付宝沙箱】


    支付宝沙箱支付使用背景:

    支付宝沙箱支付是支付宝提供的一个测试环境,用于开发者在不影响真实交易的情况下进行支付接口的开发和调试。在沙箱环境中,开发者可以模拟真实的支付流程,包括支付、退款、查询等操作,以便更好地调试和验证自己的支付接口是否正确。

    使用支付宝沙箱支付可以帮助开发者提高支付接口的稳定性和安全性,避免在开发过程中对真实交易造成影响。同时,沙箱环境还提供了丰富的测试工具和文档,方便开发者快速上手和进行测试。

    实现的页面效果

    第一步:建立项目,复制下方main.go代码

    代码架构展示

    main里的代码

    1. package main
    2. import (
    3. "fmt"
    4. "log"
    5. "net/http"
    6. "github.com/gin-gonic/gin"
    7. "github.com/smartwalle/alipay/v3"
    8. "github.com/smartwalle/xid"
    9. )
    10. var client *alipay.Client
    11. const (
    12. kAppId = "9021000134674475"
    13. //私钥
    14. kPrivateKey = "MIIEpAIBAAKCAQEAzSHBDVo52MqoAMvn1KFY7iuzFEUHDp/Iya3vK5s6Qp1N9hxvxwbN5Y3CjtyapDyPwBNGFYpxsoDFUOoH55vc5Z0mTxWAI3a9R1WSrL3cAAi7/2DIf0CHk9RCnzOJWGOY8luNY3iEHl2hdn0qRqBSryTKwD5znedpowphTdIDeXHBzEhkSGTAQ5+VDT9H7j3Fka6BMgmMaNvrmMh/23y6ZEYKvFncTJOBWeHcWX5wdONle1RDEC2YL9hkxZhjC3wIpMwDgDLA3J+Bx8nNhuVJW+eTV6iVaXy4HVojgoIYYyniT64VwFRIYsp9ArCKbWWJz+IIueaZe0eSiOfsH/hIuQIDAQABAoIBAG0/N8h7r+kkbPsXnV0hnPIjNdlqtcp1EINQbdsEba/ChR24oVMW7Zr+t4pMNNOZKVm7Kg0Y0Vqmt+9S5GjWGnvzCM7/fWHlwAJ4sYfsCXm/LRhiHAWhgVMarWyKDvCTAoa4eYFrUrm1VeN734MDqWV7q7tcx0hmUV0yjwXZ/l2zYkiyN5z6ElqNDI7gfKNEBmlCm42qwOEs6Xc3So2+LTSI+fpkLoI0FBqsj0AJ6nKc2gzQzTkfZ0MNY9hd//tCpz8FINxiO3z/ZcKDU90Ug3QIVxXEg/XLEYySPoetaCzaG+Qnrkz4JHBXObppObGmbff+7eConipHMPubCb81xzECgYEA9OyYmy7K+ibsdARgwEweV8KzVYCWND3O0KC/73eNOJi4thqDMV9RVJWp3CgFIVR1c1z3Gf4ZctO9jC/GvmPI72DWc/K9NyrHTGTnZhIVEQy85c9/sdm2SByTOoBWF9OwPlhlP+meOGmMxECvgL3dlFiGUoIYMu7JXNkF/eiS2F0CgYEA1mh+2qSZ6wtuW+F7Z/T4PhKgzWH4by1oOdMc4BDnA4+rw/Yp1emBlnIFr5TbTaQmS+HNl6mXsHyZiZ1/2FNVDPIaKU3nbkEVQ33LYMV/qPUixxH5ArO+btUHDPac7U4hBoxt/xdVTRqjV57x59+/eFHokQ542dekDe12u4orvA0CgYEA06uyS9NJ6p0/Fxk9gJOIWbJUCJ4DsgyEs3tpxYxdyT77y63oGgBVqrNZxIH1xRNYGiaLC7S1y65BD2mu6pYUbwUS8cwkSQw4h8Zg0a7o8/49NqN4qX0Ncw73EsUdIqR5mbgNcQn3Cqv10xpQUwRD/lPvalkyjrod3pdU/VZFqqUCgYEAlYenAMFO/xenzbiBoky8XD4Nm286Hf9i8wEC4FmpY1htiGtDXgZN9ChtQrjkAU/7zWwbQCxsuA8N3WXUZYAojrDCAhBs2P3W4Iz4q/LRR3o+2Or16SaGJzG2ixnq861LZw/FHuSc/vsW8+LL/tSS6kzlj1Syf+reZUA5UC3atnkCgYBfQjNAhDpUJQKpt+9KgdqjBa6YUtVxeFWQF9Ves9Rdk6KSE+mWounV4u3Tq/FUjDaHUOdyfiV+Q5Vrs9yQdwrWRTnMGFCTM6zfJEoU19ahtXaodoeaDpefOZhQU7Nfnv1r/xjlAP/LZsPACPIXPayKK+UWN1/ay2Jq7jp4yWna7Q=="
    15. // TODO 设置回调地址域名
    16. kServerDomain = ""
    17. )
    18. func main() {
    19. var err error
    20. //支付宝提供了用于开发时测试的 sandbox 环境,对接的时候需要注意相关的 app id 和密钥是 sandbox 环境还是 production 环境的。如果是 sandbox 环境,本参数应该传 false,否则为 true。
    21. if client, err = alipay.New(kAppId, kPrivateKey, false); err != nil {
    22. log.Println("初始化支付宝失败", err)
    23. return
    24. }
    25. // 加载证书
    26. // 加载应用公钥证书
    27. if err = client.LoadAppCertPublicKeyFromFile("appPublicCert.crt"); err != nil {
    28. log.Println("加载证书发生错误", err)
    29. return
    30. }
    31. // 加载支付宝根证书
    32. if err = client.LoadAliPayRootCertFromFile("alipayRootCert.crt"); err != nil {
    33. log.Println("加载证书发生错误", err)
    34. return
    35. }
    36. // 加载支付宝公钥证书
    37. if err = client.LoadAlipayCertPublicKeyFromFile("alipayPublicCert.crt"); err != nil {
    38. log.Println("加载证书发生错误", err)
    39. return
    40. }
    41. //接口内容加密
    42. // if err = client.SetEncryptKey("iotxR/d99T9Awom/UaSqiQ=="); err != nil {
    43. log.Println("加载内容加密密钥发生错误", err)
    44. return
    45. }
    46. //路由函数
    47. r := gin.Default()
    48. r.GET("/alipay/pay", pay)
    49. r.GET("/alipay/callback", callback)
    50. r.GET("/alipay/notify", notify)
    51. //http.HandleFunc("/alipay/pay", pay)
    52. //http.HandleFunc("/alipay/callback", callback)
    53. //http.HandleFunc("/alipay/notify", notify)
    54. //http.ListenAndServe(":"+kServerPort, nil)
    55. r.Run()
    56. }
    57. func pay(c *gin.Context) {
    58. var tradeNo = fmt.Sprintf("%d", xid.Next())
    59. var p = alipay.TradePagePay{}
    60. p.NotifyURL = kServerDomain + "/alipay/notify"
    61. p.ReturnURL = kServerDomain + "/alipay/callback"
    62. p.Subject = "支付测试:" + tradeNo
    63. p.OutTradeNo = tradeNo
    64. p.TotalAmount = "20.00"
    65. p.ProductCode = "FAST_INSTANT_TRADE_PAY"
    66. url, _ := client.TradePagePay(p)
    67. c.Redirect(http.StatusTemporaryRedirect, url.String())
    68. //http.Redirect(writer, request, url.String(), http.StatusTemporaryRedirect)
    69. }
    70. func callback(c *gin.Context) {
    71. // 解析请求参数
    72. if err := c.Request.ParseForm(); err != nil {
    73. log.Println("解析请求参数发生错误", err)
    74. c.JSON(http.StatusBadRequest, gin.H{"error": "解析请求参数发生错误"})
    75. return
    76. }
    77. // 获取通知参数
    78. outTradeNo := c.Request.Form.Get("out_trade_no")
    79. // 验证签名
    80. if err := client.VerifySign(c.Request.Form); err != nil {
    81. log.Println("回调验证签名发生错误", err)
    82. c.JSON(http.StatusBadRequest, gin.H{"error": "回调验证签名发生错误"})
    83. return
    84. }
    85. log.Println("回调验证签名通过")
    86. // 查询订单状态
    87. var p = alipay.TradeQuery{}
    88. p.OutTradeNo = outTradeNo
    89. rsp, err := client.TradeQuery(p)
    90. if err != nil {
    91. log.Printf("验证订单 %s 信息发生错误: %s", outTradeNo, err.Error())
    92. c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("验证订单 %s 信息发生错误: %s", outTradeNo, err.Error())})
    93. return
    94. }
    95. if rsp.IsFailure() {
    96. log.Printf("验证订单 %s 信息发生错误: %s-%s", outTradeNo, rsp.Msg, rsp.SubMsg)
    97. c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("验证订单 %s 信息发生错误: %s-%s", outTradeNo, rsp.Msg, rsp.SubMsg)})
    98. return
    99. }
    100. c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("订单 %s 支付成功", outTradeNo)})
    101. }
    102. func notify(c *gin.Context) {
    103. // 解析请求参数
    104. if err := c.Request.ParseForm(); err != nil {
    105. log.Println("解析请求参数发生错误", err)
    106. c.JSON(http.StatusBadRequest, gin.H{"error": "解析请求参数发生错误"})
    107. return
    108. }
    109. // 解析异步通知
    110. notification, err := client.DecodeNotification(c.Request.Form)
    111. if err != nil {
    112. log.Println("解析异步通知发生错误", err)
    113. c.JSON(http.StatusBadRequest, gin.H{"error": "解析异步通知发生错误"})
    114. return
    115. }
    116. log.Println("解析异步通知成功:", notification.NotifyId)
    117. // 查询订单状态
    118. var p = alipay.NewPayload("alipay.trade.query")
    119. p.AddBizField("out_trade_no", notification.OutTradeNo)
    120. var rsp *alipay.TradeQueryRsp
    121. if err := client.Request(p, &rsp); err != nil {
    122. log.Printf("异步通知验证订单 %s 信息发生错误: %s", notification.OutTradeNo, err.Error())
    123. c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("异步通知验证订单 %s 信息发生错误: %s", notification.OutTradeNo, err.Error())})
    124. return
    125. }
    126. if rsp.IsFailure() {
    127. log.Printf("异步通知验证订单 %s 信息发生错误: %s-%s", notification.OutTradeNo, rsp.Msg, rsp.SubMsg)
    128. c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("异步通知验证订单 %s 信息发生错误: %s-%s", notification.OutTradeNo, rsp.Msg, rsp.SubMsg)})
    129. return
    130. }
    131. log.Printf("订单 %s 支付成功", notification.OutTradeNo)
    132. client.ACKNotification(c.Writer)
    133. }

    第二步去支付宝开放平台下载自己的三个密钥证书以及APPID

    支付宝开放平台链接

    扫码登录

    进入控制台

    下滑到最底部点击沙箱

    第三步在main.go中修改配置信息

    (1)修改私钥和KAppId
    1. const (
    2. kAppId = "9021000134674475"
    3. //私钥
    4. kPrivateKey = "MIIEpAIBAAKCAQEAzSHBDVo52MqoAMvn1KFY7iuzFEUHDp/Iya3vK5s6Qp1N9hxvxwbN5Y3CjtyapDyPwBNGFYpxsoDFUOoH55vc5Z0mTxWAI3a9R1WSrL3cAAi7/2DIf0CHk9RCnzOJWGOY8luNY3iEHl2hdn0qRqBSryTKwD5znedpowphTdIDeXHBzEhkSGTAQ5+VDT9H7j3Fka6BMgmMaNvrmMh/23y6ZEYKvFncTJOBWeHcWX5wdONle1RDEC2YL9hkxZhjC3wIpMwDgDLA3J+Bx8nNhuVJW+eTV6iVaXy4HVojgoIYYyniT64VwFRIYsp9ArCKbWWJz+IIueaZe0eSiOfsH/hIuQIDAQABAoIBAG0/N8h7r+kkbPsXnV0hnPIjNdlqtcp1EINQbdsEba/ChR24oVMW7Zr+t4pMNNOZKVm7Kg0Y0Vqmt+9S5GjWGnvzCM7/fWHlwAJ4sYfsCXm/LRhiHAWhgVMarWyKDvCTAoa4eYFrUrm1VeN734MDqWV7q7tcx0hmUV0yjwXZ/l2zYkiyN5z6ElqNDI7gfKNEBmlCm42qwOEs6Xc3So2+LTSI+fpkLoI0FBqsj0AJ6nKc2gzQzTkfZ0MNY9hd//tCpz8FINxiO3z/ZcKDU90Ug3QIVxXEg/XLEYySPoetaCzaG+Qnrkz4JHBXObppObGmbff+7eConipHMPubCb81xzECgYEA9OyYmy7K+ibsdARgwEweV8KzVYCWND3O0KC/73eNOJi4thqDMV9RVJWp3CgFIVR1c1z3Gf4ZctO9jC/GvmPI72DWc/K9NyrHTGTnZhIVEQy85c9/sdm2SByTOoBWF9OwPlhlP+meOGmMxECvgL3dlFiGUoIYMu7JXNkF/eiS2F0CgYEA1mh+2qSZ6wtuW+F7Z/T4PhKgzWH4by1oOdMc4BDnA4+rw/Yp1emBlnIFr5TbTaQmS+HNl6mXsHyZiZ1/2FNVDPIaKU3nbkEVQ33LYMV/qPUixxH5ArO+btUHDPac7U4hBoxt/xdVTRqjV57x59+/eFHokQ542dekDe12u4orvA0CgYEA06uyS9NJ6p0/Fxk9gJOIWbJUCJ4DsgyEs3tpxYxdyT77y63oGgBVqrNZxIH1xRNYGiaLC7S1y65BD2mu6pYUbwUS8cwkSQw4h8Zg0a7o8/49NqN4qX0Ncw73EsUdIqR5mbgNcQn3Cqv10xpQUwRD/lPvalkyjrod3pdU/VZFqqUCgYEAlYenAMFO/xenzbiBoky8XD4Nm286Hf9i8wEC4FmpY1htiGtDXgZN9ChtQrjkAU/7zWwbQCxsuA8N3WXUZYAojrDCAhBs2P3W4Iz4q/LRR3o+2Or16SaGJzG2ixnq861LZw/FHuSc/vsW8+LL/tSS6kzlj1Syf+reZUA5UC3atnkCgYBfQjNAhDpUJQKpt+9KgdqjBa6YUtVxeFWQF9Ves9Rdk6KSE+mWounV4u3Tq/FUjDaHUOdyfiV+Q5Vrs9yQdwrWRTnMGFCTM6zfJEoU19ahtXaodoeaDpefOZhQU7Nfnv1r/xjlAP/LZsPACPIXPayKK+UWN1/ay2Jq7jp4yWna7Q=="
    5. // TODO 设置回调地址域名
    6. kServerDomain = ""
    7. )

    将私钥 和 KAppId改成自己的

    (2)将下载好的应用公钥、支付宝公钥证书、支付宝根证书复制到文件夹下
    (3)修改main.go里支付宝里证书的名称
    1. // 加载应用公钥证书
    2. if err = client.LoadAppCertPublicKeyFromFile("自己公钥证书的文件名"); err != nil {
    3. log.Println("加载证书发生错误", err)
    4. return
    5. }
    6. // 加载支付宝根证书
    7. if err = client.LoadAliPayRootCertFromFile("自己支付宝根证书的文件名"); err != nil {
    8. log.Println("加载证书发生错误", err)
    9. return
    10. }
    11. // 加载支付宝公钥证书
    12. if err = client.LoadAlipayCertPublicKeyFromFile("自己支付宝公钥证书的文件名"); err != nil {
    13. log.Println("加载证书发生错误", err)
    14. return
    15. }
    结束 

     在控制台的沙箱操作时可以查看自己的沙箱账号用于模拟收付款

  • 相关阅读:
    现代密码学-数字签名
    哈工大2024春季计算机系统大作业(水平有限,仅供参考)
    构建知识库:一文解决跨平台科研文献及笔记同步问题
    学生信息管理系统(JAVA+MYSQL)
    C++ STL进阶与补充(list容器)
    Java入门基础第9天Java eclipse如何调试代码
    数据库系统及应用复习——第二章关系数据库
    01.Swagger配置
    新加坡国立大学『3D计算机视觉』课程;Python爬虫知识库;基于SKLearn时序预测模块;从零构建AI推理引擎;前沿论文 | ShowMeAI资讯日报
    React18 新特性
  • 原文地址:https://blog.csdn.net/xiao_xiao_w/article/details/136586052