首页 > 【全网唯一】全网唯一能够跑通的,跑不通你来找我~用node.js完成微信支付下单功能,且只需要一个文件wxpay.js就解决业务

【全网唯一】全网唯一能够跑通的,跑不通你来找我~用node.js完成微信支付下单功能,且只需要一个文件wxpay.js就解决业务

 

 

先吐为敬!

 

最近心血来潮研究nodejs如何完成微信支付功能,结果网上一搜索,一大堆“代码拷贝党”、“留一手”、“缺斤少两”、“不说人话”、“自己都没跑通还出来发blog”、“各种缺少依赖包”、“各种注释都没有”、“自己都不知道在写什么”的程序大神纷纷为了增加自己博客一个帖子的名额而发布了各种千奇百怪的文章,强哥饱受煎熬,浪费了流量和时间居然没有一个教程能够跑通

叔可忍婶不可忍,我必须要发布一篇真正能够用nodejs跑通微信支付功能的干货文章,由于时间关系,错别字大家就谅解,反正程序能够跑通,跑不通你来找我!!!

注意,前情提示:

本代码基于《Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)》

传送门Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)_你挚爱的强哥❤给你发来1条消息❤-CSDN博客

首先要去package.json加入依赖包

"dependencies": {"crypto": "^1.0.1","express": "^4.16.3","request": "^2.85.0","xmlreader": "^0.2.3"},

在/api/文件夹下面创建wxpay.js 

代码内容

