前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【愚公系列】2022年10月 微信小程序-电商项目-微信支付后端功能实现(node版)

【愚公系列】2022年10月 微信小程序-电商项目-微信支付后端功能实现(node版)

作者头像
愚公搬代码
发布2022-10-31 10:30:11
8830
发布2022-10-31 10:30:11
举报
文章被收录于专栏:历史专栏

文章目录


前言

微信支付是腾讯集团旗下的第三方支付平台,致力于为用户和企业提供安全、便捷、专业的在线支付服务。以“微信支付,不止支付”为核心理念,为个人用户创造了多种便民服务和应用场景。微信支付为各类企业以及小微商户提供专业的收款能力,运营能力,资金结算解决方案,以及安全保障。用户可以使用微信支付来购物、吃饭、旅游、就医、交水电费等。企业、商品、门店、用户已经通过微信连在了一起,让智慧生活,变成了现实。

小程序实现微信支付主要有两种方式:

  • 小程序内部API,要求商户开通了小程序支付功能
  • 第三方网站

一、微信支付后端功能实现(node版)

1.相关文档

微信支付开发文档V2、V3选择: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/api.shtml

在这里插入图片描述
在这里插入图片描述

微信小程序调用微信支付接口需要5个参数都是来源于后端接口生成的

代码语言:javascript
复制
wx.requestPayment({
	timeStamp: payArgs.timeStamp,
	nonceStr: payArgs.nonceStr,
	package: payArgs. package,
	signType:'MD5',
	paySign: payArgs. paySign
})

小程序ID(appld) 时间戳(timeStamp)当前的时间,从1970年1月1日00:00:00至今的秒数 随机串(nonceStr) 一个32位的随机字符串 数据包(package) prepay_id=wx2017033010242291fcfe0db70013231072 签名方式(signType)默认为MD5,也有其它支持的类型 签名字符串(paySign)

2.项目配置

node安装相关依赖

router .js

代码语言:javascript
复制
npm install koa3-wechat
npm install short-uuid
npm i raw-body
npm i redis
npm i babel-runtime@6.26.0

在路由模块中引入支付模块

代码语言:javascript
复制
const Pay = require("./pay")
const Router = require("@koa/router")
const router = new Router({
  prefix: '/user'
});

Pay.init(router)

module.exports = router

pay.js

代码语言:javascript
复制
const { wepay: WechatPay } = require('koa3-wechat');
const short = require('short-uuid');
// const fs = require('fs');
const wepay = require("../lib/wepay")
const Order = require("../models/order-model")
const wepay2 = require('../lib/wepay2')

function init(router) {
  // post /user/my/order
  // 下新定单,准备支付
  router.post('/my/order', async ctx => {
    let { uid: userId, openId } = ctx.user
    let { totalFee, addressId, addressDesc, goodsCartsIds, goodsNameDesc } = ctx.request.body
    // 为测试方便,所有金额支付数均为1分
    totalFee = 1
    let payState = 0
    // 依照Order模型接收参数
    let outTradeNo = `${new Date().getFullYear()}${short().new()}`
    // 获取订单的预支付信息
    var trade = {
      body: goodsNameDesc.substr(0, 127), //最长127字节
      attach: '支付测试', //最长127字节
      out_trade_no: outTradeNo, //
      total_fee: totalFee, //以分为单位,货币的最小金额
      trade_type: 'JSAPI',//NATIVE
      spbill_create_ip: ctx.request.ip, //ctx.request.ip
      openid: openId
    };
    var params = await wepay.getBrandWCPayRequestParams(trade);
    let err = '', res
    if (params && params.package && params.paySign) {
      // 创建记录
      res = await Order.create({
        userId,
        outTradeNo,
        payState,
        totalFee,
        addressId,
        addressDesc,
        goodsCartsIds,
        goodsNameDesc
      })
      if (!res) err = 'db create error'
    } else {
      err = 'error! return null!'
      console.log(err);
    }
    ctx.status = 200
    ctx.body = {
      code: 200,
      msg: !err ? 'ok' : '',
      data: {
        res,
        params
      }
    }
  })

  // post /user/my/order2
  // 使用weixin-pay实现的接口,测试通过
  router.post('/my/order2', async ctx => {
    let { uid: userId, openId } = ctx.user
    let { totalFee, addressId, addressDesc, goodsCartsIds, goodsNameDesc } = ctx.request.body
    // 为测试方便,所有金额支付数均为1分
    totalFee = 1
    let payState = 0
    // 依照Order模型接收参数
    let outTradeNo = `${new Date().getFullYear()}${short().new()}`
    console.log('outTradeNo', outTradeNo);
    // 获取订单的预支付信息
    var trade = {
      body: goodsNameDesc.substr(0, 127), //最长127字节
      out_trade_no: outTradeNo, //
      total_fee: totalFee, //以分为单位,货币的最小金额
      spbill_create_ip: ctx.request.ip, //ctx.request.ip
      notify_url: 'https://rxyk.cn/apis/pay_notify', // 支付成功通知地址
      trade_type: 'JSAPI',
      openid: openId
    };
    let params = await (() => {
      return new Promise((resolve, reject) => {
        wepay2.getBrandWCPayRequestParams(trade, (err, result) => {
          console.log(err, result);
          if (err) reject(err)
          else resolve(result)
        });
      })
    })()
    let err = '', res
    if (params && params.package && params.paySign) {
      // 创建记录
      res = await Order.create({
        userId,
        outTradeNo,
        payState,
        totalFee,
        addressId,
        addressDesc,
        goodsCartsIds,
        goodsNameDesc
      })
      if (!res) err = 'db create error'
    } else {
      err = 'error! getBrandWCPayRequestParams() return null!'
      console.log(err);
    }
    ctx.status = 200
    ctx.body = {
      code: 200,
      msg: !err ? 'ok' : '',
      data: {
        res,
        params
      }
    }
  })

}

