123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- /**
- * 支付宝相关函数
- */
- 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;
|