Go语言对接微信支付与退款全流程指南

在互联网技术日益发展的今天,线上支付已成为不可或缺的一部分。作为一门简洁高效的编程语言,Go(又称Golang)凭借其强大的并发处理能力和高效性能,在后端开发领域越来越受到开发者的青睐。本文将详细介绍如何使用Go语言对接微信支付,并实现支付和退款功能,帮助开发者快速上手。

一、准备工作

在开始编写代码之前,你需要先准备好以下几项工作:

1、注册成为微信支付商户:如果你还没有微信支付商户账号,需要先前往微信支付商户平台完成注册。

2、获取必要的配置信息

  • 商户号 (MchId)

  • AppID (Appid)

  • API v3 密钥 (ApiV3Key)

  • 商户证书序列号 (MchSerialNo)

  • 私钥 (PrivateKey)

  • 支付通知地址 (NotifyUrl)

  • 退款通知地址 (RefundUrl)

3、安装第三方库:为了简化微信支付接口的调用,推荐使用github.com/go-pay/gopay这个库。可以通过go get命令安装:

go get github.com/go-pay/gopay

二、初始化微信支付客户端

首先,我们需要创建一个WechatPayService结构体来封装微信支付的相关操作。该结构体包含上下文、配置信息和微信支付客户端实例。

type WechatPayService struct {ctx       context.Contextconfig    WechatPayConfigwechatPay *wechat.ClientV3
}type WechatPayConfig struct {Appid       stringAppid1      stringMchId       stringApiV3Key    stringMchSerialNo stringPrivateKey  stringNotifyUrl   stringRefundUrl   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.DebugOnreturn &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.H5Urlreturn
}

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.CodeUrlreturn
}

Android端支付

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)  // 解密回调内容
}

  • APP支付跟JSAPI支付很像。主要区别在于app与商户服务后台的交互。app会从商户服务后台获取签名信息,根据签名信息,app直接调用微信支付服务下单。

3. 解析支付回调

当用户完成支付后,微信会向我们的服务器发送支付成功的回调通知。我们需要解析这个通知并验证其合法性。

通过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语言对接微信支付,并实现了支付和退款功能。这些功能不仅能够提升用户体验,还能帮助你在实际项目中更加高效地处理支付相关的业务逻辑。希望本文对你有所帮助!

文章转载自:tatasix

原文链接:https://www.cnblogs.com/crazytata/p/18452145

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1559211.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Java SE基础回顾】看这篇就够了!

JavaSE复习 参考视频:【狂神说Java】JavaSE阶段回顾总结 简单的就不讲了,比如什么break和continue区别,甚至一些什么什么继承封装多态的概念等等。 主要写一些Java特有的,重点的基础知识。主要还是例子和代码更多,更有…

对象存储之阿里云OSS最详细的实现

Hello,大家好,我是Feri,一枚十多年的程序员,同时也是一名在读研究生,关注我,且看一个平凡的程序员如何在自我成长,只为各位小伙伴提供编程相关干货知识,希望在自我蜕变的路上&#x…

【JS】环形链表怎么找入口?

思路 判断是否有环:定义快慢指针,慢指针(slow)走一步,快指针(fast)走两步。 无环:快指针最终会到达链表的末尾(即fast.next为null),永远不可能相遇有环&#…

C++ 二叉搜索树转换为双向链表

描述 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表: 代码 #include <iostream> #include <string> #include <optional>struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;TreeNode(int x): val(x), left(…

陈零九全新单曲《也曾想走进你的心底》 揭露爱而不得的情感遗憾

图片提供&#xff1a;种子音乐 “创作男神”陈零九于10月9日推出充满深情的全新创作单曲《也曾想走进你的心底》&#xff0c;这首歌再次延续他招牌的“九式情歌”风格&#xff0c;展现其创作魅力。歌曲以一段“爱而不得”的感情故事为主线&#xff0c;深入探讨人们在爱情中的复…

项目启动 | 盘古信息赋能奥尼视讯数字化转型升级,实现全面数智化发展

随着信息技术的飞速发展与全球市场竞争的日益激烈&#xff0c;传统制造业正面临生存和发展的危机&#xff0c;制造企业为谋求发展&#xff0c;纷纷开启数字化转型之路&#xff0c;深度融入数字技术&#xff0c;实现生产流程的智能化、管理模式的精细化以及产品服务的个性化&…

科普|网络准入控制系统是什么?2024年好用的网络准入控制系统推荐!

在宁波的传统习俗中&#xff0c;有一个有趣的谚语故事——“阿旺炒年糕”。 据说&#xff0c;宁波的男子名字中多“旺”&#xff0c;凡名字中有“旺”者&#xff0c;小名就被叫作“阿旺”。炒年糕须用慢火&#xff0c;但有一位不懂家务的男子心急&#xff0c;用旺火炒年糕&…

LSTM(长短时记忆网络)

