Go语言对接微信支付与退款全流程指南
目录:
一、准备工作
二、初始化微信支付客户端
三、实现支付功能
1. 付款时序图
2. 实现不同场景下的支付
WAP端支付
PC端支付
Android端支付
3. 解析支付回调
四、实现退款功能
退款时序图
发起退款
解析退款回调
五、总结
在互联网技术日益发展的今天,线上支付已成为不可或缺的一部分。作为一门简洁高效的编程语言,Go(又称Golang)凭借其强大的并发处理能力和高效性能,在后端开发领域越来越受到开发者的青睐。本文将详细介绍如何使用Go语言对接微信支付,并实现支付和退款功能,帮助开发者快速上手。
一、准备工作
在开始编写代码之前,你需要先准备好以下几项工作:
- 注册成为微信支付商户:如果你还没有微信支付商户账号,需要先前往微信支付商户平台完成注册。
- 获取必要的配置信息:
- 商户号 (
MchId) - AppID (
Appid) - API v3 密钥 (
ApiV3Key) - 商户证书序列号 (
MchSerialNo) - 私钥 (
PrivateKey) - 支付通知地址 (
NotifyUrl) - 退款通知地址 (
RefundUrl)
- 商户号 (
- 安装第三方库:为了简化微信支付接口的调用,推荐使用
github.com/go-pay/gopay这个库。可以通过go get命令安装:go get github.com/go-pay/gopay
二、初始化微信支付客户端
首先,我们需要创建一个WechatPayService结构体来封装微信支付的相关操作。该结构体包含上下文、配置信息和微信支付客户端实例。
type WechatPayService struct {
ctx context.Context
config WechatPayConfig
wechatPay *wechat.ClientV3
}
type WechatPayConfig struct {
Appid string
Appid1 string
MchId string
ApiV3Key string
MchSerialNo string
PrivateKey string
NotifyUrl string
RefundUrl string
}
接着,我们通过NewWechatPayService函数来初始化WechatPayService实例。
func NewWechatPayService(ctx context.Context, config WechatPayConfig) *WechatPayService {
client, err := wechat.NewClientV3(config.MchId, config.MchSerialNo, config.ApiV3Key, config.PrivateKey)
if err != nil {
fmt.Println(err)
return nil
}
err = client.AutoVerifySign()
if err != nil {
fmt.Println(err)
return nil
}
client.DebugSwitch = gopay.DebugOn
return &WechatPayService{
ctx: ctx,
wechatPay: client,
config: config,
}
}
此代码段中,我们通过NewClientV3方法初始化了微信支付客户端,传入商户号、证书序列号、API v3密钥和私钥等关键参数。为了保障支付的安全性,开启了自动验签功能。
三、实现支付功能
1. 付款时序图

2. 实现不同场景下的支付
WAP端支付
func (w *WechatPayService) WapPay(charge *Charge) (result string, err error) {
amount := decimal.NewFromInt(charge.MoneyFee).DivRound(decimal.NewFromInt(1), 2).IntPart()
expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
bm := make(gopay.BodyMap)
bm.Set("appid", w.config.Appid).
Set("mchid", w.config.MchId).
Set("description", charge.Describe).
Set("out_trade_no", charge.TradeNum).
Set("time_expire", expire).
Set("notify_url", w.config.NotifyUrl).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", amount).
Set("currency", "CNY")
}).
SetBodyMap("scene_info", func(bm gopay.BodyMap) {
bm.Set("payer_client_ip", "127.0.0.1").
SetBodyMap("h5_info", func(bm gopay.BodyMap) {
bm.Set("type", "Wap")
})
})
rsp, err := w.wechatPay.V3TransactionH5(w.ctx, bm)
if err != nil {
return
}
result = rsp.Response.H5Url
return
}
PC端支付
func (w *WechatPayService) PcPay(charge *Charge) (result string, err error) {
amount := decimal.NewFromInt(charge.MoneyFee).DivRound(decimal.NewFromInt(1), 2).IntPart()
expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
bm := make(gopay.BodyMap)
bm.Set("appid", w.config.Appid).
Set("mchid", w.config.MchId).
Set("description", charge.Describe).
Set("out_trade_no", charge.TradeNum).
Set("time_expire", expire).
Set("notify_url", w.config.NotifyUrl).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", amount).
Set("currency", "CNY")
})
rsp, err := w.wechatPay.V3TransactionNative(w.ctx, bm)
if err != nil {
return
}
result = rsp.Response.CodeUrl
return
}
Android端支付
func (w *WechatPayService) AndroidPay(charge *Charge) (result string, err error) {
amount := decimal.NewFromInt(charge.MoneyFee).DivRound(decimal.NewFromInt(1), 2).IntPart()
expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
bm := make(gopay.BodyMap)
bm.Set("appid", w.config.Appid1).
Set("mchid", w.config.MchId).
Set("description", charge.Describe).
Set("out_trade_no", charge.TradeNum).
Set("time_expire", expire).
Set("notify_url", w.config.NotifyUrl).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", amount).
Set("currency", "CNY")
})
rsp, err := w.wechatPay.V3TransactionApp(w.ctx, bm)
if err != nil {
return
}
jsapiInfo, err := w.wechatPay.PaySignOfApp(w.config.Appid1, rsp.Response.PrepayId)
str, _ := json.Marshal(jsapiInfo)
result = string(str)
return
}
- APP支付跟JSAPI支付很像。主要区别在于app与商户服务后台的交互。app会从商户服务后台获取签名信息,根据签名信息,app直接调用微信支付服务下单。
3. 解析支付回调
当用户完成支付后,微信会向我们的服务器发送支付成功的回调通知。我们需要解析这个通知并验证其合法性。
func (w *WechatPayService) GetNotifyResult(r *http.Request) (res *wechat.V3DecryptResult, err error) {
notifyReq, err := wechat.V3ParseNotify(r) // 解析回调参数
if err != nil {
fmt.Println(err)
return
}
if notifyReq == nil {
return
}
return notifyReq.DecryptCipherText(w.config.ApiV3Key) // 解密回调内容
}
通过V3ParseNotify方法,解析支付通知,并使用API v3密钥解密支付结果。
四、实现退款功能
退款时序图

