微信小程序开发实战11_4 微信支付退款流程

这篇具有很好参考价值的文章主要介绍了微信小程序开发实战11_4 微信支付退款流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

当交易发生之后一年内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付金额退还给买家,微信支付将收到退款请求并且验证成功之后,将支付款按原路退还至买家账号上。使用该接口时的一些注意事项如下:

  • 交易时间超过一年的订单无法提交退款。
  • 微信支付退款支持单笔交易分多次退款(不超50次),多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号。
  • 如果同一个用户有多笔退款,建议分不同批次进行退款,避免并发退款导致退款失败。
  • 申请退款接口的返回仅代表业务的受理情况,具体退款是否成功,需要通过退款查询接口获取结果。
    微信退款的操作流程如下:
    1)买家或者卖家发起退款请求,需要提供商户订单号、退款金额等参数。
    2)商户服务器调用退款申请接口提交退款申请。
    3)微信平台向商户服务器发送退款通知,商户服务器收到通知后更新订单的退款状态。
    4)商户在没有接收到退款通知的情况下需要主动调用退款查询接口查询订单的退款状态。

13.1退款申请

退款申请接口的请求地址为:https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
退款申请接口的请求参数说明如下:

参数名 变量 描述
子商户号 sub_mchid 子商户的商户号(服务商模式下)
微信支付订单号 transaction_id 原支付交易对应的微信订单号
商户订单号 out_trade_no 原支付交易对应的商户订单号
商户退款单号 out_refund_no 商户系统内部的退款单号
退款原因 reason 若商户传入,会在下发给用户的退款消息中体现退款原因
退款结果回调url notify_url 异步接收微信支付退款结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效,优先回调当前传的这个地址。
退款资金来源 funds_account 若传递此参数则使用对应的资金账户退款,否则默认使用未结算资金退款(仅对老资金流商户适用)
金额信息 amoun t 订单金额信息
退款商品 goods_detail 指定商品退款需要传此参数,其他场景无需传递

接下来分别给出直连商户与服务商两种模式下的支付退款申请接口的相关数据结构以及函数。

//退款金额信息
type RefundCreateAmount struct {
   //退款金额,单位为分
   Refund           int       `json:"refund"`
   //原订单金额,单位为分
   Total        int       `json:"total"`
   //退款币种:CNY(人民币),境内商户号仅支持人民币。
   Currency           string    `json:"currency"`
}
//微信支付退款申请请求参数
type RefundCreateReq struct {
   //子商户的商户号(服务商)
   Sub_mchid          string `json:"sub_mchid,omitempty"`
   //商户系统内部订单号
   Out_trade_no       string `json:"out_trade_no,omitempty"`
   //微信支付订单号
   Transaction_id         string `json:"transaction_id,omitempty"`
   //商户系统内部的退款单号
   Out_refund_no      string `json:"out_refund_no"`
   //退款原因
   Reason            string `json:"reason,omitempty"`
   //退款结果回调的URL,不允许携带查询串
   Notify_url           string `json:"notify_url,omitempty"`
   //退款金额信息
   Amount     RefundCreateAmount     `json:"amount"`
}
//微信退款订单信息
type RefundOrderInfo struct {
   //服务商户号(普通商户)
   Mchid                 string `json:"mchid"`
   //服务商户号(服务商)
   Sp_mchid           string `json:"sp_mchid"`
   //子商户的商户号(服务商)
   Sub_mchid          string `json:"sub_mchid"`
   //微信支付退款单号
   Refund_id          string `json:"refund_id"`
   //商户系统内部的退款单号
   Out_refund_no      string `json:"out_refund_no"`
   //微信支付订单号
   Transaction_id         string `json:"transaction_id"`
   //商户系统内部订单号
   Out_trade_no       string `json:"out_trade_no"`
   //退款渠道 
   Channel          string `json:"channel"`
   //退款入账账户
   User_received_account    string    `json:"user_received_account"`
   //退款成功时间
   Success_time           string `json:"success_time"`
   //退款创建时间
   Create_time        string `json:"create_time"`
   //退款状态
   Status               string `json:"status"`
   //退款所使用资金对应的资金账户类型 
   Funds_account       string `json:"funds_account"`
   //订单金额信息
   Amount     RefundOrderAmount  `json:"amount"`
}
//提交退款申请(服务商模式)
func refundOrderX(ent *MchParam, data RefundCreateReq) (RefundOrderInfo, error) {
   data_body, _ := json.Marshal(data)

   var pret RefundOrderInfo
   const url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"
   result, err := WxPayPostV3(ent, url, data_body)
   if err != nil {
      return pret, err
   }
   err = json.Unmarshal([]byte(result), &pret)
   if err != nil {
      return pret, err
   }
   return pret, nil
}
//提交退款申请(普通商户模式)
func refundOrder(ent *MchParam, data RefundCreateReq) (RefundOrderInfo, error) {
   data.Sub_mchid = ""
   data_body, _ := json.Marshal(data)

   var pret RefundOrderInfo
   const url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"
   result, err := WxPayPostV3(ent, url, data_body)
   if err != nil {
      return pret, err
   }
   err = json.Unmarshal([]byte(result), &pret)
   if err != nil {
      return pret, err
   }
   return pret, nil
}

