npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nest-wechat

v0.2.50

Published

nestjs module for wechat server-side api.

Downloads

549

Readme

快速开始

安装

npm i --save nest-wechat

nestjs 模块引入

  • 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],
      useFactory: (configService: ConfigService, cache: 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'});

全局接口

ICache

/**
 * 缓存接口,需要自定义缓存,请实现该接口
 * 
 * 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;
}

WeChatService 属性与方法

config: WeChatModuleOptions

配置读写属性,类型:WeChatModuleOptions

cacheAdapter: ICache

缓存适配器读写属性,类型:ICache,默认是一个Map实现的缓存

微信公众号API

网页授权

getAccessTokenByCode

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"
}

参考文档

getUserInfo

公众号拉取用户信息

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/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
  "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

错误返回

{
  "errcode":40003,
  "errmsg":" invalid openid "
}

获取Access token

getAccountAccessToken

public async getAccountAccessToken (_appId?: string, _secret?: string): Promise<AccountAccessTokenResult>;

正确返回

{
  "access_token": "52_s0Mcl3E3DBKs12rthjxG8_DOvsIC4puV9A34WQR6Bhb_30TW9W9BjhUxDRkyph-hY9Ab2QS03Q8wZBe5UkA1k0q0hc17eUDZ7vAWItl4iahnhq_57dCoKc1dQ3AfiHUKGCCMJ2NcQ0BmbBRIKBEgAAAPGJ",
  "expires_in": 7200
}

错误返回

{
  "errcode": 40013,
  "errmsg": "invalid appid"
}

参考文档

获取稳定版接口调用凭据

getStableAccessToken

public async getStableAccessToken (_appId?: string, _secret?: string, force = false): Promise<AccountAccessTokenResult>;

参考文档

获取jsapi_ticket

getJSApiTicket

public async getJSApiTicket (_appId?: string, _secret?: string): Promise<TicketResult>;

返回数据

{
  "errcode": 0,
  "errmsg": "ok",
  "ticket": "bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
  "expires_in": 7200
}

参考文档

JS-SDK使用权限签名

jssdkSignature

public async jssdkSignature (url: string): Promise<SignatureResult>;
public async jssdkSignature (url: string, appId: string, secret:string): Promise<SignatureResult>;

参考文档

发送模板消息

sendTemplateMessage

public async sendTemplateMessage (message: TemplateMessage, appId?: string, secret?: string): Promise<DefaultRequestResult & { msgid: string }>;

参考文档

生成带参数的二维码

createQRCode

public async createQRCode (data: AccountCreateQRCode, appId?: string, secret?: string): Promise<AccountCreateQRCodeResult>;

参考文档

通过ticket换取二维码

showQRCode

public showQRCode (ticket: string): Promis<Buffer>;

参考文档

填写服务器配置

checkSignatureExpress

WeChatService.checkSignatureExpress (req: Request, res: Response);

Usage:

@Get('push')
async pushTest (@Req() req: Request, @Res() res: Response) {
  this.service.checkSignatureExpress(req, res);
}

参考文档

接收事件推送

messagePushExpressHandler

// 加密模式
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);

查询rid信息

public async getRid (rid: string, accessToken: string): Promise<RidInfo>;

获取插件用户openpid

public async getPluginOpenPId (code: string, accessToken: string): Promise<DefaultRequestResult & { openpid: string }>;

登录code2Session

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 }>;

查询scheme码

public async queryScheme (scheme: string, accessToken: string): Promise<DefaultRequestResult & { scheme_info: SchemeInfo, scheme_quota: SchemeQuota }>;

获取scheme码

public generateScheme (params: GenerateScheme, accessToken: string): Promise<DefaultRequestResult & { openlink: string >;

获取NFC的小程序scheme

public generateNFCScheme (params: GenerateNFCScheme, accessToken: string): Promise<DefaultRequestResult & { openlink: string }>;

获取URLLink

public generateUrlLink (params: GenerateUrlLink, accessToken: string): Promise<DefaultRequestResult & { url_link: string }>;

查询URLLink

public queryUrlLink (urlLink: string, accessToken: string): Promise<UrlLinkResult>;

获取ShortLink

public generateShortLink (params: GenerateShortLink, accessToken: string): Promise<DefaultRequestResult & { link: string }>;

下发统一消息

public sendUniformMessage (params: SendUniformMessage, accessToken: string): Promise<DefaultRequestResult>;

创建activity_id

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();

通过code获取access_token

public getAccessToken (code: string, appId: string, secret: string): Promise<AxiosResponse<MobileAppAccessTokenResult, any>>;

刷新或续期access_token

public refreshAccessToken (appId: string, refreshToken: string): Promise<AxiosResponse<MobileAppAccessTokenResult, any>>;

检验access_token

public checkAccessToken (openId: string, accessToken: string): Promise<AxiosResponse<DefaultRequestResult, any>>;

微信支付

小程序

JSAPI下单

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<string, any>>;

发放裂变红包

pay.sendGroupRedPack(redPack: GroupRedPackData, appId: string, mchId: string, apiKey: string, publicKey: Buffer | string, privateKey: Buffer | string): Promise<AxiosResponse<string, any>>;

查询红包记录

pay.getHbInfo(billNO: string, appId: string, mchId: string, apiKey: string, publicKey: Buffer | string, privateKey: Buffer | string): Promise<AxiosResponse<string, any>>;

微信支付服务商

服务商JSAPI下单

参考文档

jsapiOfPartner (order: TransactionOrderOfPartner, serialNo: string, privateKey: Buffer | string);

服务商JSAPI调起支付

参考文档

构建调起微信支付参数接口

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);

Run Test

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
}