UNPKG

node-easywechat

Version:

EasyWechat SDK for Node.js (NOT OFFICIAL)

188 lines (187 loc) 7.55 kB
'use strict'; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; const fs_1 = __importDefault(require("fs")); const merge_1 = __importDefault(require("merge")); const Utils_1 = require("../Core/Support/Utils"); const HttpClient_1 = __importDefault(require("../Core/HttpClient/HttpClient")); const HttpClientMethodsMixin_1 = __importDefault(require("../Core/HttpClient/Mixins/HttpClientMethodsMixin")); const PresetMixin_1 = __importDefault(require("../Core/HttpClient/Mixins/PresetMixin")); const Signature_1 = __importDefault(require("./Signature")); const LegacySignature_1 = __importDefault(require("./LegacySignature")); const form_data_1 = __importDefault(require("form-data")); class Client { constructor(merchant, client, defaultOptions = {}) { var _a; this.merchant = merchant; this.throw = true; this.client = null; this.defaultOptions = { baseURL: 'https://api.mch.weixin.qq.com', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, }; this.V3_URI_PREFIXES = [ '/v3/', '/sandbox/v3/', '/hk/v3/', '/global/v3/', ]; this.throw = !!((_a = defaultOptions['throw']) !== null && _a !== void 0 ? _a : true); this.defaultOptions = merge_1.default.recursive(true, this.defaultOptions, defaultOptions); this.client = client || HttpClient_1.default.create(); } getInstance() { return this.client.getInstance(); } setInstance(instance) { this.client.setInstance(instance); return this; } setLogger(logger) { this.client.setLogger(logger); return this; } request(method, url, payload = {}) { return __awaiter(this, void 0, void 0, function* () { if (!payload.headers) payload.headers = {}; if (!payload.headers['user-agent'] && !payload.headers['User-Agent']) { payload.headers['user-agent'] = (0, Utils_1.createUserAgent)(); } if (this.isV3Request(url)) { payload.headers['authorization'] = this.createSignature(method, url, payload); } else { if (payload.xml) { if (Array.isArray(payload.xml)) { payload.xml = (0, Utils_1.buildXml)(this.attachLegacySignature(payload.xml)); } if (typeof payload.xml !== 'string') { throw new Error('The `xml` option must be a string or object.'); } payload.data = payload.xml; delete payload.xml; } if (payload.data && typeof payload.data === 'object') { payload.data = (0, Utils_1.buildXml)(this.attachLegacySignature(payload.data)); } if (!payload.headers['content-type'] && !payload.headers['Content-Type']) { payload.headers['content-type'] = 'text/xml'; } } if (this.prependData && Object.keys(this.prependData).length > 0) { payload.data = Object.assign(Object.assign({}, this.prependData), payload.data); } if (this.prependHeaders && Object.keys(this.prependHeaders).length > 0) { payload.headers = Object.assign(Object.assign({}, this.prependHeaders), payload.headers); } return this.client.request(method, (0, Utils_1.ltrim)(url, '\\/+'), payload); }); } /** * 文件上传 * @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter2_1_1.shtml * @param uri 接口地址 * @param file 文件路径或文件可读流 * @param meta 文件元信息,包含 filename 和 sha256 两个字段 * @param filename 文件名,必须以 .jpg、.bmp、.png 为后缀 * @returns */ uploadMedia(uri, file, meta = null, filename = null) { return __awaiter(this, void 0, void 0, function* () { if (typeof file === 'string') { file = fs_1.default.createReadStream(file); } if (!meta) { meta = { filename: filename !== null && filename !== void 0 ? filename : 'file.jpg', sha256: yield (0, Utils_1.createFileHash)(file, 'sha256'), }; } let metaJson = JSON.stringify(meta); let formData = new form_data_1.default(); formData.append('file', file); formData.append('meta', metaJson, { contentType: 'application/json', }); return this.client.request('POST', (0, Utils_1.ltrim)(uri, '\\/+'), { formData, headers: { 'authorization': this.createSignature('POST', uri, { data: metaJson, }), } }); }); } /** * 判断是否是V3请求 * @param url 请求地址 * @returns */ isV3Request(url) { let pathname = url; if (url.startsWith('https://') || url.startsWith('http://')) { let urlObj = new URL(url); pathname = urlObj.pathname; } for (let i = 0; i < this.V3_URI_PREFIXES.length; i++) { if (pathname.startsWith(this.V3_URI_PREFIXES[i])) { return true; } } return false; } /** * 创建签名(V3) * @param method 请求方式 * @param url 请求地址 * @param payload 请求载荷 * @returns */ createSignature(method, url, payload) { return (new Signature_1.default(this.merchant)).createHeader(method, url, payload); } /** * 创建签名(V2) * @param body 请求参数 * @returns */ attachLegacySignature(body) { return (new LegacySignature_1.default(this.merchant)).sign(body); } /** * 预设置mch_id(因nodejs不支持魔术方法,只好预先设置几个常用的方法) * @param new_mch_id * @returns */ withMchId(new_mch_id = null) { this.with('mch_id', new_mch_id); return this; } /** * 预设置mch_id别名(因nodejs不支持魔术方法,只好预先设置几个常用的方法) * @param new_alias * @returns */ withMchIdAs(new_alias = null) { this.with(new_alias, this.presets['mch_id']); return this; } } ; (0, Utils_1.applyMixins)(Client, [HttpClientMethodsMixin_1.default, PresetMixin_1.default]); module.exports = Client;