13.2处理退款通知

当商户申请的退款有结果后(退款状态为:退款成功、退款关闭、退款异常),微信会把相关结果发送给商户,商户需要进行接收处理,并返回应答。微信会对发送给商户的通知进行签名,并将签名值放在通知的HTTP请求头中:Wechatpay-Signature。商户应当验证签名,以确认请求来自微信,而不是其他的第三方。
退款通知HTTP应答码为200且返回状态码为SUCCESS才会当做商户接收成功。如果微信收到的应答不符合规范或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。如果在所有通知频率后没有收到微信侧回调。商户应调用退款查询接口确认退款状态。
同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。推荐的做法是,当商户系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
退款通知的处理逻辑如下:
1)首先从请求的header中获取签名
2)使用微信支付 的平台私钥(不是商户私钥 )进行签名验证。
3)使用APIv3密钥对支付订单数据进行解密
首先看看退款通知的相关参数说明:

参数名 变量 描述
通知ID id 通知的唯一ID
通知创建时间 create_time 通知创建的时间
通知类型 event_type 通知的类型:REFUND.SUCCESS:退款成功通知REFUND.ABNORMAL:退款异常通知REFUND.CLOSED:退款关闭通知
通知简要说明 summary 通知简要说明
通知数据类型 resource_type 通知的资源数据类型,支付成功通知为encrypt-resource
通知数据 resource 通知资源数据JSON格式

退款结果对重要的数据进行了加密,商户需要用商户密钥进行解密后才能获得结果通知的内容。商户对resource对象进行解密后,得到的通知参数,具体字段含义如下:

参数名 变量 描述
直连商户号 mchid 直连商户的商户号(直连模式下)。
服务商户号 sp_mchid 服务商户号(服务商模式下)。
子商户号 sub_mchid 子商户的商户号(服务商模式下)。
商户订单号 out_trade_no 返回的商户订单号
微信支付订单号 transaction_id 微信支付订单号
商户退款单号 out_refund_no 商户退款单号
微信支付退款单号 refund_id 微信退款单号
退款状态 refund_status 退款状态,枚举值:SUCCESS:退款成功CLOSE:退款关闭ABNORMAL:退款异常
退款成功时间 success_time 退款成功时间
退款入账账户 user_received_account 取当前退款单的退款入账方。
金额信息 amount 金额信息

退款通知相关的数据结构定义如下:

