<?php

/**
 * 支付宝插件 使用方法请查看同文件夹下的demo
 * 目前已经支持电脑网站支付,手机APP支付,支付回调校验,用户提现等功能,如需拓展请联系作者
 * @author Jack_YanTC <627495692@qq.com>
 */
class AliPay {

    private $appId;
    private $rsaPrivateKey;
    private $signType;
    private $alipayrsaPublicKey;
    private $notifyUrl;
    private $returnUrl;

    /**
     * 初始化参数
     *
     * C('ALI_PAY') Api Config中的配置
     * @param array $options
     * @param $options ['appId']  应用ID,在支付宝上获取
     * @param $options ['rsaPrivateKey'] 应用密钥,与应用公钥一组,公钥填写到支付宝
     * @param $options ['signType'] 签名方式
     * @param $options ['alipayrsaPublicKey'] 支付宝公钥,在支付宝上获取
     * @param $options ['notifyUrl'] 支付宝回调地址
     * @param $options ['returnUrl'] 用于web支付返回地址
     */
    public function __construct($options = null) {
        $this->appId = isset ($options['appId']) ? $options['appId'] : config('ali_app_id');
        $this->rsaPrivateKey = isset ($options['private_key_path']) ? $options['private_key_path'] : config('private_key');
        $this->signType = isset ($options['sign_type']) ? $options['sign_type'] : config('ali_sign_type');
        $this->notifyUrl = isset ($options['notify_url']) ? $options['notify_url'] : config('notify_url');
        $this->alipayrsaPublicKey = isset ($options['ali_public_key_path']) ? $options['ali_public_key_path'] : config('ali_public_key');
//        $this->returnUrl = isset ($options ['returnUrl']) ? $options ['returnUrl'] : C('ALI_PAY')['returnUrl'];
    }

    /**
     * 支付宝app支付 需要签约 APP支付
     * @param string $data 业务参数 body subject out_trade_no total_amount
     * @param string $data['out_trade_no'] 订单号  必填
     * @param string $data['total_amount'] 订单金额  必填
     * @param string $data['subject'] 订单标题  必填
     * @param string $data['body'] 订单详情  可选
     * @return $response 返回app所需字符串
     */
    public function AliPayApp($data) {
        if (empty($this->appId))
            return false;
        $aliPayPath = './Plugins/AliPay/alipay-sdk/';
        require_once($aliPayPath . "aop/AopClient.php");
        require_once($aliPayPath . 'aop/request/AlipayTradeAppPayRequest.php');
        $aop = new \AopClient;
        $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
        $aop->appId = $this->appId;
        $aop->rsaPrivateKey = $this->rsaPrivateKey;
        $aop->format = "json";
        $aop->charset = "UTF-8";
        $aop->signType = $this->signType;
        $aop->alipayrsaPublicKey = $this->alipayrsaPublicKey;
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        $request = new \AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数
        $bizcontent = json_encode([
            'body' => $data['body'],
            'subject' => $data['subject'],
            'out_trade_no' => $data['out_trade_no'],//此订单号为商户唯一订单号
            'total_amount' => $data['total_amount'],//保留两位小数
            'timeout_express' => '30m',
            'passback_params' => urlencode($data['pass_back_params']), //区分安卓ios支付
            'product_code' => 'QUICK_MSECURITY_PAY'
        ]);
        $request->setNotifyUrl($this->notifyUrl);
        $request->setBizContent($bizcontent);
        //这里和普通的接口调用不同,使用的是sdkExecute
        $response = $aop->sdkExecute($request);
        //htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题
        //return htmlspecialchars($response);//就是orderString 可以直接给客户端请求,无需再做处理。
        //返回app所需字符串
        return $response;
    }

    /**
     * 支付宝web支付 需要签约 电脑网站支付
     * @param string $data 业务参数
     * @param string $data['out_trade_no'] 订单号  必填
     * @param string $data['total_amount'] 订单金额  必填
     * @param string $data['subject'] 订单标题  必填
     * @param string $data['body'] 订单详情  可选
     * @return $result 返回form表单,插入到当前网页即跳转到支付宝付款界面
     */
    public function AliPayWeb($data) {
        if (empty($this->appId))
            return false;
        $aliPayPath = './Plugins/AliPay/alipay-sdk/';
        require_once($aliPayPath . "aop/AopClient.php");
        require_once($aliPayPath . 'aop/request/AlipayTradePagePayRequest.php');
        $aop = new \AopClient();
        $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
        $aop->appId = $this->appId;
        $aop->rsaPrivateKey = $this->rsaPrivateKey;
        $aop->signType = $this->signType;
        $aop->alipayrsaPublicKey = $this->alipayrsaPublicKey;
        $aop->apiVersion = '1.0';
        $aop->postCharset = 'UTF-8';
        $aop->format = 'json';
        $request = new \AlipayTradePagePayRequest();
        $bizcontent = json_encode([
            'body' => $data['body'],
            'subject' => $data['subject'],
            'out_trade_no' => $data['out_trade_no'],//此订单号为商户唯一订单号
            'total_amount' => $data['total_amount'],//保留两位小数
            'product_code' => 'FAST_INSTANT_TRADE_PAY'
        ]);
        $request->setNotifyUrl($this->notifyUrl);
        $request->setReturnUrl($this->returnUrl);
        $request->setBizContent($bizcontent);
        $result = $aop->pageExecute($request);
        //返回form提交表单
        return $result;
    }