/**做微信支付开发之前一定要修改的配置,各位看官看清楚了◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆*/
const appid = "wx你挚爱的强哥";//公众号开发者ID[必填,公众号后台去拿https://mp.weixin.qq.com/ 开发-基本配置-公众号开发信息-开发者ID(AppID)]
const appsecret = "a071e61你挚爱的强哥9efc7a";//公众号开发者密码[必填,公众号后台去拿https://mp.weixin.qq.com/ 开发-基本配置-公众号开发信息-开发者密码(AppSecret)]
const mchid = "16你挚爱的强哥3";//微信商户号[必填,微信商户平台去拿https://pay.weixin.qq.com/ 个人信息-账号信息-登录账号]
const mchkey = "你挚爱的强哥32位秘钥";//微信支付安全密钥[必填, 在微信商户平台-账户中心-API安全-API密钥-安装操作证书(首次设置才需要)-设置API密钥(注意这个密钥自己保存好勿外传!!!)]
const notify_url = "http://你挚爱的强哥.com";//异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
/**◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆*///下面的代码几乎不用修改----------------------------------------------------------------
//如果运行过程提示你“商户号该产品权限未开通,请前往商户平台>产品中心检查后重试”,请你去这里https://pay.weixin.qq.com/index.php/public/product/detail?pid=32&productType=0开通微信H5支付(这个一般审核要几个工作日,如果你的项目很急,建议早点来开通审核)
const $g = global.SG.$g, fs = global.SG.fs, router = global.SG.router, request = global.SG.request, xmlreader = global.SG.xmlreader;
module.exports = global.SG.router;
/*微信支付干货,微信统一下单帮助文档
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1*/
//强哥为你量身打造的微信支付方法工具包
let sgWxpay = {signType: "MD5",//签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致raw(args) {let keys = Object.keys(args);keys = keys.sort();let newArgs = {};keys.forEach(key => {newArgs[key] = args[key];});let string = "";for (let k in newArgs) {string += "&" + k + "=" + newArgs[k];}string = string.substr(1);return string;},//把金额转为分getmoney(money) {return parseFloat(money) * 100;},// 随机字符串产生函数createNonceStr() {return Math.random().toString(36).substr(2, 15);},// 时间戳产生函数createTimeStamp() {return parseInt(new Date().getTime() / 1000) + "";},//签名加密算法paysignjsapi(appid, body, mch_id, nonce_str, notify_url, out_trade_no, spbill_create_ip, total_fee, trade_type, mchkey) {let ret = {appid: appid,mch_id: mch_id,nonce_str: nonce_str,body: body,notify_url: notify_url,out_trade_no: out_trade_no,spbill_create_ip: spbill_create_ip,total_fee: total_fee,trade_type: trade_type};let string = this.raw(ret);let key = mchkey;string = string + "&key=" + key;return global.SG.crypto.createHash(this.signType).update(string, "utf8").digest("hex").toUpperCase();},//签名加密算法,第二次的签名paysignjsapifinal(appid, mch_id, prepayid, noncestr, timestamp, mchkey) {let ret = {appid: appid,partnerid: mch_id,prepayid: prepayid,package: "Sign=WXPay",noncestr: noncestr,timestamp: timestamp};let string = this.raw(ret), key = mchkey;string = string + "&key=" + key;return global.SG.crypto.createHash(this.signType).update(string, "utf8").digest("hex").toUpperCase();},getXMLNodeValue(xml) {// let tmp = xml.split("<"+node_name+">");// console.log('tmp',tmp);// let _tmp = tmp[1].split("");// console.log('_tmp',_tmp);// return _tmp[0];xmlreader.read(xml, (errors, res) => {if (null !== errors) {console.log(errors);return;}console.log("长度===", res.xml.prepay_id.text().length);let prepay_id = res.xml.prepay_id.text();console.log("解析后的prepay_id==", prepay_id);return prepay_id;});}
};
//微信支付(all方法支持POST、GET、PUT、PATCH、DELETE传参方式)
router.all("/demo/wx/wxpay", (req, res) => {//首先拿到前端传过来的参数let out_trade_no = req.body.out_trade_no || req.query.out_trade_no;//商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一。详见商户订单号let body = req.body.body || req.query.body;//商品简单描述,该字段请按照规范传递,具体请见参数规定https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2let total_fee = req.body.total_fee || req.query.total_fee;//准备付款多少钱呀大哥?金额单位分(但是你的前端请传元为单位,因为这里强哥帮你转成了分)console.log($g.date.nowtime() + "
", `商户系统内部订单号:${out_trade_no}
商品描述:${body}
标价金额:${total_fee}
${appid}
${appsecret}
${mchid}
${mchkey}`);let msg = null;out_trade_no || (msg = "强哥对你说:你为什么不提供商品订单号?");body || (msg = "强哥对你说:你为什么不提供商品描述?");total_fee || (msg = "强哥对你说:你为什么不提供商品订单号?");if (msg) return $g.json.res(req, res, msg, req.body || req.query, false);//首先生成签名signlet mch_id = mchid;let nonce_str = sgWxpay.createNonceStr();let timestamp = sgWxpay.createTimeStamp();total_fee = sgWxpay.getmoney(total_fee);//强哥为你转换为分let spbill_create_ip = req.connection.remoteAddress;let trade_type = "APP";let sign = sgWxpay.paysignjsapi(appid, body, mch_id, nonce_str, notify_url, out_trade_no, spbill_create_ip, total_fee, trade_type, mchkey);// console.log("sign:", sign);//组装xml数据body = "";body += "" + appid + "";//appidbody += "";body += "" + mch_id + "";//商户号body += "" + nonce_str + ""; //随机字符串,不长于32位。body += "" + notify_url + "";body += "" + out_trade_no + "";body += "" + spbill_create_ip + "";body += "" + total_fee + "";body += "" + trade_type + "";body += "" + sign + "";body += "";const url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//下单地址// const url = "https://api2.mch.weixin.qq.com/pay/unifiedorder";//冗灾备用域名,正常使用主域名调用,备域名需有流量,保证业务能实时切换。当域名出现请求超时、读写超时,自动换备域名重试。request.post({url, body}, (err, r, body) => {if (!err && r.statusCode == 200) {console.log("body:", body);xmlreader.read(body.toString("utf-8"), (err, r) => {if (err) return $g.json.res(req, res, "微信下单报错", err, false);let prepay_id = r.xml.prepay_id;if (!prepay_id) return $g.json.res(req, res, r.xml.return_msg.text(), r.xml, false);prepay_id = prepay_id.prepay_id.text();console.log("解析后的prepay_id", prepay_id);let finalsign = sgWxpay.paysignjsapifinal(appid, mch_id, prepay_id, nonce_str, timestamp, mchkey);//将预支付订单和其他信息一起签名后返回给前端$g.json.res(req, res, "微信下单成功", {// mchid: mchid,//商户ID(唤起支付貌似不需要这个)// prepayId: prepay_id,appId: appid,//商户注册具有支付权限的公众号成功后即可获得timeStamp: timestamp,//当前的时间,其他详见时间戳规则https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2nonceStr: nonce_str,//随机字符串,不长于32位。推荐随机数生成算法https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3package: "prepay_id=sgWxPay",//统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***signType: sgWxpay.signType,//签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致paySign: finalsign//签名,详见签名生成算法https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3}, true);});}});
});

在index.js最后一行加入

app.use(API_PATH, require(`.${API_PATH}/demo/wxpay`));//微信支付

运行

node index

 打完收工!

更多相关:

  • 阅读ceph源码过程中需要明确当前操作是由哪个线程发出,此时需要根据线程id来确认线程名称 C++获取线程id是通过系统调用来直接获取 函数描述 头文件: 函数名称:syscall(SYS_gettid) 该函数直接返回了一个pid_t int类型的数字,即为当前线程id 此外函数pthread_s...

  • 面试题 分库分表之后,id 主键如何处理? 面试官心理分析 其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持。所以这都是你实际生产环境中必须考虑的问题。 面试题剖析 基于数据库的实现方案 数据库自增 id 这个就是说你的...

  • ORM操作    单表、一对多表操作 1 from django.db import models 2 3 4 class UserGroup(models.Model): 5 title = models.CharField(max_length=32) 6 7 8 class UserInfo(m...

  • 建立如下表: 建表语句: class表创建语句 create table class(cid int not null auto_increment primary key, caption varchar(32) not null)engine=innodb default charset=utf8;student表创建语句 c...

  • 1 1. 鼠标的哪个按键被点击? 2 3 4