module.exports = {
  init
}

order.js

代码语言:javascript
复制
const DataTypes = require('sequelize')
const db = require("./mysql-db")

module.exports = db.define("order",{
  id:{
    type:DataTypes.INTEGER(11),
    allowNull:false,
    primaryKey:true,
    autoIncrement:true
  },
  userId:{
    type:DataTypes.INTEGER(20),
    allowNull:false
  },
  outTradeNo:{// 微信商号单号
    type:DataTypes.STRING(50),
    allowNull:false
  },
  transactionId:{// 微信交易单号
    type:DataTypes.STRING(50),
    allowNull:true //允许为空
  },
  payState:{// 支付订单的状态,0=未支付,1=已支付,2=取消或其它
    type:DataTypes.INTEGER,
    defaultValue:0,
    allowNull: false
  },
  totalFee:{//总价,单位分
    type:DataTypes.INTEGER(11),
    allowNull:false
  },
  addressId:{//收货地址id
    type:DataTypes.INTEGER(20),
    allowNull:false
  },
  addressDesc:{//收货地址总描述
    type:DataTypes.TEXT('tiny'),//最大长度255个字节
    allowNull:false
  },
  goodsCartsIds:{//购买车商品ids
    type:DataTypes.JSON,
    allowNull:false
  },
  goodsNameDesc:{//商品名称描述
    type:DataTypes.TEXT('tiny'),//最大长度255个字节
    allowNull:false
  }
},{
  indexes: [{
    unique: true,// 唯一索引
    fields: ['out_trade_no']
  }],
  underscored: true,
  freezeTableName:true,
  timestamps:true
});

wepay.js

代码语言:javascript
复制
const {wepay:WechatPay} = require('koa3-wechat');
// const short = require('short-uuid');
const fs = require('fs');

 // 普通商户的参数
 let config = {
  appId: '自己的APPID', // 小程序APPID
  mchId: '自己的商户id',//商户id
  notifyUrl: '自己的通知地址', // 支付成功通知地址
  partnerKey: '自己的api key', // 微信商户平台的api key,在pay.weixin.qq.com设置
  pfx: fs.readFileSync(__dirname + '/apiclient_cert.p12'),
  // passphrase: '预留信息',// 添加了无法退款
}

// 初始化
let wepay = new WechatPay(config);

module.exports = wepay

wepay2.js

代码语言:javascript
复制
const WXPay = require('weixin-pay')
// const short = require('short-uuid')
const fs = require('fs')

const wxpay2 = WXPay({
  appid: "自己的APPID",//小程序APPID
  mch_id: '自己的商户id',//商户id
  notify_url: '自己的通知地址', // 支付成功通知地址
  partnerKey: '自己的api key', // 微信商户平台的api key,在 API secret,非小程序 secret
  pfx: fs.readFileSync(__dirname + '/apiclient_cert.p12'), 
  passphrase: '预留信息'
});

module.exports = wxpay2
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 前言
  • 一、微信支付后端功能实现(node版)
    • 1.相关文档
      • 2.项目配置
      相关产品与服务
      云开发 CloudBase
      云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档