Go 实现微信支付和回调

go 微信支付开发 jsapi
一、准备工作
1 . 注册企业账号: https://pay.weixin.qq.com/
2 . 配置V3 支付
3 . 绑定微信小程序
4 . 设置 下载证书
5 . 也可以手撸文档 https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/direct-jsons/jsapi-prepay.html
二、证书放在项目 cert中

image-20231010171100268.png

三、配置config.yml

1 . 注册企业账号: https://pay.weixin.qq.com/
2 . 配置V3 支付
3 . 绑定微信小程序
4 . 设置 下载证书
5 . 也可以手撸文档  https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/direct-jsons/jsapi-prepay.html

四、下载对应的SDK

go get github.com/wechatpay-apiv3/wechatpay-go

五、封装微信支付类 pay.go

package wepay

//支付公共uri
const (
  publicKeyUrl = "https://api.mch.weixin.qq.com/v3/certificates"
  commonPayUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"
)
//自定义回调uri
const (
  notifyUrl = "https://xxxxxxx/api/v1/order/notify"
)

// 微信支付
func JsApi(payResMap map[string]string) (payJson map[string]string, err error) {
appId := viper.GetString("mini.appId")
privatePath := viper.GetString("wePay.privatePath")
payMap := make(map[string]string)
timeStamp := time.Now().Unix()
nonce := waymon.GetRandomString(32)
packageStr := "prepay_id=" + payResMap["prepay_id"]
payMap["appId"] = appId
payMap["timeStamp"] = fmt.Sprintf("%v", timeStamp)
payMap["nonceStr"] = nonce
payMap["package"] = packageStr
// 签名
message := fmt.Sprintf("%s\n%s\n%s\n%s\n", appId, fmt.Sprintf("%v", timeStamp), nonce, packageStr)
dir, _ := os.Getwd()
open, err := os.Open(dir + privatePath)
if err != nil {
return payJson, err
}
defer open.Close()
privateKey, err := ioutil.ReadAll(open)
if err != nil {
return payJson, err
}
signBytes, err := signPKCS1v15(hasha256(message), privateKey, crypto.SHA256)
if err != nil {
return payJson, err
}
sign := base64EncodeStr(signBytes)
payMap["signType"] = "RSA"
payMap["paySign"] = sign
payJsonBytes, err := json.Marshal(payMap)
if err != nil {
return payJson, err
}
err = json.Unmarshal(payJsonBytes, &payJson)
if err != nil {
return nil, err
}
return payJson, nil
}


func CommonPay(tradeNo, desc, openId string, amount int) (payResMap map[string]string, err error) {
appId := viper.GetString("mini.appId")
mchId := viper.GetString("wePay.mchId")
payResMap = make(map[string]string)
paramMap := make(map[string]interface{})
paramMap["appid"] = appId
paramMap["mchid"] = mchId
paramMap["description"] = desc
paramMap["out_trade_no"] = tradeNo
paramMap["notify_url"] = notifyUrl
paramMap["amount"] = map[string]interface{}{
"total":    amount,
"currency": "CNY",
}
paramMap["payer"] = map[string]string{
"openid": openId,
}
token, err := authorization(http.MethodPost, paramMap, commonPayUrl)
if err != nil {
return payResMap, err
}
marshal, _ := json.Marshal(paramMap)
request, err := http.NewRequest(http.MethodPost, commonPayUrl, bytes.NewReader(marshal))
if err != nil {
return payResMap, err
}
request.Header.Add("Authorization", "WECHATPAY2-SHA256-RSA2048 "+token)
request.Header.Add("User-Agent", "用户代理(https://zh.wikipedia.org/wiki/User_agent)")
request.Header.Add("Content-type", "application/json;charset='utf-8'")
request.Header.Add("Accept", "application/json")
client := http.DefaultClient
response, err := client.Do(request)
if err != nil {
return payResMap, err
}
defer func() {
response.Body.Close()
}()
bodyBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
return payResMap, err
}
if err = json.Unmarshal(bodyBytes, &payResMap); err != nil {
return payResMap, err
}
if payResMap["prepay_id"] == "" {
return payResMap, errors.New("code:" + payResMap["code"] + "err:" + payResMap["message"])
}
return payResMap, nil
}

六、调用方法

payRes, err := wepay.CommonPay(service.TradeNo, service.Desc, service.OpenId, service.Money)
if err != nil {
code = e.Error
return res.Response{
Status: code,
Msg:    err.Error(),
Data:   nil,
}
}
pay, err := wepay.JsApi(payRes)
if err != nil {
code = e.Error
return res.Response{
Status: code,
Msg:    err.Error(),
Data:   nil,
}
}

pay : 返回给前端小程序调起支付

七、回调

func OrderNotify(c *gin.Context) {
aesKey := viper.GetString("wePay.aesKey")
defer func() {
//错误处理
if e := recover(); e != nil {
zap.S().Error("微信支付回调异常:", e)
log.Logger.Error("微信支付回调异常")
}
}()
request := notify.Request{}
c.ShouldBind(&request)
mapstructure.Decode(c.Params, &request)
if request.EventType == "TRANSACTION.SUCCESS" {
plaintext, err := wepay.DecryptAES256GCM(
aesKey, request.Resource.AssociatedData, request.Resource.Nonce, request.Resource.Ciphertext,
)
if err != nil {
fmt.Println(err)
zap.S().Error("DecryptAES256GCM err" + err.Error())
log.Logger.Error("DecryptAES256GCM err" + err.Error())
}
transaction := payments.Transaction{}
json.Unmarshal([]byte(plaintext), &transaction)
go func() {
  // 执行service层代码
}()
tmp := make(map[string]interface{})
tmp["code"] = "SUCCESS"
tmp["message"] = "成功"
tmpJson, _ := json.Marshal(tmp)
c.Writer.Write(tmpJson)
} else {
tmp := make(map[string]interface{})
tmp["code"] = "500"
tmp["message"] = "失败"
tmpJson, _ := json.Marshal(tmp)
c.Writer.Write(tmpJson)
}
}

八、代码

https://github.com/Waymon102092/WaymonWeXinPay

eg
github主页: https://github.com/Waymon102092/
微信公众号: Waymon

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值