小程序云开发支付功能

服务端

进入云开发

新建云函数pay

编写后端代码index.js

这里用到第三方库wx-js-utils

const cloud = require('wx-server-sdk');
const {
  WXPay,
  WXPayUtil
} = require('wx-js-utils');

cloud.init();


const appId = 'wx****************';           // 小程序appid
const mchId = '152*******';                   // 商户号
const key = '****************************';   // 商户密钥
const timeout = 10000;                        // 超时时间

let wxpay = new WXPay({
  appId,
  mchId,
  key,
  timeout: 10000,
  signType: 'MD5',
  useSandbox: false       // 不使用沙箱环境
});

exports.main = async(event, context) => {
  const curTime = Date.now();
  const tradeNo = `${event.userInfo.openId.substr(-5)}-${curTime}`; // 生成订单号
  const body = '测试订单';   // 订单商品名称
  const spbill_create_ip = '127.0.0.1';   // 发起支付的IP
  const notify_url = 'http://www.qq.com'; // 回调地址
  const total_fee = event.price * 100;    // 支付金额,单位为分
  const time_stamp = '' + Math.ceil(Date.now() / 1000);
  const out_trade_no = `${tradeNo}`;
  let orderParam = {
    body,
    spbill_create_ip,
    notify_url,
    out_trade_no,
    total_fee,
    openid: event.userInfo.openId,
    trade_type: 'JSAPI',
    timeStamp: time_stamp,
  };
  const {
    return_code,
    result_code,
    ...restData
  } = await wxpay.unifiedOrder(orderParam); // 统一下单
  if (return_code === 'SUCCESS' && result_code === 'SUCCESS') {
    const {
      prepay_id,
      nonce_str
    } = restData;
    const sign = WXPayUtil.generateSignature({
      appId,
      nonceStr: nonce_str,
      package: `prepay_id=${prepay_id}`,
      signType: 'MD5',
      timeStamp: time_stamp
    }, key); // 签名
    return {
      code: 0,
      data: {
        out_trade_no,
        time_stamp,
        ...restData,
        sign
      }
    }
  }
  return {
    code: -1
  }
};
复制代码

小程序

app.js

App({
  onLaunch() {
    wx.cloud.init({
      traceUser: true,
    });
  }
});
复制代码

index.wxml

<view class='container'>
  <input class='ipt' value='{{price}}' bindinput='onInput' type='digit' />
  <button class='btn-pay' bindtap='pay'>Paybutton>
view>
复制代码

index.wxss

.container {
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh;
  justify-content: center;
  align-items: center;
}

.ipt {
  border-bottom: 1px solid #f1f2f3;
  text-align: center;
  font-size: 50rpx;
  font-weight: bold;
  width: 220rpx;
  color: #17233d;
}

.btn-pay {
  margin-top: 100rpx;
  padding: 14rpx 100rpx;
  line-height: 1.5em;
  font-size: 36rpx;
  background: #5cadff;
  color: #fff;
}

.btn-pay::after {
  border: 0;
}
复制代码

index.js

Page({
  data: {
    price: 0.01
  },

  onInput(event) {
    this.setData({ price: event.detail.value });
  },

  pay() {
    const price = parseFloat(this.data.price).toFixed(2);
    wx.showLoading({
      title: ''
    });
    wx.cloud.callFunction({
      name: 'pay',    // 调用pay函数
      data: { price }, // 支付金额
      success: (res) => {
        wx.hideLoading();
        const { result } = res;
        const { code, data } = result;
        if (code !== 0) {
          wx.showModal({
            title: '提示',
            content: '支付失败',
            showCancel: false
          });
          return;
        }
        console.log(data);
        wx.requestPayment({
          timeStamp: data.time_stamp,
          nonceStr: data.nonce_str,
          package: `prepay_id=${data.prepay_id}`,
          signType: 'MD5',
          paySign: data.sign,
          success: () => {
            wx.showToast({title: '支付成功'});
          }
        });
      },
      fail: (res) => {
        wx.hideLoading();
        console.log('FAIL');
        console.log(res);
      }
    });
  }
});
复制代码

最终效果

转载于:https://juejin.im/post/5c876108e51d45543d2836e4

你可能感兴趣的:(后端)