Rumah >pembangunan bahagian belakang >Golang >Cara menggunakan Golang untuk melaksanakan pembayaran WeChat untuk aplikasi web

Cara menggunakan Golang untuk melaksanakan pembayaran WeChat untuk aplikasi web

PHPz
PHPzasal
2023-06-24 09:12:052698semak imbas

WeChat Pay ialah kaedah pembayaran dalam talian yang sangat biasa, dan banyak tapak web/aplikasi perlu menyepadukan fungsi ini. Artikel ini akan memperkenalkan cara menggunakan Golang untuk melaksanakan fungsi pembayaran WeChat. Dalam artikel ini, kami akan menggunakan rangka kerja Gin untuk membina aplikasi web mudah dan menggunakan SDK WeChat go-wechat untuk melaksanakan pembayaran WeChat dengan cepat.

Keperluan

Dalam tutorial ini, kami akan membina laman web e-dagang yang ringkas. Laman web perlu melaksanakan fungsi berikut:

  1. Pengguna log masuk ke tapak web melalui WeChat.
  2. Pengguna menyemak imbas item dan menambahkan item pada troli beli-belah mereka.
  3. Pengguna boleh menggunakan WeChat Pay untuk membeli barangan.

Persediaan

Sebelum anda mula, sila pastikan anda mempunyai keperluan berikut:

  • Telah mendaftar akaun pembayaran WeChat, mempunyai appid, mch_id, key dan parameter lain.
  • Rangka kerja Golang dan Gin dipasang.

Pasang SDK go-wechat

Sebelum meneruskan, sila pasang SDK WeChat daripada repositori Github go-wechat.

go get github.com/silenceper/wechat/v2

Konfigurasikan pembolehubah persekitaran

Dapatkan parameter berikut daripada akaun pembayaran WeChat dan tambahkannya pada pembolehubah persekitaran sistem:

  • APP_ID : WeChat APP_ID
  • MCH_ID: ID Pedagang
  • API_KEY: Kunci API Pedagang
export APP_ID=your_appid
export MCH_ID=your_mchid
export API_KEY=your_api_key

Aplikasi Bina

Inisialisasikan Gin

Dalam fail main.go kami akan menggunakan pakej gin untuk memulakan aplikasi.

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")
}

Tambah log masuk WeChat ke apl

Pada halaman sebelumnya, kami menyediakan apl asas Gin. Kami kini akan menambah fungsi log masuk WeChat.

  1. Tambah fail konfigurasi

Anda boleh memilih untuk menentukan konfigurasi melalui format JSON, YAML atau TOML. Di sini, kami akan mencipta fail config.json untuk menentukan konfigurasi.

{
    "wechat": {
        "appid": "your_appid",
        "secret": "your_app_secret"
    }
}
  1. Initialize WeChat

Langkah seterusnya ialah untuk memulakan WeChatClient dan gunakan kod permintaan oauth2 untuk mendapatkan token akses.

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)
}

Pada asasnya, kami mentakrifkan WeChatClient yang mengandungi pengesahan untuk aplikasi. Kami juga mentakrifkan pengendali Gin yang menetapkan URL ubah hala dan mendapatkan token akses menggunakan WeChatClient dalam permintaan. oauth2

    Mengendalikan kebenaran WeChat
Dalam URL ubah hala, pengendali

dipanggil apabila pengguna membenarkan apl kami untuk dijalankan di bawah akaun mereka. Pengendali ini menyimpan ID WeChat pengguna, nama panggilan dan data awam lain dalam sesi pengguna. /wechat/callback

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, "/")
}

    Sepadukan log masuk WeChat
Kami harus menyepadukan log masuk WeChat ke dalam aplikasi kami. Prosesnya agak mudah. Hanya tambahkan pengendali pada penghala Gin.

func main() {
    ...
    router.GET("/wechat/login", weChatLoginHandler)
    router.GET("/wechat/callback", callbackHandler)
    ...
}

Melaksanakan troli beli-belah

Kami akan menambah keadaan troli beli-belah asas pada aplikasi. Hanya tambah maklumat troli beli-belah dalam sesi pengguna.

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()
}

Seperti yang ditunjukkan di atas, kami melaksanakan struct troli yang mengandungi beberapa kaedah:

, Add(productID, quantity int), Remove(productID int). Kami menyimpan dan memuatkan data troli (Total() float64 dan cartFromSession()) daripada sesi dan mengira jumlah kecil item melalui kaedah syncCartToSession(). CartItem.Subtotal()

Paparkan status troli beli-belah di bahagian bawah halaman:

<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>

WeChat Payment

Untuk melaksanakan pembayaran WeChat, kita perlu mentakrifkan struktur pesanan, menjana pesan dan hantar ke pembayaran WeChat , memproses pemberitahuan pembayaran. Di bawah adalah pelaksanaan mudah.

    Tentukan struktur pesanan
  1. type Order struct {
        OrderNumber string
        Amount      float64
    }
    Jana pesanan dan hantar pesanan ke WeChat
Dalam langkah ini, kami akan menjana pesanan Dan buat nombor pesanan melalui pembayaran WeChat. Baca dokumentasi pembayaran go-wechat untuk mengetahui lebih lanjut.

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
}

    Memproses pemberitahuan pembayaran WeChat
Selepas WeChat memberitahu kami bahawa kami telah menerima bayaran pengguna, dalam panggilan balik, kami akan menyimpan status pesanan untuk pertanyaan kemudian.

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.
            }
        }
    }()
}

Kami perlu memanggil fungsi pertanyaan untuk menyemak transaksi di mana WeChat memaksa menukar status pesanan. SDK WeChat akan mengembalikan salah satu daripada status berikut.

    TradeStateSuccess: Pembayaran pengguna telah berjaya.
  • TradeStateClosed: Pesanan telah ditutup.
  • TradeStateRefund: Urus niaga telah dibayar balik.
Ringkasan

Dalam artikel ini, kami mempelajari cara menggunakan rangka kerja Golang dan Gin untuk membina tapak web e-dagang, dan menggunakan SDK go-wechat untuk melaksanakan log masuk dan Pembayaran WeChat dengan pantas fungsi. Kami mempelajari cara mengendalikan pengesahan dan kebenaran pengguna melalui WeChatClient dan cara menyimpan data pengguna WeChat dalam sesi pengguna. Kami juga mempelajari cara untuk menentukan troli beli-belah yang ringkas dan memesan serta menyepadukan dengan WeChat Pay menggunakan SDK go-wechat.

Atas ialah kandungan terperinci Cara menggunakan Golang untuk melaksanakan pembayaran WeChat untuk aplikasi web. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn