/// <reference types="node"/>

declare module 'xx-weixin-pay' {
  import * as Stream from 'stream';

  export interface IOptions {
    appid: string;
    mch_id: string;
    partner_key: string;
    pfx: Buffer;
    sandbox?: boolean;
  }

  export interface IObject {
    [key: string]: any;
  }

  export interface IUtil {
    buildXML(json: IObject): string;

    parseXML(xml: string, fn: (err: Error, result: IObject) => void): void;

    parseRaw(): (req: any, res: any, next: any) => void;

    pipe(stream: Stream, fn: (err: Error, buf: Buffer) => void): void;

    mix<T>(root: T, ...args: any[]): T & IObject;

    generateNonceString(length?: number): string;
  }

  export default class WXPay {
    options: IOptions;
    wxpayID: {
      appid: string;
      mch_id: string;
    };

    Util: IUtil;

    constructor(options: IOptions);

    mix(obj: IObject): void;
    mix(key: string, fn: (...args: any[]) => any): void;

    option(option: IOptions): void;

    sign(param: IObject): string;

    createUnifiedOrder(opts: {
      body: string;
      out_trade_no: string;
      total_fee: number;
      spbill_create_ip: string;
      time_start: string;
      time_expire: string;
      notify_url: string;
      trade_type: string;
      openid?: string;
      sign_type?: 'MD5' | 'HMAC-SHA256',
      nonce_str?: string;
    }, fn: (error: Error, data: {
      return_code: string;
      return_msg: string;
      result_code: string;
      err_code: string;
      err_code_des: string;
      prepay_id: string;
      [other: string]: any;
    }) => void): void;

    getBrandWCPayRequestParams(order: {
      body: string;
      out_trade_no: string;
      total_fee: number;
      spbill_create_ip: string;
      time_start: string;
      time_expire: string;
      notify_url: string;
      trade_type: string;
      nonce_str?: string;
    }, fn: (error: Error, data: {
      appId: string;
      timeStamp: string;
      nonceStr: string;
      package: string;
      signType: string;
      paySign: string;
      [other: string]: any;
    }) => void): void;

    createMerchantPrepayUrl(param: IObject): string;

    useWXCallback(fn: (msg: any, req: any, res: any, next: any) => void): (req: any, res: any, next: any) => void;

    queryOrder(query: {
      out_trade_no?: string;
      transaction_id?: string;
      nonce_str?: string;
    }, fn: (error: Error, data: {
      return_code: string;
      return_msg: string;
      result_code: string;
      err_code: string;
      err_code_des: string;
      trade_state: string;
      trade_state_desc: string;
      total_fee: string;
      transaction_id: string;
      time_end: string;
      openid: string;
      [other: string]: any;
    }) => void): void;

    closeOrder(order: {
      out_trade_no: string;
      nonce_str?: string;
    }, fn: (error: Error, data: {
      return_code: string;
      return_msg: string;
      result_code: string;
      err_code: string;
      err_code_des: string;
      [other: string]: any;
    }) => void): void;

    refund(order: {
      out_trade_no?: string;
      transaction_id?: string;
      out_refund_no: string;
      nonce_str?: string;
      total_fee: number;
      refund_fee: number;
      refund_desc?: string;
      refund_account?: string;
      notify_url?: string;
    }, fn: (error: Error, data: {
      return_code: string;
      return_msg: string;
      result_code: string;
      err_code: string;
      err_code_des: string;
      transaction_id: string;
      out_trade_no: string;
      out_refund_no: string;
      refund_id: string;
      refund_fee: string;
      total_fee: string;
      [other: string]: any;
    }) => void): void;

    queryRefund(order: {
      transaction_id?: string;
      out_trade_no?: string;
      out_refund_no?: string;
      refund_id?: string;
    }, fn: (error: Error, data: {
      return_code: string;
      return_msg: string;
      result_code: string;
      err_code: string;
      err_code_des: string;
      out_trade_no: string;
      out_refund_no: string;
      refund_count: number;
      [other: string]: any;
    }) => void): void;

    getSignKey(fn: (error: Error, data: IObject) => void): void;
  }
}
