微信支付是一種非常普遍的線上支付方式,許多網站/應用程式都需要整合這個功能。本文將介紹如何使用 Golang 實作微信支付功能。在本文中,我們將使用 Gin 框架來建立一個簡單的 Web 應用程序,並使用 go-wechat 微信 SDK 來快速實現微信支付。
在本教學中,我們將建立一個簡單的電商網站。網站需要實現以下功能:
在開始之前,請確保您有以下要求:
appid
、mch_id
、key
等參數。 在繼續之前,請從 go-wechat 的 Github 儲存庫安裝微信 SDK。
go get github.com/silenceper/wechat/v2
從微信支付帳戶中取得下列參數並將其新增至系統環境變數:
APP_ID
: 微信APP_IDMCH_ID
: 商家號碼API_KEY
:商家API 金鑰export APP_ID=your_appid export MCH_ID=your_mchid export API_KEY=your_api_key
在檔案main.go
中,我們將使用gin 套件來初始化應用程式。
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() router.GET("/", func(c *gin.Context) { c.String(http.StatusOK, "Hello World!") }) router.Run(":8080") }
在上一頁中,我們設定了基本的 Gin 應用程式。我們現在將新增微信登入功能。
您可以選擇透過 JSON 、YAML 或 TOML 格式定義設定。這裡,我們將 建立一個 config.json
檔案來定義設定。
{ "wechat": { "appid": "your_appid", "secret": "your_app_secret" } }
下一步是初始化 WeChatClient
並使用 oauth2
請求程式碼來取得存取權杖。
import ( "encoding/json" "io/ioutil" "net/http" "os" "github.com/silenceper/wechat/v2" ) func loadConfig() map[string]string { file, err := os.Open("config.json") if err != nil { panic("Failed to load config file.") } defer file.Close() data, err := ioutil.ReadAll(file) if err != nil { panic("Failed to read config file.") } var config map[string]map[string]string err = json.Unmarshal(data, &config) if err != nil { panic("Failed to parse config file.") } return config["wechat"] } func initializeWeChat() *wechat.WeChat { config := loadConfig() client := wechat.NewWechat(&wechat.Config{ AppID: config["appid"], AppSecret: config["secret"], Token: "", EncodingAESKey: "", }) return client } func weChatLoginHandler(c *gin.Context) { client := initializeWeChat() redirectURL := "<YOUR_REDIRECT_URL>" url := client.Oauth2.GetRedirectURL(redirectURL, "snsapi_userinfo", "") c.Redirect(http.StatusTemporaryRedirect, url) }
從本質上講,我們定義了一個包含應用程式的身份驗證的 WeChatClient。我們還定義了一個 Gin 處理程序,該處理程序設定了重定向 URL 並使用 WeChatClient
中的 oauth2
請求取得存取權杖。
在重定向URL 中,使用者授權我們的應用程式在其帳戶下運行時,將呼叫/wechat/callback
處理程序。此處理程序將使用者的微信 ID、暱稱和其他公開資料儲存在使用者會話中。
func callbackHandler(c *gin.Context) { code := c.Request.URL.Query().Get("code") client := initializeWeChat() accessToken, err := client.Oauth2.GetUserAccessToken(code) if err != nil { panic("Failed to get access token from WeChat.") } userInfo, err := client.Oauth2.GetUserInfo(accessToken.AccessToken, accessToken.Openid) if err != nil { panic("Failed to get user info from WeChat.") } session := sessions.Default(c) session.Set("wechat_openid", userInfo.Openid) session.Set("wechat_nickname", userInfo.Nickname) session.Save() c.Redirect(http.StatusTemporaryRedirect, "/") }
我們應該將微信登入整合到我們的應用程式中。這個過程相對簡單。只需將處理程序新增至 Gin 路由器即可。
func main() { ... router.GET("/wechat/login", weChatLoginHandler) router.GET("/wechat/callback", callbackHandler) ... }
我們將為應用程式新增 basic 的購物車狀態。只需在用戶會話中添加購物車資訊即可。
type CartItem struct { ProductID int Quantity int } func (c *CartItem) Subtotal() float64 { // TODO: Implement. } type Cart struct { Contents []*CartItem } func (c *Cart) Add(productID, quantity int) { item := &CartItem{ ProductID: productID, Quantity: quantity, } found := false for _, existingItem := range c.Contents { if existingItem.ProductID == productID { existingItem.Quantity += quantity found = true break } } if !found { c.Contents = append(c.Contents, item) } } func (c *Cart) Remove(productID int) { for i, item := range c.Contents { if item.ProductID == productID { c.Contents = append(c.Contents[:i], c.Contents[i+1:]...) break } } } func (c *Cart) Total() float64 { total := 0.0 for _, item := range c.Contents { total += item.Subtotal() } return total } func cartFromSession(session sessions.Session) *Cart { value := session.Get("cart") if value == nil { return &Cart{} } cartBytes := []byte(value.(string)) var cart Cart json.Unmarshal(cartBytes, &cart) return &cart } func syncCartToSession(session sessions.Session, cart *Cart) { cartBytes, err := json.Marshal(cart) if err != nil { panic("Failed to sync cart with session data store.") } session.Set("cart", string(cartBytes)) session.Save() }
如上圖所示,我們實作了一個包含Add(productID, quantity int)
,Remove(productID int)
, Total() float64
幾個方法的cart struct。我們從會話中儲存和載入cart 資料(cartFromSession()
和syncCartToSession()
),並透過CartItem.Subtotal()
方法計算項目的小計。
在頁面底部展示購物車狀態:
<footer> <div class="container"> <div class="row"> <div class="col-sm-4"> <a href="/">Back to home</a> </div> <div class="col-sm-4"> <p id="cart-count"></p> </div> <div class="col-sm-4"> <p id="cart-total"></p> </div> </div> </div> </footer> <script> document.getElementById("cart-count").innerText = "{{.CartItemCount}} items in cart"; document.getElementById("cart-total").innerText = "Total: ${{.CartTotal}}"; </script>
#為了實現微信支付,我們需要定義一個訂單struct、產生訂單並將其發送給微信支付、處理支付通知。以下是一個簡單的實作。
type Order struct { OrderNumber string Amount float64 }
在此步驟中,我們將產生訂單並透過微信支付建立訂單號碼。閱讀 go-wechat 的付款文件以了解有關更多資訊。
func generateOutTradeNo() string { // TODO: Implement. } func createOrder(cart *Cart) *Order { order := &Order{ OrderNumber: generateOutTradeNo(), Amount: cart.Total(), } client := initializeWeChat() payment := &wechat.Payment{ AppID: APP_ID, MchID: MCH_ID, NotifyURL: "<YOUR_NOTIFY_URL>", TradeType: "JSAPI", Body: "购物车结算", OutTradeNo: order.OrderNumber, TotalFee: int(order.Amount * 100), SpbillCreateIP: "127.0.0.1", OpenID: "<USER_WECHAT_OPENID>", Key: API_KEY, } result, err := client.Pay.SubmitPayment(payment) if err != nil { panic("Failed to submit payment.") } // Save order state and return it. return order }
在微信通知我們已經收到用戶的付款後,在回調中,我們將儲存訂單狀態,以供以後查詢。
func setupCheckOrderStatus() { go func() { for { // Wait 10 seconds before checking (or less if you want to check more frequently). time.Sleep(10 * time.Second) client := initializeWeChat() // TODO: Retrieve orders that need to be checked. for _, order := range ordersToCheck { queryOrderResult, err := client.Pay.QueryOrder(&wechat.QueryOrderParams{ OutTradeNo: order.OrderNumber, }) if err != nil { panic("Failed to query order.") } switch queryOrderResult.TradeState { case wechat.TradeStateSuccess: // Handle order payment in your app. order.Paid = true // TODO: Update order state in database. case wechat.TradeStateClosed: // Handle order payment in your app. order.Paid = false // TODO: Update order state in database. case wechat.TradeStateRefund: // Handle order payment in your app. order.Paid = false // TODO: Update order state in database. default: break } // TODO: Remove checked order from cache. } } }() }
我們需要呼叫查詢功能以檢查微信強制更改訂單狀態的交易。微信 SDK 會傳回下列狀態之一。
在這篇文章中,我們學習如何使用Golang 和Gin 框架來建立一個電商網站,並使用go-wechat SDK 快速實現了微信登入和支付功能。我們了解如何透過 WeChatClient 處理使用者的認證和授權,並如何將微信使用者資料儲存在使用者的會話中。我們還學習如何定義一個簡單的購物車和訂單,並使用 go-wechat SDK 與微信支付整合。
以上是如何使用Golang實現網路應用程式的微信支付的詳細內容。更多資訊請關注PHP中文網其他相關文章!