美文网首页
微信小程序:微信支付

微信小程序:微信支付

作者: 我的小小笔尖 | 来源:发表于2021-10-17 23:03 被阅读0次

    前提:有一个企业认证的小程序

    开通微信支付的步骤:

    1. 开通微信支付
      按页面指引,提交营业执照、身份证等信息,然后等待审核通过即可。
      https://pay.weixin.qq.com/static/applyment_guide/applyment_detail_miniapp.shtml

    微信扫码开通,该微信号作为超级管理员将接收开户信息及日常重要管理信息,并可进行资金操作,需确定该微信号为商户法定代表人或负责人再进行操作。

    1. 关联商户号和申请接入微信支付
      审核通过,登录公众平台,点击“微信支付-商户号管理”,查看相关商户号信息,确认授权申请。
      点击“微信支付-接入微信支付”,申请接入
      https://mp.weixin.qq.com/

    2. 账号管理-分配开发账号(如果是超级管理员自己开放,则不需要分配???)
      https://pay.weixin.qq.com/

    3. 开发工具-云开发-设置-其他设置
      添加商户号

    4. 微信支付平台,产品中心-我的产品,进行确认授权
      https://pay.weixin.qq.com

    微信支付代码实现-主要逻辑:

    step1. 用户点击支付按钮
    step2. 小程序弹出付款二维码
    step3. 存储订单信息status=0,待支付
    step4. 用户扫码
    step5. 用户支付
    step6. 调用回调函数,设置status=1,支付成功
    step7. 用户点击完成
    step8. 跳转到订单成功页面

    微信支付代码实现-次要逻辑:

    1. 用户未扫码或扫码后未支付,此时订单已创建,可以在订单列表页面查看该订单,支持再次支付,或一定时间后自动关闭待支付的订单
    2. 用户支付后未点击完成,那么点击完成后才能处理的逻辑不会执行,需要通过定时器触发已支付订单的处理逻辑

    附云函数实现微信支付的代码(主要逻辑):

    page.js

      // 开通会员(step1. 用户点击了支付按钮)
      onBuyMemberships: util.throttleFunc(function(e) {
        // 提示:执行中
        wx.showLoading({
          title: '执行中',
          mask: true,
        })
        // 定义参数
        let newDate = new Date()
        let money = parseInt(e.currentTarget.dataset.money) //* 100 // 总金额(单位:分),注意是int型
        let body = e.currentTarget.dataset.body // 商品描述
        let timeStr = util.formatTime2(newDate) // 年月日时分秒,长度14位
        let nonceStr = Math.random().toString(36).substr(2,9).toUpperCase() + Math.random().toString(36).substr(2,9).toUpperCase() // 随机字符串,长度18
        let outTradeNo = timeStr + nonceStr // 商户订单号,长度32
        let spbillCreateIp = this.data.terminalIp // 终端IP
        let timestart = timeStr // 交易起始时间,长度14位
        let orderInfo = {
          money: money,
          body: body,
          nonceStr: nonceStr,
          outTradeNo: outTradeNo,
          spbillCreateIp: spbillCreateIp,
          timestart: timestart,
        }
        console.log('orderInfo', orderInfo)
        // 调用微信支付云函数下单
        this.placeAnOrder(orderInfo)
      }, 3000), // 节流,3秒内重复点击无效
      
      // 调用微信支付云函数下单
      placeAnOrder(orderInfo) {
        var that = this
        wx.cloud.callFunction({
          name: 'wechatcloudpay',
          data: {
            action: 'placeAnOrder',
            orderInfo: orderInfo,
          },
          success: res => {
            console.warn('[云函数] [wechatcloudpay] placeAnOrder 调用成功:', res)
            let returnCode = res.result.returnCode // 通信标识
            if(returnCode == 'SUCCESS') {
              let resultCode = res.result.resultCode // 是否成功
              console.log('resultCode', resultCode)
              if(resultCode == 'SUCCESS') {
                const payment = res.result.payment
                // 唤起二维码支付页面(发起微信支付)
                wx.requestPayment({
                  ...payment,
                  success (res) {
                    // 用户点击了支付成功界面中的“完成”按钮,才会执行下面的代码
                    console.log('支付成功', res)
                    // 跳转到订单成功页面
                  },
                  fail (err) {
                    // 用户扫码后点击了左上角“x”关闭支付,则会执行下面的代码
                    console.error('支付失败', err)
                    // 跳转到订单失败页面
                  }
                })
              }
            }else {
              /**
               * returnMsg:
               * --参数格式校验错误,没有将'总金额'转为int型
               * --受理关系不存在,没有在'微信支付商家助手'的'模板消息'中确认
               */
              let returnMsg = res.result.returnMsg
              wx.showToast({
                icon: 'none',
                title: returnMsg,
                duration: 3000,
              })
            }
          },
          fail: err => {
            console.error('[云函数] [wechatcloudpay] placeAnOrder 调用失败:', err)
          },
          complete: res => {
            // 隐藏提示:执行中
            wx.hideLoading({
              success: (res) => {},
            })
          }
        })
      },
      
      // 获取终端ip
      getTerminalIp() {
        var that = this
        let url = 'https://pv.sohu.com/cityjson?ie=utf-8'
        let terminalIp = '127.0.0.1'
        wx.request({
          url: url,
          success(res) {
            // console.log('res', res)
            let start = res.data.indexOf('{')
            let stop = res.data.lastIndexOf('}') + 1
            let cityjson = res.data.substring(start, stop) // {"cip": "49.67.182.147", "cid": "320000", "cname": "江苏省"}
            if(res.errMsg == "request:ok") {
              cityjson = JSON.parse(cityjson)
              terminalIp = cityjson.cip
            }
          },
          complete() {
            that.setData({
              terminalIp: terminalIp
            })
          }
        })
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        // 设置导航栏背景色
        wx.setNavigationBarColor({
          backgroundColor: '#4752A4',
          frontColor: '#ffffff',
        })
        // 获取本地用户信息
        this.getLocalUserInfo() 
        // 获取终端ip
        this.getTerminalIp()
      },
    

    云函数实现微信支付

    // 云函数入口函数
    exports.main = async (event, context) => {
      const wxContext = cloud.getWXContext()
      // console.log('event', event)
      
      switch (event.action) {
        // 下单
        case 'placeAnOrder': {
          return placeAnOrder(event, wxContext)
        }
      }
    
      // 下单
      async function placeAnOrder(event, wxContext) {
        try {  
          // 生成支付交易单,小程序云函数调用免填属性:mch_id、appid、sign、sign_type
          const res = await cloud.cloudPay.unifiedOrder({
            "body" : event.orderInfo.body, // 商品描述 String(128)
            "nonceStr": event.orderInfo.nonceStr, // 随机字符串 String(32)
            "outTradeNo" : event.orderInfo.outTradeNo, // 商户订单号 String(32)
            "spbillCreateIp" : event.orderInfo.spbillCreateIp, // 终端IP String(64)
            "subMchId" : mchId, // 子商户号 String(32)
            "totalFee" : event.orderInfo.money, // 总金额 Int
            "tradeType": 'JSAPI', // String(16) 小程序取值如下:JSAPI
            "openid": wxContext.OPENID, // 用户标识, trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
            "subOpenid": wxContext.OPENID, // 用户子标识,trade_type=JSAPI,此参数必传,用户在子商户appid下的唯一标识
            "timeStart": event.orderInfo.timeStart, // 交易起始时间 String(14),订单生成时间,格式为yyyyMMddHHmmss
            "envId": envId, // envId 和 functionName 用来设置接收支付后的异步通知回调的云函数
            "functionName": "wechatcloudpaycallback", // 用户支付成功就会调用该回调函数(不需要点击支付成功页面的完成按钮)
          })
          // 记录预支付交易单信息
          db.collection('orderInfo').add({
            data: {
              _openid: wxContext.OPENID,
              outTradeNo: event.orderInfo.outTradeNo, // 订单号
              totalFee: event.orderInfo.money, // 总金额
              orderInfo: event.orderInfo, // 订单信息
              result: res, // 生成交易订单的返回结果
              status: 0,
              createTime: Date.now()
            }
          })
          // 返回
          return res
        } catch (e) {
          console.error(e)
        }
      }
    }
    

    云函数实现的回调函数

    // 云函数入口函数
    exports.main = async (event, context) => {
      try {
        console.log('event', event)
        const wxContext = cloud.getWXContext()
        let resultCode = event.resultCode
        let transactionId = event.transactionId
        let outTradeNo = event.outTradeNo
        let status = resultCode === 'SUCCESS' ? 1 : -1 // 0:新建订单,1:支付成功,-1:支付失败
        const res = await db.collection('orderInfo').where({
          outTradeNo: outTradeNo
        })
        .update({
          data: {
            status: status, // 更新状态
            event: event,
            transactionId: transactionId,
            updateTime: Date.now(),
          }
        })
        return {
          errcode: 0, // 注意:一定要返回errcode,否则回调函数会多次调用
          msg: 'wechatcloudpaycallback:ok',
        }
      } catch (e) {
        console.error(e)
      }
    }
    

    注意点:

    1. 总金额的单位是分,总金额只能是int型,字符串型的话会报错:参数格式校验错误
    2. 回调函数最后要返回{errcode:0},否则会重复调用回调函数

    微信官网文档及视频
    https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/wechatpay/wechatpay.html
    https://developers.weixin.qq.com/community/business/doc/000c82ce840420b2483b556f25e40d

    相关文章

      网友评论

          本文标题:微信小程序:微信支付

          本文链接:https://www.haomeiwen.com/subject/mnzvoltx.html