微信小程序 支付简单实例及注意事项

发布时间 - 2026-01-10 22:21:39    点击率:

微信小程序 支付

微信小程序的支付和微信公众号的支付是类似的,对比起来还比公众号支付简单了一些,我们只需要调用微信的统一下单接口获取prepay_id之后我们在调用微信的支付即可。

今天我们来封装一般node的支付接口!!!

首先调用统一下单接口我们需要知道一些信息

var bookingNo = 'davdian' + this.createNonceStr() + this.createTimeStamp()
  var deferred = Q.defer() 
  var appid = config.appId 
  var nonce_str = this.createNonceStr() 
  var timeStamp = this.createTimeStamp() 
  var url = "https://api.mch.weixin.qq.com/pay/unifiedorder" 
  var formData = "<xml>" 
  formData += "<appid>" + appid + "</appid>" //appid 
  formData += "<attach>" + attach + "</attach>" //附加数据 
  formData += "<body>" + body + "</body>" 
  formData += "<mch_id>" + mch_id + "</mch_id>" //商户号 
  formData += "<nonce_str>" + nonce_str + "</nonce_str>" //随机字符串,不长于32位。 
  formData += "<notify_url>" + notify_url + "</notify_url>" 
  formData += "<openid>" + openid + "</openid>" 
  formData += "<out_trade_no>" + bookingNo + "</out_trade_no>" 
  formData += "<spbill_create_ip>61.50.221.43</spbill_create_ip>" 
  formData += "<total_fee>" + total_fee + "</total_fee>" 
  formData += "<trade_type>JSAPI</trade_type>" 
  formData += "<sign>" + this.paysignjsapi(appid, attach, body, mch_id, nonce_str, notify_url, openid, bookingNo, '61.50.221.43', total_fee, 'JSAPI') + "</sign>" 
  formData += "</xml>" 
  var self = this
  request({ 
   url: url, 
   method: 'POST', 
   body: formData 
  }, function(err, response, body) { 
   if (!err && response.statusCode == 200) { 
    var prepay_id = self.getXMLNodeValue('prepay_id', body.toString("utf-8")) 
    var tmp = prepay_id.split('[') 
    var tmp1 = tmp[2].split(']') 
    //签名 
    var _paySignjs = self.paysignjs(appid, nonce_str, 'prepay_id=' + tmp1[0], 'MD5', timeStamp) 
    var args = { 
     appId: appid, 
     timeStamp: timeStamp, 
     nonceStr: nonce_str, 
     signType: "MD5", 
     package: tmp1[0], 
     paySign: _paySignjs 
    }
    deferred.resolve(args) 
   } else { 
    console.log(body) 
   } 
  }) 
  return deferred.promise 

这个是一个统一下单接口的代码,我们需要appid小程序公众号id,mch_id商户号id,openid小程序的唯一标实,key支付用的密码,剩下的参数都是订单的信息和价格之类的,本人require进q模块使用promise,这个因人而异,可以根据自己需要来。我们需要请求https://api.mch.weixin.qq.com/pay/unifiedorder接口

注意:这里我们传递的formdata是一个xml而不是json

然后我们需要签名方法,这里我们需要封装两个方法,一个是签名方法调用统一下单接口会用到,另一个是调用小程序支付用到

统一下单接口sign:

var ret = { 
   appid: appid, 
   attach: attach, 
   body: body, 
   mch_id: mch_id, 
   nonce_str: nonce_str, 
   notify_url: notify_url, 
   openid: openid, 
   out_trade_no: out_trade_no, 
   spbill_create_ip: spbill_create_ip, 
   total_fee: total_fee, 
   trade_type: trade_type 
  } 
  var string = this.raw(ret) 
  string = string + '&key=' + key 
  var crypto = require('crypto') 
  var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex') 
  return sign.toUpperCase() 

支付sign:

var ret = { 
    appId: appid, 
    nonceStr: nonceStr, 
    package: package, 
    signType: signType, 
    timeStamp: timeStamp 
  } 
  var string = this.raw(ret) 
  string = string + '&key=' + key 
  var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex') 
  return sign.toUpperCase() 

注意加密的时候我们获取的是string而不是一个json,所以我们需要吧json转换成string,代码如下:

var keys = Object.keys(args) 
  keys = keys.sort() 
  var newArgs = {} 
  keys.forEach(function(key) { 
    newArgs[key] = args[key] 
  }) 
  var string = '' 
  for (var k in newArgs) { 
    string += '&' + k + '=' + newArgs[k] 
  } 
  string = string.substr(1) 
  return string 

