微信公眾號、微信程式開、微信小遊戲、微信支付以及企業微信等服務端API nestjs 模組封裝。也可以直接當工具類別使用。
nest-wechat是自用業務的封裝,如果你需要用到的api還沒有,可以提issues 給我,我會盡快補上。
中文文檔
npm i --save nest-wechat
register方法註冊
import { Module } from '@nestjs/common';import { WeChatModule } from 'nest-wechat';@Module({ imports: [WeChatModule.register({appId: 'your app id', secret: 'your secret'})],})export class AppModule {}
forRoot配置註冊
import { CACHE_MANAGER, Module } from '@nestjs/common';import { ConfigModule, ConfigService } from '@nestjs/config';import { Cache } from 'cache-manager';import { RedisCache, WeChatModule } from 'nest-wechat ';@Module({ imports: [ConfigModule.forRoot({ envFilePath: '.env.test.local',}),WeChatModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService, CACHE_MANAGER],Service Factor: cacheService, Cache) => ({appId: configService.get('WX_APPID'),secret: configService.get('WX_SECRET'),token: configService.get('WX_TOKEN'),encodingAESKey: configService.get('WX_AESKEY'),cacheAdapter: new RedisCache(cache) debug: true, }),}), ]})export class AppModule {}
import { WeChatService } from 'nest-wechat';const service = new WeChatService({ appId: 'your app id', secret: 'your secret'});
/** * 快取接口,需要自訂緩存,請實作該接口 * * cache interface, please implement this interface if you need. * */export interface ICache { get<T> (key: string): Promise<T>; // eslint-disable-next-line @typescript-eslint/no-explicit-any set (key: string, value: any): void; remove (key: string): boolean; close (): void;}
配置讀寫屬性,類型:WeChatModuleOptions
快取適配器讀寫屬性,類型:ICache,預設是一個Map實作的快取
public async getAccessTokenByCode (code: string, _appId?: string, _secret?: string): Promise<UserAccessTokenResult>;
正確返回
{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
錯誤返回
{"errcode": 40029,"errmsg": "invalid code"}
參考文檔
公眾號拉取用戶訊息
public async getUserInfo (accessToken: string, openid: string, lang: 'zh_CN' | 'zh_TW' | 'en' = 'zh_CN'): Promise<UserInfoResult>;
正確返回
{ "openid": "OPENID", "nickname": NICKNAME, "sex": 1, "province":"PROVINCE", "city":"CITY", "country":"COUNTRY", "headimgurl":"https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQQ4e. "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"}
錯誤返回
{ "errcode":40003, "errmsg":" invalid openid "}
public async getAccountAccessToken (_appId?: string, _secret?: string): Promise<AccountAccessTokenResult>;
正確返回
{ "access_token": "52_s0Mcl3E3DBKs12rthjxG8_DOvsIC4puV9A34WQR6Bhb_30TW9W9BjhUxDRkyph-hY9Ab2QS03Q8w ZBe5UkA1k0q0hc17eUDZ7vAWItl4iahnhq_57dCoKc1dQ3AfiHUKGCCMJ2NcQ0BmbBRIKBEgAAAPGJ", "expires_in": 7200}
錯誤返回
{ "errcode": 40013, "errmsg": "invalid appid"}
參考文檔
public async getStableAccessToken (_appId?: string, _secret?: string, force = false): Promise<AccountAccessTokenResult>;
參考文檔
public async getJSApiTicket (_appId?: string, _secret?: string): Promise<TicketResult>;
傳回數據
{ "errcode": 0, "errmsg": "ok", "ticket": "bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVKAUgWgv."
參考文檔
public async jssdkSignature (url: string): Promise<SignatureResult>;public async jssdkSignature (url: string, appId: string, secret:string): Promise<SignatureResult>;
參考文檔
public async sendTemplateMessage (message: TemplateMessage, appId?: string, secret?: string): Promise<DefaultRequestResult & { msgid: string }>;
參考文檔
public async createQRCode (data: AccountCreateQRCode, appId?: string, secret?: string): Promise<AccountCreateQRCodeResult>;
參考文檔
public showQRCode (ticket: string): Promis<Buffer>;
參考文檔
WeChatService.checkSignatureExpress (req: Request, res: Response);
Usage:
@Get('push')async pushTest (@Req() req: Request, @Res() res: Response) { this.service.checkSignatureExpress(req, res);}
參考文檔
// 加密模式WeChatService.messagePushExpressHandler (req: Request, res?: Response, resText?: string);// 明文模式WeChatService.plainMessagePushExpressHandler (req: Request, res?: Response, resText?: string);
Usage:
@Post('push')async officialPushTest (@Req() req: Request, @Res() res: Response) { const decrypt = await this.service.messagePushExpressHandler(req, res);}
參考文檔
public getAccessToken (appId?: string, secret?: string): Promise<AccessTokenResult>;
const service = new WeChatService({ appId: 'your app id', secret: 'your secret'});const res = await service.mp.getAccessToken();console.log(res.data.access_token);
public async getRid (rid: string, accessToken: string): Promise<RidInfo>;
public async getPluginOpenPId (code: string, accessToken: string): Promise<DefaultRequestResult & { openpid: string }>;
public async code2Session (code: string, appId?: string, secret?: string): Promise<SessionResult>;
傳回數據
{ "openid": "openid", "session_key": "key", "unionid": "unionid", "errcode": 0, "errmsg": "ok", }
參考文檔
public async getPhoneNumber (code: string, accessToken: string);
參考文檔
public async getQRCode (params: QRCode, accessToken: string): Promise<DefaultRequestResult & { contentType: string, buffer: Buffer }>;
public getUnlimitedQRCode (params: GetUnlimitedQRCode, accessToken: string): Promise<DefaultRequestResult & { buffer: Buffer }>;
public async createQRCode (params: CreateQRCode, accessToken: string): Promise<DefaultRequestResult & { contentType: string, buffer: Buffer }>;
public async queryScheme (scheme: string, accessToken: string): Promise<DefaultRequestResult & { scheme_info: SchemeInfo, scheme_quota: SchemeQuota }>;
public generateScheme (params: GenerateScheme, accessToken: string): Promise<DefaultRequestResult & { openlink: string >;
public generateNFCScheme (params: GenerateNFCScheme, accessToken: string): Promise<DefaultRequestResult & { openlink: string }>;
public generateUrlLink (params: GenerateUrlLink, accessToken: string): Promise<DefaultRequestResult & { url_link: string }>;
public queryUrlLink (urlLink: string, accessToken: string): Promise<UrlLinkResult>;
public generateShortLink (params: GenerateShortLink, accessToken: string): Promise<DefaultRequestResult & { link: string }>;
public sendUniformMessage (params: SendUniformMessage, accessToken: string): Promise<DefaultRequestResult>;
public createActivityId (params: CreateActivityId, accessToken: string): Promise<ActivityIdResult>;
public setUpdatableMsg (params: UpdatableMsg, accessToken: string): Promise<DefaultRequestResult>;
public deleteMessageTemplate (priTmplId: string, accessToken: string): Promise<DefaultRequestResult>;
public getCategory (accessToken: string): Promise<DefaultRequestResult & { data: {id: number, name: string}[] }>;
public getPubTemplateKeyWordsById (tid: number, accessToken: string): Promise<PubTemplateKeyWords>;
public getPubTemplateTitleList (params: PubTemplateTitleList, accessToken: string): Promise<PubTemplateTitleListResult>;
public getMessageTemplateList (accessToken: string): Promise<MessageTemplateListResult>;
public sendMessage (params: SendMessage, accessToken: string): Promise<DefaultRequestResult>;
public addMessageTemplate (params: MessageTemplate, accessToken: string): Promise<DefaultRequestResult & { priTmplId: string }>;
Module導入
import { Module } from '@nestjs/common';import { WeChatMobileModule } from 'nest-wechat';@Module({ imports: [WeChatMobileModule.register()],})export class AppModule {}
工具類引入
import { MobileService } from 'nest-wechat';const service = new MobileService();
public getAccessToken (code: string, appId: string, secret: string): Promise<AxiosResponse<MobileAppAccessTokenResult, any>>;
public refreshAccessToken (appId: string, refreshToken: string): Promise<AxiosResponse<MobileAppAccessTokenResult, any>>;
public checkAccessToken (openId: string, accessToken: string): Promise<AxiosResponse<DefaultRequestResult, any>>;
pay.jsapi (order: TransactionOrder, serialNo: string, privateKey: Buffer | string): Promise<{prepay_id: string}>;
pay.getTransactionById (id: string, mchId: string, serialNo: string, privateKey: Buffer | string): Promise<Trade>;
pay.getTransactionByOutTradeNo (outTradeNo: string, mchId: string, serialNo: string, privateKey: Buffer | string): Promise<Trade>;
pay.close (outTradeNo: string, mchId: string, serialNo: string, privateKey: Buffer | string);
pay.refund (refund: RequireOnlyOne<RefundParameters, 'transaction_id' | 'out_trade_no'>, mchId: string, serialNo: string, privateKey: Buffer | string): Promise<RefundResult>;
pay.getRefund (outRefundNo: string, mchId: string, serialNo: string, privateKey: Buffer | string): Promise<RefundResult>;
pay.buildMiniProgramPayment (appId: string, prepayId: string, privateKey: Buffer | string): MiniProgramPaymentParameters;
pay.paidCallback (publicKey: Buffer | string, apiKey: string, req: Request, res: Response): Promise<Trade>;
pay.refundedCallback (certs: Map<string, string>, apiKey: string, req: Request, res: Response): Promise<RefundNotifyResult>;
pay.fapiaoDevConfig (data: DevelopmentConfigRequest, mchId: string, serialNo: string, privateKey: Buffer | string);
pay.getFapiaoDevConfig (mchId: string, serialNo: string, privateKey: Buffer | string);
pay.createCardTemplate (data: CreateCardTemplateRequest, mchId: string, serialNo: string, privateKey: Buffer | string);
pay.fapiaoCallback (certs: Map<string, string>, apiKey: string, req: Request, res: Response): Promise<FapiaoNotifyResult>;
pay.getUserTitle (params: GetUserTitleParams, mchId: string, serialNo: string, privateKey: Buffer | string);
pay.issueFapiao (data: IssueFapiaoRequest, mchId: string, serialNo: string, privateKey: Buffer | string);
pay.getIssueFapiao (fapiaoApplyId: string, fapiaoId: string, mchId: string, serialNo: string, privateKey: Buffer | string);
pay.reverseFapiao (fapiaoApplyId: string, data: ReverseFapiaoRequest, mchId: string, serialNo: string, privateKey: Buffer | string);
pay.rsaEncryptOAEP (text: string, publicKey: Buffer | string);
pay.rsaDecryptOAEP (cipherText: string, privateKey: Buffer | string);
沒有可用測試商戶,未做成功測試,請自行測試,有問題請提issue。
測試可自行執行單元測試(需修改配置)
npm run test lib/wepay.hb.spec.ts
pay.sendRedPack(redPack: RedPackData, appId: string, mchId: string, apiKey: string, publicKey: Buffer | string, privateKey: Buffer | string, group = false): Promise<AxiosResponse>;
pay.sendGroupRedPack(redPack: GroupRedPackData, appId: string, mchId: string, apiKey: string, publicKey: Buffer | string, privateKey: Buffer | string): Promise<AxiosResponse<string, any><string, any>;
pay.getHbInfo(billNO: string, appId: string, mchId: string, apiKey: string, publicKey: Buffer | string, privateKey: Buffer | string): Promise<AxiosResponse<string, any>>;
參考文檔
jsapiOfPartner (order: TransactionOrderOfPartner, serialNo: string, privateKey: Buffer | string);
參考文檔
建構調起微信支付參數接口
buildJSAPIParameters (appId: string, prepayId: string, privateKey: Buffer | string): MiniProgramPaymentParameters;
參考文檔
paidCallbackOfPartner (certs: Map<string, string>, apiKey: string, req: Request, res: Response): Promise<TradeOfPartner>;
參考文檔
closeOfPartner (outTradeNo: string, spMchId: string, subMchId: string, serialNo: string, privateKey: Buffer | string);
參考文檔
getTransactionByIdOfPartner (id: string, spMchId: string, subMchid: string, serialNo: string, privateKey: Buffer | string);
參考文檔
getTransactionByOutTradeNoOfPartner (outTradeNo: string, spMchId: string, subMchid: string, serialNo: string, privateKey: Buffer | string);
參考文檔
refundOfPartner (refund: RequireOnlyOne<RefundParametersOfPartner, 'transaction_id' | 'out_trade_no'>, spMchId: string, serialNo: string, privateKey: Buffer | string);
參考文檔
getRefundOfPartner (outRefundNo: string, spMchId: string, subMchId: string, serialNo: string, privateKey: Buffer | string);
參考文檔
refundedCallbackOfPartner (certs: Map<string, string>, apiKey: string, req: Request, res: Response): Promise<RefundNotifyResultOfPartner>;
參考文檔
createCardTemplateOfPartner (data: CreateCardTemplateRequestOfPartner, spMchId: string, serialNo: string, privateKey: Buffer | string);
參考文檔
fapiaoDevConfigOfPartner (data: DevelopmentConfigRequestOfPartner, spMchId: string, serialNo: string, privateKey: Buffer | string);
參考文檔
getFapiaoDevConfigOfPartner (spMchId: string, subMchId: string, serialNo: string, privateKey: Buffer | string);
參考文檔
fapiaoCallbackOfPartner (certs: Map<string, string>, apiKey: string, req: Request, res: Response): Promise<FapiaoNotifyResultOfPartner>;
參考文檔
getUserTitleOfPartner (params: GetUserTitleParams, spMchId: string, subMchId: string, serialNo: string, privateKey: Buffer | string);
參考文檔
issueFapiaoOfPartner (data: IssueFapiaoRequestOfPartner, spMchId: string, serialNo: string, privateKey: Buffer | string, platformSerial: string);
參考文檔
getIssueFapiaoOfPartner (fapiaoApplyId: string, fapiaoId: string | null | undefined, spMchId: string, subMchid: string, serialNo: string, privateKey: Buffer | string);
參考文檔
reverseFapiaoOfPartner (fapiaoApplyId: string, data: ReverseFapiaoRequestOfPartner, spMchId: string, serialNo: string, privateKey: Buffer | string);
decryptCipherText
decryptCipherText<T> (apiKey: string, cipher: string, associatedData: string, nonce: string): T | string;
參考文檔
import { MessageCrypto } from 'nest-wechat';const sha1 = MessageCrypto.sha1('string to hash');
靜態方法:
sha1 (...args: string[]): string;
md5 (text: string): string;
getAESKey (encodingAESKey: string): Buffer;
getAESKeyIV (aesKey: Buffer): Buffer;
PKCS7Encoder (buff: Buffer): Buffer;
PKCS7Decoder (buff: Buffer): Buffer;
decrypt (aesKey: Buffer, iv: Buffer, str: string): string;
encrypt (aesKey: Buffer, iv: Buffer, msg: string, appId: string): string;
createNonceStr (length = 16): string;
encryptMessage (appId: string, token: string, encodingAESKey: string, message: string, timestamp: string, nonce: string): string;
decryptMessage (token: string, encodingAESKey: string, signature: string, timestamp: string, nonce: string, encryptXml: string);
decryptMessage (token: string, encodingAESKey: string, signature: string, timestamp: string, nonce: string, encryptXml: string);
checkSignature (signature: string, timestamp: string, nonce: string, token: string);
Create .env.test.local file, and save your test appid and secret in the file.
TEST_APPID=your/test/appid
TEST_SECRET=your/test/secret
TEST_JSSDK_URL=https://your/website/url
TEST_TOKEN=your/token
TEST_AESKEY=your/aeskey
REDIS_HOST=your/redis/host
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
REDIS_TTL=600
Run e2e test.
npm run test:e2e
Run unit test.
npm run test wechat.service.userinfo.spec.ts
開啟服務測試
npx ts-node -T tests/e2e/wechat-app.main.ts
公眾號訊息推送配置(微信公眾測試平台),開啟上面服務測試後,可以通過配置驗證
URL: http://your/url/wechat/push,如:http://113.22.11.2:3001/wechat/push
Token: pamtest
在微信公眾平台介面除錯工具獲得access_token
body
{ "grant_type": "client_credential", "appid": "your/appid", "secret": "your/secret", "force_refresh": false}
在微信開放平台調試工具-訊息推送測試的調試工具測試推送