发起退款
除了支付,退款也是微信支付中常用的功能。接下来,我们来看如何使用Go语言实现退款功能。
当需要对已支付的订单进行退款时,可以调用Refund方法。
func (w *WechatPayService) Refund(charge *RefundCharge) (err error) {
amount := decimal.NewFromInt(charge.MoneyFee).DivRound(decimal.NewFromInt(1), 2).IntPart()
bm := make(gopay.BodyMap)
bm.Set("out_trade_no", charge.TradeNum).
Set("out_refund_no", charge.OutRefundNo).
Set("reason", charge.RefundReason).
Set("notify_url", w.config.RefundUrl).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", amount).
Set("refund", amount).
Set("currency", "CNY")
})
rsp, err := w.wechatPay.V3Refund(w.ctx, bm) // 发起退款请求
if err != nil {
return
}
if rsp == nil || rsp.Response == nil || rsp.Error != "" {
// 处理退款错误
err = errors.New(rsp.Error)
return
}
return
}
解析退款回调
func (w *WechatPayService) GetRefundNotifyResult(r *http.Request) (res *wechat.V3DecryptRefundResult, err error) {
notifyReq, err := wechat.V3ParseNotify(r)
if err != nil {
return
}
return notifyReq.DecryptRefundCipherText(w.config.ApiV3Key)
}
五、总结
通过本文的介绍,相信你已经掌握了如何使用Go语言对接微信支付,并实现了支付和退款功能。这些功能不仅能够提升用户体验,还能帮助你在实际项目中更加高效地处理支付相关的业务逻辑。希望本文对你有所帮助!
如果你有任何问题或建议,欢迎在评论区留言交流。期待你的宝贵意见!