统一下单接口返回的是带有prepay_id的xml,所以我们需要一个方法进行解析,代码如下:

var tmp = xml.split("<" + node_name + ">") 
  var _tmp = tmp[1].split("</" + node_name + ">") 
  return _tmp[0] 

最后我们只需要把这些连接到一起就是可以获取所有微信支付所需参数,代码如下:

//微信小程序支付封装,暂支持md5加密,不支持sha1
/**
***create order by jianchep 2016/11/22   
 **/
var config = require('../config/weapp.js')
var Q = require("q") 
var request = require("request") 
var crypto = require('crypto') 
var ejs = require('ejs')
var fs = require('fs') 
var key = config.key
module.exports = {
 // 获取prepay_id
 getXMLNodeValue: function(node_name, xml) { 
  var tmp = xml.split("<" + node_name + ">") 
  var _tmp = tmp[1].split("</" + node_name + ">") 
  return _tmp[0] 
 },
 // object-->string
 raw: function(args) { 
  var keys = Object.keys(args) 
  keys = keys.sort() 
  var newArgs = {} 
  keys.forEach(function(key) { 
    newArgs[key] = args[key] 
  }) 
  var string = '' 
  for (var k in newArgs) { 
    string += '&' + k + '=' + newArgs[k] 
  } 
  string = string.substr(1) 
  return string 
 }, 
  // 随机字符串产生函数 
 createNonceStr: function() { 
   return Math.random().toString(36).substr(2, 15) 
 }, 
 // 时间戳产生函数 
 createTimeStamp: function() { 
   return parseInt(new Date().getTime() / 1000) + '' 
 },
 // 支付md5加密获取sign
 paysignjs: function(appid, nonceStr, package, signType, timeStamp) { 
  var ret = { 
    appId: appid, 
    nonceStr: nonceStr, 
    package: package, 
    signType: signType, 
    timeStamp: timeStamp 
  } 
  var string = this.raw(ret) 
  string = string + '&key=' + key 
  var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex') 
  return sign.toUpperCase() 
 },
 // 统一下单接口加密获取sign
 paysignjsapi: function(appid, attach, body, mch_id, nonce_str, notify_url, openid, out_trade_no, spbill_create_ip, total_fee, trade_type) { 
  var ret = { 
   appid: appid, 
   attach: attach, 
   body: body, 
   mch_id: mch_id, 
   nonce_str: nonce_str, 
   notify_url: notify_url, 
   openid: openid, 
   out_trade_no: out_trade_no, 
   spbill_create_ip: spbill_create_ip, 
   total_fee: total_fee, 
   trade_type: trade_type 
  } 
  var string = this.raw(ret) 
  string = string + '&key=' + key 
  var crypto = require('crypto') 
  var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex') 
  return sign.toUpperCase() 
 },
 // 下单接口
 order: function(attach, body, mch_id, openid, total_fee, notify_url) {
  var bookingNo = 'davdian' + this.createNonceStr() + this.createTimeStamp()
  var deferred = Q.defer() 
  var appid = config.appId 
  var nonce_str = this.createNonceStr() 
  var timeStamp = this.createTimeStamp() 
  var url = "https://api.mch.weixin.qq.com/pay/unifiedorder" 
  var formData = "<xml>" 
  formData += "<appid>" + appid + "</appid>" //appid 
  formData += "<attach>" + attach + "</attach>" //附加数据 
  formData += "<body>" + body + "</body>" 
  formData += "<mch_id>" + mch_id + "</mch_id>" //商户号 
  formData += "<nonce_str>" + nonce_str + "</nonce_str>" //随机字符串,不长于32位。 
  formData += "<notify_url>" + notify_url + "</notify_url>" 
  formData += "<openid>" + openid + "</openid>" 
  formData += "<out_trade_no>" + bookingNo + "</out_trade_no>" 
  formData += "<spbill_create_ip>61.50.221.43</spbill_create_ip>" 
  formData += "<total_fee>" + total_fee + "</total_fee>" 
  formData += "<trade_type>JSAPI</trade_type>" 
  formData += "<sign>" + this.paysignjsapi(appid, attach, body, mch_id, nonce_str, notify_url, openid, bookingNo, '61.50.221.43', total_fee, 'JSAPI') + "</sign>" 
  formData += "</xml>" 
  var self = this
  request({ 
   url: url, 
   method: 'POST', 
   body: formData 
  }, function(err, response, body) { 
   if (!err && response.statusCode == 200) { 
    var prepay_id = self.getXMLNodeValue('prepay_id', body.toString("utf-8")) 
    var tmp = prepay_id.split('[') 
    var tmp1 = tmp[2].split(']') 
    //签名 
    var _paySignjs = self.paysignjs(appid, nonce_str, 'prepay_id=' + tmp1[0], 'MD5', timeStamp) 
    var args = { 
     appId: appid, 
     timeStamp: timeStamp, 
     nonceStr: nonce_str, 
     signType: "MD5", 
     package: tmp1[0], 
     paySign: _paySignjs 
    }
    deferred.resolve(args) 
   } else { 
    console.log(body) 
   } 
  }) 
  return deferred.promise 
 }
}