    /**
     * 支付宝MobileWeb支付 需要签约 手机网站支付
     * @param string $data 业务参数
     * @param string $data['out_trade_no'] 订单号  必填
     * @param string $data['total_amount'] 订单金额  必填
     * @param string $data['subject'] 订单标题  必填
     * @param string $data['body'] 订单详情  可选
     * @return $result 返回form表单,插入到当前网页即跳转到支付宝付款界面
     */
    public function AliPayMobileWeb($data) {
        if (empty($this->appId))
            return false;
        $aliPayPath = './Plugins/AliPay/alipay-sdk/';
        require_once($aliPayPath . "aop/AopClient.php");
        require_once($aliPayPath . 'aop/request/AlipayTradeWapPayRequest.php');
        $aop = new \AopClient();
        $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
        $aop->appId = $this->appId;
        $aop->rsaPrivateKey = $this->rsaPrivateKey;
        $aop->signType = $this->signType;
        $aop->alipayrsaPublicKey = $this->alipayrsaPublicKey;
        $aop->apiVersion = '1.0';
        $aop->postCharset = 'UTF-8';
        $aop->format = 'json';
        $request = new \AlipayTradeWapPayRequest ();
        $bizcontent = json_encode([
            'body' => $data['body'],
            'subject' => $data['subject'],
            'out_trade_no' => $data['out_trade_no'],//此订单号为商户唯一订单号
            'total_amount' => $data['total_amount'],//保留两位小数
            'timeout_express' => '90m',
            'product_code' => 'QUICK_WAP_WAY'
        ]);
        $request->setNotifyUrl($this->notifyUrl);
        $request->setReturnUrl($this->returnUrl);
        $request->setBizContent($bizcontent);
        $result = $aop->pageExecute($request);
        //返回form提交表单
        return $result;
    }

    /**
     * 支付宝支付回调签名验证
     * @param string $data 业务参数
     * @return bool
     */
    public function AliPayNotifyCheck() {
        $aliPayPath = './Plugins/AliPay/alipay-sdk/';
        require_once($aliPayPath . "aop/AopClient.php");
        $aop = new \AopClient;
        $aop->alipayrsaPublicKey = $this->alipayrsaPublicKey;
        //此处验签方式必须与下单时的签名方式一致
        $flag = $aop->rsaCheckV1($_POST, NULL, $this->signType);
        return $flag;
    }

    /**
     * 支付宝提现转账 需要签约 单笔转账到支付宝账户接口
     * @param string $data 业务参数
     * @param $data['out_biz_no'] 订单号  必填
     * @param $data['amount'] 提现金额 必填 金额不小于0.1元,单日转出累计额度为100万元,转账给个人支付宝账户,单笔最高5万元;转账给企业支付宝账户,单笔最高10万元。
     * @param $data['payee_account'] 收款支付宝账号  必填
     * @param $data['payee_real_name'] 收款支付宝账号真实姓名  最好填上 填上会验证账号是否正确
     * @param $data['payer_show_name'] 付款方姓名  可选
     * @param $data['remark'] 转账提现备注  可选
     * @return bool
     */
    public function AliPayWithdrawOld($data) {
        if (empty($this->appId))
            return false;
        if ($data['amount']<0.1)
            return false;
        $aliPayPath = './Plugins/AliPay/alipay-sdk/';
        require_once($aliPayPath . "aop/AopClient.php");
        require_once($aliPayPath . 'aop/request/AlipayFundTransToaccountTransferRequest.php');
        $aop = new \AopClient;
        $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
        $aop->appId = $this->appId;
        $aop->rsaPrivateKey = $this->rsaPrivateKey;
        $aop->format = "json";
        $aop->charset = "UTF-8";
        $aop->signType = $this->signType;
        $aop->alipayrsaPublicKey = $this->alipayrsaPublicKey;
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        $request = new \AlipayFundTransToaccountTransferRequest ();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数
        $bizcontent = json_encode([
            'out_biz_no' => $data['out_biz_no'],//此订单号为商户唯一订单号
            'payee_type' => 'ALIPAY_LOGONID',//默认登录账号,后期可拓展
            'payee_account' => $data['payee_account'],
            'amount' => $data['amount'],
            'payee_real_name' => $data['payee_real_name'],
            'payer_show_name' => $data['payer_show_name'],
            'remark' => $data['remark'],
        ]);
        $request->setBizContent($bizcontent);
        $result = $aop->execute($request);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if(!empty($resultCode)&&$resultCode == 10000){
            //echo "成功"; 提现成功
            return true;
        } else {
            //echo "失败";
            return false;
        }
    }

