wechat-ts 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +3 -0
  2. package/dist/index.cjs +328 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +239 -0
  5. package/dist/index.d.ts +239 -0
  6. package/dist/index.global.js +321 -0
  7. package/dist/index.global.js.map +1 -0
  8. package/dist/index.js +283 -0
  9. package/dist/index.js.map +1 -0
  10. package/package.json +41 -0
  11. package/src/constants/index.ts +2 -0
  12. package/src/constants/wechat.ts +4 -0
  13. package/src/index.ts +5 -0
  14. package/src/jssdk/getJssdkConfig.ts +122 -0
  15. package/src/jssdk/index.ts +1 -0
  16. package/src/oauth2/authorize.ts +95 -0
  17. package/src/oauth2/index.ts +1 -0
  18. package/src/server/cgi-bin/getAccessToken.ts +28 -0
  19. package/src/server/cgi-bin/getStableAccessToken.ts +24 -0
  20. package/src/server/cgi-bin/index.ts +3 -0
  21. package/src/server/cgi-bin/message/index.ts +1 -0
  22. package/src/server/cgi-bin/message/template/index.ts +1 -0
  23. package/src/server/cgi-bin/message/template/sendTemplateMessage.ts +41 -0
  24. package/src/server/cgi-bin/ticket/getTicket.ts +28 -0
  25. package/src/server/cgi-bin/ticket/index.ts +1 -0
  26. package/src/server/index.ts +2 -0
  27. package/src/server/types/response.ts +4 -0
  28. package/src/server/utils/request.ts +25 -0
  29. package/src/server/utils/token.ts +21 -0
  30. package/src/sns/getUserInfo.ts +49 -0
  31. package/src/sns/index.ts +3 -0
  32. package/src/sns/snsAccessToken.ts +47 -0
  33. package/src/sns/snsUserInfo.ts +49 -0
  34. package/src/types/wechat-api.d.ts +164 -0
  35. package/src/utils/config.ts +35 -0
  36. package/src/utils/promise.ts +14 -0
  37. package/src/utils/request.ts +20 -0
  38. package/src/utils/string.ts +33 -0
  39. package/tsconfig.json +15 -0
  40. package/tsup.config.ts +11 -0