一、引言 在处理序列数据时&#xff0c;循环神经网络&#xff08;RNN&#xff09;虽然能够处理序列数据并保留历史信息&#xff0c;但在实践中发现它对于捕捉长时间依赖关系的能力有限&#xff0c;尤其是在训练过程中容易遇到梯度消失或梯度爆炸的问题。为了解决这些问题&…

组装首页:其他组件html、css移入JS中再引入首页

组装首页 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>组装首页</title><style>* …

【计算机方向】IEEE二区宝刊,IF=9.6,2个月秒速接受,备受国人吹捧!

期刊解析 01 期刊信息✦ 期刊名称&#xff1a;IEEE Transactions on Affective Computing 出版商&#xff1a;Institute of Electrical and Electronics Engineers Inc. ISSN&#xff1a;1949-3045 …

重头开始嵌入式第四十七天(硬件 ARM裸机开发 RS232 RS4885 IIC)

目录 一.什么是RS232&#xff1f; 1. 历史背景&#xff1a; 2. 电气特性&#xff1a; 3. 连接器类型&#xff1a; 4. 通信特点&#xff1a; 5. 应用场景&#xff1a; 二.什么是RS485&#xff1f; 1. 电气特性&#xff1a; 2. 通信模式&#xff1a; 3. 传输距离与速率&…

扫描电镜是用来测什么的?

扫描电镜是一种用于对样品进行微观尺度形貌观测和分析的仪器。它能够提供高分辨率的图像&#xff0c;帮助科学家和工程师了解样品的微观结构和特性。 一、扫描电镜的一般测量功能 微观形貌观测 扫描电镜可以清晰地观察到样品表面的微观形貌&#xff0c;如颗粒的形状、大小、…

GC9113:电子锁领域的革新力量

在现代社会&#xff0c;安全与便捷成为人们对生活品质的重要追求。电子锁作为保障家庭和商业安全的关键设备&#xff0c;不断经历着技术的革新与升级。而 GC9113 的出现&#xff0c;为电子锁领域带来了全新的替代选择。 GC9113 以其卓越的性能和独特的优势&#xff0c;在电子锁…

【嵌入式软件-STM32】STM32简介

目录 一、STM32定义 二、STM32用途 三、STM32特点 四、STM32 四个系列 五、了解ARM 六、芯片解释 七、片上资源 八、命名规则 九、系统结构 内核 Flash DMA 外设种类和分布 十、引脚定义 类型 名称 引脚 十一、启动配置 十二、STM32最小系统电路 STM32及供电 供电引脚 滤波电容…

深度学习:循环神经网络RNN

目录 一、神经网络的历程 1.传统神经网络存在的问题 2.提出一种新的神经网络 二、RNN基本结构 1.RNN基本结构 2.RNN的独特结构 3.RNN的局限性 一、神经网络的历程 1.传统神经网络存在的问题 无法训练出具有顺序的数据。模型搭建时没有考虑数据上下之间的关系。因为传统…

十年网络安全工程师谈学习网络安全的正确顺序

当今数字化时代&#xff0c;网络安全行业如守护数字世界的坚固堡垒&#xff0c;其重要性愈发凸显。随着信息技术的迅猛发展&#xff0c;我们的生活、工作、社交等方方面面都与网络紧密相连&#xff0c;从个人隐私信息到企业核心数据&#xff0c;再到国家关键基础设施乃至全球互…

什么是Cookie 它有什么作用 及如何使用Session-Cookie方案进行身份验证 总结

Cookie 和 Session 都是用来跟踪浏览器用户身份的会话方式&#xff0c;但是两者的应用场景不太一样。 维基百科是这样定义 Cookie 的&#xff1a; Cookies 是某些网站为了辨别用户身份而储存在用户本地终端上的数据&#xff08;通常经过加密&#xff09;。 简单来说&#xff1…

实战千问2大模型第五天——VLLM 运行 Qwen2-VL-7B(多模态)

一、简介 VLLM 是一种高效的深度学习推理库&#xff0c;通过PagedAttention算法有效管理大语言模型的注意力内存&#xff0c;其特点包括24倍的吞吐提升和3.5倍的TGI性能&#xff0c;无需修改模型结构&#xff0c;专门设计用于加速大规模语言模型&#xff08;LLM&#xff09;的…

网站排名,让网站快速有排名的几个方法

要让网站快速获得并提升排名&#xff0c;需要综合运用一系列专业策略和技术&#xff0c;这些策略涵盖了内容优化、技术调整、外链建设、用户体验提升等多个方面。以下是让网站快速有排名的几个方法&#xff1a; 1.内容为王&#xff1a;创造高质量、有价值的内容 -深入…

The Android SDK location cannot be at the filesystem root

win11&#xff0c; 安装启动完Android Studio后&#xff0c;一直显示 The Android SDK location cannot be at the filesystem root因此需要下载SDK包&#xff0c;必须开启代理。 开启代理后&#xff0c;在System下开启自动检测代理&#xff0c;如图 重启Android Studio&a…