    /**
     * 支付宝提现转账 需要签约 单笔转账到支付宝账户接口(新版2022-11-21)
     * @return bool
     */
    public function AliPayWithdraw($data) {
        if (empty($this->appId))
            return false;
        if ($data['trans_amount'] < 0.1)
            return false;
        $aliPayPath = '../extend/AliPay/aop/';
        require_once $aliPayPath . 'AopClient.php';
        require_once $aliPayPath . 'AopCertClient.php';
        require_once $aliPayPath . 'AopCertification.php';
        require_once $aliPayPath . 'AlipayConfig.php';
        require_once $aliPayPath . 'request/AlipayFundTransUniTransferRequest.php';

        $privateKey = $this->rsaPrivateKey;//"<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->";
        $alipayConfig = new AlipayConfig();
        $alipayConfig->setPrivateKey($privateKey);
        $alipayConfig->setServerUrl("https://openapi.alipay.com/gateway.do");
        $alipayConfig->setAppId($this->appId); //"<-- 请填写您的AppId,例如:2019091767145019 -->"
        $alipayConfig->setCharset("UTF-8");
        $alipayConfig->setSignType("RSA2");
        $alipayConfig->setEncryptKey("");
        $alipayConfig->setFormat("json");
        $alipayConfig->setAppCertPath('../extend/AliPay/cert/appCertPublicKey_2021003139615320.crt');//"<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->"
        $alipayConfig->setAlipayPublicCertPath('../extend/AliPay/cert/alipayCertPublicKey_RSA2.crt');//"<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->"
        $alipayConfig->setRootCertPath('../extend/AliPay/cert/alipayRootCert.crt');//"<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt -->"
        $alipayClient = new AopCertClient($alipayConfig);
        $alipayClient->isCheckAlipayPublicCert = true;
        $request = new AlipayFundTransUniTransferRequest();
        $data = json_encode($data);
        $request->setBizContent($data);
        $responseResult = $alipayClient->execute($request);
        $responseApiName = str_replace(".","_",$request->getApiMethodName())."_response";
        $responsecode = $responseResult->$responseApiName->code;
        if(!empty($responsecode)&&$responsecode==10000){
//            echo("调用成功");
            return true;
        } else{
//            echo("调用失败");
            return false;
        }
    }

    /**
     * 支付宝身份认证初始化服务
     */
    public function userCertifyInitialize($data) {
        $aliPayPath = './Plugins/AliPay/alipay-sdk/';
        require_once($aliPayPath . "aop/AopClient.php");
        require_once($aliPayPath . 'aop/request/AlipayUserCertifyOpenInitializeRequest.php');

        $aop = new \AopClient;
        $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
        $aop->appId = $this->appId;
        $aop->rsaPrivateKey = $this->rsaPrivateKey;
        $aop->format = "json";
        $aop->postCharset = "UTF-8";
        $aop->signType = $this->signType;
        $aop->alipayrsaPublicKey = $this->alipayrsaPublicKey;

        $request = new \AlipayUserCertifyOpenInitializeRequest();
        $request->setBizContent(json_encode($data));
        $result = $aop->execute ($request);

        $result = json_decode(json_encode($result), true);
        return $result['alipay_user_certify_open_initialize_response'];
    }

    /**
     * 支付宝身份认证开始认证
     */
    public function userCertify($data) {
        $aliPayPath = './Plugins/AliPay/alipay-sdk/';
        require_once($aliPayPath . "aop/AopClient.php");
        require_once($aliPayPath . 'aop/request/AlipayUserCertifyOpenCertifyRequest.php');

        $aop = new \AopClient;
        $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
        $aop->appId = $this->appId;
        $aop->rsaPrivateKey = $this->rsaPrivateKey;
        $aop->format = "json";
        $aop->postCharset = "UTF-8";
        $aop->signType = $this->signType;
        $aop->alipayrsaPublicKey = $this->alipayrsaPublicKey;

        $request = new \AlipayUserCertifyOpenCertifyRequest();
        $request->setBizContent(json_encode($data));
        $result = $aop->pageExecute ($request, 'GET');

        return $result;
//        $result = json_decode($result, true); p($result);die;
//        return $result['alipay_user_certify_open_certify_response'];
    }

    /**
     * 支付宝身份认证状态查询
     */
    public function userCertifyState($data) {
        $aliPayPath = './Plugins/AliPay/alipay-sdk/';
        require_once($aliPayPath . "aop/AopClient.php");
        require_once($aliPayPath . 'aop/request/AlipayUserCertifyOpenQueryRequest.php');

        $aop = new \AopClient;
        $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
        $aop->appId = $this->appId;
        $aop->rsaPrivateKey = $this->rsaPrivateKey;
        $aop->format = "json";
        $aop->postCharset = "UTF-8";
        $aop->signType = $this->signType;
        $aop->alipayrsaPublicKey = $this->alipayrsaPublicKey;

        $request = new \AlipayUserCertifyOpenQueryRequest();
        $request->setBizContent(json_encode($data));
        $result = $aop->execute ($request);

        $result = json_decode(json_encode($result), true);
        return $result['alipay_user_certify_open_query_response'];
    }
}