npm package: @lantsang/nestjs-wechat-pay-provider
Description: 微信服务商支付-nestjs插件
Author: lantsang
Latest version: 0.0.4

# Nestjs 微信支付插件

注意：<font color="#dd0000">仍在开发中，目前仅在内部使用</font><br /> 

## 使用说明

* 外部人员仅供参考，请不要用于生产环境，因此导致的事故后果请自行承担。
* TS target es2019

## 安装

`$ npm i @lantsang/nestjs-wechat-pay-provider` <br />
or <br />
`$ yarn add @lantsang/nestjs-wechat-pay-provider` <br />
推荐使用yarn

## 模块注册

``` typescript
import { WechatPayModule, WechatPaySignType } from '@lantsang/nestjs-wechat-pay-provider'

@Module({
  imports: [
    WechatPayModule.forRoot({
      appid: '服务商appid,开启服务商的公众号对应的appid',
      mchId: '服务商商户号',
      sub_appid: '子商户appid',
      sub_mch_id: '子商户号',
      secretKey: "服务商APi秘钥",
      pfx: readFileSync(join(__dirname, '../config/apiclient_cert.p12')),
      sandbox: true,  //是否开启沙盒
      signType: WechatPaySignType.MD5
    })  
  ]
})
export class AppModule { }
```

## 使用

### 统一下单

* **小程序**

``` typescript
import { Request, Response } from "express";
import { JSAPIPayService } from '@lantsang/nestjs-wechat-pay-provider'

@ApiTags('pay')
@Controller('pay')
export class PayController {
  constructor(
    private readonly wechatMpPayService: JSAPIPayService,
  ) { }

  @ApiOperation({ description: '使用微信支付支付订单' })
  @ApiOkResponse({ description: '返回微信支付参数', type: WechatPayMpResDto })
  @Post('wechat')
  async MpUserPay(@Req() req: Request, @Body() { uuid }: UuidReqDto):Promise<WechatPayMpResDto> {
    try {
      const rawIp: string = req.headers['x-forwarded-for'] ||
        req.connection.remoteAddress ||
        req.socket.remoteAddress ||
        req.connection['socket'].remoteAddress;
      const ip = rawIp.split(',')[0];
      const user = req.user;

      //根据订单uuid查询订单，验证订单是否存在
      const order = await this.orderService.findOneByUuid(uuid);
      if (!order) return res.status(HttpStatus.BAD_REQUEST).send('无该订单');
      if (order.orderStatus !== OrderStatus.pending) return res.status(HttpStatus.OK).send('该订单已支付');

      const mpUser = await this.userMpInfoService.findOneByUserUuid(user.uuid);
      if (!mpUser) return res.status(HttpStatus.BAD_REQUEST).send('无法获取个人信息');

      const { success, data, errorMessage } = await this.wechatMpPayService.placeOrder({
        sun_openid: mpUser.openid, notify_url: config.Pay.Wechat.NotifyUrl, out_trade_no: order.tradeNo, body: 'test', total_fee: order.price, spbill_create_ip: ip
      })

      if (!success) return res.status(HttpStatus.BAD_REQUEST).send(errorMessage);

      return {
        time_stamp: data.timeStamp,
        nonce_str: data.nonceStr,
        package: data.package,
        sign_type: data.signType,
        pay_sign: data.paySign
      }
    } catch (error) {
      if (error instanceof HttpException) throw error;
      this.logService.fatal(SystemLogAppender.pay, `Mp user ${req.user.uuid} pay order ${uuid} by wechatPay failed and error is ${error}` , this.lantUtil.parseError(error));
      throw new HttpException(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }
}
```

* **JSAPI(公众号)**

``` typescript
const { success, data, errorMessage } = await this.wechatJSAPIPayService.placeOrder({
  sub_openid: mpUser.openid, notify_url: config.Pay.Wechat.NotifyUrl, out_trade_no: order.tradeNo, body: 'test', total_fee: order.price, spbill_create_ip: ip
})
```