From bd60be61d42af5768ce72485b2eb46f2689fb2d7 Mon Sep 17 00:00:00 2001 From: "Xc@centOs" Date: Wed, 10 Aug 2022 18:48:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAwechatPublic=E5=92=8CwechatWeb?= =?UTF-8?q?=E5=BB=BA=E7=AB=8Bmock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/AmapSDK.d.ts | 8 ++ lib/AmapSDK.js | 22 ++++ lib/WechatSDK.d.ts | 13 ++ lib/WechatSDK.js | 56 +++++++++ lib/index.d.ts | 4 + lib/index.js | 36 ++++++ lib/service/ali/Ali.d.ts | 0 lib/service/ali/Ali.js | 1 + lib/service/amap/Amap.d.ts | 22 ++++ lib/service/amap/Amap.js | 155 +++++++++++++++++++++++ lib/service/wechat/WechatMp.d.ts | 28 +++++ lib/service/wechat/WechatMp.js | 176 +++++++++++++++++++++++++++ lib/service/wechat/WechatPublic.d.ts | 15 +++ lib/service/wechat/WechatPublic.js | 149 +++++++++++++++++++++++ lib/service/wechat/WechatWeb.d.ts | 15 +++ lib/service/wechat/WechatWeb.js | 149 +++++++++++++++++++++++ src/service/wechat/WechatPublic.ts | 17 ++- src/service/wechat/WechatWeb.ts | 13 +- 18 files changed, 871 insertions(+), 8 deletions(-) create mode 100644 lib/AmapSDK.d.ts create mode 100644 lib/AmapSDK.js create mode 100644 lib/WechatSDK.d.ts create mode 100644 lib/WechatSDK.js create mode 100644 lib/index.d.ts create mode 100644 lib/index.js create mode 100644 lib/service/ali/Ali.d.ts create mode 100644 lib/service/ali/Ali.js create mode 100644 lib/service/amap/Amap.d.ts create mode 100644 lib/service/amap/Amap.js create mode 100644 lib/service/wechat/WechatMp.d.ts create mode 100644 lib/service/wechat/WechatMp.js create mode 100644 lib/service/wechat/WechatPublic.d.ts create mode 100644 lib/service/wechat/WechatPublic.js create mode 100644 lib/service/wechat/WechatWeb.d.ts create mode 100644 lib/service/wechat/WechatWeb.js diff --git a/lib/AmapSDK.d.ts b/lib/AmapSDK.d.ts new file mode 100644 index 0000000..cd7817f --- /dev/null +++ b/lib/AmapSDK.d.ts @@ -0,0 +1,8 @@ +import { AmapInstance } from './service/amap/Amap'; +declare class AmapSDK { + webKeyMap: Record; + constructor(); + getInstance(key: string): AmapInstance; +} +declare const SDK: AmapSDK; +export default SDK; diff --git a/lib/AmapSDK.js b/lib/AmapSDK.js new file mode 100644 index 0000000..964cafc --- /dev/null +++ b/lib/AmapSDK.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Amap_1 = require("./service/amap/Amap"); +var AmapSDK = /** @class */ (function () { + function AmapSDK() { + this.webKeyMap = {}; + } + AmapSDK.prototype.getInstance = function (key) { + var _a; + if (this.webKeyMap[key]) { + return this.webKeyMap[key]; + } + var instance = new Amap_1.AmapInstance(key); + Object.assign(this.webKeyMap, (_a = {}, + _a[key] = instance, + _a)); + return instance; + }; + return AmapSDK; +}()); +var SDK = new AmapSDK(); +exports.default = SDK; diff --git a/lib/WechatSDK.d.ts b/lib/WechatSDK.d.ts new file mode 100644 index 0000000..34dd7e3 --- /dev/null +++ b/lib/WechatSDK.d.ts @@ -0,0 +1,13 @@ +import { WechatMpInstance } from './service/wechat/WechatMp'; +import { WechatPublicInstance } from './service/wechat/WechatPublic'; +import { WechatWebInstance } from './service/wechat/WechatWeb'; +declare class WechatSDK { + mpMap: Record; + publicMap: Record; + webMap: Record; + constructor(); + getInstance(appId: string, appSecret: string, type: 'wechatMp' | 'wechatPublic' | 'web'): WechatMpInstance | WechatPublicInstance | WechatWebInstance; +} +declare const SDK: WechatSDK; +export default SDK; +export { WechatMpInstance, WechatWebInstance, WechatPublicInstance }; diff --git a/lib/WechatSDK.js b/lib/WechatSDK.js new file mode 100644 index 0000000..bf55363 --- /dev/null +++ b/lib/WechatSDK.js @@ -0,0 +1,56 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WechatPublicInstance = exports.WechatWebInstance = exports.WechatMpInstance = void 0; +var WechatMp_1 = require("./service/wechat/WechatMp"); +Object.defineProperty(exports, "WechatMpInstance", { enumerable: true, get: function () { return WechatMp_1.WechatMpInstance; } }); +var WechatPublic_1 = require("./service/wechat/WechatPublic"); +Object.defineProperty(exports, "WechatPublicInstance", { enumerable: true, get: function () { return WechatPublic_1.WechatPublicInstance; } }); +var WechatWeb_1 = require("./service/wechat/WechatWeb"); +Object.defineProperty(exports, "WechatWebInstance", { enumerable: true, get: function () { return WechatWeb_1.WechatWebInstance; } }); +var WechatSDK = /** @class */ (function () { + function WechatSDK() { + this.mpMap = {}; + this.publicMap = {}; + this.webMap = {}; + } + WechatSDK.prototype.getInstance = function (appId, appSecret, type) { + var _a, _b, _c; + // type 支持web网站扫码登录 + if (type === 'wechatMp') { + if (this.mpMap[appId]) { + return this.mpMap[appId]; + } + var instance = new WechatMp_1.WechatMpInstance(appId, appSecret); + Object.assign(this.mpMap, (_a = {}, + _a[appId] = instance, + _a)); + return instance; + } + else if (type === 'wechatPublic') { + if (this.publicMap[appId]) { + return this.publicMap[appId]; + } + var instance = new WechatPublic_1.WechatPublicInstance(appId, appSecret); + Object.assign(this.publicMap, (_b = {}, + _b[appId] = instance, + _b)); + return instance; + } + else if (type === 'web') { + if (this.webMap[appId]) { + return this.publicMap[appId]; + } + var instance = new WechatWeb_1.WechatWebInstance(appId, appSecret); + Object.assign(this.webMap, (_c = {}, + _c[appId] = instance, + _c)); + return instance; + } + else { + throw new Error('public not implemented'); + } + }; + return WechatSDK; +}()); +var SDK = new WechatSDK(); +exports.default = SDK; diff --git a/lib/index.d.ts b/lib/index.d.ts new file mode 100644 index 0000000..c4c2cae --- /dev/null +++ b/lib/index.d.ts @@ -0,0 +1,4 @@ +import WechatSDK, { WechatMpInstance, WechatPublicInstance, WechatWebInstance } from './WechatSDK'; +import AmapSDK from './AmapSDK'; +export * from './service/amap/Amap'; +export { WechatSDK, AmapSDK, WechatMpInstance, WechatPublicInstance, WechatWebInstance, }; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..dbc9229 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,36 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WechatWebInstance = exports.WechatPublicInstance = exports.WechatMpInstance = exports.AmapSDK = exports.WechatSDK = void 0; +var WechatSDK_1 = __importStar(require("./WechatSDK")); +exports.WechatSDK = WechatSDK_1.default; +Object.defineProperty(exports, "WechatMpInstance", { enumerable: true, get: function () { return WechatSDK_1.WechatMpInstance; } }); +Object.defineProperty(exports, "WechatPublicInstance", { enumerable: true, get: function () { return WechatSDK_1.WechatPublicInstance; } }); +Object.defineProperty(exports, "WechatWebInstance", { enumerable: true, get: function () { return WechatSDK_1.WechatWebInstance; } }); +var AmapSDK_1 = __importDefault(require("./AmapSDK")); +exports.AmapSDK = AmapSDK_1.default; +__exportStar(require("./service/amap/Amap"), exports); diff --git a/lib/service/ali/Ali.d.ts b/lib/service/ali/Ali.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/lib/service/ali/Ali.js b/lib/service/ali/Ali.js new file mode 100644 index 0000000..3918c74 --- /dev/null +++ b/lib/service/ali/Ali.js @@ -0,0 +1 @@ +"use strict"; diff --git a/lib/service/amap/Amap.d.ts b/lib/service/amap/Amap.d.ts new file mode 100644 index 0000000..e60bc8e --- /dev/null +++ b/lib/service/amap/Amap.d.ts @@ -0,0 +1,22 @@ +export declare class AmapInstance { + key: string; + constructor(key: string); + getDrivingPath(data: { + from: [number, number]; + to: [number, number]; + }): Promise; + regeo(data: { + longitude: number; + latitude: number; + }): Promise; + ipLoc(data: { + ip: string; + }): Promise; + getDistrict(data: { + keywords: string; + subdistrict: string; + }): Promise; + geocode(data: { + address: string; + }): Promise; +} diff --git a/lib/service/amap/Amap.js b/lib/service/amap/Amap.js new file mode 100644 index 0000000..ee7d0c7 --- /dev/null +++ b/lib/service/amap/Amap.js @@ -0,0 +1,155 @@ +"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 __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AmapInstance = void 0; +var AmapInstance = /** @class */ (function () { + function AmapInstance(key) { + this.key = key; + } + AmapInstance.prototype.getDrivingPath = function (data) { + return __awaiter(this, void 0, void 0, function () { + var from, to, url, result, jsonData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + from = data.from, to = data.to; + url = "http://restapi.amap.com/v3/direction/driving?origin=".concat(from[0].toFixed(6), ",").concat(from[1].toFixed(6), "&destination=").concat(to[0].toFixed(6), ",").concat(to[1].toFixed(6), "&strategy=10&key=").concat(this.key); + return [4 /*yield*/, global.fetch(url)]; + case 1: + result = _a.sent(); + return [4 /*yield*/, result.json()]; + case 2: + jsonData = _a.sent(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return [2 /*return*/, Promise.resolve(jsonData)]; + } + }); + }); + }; + AmapInstance.prototype.regeo = function (data) { + return __awaiter(this, void 0, void 0, function () { + var longitude, latitude, result, jsonData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + longitude = data.longitude, latitude = data.latitude; + return [4 /*yield*/, global.fetch("https://restapi.amap.com/v3/geocode/regeo?location=".concat(longitude, ",").concat(latitude, "&key=").concat(this.key))]; + case 1: + result = _a.sent(); + return [4 /*yield*/, result.json()]; + case 2: + jsonData = _a.sent(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return [2 /*return*/, Promise.resolve(jsonData)]; + } + }); + }); + }; + AmapInstance.prototype.ipLoc = function (data) { + return __awaiter(this, void 0, void 0, function () { + var ip, url, result, jsonData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ip = data.ip; + url = "https://restapi.amap.com/v3/ip?key=".concat(this.key, "&ip=").concat(ip); + return [4 /*yield*/, global.fetch(url)]; + case 1: + result = _a.sent(); + return [4 /*yield*/, result.json()]; + case 2: + jsonData = _a.sent(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return [2 /*return*/, Promise.resolve(jsonData)]; + } + }); + }); + }; + AmapInstance.prototype.getDistrict = function (data) { + return __awaiter(this, void 0, void 0, function () { + var keywords, subdistrict, url, result, jsonData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + keywords = data.keywords, subdistrict = data.subdistrict; + url = "https://restapi.amap.com/v3/config/district?keywords=".concat(keywords, "&subdistrict=").concat(subdistrict, "&key=").concat(this.key); + return [4 /*yield*/, global.fetch(url)]; + case 1: + result = _a.sent(); + return [4 /*yield*/, result.json()]; + case 2: + jsonData = _a.sent(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return [2 /*return*/, Promise.resolve(jsonData)]; + } + }); + }); + }; + AmapInstance.prototype.geocode = function (data) { + return __awaiter(this, void 0, void 0, function () { + var address, url, result, jsonData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + address = data.address; + url = "https://restapi.amap.com/v3/geocode/geo?address=".concat(address, "&key=").concat(this.key); + return [4 /*yield*/, global.fetch(url)]; + case 1: + result = _a.sent(); + return [4 /*yield*/, result.json()]; + case 2: + jsonData = _a.sent(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return [2 /*return*/, Promise.resolve(jsonData)]; + } + }); + }); + }; + return AmapInstance; +}()); +exports.AmapInstance = AmapInstance; diff --git a/lib/service/wechat/WechatMp.d.ts b/lib/service/wechat/WechatMp.d.ts new file mode 100644 index 0000000..57027f7 --- /dev/null +++ b/lib/service/wechat/WechatMp.d.ts @@ -0,0 +1,28 @@ +export declare class WechatMpInstance { + appId: string; + appSecret: string; + accessToken?: string; + refreshAccessTokenHandler?: any; + constructor(appId: string, appSecret: string); + private access; + code2Session(code: string): Promise<{ + sessionKey: string; + openId: string; + unionId: string; + }>; + private refreshAccessToken; + decryptData(sessionKey: string, encryptedData: string, iv: string, signature: string): any; + getMpUnlimitWxaCode({ scene, page, envVersion, width, autoColor, lineColor, isHyaline }: { + scene: string; + page: string; + envVersion?: string; + width?: number; + autoColor?: boolean; + lineColor?: { + r: number; + g: number; + b: number; + }; + isHyaline?: true; + }): Promise; +} diff --git a/lib/service/wechat/WechatMp.js b/lib/service/wechat/WechatMp.js new file mode 100644 index 0000000..6154408 --- /dev/null +++ b/lib/service/wechat/WechatMp.js @@ -0,0 +1,176 @@ +"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 __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WechatMpInstance = void 0; +var crypto_1 = __importDefault(require("crypto")); +var buffer_1 = require("buffer"); +var WechatMpInstance = /** @class */ (function () { + function WechatMpInstance(appId, appSecret) { + this.appId = appId; + this.appSecret = appSecret; + this.refreshAccessToken(); + } + WechatMpInstance.prototype.access = function (url, init) { + return __awaiter(this, void 0, void 0, function () { + var response, headers, status, contentType, json, data; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, global.fetch(url, init)]; + case 1: + response = _a.sent(); + headers = response.headers, status = response.status; + if (![200, 201].includes(status)) { + throw new Error("\u5FAE\u4FE1\u670D\u52A1\u5668\u8FD4\u56DE\u4E0D\u6B63\u786E\u5E94\u7B54\uFF1A".concat(status)); + } + contentType = headers['Content-Type'] || headers.get('Content-Type'); + if (!contentType.includes('application/json')) return [3 /*break*/, 3]; + return [4 /*yield*/, response.json()]; + case 2: + json = _a.sent(); + if (typeof json.errcode === 'number' && json.errcode !== 0) { + throw new Error("\u8C03\u7528\u5FAE\u4FE1\u63A5\u53E3\u8FD4\u56DE\u51FA\u9519\uFF0Ccode\u662F".concat(json.errcode, "\uFF0C\u4FE1\u606F\u662F").concat(json.errmsg)); + } + return [2 /*return*/, json]; + case 3: + if (!(contentType.includes('text') + || contentType.includes('xml') + || contentType.includes('html'))) return [3 /*break*/, 5]; + return [4 /*yield*/, response.text()]; + case 4: + data = _a.sent(); + return [2 /*return*/, data]; + case 5: + if (!contentType.includes('application/octet-stream')) return [3 /*break*/, 7]; + return [4 /*yield*/, response.arrayBuffer()]; + case 6: return [2 /*return*/, _a.sent()]; + case 7: return [2 /*return*/, response]; + } + }); + }); + }; + WechatMpInstance.prototype.code2Session = function (code) { + return __awaiter(this, void 0, void 0, function () { + var result, _a, session_key, openid, unionid; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/sns/jscode2session?appid=".concat(this.appId, "&secret=").concat(this.appSecret, "&js_code=").concat(code, "&grant_type=authorization_code"))]; + case 1: + result = _b.sent(); + _a = JSON.parse(result), session_key = _a.session_key, openid = _a.openid, unionid = _a.unionid; + return [2 /*return*/, { + sessionKey: session_key, + openId: openid, + unionId: unionid, + }]; + } + }); + }); + }; + WechatMpInstance.prototype.refreshAccessToken = function () { + return __awaiter(this, void 0, void 0, function () { + var result, access_token, expires_in; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".concat(this.appId, "&secret=").concat(this.appSecret))]; + case 1: + result = _a.sent(); + access_token = result.access_token, expires_in = result.expires_in; + this.accessToken = access_token; + // 生成下次刷新的定时器 + this.refreshAccessTokenHandler = setTimeout(function () { + _this.refreshAccessToken(); + }, (expires_in - 10) * 1000); + return [2 /*return*/]; + } + }); + }); + }; + WechatMpInstance.prototype.decryptData = function (sessionKey, encryptedData, iv, signature) { + var skBuf = buffer_1.Buffer.from(sessionKey, 'base64'); + // const edBuf = Buffer.from(encryptedData, 'base64'); + var ivBuf = buffer_1.Buffer.from(iv, 'base64'); + var decipher = crypto_1.default.createDecipheriv('aes-128-cbc', skBuf, ivBuf); + // 设置自动 padding 为 true,删除填充补位 + decipher.setAutoPadding(true); + var decoded = decipher.update(encryptedData, 'base64', 'utf8'); + decoded += decipher.final('utf8'); + var data = JSON.parse(decoded); + if (data.watermark.appid !== this.appId) { + throw new Error('Illegal Buffer'); + } + return data; + }; + WechatMpInstance.prototype.getMpUnlimitWxaCode = function (_a) { + var scene = _a.scene, page = _a.page, envVersion = _a.envVersion, width = _a.width, autoColor = _a.autoColor, lineColor = _a.lineColor, isHyaline = _a.isHyaline; + return __awaiter(this, void 0, void 0, function () { + var result; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=".concat(this.accessToken), { + method: 'POST', + headers: { + 'Content-type': "application/json", + 'Accept': 'image/jpg', + }, + body: JSON.stringify({ + // access_token: this.accessToken, + scene: scene, + page: page, + env_version: envVersion, + width: width, + auto_color: autoColor, + line_color: lineColor, + is_hyaline: isHyaline, + }) + })]; + case 1: + result = _b.sent(); + return [4 /*yield*/, result.arrayBuffer()]; + case 2: return [2 /*return*/, (_b.sent())]; + } + }); + }); + }; + return WechatMpInstance; +}()); +exports.WechatMpInstance = WechatMpInstance; +; diff --git a/lib/service/wechat/WechatPublic.d.ts b/lib/service/wechat/WechatPublic.d.ts new file mode 100644 index 0000000..cb9e136 --- /dev/null +++ b/lib/service/wechat/WechatPublic.d.ts @@ -0,0 +1,15 @@ +export declare class WechatPublicInstance { + appId: string; + appSecret: string; + accessToken?: string; + refreshAccessTokenHandler?: any; + constructor(appId: string, appSecret: string); + private access; + code2Session(code: string): Promise<{ + sessionKey: string; + openId: string; + unionId: string; + }>; + private refreshAccessToken; + decryptData(sessionKey: string, encryptedData: string, iv: string, signature: string): any; +} diff --git a/lib/service/wechat/WechatPublic.js b/lib/service/wechat/WechatPublic.js new file mode 100644 index 0000000..2a5b940 --- /dev/null +++ b/lib/service/wechat/WechatPublic.js @@ -0,0 +1,149 @@ +"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 __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WechatPublicInstance = void 0; +var crypto_1 = __importDefault(require("crypto")); +var buffer_1 = require("buffer"); +var WechatPublicInstance = /** @class */ (function () { + function WechatPublicInstance(appId, appSecret) { + this.appId = appId; + this.appSecret = appSecret; + this.refreshAccessToken(); + } + WechatPublicInstance.prototype.access = function (url, mockData, init) { + return __awaiter(this, void 0, void 0, function () { + var response, headers, status, contentType, json, data; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (process.env.NODE_ENV === 'development') { + return [2 /*return*/, mockData]; + } + return [4 /*yield*/, global.fetch(url, init)]; + case 1: + response = _a.sent(); + headers = response.headers, status = response.status; + if (![200, 201].includes(status)) { + throw new Error("\u5FAE\u4FE1\u670D\u52A1\u5668\u8FD4\u56DE\u4E0D\u6B63\u786E\u5E94\u7B54\uFF1A".concat(status)); + } + contentType = headers['Content-Type'] || headers.get('Content-Type'); + if (!contentType.includes('application/json')) return [3 /*break*/, 3]; + return [4 /*yield*/, response.json()]; + case 2: + json = _a.sent(); + if (typeof json.errcode === 'number' && json.errcode !== 0) { + throw new Error("\u8C03\u7528\u5FAE\u4FE1\u63A5\u53E3\u8FD4\u56DE\u51FA\u9519\uFF0Ccode\u662F".concat(json.errcode, "\uFF0C\u4FE1\u606F\u662F").concat(json.errmsg)); + } + return [2 /*return*/, json]; + case 3: + if (!(contentType.includes('text') + || contentType.includes('xml') + || contentType.includes('html'))) return [3 /*break*/, 5]; + return [4 /*yield*/, response.text()]; + case 4: + data = _a.sent(); + return [2 /*return*/, data]; + case 5: + if (!contentType.includes('application/octet-stream')) return [3 /*break*/, 7]; + return [4 /*yield*/, response.arrayBuffer()]; + case 6: return [2 /*return*/, _a.sent()]; + case 7: return [2 /*return*/, response]; + } + }); + }); + }; + WechatPublicInstance.prototype.code2Session = function (code) { + return __awaiter(this, void 0, void 0, function () { + var result, _a, session_key, openid, unionid; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/sns/oauth2/access_token?appid=".concat(this.appId, "&secret=").concat(this.appSecret, "&code=").concat(code, "&grant_type=authorization_code"), { session_key: 'aaa', openid: code, unionid: code })]; + case 1: + result = _b.sent(); + _a = typeof result === 'string' ? JSON.parse(result) : result, session_key = _a.session_key, openid = _a.openid, unionid = _a.unionid; + return [2 /*return*/, { + sessionKey: session_key, + openId: openid, + unionId: unionid, + }]; + } + }); + }); + }; + WechatPublicInstance.prototype.refreshAccessToken = function () { + return __awaiter(this, void 0, void 0, function () { + var result, access_token, expires_in; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".concat(this.appId, "&secret=").concat(this.appSecret), { access_token: 'mockToken', expires_in: 3600 * 1000 })]; + case 1: + result = _a.sent(); + access_token = result.access_token, expires_in = result.expires_in; + this.accessToken = access_token; + // 生成下次刷新的定时器 + this.refreshAccessTokenHandler = setTimeout(function () { + _this.refreshAccessToken(); + }, (expires_in - 10) * 1000); + return [2 /*return*/]; + } + }); + }); + }; + WechatPublicInstance.prototype.decryptData = function (sessionKey, encryptedData, iv, signature) { + var skBuf = buffer_1.Buffer.from(sessionKey, 'base64'); + // const edBuf = Buffer.from(encryptedData, 'base64'); + var ivBuf = buffer_1.Buffer.from(iv, 'base64'); + var decipher = crypto_1.default.createDecipheriv('aes-128-cbc', skBuf, ivBuf); + // 设置自动 padding 为 true,删除填充补位 + decipher.setAutoPadding(true); + var decoded = decipher.update(encryptedData, 'base64', 'utf8'); + decoded += decipher.final('utf8'); + var data = JSON.parse(decoded); + if (data.watermark.appid !== this.appId) { + throw new Error('Illegal Buffer'); + } + return data; + }; + return WechatPublicInstance; +}()); +exports.WechatPublicInstance = WechatPublicInstance; +; diff --git a/lib/service/wechat/WechatWeb.d.ts b/lib/service/wechat/WechatWeb.d.ts new file mode 100644 index 0000000..22e5fa4 --- /dev/null +++ b/lib/service/wechat/WechatWeb.d.ts @@ -0,0 +1,15 @@ +export declare class WechatWebInstance { + appId: string; + appSecret: string; + accessToken?: string; + refreshAccessTokenHandler?: any; + constructor(appId: string, appSecret: string); + private access; + code2Session(code: string): Promise<{ + sessionKey: string; + openId: string; + unionId: string; + }>; + private refreshAccessToken; + decryptData(sessionKey: string, encryptedData: string, iv: string, signature: string): any; +} diff --git a/lib/service/wechat/WechatWeb.js b/lib/service/wechat/WechatWeb.js new file mode 100644 index 0000000..683973d --- /dev/null +++ b/lib/service/wechat/WechatWeb.js @@ -0,0 +1,149 @@ +"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 __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WechatWebInstance = void 0; +var crypto_1 = __importDefault(require("crypto")); +var buffer_1 = require("buffer"); +var WechatWebInstance = /** @class */ (function () { + function WechatWebInstance(appId, appSecret) { + this.appId = appId; + this.appSecret = appSecret; + this.refreshAccessToken(); + } + WechatWebInstance.prototype.access = function (url, mockData, init) { + return __awaiter(this, void 0, void 0, function () { + var response, headers, status, contentType, json, data; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (process.env.NODE_ENV === 'development') { + return [2 /*return*/, mockData]; + } + return [4 /*yield*/, global.fetch(url, init)]; + case 1: + response = _a.sent(); + headers = response.headers, status = response.status; + if (![200, 201].includes(status)) { + throw new Error("\u5FAE\u4FE1\u670D\u52A1\u5668\u8FD4\u56DE\u4E0D\u6B63\u786E\u5E94\u7B54\uFF1A".concat(status)); + } + contentType = headers['Content-Type'] || headers.get('Content-Type'); + if (!contentType.includes('application/json')) return [3 /*break*/, 3]; + return [4 /*yield*/, response.json()]; + case 2: + json = _a.sent(); + if (typeof json.errcode === 'number' && json.errcode !== 0) { + throw new Error("\u8C03\u7528\u5FAE\u4FE1\u63A5\u53E3\u8FD4\u56DE\u51FA\u9519\uFF0Ccode\u662F".concat(json.errcode, "\uFF0C\u4FE1\u606F\u662F").concat(json.errmsg)); + } + return [2 /*return*/, json]; + case 3: + if (!(contentType.includes('text') || + contentType.includes('xml') || + contentType.includes('html'))) return [3 /*break*/, 5]; + return [4 /*yield*/, response.text()]; + case 4: + data = _a.sent(); + return [2 /*return*/, data]; + case 5: + if (!contentType.includes('application/octet-stream')) return [3 /*break*/, 7]; + return [4 /*yield*/, response.arrayBuffer()]; + case 6: return [2 /*return*/, _a.sent()]; + case 7: return [2 /*return*/, response]; + } + }); + }); + }; + WechatWebInstance.prototype.code2Session = function (code) { + return __awaiter(this, void 0, void 0, function () { + var result, _a, session_key, openid, unionid; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/sns/oauth2/access_token?appid=".concat(this.appId, "&secret=").concat(this.appSecret, "&code=").concat(code, "&grant_type=authorization_code"), { session_key: 'aaa', openid: code, unionid: code })]; + case 1: + result = _b.sent(); + _a = typeof result === 'string' ? JSON.parse(result) : result, session_key = _a.session_key, openid = _a.openid, unionid = _a.unionid; + return [2 /*return*/, { + sessionKey: session_key, + openId: openid, + unionId: unionid, + }]; + } + }); + }); + }; + WechatWebInstance.prototype.refreshAccessToken = function () { + return __awaiter(this, void 0, void 0, function () { + var result, access_token, expires_in; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".concat(this.appId, "&secret=").concat(this.appSecret), { access_token: 'mockToken', expires_in: 3600 * 1000 })]; + case 1: + result = _a.sent(); + access_token = result.access_token, expires_in = result.expires_in; + this.accessToken = access_token; + // 生成下次刷新的定时器 + this.refreshAccessTokenHandler = setTimeout(function () { + _this.refreshAccessToken(); + }, (expires_in - 10) * 1000); + return [2 /*return*/]; + } + }); + }); + }; + WechatWebInstance.prototype.decryptData = function (sessionKey, encryptedData, iv, signature) { + var skBuf = buffer_1.Buffer.from(sessionKey, 'base64'); + // const edBuf = Buffer.from(encryptedData, 'base64'); + var ivBuf = buffer_1.Buffer.from(iv, 'base64'); + var decipher = crypto_1.default.createDecipheriv('aes-128-cbc', skBuf, ivBuf); + // 设置自动 padding 为 true,删除填充补位 + decipher.setAutoPadding(true); + var decoded = decipher.update(encryptedData, 'base64', 'utf8'); + decoded += decipher.final('utf8'); + var data = JSON.parse(decoded); + if (data.watermark.appid !== this.appId) { + throw new Error('Illegal Buffer'); + } + return data; + }; + return WechatWebInstance; +}()); +exports.WechatWebInstance = WechatWebInstance; +; diff --git a/src/service/wechat/WechatPublic.ts b/src/service/wechat/WechatPublic.ts index 577c692..1100ed2 100644 --- a/src/service/wechat/WechatPublic.ts +++ b/src/service/wechat/WechatPublic.ts @@ -15,7 +15,10 @@ export class WechatPublicInstance { this.refreshAccessToken(); } - private async access(url: string, init?: RequestInit) { + private async access(url: string, mockData: any, init?: RequestInit) { + if (process.env.NODE_ENV === 'development') { + return mockData; + } const response = await global.fetch(url, init); const { headers, status } = response; @@ -46,8 +49,11 @@ export class WechatPublicInstance { } async code2Session(code: string) { - const result = await this.access(`https://api.weixin.qq.com/sns/oauth2/access_token?appid=${this.appId}&secret=${this.appSecret}&code=${code}&grant_type=authorization_code`); - const { session_key, openid, unionid } = JSON.parse(result); // 这里微信返回的数据竟然是text/plain + const result = await this.access( + `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${this.appId}&secret=${this.appSecret}&code=${code}&grant_type=authorization_code`, + { session_key: 'aaa', openid: code, unionid: code } + ); + const { session_key, openid, unionid } = typeof result === 'string' ? JSON.parse(result) : result; // 这里微信返回的数据有时候竟然是text/plain return { sessionKey: session_key as string, @@ -57,7 +63,10 @@ export class WechatPublicInstance { } private async refreshAccessToken() { - const result = await this.access(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`, + { access_token: 'mockToken', expires_in: 3600 * 1000 } + ); const { access_token, expires_in } = result; this.accessToken = access_token; // 生成下次刷新的定时器 diff --git a/src/service/wechat/WechatWeb.ts b/src/service/wechat/WechatWeb.ts index 236b55f..3e84d2b 100644 --- a/src/service/wechat/WechatWeb.ts +++ b/src/service/wechat/WechatWeb.ts @@ -15,7 +15,10 @@ export class WechatWebInstance { this.refreshAccessToken(); } - private async access(url: string, init?: RequestInit) { + private async access(url: string, mockData: any, init?: RequestInit) { + if (process.env.NODE_ENV === 'development') { + return mockData; + } const response = await global.fetch(url, init); const { headers, status } = response; @@ -50,9 +53,10 @@ export class WechatWebInstance { async code2Session(code: string) { const result = await this.access( - `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${this.appId}&secret=${this.appSecret}&code=${code}&grant_type=authorization_code` + `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${this.appId}&secret=${this.appSecret}&code=${code}&grant_type=authorization_code`, + { session_key: 'aaa', openid: code, unionid: code } ); - const { session_key, openid, unionid } = JSON.parse(result); // 这里微信返回的数据竟然是text/plain + const { session_key, openid, unionid } = typeof result === 'string' ? JSON.parse(result) : result; // 这里微信返回的数据有时候竟然是text/plain return { sessionKey: session_key as string, @@ -63,7 +67,8 @@ export class WechatWebInstance { private async refreshAccessToken() { const result = await this.access( - `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}` + `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`, + { access_token: 'mockToken', expires_in: 3600 * 1000 } ); const { access_token, expires_in } = result; this.accessToken = access_token;