返回 AiToEarn
wxGzh.service.ts
根目录 / project / aitoearn-electron / server / src / lib / wx / wxGzh.service.ts
1 /*
2 * @Author: nevin
3 * @Date: 2024-06-17 16:12:56
4 * @LastEditTime: 2025-02-26 10:12:02
5 * @LastEditors: nevin
6 * @Description: 微信公众号服务
7 */
8 import { Injectable } from '@nestjs/common';
9 import { ConfigService } from '@nestjs/config';
10 import * as crypto from 'crypto';
11 import { RedisService } from '../redis/redis.service';
12 import axios from 'axios';
13
14 @Injectable()
15 export class WxGzhService {
16 appId = '';
17 secret = '';
18 token = '';
19 aesKey = '';
20 constructor(
21 private readonly configService: ConfigService,
22 private readonly redisService: RedisService,
23 ) {
24 this.appId = this.configService.get('WX_GZH.WX_GZH_ID');
25 this.secret = this.configService.get('WX_GZH.WX_GZH_SECRET');
26 this.token = this.configService.get('WX_GZH.WX_GZH_TOKEN');
27 this.aesKey = this.configService.get('WX_GZH.WX_GZH_AES_KEY');
28 }
29
30 /**
31 * 获取access_token
32 * @returns
33 */
34 private async getAccessToken(): Promise<string> {
35 try {
36 const orgValue: string = await this.redisService.get(
37 `${this.appId}:access_token`,
38 );
39 if (orgValue) return orgValue;
40
41 const url = `https://api.weixin.qq.com/cgi-bin/stable_token`;
42 const result: {
43 data: {
44 access_token: string;
45 expires_in: number;
46 errcode: number;
47 errmsg: string;
48 };
49 } = await axios.post(url, {
50 grant_type: 'client_credential',
51 appid: this.appId,
52 secret: this.secret,
53 });
54
55 if (!!result.data.errcode)
56 throw new Error(result.data.errcode + '---' + result.data.errmsg);
57
58 if (result.data.access_token) {
59 await this.redisService.setKey(
60 `${this.appId}:access_token`,
61 result.data.access_token,
62 result.data.expires_in,
63 );
64 }
65
66 return result.data.access_token;
67 } catch (error: any) {
68 console.log('--------- getAccessToken ---- error', error);
69
70 return '';
71 }
72 }
73
74 /**
75 * 创建二维码
76 * @returns
77 */
78 async createQrcode(sceneStr: string): Promise<string> {
79 const orgValue: string = await this.redisService.get(
80 `${this.appId}:create_qrcode_ticket:${sceneStr}`,
81 );
82 if (orgValue) return orgValue;
83
84 const accessToken = await this.getAccessToken();
85 if (!accessToken) return '';
86
87 try {
88 const url = `https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=${accessToken}`;
89 const result: {
90 data: {
91 errcode: number;
92 errmsg: string;
93 ticket: string;
94 expire_seconds: number;
95 url: string;
96 };
97 } = await axios.post(url, {
98 expire_seconds: 60 * 8,
99 action_name: 'QR_STR_SCENE',
100 action_info: { scene: { scene_str: sceneStr } },
101 });
102
103 if (!!result.data.errcode)
104 throw new Error(result.data.errcode + '---' + result.data.errmsg);
105
106 if (!!result.data.ticket) {
107 await this.redisService.setKey(
108 `${this.appId}:create_qrcode_ticket:${sceneStr}`,
109 result.data.ticket,
110 result.data.expire_seconds,
111 );
112 }
113
114 return result.data.ticket;
115 } catch (error) {
116 console.log('--------- createQrcode ---- error', error);
117 return '';
118 }
119 }
120
121 /**
122 * 提供给微信进行验证
123 * @returns
124 */
125 async checkCallback(param: {
126 signature: string;
127 echostr: string;
128 timestamp: string;
129 nonce: string;
130 }): Promise<string> {
131 const { signature, echostr, timestamp, nonce } = param;
132
133 // 将 token、timestamp、nonce三个参数按字典序排序
134 const str = [this.token, timestamp, nonce].sort().join('');
135
136 // 加密字符串, 建议使用 sha1加密
137 const sha1 = crypto.createHash('sha1');
138 sha1.update(str);
139 const sha1Str = sha1.digest('hex');
140
141 if (sha1Str === signature) {
142 console.log('验证成功');
143 return echostr;
144 } else {
145 return 'error';
146 }
147 }
148
149 async doMsg(
150 param: {
151 signature: string;
152 timestamp: string;
153 nonce: string;
154 },
155 xml: {
156 ToUserName: string;
157 FromUserName: string;
158 CreateTime: string;
159 MsgType: string;
160 Event: string;
161 EventKey: string;
162 },
163 ): Promise<string> {
164 return '';
165 }
166 }
167
167 lines TYPESCRIPT