目录:

一、准备工作

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

三、实现支付功能

1. 付款时序图

2. 实现不同场景下的支付

WAP端支付

PC端支付

Android端支付

3. 解析支付回调

四、实现退款功能

退款时序图

发起退款

解析退款回调

五、总结

在互联网技术日益发展的今天,线上支付已成为不可或缺的一部分。作为一门简洁高效的编程语言,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.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语言对接微信支付与退款全流程指南的更多相关文章

  1. PHP对接微信支付采坑

    第一次做PHP商城项目对接微信支付接口,踩了N次坑,这也不对,那也不对,搞了很久,查了一些资料,终于实现了支付功能,小小总结一下,万一下次遇到就不用到处找资料了. 微信扫码支付 前期准备: 1.微信公 ...

  2. Android对接微信支付体验

    在写正文之前我不得不吐槽一下:微信支付所提供的参考文档以及技术支持真心太烂了. 微信的坑: 1.在生成prepay_id向微信服务器传递参数时<body>不支持中文.需要对其进行转码,否则 ...

  3. 微信支付 - V3退款

        退款问题: 1.证书加载不进去,出现"内部错误" 解决:在iis中找到对应的应用连接池,右键高级设置,找到"加载用户配置文件"改为true.   2.需 ...

  4. java对接微信支付

    对接微信扫码支付(模式2),前端使用velocity技术 (1)调用微信支付接口(view层)  此部分业务逻辑部分可以省略 @RequestMapping("/wxpay.htm" ...

  5. python - 对接微信支付(PC)和 注意点

    注:本文仅提供 pc 端微信扫码支付(模式一)的示例代码. 关于对接过程中遇到的问题总结在本文最下方. 参考: 官方文档,    https://blog.csdn.net/lm_is_dc/arti ...

  6. iOS中 最新微信支付/最全的微信支付教程详解 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博! 亲们, 首先让我们来看一下微信支付的流程吧. 1. 注册微信开放平台,创建应用获取appid,appSecret, ...

  7. iOS中 最新微信支付/最全的微信支付教程具体解释 韩俊强的博客

    亲们, 首先让我们来看一下微信支付的流程吧. 1. 注冊微信开放平台,创建应用获取appid,appSecret,申请支付功能,申请成功之后会返回一些參数. 2. 下载微信支付sdk 3. clien ...

  8. SpringBoot项目后台对接微信支付开发——微信统一下单接口开发

    开始没找到微信支付的sdk.自己根据官方给的接口文档纯手写,各种xml转JSON,JSON转xml,加密解密,签名....整个人都是崩溃的 开发的第三天,发现有官方的sdk.心情一下子豁然开朗,整个人 ...

  9. app对接微信支付(app支付)

    (先补充一下,app唤醒微信支付失败的话,在确保没错的情况下,建议换一个手机或者重新下载微信,不知道是微信缓存还是什么原因) 1.先申请好开发环境 app支付不需要公众号,所以申请好开发商号和开发平台 ...

  10. 微信小程序中的微信支付js代码和流程详解

    微信支付流程 步骤 (一)获取用户的信息 (二)统一下单(返回的prepay_id用于第(三)步的请求参数) (三)发起支付请求 操作(这边假设你已经获得了用户的openId) (一).获取用户ope ...

随机推荐

  1. PHP进阶

    只是简要说明起原理和用法,具体可以百度 abstract 抽象类 抽象类是指在 class 前加了 abstract 关键字且存在抽象方法,不带{},如public function test() i ...

  2. SecureCRT通过vbs脚本实现自动化登录linux服务器

    1.配置登录主机名.用户和密码 2.配置登录后操作脚本目录 3.vbs操作脚本如下(crt也支持python) #$language = "VBScript" #$interfac ...

  3. 基于EasyTcp4Net开发一个功能较为完善的去持久化聊天软件

    之前自己写了一篇介绍TCP的一些常用的功能介绍和特征,并且用代码做了示例,最终开发了一个EasyTcp4Net的TCP工具库,其最大的特色就是使用了微软提供的高性能库中的一些数据结构来处理TCP数据. ...

  4. 在Ubuntu 18.04 Desktop图形中配置静态和动态IP

    在Ubuntu 18.04 图形界面中配置静态和动态IP 设置静态ip 设置为dhcp动态获取ip

  5. 【Java】Oshi 硬件信息读取库

    实现的功能: 用于开发服务器监控面板,获取服务器硬件参数 官方Github仓库地址: https://github.com/oshi/oshi Maven坐标: <!-- https://mvn ...

  6. 【SpringBoot】02 概述

    [目标] - 什么是SpringBoot? 并不是新技术,只是一个Spring的加强 解脱XML配置,增加了新的注解,但是并不是新的内容 - 新型配置文件技术 YAML - 自动装配原理[了解即可,不 ...

  7. vscode中使用ssh进行远程项目开发时无法连接远端服务器——如何解决

    找到vscode中的ssh扩展(Visual Studio Code Remote - SSH),然后卸载,再重新安装,即可解决. PS: 重新安装时需要较长时间的等待. ============== ...

  8. gym.ObservationWrapper使用时的注意点——reset和step函数可以覆盖observation函数

    记录一个刚学习到的gym使用的点,就是gym.ObservationWrapper使用时的注意点--reset和step函数可以覆盖observation函数. 给出代码: import gym cl ...

  9. 强化学习的REIINFORCE算法和交叉熵RL算法

    注意: 本文并不讲REINFORCE算法,而是讲强化学习的交叉熵算法,关于REINFORCE算法可以参看: https://www.cnblogs.com/devilmaycry812839668/p ...

  10. SMU Spring 2023 Contest Round 3(2023年湘潭大学新生赛)

    Problem A. 签到啦 从大到小排序,累加大于行李w时输出下标即可 int ans; void solve() { cin >> n >> m; int ans = 0; ...