From 0d90e20ec20f0aeee642756a7ebf9e8514174124 Mon Sep 17 00:00:00 2001
From: wangrong <wangrong@shsening.com>
Date: 星期一, 26 十月 2026 21:15:20 +0800
Subject: [PATCH] 微信小程序插件支持
---
src/modules/base/db.json | 14 +
src/modules/cs/socket/middleware/token.ts | 13 +
src/modules/user/controller/app/address.ts | 8
typings/pay-wx.d.ts | 16 +
src/modules/user/service/address.ts | 4
src/modules/user/service/wx.ts | 129 ++++++++++++
src/modules/user/middleware/app.ts | 27 ++
typings/wxBaseMessage.d.ts | 153 +++++++++++++++
src/modules/user/controller/app/login.ts | 12
src/modules/app/controller/app/feedback.ts | 6
src/modules/cs/controller/app/session.ts | 4
src/modules/app/controller/app/complain.ts | 6
src/modules/user/controller/app/info.ts | 15 +
src/modules/user/service/login.ts | 84 +++++++
src/modules/goods/controller/app/comment.ts | 4
src/modules/user/service/info.ts | 29 ++
typings/wx.d.ts | 7
src/modules/cs/controller/app/msg.ts | 6
typings/plugin.d.ts | 2
src/modules/cs/service/session.ts | 5
20 files changed, 493 insertions(+), 51 deletions(-)
diff --git a/src/modules/app/controller/app/complain.ts b/src/modules/app/controller/app/complain.ts
index aeaaa33..9bb9b9e 100644
--- a/src/modules/app/controller/app/complain.ts
+++ b/src/modules/app/controller/app/complain.ts
@@ -11,13 +11,13 @@
entity: AppComplainEntity,
insertParam: ctx => {
return {
- userId: ctx.user.id,
+ userId: ctx.user.userId,
};
},
pageQueryOp: {
fieldEq: ['a.type'],
where: ctx => {
- const userId = ctx.user.id;
+ const userId = ctx.user.userId;
return [['a.userId = :userId', { userId }]];
},
},
@@ -31,7 +31,7 @@
@Post('/submit', { summary: '鎻愪氦鎶曡瘔涓炬姤' })
async submit(@Body() info) {
- info.userId = this.ctx.user.id;
+ info.userId = this.ctx.user.userId;
await this.appComplainService.submit(info);
return this.ok();
}
diff --git a/src/modules/app/controller/app/feedback.ts b/src/modules/app/controller/app/feedback.ts
index 17f4805..e4d2140 100644
--- a/src/modules/app/controller/app/feedback.ts
+++ b/src/modules/app/controller/app/feedback.ts
@@ -11,13 +11,13 @@
entity: AppFeedbackEntity,
insertParam: ctx => {
return {
- userId: ctx.user.id,
+ userId: ctx.user.userId,
};
},
pageQueryOp: {
fieldEq: ['a.type'],
where: ctx => {
- const userId = ctx.user.id;
+ const userId = ctx.user.userId;
return [['a.userId = :userId', { userId }]];
},
},
@@ -31,7 +31,7 @@
@Post('/submit', { summary: '鎻愪氦鎰忚鍙嶉' })
async submit(@Body() info) {
- info.userId = this.ctx.user.id;
+ info.userId = this.ctx.user.userId;
await this.appFeedbackService.submit(info);
return this.ok();
}
diff --git a/src/modules/base/db.json b/src/modules/base/db.json
index dea4747..da8e5be 100644
--- a/src/modules/base/db.json
+++ b/src/modules/base/db.json
@@ -118,6 +118,20 @@
"data": "400",
"dataType": 0,
"remark": "閫愬彴鏌ヨ璁惧鏃剁殑闂撮殧锛岄伩鍏嶈Е鍙� QPS 闄愭祦"
+ },
+ {
+ "keyName": "wx.mini.appId",
+ "name": "灏忕▼搴廇ppId",
+ "data": "wx88c344d1b0db243a",
+ "dataType": 0,
+ "remark": "寰俊灏忕▼搴� AppId锛岀敤浜庢墜鏈哄彿鐧诲綍"
+ },
+ {
+ "keyName": "wx.mini.appSecret",
+ "name": "灏忕▼搴廇ppSecret",
+ "data": "",
+ "dataType": 0,
+ "remark": "寰俊鍏紬骞冲彴-寮�鍙戠鐞�-寮�鍙戣缃腑鐨� AppSecret锛岀敤浜庣敤鎺堟潈鐮佹崲鍙栨墜鏈哄彿"
}
],
"base_sys_conf": [
diff --git a/src/modules/cs/controller/app/msg.ts b/src/modules/cs/controller/app/msg.ts
index 9aea144..453322c 100644
--- a/src/modules/cs/controller/app/msg.ts
+++ b/src/modules/cs/controller/app/msg.ts
@@ -38,7 +38,7 @@
},
],
where: ctx => {
- return [['d.userId = :userId', { userId: ctx.user?.id }]];
+ return [['d.userId = :userId', { userId: ctx.user?.userId }]];
},
},
})
@@ -51,7 +51,9 @@
@Get('/unreadCount', { summary: '鏈娑堟伅鏁�' })
async unreadCount() {
- return this.ok(await this.csMsgService.unreadCount(this.ctx.user?.id, 1));
+ return this.ok(
+ await this.csMsgService.unreadCount(this.ctx.user?.userId, 1)
+ );
}
@Post('/read', { summary: '鏍囪宸茶' })
diff --git a/src/modules/cs/controller/app/session.ts b/src/modules/cs/controller/app/session.ts
index fe73446..4bb630b 100644
--- a/src/modules/cs/controller/app/session.ts
+++ b/src/modules/cs/controller/app/session.ts
@@ -15,11 +15,11 @@
@Get('/detail', { summary: '浼氳瘽璇︽儏' })
async detail() {
- return this.ok(await this.csSessionService.detail(this.ctx.user?.id));
+ return this.ok(await this.csSessionService.detail(this.ctx.user?.userId));
}
@Post('/create', { summary: '鍒涘缓浼氳瘽' })
async create() {
- return this.ok(await this.csSessionService.create(this.ctx.user?.id));
+ return this.ok(await this.csSessionService.create(this.ctx.user?.userId));
}
}
diff --git a/src/modules/cs/service/session.ts b/src/modules/cs/service/session.ts
index 3994ad7..237025d 100644
--- a/src/modules/cs/service/session.ts
+++ b/src/modules/cs/service/session.ts
@@ -1,5 +1,5 @@
import { Provide } from '@midwayjs/core';
-import { BaseService } from '@cool-midway/core';
+import { BaseService, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { CsSessionEntity } from '../entity/session';
@@ -26,6 +26,9 @@
* @returns
*/
async create(userId: number) {
+ if (!userId) {
+ throw new CoolCommException('鐢ㄦ埛涓嶅瓨鍦�');
+ }
const check = await this.detail(userId);
if (check) {
return check;
diff --git a/src/modules/cs/socket/middleware/token.ts b/src/modules/cs/socket/middleware/token.ts
index 42ac237..8e843f4 100644
--- a/src/modules/cs/socket/middleware/token.ts
+++ b/src/modules/cs/socket/middleware/token.ts
@@ -1,6 +1,7 @@
-import { Config, Middleware } from '@midwayjs/core';
+import { Config, Inject, Middleware } from '@midwayjs/core';
import { NextFunction } from '@midwayjs/socketio';
import * as jwt from 'jsonwebtoken';
+import { UserInfoService } from '../../../user/service/info';
@Middleware()
export class CsSocketTokenMiddleware {
@@ -9,6 +10,9 @@
@Config('module.base.jwt')
adminJwtConfig;
+
+ @Inject()
+ userInfoService: UserInfoService;
resolve() {
return async (ctx, next: NextFunction) => {
@@ -20,8 +24,13 @@
token,
isAdmin ? this.adminJwtConfig.secret : this.appJwtConfig.secret
);
+ let userId = isAdmin ? data.userId : data.id;
+ if (!isAdmin) {
+ const info = await this.userInfoService.person(data.id);
+ userId = info?.id;
+ }
ctx.connData = {
- userId: isAdmin ? data.userId : data.id,
+ userId,
isAdmin,
};
} catch (error) {
diff --git a/src/modules/goods/controller/app/comment.ts b/src/modules/goods/controller/app/comment.ts
index 521c871..8e9cc64 100644
--- a/src/modules/goods/controller/app/comment.ts
+++ b/src/modules/goods/controller/app/comment.ts
@@ -21,7 +21,7 @@
entity: GoodsCommentEntity,
insertParam: ctx => {
return {
- userId: ctx.user.id,
+ userId: ctx.user.userId,
};
},
pageQueryOp: {
@@ -49,7 +49,7 @@
@Body('orderId') orderId: number
) {
return this.ok(
- await this.goodsCommentService.submit(this.ctx.user.id, orderId, data)
+ await this.goodsCommentService.submit(this.ctx.user.userId, orderId, data)
);
}
}
diff --git a/src/modules/user/controller/app/address.ts b/src/modules/user/controller/app/address.ts
index ae3eba5..bcf018d 100644
--- a/src/modules/user/controller/app/address.ts
+++ b/src/modules/user/controller/app/address.ts
@@ -13,12 +13,12 @@
service: UserAddressService,
insertParam: ctx => {
return {
- userId: ctx.user.id,
+ userId: ctx.user.userId,
};
},
pageQueryOp: {
where: async ctx => {
- return [['userId =:userId', { userId: ctx.user.id }]];
+ return [['userId =:userId', { userId: ctx.user.userId }]];
},
addOrderBy: {
isDefault: 'DESC',
@@ -34,6 +34,8 @@
@Get('/default', { summary: '榛樿鍦板潃' })
async default() {
- return this.ok(await this.userAddressService.default(this.ctx.user.id));
+ return this.ok(
+ await this.userAddressService.default(this.ctx.user.userId)
+ );
}
}
diff --git a/src/modules/user/controller/app/info.ts b/src/modules/user/controller/app/info.ts
index d96e807..0bc8ab5 100644
--- a/src/modules/user/controller/app/info.ts
+++ b/src/modules/user/controller/app/info.ts
@@ -1,4 +1,10 @@
-import { CoolController, BaseController } from '@cool-midway/core';
+import {
+ CoolController,
+ BaseController,
+ CoolUrlTag,
+ CoolTag,
+ TagTypes,
+} from '@cool-midway/core';
import { Body, Get, Inject, Post } from '@midwayjs/core';
import { UserInfoService } from '../../service/info';
import { UserInfoEntity } from '../../entity/info';
@@ -6,6 +12,7 @@
/**
* 鐢ㄦ埛淇℃伅
*/
+@CoolUrlTag()
@CoolController({
api: [],
entity: UserInfoEntity,
@@ -63,10 +70,10 @@
);
}
- @Post('/dashboard', { summary: '鑾峰彇鐢ㄦ埛纰崇Н鍒嗕俊鎭�' })
+ @CoolTag(TagTypes.IGNORE_TOKEN)
+ @Post('/dashboard', { summary: '鑾峰彇鐢ㄦ埛纰崇Н鍒嗕俊鎭�' })
async dashboard(@Body() body) {
- console.log(body)
- const {unionid} = body;
+ const { unionid } = body;
return this.ok(
await this.userInfoService.dashboard(
unionid
diff --git a/src/modules/user/controller/app/login.ts b/src/modules/user/controller/app/login.ts
index 3f76431..4b26801 100644
--- a/src/modules/user/controller/app/login.ts
+++ b/src/modules/user/controller/app/login.ts
@@ -59,15 +59,21 @@
}
@CoolTag(TagTypes.IGNORE_TOKEN)
- @Post('/miniPhone', { summary: '缁戝畾灏忕▼搴忔墜鏈哄彿' })
+ @Post('/miniPhone', { summary: '灏忕▼搴忔墜鏈哄彿鎺堟潈鐧诲綍' })
async miniPhone(@Body() body) {
- const { code, encryptedData, iv } = body;
+ const { code, encryptedData, iv, loginCode } = body;
return this.ok(
- await this.userLoginService.miniPhone(code, encryptedData, iv)
+ await this.userLoginService.miniPhone(code, encryptedData, iv, loginCode)
);
}
@CoolTag(TagTypes.IGNORE_TOKEN)
+ @Post('/miniAuto', { summary: '灏忕▼搴忛潤榛樼櫥褰�' })
+ async miniAuto(@Body('code') code: string) {
+ return this.ok(await this.userLoginService.miniAuto(code));
+ }
+
+ @CoolTag(TagTypes.IGNORE_TOKEN)
@Get('/captcha', { summary: '鍥剧墖楠岃瘉鐮�' })
async captcha(
@Query('width') width: number,
diff --git a/src/modules/user/middleware/app.ts b/src/modules/user/middleware/app.ts
index 5988fa7..d97cb13 100644
--- a/src/modules/user/middleware/app.ts
+++ b/src/modules/user/middleware/app.ts
@@ -5,6 +5,7 @@
import * as _ from 'lodash';
import { CoolCommException, CoolUrlTagData, TagTypes } from '@cool-midway/core';
import { Utils } from '../../../comm/utils';
+import { UserInfoService } from '../service/info';
/**
* 鐢ㄦ埛
@@ -38,14 +39,30 @@
let { url } = ctx;
url = url.replace(this.prefix, '').split('?')[0];
if (_.startsWith(url, '/app/')) {
- const token = ctx.get('Authorization');
+ let token = ctx.get('Authorization') || '';
+ token = token.replace(/^Bearer\s+/i, '').trim();
try {
ctx.user = jwt.verify(token, this.jwtConfig.secret);
-
- if (ctx.user.isRefresh) {
- throw new CoolCommException('鐧诲綍澶辨晥~');
+ } catch (error) {
+ ctx.user = undefined;
+ if (token) {
+ console.error('[user] token鏃犳晥:', (error as Error).message);
}
- } catch (error) {}
+ }
+ if (ctx.user?.isRefresh) {
+ ctx.user = undefined;
+ } else if (ctx.user?.id) {
+ try {
+ // 浠ょ墝閲岀殑 id 鏄� unionid锛堟墜鏈哄彿鐧诲綍鏃跺氨鏄墜鏈哄彿锛夛紝鏁村瀷 userId 鍒楄鐢ㄧ敤鎴蜂富閿�
+ const userInfoService = await ctx.requestContext.getAsync(
+ UserInfoService
+ );
+ const info = await userInfoService.person(ctx.user.id);
+ if (info?.id) {
+ ctx.user.userId = info.id;
+ }
+ } catch (error) {}
+ }
// 浣跨敤matchUrl鏂规硶鏉ユ鏌RL鏄惁搴旇琚拷鐣�
const isIgnored = this.ignoreUrls.some(pattern =>
this.utils.matchUrl(pattern, url)
diff --git a/src/modules/user/service/address.ts b/src/modules/user/service/address.ts
index a478640..d676bab 100644
--- a/src/modules/user/service/address.ts
+++ b/src/modules/user/service/address.ts
@@ -27,7 +27,7 @@
async list() {
return this.userAddressEntity
.createQueryBuilder()
- .where('userId = :userId ', { userId: this.ctx.user.id })
+ .where('userId = :userId ', { userId: this.ctx.user.userId })
.addOrderBy('isDefault', 'DESC')
.getMany();
}
@@ -44,7 +44,7 @@
.createQueryBuilder()
.update()
.set({ isDefault: false })
- .where('userId = :userId ', { userId: this.ctx.user.id })
+ .where('userId = :userId ', { userId: this.ctx.user.userId })
.andWhere('id != :id', { id: data.id })
.execute();
}
diff --git a/src/modules/user/service/info.ts b/src/modules/user/service/info.ts
index c918e6f..73f26c9 100644
--- a/src/modules/user/service/info.ts
+++ b/src/modules/user/service/info.ts
@@ -50,8 +50,17 @@
* @returns
*/
async person(id) {
- const info = await this.userInfoEntity.findOneBy({ id: Equal(id) });
- //delete info.password;
+ const idText = id === undefined || id === null ? '' : String(id);
+ // 鎵嬫満鍙风櫥褰曠鍙戠殑鏄� unionid锛堟墜鏈哄彿锛夛紝涓嶈兘鎷垮幓鏌ユ暣鍨嬩富閿�
+ let info = null;
+ if (/^\d{1,10}$/.test(idText)) {
+ info = await this.userInfoEntity.findOneBy({ id: Equal(Number(idText)) });
+ }
+ if (!info && idText) {
+ info = await this.userInfoEntity.findOneBy({
+ unionid: Equal(idText),
+ });
+ }
return info;
}
@@ -60,8 +69,12 @@
* @param userId
*/
async logoff(userId: number) {
+ const info = await this.person(userId);
+ if (!info) {
+ throw new CoolCommException('鐢ㄦ埛涓嶅瓨鍦�');
+ }
await this.userInfoEntity.update(
- { id: userId },
+ { id: info.id },
{
status: 2,
phone: "",
@@ -92,7 +105,7 @@
}
} catch (err) { }
try {
- return await this.userInfoEntity.update({ id }, param);
+ return await this.userInfoEntity.update({ id: info.id }, param);
} catch (err) {
throw new CoolCommException('鏇存柊澶辫触锛屽弬鏁伴敊璇垨鑰呮墜鏈哄彿宸插瓨鍦�');
}
@@ -116,7 +129,7 @@
throw new CoolCommException('楠岃瘉鐮侀敊璇�');
}
- await this.userInfoEntity.update(user.unionid, {
+ await this.userInfoEntity.update(user.id, {
password: md5(password),
});
}
@@ -132,7 +145,11 @@
if (!check) {
throw new CoolCommException('楠岃瘉鐮侀敊璇�');
}
- await this.userInfoEntity.update({ id: userId }, { phone });
+ const info = await this.person(userId);
+ if (!info) {
+ throw new CoolCommException('鐢ㄦ埛涓嶅瓨鍦�');
+ }
+ await this.userInfoEntity.update({ id: info.id }, { phone });
}
/**
diff --git a/src/modules/user/service/login.ts b/src/modules/user/service/login.ts
index f1260bd..4964cfe 100644
--- a/src/modules/user/service/login.ts
+++ b/src/modules/user/service/login.ts
@@ -78,12 +78,85 @@
* @param encryptedData
* @param iv
*/
- async miniPhone(code, encryptedData, iv) {
+ async miniPhone(code, encryptedData, iv, loginCode?) {
const phone = await this.userWxService.miniPhone(code, encryptedData, iv);
- if (phone) {
- return await this.phone(phone);
- } else {
+ if (!phone) {
throw new CoolCommException('鑾峰緱鎵嬫満鍙峰け璐ワ紝璇锋鏌ラ厤缃�');
+ }
+ const token = await this.phone(phone);
+ await this.bindMiniOpenid(phone, loginCode);
+ return {
+ ...token,
+ phone,
+ };
+ }
+
+ /**
+ * 灏忕▼搴忓啀娆℃墦寮�鏃讹紝鐢� openid 闈欓粯鐧诲綍
+ */
+ async miniAuto(code: string) {
+ if (!code) {
+ return null;
+ }
+ const session = await this.userWxService.miniSession(code);
+ if (!session?.openid || session.errcode) {
+ return null;
+ }
+ const wx = await this.userWxEntity.findOneBy({
+ openid: Equal(session.openid),
+ });
+ if (!wx?.unionid) {
+ return null;
+ }
+ const user = await this.userInfoEntity.findOneBy({
+ unionid: Equal(wx.unionid),
+ });
+ if (!user?.phone || user.status === 2) {
+ return null;
+ }
+ const token = await this.token({ id: user.unionid });
+ return {
+ ...token,
+ phone: user.phone,
+ nickName: user.nickName,
+ avatarUrl: user.avatarUrl,
+ unionid: user.unionid,
+ id: user.id,
+ };
+ }
+
+ /**
+ * 鎶婂綋鍓嶅井淇� openid 璁板埌鎵嬫満鍙疯处鍙蜂笂锛屼緵涓嬫闈欓粯鐧诲綍
+ */
+ async bindMiniOpenid(phone: string, loginCode?: string) {
+ if (!loginCode) {
+ return;
+ }
+ try {
+ const session = await this.userWxService.miniSession(loginCode);
+ if (!session?.openid || session.errcode) {
+ return;
+ }
+ const user = await this.userInfoEntity.findOneBy({
+ phone: Equal(phone),
+ });
+ if (!user) {
+ return;
+ }
+ const unionid = user.unionid || session.unionid || phone;
+ const exist = await this.userWxEntity.findOneBy({
+ openid: Equal(session.openid),
+ });
+ await this.userWxEntity.save({
+ id: exist?.id,
+ openid: session.openid,
+ unionid,
+ nickName: user.nickName,
+ avatarUrl: user.avatarUrl,
+ type: 0,
+ });
+ } catch (err) {
+ // 缁戝畾 openid 澶辫触涓嶅奖鍝嶆湰娆℃墜鏈哄彿鐧诲綍
}
}
@@ -115,7 +188,8 @@
user = {
phone,
unionid: phone,
- loginType: 2,
+ loginType: 0,
+ departmentId: 1,
nickName: phone.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2'),
};
await this.userInfoEntity.insert(user);
diff --git a/src/modules/user/service/wx.ts b/src/modules/user/service/wx.ts
index 9c1c97a..6c85ac7 100644
--- a/src/modules/user/service/wx.ts
+++ b/src/modules/user/service/wx.ts
@@ -6,6 +6,7 @@
import * as moment from 'moment';
import { Equal, Repository } from 'typeorm';
import { v1 as uuid } from 'uuid';
+import { BaseSysParamEntity } from '../../base/entity/sys/param';
import { PluginService } from '../../plugin/service/info';
import { UserInfoEntity } from '../entity/info';
import { UserWxEntity } from '../entity/wx';
@@ -18,14 +19,22 @@
@Config('module.user')
config;
+ @Config('wxMini')
+ wxMini: { appId?: string; appSecret?: string };
+
@InjectEntityModel(UserInfoEntity)
userInfoEntity: Repository<UserInfoEntity>;
@InjectEntityModel(UserWxEntity)
userWxEntity: Repository<UserWxEntity>;
+ @InjectEntityModel(BaseSysParamEntity)
+ baseSysParamEntity: Repository<BaseSysParamEntity>;
+
@Inject()
pluginService: PluginService;
+
+ private miniTokenCache: { appId: string; token: string; expireAt: number };
/**
* 鑾峰緱鎻掍欢瀹炰緥
@@ -49,6 +58,68 @@
async getMiniApp() {
const wxPlugin: any = await this.getPlugin();
return wxPlugin.MiniApp();
+ }
+
+ async readParam(key: string) {
+ const row = await this.baseSysParamEntity.findOneBy({ keyName: key });
+ return (row?.data || '').trim();
+ }
+
+ /**
+ * 灏忕▼搴忚处鍙枫�備紭鍏堟彃浠讹紝鍏舵绯荤粺鍙傛暟 wx.mini.appId / wx.mini.appSecret
+ */
+ async getMiniCredential() {
+ try {
+ const app = await this.getMiniApp();
+ const account = app.getAccount();
+ const appId = account.getAppId?.() || account.appId;
+ const secret = account.getSecret?.() || account.appSecret || account.secret;
+ if (appId && secret) {
+ return { appId, secret };
+ }
+ } catch (error) {
+ // 鏈畨瑁呭井淇℃彃浠舵椂鏀圭敤绯荤粺鍙傛暟
+ }
+
+ const paramAppId = await this.readParam('wx.mini.appId');
+ const paramSecret = await this.readParam('wx.mini.appSecret');
+ const appId = paramAppId || this.wxMini?.appId || '';
+ const secret = paramSecret || this.wxMini?.appSecret || '';
+ if (!appId || !secret) {
+ throw new CoolCommException(
+ '鏈厤缃皬绋嬪簭瀵嗛挜銆傝鍦ㄧ郴缁熷弬鏁板~鍐� wx.mini.appSecret锛堝井淇″叕浼楀钩鍙�-寮�鍙戠鐞�-寮�鍙戣缃級'
+ );
+ }
+ return { appId, secret };
+ }
+
+ async getMiniAccessToken() {
+ const { appId, secret } = await this.getMiniCredential();
+ const now = Date.now();
+ if (
+ this.miniTokenCache &&
+ this.miniTokenCache.appId === appId &&
+ this.miniTokenCache.expireAt > now
+ ) {
+ return this.miniTokenCache.token;
+ }
+
+ const { data } = await axios.get('https://api.weixin.qq.com/cgi-bin/token', {
+ params: {
+ grant_type: 'client_credential',
+ appid: appId,
+ secret,
+ },
+ });
+ if (!data?.access_token) {
+ throw new CoolCommException(data?.errmsg || '鑾峰彇寰俊鍑瘉澶辫触锛岃妫�鏌� AppSecret');
+ }
+ this.miniTokenCache = {
+ appId,
+ token: data.access_token,
+ expireAt: now + Math.max(60, (data.expires_in || 7200) - 120) * 1000,
+ };
+ return data.access_token;
}
/**
@@ -215,10 +286,20 @@
* @param conf 閰嶇疆
*/
async miniSession(code) {
- const app = await this.getMiniApp();
- const utils = app.getUtils();
- const result = await utils.codeToSession(code);
- return result;
+ const { appId, secret } = await this.getMiniCredential();
+ const { data } = await axios.get(
+ 'https://api.weixin.qq.com/sns/jscode2session',
+ {
+ params: {
+ appid: appId,
+ secret,
+ js_code: code,
+ grant_type: 'authorization_code',
+ },
+ }
+ );
+ console.log('[miniSession] appId=', appId, 'code鍓�6浣�=', String(code).slice(0,6), 'ret=', JSON.stringify(data));
+ return data;
}
/**
@@ -255,6 +336,11 @@
* @param iv
*/
async miniPhone(code, encryptedData, iv) {
+ // 鏂扮増鑾峰彇鎵嬫満鍙峰彧杩斿洖鍔ㄦ�佷护鐗岋紝鐢辨湇鍔$鍚戝井淇℃崲鍙栨墜鏈哄彿
+ if (!encryptedData || !iv) {
+ return await this.getPhoneNumber(code);
+ }
+
const session = await this.miniSession(code);
if (session.errcode) {
throw new CoolCommException('鑾峰彇鎵嬫満鍙峰け璐ワ紝璇峰埛鏂伴噸璇�');
@@ -268,6 +354,41 @@
}
/**
+ * 鐢ㄦ墜鏈哄彿鍔ㄦ�佷护鐗屾崲鍙栨墜鏈哄彿
+ * @param code getPhoneNumber 杩斿洖鐨� code
+ */
+ async getPhoneNumber(code: string) {
+ if (!code) {
+ throw new CoolCommException('鏈幏鍙栧埌鎵嬫満鍙锋巿鏉�');
+ }
+
+ const accessToken = await this.getMiniAccessToken();
+
+ const { data } = await axios.post(
+ 'https://api.weixin.qq.com/wxa/business/getuserphonenumber',
+ { code },
+ {
+ params: {
+ access_token: accessToken,
+ },
+ }
+ );
+
+ if (data?.errcode) {
+ throw new CoolCommException(data.errmsg || '鑾峰彇鎵嬫満鍙峰け璐�');
+ }
+
+ const phone =
+ data?.phone_info?.purePhoneNumber || data?.phone_info?.phoneNumber;
+
+ if (!phone) {
+ throw new CoolCommException('鑾峰緱鎵嬫満鍙峰け璐ワ紝璇锋鏌ラ厤缃�');
+ }
+
+ return phone;
+ }
+
+ /**
* 灏忕▼搴忎俊鎭В瀵�
* @param encryptedData
* @param iv
diff --git a/typings/pay-wx.d.ts b/typings/pay-wx.d.ts
index 035a8fc..1ce2b6e 100644
--- a/typings/pay-wx.d.ts
+++ b/typings/pay-wx.d.ts
@@ -23,9 +23,16 @@
mchid: string;
key: string;
notify_url: string;
- publicKey: Buffer;
- privateKey: Buffer;
+ publicKey: string;
+ privateKey: string;
+ verifyPublicKey?: string;
}): Promise<any>;
+ /**
+ * 鑾峰緱Buffer
+ * @param path
+ * @returns
+ */
+ getBuffer(path: string): Promise<Buffer<any>>;
/**
* 鏍规嵁缁欏畾鐨� URL 涓嬭浇鏂囦欢骞惰繑鍥炰竴涓� Buffer銆�
* @param {string} url 鏂囦欢鐨� URL
@@ -45,8 +52,9 @@
mchid: string;
key: string;
notify_url: string;
- publicKey: Buffer;
- privateKey: Buffer;
+ publicKey: string;
+ privateKey: string;
+ verifyPublicKey?: string;
},
): Promise<any>;
}
diff --git a/typings/plugin.d.ts b/typings/plugin.d.ts
index 14b5d95..a5a69f7 100644
--- a/typings/plugin.d.ts
+++ b/typings/plugin.d.ts
@@ -1,3 +1,4 @@
+import * as wxBaseMessage from './wxBaseMessage';
import * as wuliu from './wuliu';
import * as pay_wx from './pay-wx';
import * as wx from './wx';
@@ -15,4 +16,5 @@
wx: wx.CoolPlugin;
'pay-wx': pay_wx.CoolPlugin;
wuliu: wuliu.CoolPlugin;
+ wxBaseMessage: wxBaseMessage.CoolPlugin;
}
diff --git a/typings/wx.d.ts b/typings/wx.d.ts
index a1f8c73..efa34f3 100644
--- a/typings/wx.d.ts
+++ b/typings/wx.d.ts
@@ -7,6 +7,7 @@
Work,
OpenWork,
} from 'node-easywechat';
+import { IncomingMessage } from 'http';
/**
* 寰俊
*/
@@ -18,6 +19,12 @@
*/
OfficialAccount(config?: any): Promise<any>;
/**
+ * 鍒涘缓璇锋眰
+ * @param req
+ * @returns
+ */
+ createRequest(req: IncomingMessage): Promise<any>;
+ /**
* 灏忕▼搴�
* @param config
* @returns
diff --git a/typings/wxBaseMessage.d.ts b/typings/wxBaseMessage.d.ts
new file mode 100644
index 0000000..a4ca04b
--- /dev/null
+++ b/typings/wxBaseMessage.d.ts
@@ -0,0 +1,153 @@
+import { BasePlugin } from '@cool-midway/plugin-cli';
+interface TemplateDataItem {
+ value: string;
+ color?: string;
+}
+interface TemplateData {
+ [key: string]: TemplateDataItem;
+}
+interface MiniProgramParams {
+ appid?: string;
+ pagepath?: string;
+}
+interface SendTemplateMessageParams {
+ touser: string;
+ template_id: string;
+ url?: string;
+ miniprogram?: MiniProgramParams;
+ data: TemplateData;
+ client_msg_id?: string;
+}
+interface SendResult {
+ msgid: number;
+ errcode: number;
+ errmsg: string;
+}
+interface MassSendFilter {
+ is_to_all?: boolean;
+ tag_id?: string;
+}
+interface MassSendByOpenIdParams {
+ touser: string[];
+ msgtype: string;
+ mpnews?: {
+ media_id: string;
+ };
+ text?: {
+ content: string;
+ };
+ voice?: {
+ media_id: string;
+ };
+ image?: {
+ media_ids: string[];
+ recommend?: string;
+ title?: string;
+ need_open_comment?: number;
+ only_fans_can_comment?: number;
+ };
+ mpvideo?: {
+ media_id: string;
+ title?: string;
+ description?: string;
+ };
+ wxcard?: {
+ card_id: string;
+ };
+ send_ignore_reprint?: number;
+ clientmsgid?: string;
+}
+interface MassSendByTagParams {
+ filter: MassSendFilter;
+ msgtype: string;
+ mpnews?: {
+ media_id: string;
+ };
+ text?: {
+ content: string;
+ };
+ voice?: {
+ media_id: string;
+ };
+ image?: {
+ media_ids: string[];
+ recommend?: string;
+ title?: string;
+ need_open_comment?: number;
+ only_fans_can_comment?: number;
+ };
+ mpvideo?: {
+ media_id: string;
+ title?: string;
+ description?: string;
+ };
+ wxcard?: {
+ card_id: string;
+ };
+ clientmsgid?: string;
+}
+interface MassSendResult {
+ type: string;
+ msg_id: number;
+ msg_data_id: number;
+ errcode: number;
+ errmsg: string;
+}
+interface SubscribeDataItem {
+ value: string;
+}
+interface SubscribeData {
+ [key: string]: SubscribeDataItem;
+}
+interface SendSubscribeMsgParams {
+ template_id: string;
+ touser: string;
+ page?: string;
+ data: SubscribeData;
+ miniprogram_state: string;
+ lang?: string;
+}
+interface SubscribeResult {
+ errcode: number;
+ errmsg: string;
+}
+interface OneTimeMiniProgram {
+ appid: string;
+ pagepath: string;
+}
+interface OneTimeMsgData {
+ content: {
+ value: string;
+ color?: string;
+ };
+}
+interface SendOneTimeSubscribeParams {
+ touser: string;
+ template_id: string;
+ url?: string;
+ miniprogram?: OneTimeMiniProgram;
+ scene: string;
+ title: string;
+ data: OneTimeMsgData;
+}
+interface OneTimeSubscribeResult {
+ errcode: number;
+ errmsg: string;
+}
+export declare class CoolPlugin extends BasePlugin {
+ private getAccessToken;
+ private handleApiError;
+ private validateMassSendParams;
+ massSendByOpenId(params: MassSendByOpenIdParams): Promise<MassSendResult>;
+ massSendByTag(params: MassSendByTagParams): Promise<MassSendResult>;
+ sendTemplateMessage(params: SendTemplateMessageParams): Promise<SendResult>;
+ batchSendTemplateMessage(
+ paramsList: SendTemplateMessageParams[],
+ ): Promise<SendResult[]>;
+ sendSubscribeMsg(params: SendSubscribeMsgParams): Promise<SubscribeResult>;
+ sendOneTimeSubscribeMsg(
+ params: SendOneTimeSubscribeParams,
+ ): Promise<OneTimeSubscribeResult>;
+}
+export declare const Plugin: typeof CoolPlugin;
+export {};
--
Gitblit v1.9.1