package/dist/index.js ADDED
@@ -0,0 +1,283 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __async = (__this, __arguments, generator) => {
21
+ return new Promise((resolve, reject) => {
22
+ var fulfilled = (value) => {
23
+ try {
24
+ step(generator.next(value));
25
+ } catch (e) {
26
+ reject(e);
27
+ }
28
+ };
29
+ var rejected = (value) => {
30
+ try {
31
+ step(generator.throw(value));
32
+ } catch (e) {
33
+ reject(e);
34
+ }
35
+ };
36
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
+ step((generator = generator.apply(__this, __arguments)).next());
38
+ });
39
+ };
40
+
41
+ // src/constants/index.ts
42
+ var baseDemain = "https://api.weixin.qq.com";
43
+
44
+ // src/utils/request.ts
45
+ function requestGetBase(url, params, options = {}) {
46
+ const urlParams = new URLSearchParams(params);
47
+ return requestBase(`${url}?${urlParams}`, __spreadProps(__spreadValues({}, options), { method: "GET" }));
48
+ }
49
+ function requestPostBase(url, data, options = {}) {
50
+ return requestBase(url, __spreadProps(__spreadValues({}, options), { method: "POST", body: JSON.stringify(data) }));
51
+ }
52
+ function requestBase(_0) {
53
+ return __async(this, arguments, function* (url, options = {}) {
54
+ const res = yield fetch(`${baseDemain}${url}`, options);
55
+ return yield res.json();
56
+ });
57
+ }
58
+
59
+ // src/server/cgi-bin/getAccessToken.ts
60
+ function getAccessToken(data) {
61
+ return requestPostBase("/cgi-bin/token", data);
62
+ }
63
+
64
+ // src/server/cgi-bin/getStableAccessToken.ts
65
+ function getStableAccessToken(data) {
66
+ return requestPostBase("/cgi-bin/stable_token", data);
67
+ }
68
+
69
+ // src/utils/config.ts
70
+ var appId = "";
71
+ var appSecret = "";
72
+ function setConfig(config) {
73
+ appId = config.appId;
74
+ appSecret = config.appSecret;
75
+ }
76
+ function getConfig() {
77
+ if (!appId || !appSecret) {
78
+ throw new Error("\u8BF7\u5148\u8C03\u7528setConfig\u914D\u7F6EappId/appSecret");
79
+ }
80
+ return {
81
+ appId,
82
+ appSecret
83
+ };
84
+ }
85
+
86
+ // src/server/utils/token.ts
87
+ var token = "";
88
+ var expires = 0;
89
+ function getToken() {
90
+ return __async(this, null, function* () {
91
+ const { appId: appId2, appSecret: appSecret2 } = getConfig();
92
+ const now = Date.now();
93
+ if (expires < now) {
94
+ const resToken = yield getStableAccessToken({
95
+ appid: appId2,
96
+ secret: appSecret2,
97
+ grant_type: "client_credential"
98
+ });
99
+ token = resToken.access_token;
100
+ expires = now + resToken.expires_in * 950;
101
+ }
102
+ return token;
103
+ });
104
+ }
105
+
106
+ // src/server/utils/request.ts
107
+ function urlAddToken(url) {
108
+ return __async(this, null, function* () {
109
+ if (url.includes("?")) {
110
+ url += "&";
111
+ }
112
+ url += `access_token=${yield getToken()}`;
113
+ return url;
114
+ });
115
+ }
116
+ function requestGet(url, params, options) {
117
+ return __async(this, null, function* () {
118
+ return requestGetBase(yield urlAddToken(url), params, options);
119
+ });
120
+ }
121
+ function requestPost(url, data, options) {
122
+ return __async(this, null, function* () {
123
+ return requestPostBase(yield urlAddToken(url), data, options);
124
+ });
125
+ }
126
+
127
+ // src/server/cgi-bin/message/template/sendTemplateMessage.ts
128
+ function sendTemplateMessage(params) {
129
+ return requestPost("/cgi-bin/message/template/send", params);
130
+ }
131
+
132
+ // src/sns/snsAccessToken.ts
133
+ function snsAccessToken(code) {
134
+ return __async(this, null, function* () {
135
+ const { appId: appId2, appSecret: appSecret2 } = getConfig();
136
+ return requestGetBase("/sns/oauth2/access_token", {
137
+ appid: appId2,
138
+ secret: appSecret2,
139
+ code,
140
+ grant_type: "authorization_code"
141
+ });
142
+ });
143
+ }
144
+
145
+ // src/sns/snsUserInfo.ts
146
+ function snsUserInfo(data) {
147
+ return __async(this, null, function* () {
148
+ const { access_token, openid, lang = "zh_CN" } = data;
149
+ return requestGetBase(`/sns/userinfo`, {
150
+ access_token,
151
+ openid,
152
+ lang
153
+ });
154
+ });
155
+ }
156
+
157
+ // src/sns/getUserInfo.ts
158
+ function getSnsUserInfo(code) {
159
+ return __async(this, null, function* () {
160
+ const tokenData = yield snsAccessToken(code);
161
+ const { access_token, openid } = tokenData;
162
+ if (!openid) {
163
+ throw new Error("\u83B7\u53D6openid\u5931\u8D25");
164
+ }
165
+ const userInfo = yield snsUserInfo({ access_token, openid });
166
+ if (userInfo.openid) {
167
+ return userInfo;
168
+ } else {
169
+ throw new Error("\u83B7\u53D6\u7528\u6237\u4FE1\u606F\u5931\u8D25");
170
+ }
171
+ });
172
+ }
173
+
174
+ // src/oauth2/authorize.ts
175
+ function getOauth2AuthorizeUrl(params) {
176
+ const { redirectUrl, state = "", responseType = "code", scope = "snsapi_userinfo" } = params;
177
+ const { appId: appId2 } = getConfig();
178
+ let url = `${baseDemain}/connect/oauth2/authorize?`;
179
+ url += `appid=${appId2}`;
180
+ url += `&redirect_uri=${encodeURIComponent(redirectUrl)}`;
181
+ url += `&response_type=${responseType}`;
182
+ url += `&scope=${scope}`;
183
+ url += `&state=${state}`;
184
+ url += `#wechat_redirect`;
185
+ const authorizeUrl = url;
186
+ return authorizeUrl;
187
+ }
188
+
189
+ // src/jssdk/getJssdkConfig.ts
190
+ import crypto from "crypto";
191
+
192
+ // src/server/cgi-bin/ticket/getTicket.ts
193
+ function getTicket(data) {
194
+ return requestGet("/cgi-bin/ticket/getticket", data);
195
+ }
196
+
197
+ // src/utils/string.ts
198
+ var createNonceStr = function() {
199
+ return Math.random().toString(36).substr(2, 15);
200
+ };
201
+ var createTimestamp = function() {
202
+ return Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3) + "";
203
+ };
204
+ var raw = function(args) {
205
+ var keys = Object.keys(args);
206
+ keys = keys.sort();
207
+ var newArgs = {};
208
+ keys.forEach(function(key) {
209
+ newArgs[key.toLowerCase()] = args[key];
210
+ });
211
+ var string = "";
212
+ var newKeys = Object.keys(newArgs);
213
+ for (var i = 0; i < newKeys.length; i++) {
214
+ var k = newKeys[i];
215
+ string += "&" + k + "=" + newArgs[k];
216
+ }
217
+ return string.substr(1);
218
+ };
219
+
220
+ // src/jssdk/getJssdkConfig.ts
221
+ function sign(data) {
222
+ var string = raw(data);
223
+ var shasum = crypto.createHash("sha1");
224
+ shasum.update(string);
225
+ return shasum.digest("hex");
226
+ }
227
+ var ticket;
228
+ var expires2 = 0;
229
+ function getJsTicket() {
230
+ return __async(this, null, function* () {
231
+ const now = Date.now();
232
+ if (expires2 < now) {
233
+ const res = yield getTicket({ type: "jsapi" });
234
+ if (res.errcode === 0) {
235
+ ticket = res.ticket;
236
+ expires2 = now + res.expires_in * 950;
237
+ }
238
+ }
239
+ return ticket;
240
+ });
241
+ }
242
+ function getJssdkConfig(params) {
243
+ return __async(this, null, function* () {
244
+ const { url, jsApiList = ["updateAppMessageShareData", "updateTimelineShareData"] } = params;
245
+ if (!url) throw new Error("\u7F3A\u5C11\u53C2\u6570 url");
246
+ const jsapi_ticket = yield getJsTicket();
247
+ const timestamp = createTimestamp();
248
+ const nonceStr = createNonceStr();
249
+ const signature = sign({ jsapi_ticket, url, nonceStr, timestamp });
250
+ const { appId: appId2 } = getConfig();
251
+ return {
252
+ appId: appId2,
253
+ timestamp,
254
+ nonceStr,
255
+ signature,
256
+ jsApiList
257
+ };
258
+ });
259
+ }
260
+ export {
261
+ appId,
262
+ appSecret,
263
+ getAccessToken,
264
+ getConfig,
265
+ getJssdkConfig,
266
+ getOauth2AuthorizeUrl,
267
+ getSnsUserInfo,
268
+ getStableAccessToken,
269
+ sendTemplateMessage,
270
+ setConfig,
271
+ snsAccessToken,
272
+ snsUserInfo
273
+ };
274
+ /*!
275
+ * 生成随机字符串
276
+ */
277
+ /*!
278
+ * 生成时间戳
279
+ */
280
+ /*!
281
+ * 排序查询字符串
282
+ */
283
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants/index.ts","../src/utils/request.ts","../src/server/cgi-bin/getAccessToken.ts","../src/server/cgi-bin/getStableAccessToken.ts","../src/utils/config.ts","../src/server/utils/token.ts","../src/server/utils/request.ts","../src/server/cgi-bin/message/template/sendTemplateMessage.ts","../src/sns/snsAccessToken.ts","../src/sns/snsUserInfo.ts","../src/sns/getUserInfo.ts","../src/oauth2/authorize.ts","../src/jssdk/getJssdkConfig.ts","../src/server/cgi-bin/ticket/getTicket.ts","../src/utils/string.ts"],"sourcesContent":["/** 基础域名 */\nexport const baseDemain = 'https://api.weixin.qq.com'\n","import { baseDemain } from '../constants'\r\nexport function requestGetBase<T>(\r\n url: string,\r\n params: Record<string, any>,\r\n options: RequestInit = {}\r\n) {\r\n const urlParams = new URLSearchParams(params)\r\n return requestBase<T>(`${url}?${urlParams}`, { ...options, method: 'GET' })\r\n}\r\nexport function requestPostBase<T>(\r\n url: string,\r\n data: Record<string, any>,\r\n options: RequestInit = {}\r\n) {\r\n return requestBase<T>(url, { ...options, method: 'POST', body: JSON.stringify(data) })\r\n}\r\nexport async function requestBase<T>(url: string, options: RequestInit = {}) {\r\n const res = await fetch(`${baseDemain}${url}`, options)\r\n return (await res.json()) as T\r\n}\r\n","import { requestPostBase } from \"../../utils/request\"\r\n\r\n/** 获取访问令牌参数 */\r\nexport interface GetAccessTokenDTO {\r\n /** 填写 client_credential */\r\n grant_type: 'client_credential'\r\n /** 账号的唯一凭证,即 AppID,点此查看如何获取Appid */\r\n appid: string\r\n /** 唯一凭证密钥,即 AppSecret,点此查看如何获取AppSecret */\r\n secret: string\r\n}\r\n/** 获取访问令牌响应 */\r\nexport interface GetAccessTokenVO {\r\n /** 获取到的凭证 */\r\n access_token: string\r\n /** 凭证有效时间,单位:秒。目前是7200秒之内的值。 */\r\n expires_in: number\r\n}\r\n/**\r\n * 获取接口调用凭据\r\n * @param data GetAccessTokenDTO\r\n * @returns GetAccessTokenVO\r\n * \r\n * @see https://developers.weixin.qq.com/doc/service/api/base/api_getaccesstoken.html\r\n */\r\nexport function getAccessToken(data: GetAccessTokenDTO) {\r\n return requestPostBase<GetAccessTokenVO>('/cgi-bin/token', data)\r\n}\r\n","import { requestPostBase } from '../../utils/request'\r\nimport { GetAccessTokenDTO, GetAccessTokenVO } from './getAccessToken'\r\n/** 获取访问令牌参数 */\r\nexport interface GetAccessStableTokenDTO extends GetAccessTokenDTO {\r\n /**\r\n * 1. force_refresh = false 时为普通调用模式,access_token 有效期内重复调用该接口不会更新 access_token;\r\n * 2. 当force_refresh = true 时为强制刷新模式,会导致上次获取的 access_token 失效,并返回新的 access_token\r\n * @default false\r\n */\r\n force_refresh?: boolean\r\n}\r\n/** 获取访问令牌响应 */\r\nexport type GetAccessStableTokenVO = GetAccessTokenVO\r\n\r\n/**\r\n * 获取稳定版接口调用凭据\r\n * @param data GetAccessStableTokenDTO\r\n * @returns GetAccessStableTokenVO\r\n * \r\n * @see https://developers.weixin.qq.com/doc/service/api/base/api_getstableaccesstoken.html\r\n */\r\nexport function getStableAccessToken(data: GetAccessStableTokenDTO) {\r\n return requestPostBase<GetAccessStableTokenVO>('/cgi-bin/stable_token', data)\r\n}\r\n","// 微信配置\r\nexport let appId = ''\r\nexport let appSecret = ''\r\n\r\n/** WechatAPI实例 */\r\n// let api: WechatAPI\r\n// export function createApi() {\r\n// getConfig()\r\n// if (!api) {\r\n// api = new WechatAPI(appId, appSecret)\r\n// }\r\n// return api\r\n// }\r\n\r\nexport interface WechatConfig {\r\n /** 微信公众号appid */\r\n appId: string\r\n /** 微信公众号appsecret */\r\n appSecret: string\r\n}\r\n\r\nexport function setConfig(config: WechatConfig) {\r\n appId = config.appId\r\n appSecret = config.appSecret\r\n}\r\n\r\nexport function getConfig(): WechatConfig {\r\n if (!appId || !appSecret) {\r\n throw new Error('请先调用setConfig配置appId/appSecret')\r\n }\r\n return {\r\n appId,\r\n appSecret\r\n }\r\n}\r\n","import { getStableAccessToken } from '../cgi-bin/getStableAccessToken'\r\nimport { getConfig } from '../../utils/config'\r\n\r\nlet token = '',\r\n expires = 0\r\n\r\nexport async function getToken() {\r\n const { appId, appSecret } = getConfig()\r\n const now = Date.now()\r\n if (expires < now) {\r\n const resToken = await getStableAccessToken({\r\n appid: appId,\r\n secret: appSecret,\r\n grant_type: 'client_credential'\r\n })\r\n token = resToken.access_token\r\n // 设置过期时间,留出5%的缓冲时间\r\n expires = now + resToken.expires_in * 950\r\n }\r\n return token\r\n}\r\n","import { requestGetBase, requestPostBase } from '../../utils/request'\r\nimport { getToken } from './token'\r\n\r\nasync function urlAddToken(url: string) {\r\n if (url.includes('?')) {\r\n url += '&'\r\n }\r\n url += `access_token=${await getToken()}`\r\n return url\r\n}\r\n\r\nexport async function requestGet<T>(\r\n url: string,\r\n params: Record<string, any>,\r\n options?: RequestInit\r\n) {\r\n return requestGetBase<T>(await urlAddToken(url), params, options)\r\n}\r\nexport async function requestPost<T>(\r\n url: string,\r\n data: Record<string, any>,\r\n options?: RequestInit\r\n) {\r\n return requestPostBase<T>(await urlAddToken(url), data, options)\r\n}\r\n","import { WechatResponse } from '../../../types/response'\nimport { requestPost } from '../../../utils/request'\n\n/**\n * 发送模板消息参数\n * @interface sendTemplateMessageDTO\n */\nexport interface SendTemplateMessageDTO {\n /** 接收者openid */\n touser: string\n /** 模板ID */\n template_id: string\n /** 跳转URL */\n url?: string\n /** 小程序信息 */\n miniprogram?: {\n /** 小程序appid */\n appid?: string\n /** 小程序页面路径 */\n pagepath?: string\n }\n /** 模板数据 */\n data: Record<string, { value: string; color?: string }>\n /** 防重入id。对于同一个openid + client_msg_id, 只发送一条消息,10分钟有效,超过10分钟不保证效果。若无防重入需求,可不填 */\n client_msg_id?: string\n}\n\nexport interface SendTemplateMessageVO extends WechatResponse {\n msgid: number\n}\n\n/**\n * 发送模板消息\n * @param params\n * @returns\n *\n * @see https://developers.weixin.qq.com/doc/service/api/notify/template/api_sendtemplatemessage.html\n */\nexport function sendTemplateMessage(params: SendTemplateMessageDTO) {\n return requestPost<SendTemplateMessageVO>('/cgi-bin/message/template/send', params)\n}\n","import { getConfig } from '../utils/config'\r\nimport { requestGetBase } from '../utils/request'\r\n\r\n/**\r\n * 获取微信用户信息参数\r\n * @interface WeixinGetUserInfoDTO\r\n */\r\nexport interface WeixinGetUserInfoDTO {\r\n /** 授权码 */\r\n code: string\r\n /** 重定向后会带上 state 参数,开发者可以填写任意参数值,最多 128 字节 */\r\n state?: string\r\n}\r\n\r\n/**\r\n * 微信访问令牌接口\r\n */\r\nexport interface SnsAccessTokenVO {\r\n /** 访问令牌 */\r\n access_token: string\r\n /** 过期时间(秒) */\r\n expires_in: number\r\n /** 刷新令牌 */\r\n refresh_token: string\r\n /** 用户openid */\r\n openid: string\r\n /** 授权作用域 */\r\n scope: string\r\n}\r\n\r\n/**\r\n * 获取微信访问令牌\r\n * @param code 授权码\r\n * @returns 微信访问令牌信息\r\n * \r\n * @see https://developers.weixin.qq.com/doc/service/api/webdev/access/api_snsaccesstoken.html\r\n */\r\nexport async function snsAccessToken(code: string) {\r\n const { appId, appSecret } = getConfig()\r\n // 通过code换取网页授权access_token\r\n return requestGetBase<SnsAccessTokenVO>('/sns/oauth2/access_token', {\r\n appid: appId,\r\n secret: appSecret,\r\n code,\r\n grant_type: 'authorization_code'\r\n })\r\n}\r\n","import { requestGetBase } from '../utils/request'\r\nimport { SnsAccessTokenVO } from './snsAccessToken'\r\n\r\nexport interface SnsUserInfoDTO extends Pick<SnsAccessTokenVO, 'access_token' | 'openid'> {\r\n /**\r\n * 语言\r\n * @default zh_CN\r\n */\r\n lang?: 'zh_CN' | 'zh_TW' | 'en'\r\n}\r\n\r\nexport interface SnsUserInfoVO {\r\n /** 用户的微信openid */\r\n openid?: string\r\n /** 用户昵称 */\r\n nickname?: string\r\n /** 性别 0-未知 1-男 2-女 */\r\n sex?: 0 | 1 | 2\r\n /** 用户语言 */\r\n language?: string\r\n /** 用户所在城市 */\r\n city?: string\r\n /** 用户所在省份 */\r\n province?: string\r\n /** 用户所在国家 */\r\n country?: string\r\n /** 用户头像URL */\r\n headimgurl?: string\r\n /** 用户特权信息 */\r\n privilege?: any[]\r\n /** 用户在开放平台的唯一标识符 */\r\n unionid?: string\r\n}\r\n/**\r\n * 获取授权用户信息\r\n * @param data SnsUserInfoDTO\r\n * @returns SnsUserInfoVO\r\n * \r\n * @see https://developers.weixin.qq.com/doc/service/api/webdev/access/api_snsuserinfo.html\r\n */\r\nexport async function snsUserInfo(data: SnsUserInfoDTO) {\r\n const { access_token, openid, lang = 'zh_CN' } = data\r\n // 2. 获取用户信息\r\n return requestGetBase<SnsUserInfoVO>(`/sns/userinfo`, {\r\n access_token: access_token,\r\n openid: openid,\r\n lang: lang\r\n })\r\n}\r\n","import { snsAccessToken } from './snsAccessToken'\r\nimport { snsUserInfo } from './snsUserInfo'\r\n\r\n/**\r\n * 获取微信用户信息\r\n * @param {WeixinGetUserInfoDTO} params - 获取微信用户信息参数\r\n * @returns {Promise<SnsUserInfo>} 用户信息\r\n */\r\nexport async function getSnsUserInfo(code: string) {\r\n // 通过code换取网页授权access_token\r\n // const { code } = params\r\n // const accessToken: WeixinAccessToken = await OpenMpSnsAccessTokenApi.getSnsAccessToken(\r\n // code,\r\n // appid\r\n // )\r\n // console.log('accessToken:', accessToken)\r\n\r\n // // 拉取用户信息(需scope为 snsapi_userinfo)\r\n // const { access_token, openid } = accessToken\r\n // const userInfo: TableUser = await OpenMpSnsAccessTokenApi.getUserInfo(\r\n // access_token,\r\n // openid,\r\n // Lang.ZH_CN\r\n // )\r\n\r\n // if (userInfo.openid) {\r\n // // 3. 使用user.ts中的函数保存用户信息\r\n // saveUser(userInfo)\r\n // return userInfo\r\n // } else {\r\n // throw new Error('获取用户信息失败')\r\n // }\r\n // 1. 获取access_token和openid\r\n const tokenData = await snsAccessToken(code)\r\n const { access_token, openid } = tokenData\r\n\r\n if (!openid) {\r\n throw new Error('获取openid失败')\r\n }\r\n\r\n // 2. 获取用户信息\r\n const userInfo = await snsUserInfo({ access_token, openid })\r\n if (userInfo.openid) {\r\n // 3. 使用user.ts中的函数保存用户信息\r\n return userInfo\r\n } else {\r\n throw new Error('获取用户信息失败')\r\n }\r\n}\r\n","import { baseDemain } from '../constants'\r\nimport { getConfig } from '../utils/config'\r\n\r\nexport interface Oauth2AuthorizeVO {\r\n /** 回调地址 */\r\n redirectUrl: string\r\n /** 重定向后会带上 state 参数,开发者可以填写任意参数值,最多 128 字节 */\r\n state?: string\r\n /**\r\n * @default 'code'\r\n */\r\n responseType?: 'code' | 'token'\r\n /**\r\n *\r\n * @default 'snsapi_userinfo'\r\n */\r\n scope?: 'snsapi_base' | 'snsapi_userinfo'\r\n}\r\n\r\n/**\r\n * 获取微信授权URL\r\n * @param {Oauth2AuthorizeVO} params - 获取微信授权URL参数\r\n * \r\n * @see https://developers.weixin.qq.com/doc/service/guide/h5/auth.html\r\n */\r\nexport function getOauth2AuthorizeUrl(params: Oauth2AuthorizeVO) {\r\n const { redirectUrl, state = '', responseType = 'code', scope = 'snsapi_userinfo' } = params\r\n const { appId } = getConfig()\r\n\r\n let url = `${baseDemain}/connect/oauth2/authorize?`\r\n url += `appid=${appId}`\r\n url += `&redirect_uri=${encodeURIComponent(redirectUrl)}`\r\n url += `&response_type=${responseType}`\r\n url += `&scope=${scope}`\r\n url += `&state=${state}`\r\n url += `#wechat_redirect`\r\n\r\n const authorizeUrl = url\r\n // const authorizeUrl = OpenMpSnsAccessTokenApi.getAuthorizeUrl(\r\n // appid,\r\n // redirectUrl,\r\n // ScopeEnum.SNSAPI_USERINFO,\r\n // state\r\n // )\r\n return authorizeUrl\r\n\r\n // https://open.weixin.qq.com/connect/oauth2/authorize?\r\n // appid=wx2dc26f0c6d48cde8\r\n // &redirect_uri=https%3A%2F%2Fgirl.kafei88.com%2Fapi%2Fweixin%2FauthCallback\r\n // &response_type=code\r\n // &scope=snsapi_userinfo\r\n // &component_appid=wx2dc26f0c6d48cde8\r\n // &state={\\\"redirectUrl\\\":\\\"https%3A%2F%2Fgirl.kafei88.com%2Forder%2Ftoday\\\",\\\"inviter\\\":null}\r\n // #wechat_redirect\r\n\r\n // https://open.weixin.qq.com/connect/oauth2/authorize?\r\n // appid=wx2dc26f0c6d48cde8\r\n // &redirect_uri=https%3A%2F%2Fgirl.kafei88.com%2Fapi%2Fweixin%2FauthCallback\r\n // &response_type=code\r\n // &scope=snsapi_userinfo\r\n // &component_appid=wx2dc26f0c6d48cde8\r\n // &state=123\r\n // #wechat_redirect\r\n\r\n // https://open.weixin.qq.com/connect/oauth2/authorize?\r\n // appid=wx2dc26f0c6d48cde8\r\n // &redirect_uri=https%3A%2F%2Fgirl.kafei88.com%2Fapi%2Fweixin%2FauthCallback\r\n // &response_type=code\r\n // &scope=snsapi_userinfo\r\n // &state=https%3A%2F%2Fgirl.kafei88.com%2Fapi%2Fweixin%2FauthCallback\r\n // #wechat_redirect\r\n\r\n // https://open.weixin.qq.com/connect/oauth2/authorize?\r\n // appid=wx807d86fb6b3d4fd2\r\n // &redirect_uri=http%3A%2F%2Fdevelopers.weixin.qq.com\r\n // &response_type=code\r\n // &scope=snsapi_userinfo\r\n // &state=STATE\r\n // #wechat_redirect\r\n\r\n // try {\r\n // const url = api.getAuthorizeURL(redirectUrl, state, 'snsapi_userinfo')\r\n // return {\r\n // success: true,\r\n // url\r\n // }\r\n // } catch (error) {\r\n // console.error('生成授权URL失败:', error)\r\n // return {\r\n // success: false,\r\n // url: '',\r\n // message: '生成授权URL失败'\r\n // }\r\n // }\r\n}\r\n","import crypto from 'node:crypto'\r\nimport { getTicket } from '../server/cgi-bin/ticket'\r\nimport { createNonceStr, createTimestamp, raw } from '../utils/string'\r\nimport { getConfig } from '../utils/config'\r\nexport interface GetJssdkConfigDTO {\r\n /** 当前页面URL */\r\n url: string\r\n /** 需要使用的JS API列表 */\r\n jsApiList?: string[]\r\n /** 是否开启调试模式 */\r\n debug?: boolean\r\n /** 微信硬件开发用 */\r\n beta?: boolean\r\n}\r\n\r\n/**\r\n * 微信JS-SDK配置接口\r\n */\r\nexport interface GetJssdkConfigVO {\r\n /** 开启调试模式,调用的所有API的返回值会在客户端alert出来,若要查看传入的参数,可以在PC端打开,参数信息会通过log打出,仅在PC端时才会打印 */\r\n debug: boolean\r\n /** 微信硬件开发用 */\r\n beta?: boolean\r\n /** 必填,公众号的唯一标识 */\r\n appId: string\r\n /** 必填,生成签名的时间戳 */\r\n timestamp: string\r\n /** 必填,生成签名的随机串 */\r\n nonceStr: string\r\n /** 必填,签名 */\r\n signature: string\r\n /** 必填,需要使用的JS接口列表 */\r\n jsApiList: string[]\r\n}\r\n\r\n// 工具:按 ASCII 字典序拼接并 SHA1\r\nfunction sign(data: { nonceStr: string; jsapi_ticket: string; timestamp: string; url: string }) {\r\n var string = raw(data)\r\n var shasum = crypto.createHash('sha1')\r\n shasum.update(string)\r\n return shasum.digest('hex')\r\n}\r\n\r\nlet ticket: string,\r\n expires = 0\r\nasync function getJsTicket() {\r\n const now = Date.now()\r\n if (expires < now) {\r\n const res = await getTicket({ type: 'jsapi' })\r\n if (res.errcode === 0) {\r\n ticket = res.ticket\r\n expires = now + res.expires_in * 950\r\n }\r\n }\r\n return ticket\r\n}\r\n\r\n/**\r\n * 获取JS配置\r\n * @param {GetJssdkConfigDTO} params - 获取JS配置参数\r\n * @returns {Promise<WeixinGetJsConfigVO>} JS配置结果\r\n */\r\nexport async function getJssdkConfig(params: GetJssdkConfigDTO) {\r\n const { url, jsApiList = ['updateAppMessageShareData', 'updateTimelineShareData'] } = params\r\n if (!url) throw new Error('缺少参数 url')\r\n\r\n const jsapi_ticket = await getJsTicket()\r\n const timestamp = createTimestamp()\r\n const nonceStr = createNonceStr()\r\n const signature = sign({ jsapi_ticket, url, nonceStr, timestamp })\r\n const { appId } = getConfig()\r\n return {\r\n appId,\r\n timestamp,\r\n nonceStr,\r\n signature,\r\n jsApiList\r\n } as GetJssdkConfigVO\r\n\r\n // try {\r\n // const { url, jsApiList = ['updateAppMessageShareData', 'updateTimelineShareData'] } = params\r\n\r\n // const nonceStr = createNonceStr()\r\n // const jsAPITicket = await JsTicketApi.getTicket(JsApiType.JSAPI)\r\n // const timestamp = createTimestamp()\r\n // const signature = sign(nonceStr, jsAPITicket.getTicket, timestamp, url)\r\n\r\n // const result: GetJssdkConfigVO = {\r\n // debug: false, // params.debug,\r\n // appId: appid,\r\n // timestamp,\r\n // nonceStr,\r\n // signature,\r\n // jsApiList\r\n // }\r\n\r\n // return jssdk.getConfig(params)\r\n\r\n // 创建WechatAPI实例\r\n // const api = createApi()\r\n // const { promise, resolve, reject } = usePromiseWithResolvers<GetJssdkConfigVO>()\r\n // api.getJsConfig(params, (err, result) => {\r\n // if (err) {\r\n // reject(err)\r\n // } else {\r\n // resolve(result)\r\n // }\r\n // })\r\n // return promise\r\n // const config =\r\n // return {\r\n // success: true,\r\n // config\r\n // }\r\n // } catch (error) {\r\n // console.error('获取JS配置失败:', error)\r\n // return {\r\n // success: false,\r\n // message: '获取JS配置失败'\r\n // }\r\n // }\r\n}\r\n","import { WechatResponse } from \"../../types/response\"\r\nimport { requestGet } from \"../../utils/request\"\r\n\r\nexport interface GetTicketDTO {\r\n /** ticket 类型,jsapi 为 js-sdk 凭证;wx_card 为微信卡券凭证 */\r\n type: 'jsapi' | 'wx_card'\r\n}\r\n\r\nexport interface GetTicketVO extends WechatResponse {\r\n /** 临时票据 */\r\n ticket: string\r\n /** \r\n * 有效期(秒)\r\n * @default 7200\r\n */\r\n expires_in: number\r\n}\r\n\r\n/**\r\n * 获取sdk临时票据\r\n * @param data GetTicketDTO\r\n * @returns GetTicketVO\r\n * \r\n * @see https://developers.weixin.qq.com/doc/service/api/webdev/jssdk/api_getticket.html\r\n */\r\nexport function getTicket(data: GetTicketDTO) {\r\n return requestGet<GetTicketVO>('/cgi-bin/ticket/getticket', data)\r\n}\r\n","/*!\n * 生成随机字符串\n */\nexport const createNonceStr = function () {\n return Math.random().toString(36).substr(2, 15)\n}\n\n/*!\n * 生成时间戳\n */\nexport const createTimestamp = function () {\n return Math.round(new Date().getTime() / 1000) + ''\n}\n\n/*!\n * 排序查询字符串\n */\nexport const raw = function (args: Record<string, string | number>) {\n var keys = Object.keys(args)\n keys = keys.sort()\n var newArgs: typeof args = {}\n keys.forEach(function (key) {\n newArgs[key.toLowerCase()] = args[key]\n })\n\n var string = ''\n var newKeys = Object.keys(newArgs)\n for (var i = 0; i < newKeys.length; i++) {\n var k = newKeys[i]\n string += '&' + k + '=' + newArgs[k]\n }\n return string.substr(1)\n}\n"],"mappings":"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","names":["appId","appSecret","appId","appSecret","appId","expires","appId"]}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "wechat-ts",
3
+ "version": "0.0.1",
4
+ "description": "微信服务端api",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "deploy": "pnpm run build && npm publish"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/xucoffee/wechat.git"
23
+ },
24
+ "keywords": [
25
+ "wechat api"
26
+ ],
27
+ "author": "coffee X.",
28
+ "license": "MIT",
29
+ "bugs": {
30
+ "url": "https://github.com/xucoffee/wechat/issues"
31
+ },
32
+ "homepage": "https://www.zhifux.com",
33
+ "dependencies": {
34
+ "wechat-api": "^1.35.1"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^24.10.1",
38
+ "tsup": "^8.5.0",
39
+ "typescript": "^5.9.3"
40
+ }
41
+ }
@@ -0,0 +1,2 @@
1
+ /** 基础域名 */
2
+ export const baseDemain = 'https://api.weixin.qq.com'
@@ -0,0 +1,4 @@
1
+ /** 微信公众号appid */
2
+ export const WECHAT_APPID = 'wx2dc26f0c6d48cde8'
3
+ /** 微信公众号appsecret */
4
+ export const WECHAT_APPSECRET = '6af073620557f8df63f7befe7e95b2e1'
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from './server'
2
+ export * from './sns'
3
+ export * from './oauth2'
4
+ export * from './jssdk'
5
+ export * from './utils/config'
@@ -0,0 +1,122 @@
1
+ import crypto from 'node:crypto'
2
+ import { getTicket } from '../server/cgi-bin/ticket'
3
+ import { createNonceStr, createTimestamp, raw } from '../utils/string'
4
+ import { getConfig } from '../utils/config'
5
+ export interface GetJssdkConfigDTO {
6
+ /** 当前页面URL */
7
+ url: string
8
+ /** 需要使用的JS API列表 */
9
+ jsApiList?: string[]
10
+ /** 是否开启调试模式 */
11
+ debug?: boolean
12
+ /** 微信硬件开发用 */
13
+ beta?: boolean
14
+ }
15
+
16
+ /**
17
+ * 微信JS-SDK配置接口
18
+ */
19
+ export interface GetJssdkConfigVO {
20
+ /** 开启调试模式,调用的所有API的返回值会在客户端alert出来,若要查看传入的参数,可以在PC端打开,参数信息会通过log打出,仅在PC端时才会打印 */
21
+ debug: boolean
22
+ /** 微信硬件开发用 */
23
+ beta?: boolean
24
+ /** 必填,公众号的唯一标识 */
25
+ appId: string
26
+ /** 必填,生成签名的时间戳 */
27
+ timestamp: string
28
+ /** 必填,生成签名的随机串 */
29
+ nonceStr: string
30
+ /** 必填,签名 */
31
+ signature: string
32
+ /** 必填,需要使用的JS接口列表 */
33
+ jsApiList: string[]
34
+ }
35
+
36
+ // 工具:按 ASCII 字典序拼接并 SHA1
37
+ function sign(data: { nonceStr: string; jsapi_ticket: string; timestamp: string; url: string }) {
38
+ var string = raw(data)
39
+ var shasum = crypto.createHash('sha1')
40
+ shasum.update(string)
41
+ return shasum.digest('hex')
42
+ }
43
+
44
+ let ticket: string,
45
+ expires = 0
46
+ async function getJsTicket() {
47
+ const now = Date.now()
48
+ if (expires < now) {
49
+ const res = await getTicket({ type: 'jsapi' })
50
+ if (res.errcode === 0) {
51
+ ticket = res.ticket
52
+ expires = now + res.expires_in * 950
53
+ }
54
+ }
55
+ return ticket
56
+ }
57
+
58
+ /**
59
+ * 获取JS配置
60
+ * @param {GetJssdkConfigDTO} params - 获取JS配置参数
61
+ * @returns {Promise<WeixinGetJsConfigVO>} JS配置结果
62
+ */
63
+ export async function getJssdkConfig(params: GetJssdkConfigDTO) {
64
+ const { url, jsApiList = ['updateAppMessageShareData', 'updateTimelineShareData'] } = params
65
+ if (!url) throw new Error('缺少参数 url')
66
+
67
+ const jsapi_ticket = await getJsTicket()
68
+ const timestamp = createTimestamp()
69
+ const nonceStr = createNonceStr()
70
+ const signature = sign({ jsapi_ticket, url, nonceStr, timestamp })
71
+ const { appId } = getConfig()
72
+ return {
73
+ appId,
74
+ timestamp,
75
+ nonceStr,
76
+ signature,
77
+ jsApiList
78
+ } as GetJssdkConfigVO
79
+
80
+ // try {
81
+ // const { url, jsApiList = ['updateAppMessageShareData', 'updateTimelineShareData'] } = params
82
+
83
+ // const nonceStr = createNonceStr()
84
+ // const jsAPITicket = await JsTicketApi.getTicket(JsApiType.JSAPI)
85
+ // const timestamp = createTimestamp()
86
+ // const signature = sign(nonceStr, jsAPITicket.getTicket, timestamp, url)
87
+
88
+ // const result: GetJssdkConfigVO = {
89
+ // debug: false, // params.debug,
90
+ // appId: appid,
91
+ // timestamp,
92
+ // nonceStr,
93
+ // signature,
94
+ // jsApiList
95
+ // }
96
+
97
+ // return jssdk.getConfig(params)
98
+
99
+ // 创建WechatAPI实例
100
+ // const api = createApi()
101
+ // const { promise, resolve, reject } = usePromiseWithResolvers<GetJssdkConfigVO>()
102
+ // api.getJsConfig(params, (err, result) => {
103
+ // if (err) {
104
+ // reject(err)
105
+ // } else {
106
+ // resolve(result)
107
+ // }
108
+ // })
109
+ // return promise
110
+ // const config =
111
+ // return {
112
+ // success: true,
113
+ // config
114
+ // }
115
+ // } catch (error) {
116
+ // console.error('获取JS配置失败:', error)
117
+ // return {
118
+ // success: false,
119
+ // message: '获取JS配置失败'
120
+ // }
121
+ // }
122
+ }
@@ -0,0 +1 @@
1
+ export * from './getJssdkConfig'
@@ -0,0 +1,95 @@
1
+ import { baseDemain } from '../constants'
2
+ import { getConfig } from '../utils/config'
3
+
4
+ export interface Oauth2AuthorizeVO {
5
+ /** 回调地址 */
6
+ redirectUrl: string
7
+ /** 重定向后会带上 state 参数,开发者可以填写任意参数值,最多 128 字节 */
8
+ state?: string
9
+ /**
10
+ * @default 'code'
11
+ */
12
+ responseType?: 'code' | 'token'
13
+ /**
14
+ *
15
+ * @default 'snsapi_userinfo'
16
+ */
17
+ scope?: 'snsapi_base' | 'snsapi_userinfo'
18
+ }
19
+
20
+ /**
21
+ * 获取微信授权URL
22
+ * @param {Oauth2AuthorizeVO} params - 获取微信授权URL参数
23
+ *
24
+ * @see https://developers.weixin.qq.com/doc/service/guide/h5/auth.html
25
+ */
26
+ export function getOauth2AuthorizeUrl(params: Oauth2AuthorizeVO) {
27
+ const { redirectUrl, state = '', responseType = 'code', scope = 'snsapi_userinfo' } = params
28
+ const { appId } = getConfig()
29
+
30
+ let url = `${baseDemain}/connect/oauth2/authorize?`
31
+ url += `appid=${appId}`
32
+ url += `&redirect_uri=${encodeURIComponent(redirectUrl)}`
33
+ url += `&response_type=${responseType}`
34
+ url += `&scope=${scope}`
35
+ url += `&state=${state}`
36
+ url += `#wechat_redirect`
37
+
38
+ const authorizeUrl = url
39
+ // const authorizeUrl = OpenMpSnsAccessTokenApi.getAuthorizeUrl(
40
+ // appid,
41
+ // redirectUrl,
42
+ // ScopeEnum.SNSAPI_USERINFO,
43
+ // state
44
+ // )
45
+ return authorizeUrl
46
+
47
+ // https://open.weixin.qq.com/connect/oauth2/authorize?
48
+ // appid=wx2dc26f0c6d48cde8
49
+ // &redirect_uri=https%3A%2F%2Fgirl.kafei88.com%2Fapi%2Fweixin%2FauthCallback
50
+ // &response_type=code
51
+ // &scope=snsapi_userinfo
52
+ // &component_appid=wx2dc26f0c6d48cde8
53
+ // &state={\"redirectUrl\":\"https%3A%2F%2Fgirl.kafei88.com%2Forder%2Ftoday\",\"inviter\":null}
54
+ // #wechat_redirect
55
+
56
+ // https://open.weixin.qq.com/connect/oauth2/authorize?
57
+ // appid=wx2dc26f0c6d48cde8
58
+ // &redirect_uri=https%3A%2F%2Fgirl.kafei88.com%2Fapi%2Fweixin%2FauthCallback
59
+ // &response_type=code
60
+ // &scope=snsapi_userinfo
61
+ // &component_appid=wx2dc26f0c6d48cde8
62
+ // &state=123
63
+ // #wechat_redirect
64
+
65
+ // https://open.weixin.qq.com/connect/oauth2/authorize?
66
+ // appid=wx2dc26f0c6d48cde8
67
+ // &redirect_uri=https%3A%2F%2Fgirl.kafei88.com%2Fapi%2Fweixin%2FauthCallback
68
+ // &response_type=code
69
+ // &scope=snsapi_userinfo
70
+ // &state=https%3A%2F%2Fgirl.kafei88.com%2Fapi%2Fweixin%2FauthCallback
71
+ // #wechat_redirect
72
+
73
+ // https://open.weixin.qq.com/connect/oauth2/authorize?
74
+ // appid=wx807d86fb6b3d4fd2
75
+ // &redirect_uri=http%3A%2F%2Fdevelopers.weixin.qq.com
76
+ // &response_type=code
77
+ // &scope=snsapi_userinfo
78
+ // &state=STATE
79
+ // #wechat_redirect
80
+
81
+ // try {
82
+ // const url = api.getAuthorizeURL(redirectUrl, state, 'snsapi_userinfo')
83
+ // return {
84
+ // success: true,
85
+ // url
86
+ // }
87
+ // } catch (error) {
88
+ // console.error('生成授权URL失败:', error)
89
+ // return {
90
+ // success: false,
91
+ // url: '',
92
+ // message: '生成授权URL失败'
93
+ // }
94
+ // }
95
+ }
@@ -0,0 +1 @@
1
+ export * from './authorize'
@@ -0,0 +1,28 @@
1
+ import { requestPostBase } from "../../utils/request"
2
+
3
+ /** 获取访问令牌参数 */
4
+ export interface GetAccessTokenDTO {
5
+ /** 填写 client_credential */
6
+ grant_type: 'client_credential'
7
+ /** 账号的唯一凭证,即 AppID,点此查看如何获取Appid */
8
+ appid: string
9
+ /** 唯一凭证密钥,即 AppSecret,点此查看如何获取AppSecret */
10
+ secret: string
11
+ }
12
+ /** 获取访问令牌响应 */
13
+ export interface GetAccessTokenVO {
14
+ /** 获取到的凭证 */
15
+ access_token: string
16
+ /** 凭证有效时间,单位:秒。目前是7200秒之内的值。 */
17
+ expires_in: number
18
+ }
19
+ /**
20
+ * 获取接口调用凭据
21
+ * @param data GetAccessTokenDTO
22
+ * @returns GetAccessTokenVO
23
+ *
24
+ * @see https://developers.weixin.qq.com/doc/service/api/base/api_getaccesstoken.html
25
+ */
26
+ export function getAccessToken(data: GetAccessTokenDTO) {
27
+ return requestPostBase<GetAccessTokenVO>('/cgi-bin/token', data)
28
+ }
@@ -0,0 +1,24 @@
1
+ import { requestPostBase } from '../../utils/request'
2
+ import { GetAccessTokenDTO, GetAccessTokenVO } from './getAccessToken'
3
+ /** 获取访问令牌参数 */
4
+ export interface GetAccessStableTokenDTO extends GetAccessTokenDTO {
5
+ /**
6
+ * 1. force_refresh = false 时为普通调用模式,access_token 有效期内重复调用该接口不会更新 access_token;
7
+ * 2. 当force_refresh = true 时为强制刷新模式,会导致上次获取的 access_token 失效,并返回新的 access_token
8
+ * @default false
9
+ */
10
+ force_refresh?: boolean
11
+ }
12
+ /** 获取访问令牌响应 */
13
+ export type GetAccessStableTokenVO = GetAccessTokenVO
14
+
15
+ /**
16
+ * 获取稳定版接口调用凭据
17
+ * @param data GetAccessStableTokenDTO
18
+ * @returns GetAccessStableTokenVO
19
+ *
20
+ * @see https://developers.weixin.qq.com/doc/service/api/base/api_getstableaccesstoken.html
21
+ */
22
+ export function getStableAccessToken(data: GetAccessStableTokenDTO) {
23
+ return requestPostBase<GetAccessStableTokenVO>('/cgi-bin/stable_token', data)
24
+ }