
/*=============================================================================================
	author:ZhaoJun
	version:1.2
	email:2732810281@qq.com
=============================================================================================*/


//严格模式
/*-------------------------------------------------------------------------------------------*/	
'use strict';
/*-------------------------------------------------------------------------------------------*/
const fs=require('fs')
const crypto=require('crypto')

// 支付宝的操作
/*-------------------------------------------------------------------------------------------*/	
class Ali 
{
    static com(obj)
    {
        if(obj instanceof Object)
        {
            return obj
        }
        else
        {
            try 
            {
                return JSON.parse(obj)    
            } 
            catch (error) 
            {
                return {}
            }
        }
    }

    static buildParams(obj,type='alipay.trade.wap.pay') 
    {
        let params = new Map();
        params.set('app_id', $ToolPay.ali.appid);
        params.set('method', type);
        params.set('charset', 'utf-8');
        params.set('sign_type', 'RSA2');
        params.set('timestamp', $Sys.model('/tool/time','format',['y-m-d h:i:s']));
        params.set('version', '1.0');
        if(obj.notify_url)params.set('notify_url', obj.notify_url);
        params.set('biz_content',JSON.stringify(obj));
        params.set('sign', Ali._buildSign(params));
 
        return [...params].map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&');
    }

    static _buildSign(paramsMap) 
    {
        let paramsList = [...paramsMap].filter(([k1, v1]) => k1 !== 'sign' && v1);
        paramsList.sort();
        let paramsString = paramsList.map(([k, v]) => `${k}=${v}`).join('&');
 
        let privateKey = fs.readFileSync($ToolPay.ali.privateKey, 'utf8');
        let signType = paramsMap.get('sign_type');
        return Ali._PrivateKey(signType, paramsString, privateKey);
    }

    static _PrivateKey(signType, content, privateKey) 
    {
        let sign;
        if (signType.toUpperCase() === 'RSA2') 
        {
            sign = crypto.createSign("RSA-SHA256");
        } 
        else if (signType.toUpperCase() === 'RSA') 
        {
            sign = crypto.createSign("RSA-SHA1");
        } 
        else 
        {
            throw new Error('[支付宝支付]请传入正确的签名方式，signType：' + signType);
        }
        sign.update(content);
        return sign.sign(privateKey, 'base64');
    }
 

    static verifySign(params) 
    {
        try 
        {
            let sign = params['sign'];//签名
            let signType = params['sign_type'];//签名类型
            if(!signType)return false
            let paramsMap = new Map();
            for (let key in params) 
            {
                paramsMap.set(key, params[key]);
            }
            let paramsList = [...paramsMap].filter(([k1, v1]) => k1 !== 'sign' && k1 !== 'sign_type' && v1);
            paramsList.sort();
            let paramsString = paramsList.map(([k, v]) => `${k}=${decodeURIComponent(v)}`).join('&');
            let publicKey = fs.readFileSync($ToolPay.ali.publicKey, 'utf8');
            return Ali._PublicKey(signType, sign, paramsString, publicKey);
        } 
        catch (err) 
        {
            console.error('[支付宝支付]',err);
            return false;
        }
    }

    static _PublicKey(signType, sign, content, publicKey) 
    {
        try 
        {
            let verify;
            if (signType.toUpperCase() === 'RSA2') 
            {
                verify = crypto.createVerify('RSA-SHA256');
            } 
            else if (signType.toUpperCase() === 'RSA') 
            {
                verify = crypto.createVerify('RSA-SHA1');
            } 
            else 
            {
                throw new Error('未知signType：' + signType);
            }
            verify.update(content);
            return verify.verify(publicKey, sign, 'base64')
        } 
        catch (err) 
        {
            console.error('[支付宝支付]',err);
            return false;
        }
    }

    static async back(obj)
    {
        let sign=Ali.buildParams(obj,'alipay.trade.refund')
        let data= await $Sys.model
        (
            '/request/fetch','post',
            [
                {
                    host: 'openapi.alipay.com',
                    path: '/gateway.do',
                    method: 'POST',
                    data:sign,
                }
            ]
        );

        return Ali.com(data.data)
    }

    static async query(obj,type='alipay.trade.query')
    {
        //查询转账接口alipay.fund.trans.order.query
        let sign=Ali.buildParams(obj,type)
        
        let data= await $Sys.model
        (
            '/request/https','post',
            [
                {
                    host: 'openapi.alipay.com',
                    path: '/gateway.do',
                    method: 'POST',
                    data:sign,
                }
            ]
        );
        
        return Ali.com(data.data)
    }

    static async tran(obj,type='alipay.fund.trans.toaccount.transfer')
    {
        obj.payee_type='ALIPAY_LOGONID'
        let sign=Ali.buildParams(obj,type)
        
        let data= await $Sys.model
        (
            '/request/https','post',
            [
                {
                    host: 'openapi.alipay.com',
                    path: '/gateway.do',
                    method: 'POST',
                    data:sign,
                }
            ]
        );
        
        return Ali.com(data.data)
    }

    static async code(obj)
    {
        let sign=Ali.buildParams(obj,'alipay.trade.precreate')
        
        let data= await $Sys.model
        (
            '/request/fetch','post',
            [
                {
                    host: 'openapi.alipay.com',
                    path: '/gateway.do',
                    method: 'POST',
                    data:sign,
                }
            ]
        );
        
        return Ali.com(data.data)
    }

    static success()
    {
    	return `success`
    }
 
}
 
module.exports = Ali;