1
+ import { WeChatUtil } from '../../utile/wechat.util' ;
2
+ import { CACHE_MANAGER , HttpException , HttpService , Inject , Injectable } from '@nestjs/common' ;
3
+ import * as crypto from 'crypto' ;
4
+
5
+ @Injectable ( )
6
+ export class WechatSdk {
7
+ constructor (
8
+ @Inject ( WeChatUtil ) private readonly wechatUtil : WeChatUtil ,
9
+ @Inject ( HttpService ) private readonly httpService : HttpService ,
10
+ @Inject ( CACHE_MANAGER ) protected readonly cacheManager : any ,
11
+ ) { }
12
+
13
+ /**
14
+ * sdk 签名算法
15
+ * @param {string } appid (必传)用于取 jsapi_ticket
16
+ * @param {string } url (必传) 用于签名的url,注意必须与调用JSAPI时的页面URL完全一致
17
+ * @returns {Promise<string> }
18
+ * 注意事项:
19
+ * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
20
+ * 2.签名用的url必须是调用JS接口页面的完整URL。
21
+ * 详情请参开微信公众平台js-sdk附录一,https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
22
+ */
23
+ async signatureAlgorithm ( nonceStr : string , timestamp : string , appid : string , url : string ) {
24
+ const ticket = await this . getTicket ( appid ) ;
25
+ const ret = { jsapi_ticket : ticket , nonceStr, timestamp, url} ;
26
+ const str = await this . wechatUtil . sortQuery ( ret ) ;
27
+ const shasum = crypto . createHash ( 'sha1' ) ;
28
+ shasum . update ( str ) ;
29
+ return shasum . digest ( 'hex' ) ;
30
+ }
31
+
32
+ /**
33
+ * 获取jsapi_ticket
34
+ * jsapi_ticket是公众号用于调用微信JS接口的临时票据。
35
+ * 正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。
36
+ * 由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
37
+ * @param {string } appid (必传) 用于存jsapi_ticket
38
+ * @returns {Promise<any> }
39
+ */
40
+ async getTicket ( appid : string ) {
41
+ if ( ! appid ) {
42
+ throw new HttpException ( 'appid不存在!!' , 500 ) ;
43
+ }
44
+ const ticket = await this . cacheManager . get ( appid ) ;
45
+ if ( ticket ) {
46
+ return ticket ;
47
+ }
48
+ const accessToken : string = await this . wechatUtil . ensureAccessToken ( appid ) ;
49
+ const url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${ accessToken } &type=jsapi` ;
50
+ const { data } = await this . httpService . get ( url ) . toPromise ( ) ;
51
+ if ( data . errcode ) {
52
+ throw new HttpException ( data . errmsg , data . errcode ) ;
53
+ }
54
+ await this . cacheManager . set ( appid , data . data . ticket ) ;
55
+ return ticket ;
56
+ }
57
+
58
+ /**
59
+ * 获取JsSdk wx.config接口所需的参数
60
+ * @param {string } appid (必传)
61
+ * @param {string } url (必传) 用于签名的url,注意必须与调用JSAPI时的页面URL完全一致
62
+ * @returns {Promise<{nonceStr: any; timestamp: string; signature: string}> }
63
+ */
64
+ async getJsSdkConfig ( appid : string , url : string ) {
65
+ if ( ! appid ) {
66
+ throw new HttpException ( 'appid不存在!!' , 500 ) ;
67
+ }
68
+ if ( ! url ) {
69
+ throw new HttpException ( 'url不存在!!' , 500 ) ;
70
+ }
71
+ const nonceStr = await this . wechatUtil . generatingRandomNumbers ( ) ;
72
+ const timestamp = await this . wechatUtil . generationTimestamp ( ) ;
73
+ const signature = await this . signatureAlgorithm ( nonceStr , timestamp , appid , url ) ;
74
+ return { nonceStr, timestamp, signature} ;
75
+ }
76
+ }
0 commit comments