import { HttpService , Inject , Injectable } from '@nestjs/common' ; import * as axios from 'axios' ; import { WeChatPayConfig } from '../../../common' ; import { RandomUtil } from '../../../shared/utils/random.util' ; import { XmlUtil } from '../../../shared/utils/xml.util' ; import { WeChatPayConfigProvider } from '../constants/wechat.constant' ; import { WeChatSignUtil } from './sign.util' ; /**
 * 微信支付接口请求工具
 */ @ Injectable ( ) export class WeChatRequestUtil { constructor ( @ Inject ( HttpService ) private readonly httpService , @ Inject ( WeChatPayConfigProvider ) private readonly config , @ Inject ( XmlUtil ) private readonly xmlUtil , @ Inject ( WeChatSignUtil ) private readonly signUtil , @ Inject ( RandomUtil ) private readonly randomUtil ) { } param url param params param config async post < T > ( url , params , config ? ) { if ( params . wxappid ) { } else if ( params . mch_appid ) { } else { params . appid = this . config . appid ; } if ( ! params . mchid ) { params . mch_id = this . config . mch_id ; } params . nonce_str = await this . randomUtil . genRandomStr ( ) ; let signType ; if ( params . sign_type && params . sign_type === 'no_sign_type' ) { signType = 'MD5' ; delete params . sign_type ; } else { signType = this . config . sign_type ; params . sign_type = this . config . sign_type ? this . config . sign_type : 'MD5' ; } params . sign = this . signUtil . sign ( params , signType ) ; try { const { data } = await this . httpService . post < T > ( url , this . xmlUtil . convertObjToXml ( params ) , config ) . toPromise ( ) ; if ( ( data as any ) . return_code === 'SUCCESS' ) { if ( params . sign && params . sign !== ( data as any ) . sign ) throw new Error ( '微信支付接口返回签名有误' ) ; } return this . xmlUtil . parseObjFromXml < T > ( data ) ; } catch ( error ) { throw new Error ( '微信支付请求接口时出现网络异常：' + error . toString ( ) ) ; } } param params checkParamNo ( params ) { for ( const no of [ 'out_trade_no' , 'out_refund_no' , 'mch_billno' , 'partner_trade_no' ] ) { if ( Object . keys ( params ) . includes ( no ) ) { switch ( no ) { case 'out_trade_no' : this . regexpTest ( params , 'out_trade_no' , 32 , 'special' ) ; break ; case 'out_refund_no' : this . regexpTest ( params , 'out_refund_no' , 64 , 'special' ) ; break ; case 'mch_billno' : this . regexpTest ( params , 'mch_billno' , 28 , 'normal' ) ; break ; case 'partner_trade_no' : this . regexpTest ( params , 'partner_trade_no' , 32 , 'normal' ) ; break ; } } } } param params param propertyName param maxLength param regexpType regexpTest ( params , propertyName , maxLength , regexpType ) { if ( params [ propertyName ] . length > maxLength ) { throw new Error ( `参数 ${ propertyName } 长度不能大于 ${ maxLength } 个字符` ) ; } const normalRegexp = new RegExp ( /^[A-Za-z0-9]+$/ , 'g' ) ; const specialRegexp = new RegExp ( /^[A-Za-z0-9_\-|\*@]+$/ , 'g' ) ; if ( regexpType === 'normal' ) { if ( ! normalRegexp . test ( params [ propertyName ] ) ) { throw new Error ( `参数 ${ propertyName } 只能是字母或者数字` ) ; } } if ( regexpType === 'special' ) { if ( ! specialRegexp . test ( params [ propertyName ] ) ) { throw new Error ( `参数 ${ propertyName } 只能是数字、大小写字母或_-|*@` ) ; } } } }