go使用支付寶沙箱實(shí)現(xiàn)支付寶支付的操作步驟
支付寶沙箱支付使用背景:
支付寶沙箱支付是支付寶提供的一個(gè)測(cè)試環(huán)境,用于開發(fā)者在不影響真實(shí)交易的情況下進(jìn)行支付接口的開發(fā)和調(diào)試。在沙箱環(huán)境中,開發(fā)者可以模擬真實(shí)的支付流程,包括支付、退款、查詢等操作,以便更好地調(diào)試和驗(yàn)證自己的支付接口是否正確。
使用支付寶沙箱支付可以幫助開發(fā)者提高支付接口的穩(wěn)定性和安全性,避免在開發(fā)過程中對(duì)真實(shí)交易造成影響。同時(shí),沙箱環(huán)境還提供了豐富的測(cè)試工具和文檔,方便開發(fā)者快速上手和進(jìn)行測(cè)試。
實(shí)現(xiàn)的頁面效果



第一步:建立項(xiàng)目,復(fù)制下方main.go代碼
代碼架構(gòu)展示

main里的代碼
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/smartwalle/alipay/v3"
"github.com/smartwalle/xid"
)
var client *alipay.Client
const (
kAppId = "9021000134674475"
//私鑰
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=="
// TODO 設(shè)置回調(diào)地址域名
kServerDomain = ""
)
func main() {
var err error
//支付寶提供了用于開發(fā)時(shí)測(cè)試的 sandbox 環(huán)境,對(duì)接的時(shí)候需要注意相關(guān)的 app id 和密鑰是 sandbox 環(huán)境還是 production 環(huán)境的。如果是 sandbox 環(huán)境,本參數(shù)應(yīng)該傳 false,否則為 true。
if client, err = alipay.New(kAppId, kPrivateKey, false); err != nil {
log.Println("初始化支付寶失敗", err)
return
}
// 加載證書
// 加載應(yīng)用公鑰證書
if err = client.LoadAppCertPublicKeyFromFile("appPublicCert.crt"); err != nil {
log.Println("加載證書發(fā)生錯(cuò)誤", err)
return
}
// 加載支付寶根證書
if err = client.LoadAliPayRootCertFromFile("alipayRootCert.crt"); err != nil {
log.Println("加載證書發(fā)生錯(cuò)誤", err)
return
}
// 加載支付寶公鑰證書
if err = client.LoadAlipayCertPublicKeyFromFile("alipayPublicCert.crt"); err != nil {
log.Println("加載證書發(fā)生錯(cuò)誤", err)
return
}
//接口內(nèi)容加密
// if err = client.SetEncryptKey("iotxR/d99T9Awom/UaSqiQ=="); err != nil {
log.Println("加載內(nèi)容加密密鑰發(fā)生錯(cuò)誤", err)
return
}
//路由函數(shù)
r := gin.Default()
r.GET("/alipay/pay", pay)
r.GET("/alipay/callback", callback)
r.GET("/alipay/notify", notify)
//http.HandleFunc("/alipay/pay", pay)
//http.HandleFunc("/alipay/callback", callback)
//http.HandleFunc("/alipay/notify", notify)
//http.ListenAndServe(":"+kServerPort, nil)
r.Run()
}
func pay(c *gin.Context) {
var tradeNo = fmt.Sprintf("%d", xid.Next())
var p = alipay.TradePagePay{}
p.NotifyURL = kServerDomain + "/alipay/notify"
p.ReturnURL = kServerDomain + "/alipay/callback"
p.Subject = "支付測(cè)試:" + tradeNo
p.OutTradeNo = tradeNo
p.TotalAmount = "20.00"
p.ProductCode = "FAST_INSTANT_TRADE_PAY"
url, _ := client.TradePagePay(p)
c.Redirect(http.StatusTemporaryRedirect, url.String())
//http.Redirect(writer, request, url.String(), http.StatusTemporaryRedirect)
}
func callback(c *gin.Context) {
// 解析請(qǐng)求參數(shù)
if err := c.Request.ParseForm(); err != nil {
log.Println("解析請(qǐng)求參數(shù)發(fā)生錯(cuò)誤", err)
c.JSON(http.StatusBadRequest, gin.H{"error": "解析請(qǐng)求參數(shù)發(fā)生錯(cuò)誤"})
return
}
// 獲取通知參數(shù)
outTradeNo := c.Request.Form.Get("out_trade_no")
// 驗(yàn)證簽名
if err := client.VerifySign(c.Request.Form); err != nil {
log.Println("回調(diào)驗(yàn)證簽名發(fā)生錯(cuò)誤", err)
c.JSON(http.StatusBadRequest, gin.H{"error": "回調(diào)驗(yàn)證簽名發(fā)生錯(cuò)誤"})
return
}
log.Println("回調(diào)驗(yàn)證簽名通過")
// 查詢訂單狀態(tài)
var p = alipay.TradeQuery{}
p.OutTradeNo = outTradeNo
rsp, err := client.TradeQuery(p)
if err != nil {
log.Printf("驗(yàn)證訂單 %s 信息發(fā)生錯(cuò)誤: %s", outTradeNo, err.Error())
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("驗(yàn)證訂單 %s 信息發(fā)生錯(cuò)誤: %s", outTradeNo, err.Error())})
return
}
if rsp.IsFailure() {
log.Printf("驗(yàn)證訂單 %s 信息發(fā)生錯(cuò)誤: %s-%s", outTradeNo, rsp.Msg, rsp.SubMsg)
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("驗(yàn)證訂單 %s 信息發(fā)生錯(cuò)誤: %s-%s", outTradeNo, rsp.Msg, rsp.SubMsg)})
return
}
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("訂單 %s 支付成功", outTradeNo)})
}
func notify(c *gin.Context) {
// 解析請(qǐng)求參數(shù)
if err := c.Request.ParseForm(); err != nil {
log.Println("解析請(qǐng)求參數(shù)發(fā)生錯(cuò)誤", err)
c.JSON(http.StatusBadRequest, gin.H{"error": "解析請(qǐng)求參數(shù)發(fā)生錯(cuò)誤"})
return
}
// 解析異步通知
notification, err := client.DecodeNotification(c.Request.Form)
if err != nil {
log.Println("解析異步通知發(fā)生錯(cuò)誤", err)
c.JSON(http.StatusBadRequest, gin.H{"error": "解析異步通知發(fā)生錯(cuò)誤"})
return
}
log.Println("解析異步通知成功:", notification.NotifyId)
// 查詢訂單狀態(tài)
var p = alipay.NewPayload("alipay.trade.query")
p.AddBizField("out_trade_no", notification.OutTradeNo)
var rsp *alipay.TradeQueryRsp
if err := client.Request(p, &rsp); err != nil {
log.Printf("異步通知驗(yàn)證訂單 %s 信息發(fā)生錯(cuò)誤: %s", notification.OutTradeNo, err.Error())
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("異步通知驗(yàn)證訂單 %s 信息發(fā)生錯(cuò)誤: %s", notification.OutTradeNo, err.Error())})
return
}
if rsp.IsFailure() {
log.Printf("異步通知驗(yàn)證訂單 %s 信息發(fā)生錯(cuò)誤: %s-%s", notification.OutTradeNo, rsp.Msg, rsp.SubMsg)
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("異步通知驗(yàn)證訂單 %s 信息發(fā)生錯(cuò)誤: %s-%s", notification.OutTradeNo, rsp.Msg, rsp.SubMsg)})
return
}
log.Printf("訂單 %s 支付成功", notification.OutTradeNo)
client.ACKNotification(c.Writer)
}第二步:去支付寶開放平臺(tái)下載自己的三個(gè)密鑰證書以及APPID
掃碼登錄

