From e9079ace460e7aed6b5f3ddf8987a98e339a9468 Mon Sep 17 00:00:00 2001 From: qsc <3153284618@qq.com> Date: Fri, 22 Sep 2023 11:12:40 +0800 Subject: [PATCH] wechatmenu --- es/service/wechat/WechatPublic.d.ts | 23 + es/service/wechat/WechatPublic.js | 282 +++++-- lib/AmapSDK.js | 25 +- lib/QiniuSDK.js | 25 +- lib/SmsSdk.js | 38 +- lib/WechatSDK.js | 127 ++-- lib/index.js | 10 +- lib/service/ali/Sms.js | 71 +- lib/service/ali/Sms.mp.js | 27 +- lib/service/ali/Sms.web.js | 27 +- lib/service/amap/Amap.js | 167 ++--- lib/service/qiniu/QiniuCloud.js | 227 +++--- lib/service/tencent/Sms.js | 55 +- lib/service/tencent/Sms.mp.js | 27 +- lib/service/tencent/Sms.web.js | 27 +- lib/service/wechat/WechatMp.js | 344 ++++----- lib/service/wechat/WechatPublic.d.ts | 23 + lib/service/wechat/WechatPublic.js | 1019 +++++++++++++------------- lib/service/wechat/WechatWeb.js | 203 ++--- lib/types/index.js | 2 +- lib/utils/cheerio/index.js | 2 +- lib/utils/cheerio/index.web.js | 2 +- package.json | 2 +- src/service/wechat/WechatPublic.ts | 372 ++++++++-- tsconfig.json | 2 +- 25 files changed, 1665 insertions(+), 1464 deletions(-) diff --git a/es/service/wechat/WechatPublic.d.ts b/es/service/wechat/WechatPublic.d.ts index 9b2b024..1916f9d 100644 --- a/es/service/wechat/WechatPublic.d.ts +++ b/es/service/wechat/WechatPublic.d.ts @@ -52,6 +52,12 @@ export declare class WechatPublicInstance { gender: string | undefined; avatar: string; }>; + getTags(): Promise; + getCurrentMenu(): Promise; + getMenu(): Promise; + createMenu(menuConfig: any): Promise; + createConditionalMenu(menuConfig: any): Promise; + deleteConditionalMenu(menuid: number): Promise; private refreshAccessToken; decryptData(sessionKey: string, encryptedData: string, iv: string, signature: string): any; getQrCode(options: { @@ -81,6 +87,23 @@ export declare class WechatPublicInstance { count: number; noContent?: 0 | 1; }): Promise; + getArticle(options: { + article_id: string; + }): Promise; + createMaterial(options: { + type: 'image' | 'voice' | 'video' | 'thumb'; + media: FormData; + description?: FormData; + }): Promise; + batchGetMaterialList(options: { + type: 'image' | 'video' | 'voice' | 'news'; + offset?: number; + count: number; + }): Promise; + getMaterial(options: { + type: 'image' | 'video' | 'voice' | 'news'; + media_id: string; + }): Promise; getTicket(): Promise; private randomString; signatureJsSDK(options: { diff --git a/es/service/wechat/WechatPublic.js b/es/service/wechat/WechatPublic.js index dc35cc6..e34a370 100644 --- a/es/service/wechat/WechatPublic.js +++ b/es/service/wechat/WechatPublic.js @@ -1,6 +1,7 @@ require('../../fetch'); import crypto from 'crypto'; import { Buffer } from 'buffer'; +import URL from 'url'; export class WechatPublicInstance { appId; appSecret; @@ -30,7 +31,7 @@ export class WechatPublicInstance { } } async access(url, mockData, init) { - if (process.env.NODE_ENV === 'development') { + if (process.env.NODE_ENV === 'development' && mockData) { return mockData; } const response = await global.fetch(url, init); @@ -61,15 +62,7 @@ export class WechatPublicInstance { return response; } async code2Session(code) { - 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`, { - access_token: 'aaa', - openid: code, - unionid: code, - refresh_token: 'aaa', - is_snapshotuser: false, - expires_in: 30, - scope: 'userinfo', - }); + 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 { access_token, openid, unionid, scope, refresh_token, is_snapshotuser, expires_in, } = typeof result === 'string' ? JSON.parse(result) : result; // 这里微信返回的数据有时候竟然是text/plain return { accessToken: access_token, @@ -83,12 +76,7 @@ export class WechatPublicInstance { }; } async refreshUserAccessToken(refreshToken) { - const result = await this.access(`https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${this.appId}&grant_type=refresh_token&refresh_token=${refreshToken}`, { - access_token: 'aaa', - refresh_token: 'aaa', - expires_in: 30, - scope: 'userinfo', - }); + const result = await this.access(`https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${this.appId}&grant_type=refresh_token&refresh_token=${refreshToken}`); const { access_token, refresh_token, expires_in, scope } = result; return { accessToken: access_token, @@ -98,11 +86,7 @@ export class WechatPublicInstance { }; } async getUserInfo(accessToken, openId) { - const result = await this.access(`https://api.weixin.qq.com/sns/userinfo?access_token=${accessToken}&openid=${openId}&lang=zh_CN`, { - nickname: '码农哥', - sex: 1, - headimgurl: 'https://www.ertongzy.com/uploads/allimg/161005/2021233Y7-0.jpg', - }); + const result = await this.access(`https://api.weixin.qq.com/sns/userinfo?access_token=${accessToken}&openid=${openId}&lang=zh_CN`); const { nickname, sex, headimgurl } = result; return { nickname: nickname, @@ -110,10 +94,93 @@ export class WechatPublicInstance { avatar: headimgurl, }; } + async getTags() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/tags/get?access_token=${token}`, undefined, myInit); + return result; + } + async getCurrentMenu() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=${token}`, undefined, myInit); + return result; + } + async getMenu() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/menu/get?access_token=${token}`, undefined, myInit); + return result; + } + async createMenu(menuConfig) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(menuConfig), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + async createConditionalMenu(menuConfig) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(menuConfig), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + async deleteConditionalMenu(menuid) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + menuid + }), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } async refreshAccessToken(url, init) { const result = this.externalRefreshFn ? await this.externalRefreshFn(this.appId) - : 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: 600 }); + : await this.access(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`); const { access_token, expires_in } = result; this.accessToken = access_token; // 生成下次刷新的定时器 @@ -122,7 +189,9 @@ export class WechatPublicInstance { this.refreshAccessToken(); }, (expires_in - 10) * 1000); if (url) { - return this.access(url, {}, init); + const url2 = new URL.URL(url); + url2.searchParams.set('access_token', access_token); + return this.access(url2.toString(), {}, init); } } decryptData(sessionKey, encryptedData, iv, signature) { @@ -182,11 +251,13 @@ export class WechatPublicInstance { }; } const token = await this.getAccessToken(); - const result = await this.access(`https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=${token}`, { - ticket: `ticket${Date.now()}`, - url: `http://mock/q/${sceneId ? sceneId : sceneStr}`, - expireSeconds: expireSeconds, - }, myInit); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=${token}`, + // { + // ticket: `ticket${Date.now()}`, + // url: `http://mock/q/${sceneId ? sceneId : sceneStr}`, + // expireSeconds: expireSeconds, + // }, + myInit); return { ticket: result.ticket, url: result.url, @@ -210,11 +281,13 @@ export class WechatPublicInstance { }), }; const token = await this.getAccessToken(); - const result = await this.access(`https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${token}`, { - errcode: 0, - errmsg: 'ok', - msgid: Date.now(), - }, myInit); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${token}`, + // { + // errcode: 0, + // errmsg: 'ok', + // msgid: Date.now(), + // }, + myInit); const { errcode } = result; if (errcode === 0) { return Object.assign({ success: true }, result); @@ -281,10 +354,12 @@ export class WechatPublicInstance { } } const token = await this.getAccessToken(); - const result = await this.access(`https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${token}`, { - errcode: 0, - errmsg: 'ok', - }, myInit); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${token}`, + // { + // errcode: 0, + // errmsg: 'ok', + // }, + myInit); const { errcode } = result; if (errcode === 0) { return Object.assign({ success: true }, result); @@ -305,39 +380,108 @@ export class WechatPublicInstance { }), }; const token = await this.getAccessToken(); - const result = await this.access(`https://api.weixin.qq.com/cgi-bin/freepublish/batchget?access_token=${token}`, { - total_count: 1, - item_count: 1, - item: [ - { - article_id: 'test', - content: { - news_item: [ - { - title: '测试文章', - author: '测试作者', - digest: '测试摘要', - content: '测试内容', - content_source_url: '', - thumb_media_id: 'TEST_MEDIA_ID', - show_cover_pic: 1, - need_open_comment: 0, - only_fans_can_comment: 0, - url: 'TEST_ARTICLE_URL', - is_deleted: false, - }, - ], - }, - update_time: Date.now(), - }, - ], - }, myInit); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/freepublish/batchget?access_token=${token}`, undefined, myInit); const { errcode } = result; if (!errcode) { return result; } throw new Error(JSON.stringify(result)); } + async getArticle(options) { + const { article_id } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + article_id, + }), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/freepublish/getarticle?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + async createMaterial(options) { + const { type, media, description } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }; + if (type === 'video') { + Object.assign(myInit, { + body: JSON.stringify({ + type, + media, + description, + }), + }); + } + else { + Object.assign(myInit, { + body: JSON.stringify({ + type, + media, + }), + }); + } + ; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + async batchGetMaterialList(options) { + const { offset, count, type } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + type, + offset, + count, + }), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + async getMaterial(options) { + const { type, media_id } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + media_id + }), + }; + let imgFile; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=${token}`, undefined, myInit); + if ('errcode' in result) { + throw new Error(JSON.stringify(result)); + } + else { + return result; + } + } async getTicket() { const myInit = { method: 'GET', @@ -346,10 +490,12 @@ export class WechatPublicInstance { }, }; const token = await this.getAccessToken(); - const result = (await this.access(`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${token}&type=jsapi`, { - ticket: `ticket${Date.now()}`, - expires_in: 30, - }, myInit)); + const result = (await this.access(`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${token}&type=jsapi`, + // { + // ticket: `ticket${Date.now()}`, + // expires_in: 30, + // }, + myInit)); const { ticket } = result; return ticket; } diff --git a/lib/AmapSDK.js b/lib/AmapSDK.js index 964cafc..7b5ad10 100644 --- a/lib/AmapSDK.js +++ b/lib/AmapSDK.js @@ -1,22 +1,21 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var Amap_1 = require("./service/amap/Amap"); -var AmapSDK = /** @class */ (function () { - function AmapSDK() { +const Amap_1 = require("./service/amap/Amap"); +class AmapSDK { + webKeyMap; + constructor() { this.webKeyMap = {}; } - AmapSDK.prototype.getInstance = function (key) { - var _a; + getInstance(key) { if (this.webKeyMap[key]) { return this.webKeyMap[key]; } - var instance = new Amap_1.AmapInstance(key); - Object.assign(this.webKeyMap, (_a = {}, - _a[key] = instance, - _a)); + const instance = new Amap_1.AmapInstance(key); + Object.assign(this.webKeyMap, { + [key]: instance, + }); return instance; - }; - return AmapSDK; -}()); -var SDK = new AmapSDK(); + } +} +const SDK = new AmapSDK(); exports.default = SDK; diff --git a/lib/QiniuSDK.js b/lib/QiniuSDK.js index 69f0d9d..5125331 100644 --- a/lib/QiniuSDK.js +++ b/lib/QiniuSDK.js @@ -1,24 +1,23 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QiniuCloudInstance = void 0; -var QiniuCloud_1 = require("./service/qiniu/QiniuCloud"); +const QiniuCloud_1 = require("./service/qiniu/QiniuCloud"); Object.defineProperty(exports, "QiniuCloudInstance", { enumerable: true, get: function () { return QiniuCloud_1.QiniuCloudInstance; } }); -var QiniuSDK = /** @class */ (function () { - function QiniuSDK() { +class QiniuSDK { + qiniuMap; + constructor() { this.qiniuMap = {}; } - QiniuSDK.prototype.getInstance = function (accessKey, accessSecret) { - var _a; + getInstance(accessKey, accessSecret) { if (this.qiniuMap[accessKey]) { return this.qiniuMap[accessKey]; } - var instance = new QiniuCloud_1.QiniuCloudInstance(accessKey, accessSecret); - Object.assign(this.qiniuMap, (_a = {}, - _a[accessKey] = instance, - _a)); + const instance = new QiniuCloud_1.QiniuCloudInstance(accessKey, accessSecret); + Object.assign(this.qiniuMap, { + [accessKey]: instance, + }); return instance; - }; - return QiniuSDK; -}()); -var SDK = new QiniuSDK(); + } +} +const SDK = new QiniuSDK(); exports.default = SDK; diff --git a/lib/SmsSdk.js b/lib/SmsSdk.js index d645ad1..d989bf9 100644 --- a/lib/SmsSdk.js +++ b/lib/SmsSdk.js @@ -1,26 +1,27 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AliSmsInstance = exports.TencentSmsInstance = void 0; -var Sms_1 = require("./service/tencent/Sms"); +const Sms_1 = require("./service/tencent/Sms"); Object.defineProperty(exports, "TencentSmsInstance", { enumerable: true, get: function () { return Sms_1.TencentSmsInstance; } }); -var Sms_2 = require("./service/ali/Sms"); +const Sms_2 = require("./service/ali/Sms"); Object.defineProperty(exports, "AliSmsInstance", { enumerable: true, get: function () { return Sms_2.AliSmsInstance; } }); -var SmsSDK = /** @class */ (function () { - function SmsSDK() { +class SmsSDK { + tencentMap; + aliMap; + constructor() { this.tencentMap = {}; this.aliMap = {}; } - SmsSDK.prototype.getInstance = function (origin, accessKey, accessSecret, region, endpoint, apiVersion //阿里云独有 + getInstance(origin, accessKey, accessSecret, region, endpoint, apiVersion //阿里云独有 ) { - var _a, _b; if (origin === 'tencent') { if (this.tencentMap[accessKey]) { return this.tencentMap[accessKey]; } - var instance = new Sms_1.TencentSmsInstance(accessKey, accessSecret, region, endpoint); - Object.assign(this.tencentMap, (_a = {}, - _a[accessKey] = instance, - _a)); + const instance = new Sms_1.TencentSmsInstance(accessKey, accessSecret, region, endpoint); + Object.assign(this.tencentMap, { + [accessKey]: instance, + }); return instance; } else if (origin === 'ali') { @@ -30,17 +31,16 @@ var SmsSDK = /** @class */ (function () { if (this.aliMap[accessKey]) { return this.aliMap[accessKey]; } - var instance = new Sms_2.AliSmsInstance(accessKey, accessSecret, region, endpoint, apiVersion); - Object.assign(this.aliMap, (_b = {}, - _b[accessKey] = instance, - _b)); + const instance = new Sms_2.AliSmsInstance(accessKey, accessSecret, region, endpoint, apiVersion); + Object.assign(this.aliMap, { + [accessKey]: instance, + }); return instance; } else { - throw new Error("".concat(origin, " not implemented")); + throw new Error(`${origin} not implemented`); } - }; - return SmsSDK; -}()); -var SDK = new SmsSDK(); + } +} +const SDK = new SmsSDK(); exports.default = SDK; diff --git a/lib/WechatSDK.js b/lib/WechatSDK.js index 1a87a69..a7544c4 100644 --- a/lib/WechatSDK.js +++ b/lib/WechatSDK.js @@ -1,103 +1,98 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WechatPublicInstance = exports.WechatWebInstance = exports.WechatMpInstance = void 0; -var tslib_1 = require("tslib"); -var WechatMp_1 = require("./service/wechat/WechatMp"); +const 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"); +const 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"); +const WechatWeb_1 = require("./service/wechat/WechatWeb"); Object.defineProperty(exports, "WechatWebInstance", { enumerable: true, get: function () { return WechatWeb_1.WechatWebInstance; } }); -var cheerio_1 = require("./utils/cheerio"); -var WechatSDK = /** @class */ (function () { - function WechatSDK() { +const cheerio_1 = require("./utils/cheerio"); +class WechatSDK { + mpMap; + publicMap; + webMap; + constructor() { this.mpMap = {}; this.publicMap = {}; this.webMap = {}; } - WechatSDK.prototype.getInstance = function (appId, type, appSecret, accessToken, externalRefreshFn) { - var _a, _b, _c; + getInstance(appId, type, appSecret, accessToken, externalRefreshFn) { // type 支持web网站扫码登录 if (type === 'wechatMp') { if (this.mpMap[appId]) { return this.mpMap[appId]; } - var instance = new WechatMp_1.WechatMpInstance(appId, appSecret, accessToken, externalRefreshFn); - Object.assign(this.mpMap, (_a = {}, - _a[appId] = instance, - _a)); + const instance = new WechatMp_1.WechatMpInstance(appId, appSecret, accessToken, externalRefreshFn); + Object.assign(this.mpMap, { + [appId]: instance, + }); return instance; } else if (type === 'wechatPublic') { if (this.publicMap[appId]) { return this.publicMap[appId]; } - var instance = new WechatPublic_1.WechatPublicInstance(appId, appSecret, accessToken, externalRefreshFn); - Object.assign(this.publicMap, (_b = {}, - _b[appId] = instance, - _b)); + const instance = new WechatPublic_1.WechatPublicInstance(appId, appSecret, accessToken, externalRefreshFn); + Object.assign(this.publicMap, { + [appId]: instance, + }); return instance; } else if (type === 'web') { if (this.webMap[appId]) { return this.webMap[appId]; } - var instance = new WechatWeb_1.WechatWebInstance(appId, appSecret, accessToken, externalRefreshFn); - Object.assign(this.webMap, (_c = {}, - _c[appId] = instance, - _c)); + const instance = new WechatWeb_1.WechatWebInstance(appId, appSecret, accessToken, externalRefreshFn); + Object.assign(this.webMap, { + [appId]: instance, + }); return instance; } else { - throw new Error("".concat(type, " not implemented")); + throw new Error(`${type} not implemented`); } - }; + } /** * 解析微信公众号文章内容 * @param url 微信公众号链接 * @returns html */ - WechatSDK.prototype.analyzePublicArticle = function (url) { - var _a; - return tslib_1.__awaiter(this, void 0, void 0, function () { - var response, html, $, title, ems, imgsElement, imageList, i, src, publishDate, lines, i, timeStr; - return tslib_1.__generator(this, function (_b) { - switch (_b.label) { - case 0: return [4 /*yield*/, fetch(url)]; - case 1: - response = _b.sent(); - return [4 /*yield*/, response.text()]; - case 2: - html = _b.sent(); - $ = (0, cheerio_1.load)(html); - title = $('#activity-name') ? (_a = $('#activity-name').text()) === null || _a === void 0 ? void 0 : _a.trim().replace(/\n/g, '') : ''; - ems = $('em'); - imgsElement = $('img'); - imageList = []; - for (i = 0; i < imgsElement.length; i++) { - src = imgsElement[i].attribs['data-src']; - if (src && (src.includes('http') || src.includes('https'))) { - imageList.push(src); - } - } - lines = html.split('\n'); - for (i = 0; i < lines.length; i++) { - if (lines[i].includes('var ct =')) { - timeStr = lines[i].split('"')[1] + '000'; - publishDate = Number(timeStr); - break; - } - } - return [2 /*return*/, { - title: title, - publishDate: publishDate, - imageList: imageList, - }]; - } - }); - }); - }; - return WechatSDK; -}()); -var SDK = new WechatSDK(); + async analyzePublicArticle(url) { + const response = await fetch(url); + const html = await response.text(); + const $ = (0, cheerio_1.load)(html); + const title = $('#activity-name') ? $('#activity-name').text()?.trim().replace(/\n/g, '') : ''; + const ems = $('em'); + const imgsElement = $('img'); + const imageList = []; + for (let i = 0; i < imgsElement.length; i++) { + // 把 img 元素中的 src 内容提取出来,加入到数组中 + const src = imgsElement[i].attribs['data-src']; + if (src && (src.includes('http') || src.includes('https'))) { + imageList.push(src); + } + } + let publishDate; + // $('em').toArray().forEach((element, index) => { + // if (index === 0) { + // publishDate = $(element).text(); + // } + // }); + const lines = html.split('\n'); + for (let i = 0; i < lines.length; i++) { + if (lines[i].includes('var ct =')) { + const timeStr = lines[i].split('"')[1] + '000'; + publishDate = Number(timeStr); + break; + } + } + return { + title, + publishDate, + imageList, + }; + } +} +const SDK = new WechatSDK(); exports.default = SDK; diff --git a/lib/index.js b/lib/index.js index ab2213b..07e3540 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,18 +1,18 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AliSmsInstance = exports.TencentSmsInstance = exports.SmsSdk = exports.QiniuCloudInstance = exports.WechatWebInstance = exports.WechatPublicInstance = exports.WechatMpInstance = exports.WechatSDK = exports.QiniuSDK = exports.AmapSDK = void 0; -var tslib_1 = require("tslib"); -var WechatSDK_1 = tslib_1.__importStar(require("./WechatSDK")); +const tslib_1 = require("tslib"); +const WechatSDK_1 = tslib_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 = tslib_1.__importDefault(require("./AmapSDK")); +const AmapSDK_1 = tslib_1.__importDefault(require("./AmapSDK")); exports.AmapSDK = AmapSDK_1.default; -var QiniuSDK_1 = tslib_1.__importStar(require("./QiniuSDK")); +const QiniuSDK_1 = tslib_1.__importStar(require("./QiniuSDK")); exports.QiniuSDK = QiniuSDK_1.default; Object.defineProperty(exports, "QiniuCloudInstance", { enumerable: true, get: function () { return QiniuSDK_1.QiniuCloudInstance; } }); -var SmsSdk_1 = tslib_1.__importStar(require("./SmsSdk")); +const SmsSdk_1 = tslib_1.__importStar(require("./SmsSdk")); exports.SmsSdk = SmsSdk_1.default; Object.defineProperty(exports, "TencentSmsInstance", { enumerable: true, get: function () { return SmsSdk_1.TencentSmsInstance; } }); Object.defineProperty(exports, "AliSmsInstance", { enumerable: true, get: function () { return SmsSdk_1.AliSmsInstance; } }); diff --git a/lib/service/ali/Sms.js b/lib/service/ali/Sms.js index 74e650a..9b314b6 100644 --- a/lib/service/ali/Sms.js +++ b/lib/service/ali/Sms.js @@ -1,10 +1,16 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AliSmsInstance = void 0; -var tslib_1 = require("tslib"); -var rpc_1 = tslib_1.__importDefault(require("@alicloud/pop-core/lib/rpc")); -var AliSmsInstance = /** @class */ (function () { - function AliSmsInstance(accessKeyId, accessKeySecret, regionId, endpoint, apiVersion) { +const tslib_1 = require("tslib"); +const rpc_1 = tslib_1.__importDefault(require("@alicloud/pop-core/lib/rpc")); +class AliSmsInstance { + accessKeyId; + accessKeySecret; + regionId; + endpoint; + apiVersion; + client; + constructor(accessKeyId, accessKeySecret, regionId, endpoint, apiVersion) { this.accessKeyId = accessKeyId; this.accessKeySecret = accessKeySecret; this.regionId = regionId; @@ -17,37 +23,30 @@ var AliSmsInstance = /** @class */ (function () { apiVersion: this.apiVersion, }); } - AliSmsInstance.prototype.sendSms = function (params) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var PhoneNumbers, _a, TemplateParam, TemplateCode, SignName, param; - return tslib_1.__generator(this, function (_b) { - PhoneNumbers = params.PhoneNumbers, _a = params.TemplateParam, TemplateParam = _a === void 0 ? {} : _a, TemplateCode = params.TemplateCode, SignName = params.SignName; - param = Object.assign({ - regionId: this.regionId, - }, { - PhoneNumbers: PhoneNumbers.join(','), - TemplateParam: JSON.stringify(TemplateParam), - TemplateCode: TemplateCode, - SignName: SignName, - }); - try { - // const data = await this.client.request( - // 'SendSms', - // param, - // { - // method: 'POST', - // } - // ); - // return data; - } - catch (err) { - console.error(err); - throw err; - } - return [2 /*return*/]; - }); + async sendSms(params) { + const { PhoneNumbers, TemplateParam = {}, TemplateCode, SignName, } = params; + const param = Object.assign({ + regionId: this.regionId, + }, { + PhoneNumbers: PhoneNumbers.join(','), + TemplateParam: JSON.stringify(TemplateParam), + TemplateCode: TemplateCode, + SignName: SignName, }); - }; - return AliSmsInstance; -}()); + try { + // const data = await this.client.request( + // 'SendSms', + // param, + // { + // method: 'POST', + // } + // ); + // return data; + } + catch (err) { + console.error(err); + throw err; + } + } +} exports.AliSmsInstance = AliSmsInstance; diff --git a/lib/service/ali/Sms.mp.js b/lib/service/ali/Sms.mp.js index 5eddfa9..c66aadf 100644 --- a/lib/service/ali/Sms.mp.js +++ b/lib/service/ali/Sms.mp.js @@ -1,14 +1,18 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AliSmsInstance = void 0; -var tslib_1 = require("tslib"); -var AliSmsInstance = /** @class */ (function () { - function AliSmsInstance(secretId, secretKey, region, endpoint) { +class AliSmsInstance { + secretId; + secretKey; + region; + endpoint; + client; + constructor(secretId, secretKey, region, endpoint) { this.secretId = secretId; this.secretKey = secretKey; this.region = region; this.endpoint = endpoint; - var clientConfig = { + const clientConfig = { credential: { secretId: this.secretId, secretKey: this.secretKey, @@ -21,14 +25,9 @@ var AliSmsInstance = /** @class */ (function () { }, }; } - AliSmsInstance.prototype.sendSms = function (params) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - return tslib_1.__generator(this, function (_a) { - console.log('mp走不到这里'); - return [2 /*return*/, {}]; - }); - }); - }; - return AliSmsInstance; -}()); + async sendSms(params) { + console.log('mp走不到这里'); + return {}; + } +} exports.AliSmsInstance = AliSmsInstance; diff --git a/lib/service/ali/Sms.web.js b/lib/service/ali/Sms.web.js index 79a9e5f..24fbd59 100644 --- a/lib/service/ali/Sms.web.js +++ b/lib/service/ali/Sms.web.js @@ -1,14 +1,18 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AliSmsInstance = void 0; -var tslib_1 = require("tslib"); -var AliSmsInstance = /** @class */ (function () { - function AliSmsInstance(secretId, secretKey, region, endpoint) { +class AliSmsInstance { + secretId; + secretKey; + region; + endpoint; + client; + constructor(secretId, secretKey, region, endpoint) { this.secretId = secretId; this.secretKey = secretKey; this.region = region; this.endpoint = endpoint; - var clientConfig = { + const clientConfig = { credential: { secretId: this.secretId, secretKey: this.secretKey, @@ -21,14 +25,9 @@ var AliSmsInstance = /** @class */ (function () { }, }; } - AliSmsInstance.prototype.sendSms = function (params) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - return tslib_1.__generator(this, function (_a) { - console.log('web走不到这里'); - return [2 /*return*/, {}]; - }); - }); - }; - return AliSmsInstance; -}()); + async sendSms(params) { + console.log('web走不到这里'); + return {}; + } +} exports.AliSmsInstance = AliSmsInstance; diff --git a/lib/service/amap/Amap.js b/lib/service/amap/Amap.js index bdea9d0..f83e59c 100644 --- a/lib/service/amap/Amap.js +++ b/lib/service/amap/Amap.js @@ -1,121 +1,60 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AmapInstance = void 0; -var tslib_1 = require("tslib"); require('../../fetch'); -var AmapInstance = /** @class */ (function () { - function AmapInstance(key) { +class AmapInstance { + key; + constructor(key) { this.key = key; } - AmapInstance.prototype.getDrivingPath = function (data) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var from, to, url, result, jsonData; - return tslib_1.__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 tslib_1.__awaiter(this, void 0, void 0, function () { - var longitude, latitude, result, jsonData; - return tslib_1.__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 tslib_1.__awaiter(this, void 0, void 0, function () { - var ip, url, result, jsonData; - return tslib_1.__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 tslib_1.__awaiter(this, void 0, void 0, function () { - var keywords, subdistrict, url, result, jsonData; - return tslib_1.__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 tslib_1.__awaiter(this, void 0, void 0, function () { - var address, url, result, jsonData; - return tslib_1.__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; -}()); + async getDrivingPath(data) { + const { from, to } = data; + const url = `http://restapi.amap.com/v3/direction/driving?origin=${from[0].toFixed(6)},${from[1].toFixed(6)}&destination=${to[0].toFixed(6)},${to[1].toFixed(6)}&strategy=10&key=${this.key}`; + const result = await global.fetch(url); + const jsonData = await result.json(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return Promise.resolve(jsonData); + } + async regeo(data) { + const { longitude, latitude } = data; + const result = await global.fetch(`https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`); + const jsonData = await result.json(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return Promise.resolve(jsonData); + } + async ipLoc(data) { + const { ip } = data; + const url = `https://restapi.amap.com/v3/ip?key=${this.key}&ip=${ip}`; + const result = await global.fetch(url); + const jsonData = await result.json(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return Promise.resolve(jsonData); + } + async getDistrict(data) { + const { keywords, subdistrict } = data; + const url = `https://restapi.amap.com/v3/config/district?keywords=${keywords}&subdistrict=${subdistrict}&key=${this.key}`; + const result = await global.fetch(url); + const jsonData = await result.json(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return Promise.resolve(jsonData); + } + async geocode(data) { + const { address } = data; + const url = `https://restapi.amap.com/v3/geocode/geo?address=${address}&key=${this.key}`; + const result = await global.fetch(url); + const jsonData = await result.json(); + if (jsonData.status !== '1') { + throw new Error(JSON.stringify(jsonData)); + } + return Promise.resolve(jsonData); + } +} exports.AmapInstance = AmapInstance; diff --git a/lib/service/qiniu/QiniuCloud.js b/lib/service/qiniu/QiniuCloud.js index 180c9fd..4b31bc2 100644 --- a/lib/service/qiniu/QiniuCloud.js +++ b/lib/service/qiniu/QiniuCloud.js @@ -1,13 +1,15 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QiniuCloudInstance = void 0; -var tslib_1 = require("tslib"); +const tslib_1 = require("tslib"); require('../../fetch'); -var crypto_1 = tslib_1.__importDefault(require("crypto")); -var ts_md5_1 = require("ts-md5"); -var buffer_1 = require("buffer"); -var QiniuCloudInstance = /** @class */ (function () { - function QiniuCloudInstance(accessKey, secretKey) { +const crypto_1 = tslib_1.__importDefault(require("crypto")); +const ts_md5_1 = require("ts-md5"); +const buffer_1 = require("buffer"); +class QiniuCloudInstance { + accessKey; + secretKey; + constructor(accessKey, secretKey) { this.accessKey = accessKey; this.secretKey = secretKey; } @@ -19,21 +21,21 @@ var QiniuCloudInstance = /** @class */ (function () { * @param key * @returns */ - QiniuCloudInstance.prototype.getUploadInfo = function (uploadHost, bucket, key) { + getUploadInfo(uploadHost, bucket, key) { try { - var scope = key ? "".concat(bucket, ":").concat(key) : bucket; - var uploadToken = this.getToken(scope); + const scope = key ? `${bucket}:${key}` : bucket; + const uploadToken = this.getToken(scope); return { - key: key, - uploadToken: uploadToken, - uploadHost: uploadHost, - bucket: bucket, + key, + uploadToken, + uploadHost, + bucket, }; } catch (err) { throw err; } - }; + } /** * 计算直播需要的token * @param method @@ -44,15 +46,15 @@ var QiniuCloudInstance = /** @class */ (function () { * @param bodyStr * @returns */ - QiniuCloudInstance.prototype.getLiveToken = function (method, path, host, rawQuery, contentType, bodyStr) { + getLiveToken(method, path, host, rawQuery, contentType, bodyStr) { // 1. 添加 Path - var data = "".concat(method, " ").concat(path); + let data = `${method} ${path}`; if (rawQuery) { - data += "?".concat(rawQuery); + data += `?${rawQuery}`; } - data += "\nHost: ".concat(host); + data += `\nHost: ${host}`; if (contentType) { - data += "\nContent-Type: ".concat(contentType); + data += `\nContent-Type: ${contentType}`; } data += '\n\n'; if (bodyStr && @@ -60,45 +62,37 @@ var QiniuCloudInstance = /** @class */ (function () { contentType !== 'application/octet-stream') { data += bodyStr; } - var sign = this.hmacSha1(data, this.secretKey); - var encodedSign = this.base64ToUrlSafe(sign); - var toke = 'Qiniu ' + this.accessKey + ':' + encodedSign; + const sign = this.hmacSha1(data, this.secretKey); + const encodedSign = this.base64ToUrlSafe(sign); + const toke = 'Qiniu ' + this.accessKey + ':' + encodedSign; return toke; - }; - QiniuCloudInstance.prototype.getLiveStream = function (hub, method, streamTitle, host, publishDomain, playDomain, publishKey, playKey, expireAt) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var path, key, bodyStr, contentType, token, url, obj; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - path = "/v2/hubs/".concat(hub, "/streams"); - key = streamTitle; - if (!key) { - key = "class".concat(new Date().getTime()); - } - bodyStr = JSON.stringify({ - key: key, - }); - contentType = 'application/json'; - token = this.getLiveToken(method, path, host); - url = "https://pili.qiniuapi.com/v2/hubs/".concat(hub, "/streams"); - return [4 /*yield*/, global.fetch(url, { - method: 'POST', - headers: { - Authorization: token, - 'Content-Type': contentType, - }, - body: bodyStr, - mode: 'no-cors', - })]; - case 1: - _a.sent(); - obj = this.getStreamObj(publishDomain, playDomain, hub, publishKey, playKey, streamTitle, expireAt); - return [2 /*return*/, obj]; - } - }); + } + async getLiveStream(hub, method, streamTitle, host, publishDomain, playDomain, publishKey, playKey, expireAt) { + // 七牛创建直播流接口路径 + const path = `/v2/hubs/${hub}/streams`; + // 如果用户没给streamTitle,那么随机生成一个 + let key = streamTitle; + if (!key) { + key = `class${new Date().getTime()}`; + } + const bodyStr = JSON.stringify({ + key, }); - }; + const contentType = 'application/json'; + const token = this.getLiveToken(method, path, host); + const url = `https://pili.qiniuapi.com/v2/hubs/${hub}/streams`; + await global.fetch(url, { + method: 'POST', + headers: { + Authorization: token, + 'Content-Type': contentType, + }, + body: bodyStr, + mode: 'no-cors', + }); + const obj = this.getStreamObj(publishDomain, playDomain, hub, publishKey, playKey, streamTitle, expireAt); + return obj; + } /** * 计算直播流地址相关信息 * @param publishDomain @@ -110,87 +104,76 @@ var QiniuCloudInstance = /** @class */ (function () { * @param expireAt * @returns */ - QiniuCloudInstance.prototype.getStreamObj = function (publishDomain, playDomain, hub, publishKey, playKey, streamTitle, expireAt) { - var signStr = "/".concat(hub, "/").concat(streamTitle, "?expire=").concat(expireAt); - var sourcePath = "/".concat(hub, "/").concat(streamTitle); - var token = this.base64ToUrlSafe(this.hmacSha1(signStr, publishKey)); - var rtmpPushUrl = "rtmp://".concat(publishDomain).concat(signStr, "&token=").concat(token); + getStreamObj(publishDomain, playDomain, hub, publishKey, playKey, streamTitle, expireAt) { + const signStr = `/${hub}/${streamTitle}?expire=${expireAt}`; + const sourcePath = `/${hub}/${streamTitle}`; + const token = this.base64ToUrlSafe(this.hmacSha1(signStr, publishKey)); + const rtmpPushUrl = `rtmp://${publishDomain}${signStr}&token=${token}`; // 生成播放地址 - var t = expireAt.toString(16).toLowerCase(); - var playSign = ts_md5_1.Md5.hashStr(playKey + sourcePath + t) + const t = expireAt.toString(16).toLowerCase(); + const playSign = ts_md5_1.Md5.hashStr(playKey + sourcePath + t) .toString() .toLowerCase(); - var rtmpPlayUrl = "https://".concat(playDomain).concat(sourcePath, ".m3u8?sign=").concat(playSign, "&t=").concat(t); + const rtmpPlayUrl = `https://${playDomain}${sourcePath}.m3u8?sign=${playSign}&t=${t}`; // obs推流需要的地址和串流密钥 - var pcPushUrl = "rtmp://".concat(publishDomain, "/").concat(hub, "/"); - var streamKey = "".concat(streamTitle, "?expire=").concat(expireAt, "&token=").concat(token); + const pcPushUrl = `rtmp://${publishDomain}/${hub}/`; + const streamKey = `${streamTitle}?expire=${expireAt}&token=${token}`; return { - streamTitle: streamTitle, - hub: hub, - rtmpPushUrl: rtmpPushUrl, - rtmpPlayUrl: rtmpPlayUrl, - pcPushUrl: pcPushUrl, - streamKey: streamKey, - expireAt: expireAt, + streamTitle, + hub, + rtmpPushUrl, + rtmpPlayUrl, + pcPushUrl, + streamKey, + expireAt, }; - }; - QiniuCloudInstance.prototype.getPlayBackUrl = function (hub, playBackDomain, streamTitle, start, end, method, host, rawQuery) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var encodeStreamTitle, path, bodyStr, contentType, token, url; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - encodeStreamTitle = this.base64ToUrlSafe(streamTitle); - path = "/v2/hubs/".concat(hub, "/streams/").concat(encodeStreamTitle, "/saveas"); - bodyStr = JSON.stringify({ - fname: streamTitle, - start: start, - end: end, - }); - contentType = 'application/json'; - token = this.getLiveToken(method, path, host, rawQuery, contentType, bodyStr); - url = "https://pili.qiniuapi.com".concat(path); - return [4 /*yield*/, global.fetch(url, { - method: 'POST', - headers: { - Authorization: token, - 'Content-Type': contentType, - }, - body: bodyStr, - mode: 'no-cors', - })]; - case 1: - _a.sent(); - return [2 /*return*/, "https://".concat(playBackDomain, "/").concat(streamTitle, ".m3u8")]; - } - }); + } + async getPlayBackUrl(hub, playBackDomain, streamTitle, start, end, method, host, rawQuery) { + const encodeStreamTitle = this.base64ToUrlSafe(streamTitle); + const path = `/v2/hubs/${hub}/streams/${encodeStreamTitle}/saveas`; + const bodyStr = JSON.stringify({ + fname: streamTitle, + start, + end, }); - }; - QiniuCloudInstance.prototype.getToken = function (scope) { + const contentType = 'application/json'; + const token = this.getLiveToken(method, path, host, rawQuery, contentType, bodyStr); + const url = `https://pili.qiniuapi.com${path}`; + await global.fetch(url, { + method: 'POST', + headers: { + Authorization: token, + 'Content-Type': contentType, + }, + body: bodyStr, + mode: 'no-cors', + }); + return `https://${playBackDomain}/${streamTitle}.m3u8`; + } + getToken(scope) { // 构造策略 - var putPolicy = { + const putPolicy = { scope: scope, deadline: 3600 + Math.floor(Date.now() / 1000), }; // 构造凭证 - var encodedFlags = this.urlSafeBase64Encode(JSON.stringify(putPolicy)); - var encoded = this.hmacSha1(encodedFlags, this.secretKey); - var encodedSign = this.base64ToUrlSafe(encoded); - var uploadToken = this.accessKey + ':' + encodedSign + ':' + encodedFlags; + const encodedFlags = this.urlSafeBase64Encode(JSON.stringify(putPolicy)); + const encoded = this.hmacSha1(encodedFlags, this.secretKey); + const encodedSign = this.base64ToUrlSafe(encoded); + const uploadToken = this.accessKey + ':' + encodedSign + ':' + encodedFlags; return uploadToken; - }; - QiniuCloudInstance.prototype.base64ToUrlSafe = function (v) { + } + base64ToUrlSafe(v) { return v.replace(/\//g, '_').replace(/\+/g, '-'); - }; - QiniuCloudInstance.prototype.hmacSha1 = function (encodedFlags, secretKey) { - var hmac = crypto_1.default.createHmac('sha1', secretKey); + } + hmacSha1(encodedFlags, secretKey) { + const hmac = crypto_1.default.createHmac('sha1', secretKey); hmac.update(encodedFlags); return hmac.digest('base64'); - }; - QiniuCloudInstance.prototype.urlSafeBase64Encode = function (jsonFlags) { - var encoded = buffer_1.Buffer.from(jsonFlags).toString('base64'); + } + urlSafeBase64Encode(jsonFlags) { + const encoded = buffer_1.Buffer.from(jsonFlags).toString('base64'); return this.base64ToUrlSafe(encoded); - }; - return QiniuCloudInstance; -}()); + } +} exports.QiniuCloudInstance = QiniuCloudInstance; diff --git a/lib/service/tencent/Sms.js b/lib/service/tencent/Sms.js index c823d6b..f19e235 100644 --- a/lib/service/tencent/Sms.js +++ b/lib/service/tencent/Sms.js @@ -1,16 +1,20 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TencentSmsInstance = void 0; -var tslib_1 = require("tslib"); -var sms_client_1 = require("tencentcloud-sdk-nodejs/tencentcloud/services/sms/v20210111/sms_client"); -var SmsClient = sms_client_1.Client; -var TencentSmsInstance = /** @class */ (function () { - function TencentSmsInstance(secretId, secretKey, region, endpoint) { +const sms_client_1 = require("tencentcloud-sdk-nodejs/tencentcloud/services/sms/v20210111/sms_client"); +const SmsClient = sms_client_1.Client; +class TencentSmsInstance { + secretId; + secretKey; + region; + endpoint; + client; + constructor(secretId, secretKey, region, endpoint) { this.secretId = secretId; this.secretKey = secretKey; this.region = region; this.endpoint = endpoint; - var clientConfig = { + const clientConfig = { credential: { secretId: this.secretId, secretKey: this.secretKey, @@ -25,26 +29,21 @@ var TencentSmsInstance = /** @class */ (function () { // 实例化要请求产品的client对象,clientProfile是可选的 this.client = new SmsClient(clientConfig); } - TencentSmsInstance.prototype.sendSms = function (params) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var data, err_1; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - return [4 /*yield*/, this.client.SendSms(params)]; - case 1: - data = _a.sent(); - return [2 /*return*/, data]; - case 2: - err_1 = _a.sent(); - console.error(err_1); - throw err_1; - case 3: return [2 /*return*/]; - } - }); - }); - }; - return TencentSmsInstance; -}()); + async sendSms(params) { + // const params: SendSmsRequest = { + // PhoneNumberSet: [], + // TemplateParamSet: [], + // SmsSdkAppId: '', + // TemplateId: '', + // }; + try { + const data = await this.client.SendSms(params); + return data; + } + catch (err) { + console.error(err); + throw err; + } + } +} exports.TencentSmsInstance = TencentSmsInstance; diff --git a/lib/service/tencent/Sms.mp.js b/lib/service/tencent/Sms.mp.js index 54f9b02..7e9039b 100644 --- a/lib/service/tencent/Sms.mp.js +++ b/lib/service/tencent/Sms.mp.js @@ -1,14 +1,18 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TencentSmsInstance = void 0; -var tslib_1 = require("tslib"); -var TencentSmsInstance = /** @class */ (function () { - function TencentSmsInstance(secretId, secretKey, region, endpoint) { +class TencentSmsInstance { + secretId; + secretKey; + region; + endpoint; + client; + constructor(secretId, secretKey, region, endpoint) { this.secretId = secretId; this.secretKey = secretKey; this.region = region; this.endpoint = endpoint; - var clientConfig = { + const clientConfig = { credential: { secretId: this.secretId, secretKey: this.secretKey, @@ -21,14 +25,9 @@ var TencentSmsInstance = /** @class */ (function () { }, }; } - TencentSmsInstance.prototype.sendSms = function (params) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - return tslib_1.__generator(this, function (_a) { - console.log('mp走不到这里'); - return [2 /*return*/, {}]; - }); - }); - }; - return TencentSmsInstance; -}()); + async sendSms(params) { + console.log('mp走不到这里'); + return {}; + } +} exports.TencentSmsInstance = TencentSmsInstance; diff --git a/lib/service/tencent/Sms.web.js b/lib/service/tencent/Sms.web.js index 2fb113b..3260fc7 100644 --- a/lib/service/tencent/Sms.web.js +++ b/lib/service/tencent/Sms.web.js @@ -1,14 +1,18 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TencentSmsInstance = void 0; -var tslib_1 = require("tslib"); -var TencentSmsInstance = /** @class */ (function () { - function TencentSmsInstance(secretId, secretKey, region, endpoint) { +class TencentSmsInstance { + secretId; + secretKey; + region; + endpoint; + client; + constructor(secretId, secretKey, region, endpoint) { this.secretId = secretId; this.secretKey = secretKey; this.region = region; this.endpoint = endpoint; - var clientConfig = { + const clientConfig = { credential: { secretId: this.secretId, secretKey: this.secretKey, @@ -21,14 +25,9 @@ var TencentSmsInstance = /** @class */ (function () { }, }; } - TencentSmsInstance.prototype.sendSms = function (params) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - return tslib_1.__generator(this, function (_a) { - console.log('web走不到这里'); - return [2 /*return*/, {}]; - }); - }); - }; - return TencentSmsInstance; -}()); + async sendSms(params) { + console.log('web走不到这里'); + return {}; + } +} exports.TencentSmsInstance = TencentSmsInstance; diff --git a/lib/service/wechat/WechatMp.js b/lib/service/wechat/WechatMp.js index 5873d20..b38ad56 100644 --- a/lib/service/wechat/WechatMp.js +++ b/lib/service/wechat/WechatMp.js @@ -1,12 +1,17 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WechatMpInstance = void 0; -var tslib_1 = require("tslib"); +const tslib_1 = require("tslib"); require('../../fetch'); -var crypto_1 = tslib_1.__importDefault(require("crypto")); -var buffer_1 = require("buffer"); -var WechatMpInstance = /** @class */ (function () { - function WechatMpInstance(appId, appSecret, accessToken, externalRefreshFn) { +const crypto_1 = tslib_1.__importDefault(require("crypto")); +const buffer_1 = require("buffer"); +class WechatMpInstance { + appId; + appSecret; + accessToken; + refreshAccessTokenHandler; + externalRefreshFn; + constructor(appId, appSecret, accessToken, externalRefreshFn) { this.appId = appId; this.appSecret = appSecret; this.externalRefreshFn = externalRefreshFn; @@ -20,228 +25,143 @@ var WechatMpInstance = /** @class */ (function () { this.refreshAccessToken(); } } - WechatMpInstance.prototype.getAccessToken = function () { - return tslib_1.__awaiter(this, void 0, void 0, function () { - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - if (!true) return [3 /*break*/, 2]; - if (this.accessToken) { - return [2 /*return*/, this.accessToken]; - } - return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(0); }, 500); })]; - case 1: - _a.sent(); - return [3 /*break*/, 0]; - case 2: return [2 /*return*/]; + async getAccessToken() { + while (true) { + if (this.accessToken) { + return this.accessToken; + } + await new Promise((resolve) => setTimeout(() => resolve(0), 500)); + } + } + async access(url, init, fresh) { + const response = await global.fetch(url, init); + const { headers, status } = response; + if (![200, 201].includes(status)) { + throw new Error(`微信服务器返回不正确应答:${status}`); + } + const contentType = headers['Content-Type'] || headers.get('Content-Type'); + if (contentType.includes('application/json')) { + const json = await response.json(); + if (typeof json.errcode === 'number' && json.errcode !== 0) { + if ([42001, 40001].includes(json.errcode)) { + if (fresh) { + throw new Error('刚刷新的token不可能马上过期,请检查是否有并发刷新token的逻辑'); + } + console.log(JSON.stringify(json)); + return this.refreshAccessToken(url, init); } - }); - }); - }; - WechatMpInstance.prototype.access = function (url, init, fresh) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var response, headers, status, contentType, json, data; - return tslib_1.__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) { - if ([42001, 40001].includes(json.errcode)) { - if (fresh) { - throw new Error('刚刷新的token不可能马上过期,请检查是否有并发刷新token的逻辑'); - } - console.log(JSON.stringify(json)); - return [2 /*return*/, this.refreshAccessToken(url, init)]; - } - 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 tslib_1.__awaiter(this, void 0, void 0, function () { - var result, _a, session_key, openid, unionid; - return tslib_1.__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 (url, init) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var result, _a, access_token, expires_in; - var _this = this; - return tslib_1.__generator(this, function (_b) { - switch (_b.label) { - case 0: - if (!this.externalRefreshFn) return [3 /*break*/, 2]; - return [4 /*yield*/, this.externalRefreshFn(this.appId)]; - case 1: - _a = _b.sent(); - return [3 /*break*/, 4]; - case 2: 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 3: - _a = _b.sent(); - _b.label = 4; - case 4: - result = _a; - access_token = result.access_token, expires_in = result.expires_in; - this.accessToken = access_token; - if (process.env.NODE_ENV === 'development') { - console.log("\u5C0F\u7A0B\u5E8F\u83B7\u5F97\u65B0\u7684accessToken\u3002appId:[".concat(this.appId, "], token: [").concat(access_token, "]")); - } - // 生成下次刷新的定时器 - this.refreshAccessTokenHandler = setTimeout(function () { - _this.refreshAccessToken(); - }, (expires_in - 10) * 1000); - if (url) { - return [2 /*return*/, this.access(url, init, true)]; - } - return [2 /*return*/]; - } - }); - }); - }; - WechatMpInstance.prototype.decryptData = function (sessionKey, encryptedData, iv, signature) { - var skBuf = buffer_1.Buffer.from(sessionKey, 'base64'); + throw new Error(`调用微信接口返回出错,code是${json.errcode},信息是${json.errmsg}`); + } + return json; + } + if (contentType.includes('text') || + contentType.includes('xml') || + contentType.includes('html')) { + const data = await response.text(); + return data; + } + if (contentType.includes('application/octet-stream')) { + return await response.arrayBuffer(); + } + return response; + } + async code2Session(code) { + const result = await this.access(`https://api.weixin.qq.com/sns/jscode2session?appid=${this.appId}&secret=${this.appSecret}&js_code=${code}&grant_type=authorization_code`); + const { session_key, openid, unionid } = JSON.parse(result); // 这里微信返回的数据竟然是text/plain + return { + sessionKey: session_key, + openId: openid, + unionId: unionid, + }; + } + async refreshAccessToken(url, init) { + const result = this.externalRefreshFn + ? await this.externalRefreshFn(this.appId) + : await this.access(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`); + const { access_token, expires_in } = result; + this.accessToken = access_token; + if (process.env.NODE_ENV === 'development') { + console.log(`小程序获得新的accessToken。appId:[${this.appId}], token: [${access_token}]`); + } + // 生成下次刷新的定时器 + this.refreshAccessTokenHandler = setTimeout(() => { + this.refreshAccessToken(); + }, (expires_in - 10) * 1000); + if (url) { + return this.access(url, init, true); + } + } + decryptData(sessionKey, encryptedData, iv, signature) { + const 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); + const ivBuf = buffer_1.Buffer.from(iv, 'base64'); + const decipher = crypto_1.default.createDecipheriv('aes-128-cbc', skBuf, ivBuf); // 设置自动 padding 为 true,删除填充补位 decipher.setAutoPadding(true); - var decoded = decipher.update(encryptedData, 'base64', 'utf8'); + let decoded = decipher.update(encryptedData, 'base64', 'utf8'); decoded += decipher.final('utf8'); - var data = JSON.parse(decoded); + const 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, _b = _a.envVersion, envVersion = _b === void 0 ? 'release' : _b, width = _a.width, autoColor = _a.autoColor, lineColor = _a.lineColor, isHyaline = _a.isHyaline; - return tslib_1.__awaiter(this, void 0, void 0, function () { - var token, result; - return tslib_1.__generator(this, function (_c) { - switch (_c.label) { - case 0: return [4 /*yield*/, this.getAccessToken()]; - case 1: - token = _c.sent(); - return [4 /*yield*/, this.access("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=".concat(token), { - 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 2: - result = _c.sent(); - return [4 /*yield*/, result.arrayBuffer()]; - case 3: return [2 /*return*/, (_c.sent())]; - } - }); + } + async getMpUnlimitWxaCode({ scene, page, envVersion = 'release', width, autoColor, lineColor, isHyaline, }) { + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${token}`, { + method: 'POST', + headers: { + 'Content-type': 'application/json', + Accept: 'image/jpg', + }, + body: JSON.stringify({ + // access_token: this.accessToken, + scene, + page, + env_version: envVersion, + width, + auto_color: autoColor, + line_color: lineColor, + is_hyaline: isHyaline, + }), }); - }; - WechatMpInstance.prototype.getUserPhoneNumber = function (code) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var token, result; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.getAccessToken()]; - case 1: - token = _a.sent(); - return [4 /*yield*/, this.access("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=".concat(token), { - method: 'POST', - headers: { - 'Content-type': 'application/json', - }, - body: JSON.stringify({ - code: code, - }), - })]; - case 2: - result = (_a.sent()); - return [2 /*return*/, result.phone_info]; - } - }); - }); - }; + return (await result.arrayBuffer()); + } + async getUserPhoneNumber(code) { + const token = await this.getAccessToken(); + const result = (await this.access(`https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=${token}`, { + method: 'POST', + headers: { + 'Content-type': 'application/json', + }, + body: JSON.stringify({ + code, + }), + })); + return result.phone_info; + } /** * 发送订阅消息 * @param param0 * @returns * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/sendMessage.html */ - WechatMpInstance.prototype.sendSubscribedMessage = function (_a) { - var templateId = _a.templateId, page = _a.page, openId = _a.openId, data = _a.data, state = _a.state, lang = _a.lang; - return tslib_1.__awaiter(this, void 0, void 0, function () { - var token; - return tslib_1.__generator(this, function (_b) { - switch (_b.label) { - case 0: return [4 /*yield*/, this.getAccessToken()]; - case 1: - token = _b.sent(); - /** - * 实测,若用户未订阅,会抛出errcode: 43101, errmsg: user refuse to accept the msg - */ - return [2 /*return*/, this.access("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=".concat(token), { - body: JSON.stringify({ - template_id: templateId, - page: page, - touser: openId, - data: data, - miniprogram_state: state || 'formal', - lang: lang || 'zh_CN', - }), - method: 'post', - })]; - } - }); + async sendSubscribedMessage({ templateId, page, openId, data, state, lang, }) { + const token = await this.getAccessToken(); + /** + * 实测,若用户未订阅,会抛出errcode: 43101, errmsg: user refuse to accept the msg + */ + return this.access(`https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=${token}`, { + body: JSON.stringify({ + template_id: templateId, + page, + touser: openId, + data, + miniprogram_state: state || 'formal', + lang: lang || 'zh_CN', + }), + method: 'post', }); - }; - return WechatMpInstance; -}()); + } +} exports.WechatMpInstance = WechatMpInstance; diff --git a/lib/service/wechat/WechatPublic.d.ts b/lib/service/wechat/WechatPublic.d.ts index 9b2b024..1916f9d 100644 --- a/lib/service/wechat/WechatPublic.d.ts +++ b/lib/service/wechat/WechatPublic.d.ts @@ -52,6 +52,12 @@ export declare class WechatPublicInstance { gender: string | undefined; avatar: string; }>; + getTags(): Promise; + getCurrentMenu(): Promise; + getMenu(): Promise; + createMenu(menuConfig: any): Promise; + createConditionalMenu(menuConfig: any): Promise; + deleteConditionalMenu(menuid: number): Promise; private refreshAccessToken; decryptData(sessionKey: string, encryptedData: string, iv: string, signature: string): any; getQrCode(options: { @@ -81,6 +87,23 @@ export declare class WechatPublicInstance { count: number; noContent?: 0 | 1; }): Promise; + getArticle(options: { + article_id: string; + }): Promise; + createMaterial(options: { + type: 'image' | 'voice' | 'video' | 'thumb'; + media: FormData; + description?: FormData; + }): Promise; + batchGetMaterialList(options: { + type: 'image' | 'video' | 'voice' | 'news'; + offset?: number; + count: number; + }): Promise; + getMaterial(options: { + type: 'image' | 'video' | 'voice' | 'news'; + media_id: string; + }): Promise; getTicket(): Promise; private randomString; signatureJsSDK(options: { diff --git a/lib/service/wechat/WechatPublic.js b/lib/service/wechat/WechatPublic.js index 7f05683..fab6ccc 100644 --- a/lib/service/wechat/WechatPublic.js +++ b/lib/service/wechat/WechatPublic.js @@ -1,12 +1,18 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WechatPublicInstance = void 0; -var tslib_1 = require("tslib"); +const tslib_1 = require("tslib"); require('../../fetch'); -var crypto_1 = tslib_1.__importDefault(require("crypto")); -var buffer_1 = require("buffer"); -var WechatPublicInstance = /** @class */ (function () { - function WechatPublicInstance(appId, appSecret, accessToken, externalRefreshFn) { +const crypto_1 = tslib_1.__importDefault(require("crypto")); +const buffer_1 = require("buffer"); +const url_1 = tslib_1.__importDefault(require("url")); +class WechatPublicInstance { + appId; + appSecret; + accessToken; + refreshAccessTokenHandler; + externalRefreshFn; + constructor(appId, appSecret, accessToken, externalRefreshFn) { this.appId = appId; this.appSecret = appSecret; this.externalRefreshFn = externalRefreshFn; @@ -20,520 +26,525 @@ var WechatPublicInstance = /** @class */ (function () { this.refreshAccessToken(); } } - WechatPublicInstance.prototype.getAccessToken = function () { - return tslib_1.__awaiter(this, void 0, void 0, function () { - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - if (!true) return [3 /*break*/, 2]; - if (this.accessToken) { - return [2 /*return*/, this.accessToken]; - } - return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(0); }, 500); })]; - case 1: - _a.sent(); - return [3 /*break*/, 0]; - case 2: return [2 /*return*/]; + async getAccessToken() { + while (true) { + if (this.accessToken) { + return this.accessToken; + } + await new Promise((resolve) => setTimeout(() => resolve(0), 500)); + } + } + async access(url, mockData, init) { + if (process.env.NODE_ENV === 'development' && mockData) { + return mockData; + } + const response = await global.fetch(url, init); + const { headers, status } = response; + if (![200, 201].includes(status)) { + throw new Error(`微信服务器返回不正确应答:${status}`); + } + const contentType = headers['Content-Type'] || headers.get('Content-Type'); + if (contentType.includes('application/json')) { + const json = await response.json(); + if (typeof json.errcode === 'number' && json.errcode !== 0) { + if ([40001, 42001].includes(json.errcode)) { + return this.refreshAccessToken(url, init); } - }); - }); - }; - WechatPublicInstance.prototype.access = function (url, mockData, init) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var response, headers, status, contentType, json, data; - return tslib_1.__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) { - if ([40001, 42001].includes(json.errcode)) { - return [2 /*return*/, this.refreshAccessToken(url, init)]; - } - 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 tslib_1.__awaiter(this, void 0, void 0, function () { - var result, _a, access_token, openid, unionid, scope, refresh_token, is_snapshotuser, expires_in; - return tslib_1.__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"), { - access_token: 'aaa', - openid: code, - unionid: code, - refresh_token: 'aaa', - is_snapshotuser: false, - expires_in: 30, - scope: 'userinfo', - })]; - case 1: - result = _b.sent(); - _a = typeof result === 'string' ? JSON.parse(result) : result, access_token = _a.access_token, openid = _a.openid, unionid = _a.unionid, scope = _a.scope, refresh_token = _a.refresh_token, is_snapshotuser = _a.is_snapshotuser, expires_in = _a.expires_in; - return [2 /*return*/, { - accessToken: access_token, - openId: openid, - unionId: unionid, - scope: scope, - refreshToken: refresh_token, - isSnapshotUser: !!is_snapshotuser, - atExpiredAt: Date.now() + expires_in * 1000, - rtExpiredAt: Date.now() + 30 * 86400 * 1000, - }]; - } - }); - }); - }; - WechatPublicInstance.prototype.refreshUserAccessToken = function (refreshToken) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var result, access_token, refresh_token, expires_in, scope; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=".concat(this.appId, "&grant_type=refresh_token&refresh_token=").concat(refreshToken), { - access_token: 'aaa', - refresh_token: 'aaa', - expires_in: 30, - scope: 'userinfo', - })]; - case 1: - result = _a.sent(); - access_token = result.access_token, refresh_token = result.refresh_token, expires_in = result.expires_in, scope = result.scope; - return [2 /*return*/, { - accessToken: access_token, - refreshToken: refresh_token, - atExpiredAt: Date.now() + expires_in * 1000, - scope: scope, - }]; - } - }); - }); - }; - WechatPublicInstance.prototype.getUserInfo = function (accessToken, openId) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var result, nickname, sex, headimgurl; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.access("https://api.weixin.qq.com/sns/userinfo?access_token=".concat(accessToken, "&openid=").concat(openId, "&lang=zh_CN"), { - nickname: '码农哥', - sex: 1, - headimgurl: 'https://www.ertongzy.com/uploads/allimg/161005/2021233Y7-0.jpg', - })]; - case 1: - result = _a.sent(); - nickname = result.nickname, sex = result.sex, headimgurl = result.headimgurl; - return [2 /*return*/, { - nickname: nickname, - gender: sex === 1 ? 'male' : sex === 2 ? 'female' : undefined, - avatar: headimgurl, - }]; - } - }); - }); - }; - WechatPublicInstance.prototype.refreshAccessToken = function (url, init) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var result, _a, access_token, expires_in; - var _this = this; - return tslib_1.__generator(this, function (_b) { - switch (_b.label) { - case 0: - if (!this.externalRefreshFn) return [3 /*break*/, 2]; - return [4 /*yield*/, this.externalRefreshFn(this.appId)]; - case 1: - _a = _b.sent(); - return [3 /*break*/, 4]; - case 2: 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: 600 })]; - case 3: - _a = _b.sent(); - _b.label = 4; - case 4: - result = _a; - access_token = result.access_token, expires_in = result.expires_in; - this.accessToken = access_token; - // 生成下次刷新的定时器 - console.log((expires_in - 10) * 1000); - this.refreshAccessTokenHandler = setTimeout(function () { - _this.refreshAccessToken(); - }, (expires_in - 10) * 1000); - if (url) { - return [2 /*return*/, this.access(url, {}, init)]; - } - return [2 /*return*/]; - } - }); - }); - }; - WechatPublicInstance.prototype.decryptData = function (sessionKey, encryptedData, iv, signature) { - var skBuf = buffer_1.Buffer.from(sessionKey, 'base64'); + throw new Error(`调用微信接口返回出错,code是${json.errcode},信息是${json.errmsg}`); + } + return json; + } + if (contentType.includes('text') || + contentType.includes('xml') || + contentType.includes('html')) { + const data = await response.text(); + return data; + } + if (contentType.includes('application/octet-stream')) { + return await response.arrayBuffer(); + } + return response; + } + async code2Session(code) { + 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 { access_token, openid, unionid, scope, refresh_token, is_snapshotuser, expires_in, } = typeof result === 'string' ? JSON.parse(result) : result; // 这里微信返回的数据有时候竟然是text/plain + return { + accessToken: access_token, + openId: openid, + unionId: unionid, + scope: scope, + refreshToken: refresh_token, + isSnapshotUser: !!is_snapshotuser, + atExpiredAt: Date.now() + expires_in * 1000, + rtExpiredAt: Date.now() + 30 * 86400 * 1000, + }; + } + async refreshUserAccessToken(refreshToken) { + const result = await this.access(`https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${this.appId}&grant_type=refresh_token&refresh_token=${refreshToken}`); + const { access_token, refresh_token, expires_in, scope } = result; + return { + accessToken: access_token, + refreshToken: refresh_token, + atExpiredAt: Date.now() + expires_in * 1000, + scope: scope, + }; + } + async getUserInfo(accessToken, openId) { + const result = await this.access(`https://api.weixin.qq.com/sns/userinfo?access_token=${accessToken}&openid=${openId}&lang=zh_CN`); + const { nickname, sex, headimgurl } = result; + return { + nickname: nickname, + gender: sex === 1 ? 'male' : sex === 2 ? 'female' : undefined, + avatar: headimgurl, + }; + } + async getTags() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/tags/get?access_token=${token}`, undefined, myInit); + return result; + } + async getCurrentMenu() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=${token}`, undefined, myInit); + return result; + } + async getMenu() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/menu/get?access_token=${token}`, undefined, myInit); + return result; + } + async createMenu(menuConfig) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(menuConfig), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + async createConditionalMenu(menuConfig) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(menuConfig), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + async deleteConditionalMenu(menuid) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + menuid + }), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + async refreshAccessToken(url, init) { + const result = this.externalRefreshFn + ? await this.externalRefreshFn(this.appId) + : await this.access(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`); + const { access_token, expires_in } = result; + this.accessToken = access_token; + // 生成下次刷新的定时器 + console.log((expires_in - 10) * 1000); + this.refreshAccessTokenHandler = setTimeout(() => { + this.refreshAccessToken(); + }, (expires_in - 10) * 1000); + if (url) { + const url2 = new url_1.default.URL(url); + url2.searchParams.set('access_token', access_token); + return this.access(url2.toString(), {}, init); + } + } + decryptData(sessionKey, encryptedData, iv, signature) { + const 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); + const ivBuf = buffer_1.Buffer.from(iv, 'base64'); + const decipher = crypto_1.default.createDecipheriv('aes-128-cbc', skBuf, ivBuf); // 设置自动 padding 为 true,删除填充补位 decipher.setAutoPadding(true); - var decoded = decipher.update(encryptedData, 'base64', 'utf8'); + let decoded = decipher.update(encryptedData, 'base64', 'utf8'); decoded += decipher.final('utf8'); - var data = JSON.parse(decoded); + const data = JSON.parse(decoded); if (data.watermark.appid !== this.appId) { throw new Error('Illegal Buffer'); } return data; - }; - WechatPublicInstance.prototype.getQrCode = function (options) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var sceneId, sceneStr, expireSeconds, isPermanent, scene, actionName, myInit, token, result; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - sceneId = options.sceneId, sceneStr = options.sceneStr, expireSeconds = options.expireSeconds, isPermanent = options.isPermanent; - if (!sceneId && !sceneStr) { - throw new Error('Missing sceneId or sceneStr'); - } - scene = sceneId - ? { - scene_id: sceneId, - } - : { - scene_str: sceneStr, - }; - actionName = sceneId ? 'QR_SCENE' : 'QR_STR_SCENE'; - myInit = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - expire_seconds: expireSeconds, - action_name: actionName, - action_info: { - scene: scene, + } + async getQrCode(options) { + const { sceneId, sceneStr, expireSeconds, isPermanent } = options; + if (!sceneId && !sceneStr) { + throw new Error('Missing sceneId or sceneStr'); + } + const scene = sceneId + ? { + scene_id: sceneId, + } + : { + scene_str: sceneStr, + }; + let actionName = sceneId ? 'QR_SCENE' : 'QR_STR_SCENE'; + let myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + expire_seconds: expireSeconds, + action_name: actionName, + action_info: { + scene, + }, + }), + }; + if (isPermanent) { + actionName = sceneId ? 'QR_LIMIT_SCENE' : 'QR_LIMIT_STR_SCENE'; + myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + action_name: actionName, + action_info: { + scene, + }, + }), + }; + } + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=${token}`, + // { + // ticket: `ticket${Date.now()}`, + // url: `http://mock/q/${sceneId ? sceneId : sceneStr}`, + // expireSeconds: expireSeconds, + // }, + myInit); + return { + ticket: result.ticket, + url: result.url, + expireSeconds: result.expire_seconds, + }; + } + async sendTemplateMessage(options) { + const { openId, templateId, url, data, miniProgram, clientMsgId } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + touser: openId, + template_id: templateId, + url, + miniProgram, + client_msg_id: clientMsgId, + data, + }), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${token}`, + // { + // errcode: 0, + // errmsg: 'ok', + // msgid: Date.now(), + // }, + myInit); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + async sendServeMessage(options) { + const { openId, type } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }; + switch (type) { + case 'text': { + Object.assign(myInit, { + body: JSON.stringify({ + touser: openId, + msgtype: 'text', + text: { + content: options.content, + }, + }), + }); + break; + } + case 'news': { + Object.assign(myInit, { + body: JSON.stringify({ + touser: openId, + msgtype: 'news', + news: { + articles: [ + { + title: options.title, + description: options.description, + url: options.url, + picurl: options.picurl, }, - }), - }; - if (isPermanent) { - actionName = sceneId ? 'QR_LIMIT_SCENE' : 'QR_LIMIT_STR_SCENE'; - myInit = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - action_name: actionName, - action_info: { - scene: scene, - }, - }), - }; - } - return [4 /*yield*/, this.getAccessToken()]; - case 1: - token = _a.sent(); - return [4 /*yield*/, this.access("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".concat(token), { - ticket: "ticket".concat(Date.now()), - url: "http://mock/q/".concat(sceneId ? sceneId : sceneStr), - expireSeconds: expireSeconds, - }, myInit)]; - case 2: - result = _a.sent(); - return [2 /*return*/, { - ticket: result.ticket, - url: result.url, - expireSeconds: result.expire_seconds, - }]; - } + ], + }, + }), + }); + break; + } + case 'mp': { + Object.assign(myInit, { + body: JSON.stringify({ + touser: openId, + msgtype: 'miniprogrampage', + miniprogrampage: { + title: options.data.title, + appid: options.data.appId, + pagepath: options.data.pagepath, + thumb_media_id: options.data.thumbnailId, + }, + }), + }); + break; + } + default: { + throw new Error('当前消息类型暂不支持'); + } + } + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${token}`, + // { + // errcode: 0, + // errmsg: 'ok', + // }, + myInit); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + async batchGetArticle(options) { + const { offset, count, noContent } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + offset, + count, + no_content: noContent, + }), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/freepublish/batchget?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + async getArticle(options) { + const { article_id } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + article_id, + }), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/freepublish/getarticle?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + async createMaterial(options) { + const { type, media, description } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }; + if (type === 'video') { + Object.assign(myInit, { + body: JSON.stringify({ + type, + media, + description, + }), }); - }); - }; - WechatPublicInstance.prototype.sendTemplateMessage = function (options) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var openId, templateId, url, data, miniProgram, clientMsgId, myInit, token, result, errcode; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - openId = options.openId, templateId = options.templateId, url = options.url, data = options.data, miniProgram = options.miniProgram, clientMsgId = options.clientMsgId; - myInit = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - touser: openId, - template_id: templateId, - url: url, - miniProgram: miniProgram, - client_msg_id: clientMsgId, - data: data, - }), - }; - return [4 /*yield*/, this.getAccessToken()]; - case 1: - token = _a.sent(); - return [4 /*yield*/, this.access("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".concat(token), { - errcode: 0, - errmsg: 'ok', - msgid: Date.now(), - }, myInit)]; - case 2: - result = _a.sent(); - errcode = result.errcode; - if (errcode === 0) { - return [2 /*return*/, Object.assign({ success: true }, result)]; - } - return [2 /*return*/, Object.assign({ success: false }, result)]; - } + } + else { + Object.assign(myInit, { + body: JSON.stringify({ + type, + media, + }), }); - }); - }; - WechatPublicInstance.prototype.sendServeMessage = function (options) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var openId, type, myInit, token, result, errcode; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - openId = options.openId, type = options.type; - myInit = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - }; - switch (type) { - case 'text': { - Object.assign(myInit, { - body: JSON.stringify({ - touser: openId, - msgtype: 'text', - text: { - content: options.content, - }, - }), - }); - break; - } - case 'news': { - Object.assign(myInit, { - body: JSON.stringify({ - touser: openId, - msgtype: 'news', - news: { - articles: [ - { - title: options.title, - description: options.description, - url: options.url, - picurl: options.picurl, - }, - ], - }, - }), - }); - break; - } - case 'mp': { - Object.assign(myInit, { - body: JSON.stringify({ - touser: openId, - msgtype: 'miniprogrampage', - miniprogrampage: { - title: options.data.title, - appid: options.data.appId, - pagepath: options.data.pagepath, - thumb_media_id: options.data.thumbnailId, - }, - }), - }); - break; - } - default: { - throw new Error('当前消息类型暂不支持'); - } - } - return [4 /*yield*/, this.getAccessToken()]; - case 1: - token = _a.sent(); - return [4 /*yield*/, this.access("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".concat(token), { - errcode: 0, - errmsg: 'ok', - }, myInit)]; - case 2: - result = _a.sent(); - errcode = result.errcode; - if (errcode === 0) { - return [2 /*return*/, Object.assign({ success: true }, result)]; - } - return [2 /*return*/, Object.assign({ success: false }, result)]; - } - }); - }); - }; - WechatPublicInstance.prototype.batchGetArticle = function (options) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var offset, count, noContent, myInit, token, result, errcode; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - offset = options.offset, count = options.count, noContent = options.noContent; - myInit = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - offset: offset, - count: count, - no_content: noContent, - }), - }; - return [4 /*yield*/, this.getAccessToken()]; - case 1: - token = _a.sent(); - return [4 /*yield*/, this.access("https://api.weixin.qq.com/cgi-bin/freepublish/batchget?access_token=".concat(token), { - total_count: 1, - item_count: 1, - item: [ - { - article_id: 'test', - content: { - news_item: [ - { - title: '测试文章', - author: '测试作者', - digest: '测试摘要', - content: '测试内容', - content_source_url: '', - thumb_media_id: 'TEST_MEDIA_ID', - show_cover_pic: 1, - need_open_comment: 0, - only_fans_can_comment: 0, - url: 'TEST_ARTICLE_URL', - is_deleted: false, - }, - ], - }, - update_time: Date.now(), - }, - ], - }, myInit)]; - case 2: - result = _a.sent(); - errcode = result.errcode; - if (!errcode) { - return [2 /*return*/, result]; - } - throw new Error(JSON.stringify(result)); - } - }); - }); - }; - WechatPublicInstance.prototype.getTicket = function () { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var myInit, token, result, ticket; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - myInit = { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }; - return [4 /*yield*/, this.getAccessToken()]; - case 1: - token = _a.sent(); - return [4 /*yield*/, this.access("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=".concat(token, "&type=jsapi"), { - ticket: "ticket".concat(Date.now()), - expires_in: 30, - }, myInit)]; - case 2: - result = (_a.sent()); - ticket = result.ticket; - return [2 /*return*/, ticket]; - } - }); - }); - }; - WechatPublicInstance.prototype.randomString = function () { - var len = 16; - var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; + } + ; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + async batchGetMaterialList(options) { + const { offset, count, type } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + type, + offset, + count, + }), + }; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=${token}`, undefined, myInit); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + async getMaterial(options) { + const { type, media_id } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + media_id + }), + }; + let imgFile; + const token = await this.getAccessToken(); + const result = await this.access(`https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=${token}`, undefined, myInit); + if ('errcode' in result) { + throw new Error(JSON.stringify(result)); + } + else { + return result; + } + } + async getTicket() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = (await this.access(`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${token}&type=jsapi`, + // { + // ticket: `ticket${Date.now()}`, + // expires_in: 30, + // }, + myInit)); + const { ticket } = result; + return ticket; + } + randomString() { + let len = 16; + let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; /** **默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/ - var maxPos = $chars.length; - var pwd = ''; - for (var i = 0; i < len; i++) { + let maxPos = $chars.length; + let pwd = ''; + for (let i = 0; i < len; i++) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; - }; - WechatPublicInstance.prototype.signatureJsSDK = function (options) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var url, noncestr, timestamp, jsapi_ticket, contentArray, zhimaString; - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - url = options.url; - noncestr = this.randomString(); - timestamp = parseInt((Date.now() / 1000).toString(), 10); - return [4 /*yield*/, this.getTicket()]; - case 1: - jsapi_ticket = _a.sent(); - contentArray = { - noncestr: noncestr, - jsapi_ticket: jsapi_ticket, - timestamp: timestamp, - url: url, - }; - zhimaString = ''; - Object.keys(contentArray) - .sort() - .forEach(function (ele, idx) { - if (idx > 0) { - zhimaString += '&'; - } - zhimaString += ele; - zhimaString += '='; - zhimaString += contentArray[ele]; - }); - return [2 /*return*/, { - signature: crypto_1.default - .createHash('sha1') - .update(zhimaString) - .digest('hex'), - noncestr: noncestr, - timestamp: timestamp, - appId: this.appId, - }]; - } - }); + } + async signatureJsSDK(options) { + const url = options.url; + const noncestr = this.randomString(); + const timestamp = parseInt((Date.now() / 1000).toString(), 10); + const jsapi_ticket = await this.getTicket(); + const contentArray = { + noncestr, + jsapi_ticket, + timestamp, + url, + }; + let zhimaString = ''; + Object.keys(contentArray) + .sort() + .forEach((ele, idx) => { + if (idx > 0) { + zhimaString += '&'; + } + zhimaString += ele; + zhimaString += '='; + zhimaString += contentArray[ele]; }); - }; - return WechatPublicInstance; -}()); + return { + signature: crypto_1.default + .createHash('sha1') + .update(zhimaString) + .digest('hex'), + noncestr, + timestamp, + appId: this.appId, + }; + } +} exports.WechatPublicInstance = WechatPublicInstance; diff --git a/lib/service/wechat/WechatWeb.js b/lib/service/wechat/WechatWeb.js index 598886e..245eb99 100644 --- a/lib/service/wechat/WechatWeb.js +++ b/lib/service/wechat/WechatWeb.js @@ -1,12 +1,17 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WechatWebInstance = void 0; -var tslib_1 = require("tslib"); +const tslib_1 = require("tslib"); require('../../fetch'); -var crypto_1 = tslib_1.__importDefault(require("crypto")); -var buffer_1 = require("buffer"); -var WechatWebInstance = /** @class */ (function () { - function WechatWebInstance(appId, appSecret, accessToken, externalRefreshFn) { +const crypto_1 = tslib_1.__importDefault(require("crypto")); +const buffer_1 = require("buffer"); +class WechatWebInstance { + appId; + appSecret; + accessToken; + refreshAccessTokenHandler; + externalRefreshFn; + constructor(appId, appSecret, accessToken, externalRefreshFn) { this.appId = appId; this.appSecret = appSecret; this.externalRefreshFn = externalRefreshFn; @@ -20,134 +25,80 @@ var WechatWebInstance = /** @class */ (function () { this.refreshAccessToken(); } } - WechatWebInstance.prototype.getAccessToken = function () { - return tslib_1.__awaiter(this, void 0, void 0, function () { - return tslib_1.__generator(this, function (_a) { - switch (_a.label) { - case 0: - if (!true) return [3 /*break*/, 2]; - if (this.accessToken) { - return [2 /*return*/, this.accessToken]; - } - return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(0); }, 500); })]; - case 1: - _a.sent(); - return [3 /*break*/, 0]; - case 2: return [2 /*return*/]; + async getAccessToken() { + while (true) { + if (this.accessToken) { + return this.accessToken; + } + await new Promise((resolve) => setTimeout(() => resolve(0), 500)); + } + } + async access(url, mockData, init) { + if (process.env.NODE_ENV === 'development') { + return mockData; + } + const response = await global.fetch(url, init); + const { headers, status } = response; + if (![200, 201].includes(status)) { + throw new Error(`微信服务器返回不正确应答:${status}`); + } + const contentType = headers['Content-Type'] || headers.get('Content-Type'); + if (contentType.includes('application/json')) { + const json = await response.json(); + if (typeof json.errcode === 'number' && json.errcode !== 0) { + if ([40001, 42001].includes(json.errcode)) { + return this.refreshAccessToken(); } - }); - }); - }; - WechatWebInstance.prototype.access = function (url, mockData, init) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var response, headers, status, contentType, json, data; - return tslib_1.__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) { - if ([40001, 42001].includes(json.errcode)) { - return [2 /*return*/, this.refreshAccessToken()]; - } - 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 tslib_1.__awaiter(this, void 0, void 0, function () { - var result, _a, session_key, openid, unionid; - return tslib_1.__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 (url, init) { - return tslib_1.__awaiter(this, void 0, void 0, function () { - var result, _a, access_token, expires_in; - var _this = this; - return tslib_1.__generator(this, function (_b) { - switch (_b.label) { - case 0: - if (!this.externalRefreshFn) return [3 /*break*/, 2]; - return [4 /*yield*/, this.externalRefreshFn(this.appId)]; - case 1: - _a = _b.sent(); - return [3 /*break*/, 4]; - case 2: 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: 600 })]; - case 3: - _a = _b.sent(); - _b.label = 4; - case 4: - result = _a; - access_token = result.access_token, expires_in = result.expires_in; - this.accessToken = access_token; - // 生成下次刷新的定时器 - this.refreshAccessTokenHandler = setTimeout(function () { - _this.refreshAccessToken(); - }, (expires_in - 10) * 1000); - if (url) { - return [2 /*return*/, this.access(url, init)]; - } - return [2 /*return*/]; - } - }); - }); - }; - WechatWebInstance.prototype.decryptData = function (sessionKey, encryptedData, iv, signature) { - var skBuf = buffer_1.Buffer.from(sessionKey, 'base64'); + throw new Error(`调用微信接口返回出错,code是${json.errcode},信息是${json.errmsg}`); + } + return json; + } + if (contentType.includes('text') || + contentType.includes('xml') || + contentType.includes('html')) { + const data = await response.text(); + return data; + } + if (contentType.includes('application/octet-stream')) { + return await response.arrayBuffer(); + } + return response; + } + async code2Session(code) { + 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, + openId: openid, + unionId: unionid, + }; + } + async refreshAccessToken(url, init) { + const result = this.externalRefreshFn ? await this.externalRefreshFn(this.appId) : 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: 600 }); + const { access_token, expires_in } = result; + this.accessToken = access_token; + // 生成下次刷新的定时器 + this.refreshAccessTokenHandler = setTimeout(() => { + this.refreshAccessToken(); + }, (expires_in - 10) * 1000); + if (url) { + return this.access(url, init); + } + } + decryptData(sessionKey, encryptedData, iv, signature) { + const 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); + const ivBuf = buffer_1.Buffer.from(iv, 'base64'); + const decipher = crypto_1.default.createDecipheriv('aes-128-cbc', skBuf, ivBuf); // 设置自动 padding 为 true,删除填充补位 decipher.setAutoPadding(true); - var decoded = decipher.update(encryptedData, 'base64', 'utf8'); + let decoded = decipher.update(encryptedData, 'base64', 'utf8'); decoded += decipher.final('utf8'); - var data = JSON.parse(decoded); + const 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/lib/types/index.js b/lib/types/index.js index e757bbd..966b2f7 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -1,4 +1,4 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var tslib_1 = require("tslib"); +const tslib_1 = require("tslib"); tslib_1.__exportStar(require("./Wechat"), exports); diff --git a/lib/utils/cheerio/index.js b/lib/utils/cheerio/index.js index 703a41c..911c836 100644 --- a/lib/utils/cheerio/index.js +++ b/lib/utils/cheerio/index.js @@ -1,5 +1,5 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.load = void 0; -var cheerio_1 = require("cheerio"); +const cheerio_1 = require("cheerio"); Object.defineProperty(exports, "load", { enumerable: true, get: function () { return cheerio_1.load; } }); diff --git a/lib/utils/cheerio/index.web.js b/lib/utils/cheerio/index.web.js index 703a41c..911c836 100644 --- a/lib/utils/cheerio/index.web.js +++ b/lib/utils/cheerio/index.web.js @@ -1,5 +1,5 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.load = void 0; -var cheerio_1 = require("cheerio"); +const cheerio_1 = require("cheerio"); Object.defineProperty(exports, "load", { enumerable: true, get: function () { return cheerio_1.load; } }); diff --git a/package.json b/package.json index 05d1b17..2b57f26 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "license": "ISC", "devDependencies": { - "@types/node": "^20.6.0", + "@types/node": "^20.6.1", "ts-node": "^10.9.1", "tslib": "^2.4.0", "typescript": "^5.2.2" diff --git a/src/service/wechat/WechatPublic.ts b/src/service/wechat/WechatPublic.ts index 104e264..a748b94 100644 --- a/src/service/wechat/WechatPublic.ts +++ b/src/service/wechat/WechatPublic.ts @@ -1,7 +1,7 @@ require('../../fetch'); import crypto from 'crypto'; import { Buffer } from 'buffer'; - +import URL from 'url'; // 目前先支持text和news, 其他type文档:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Service_Center_messages.html // type ServeMessageType = 'text' | 'news' | 'mpnews' | 'mpnewsarticle' | 'image' | 'voice' | 'video' | 'music' | 'msgmenu';/ type TextServeMessageOption = { @@ -72,10 +72,10 @@ export class WechatPublicInstance { private async access( url: string, - mockData: any, + mockData?: any, init?: RequestInit ): Promise { - if (process.env.NODE_ENV === 'development') { + if (process.env.NODE_ENV === 'development' && mockData) { return mockData; } const response = await global.fetch(url, init); @@ -116,15 +116,15 @@ 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`, - { - access_token: 'aaa', - openid: code, - unionid: code, - refresh_token: 'aaa', - is_snapshotuser: false, - expires_in: 30, - scope: 'userinfo', - } + // { + // access_token: 'aaa', + // openid: code, + // unionid: code, + // refresh_token: 'aaa', + // is_snapshotuser: false, + // expires_in: 30, + // scope: 'userinfo', + // } ); const { access_token, @@ -151,12 +151,12 @@ export class WechatPublicInstance { async refreshUserAccessToken(refreshToken: string) { const result = await this.access( `https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${this.appId}&grant_type=refresh_token&refresh_token=${refreshToken}`, - { - access_token: 'aaa', - refresh_token: 'aaa', - expires_in: 30, - scope: 'userinfo', - } + // { + // access_token: 'aaa', + // refresh_token: 'aaa', + // expires_in: 30, + // scope: 'userinfo', + // } ); const { access_token, refresh_token, expires_in, scope } = result; return { @@ -170,12 +170,12 @@ export class WechatPublicInstance { async getUserInfo(accessToken: string, openId: string) { const result = await this.access( `https://api.weixin.qq.com/sns/userinfo?access_token=${accessToken}&openid=${openId}&lang=zh_CN`, - { - nickname: '码农哥', - sex: 1, - headimgurl: - 'https://www.ertongzy.com/uploads/allimg/161005/2021233Y7-0.jpg', - } + // { + // nickname: '码农哥', + // sex: 1, + // headimgurl: + // 'https://www.ertongzy.com/uploads/allimg/161005/2021233Y7-0.jpg', + // } ); const { nickname, sex, headimgurl } = result; return { @@ -185,13 +185,128 @@ export class WechatPublicInstance { }; } + async getTags() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/tags/get?access_token=${token}`, + undefined, + myInit + ) + return result; + } + + async getCurrentMenu() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=${token}`, + undefined, + myInit + ) + return result; + } + + async getMenu() { + const myInit = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/menu/get?access_token=${token}`, + undefined, + myInit + ) + return result; + } + + async createMenu(menuConfig: any) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(menuConfig), + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${token}`, + undefined, + myInit + ); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + + async createConditionalMenu(menuConfig: any) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(menuConfig), + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=${token}`, + undefined, + myInit + ); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + + async deleteConditionalMenu(menuid: number) { + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + menuid + }), + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token=${token}`, + undefined, + myInit + ); + const { errcode } = result; + if (errcode === 0) { + return Object.assign({ success: true }, result); + } + return Object.assign({ success: false }, result); + } + + + private async refreshAccessToken(url?: string, init?: RequestInit) { const result = this.externalRefreshFn ? await this.externalRefreshFn(this.appId) : 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: 600 } - ); + `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`, + //{ access_token: 'mockToken', expires_in: 600 } + ); const { access_token, expires_in } = result; this.accessToken = access_token; // 生成下次刷新的定时器 @@ -200,7 +315,10 @@ export class WechatPublicInstance { this.refreshAccessToken(); }, (expires_in - 10) * 1000); if (url) { - return this.access(url, {}, init); + const url2= new URL.URL(url); + url2.searchParams.set('access_token', access_token) + + return this.access(url2.toString(), {}, init); } } @@ -241,11 +359,11 @@ export class WechatPublicInstance { } const scene = sceneId ? { - scene_id: sceneId, - } + scene_id: sceneId, + } : { - scene_str: sceneStr, - }; + scene_str: sceneStr, + }; let actionName = sceneId ? 'QR_SCENE' : 'QR_STR_SCENE'; let myInit = { method: 'POST', @@ -278,11 +396,11 @@ export class WechatPublicInstance { const token = await this.getAccessToken(); const result = await this.access( `https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=${token}`, - { - ticket: `ticket${Date.now()}`, - url: `http://mock/q/${sceneId ? sceneId : sceneStr}`, - expireSeconds: expireSeconds, - }, + // { + // ticket: `ticket${Date.now()}`, + // url: `http://mock/q/${sceneId ? sceneId : sceneStr}`, + // expireSeconds: expireSeconds, + // }, myInit ); @@ -322,11 +440,11 @@ export class WechatPublicInstance { const token = await this.getAccessToken(); const result = await this.access( `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${token}`, - { - errcode: 0, - errmsg: 'ok', - msgid: Date.now(), - }, + // { + // errcode: 0, + // errmsg: 'ok', + // msgid: Date.now(), + // }, myInit ); const { errcode } = result; @@ -397,10 +515,10 @@ export class WechatPublicInstance { const token = await this.getAccessToken(); const result = await this.access( `https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${token}`, - { - errcode: 0, - errmsg: 'ok', - }, + // { + // errcode: 0, + // errmsg: 'ok', + // }, myInit ); const { errcode } = result; @@ -429,33 +547,7 @@ export class WechatPublicInstance { const token = await this.getAccessToken(); const result = await this.access( `https://api.weixin.qq.com/cgi-bin/freepublish/batchget?access_token=${token}`, - { - total_count: 1, - item_count: 1, - item: [ - { - article_id: 'test', - content: { - news_item: [ - { - title: '测试文章', - author: '测试作者', - digest: '测试摘要', - content: '测试内容', - content_source_url: '', - thumb_media_id: 'TEST_MEDIA_ID', - show_cover_pic: 1, - need_open_comment: 0, - only_fans_can_comment: 0, - url: 'TEST_ARTICLE_URL', - is_deleted: false, - }, - ], - }, - update_time: Date.now(), - }, - ], - }, + undefined, myInit ); const { errcode } = result; @@ -465,6 +557,132 @@ export class WechatPublicInstance { throw new Error(JSON.stringify(result)); } + async getArticle(options: { + article_id: string, + }) { + const { article_id } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + article_id, + }), + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/freepublish/getarticle?access_token=${token}`, + undefined, + myInit + ); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + + async createMaterial(options: { + type: 'image' | 'voice' | 'video' | 'thumb', + media: FormData, + description?: FormData + }) { + const { type, media, description } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }; + if (type === 'video') { + Object.assign(myInit, { + body: JSON.stringify({ + type, + media, + description, + }), + }); + } else { + Object.assign(myInit, { + body: JSON.stringify({ + type, + media, + }), + }); + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=${token}`, + undefined, + myInit, + ); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + + async batchGetMaterialList(options: { + type: 'image' | 'video' | 'voice' | 'news', + offset?: number; + count: number; + }) { + const { offset, count, type } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + type, + offset, + count, + }), + }; + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=${token}`, + undefined, + myInit + ); + const { errcode } = result; + if (!errcode) { + return result; + } + throw new Error(JSON.stringify(result)); + } + + async getMaterial(options: { + type: 'image' | 'video' | 'voice' | 'news', + media_id: string, + }) { + const { type, media_id } = options; + const myInit = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + media_id + }), + }; + let imgFile; + + const token = await this.getAccessToken(); + const result = await this.access( + `https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=${token}`, + undefined, + myInit + ); + if ('errcode' in result) { + throw new Error(JSON.stringify(result)); + } else { + return result; + } + } + async getTicket() { const myInit = { method: 'GET', @@ -475,10 +693,10 @@ export class WechatPublicInstance { const token = await this.getAccessToken(); const result = (await this.access( `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${token}&type=jsapi`, - { - ticket: `ticket${Date.now()}`, - expires_in: 30, - }, + // { + // ticket: `ticket${Date.now()}`, + // expires_in: 30, + // }, myInit )) as { ticket: string; diff --git a/tsconfig.json b/tsconfig.json index f598e06..fb9fc1f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "jsx": "preserve", /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "ES5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ + "target": "ESNext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "lib": [ "dom",