<?php

namespace SRVX\Service\Pay;

use SRVX\Service\BaseService;
use AlipayFundTransUniTransferRequest;
use AopClient;
use AlipayFundTransToaccountTransferRequest;


class AlipayCashBookService extends BaseService
{

    static private $config = [];
    static private $aopClient;

    public $gatewayUrl = 'https://openapi.alipay.com/gateway.do';
    public $apiVersion = '1.0';
    public $signType = 'RSA2';
    public $postCharset = 'UTF-8';
    public $format = 'json';

    public function __construct()
    {
        $this->getConfig();
        $this->aopClient();
    }


    private function aopClient()
    {
        if (!self::$aopClient instanceof AopClient) {
            self::$aopClient        = new AopClient();
            self::$aopClient->appId = self::$config['cash_book_ali_app_id'];
            //支付宝私钥值
            self::$aopClient->rsaPrivateKey = self::$config['cash_book_ali_private_key'];
            //支付宝公钥值
            self::$aopClient->alipayrsaPublicKey = self::$config['cash_book_ali_public_key'];
        }
        self::$aopClient->gatewayUrl  = $this->gatewayUrl;
        self::$aopClient->apiVersion  = $this->apiVersion;
        self::$aopClient->signType    = $this->signType;
        self::$aopClient->postCharset = $this->postCharset;
        self::$aopClient->format      = $this->format;
    }


    private function getConfig()
    {
        if (empty(self::$config)) {
            $config       = $this->s->GeneralSet()->getSet(['cash_book_ali_app_id', 'cash_book_ali_private_key', 'cash_book_ali_public_key'], false);
            self::$config = $config;
        }
    }

    /**
     * alipay.user.agreement.page.sign(支付宝个人协议页面签约接口)
     * @param $external_agreement_no string 商户签约号，协议中标示用户的唯一签约号（自定义，确保在商户系统中唯一）。格式规则：支持大写小写字母和数字，最长32位。
     * @param string $external_logon_id string 用户在商户网站的登录账号，用于在签约页面展示，如果为空，则不展示。
     * @return array
     */
    public function alipayUserAgreementPageSignRequest($external_agreement_no, $external_logon_id = "")
    {
        try {
            $personal_product_code = "FUND_SAFT_SIGN_WITHHOLDING_P";
            $sign_scene            = "INDUSTRY|SATF_ACC";
            $channel               = "QRCODE";
            $grant_type            = "authorization_code";
            $third_party_type      = "PARTNER";
            $request               = new \AlipayUserAgreementPageSignRequest();
            $params                = [
                "personal_product_code" => $personal_product_code,
                "sign_scene"            => $sign_scene,
                "channel"               => $channel,
                "grant_type"            => $grant_type,
                "third_party_type"      => $third_party_type,
                "external_agreement_no" => $external_agreement_no,
            ];

            if (empty($external_logon_id)) {
                $params["external_logon_id"] = $external_logon_id;
            }
            $paramsJson = json_encode($params);
            $request->setBizContent($paramsJson);
            $response = self::$aopClient->pageExecute($request);
            return $this->returnRes(true, "success", $response);
        } catch (\Exception $exception) {
            return $this->returnRes(false, $exception->getMessage());
        }
    }

    /**
     * alipay.user.agreement.query(支付宝个人代扣协议查询接口)
     * @param $external_agreement_no string 商户签约号，协议中标示用户的唯一签约号（自定义，确保在商户系统中唯一）。格式规则：支持大写小写字母和数字，最长32位。
     * @return array
     */
    public function alipayUserAgreementQueryRequest($external_agreement_no)
    {
        try {
            $personal_product_code = "FUND_SAFT_SIGN_WITHHOLDING_P";
            $sign_scene            = "INDUSTRY|SATF_ACC";
            $request               = new \AlipayUserAgreementQueryRequest();
            $params                = [
                "personal_product_code" => $personal_product_code,
                "sign_scene"            => $sign_scene,
                "external_agreement_no" => $external_agreement_no,
            ];
            $paramsJson            = json_encode($params);
            $request->setBizContent($paramsJson);
            $response     = self::$aopClient->execute($request);
            $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
            $responseData = json_decode(json_encode($response->$responseNode), true);
            if ($responseData['code'] == 10000) {
                return $this->returnRes(true, $responseData['msg'], $responseData);
            } else {
                return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
            }
        } catch (\Exception $exception) {
            return $this->returnRes(false, $exception->getMessage());
        }
    }

