NGTools/uni_modules/uni-pay/uniCloud/cloudfunctions/uni-pay-co/libs/alipay.js

182 lines
4.7 KiB
JavaScript
Raw Normal View History

/**
* 支付宝相关函数
*/
const common = require('./common');
const crypto = require('crypto');
const certutil = require('./certutil');
const fs = require("fs");
const ALIPAY_ALGORITHM_MAPPING = {
RSA: 'RSA-SHA1',
RSA2: 'RSA-SHA256'
}
var alipay = {
/**
* 获取openid
*/
async getOpenid(data) {
let {
config={},
code,
} = data;
if (!config.appId) throw new Error("uni-pay配置alipay.mp节点下的appId不能为空");
if (!config.privateKey) throw new Error("uni-pay配置alipay.mp节点下的privateKey不能为空");
let timestamp = common.timeFormat(new Date(), "yyyy-MM-dd hh:mm:ss");
let method = "alipay.system.oauth.token";
let params = {
timestamp,
code,
grant_type: "authorization_code"
};
let signData = this._getSign(method, params, config);
// 格式化url和请求参数
const { url, execParams } = this._formatUrl(signData);
let res = await uniCloud.httpclient.request(url, {
method: 'POST',
data: execParams,
dataType: 'text',
});
const result = JSON.parse(res.data)
let response = result.alipay_system_oauth_token_response;
if (res.status === 200 && response && response.user_id) {
return {
errCode: 0,
errMsg: 'ok',
openid: response.user_id,
user_id: response.user_id,
}
} else {
return {
errCode: -1,
errMsg: result.error_response ? result.error_response.sub_msg : "alipay获取openid失败"+JSON.stringify(result)
}
}
},
/**
* 签名
* @param {String} method 方法名
* @param {Object} params 参数
* @param {Object} config 配置
*/
_getSign(method, params, config) {
let signParams = Object.assign({
method,
app_id: config.appId,
charset: config.charset || "utf-8",
version: config.version || "1.0",
sign_type: config.signType || "RSA2",
}, params);
let {
alipayPublicCertContent,
alipayRootCertContent,
appCertContent,
alipayPublicCertPath,
alipayRootCertPath,
appCertPath,
appCertSn,
alipayRootCertSn
} = config;
if (!alipayPublicCertContent && alipayPublicCertPath) {
alipayPublicCertContent = fs.readFileSync(alipayPublicCertPath);
}
if (!alipayRootCertContent && alipayRootCertPath) {
alipayRootCertContent = fs.readFileSync(alipayRootCertPath);
}
if (!appCertContent && appCertPath) {
appCertContent = fs.readFileSync(appCertPath);
}
if (!appCertSn && appCertContent) {
appCertSn = certutil.alipay.getSN(appCertContent, false);
}
if (!alipayRootCertSn && alipayRootCertContent) {
alipayRootCertSn = certutil.alipay.getSN(alipayRootCertContent, true);
}
if (!appCertSn && appCertContent) {
appCertSn = certutil.alipay.getSN(appCertContent, false);
}
if (!alipayRootCertSn && alipayRootCertContent) {
alipayRootCertSn = certutil.alipay.getSN(alipayRootCertContent, true);
}
if (appCertSn && alipayRootCertSn) {
signParams = Object.assign({
app_cert_sn: appCertSn,
alipay_root_cert_sn: alipayRootCertSn,
}, signParams);
}
const bizContent = params.biz_content;
if (bizContent) {
signParams.biz_content = JSON.stringify(bizContent);
}
// 排序
const decamelizeParams = this._sortObj(signParams);
// 拼接url参数
let signStr = this._objectToUrl(decamelizeParams);
let keyType = config.keyType || 'PKCS8';
const privateKeyType = keyType === 'PKCS8' ? 'PRIVATE KEY' : 'RSA PRIVATE KEY'
let privateKey = this._formatKey(config.privateKey, privateKeyType);
// 计算签名
const sign = crypto.createSign(ALIPAY_ALGORITHM_MAPPING[signParams.sign_type])
.update(signStr, 'utf8').sign(privateKey, 'base64');
return Object.assign(decamelizeParams, { sign });
},
_formatKey(key, type) {
return `-----BEGIN ${type}-----\n${key}\n-----END ${type}-----`
},
_sortObj(params) {
let keysArr = Object.keys(params).sort();
let sortObj = {};
for (let i in keysArr) {
sortObj[keysArr[i]] = (params[keysArr[i]]);
}
return sortObj;
},
_objectToUrl(obj) {
let str = "";
for (let key in obj) {
if (obj[key]) {
str += `&${key}=${obj[key]}`;
}
}
if (str) str = str.substring(1);
return str;
},
_formatUrl(params, url = "https://openapi.alipay.com/gateway.do") {
let requestUrl = url;
// 需要放在 url 中的参数列表
const urlArgs = [
'app_id',
'method',
'format',
'charset',
'sign_type',
'sign',
'timestamp',
'version',
'notify_url',
'return_url',
'auth_token',
'app_auth_token'
]
for (const key in params) {
if (urlArgs.indexOf(key) > -1) {
const val = encodeURIComponent(params[key])
requestUrl = `${requestUrl}${requestUrl.includes('?') ? '&' : '?'
}${key}=${val}`
// 删除 postData 中对应的数据
delete params[key]
}
}
return { execParams: params, url: requestUrl }
}
};
module.exports = alipay;