【愚公系列】2022年10月 微信小程序-电商项目-微信支付小程序确认支付结果和退款功能实现(node)

举报
愚公搬代码 发表于 2022/10/31 19:34:16 2022/10/31
【摘要】 前言一、订单退款的定义订单退款包括未发货订单退款和已发货订单退货退款。未发货订单退款未发货订单退款指的是会员下单后,在商家发货前申请的订单退款的行为。退货退款退货退款指的是会员下单后,商家已经发货,因各种原因导致会员要求退货退款的行为。二、订单退款的流程未发货订单退款1) 会员下单后,在未发货前申请退款;2) 经商家审核后,同意会员的退款申请;3) 平台收到会员申请后,在24小时内完成退款...

前言

一、订单退款的定义

订单退款包括未发货订单退款和已发货订单退货退款。
  1. 未发货订单退款

未发货订单退款指的是会员下单后,在商家发货前申请的订单退款的行为。

  1. 退货退款

    退货退款指的是会员下单后,商家已经发货,因各种原因导致会员要求退货退款的行为。

二、订单退款的流程

  1. 未发货订单退款

    1) 会员下单后,在未发货前申请退款;
    
    2) 经商家审核后,同意会员的退款申请;
    
    3) 平台收到会员申请后,在24小时内完成退款申请的处理;
    
    4) 平台审核同意退款后,最终到账时间以银行卡入账时间为准,如遇银行通道障碍,可能会有延迟;拒绝退款时,平台将附上拒绝退款理由;
    
    5) 退款时,会员对应的退款订单的收款手续费金额在商家的结算款中扣除,相应赠送的兑换券一并收回。
    
  2. 退货退款

    1) 会员支付货款并收到商品后,因各种原因要求退货退款,会员在平台上发起申请;
    
    2) 商家收到会员退还的商品后,审核是否同意退货退款。如果非产品质量问题,商品发货运费及退货运费由买家承担,否则全部由商家承担。商家承担的起初的发货运费包含在订单款项中将在退款中一并退回;对于退货运费的结算与平台无关。
    
    3) 商家通过会员退货退款申请后,平台收到会员的退款申请,平台将在24小时内完成退款申请的处理;
    
    4) 平台审核同意退款后,最终到账时间以银行卡入账时间为准,如遇银行通道障碍,可能会有延迟;拒绝退款时,平台将附上拒绝退款理由;
    
    5)退款时,会员对应的退款订单的收款手续费金额在商家的结算款中扣除,相应赠送的兑换券一并收回。
    

微信小程序在支付成功后会给注册的接口发消息来通知订单支付成功的状态,下面是微信和接口通信的数据格式:
在这里插入图片描述

微信通知频率为:
15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h-总计24h4m。

一、微信支付小程序确认支付结果和退款功能实现

1.确认支付结果

