node.js实现微信分销,支持unicloud云开发

305 阅读1分钟

注意,先需要添加为分账方才可以,否则会直接分账失败,默认需要在根目录项添加微信支付的cert文件------------------------------------------------

'use strict';
const fs = require('fs');

const path = require('path')

const crypto = require('crypto')

// 商户id
const mch_id = '商户id'
// x小程序appid
const appid = 'x小程序appid'
// 商户secrect
const key = '商户secrect'


// randomStr
// 生成随机字符串
function randomStr(len = 24) {
	const str =
		'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
	let result = '';
	for (let i = 0; i < len; i++) {
		result += str[Math.floor(Math.random() * str.length)];
	}
	return result;
}

// 签名
// mchKey是商户secrect,否则签名不通过
function signFun(data, mchKey, signType = 'MD5') {
	const keys = [];
	for (const key in data) {
		if (data[key] !== undefined) {
			keys.push(key);
		}
	}
	// 字典排序=>key=value
	const stringA = keys
		.sort()
		.map(key => `${key}=${decodeURIComponent(data[key])}`)
		.join('&');
	// 拼接商户key
	const stringSignTemp = stringA + '&key=' + mchKey;
	// 加密
	let hash;
	if (signType === 'MD5') {
		hash = crypto.createHash('md5').update(stringSignTemp);
	} else {
		hash = crypto.createHmac('sha256', mchKey).update(stringSignTemp, 'utf8');
	}

	const paySign = hash.digest('hex').toUpperCase();
	return paySign;
}



exports.main = async (event, context) => {
	
	// 添加为分账方
	if (event.action === 'addFZUser') {
		
		let openid = event.openid
		
		const nonce_str = randomStr()
		
		let receiver = {
			"account": openid,
			"amount": 1,
			"relation_type": "USER",
			"type": "PERSONAL_OPENID"
		}
		receiver = JSON.stringify(receiver)
		
		// 这一块的参数官网文档上有详细的说明
		const params = {
			appid,
			mch_id,
			nonce_str,
			receiver: `${receiver}`,
			sign_type: 'HMAC-SHA256'
		}
		
		// 签名方式必须是HMAC-SHA256
		const sign = signFun(params, key, 'HMAC-SHA256')
		
		// xmlString
		const formData = `<xml>
		  <appid>${appid}</appid>
		  <mch_id>${mch_id}</mch_id>
		  <nonce_str>${nonce_str}</nonce_str> 
		  <sign>${sign}</sign>
		  <sign_type>HMAC-SHA256</sign_type>
		  <receiver>${params.receiver}</receiver>
		 </xml>`
		
		const res = await uniCloud.httpclient.request(
			"https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver", {
				method: "POST",
				data: formData,
				dataType: 'json'
			}
		)
		
		return res
	}
	
	// 分账,注意分账的对方账号需要先添加为分账方
	if (event.action === 'addFZ') {
		
		let { transaction_id, userList } = event
		
		// // 微信支付订单号 transaction_id ,注意不是商户的
		// account 用户的openid
		// amount int类型的 ,数量为分
		// 注意,T+7的商户的话,需要等7天,T+1一般一分钟后就可以
		const nonce_str = randomStr()
		
		// 订单号
		const out_order_no = 'P20150806125346'
		
		let receivers = []
		
		for (let i = 0;i < userList.length;i++) {
			let obj = {
				"account": userList[i].account,
				"amount": userList[i].amount,
				"description": "商品购买分账",
				"type": "PERSONAL_OPENID"
			}
			receivers.push(obj)
		}
		
		
		receivers = JSON.stringify(receivers)
		
		// 这一块的参数官网文档上有详细的说明
		const params = {
			appid,
			mch_id,
			nonce_str,
			out_order_no,
			receivers: `${receivers}`,
			sign_type: 'HMAC-SHA256',
			transaction_id,
		}
		
		// 签名方式必须是HMAC-SHA256
		const sign = signFun(params, key, 'HMAC-SHA256')
		
		// xmlString
		const formData = `<xml>
		  <appid>${appid}</appid>
		  <mch_id>${mch_id}</mch_id>
		  <nonce_str>${nonce_str}</nonce_str> 
		  <out_order_no>${out_order_no}</out_order_no>
		  <transaction_id>${transaction_id}</transaction_id>
		  <sign>${sign}</sign>
		  <sign_type>HMAC-SHA256</sign_type>
		  <receivers>${params.receivers}</receivers>
		 </xml>`
		
		const res = await uniCloud.httpclient.request(
			"https://api.mch.weixin.qq.com/secapi/pay/profitsharing", {
				// 需要使用证书apiclient_cert
				cert: fs.readFileSync(path.join(__dirname, './cert/apiclient_cert.pem')),
				// 需要使用证书apiclient_key
				key: fs.readFileSync(path.join(__dirname, './cert/apiclient_key.pem')),
				method: "POST",
				data: formData,
				dataType: 'json'
			}
		)
		
		return res
	}

	
};

```