之后我们封装下单接口:

unifiedorder: function (req, res) {
  var body = "测试支付" 
  var openid = "openid"
  var total_fee = 1
  var notify_url = "http://localhost/notify"
  var mch_id = config.shopId
  var attach = "测试" 
  wxpay.order(attach, body, mch_id, openid, total_fee, notify_url)
   .then(function(data){ 
    console.log('data--->', data, 123123)
    res.json(data)
   }) 
 },

然后我们只需要在小程序里面调用这个接口,就会获取到所有的支付需要信息,再掉微信支付即可。

这里说几个小程序支付的坑:

1.统一下单接口是xml(这个不只是小程序,公众号也是),返回值也是xml格式需要自己获取prepay_id,

2.签名算法要带上key,最后要转换成大些

3.微信支付的sign算法也要带上appid(这个不科学,深坑)

4.签名算法一定不要用json拼接key

感谢阅读,希望能帮助到大家,谢谢大家对本站 的支持!


# 微信小程序  # 支付  # 支付详解及实例  # 支付注意事项  # 微信小程序支付及退款流程详解  # 微信小程序 支付功能开发错误总结  # 微信小程序调用微信支付接口的实现方法  # 微信小程序微信支付接入开发实例详解  # 微信小程序 在线支付功能的实现  # 微信小程序进行微信支付的步骤昂述  # 详解微信小程序支付流程与梳理  # 微信小程序中实现微信支付完整步骤  # 下单  # 是一个  # 的是  # 商户  # 只需  # 深坑  # 都是  # 几个  # 就会  # 也要  # 要在  # 所需  # 要把  # 而不  # 希望能  # 因人而异  # 不支持  # 只需要  # 谢谢大家  # 可以根据 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: JavaScript模板引擎Template.js使用详解  如何在万网利用已有域名快速建站?  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  Android使用GridView实现日历的简单功能  免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?  佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】  青岛网站建设如何选择本地服务器?  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  如何确认建站备案号应放置的具体位置?  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  如何快速生成可下载的建站源码工具?  购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?  Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门  Laravel如何实现事件和监听器?(Event & Listener实战)  微信推文制作网站有哪些,怎么做微信推文,急?  做企业网站制作流程,企业网站制作基本流程有哪些?  怎样使用JSON进行数据交换_它有什么限制  今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  JS中对数组元素进行增删改移的方法总结  Laravel怎么导出Excel文件_Laravel Excel插件使用教程  百度输入法ai组件怎么删除 百度输入法ai组件移除工具  微信小程序 input输入框控件详解及实例(多种示例)  装修招标网站设计制作流程,装修招标流程?  武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  西安专业网站制作公司有哪些,陕西省建行官方网站?  Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案  千库网官网入口推荐 千库网设计创意平台入口  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  在centOS 7安装mysql 5.7的详细教程  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  高防服务器如何保障网站安全无虞?  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解  香港服务器租用每月最低只需15元?  如何在橙子建站上传落地页?操作指南详解  Laravel如何配置任务调度?(Cron Job示例)  Laravel如何自定义错误页面(404, 500)?(代码示例)  php8.4header发送头信息失败怎么办_php8.4header函数问题解决【解答】  打开php文件提示内存不足_怎么调整php内存限制【解决方案】  如何快速搭建高效服务器建站系统?  Laravel如何使用.env文件管理环境变量?(最佳实践)  如何快速查询域名建站关键信息?  如何快速搭建支持数据库操作的智能建站平台?  Laravel如何实现数据库事务?(DB Facade示例)