const getRawBody = require( 'raw-body')
// all /apis/pay_notify
// 本地测试:http://localhost:3000/apis/pay_notify?test=true
// 微信支付成功通知接口
defaultRouter.all('/apis/pay_notify', async ctx=>{
  const testInLocal = !!ctx.request.query.test
  // console.log('testInLocal',testInLocal);
  var rawText = await getRawBody(ctx.req, {
      encoding: 'utf-8'
  });
  if (testInLocal){
    rawText = `<xml><appid><![CDATA[小程序appid]]></appid>
    <attach><![CDATA[支付测试]]></attach>
    <bank_type><![CDATA[OTHERS]]></bank_type>
    <cash_fee><![CDATA[1]]></cash_fee>
    <fee_type><![CDATA[CNY]]></fee_type>
    <is_subscribe><![CDATA[Y]]></is_subscribe>
    <mch_id><![CDATA[1410138302]]></mch_id>
    <nonce_str><![CDATA[1eTp670VVN04aRlpGBpHH0fKbEUgqMwK]]></nonce_str>
    <openid><![CDATA[o-hrq0EVYOTJHX9MWqk-LF-_KL0o]]></openid>
    <out_trade_no><![CDATA[2020vEPk8sib229F1rDkRgGhPh]]></out_trade_no>
    <result_code><![CDATA[SUCCESS]]></result_code>
    <return_code><![CDATA[SUCCESS]]></return_code>
    <sign><![CDATA[92AB862CF14B22193DDE9D86DC2D3701]]></sign>
    <time_end><![CDATA[20201109140319]]></time_end>
    <total_fee>1</total_fee>
    <trade_type><![CDATA[JSAPI]]></trade_type>
    <transaction_id><![CDATA[4200000728202011097892062758]]></transaction_id>
    </xml>`
  }
  
  try {
    var retobj = await wepay.notifyParse(rawText);
    console.log ("payNotify parsed:", retobj);
    /* retobj示例
    {
      appid: 'wxc3db312ddf9bcb01',
      attach: '附加信息',
      bank_type: 'OTHERS',
      cash_fee: '1',
      fee_type: 'CNY',
      is_subscribe: 'Y',
      mch_id: '1410138302',
      nonce_str: '6ma2Wk08YBGkvAaFAtSYP4el6wDBB4hd',
      openid: 'o-hrq0EVYOTJHX9MWqk-LF-_KL0o',
      out_trade_no: '20201aB6PprMLnwu7ev6aBgSZzw',
      result_code: 'SUCCESS',
      return_code: 'SUCCESS',
      sign: 'BDCFDAD06CCF5254C88F29D69B871FAE',
      time_end: '20201031173616',
      total_fee: '1',
      trade_type: 'JSAPI',
      transaction_id: '4200000727202010317871404188'
    }
    // return_code SUCCESS/FAIL此字段是通信标识,非交易标识
    // 业务结果	result_code SUCCESS/FAIL
    */
    // emitter.wechatSendOut({cmd:'payNotify', payload: retobj});
    if (retobj){
      // 商户单号
      let outTradeNo = retobj.out_trade_no
      let resultCode = retobj.result_code
      let payState = 0
      if (resultCode === 'SUCCESS'){
        // 支付成功,设置订单状态
        console.log("SUCCESS",resultCode, outTradeNo);
        payState = 1
      }else{
        payState = 2
      }
      // 存储交易单号备用
      let transactionId = retobj.transaction_id
      //  成功与失败都要同步订单状态
      let res = await Order.update({
        payState,
        transactionId
      },{
        where:{
          outTradeNo
        }
      })
      console.log(`支付状态更新${res[0] > 0?'成功':'失败'}`)
    }
    var xml = wepay.notifyResult({return_code: 'SUCCESS', return_msg: 'OK'});
    console.log("payNotify process ok: ", xml);
    ctx.body = xml;
  } catch (e) {
    console.log ("payNotify error: ", e);
    var xml = wepay.notifyResult({return_code: 'FAILURE', return_msg: 'FAIL'});
    ctx.body = xml;
  }
})

2.退款功能实现

// 这个接口不好使,使用koa3-weixin
// http://localhost:3000/apis/pay_refund?no=20201aB6PprMLnwu7ev6aBgSZzw
defaultRouter.get("/apis/pay_refund",async ctx=>{
  let {no:out_trade_no} = ctx.request.query
  debug('pay_refund....')
  // 尝试退款
  var retobj = await wepay.refund({ 
    out_trade_no,
    out_refund_no: short().new(),
    total_fee: 1,
    refund_fee: 1
   });
  ctx.status = 200
  ctx.body = retobj;
})

// 这个可以,使用weixin-pay
defaultRouter.get("/apis/pay_refund2",async ctx=>{
  let {no:out_trade_no} = ctx.request.query
  var data = {
      out_trade_no,
      out_refund_no: short().new(),
      total_fee: 1,
      refund_fee: 1
  };
  // 尝试退款,封装原方法
  let res = await (()=>{
    return new Promise((resolve, reject)=>{
      wepay2.refund(data,(err, result) => {
        if (err) reject(err)
        else resolve(result)
      });
    })
  })()
  console.log('res',res);
  ctx.status = 200
  ctx.body = res;
})
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。