    /**
     * alipay.user.agreement.unsign(支付宝个人代扣协议解约接口)
     * @param $external_agreement_no string 商户签约号，协议中标示用户的唯一签约号（自定义，确保在商户系统中唯一）。格式规则：支持大写小写字母和数字，最长32位。
     * @return array
     */
    public function alipayUserAgreementUnsignRequest($external_agreement_no)
    {
        try {
            $personal_product_code = "FUND_SAFT_SIGN_WITHHOLDING_P";
            $sign_scene            = "INDUSTRY|SATF_ACC";
            $request               = new \AlipayUserAgreementUnsignRequest();
            $params                = [
                "personal_product_code" => $personal_product_code,
                "sign_scene"            => $sign_scene,
                "external_agreement_no" => $external_agreement_no,
            ];
            $paramsJson            = json_encode($params);
            $request->setBizContent($paramsJson);
            $response     = self::$aopClient->execute($request);
            $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
            $responseData = json_decode(json_encode($response->$responseNode), true);
            if ($responseData['code'] == 10000) {
                return $this->returnRes(true, $responseData['msg'], $responseData);
            } else {
                return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
            }
        } catch (\Exception $exception) {
            return $this->returnRes(false, $exception->getMessage());
        }
    }

    /**
     * alipay.fund.accountbook.create(资金记账本开通)
     * @param $merchant_user_id string 外部商户系统会员的唯一标识；记账本创建时候的幂等字段。
     * @param $agreement_no string 支付宝协议号。
     */
    public function alipayFundAccountbookCreateRequest($merchant_user_id, $agreement_no)
    {
        try {
            $merchant_user_type = "BUSINESS_ORGANIZATION";  //外部商户用户类型，固定值。
            $scene_code         = "SATF_FUND_BOOK"; // 资金记账本的业务场景，固定值。
            $ext_info           = json_encode([
                "agreement_no" => $agreement_no
            ]);
            $request            = new \AlipayFundAccountbookCreateRequest();
            $params             = [
                "merchant_user_id"   => $merchant_user_id,
                "merchant_user_type" => $merchant_user_type,
                "scene_code"         => $scene_code,
                "ext_info"           => $ext_info,
            ];
            $paramsJson         = json_encode($params);
            $request->setBizContent($paramsJson);
            $response     = self::$aopClient->execute($request);
            $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
            $responseData = json_decode(json_encode($response->$responseNode), true);
            if ($responseData['code'] == 10000) {
                return $this->returnRes(true, $responseData['msg'], $responseData);
            } else {
                return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
            }
        } catch (\Exception $exception) {
            return $this->returnRes(false, $exception->getMessage());
        }
    }

    /**
     * alipay.fund.accountbook.query(资金记账本的信息查询)
     * @param $merchant_user_id string 外部商户系统会员的唯一标识；记账本创建时候的幂等字段。
     * @param $agreement_no string 支付宝协议号。
     */
    public function alipayFundAccountbookQueryRequest($account_book_id, $agreement_no)
    {
        try {
            $scene_code = "SATF_FUND_BOOK"; // 资金记账本的业务场景，固定值。
            $ext_info   = json_encode([
                "agreement_no" => $agreement_no
            ]);
            $request    = new \AlipayFundAccountbookQueryRequest();
            $params     = [
                "account_book_id" => $account_book_id,
                "scene_code"      => $scene_code,
                "ext_info"        => $ext_info,
            ];
            $paramsJson = json_encode($params);
            $request->setBizContent($paramsJson);
            $response     = self::$aopClient->execute($request);
            $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
            $responseData = json_decode(json_encode($response->$responseNode), true);
            if ($responseData['code'] == 10000) {
                return $this->returnRes(true, $responseData['msg'], $responseData);
            } else {
                return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
            }
        } catch (\Exception $exception) {
            return $this->returnRes(false, $exception->getMessage());
        }
    }

    /**
     * alipay.fund.trans.page.pay(资金转账页面支付接口)
     * @param $out_biz_no string 商户端的唯一订单号，对于同一笔转账请求，商户需保证该订单号唯一。
     * @param $trans_amount string 拨入总金额，单位为元，精确到小数点后两位，取值范围[0.01,9999999999999.99]
     * @param $identity string 记账本 id
     * @param $agreement_no string 支付宝协议号
     * @return array
     */
    public function alipayFundTransPagePayRequest($out_biz_no, $trans_amount, $identity, $agreement_no)
    {
        try {
            $product_code = "FUND_ACCOUNT_BOOK"; // 产品码, 固定值
            $biz_scene    = "SATF_DEPOSIT"; // 业务场景码、固定值
            $order_title  = "代发专项充值"; // 拨入订单的标题
            $time_expire  = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s") . " +10 minutes")); // 充值订单过期时间，默认会失败 TODO::给10分钟
            $payee_info   = [
                "identity_type" => "ACCOUNT_BOOK_ID",
                "identity"      => $identity,
                "ext_info"      => json_encode([
                    "agreement_no" => $agreement_no
                ])
            ];
            $request      = new \AlipayFundTransPagePayRequest();
            $params       = [
                "out_biz_no"   => $out_biz_no,
                "trans_amount" => $trans_amount,
                "product_code" => $product_code,
                "biz_scene"    => $biz_scene,
                "order_title"  => $order_title,
                "time_expire"  => $time_expire,
                "payee_info"   => $payee_info
            ];
            $paramsJson   = json_encode($params);
            $request->setBizContent($paramsJson);
            $response = self::$aopClient->pageExecute($request);
            return $this->returnRes(true, "success", $response);
        } catch (\Exception $exception) {
            return $this->returnRes(false, $exception->getMessage());
        }
    }

}