//退款金额信息
type RefundOrderAmountCB struct {
   //退款金额,单位为分
   Refund           int       `json:"refund"`
   //原订单金额,单位为分
   Total        int       `json:"total"`
   //退款币种:CNY(人民币),境内商户号仅支持人民币。
   Currency           string    `json:"currency"`
   //用户支付金额,单位为分
   Payer_total    int       `json:"payer_total,omitempty"`
   //退款给用户的金额,不包含所有优惠券金额
   Payer_refund   int       `json:"payer_refund,omitempty"`
}
//微信退款订单信息
type RefundOrderInfoCB struct {
   //服务商户号(普通商户)
   Mchid                 string `json:"mchid"`
   //服务商户号(服务商)
   Sp_mchid           string `json:"sp_mchid"`
   //子商户的商户号(服务商)
   Sub_mchid          string `json:"sub_mchid"`
   //微信支付订单号
   Transaction_id         string `json:"transaction_id"`
   //商户系统内部订单号
   Out_trade_no       string `json:"out_trade_no"`
   //微信支付退款单号
   Refund_id          string `json:"refund_id"`
   //商户系统内部的退款单号
   Out_refund_no      string `json:"out_refund_no"`
   //退款状态,SUCCESS:退款成功 CLOSE:退款关闭 ABNORMAL:退款异常
   Refund_status      string `json:"refund_status"`
   //退款成功时间
   Success_time           string `json:"success_time"`
   //退款入账账户
   User_received_account  string `json:"user_received_account"`
   //订单金额信息
   Amount        RefundOrderAmountCB `json:"amount"`
}

接下来看看一个退款通知处理的示例代码:

func HandlerRefundCB(w http.ResponseWriter, r *http.Request) {
var ret_info RefundOrderInfoCB
body, err := ioutil.ReadAll(r.Body)
if err != nil {
   wxpay4go.HttpCallBackReturn(w, 500,"FAIL", "FAIL")
   return
}
if len(body) < 1 {
   wxpay4go.HttpCallBackReturn(w, 500,"FAIL", "FAIL")
   return
}
//读取签名验证所需的参数
var sing_param WxSignParam
err = sing_param.InitFromRequest(r, string(body))
if err != nil {
   wxpay4go.HttpCallBackReturn(w, 500,"FAIL", "FAIL")
   return
}
//获取平台证书,并进行签名验证
plat_certificate := GetPlatCertificate(ent, sing_param.CertSerial)
err = ResponseValidate(&sing_param, plat_certificate);
if err != nil {
   wxpay4go.HttpCallBackReturn(w, 500,"FAIL", "FAIL")
   return
}
//body数据解析
var ent_cb WeixinPayNotice
if err = json.Unmarshal(body, &ent_cb); err != nil {
   wxpay4go.HttpCallBackReturn(w, 500,"FAIL", "FAIL")
   return
}
//数据解密
decryptBytes, err := DecryptAES256GCM(
   ent.MchAPIKey,
   ent_cb.Resource.AssociatedData,
   ent_cb.Resource.Nonce,
   ent_cb.Resource.Ciphertext)
if err != nil {
   wxpay4go.HttpCallBackReturn(w, 500,"FAIL", "FAIL")
   return
}
//订单数据解析
err = json.Unmarshal([]byte(decryptBytes), &ret_info)
if err != nil {
   wxpay4go.HttpCallBackReturn(w, 500,"FAIL", "FAIL")
   return
}
//其他业务逻辑开始
//..........................
//其他业务逻辑结束
wxpay4go.HttpCallBackReturn(w, 200, "SUCCESS", "SUCCESS")
}

13.3退款查询

