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 ...
随机推荐
- NOIP2022退役记
我是青岛西海岸新区的一名oier,qxyz(xhayz)的. (其实也不知道算不算得上真正的oier) 已经高二了,是最后一次noip了,必须写点什么记录一下了吧,这样至少可以向世界留下一点痕迹:这个 ...
- Fiddler使用界面介绍-右侧面板
右侧面板是对左侧请求进行解析的面板,点击左侧的请求右侧面板就会出现分析数据 1.Statistics关于HTTP请求的性能 2.Inspectors请求内容,包含请求数据和响应数据 3. AutoRe ...
- 【Mybatis-Plus】联表分页查询实现
参考文章: https://blog.csdn.net/weixin_43847283/article/details/125822614 上上周写的SQL案例确实可以重构,所以搬到Demo里面测试看 ...
- 【Hibernate】02 快速入门
环境搭建 : Windo7 x64 + IDEA 2018+ JDK 8+ Maven 3.0+ MySQL 5.0+ 创建Hibernate工程: 导入依赖坐标 <dependencies&g ...
- python性能分析器:cProfile
代码: (1) import cProfile import re cProfile.run('re.compile("foo|bar")') 运行结果: (2) import c ...
- tensorflow_probability.python.bijectors的一些使用
网上见到一个TensorFlow的代码,没见过这个形式的,是概率编程的代码: # coding=utf-8 # Copyright 2020 The TF-Agents Authors. # # Li ...
- 【VMware VCF】VCF 5.2:部署整合架构的SDDC。
VMware 前不久发布了 VMware Cloud Foundation 5.2 版本,并带来了许多功能的升级,比如支持 vSAN Max 分解存储,管理工作负载域支持 vSAN ESA 延伸集群, ...
- PPT或Visio比较舒适的RGB配色参数
1.187 204 235 2.222 156 83 3.117 156 83 4.64 116 52 5.117 121 74 6.69 137 148 7.182 194 154 8.207 19 ...
- 【Python自动化】之特殊的自动化定位操作
今天有时间了,想好好的把之前遇到过的自动化问题总结一下,以后有新的总结再更新 目录: 一.上传文件(4.11) 二.下拉框选择(4.11) 1.Select下拉框 2.非Select下拉框 三.下拉框 ...
- Java面试集锦(一)
计算机网络 摘要:1. 在浏览器中输入url地址 显示主页的过程,整个过程会使用哪些协议 image.jpeg总体来说分为以下几个过程: DNS解析 TCP连接 发送HTTP请求 服务器处理请求并返回 ...