Go语言对接微信支付与退款全流程指南的更多相关文章
- PHP对接微信支付采坑
第一次做PHP商城项目对接微信支付接口,踩了N次坑,这也不对,那也不对,搞了很久,查了一些资料,终于实现了支付功能,小小总结一下,万一下次遇到就不用到处找资料了. 微信扫码支付 前期准备: 1.微信公 ...
- Android对接微信支付体验
在写正文之前我不得不吐槽一下:微信支付所提供的参考文档以及技术支持真心太烂了. 微信的坑: 1.在生成prepay_id向微信服务器传递参数时<body>不支持中文.需要对其进行转码,否则 ...
- 微信支付 - V3退款
退款问题: 1.证书加载不进去,出现"内部错误" 解决:在iis中找到对应的应用连接池,右键高级设置,找到"加载用户配置文件"改为true. 2.需 ...
- java对接微信支付
对接微信扫码支付(模式2),前端使用velocity技术 (1)调用微信支付接口(view层) 此部分业务逻辑部分可以省略 @RequestMapping("/wxpay.htm" ...
- python - 对接微信支付(PC)和 注意点
注:本文仅提供 pc 端微信扫码支付(模式一)的示例代码. 关于对接过程中遇到的问题总结在本文最下方. 参考: 官方文档, https://blog.csdn.net/lm_is_dc/arti ...
- iOS中 最新微信支付/最全的微信支付教程详解 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博! 亲们, 首先让我们来看一下微信支付的流程吧. 1. 注册微信开放平台,创建应用获取appid,appSecret, ...
- iOS中 最新微信支付/最全的微信支付教程具体解释 韩俊强的博客
亲们, 首先让我们来看一下微信支付的流程吧. 1. 注冊微信开放平台,创建应用获取appid,appSecret,申请支付功能,申请成功之后会返回一些參数. 2. 下载微信支付sdk 3. clien ...
- SpringBoot项目后台对接微信支付开发——微信统一下单接口开发
开始没找到微信支付的sdk.自己根据官方给的接口文档纯手写,各种xml转JSON,JSON转xml,加密解密,签名....整个人都是崩溃的 开发的第三天,发现有官方的sdk.心情一下子豁然开朗,整个人 ...
- app对接微信支付(app支付)
(先补充一下,app唤醒微信支付失败的话,在确保没错的情况下,建议换一个手机或者重新下载微信,不知道是微信缓存还是什么原因) 1.先申请好开发环境 app支付不需要公众号,所以申请好开发商号和开发平台 ...
- 微信小程序中的微信支付js代码和流程详解
微信支付流程 步骤 (一)获取用户的信息 (二)统一下单(返回的prepay_id用于第(三)步的请求参数) (三)发起支付请求 操作(这边假设你已经获得了用户的openId) (一).获取用户ope ...
随机推荐
- Diffutoon下载介绍:真人视频转动漫工具,轻松获得上千点赞
最近在刷短视频的时候,偶尔能看到一些真人转动漫风的作品,看起来给人一种新鲜感,流量都还不错,简简单单跳个舞,就能获得上千个点赞~ 那么,这种视频是怎么制作的? 本期给大家介绍一款AI转绘工具Diffu ...
- Python和RPA网页自动化-让非标准下拉框选择指定文本的方法
以下方"节点审批"下拉框为例 该下拉框没有<select>标签,而是<div><ul><li>标签.分别使用Python和RPA网页 ...
- 【Java】Input,Output,Stream I/O流 04 对象流&序列化
对象流,序列化机制 ObjectInputStream ObjectOutputStream 序列化 对象 写入转 数据 持久化 反序列化 数据 读取转 对象 活化 - 任何实现了Serializab ...
- 老代码报错:scipy.misc.imresize报错: AttributeError: module 'scipy.misc' has no attribute 'imresize'
运行老代码报错: image = misc.imresize(image, [Config.IMAGE_HEIGHT, Config.IMAGE_WIDTH], 'bilinear')Attribut ...
- 安装windows11的注意事项
进入到安装界面后,在选择时间和货币格式的时候选择:英语(世界),据说这样可以避免第三方软件的安装. KMS命令: slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX sl ...
- [学习笔记] LCA - 图论
[NOIP2013 提高组] 货车运输 最大生成树+LCA+倍增 好家伙,这道题我写了一个晚上,调了两个晚上,对于这道题我颇有感触.但这道题确实好,实实在在的蓝题,让我发现了许多关于LCA的问题. 首 ...
- 23 暑假友谊赛 No.3
23 暑假友谊赛 No.3 Problem - B - Codeforces 贪心吧,每次看哪块瓷砖划算就尽量多的放哪块 #include <bits/stdc++.h> #define ...
- grpc断路器之sentinel
荐
背景 为了防止下游服务雪崩,这里考虑使用断路器 技术选型 由于是springboot服务且集成了istio,这里考虑三种方案 istio hystrix sentinel 这里分别有这几种方案的对比 ...
- quartz集成spring集群部署
由于quartz单节点无法满足业务的需求,后面我们在单节点的基础上进行了集群部署. 由以前的定时任务信息放在jobs.xml配置文件中,转而放到数据库中. 1.新建数据库表 CREATE TABLE ...
- Mongodb使用save更新
mongodb 的 insert().save() ,区别主要是:若存在主键,insert() 不做操作,而save() 则更改原来的内容为新内容. 在使用save时,由于mongodb默认是_i ...