退款通知HTTP应答码为200且返回状态码为SUCCESS才会当做商户接收成功。如果微信收到的应答不符合规范或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。如果在所有通知频率后没有收到微信侧回调。商户应调用退款查询接口确认退款状态。
退款有一定延时,建议在提交退款申请后1分钟发起退款状态查询,一般来说零钱支付的退款5分钟内到账,银行卡支付的退款1-3个工作日到账。
微信支付为直连商户与服务商提供了不同的退款查询接口(接口的地址与参数都不相同),接下来分别介绍两种模式下的退款查询接口的使用方式。
1)服务商模式
接口的格式为:
https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/{out_refund_no}?sub_mchid={sub_mchid}
接口中的请求参数说明如下:

  • out_refund_no:商户退款单号
  • sub_mchid: 服务商商户号
    2)直连商户模式
    接口的格式为:
    https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/{out_refund_no}
    接口中的请求参数说明如下:
  • out_refund_no:商户退款单号

两种查询方式返回结果相同,返回结果的数据结构如下所示:

参数名 变量 描述
微信支付退款单号 refund_id 微信支付退款单号
商户退款单号 out_refund_no 商户系统内部的退款单号
微信支付订单号 transaction_id 微信支付交易订单号
商户订单号 out_trade_no 原支付交易对应的商户订单号
退款渠道 channel 枚举值:ORIGINAL:原路退款BALANCE:退回到余额OTHER_BALANCE:原账户异常退到其他余额账户OTHER_BANKCARD:原银行卡异常退到其他银行卡
退款入账账户 user_received_account 取当前退款单的退款入账方
退款成功时间 success_time 退款成功时间,当退款状态为退款成功时有返回。
退款创建时间 create_time 退款受理时间
退款状态 status 枚举值:SUCCESS:退款成功CLOSED:退款关闭PROCESSING:退款处理中ABNORMAL:退款异常
资金账户 funds_account 退款所使用资金对应的资金账户类型
金额信息 amount 金额详细信息
优惠退款信息 promotion_detail 优惠退款信息

以下是退款查询的服务商模式的代码以及直连商户模式的代码:文章来源地址https://www.toymoban.com/news/detail-500734.html

//查询单笔退款(服务商模式)
func queryRefundOrderX(ent *MchParam, out_refund_no string, mchid string) (RefundOrderInfo, error) {
   var ret_info RefundOrderInfo
   url := fmt.Sprintf("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/%s?sub_mchid=%s", out_refund_no, mchid)
   result, err := WxPayGetV3(ent, url)
   if err != nil {
      fmt.Println(err)
      return ret_info, err
   }
   err = json.Unmarshal([]byte(result), &ret_info)
   if err != nil {
      fmt.Println(err)
      return ret_info, err
   }

   return ret_info, nil
}
//查询单笔退款(直连商户模式)
func queryRefundOrder(ent *MchParam, out_refund_no string, mchid string) (RefundOrderInfo, error) {
   var ret_info RefundOrderInfo
   url := fmt.Sprintf("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/%s", out_refund_no)
   result, err := WxPayGetV3(ent, url)
   if err != nil {
      fmt.Println(err)
      return ret_info, err
   }
   err = json.Unmarshal([]byte(result), &ret_info)
   if err != nil {
      fmt.Println(err)
      return ret_info, err
   }

   return ret_info, nil
}

