Go语言对接微信支付与退款指南(示例详解)
作者:tatasix
在互联网技术日益发展的今天,线上支付已成为不可或缺的一部分。作为一门简洁高效的编程语言,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语言对接微信支付与退款全流程指南的文章就介绍到这了,更多相关Go语言对接微信支付与退款内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!