go语言写一个微信支付的简单示例代码

微信支付的流程涉及多个步骤,包括创建订单、调用支付接口、处理支付结果通知等。以下是一个简单的Go语言示例代码,展示了如何通过微信支付进行支付请求和结果回调处理。请注意,这只是一个简化的示例,实际应用中需要做更多的异常处理、签名验证等。

1. 引入必要的库

首先,你需要安装一个用于HTTP请求和XML解析的Go包。Go的标准库已经包含了这些功能,可以直接使用。

1
go get github.com/google/uuid

2. 创建支付订单请求

以下是一个简化的微信支付请求示例,创建一个订单并生成支付请求的参数。需要提供商户号、API密钥等信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package main

import (
"bytes"
"crypto/sha1"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"sort"
"strings"
"time"
"crypto/hmac"
"crypto/sha256"
"github.com/google/uuid"
)

// 微信支付的相关配置
const (
AppID = "wx1234567890abcdef" // 你的AppID
MchID = "1234567890" // 你的商户号
Key = "your_api_key" // 你的API密钥
NotifyURL = "https://yourdomain.com/notify" // 支付结果回调地址
TradeType = "APP" // 支付类型,APP支付
UnifiedOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder" // 微信统一下单接口
)

type UnifiedOrderRequest struct {
AppID string `xml:"appid"`
MchID string `xml:"mch_id"`
NonceStr string `xml:"nonce_str"`
Sign string `xml:"sign"`
Body string `xml:"body"`
OutTradeNo string `xml:"out_trade_no"`
TotalFee int `xml:"total_fee"`
SpbillCreateIP string `xml:"spbill_create_ip"`
NotifyURL string `xml:"notify_url"`
TradeType string `xml:"trade_type"`
}

type UnifiedOrderResponse struct {
ReturnCode string `xml:"return_code"`
ReturnMsg string `xml:"return_msg"`
PrepayID string `xml:"prepay_id"`
}

func main() {
// 创建订单
order := UnifiedOrderRequest{
AppID: AppID,
MchID: MchID,
NonceStr: generateNonceStr(),
Body: "测试订单",
OutTradeNo: generateOrderID(),
TotalFee: 1, // 金额,单位为分
SpbillCreateIP: "123.12.12.123", // 用户的IP地址
NotifyURL: NotifyURL,
TradeType: TradeType,
}

// 签名
order.Sign = generateSign(order)

// 请求微信统一下单接口
requestXML, err := xml.Marshal(order)
if err != nil {
fmt.Println("XML Marshal failed:", err)
return
}

resp, err := http.Post(UnifiedOrderURL, "application/xml", bytes.NewBuffer(requestXML))
if err != nil {
fmt.Println("Request failed:", err)
return
}
defer resp.Body.Close()

// 解析微信返回的XML
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Read response failed:", err)
return
}

var unifiedResp UnifiedOrderResponse
err = xml.Unmarshal(body, &unifiedResp)
if err != nil {
fmt.Println("XML Unmarshal failed:", err)
return
}

if unifiedResp.ReturnCode == "SUCCESS" {
fmt.Println("预支付ID:", unifiedResp.PrepayID)
} else {
fmt.Println("下单失败:", unifiedResp.ReturnMsg)
}
}

// 生成随机字符串
func generateNonceStr() string {
return uuid.New().String()
}

// 生成订单号(商户系统生成)
func generateOrderID() string {
return time.Now().Format("20060102150405") + "000001" // 示例:202501151505000001
}

// 生成签名
func generateSign(order UnifiedOrderRequest) string {
params := make(map[string]string)
params["appid"] = order.AppID
params["mch_id"] = order.MchID
params["nonce_str"] = order.NonceStr
params["body"] = order.Body
params["out_trade_no"] = order.OutTradeNo
params["total_fee"] = fmt.Sprintf("%d", order.TotalFee)
params["spbill_create_ip"] = order.SpbillCreateIP
params["notify_url"] = order.NotifyURL
params["trade_type"] = order.TradeType

// 按字典顺序排序
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)

// 拼接参数
var queryString string
for _, key := range keys {
queryString += fmt.Sprintf("%s=%s&", key, params[key])
}
queryString += "key=" + Key

// 计算签名
return calculateMD5(queryString)
}

// 计算MD5签名
func calculateMD5(str string) string {
hash := sha256.New()
hash.Write([]byte(str))
return fmt.Sprintf("%x", hash.Sum(nil))
}

3. 生成签名

微信支付接口需要使用特定的签名算法进行请求签名。上面的代码通过拼接请求参数并使用HMAC-MD5生成签名。为了保证签名安全性,需要确保所有参数按字典顺序排列,并在最后加上API密钥。

4. 回调通知处理

当支付完成后,微信服务器会调用你设置的NotifyURL进行支付结果通知。在这个回调中,你需要验证签名并处理支付结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main

import (
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
)

type NotifyRequest struct {
ReturnCode string `xml:"return_code"`
PrepayID string `xml:"prepay_id"`
OutTradeNo string `xml:"out_trade_no"`
TotalFee int `xml:"total_fee"`
}

func handleNotify(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Println("Read body failed:", err)
return
}

var notify NotifyRequest
err = xml.Unmarshal(body, &notify)
if err != nil {
fmt.Println("XML Unmarshal failed:", err)
return
}

// 校验签名
if notify.ReturnCode == "SUCCESS" {
// 支付成功逻辑
fmt.Println("支付成功,订单号:", notify.OutTradeNo)
} else {
// 支付失败逻辑
fmt.Println("支付失败")
}

// 返回成功
w.Write([]byte("<xml><return_code>SUCCESS</return_code></xml>"))
}

func main() {
http.HandleFunc("/notify", handleNotify)
http.ListenAndServe(":8080", nil)
}

5. 总结

这个Go语言示例展示了微信支付的流程,主要包括:

  • 创建订单并请求微信的统一下单接口。
  • 生成签名并验证返回的支付结果。
  • 处理支付成功或失败的回调通知。

注意事项

  • 在实际生产环境中,确保保护好商户API密钥,并严格校验所有请求的签名。
  • 此示例为简化版,实际应用中需要考虑错误处理、参数校验等问题。

go语言写一个微信支付的简单示例代码

https://blog.jiejaitt.top/posts/96ee433e.html

作者

JIeJaitt

发布于

2025-01-24

更新于

2025-01-24

许可协议

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×