到了这里,关于微信小程序开发实战11_4 微信支付退款流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【小程序】零基础微信小程序开发+实战项目

    如何拥有一款属于你自己的小程序,惊喜就在下面! 目前,小程序行业已经成为互联网营销的热门黑马之一,依托于各大流量平台,小程序行业具有天然的用户基础和得天独厚的资源优势,凭借其方便快捷的操作以及简单通俗的模式,仅短短一年的时间,就迎来了爆发性的增

    2024年02月11日
    浏览(36)
  • 微信小程序开发入门与实战 ①(初始微信小程序)

    @作者 : SYFStrive   @博客首页 : HomePage 📜: 微信小程序 📌: 个人社区(欢迎大佬们加入) 👉: 社区链接🔗 📌: 觉得文章不错可以点点关注 👉: 微信小程序专栏🔗 💃: 感谢支持,学累了可以先看小段由小胖给大家带来的街舞😀 🔗: 阅读文章 👉 微信小程序 (🔥)

    2024年02月09日
    浏览(98)
  • 微信小程序开发实战9_2 小程序页面转发

    小程序页面转发是小程序分享的一个重要方式,在设计小程序应用时就需要考虑那些页面需要实现转发功能,以及页面的转发参数。本节介绍如何进行小程序页面的分享,并介绍如何获取小程序卡片的分享票据。 9.2.1小程序页面转发 微信小程序提供了页面的转发的功能,用户

    2024年02月16日
    浏览(33)
  • 微信小程序实战:智能水印相机小程序开发附源码

    一款智能水印相机,拍照自动添加时间、地点、经纬度等水印文字,可用于工作考勤、学习打卡、工作取证等,支持自定义内容以及给现有照片添加水印。无需安装,无需注册,即开即用。 主要是通过canvas给图片上添加上时间水印地点信息。首先通过官方API(chooseLocation)获取

    2024年02月09日
    浏览(42)
  • Taro 小程序开发大型实战(七):尝鲜微信小程序云(下篇)

    欢迎继续阅读《Taro 小程序开发大型实战》系列,前情回顾: 熟悉的 React,熟悉的 Hooks:我们用 React 和 Hooks 实现了一个非常简单的添加帖子的原型 多页面跳转和 Taro UI 组件库:我们用 Taro 自带的路由功能实现了多页面跳转,并用 Taro UI 组件库升级了应用界面 实现微信和支付

    2024年03月10日
    浏览(39)
  • (后续更新)【微信小程序】毕业设计 租房小程序开发实战,零基础开发房屋租赁系统小程序

    大家好,我是子木。 以前没接触过小程序,刚好毕业设计选题选到了小程序,有前端基础,于是在提交完开题后开始自学小程序(云开发),属于边学边开发的那种。缝缝补补,最终耗时1个多月写完了我的课题。 这段时间刚写完论文比较闲,所以来记录一下自己的开发过程

    2024年02月11日
    浏览(47)
  • 支付宝小程序开发踩坑笔记(支付宝、学习强国小程序)

    1、接口请求安卓端回调 success ,IOS 端回调 fail 原因: dataType 设置不对,默认是 json 格式,对返回数据会进行 json 解析,如果解析失败,就会回调 fail 。加密传输一般是 text 格式。 2、input 禁止输入空格 input 、 textarea 组件默认不会双向绑定,需要借助 setData 进行中转。 如果

    2024年01月25日
    浏览(35)
  • uniapp(微信小程序/支付宝小程序) - 最新解决canavs绘制海报、二维码图片等不显示问题,在uniapp小程序开发中使用canavs制作base64图片在真机运行时空白不显示(详细解决方法)

    在uniapp微信小程序 | uniapp支付宝小程序中,详解canavs技术绘制图像后在真实手机上运行不显示的问题,解决uniapp安卓苹果ios运行小程序后二维码/海报无法加载和展示,完美解决兼容问题、图片太大画不出来、加载失败等。支持保存到相册中或长按保存。 很多教程都无效,本

    2024年04月25日
    浏览(38)
  • 抖音小程序支付开发流程和实现

    第一步:在字节小程序开发者平台注册账号 第二步:创建应用完善资料 第三步:在功能管理--支付 中申请相对应的担保支付(微信,支付宝,抖音支付) 还需要后端同学配一下这个 这步完成了就到代码开发环节了 第四步 按照开发文档开发 开发文档地址:https://microapp.byt

    2024年02月13日
    浏览(31)
  • 【微信支付】springboot-java接入微信支付-JSAPI支付/查单/退款/发送红包(三)---退款

    微信支付开发文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/create.html 退款与查单的请求头类似,但是查单是GET请求,所以在构造签名的时候相对简单些,但是退款请求中有请求参数,在构造签名时,需要将请求体添加到请求头参数中。 1、构造请求参数 查看微信支付开

    2024年01月19日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包