進(jìn)入控制臺(tái)

下滑到最底部點(diǎn)擊沙箱




第三步:在main.go中修改配置信息
(1)修改私鑰和KAppId
const ( kAppId = "9021000134674475" //私鑰 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==" // TODO 設(shè)置回調(diào)地址域名 kServerDomain = "" )
將私鑰 和 KAppId改成自己的

(2)將下載好的應(yīng)用公鑰、支付寶公鑰證書、支付寶根證書復(fù)制到文件夾下

(3)修改main.go里支付寶里證書的名稱
// 加載應(yīng)用公鑰證書
if err = client.LoadAppCertPublicKeyFromFile("自己公鑰證書的文件名"); err != nil {
log.Println("加載證書發(fā)生錯(cuò)誤", err)
return
}
// 加載支付寶根證書
if err = client.LoadAliPayRootCertFromFile("自己支付寶根證書的文件名"); err != nil {
log.Println("加載證書發(fā)生錯(cuò)誤", err)
return
}
// 加載支付寶公鑰證書
if err = client.LoadAlipayCertPublicKeyFromFile("自己支付寶公鑰證書的文件名"); err != nil {
log.Println("加載證書發(fā)生錯(cuò)誤", err)
return
}結(jié)束
在控制臺(tái)的沙箱操作時(shí)可以查看自己的沙箱賬號(hào)用于模擬收付款

以上就是go使用支付寶沙箱實(shí)現(xiàn)支付寶支付的操作步驟的詳細(xì)內(nèi)容,更多關(guān)于go支付寶沙箱支付的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang實(shí)現(xiàn)并發(fā)安全帶過期清理的緩存結(jié)構(gòu)
本文主要介紹了Golang實(shí)現(xiàn)并發(fā)安全帶過期清理的緩存結(jié)構(gòu),采用RWMutex保障并發(fā),定時(shí)清理與惰性刪除處理過期,分片優(yōu)化性能,應(yīng)對(duì)緩存雪崩和穿透,感興趣的可以了解一下2025-06-06
Go中并發(fā)控制的實(shí)現(xiàn)方式總結(jié)
在Go實(shí)際開發(fā)中,并發(fā)安全是老生常談的事情,在并發(fā)下,goroutine之間的存在數(shù)據(jù)資源等方面的競(jìng)爭(zhēng),為了保證數(shù)據(jù)一致性、防止死鎖等問題的出現(xiàn),在并發(fā)中需要使用一些方式來實(shí)現(xiàn)并發(fā)控制,本文給大家總結(jié)了幾種實(shí)現(xiàn)方式,需要的朋友可以參考下2023-12-12
Go語言類型轉(zhuǎn)換工具庫cast的實(shí)現(xiàn)
本文介紹了Go語言中的類型轉(zhuǎn)換工具庫cast,cast庫提供了一種簡(jiǎn)單安全的方式來在各種類型間轉(zhuǎn)換,如ToIntSliceE、ToStringSliceE等,同時(shí)支持時(shí)間類型和時(shí)長(zhǎng)類型的轉(zhuǎn)換,并能處理轉(zhuǎn)換失敗的情況,感興趣的可以了解一下2025-11-11
golang將切片或數(shù)組根據(jù)某個(gè)字段進(jìn)行分組操作
這篇文章主要介紹了golang將切片或數(shù)組根據(jù)某個(gè)字段進(jìn)行分組操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12

