<?php

namespace SRVX\Service\Pay;

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


class AlipayService 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($config = [])
    {
        empty($config) && $this->getConfig();
        $this->aopClient($config);
    }


    private function aopClient($config)
    {
        if (!self::$aopClient instanceof AopClient) {
            self::$aopClient = new AopClient();
            if (empty($config)) :
                self::$aopClient->appId = self::$config['pay_ali_app_id'];
                //支付宝私钥值
                self::$aopClient->rsaPrivateKey = self::$config['pay_ali_private_key'];
                //支付宝公钥值
                self::$aopClient->alipayrsaPublicKey = self::$config['pay_ali_public_key'];
            else :
                self::$aopClient->appId = $config['pay_ali_app_id'];
                //支付宝私钥值
                self::$aopClient->rsaPrivateKey = $config['pay_ali_private_key'];
                //支付宝公钥值
                self::$aopClient->alipayrsaPublicKey = $config['pay_ali_public_key'];
            endif;
        }
        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(['pay_ali_app_id', 'pay_ali_private_key', 'pay_ali_public_key'], false);
            self::$config = $config;
        }
    }

    /**
     * 换取应用授权令牌
     * @param string $grant_type 授权方式。支持：authorization_code：使用应用授权码换取应用授权令牌app_auth_token。refresh_token：使用app_refresh_token刷新获取新授权令牌。
     * @param string $app_auth_code 应用授权码。 grant_type 为 authorization_code 时，本参数必填；grant_type 为 refresh_token 时不填。
     * @param string $refresh_token 刷新令牌，上次换取访问令牌时得到。本参数在 grant_type 为 authorization_code 时不填；为 refresh_token 时必填，且该值来源于此接口的返回值 app_refresh_token（即至少需要通过 grant_type=authorization_code 调用此接口一次才能获取）。
     */
    public function alipayOpenAuthTokenAppRequest($app_auth_code = "", $refresh_token = "", $grant_type = "authorization_code")
    {
        $request = new \AlipayOpenAuthTokenAppRequest();
        $params = ["grant_type" => $grant_type];
        if ($grant_type == "authorization_code") {
            $params["code"] = $app_auth_code;
        } else {
            $params["refresh_token"] = $refresh_token;
        }
        $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);
        $this->logger(["params" => $params, "response" => $responseData], 'alipay_open_auth_token_app_request', true);
        if ($responseData['code'] == 10000) {
            return $this->returnRes(true, $responseData['msg'], $responseData);
        } else {
            return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
        }
    }

    /**
     * alipay.user.info.share(支付宝会员授权信息查询接口)
     * @param string $auth_token 用户授权令牌，同 access_token（用户访问令牌）。针对用户授权接口，获取用户相关数据时，用于标识用户授权关系。需使用 auth_code（用户授权码）换取此令牌
     * @param string $app_auth_token 应用授权（详见应用授权概述https://opendocs.alipay.com/isv/10467/xldcyq）
     */
    public function alipayUserInfoShare($auth_token, $app_auth_token = "")
    {
        $request = new \AlipayUserInfoShareRequest();
        $params = ["auth_token" => $auth_token];
        !empty($app_auth_token) && $params["app_auth_token"] = $app_auth_token;
        $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);
        $this->logger(["params" => $params, "response" => $responseData], 'alipay.user.info.share', true);
        if ($responseData['code'] == 10000) {
            return $this->returnRes(true, $responseData['msg'], $responseData);
        } else {
            return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
        }
    }

    /**
     * alipay.trade.create(统一收单交易创建接口)
     * @param string $auth_token 用户授权令牌，同 access_token（用户访问令牌）。针对用户授权接口，获取用户相关数据时，用于标识用户授权关系。需使用 auth_code（用户授权码）换取此令牌
     * @param string $app_auth_token 应用授权（详见应用授权概述https://opendocs.alipay.com/isv/10467/xldcyq）
     */
    public function alipayTradeCreateRequest($op_app_id, $subject, $out_trade_no, $total_amount, $buyer_id, $app_auth_token)
    {
        $params["subject"] = $subject;
        $params["out_trade_no"] = $out_trade_no;
        $params["total_amount"] = $total_amount;
        $params["buyer_id"] = $buyer_id;
        $params["op_app_id"] = $op_app_id;
        $params["product_code"] = "JSAPI_PAY";
        $params["timeout_express"] = "10m";

        $request = new \AlipayTradeCreateRequest();
        $paramsJson = json_encode($params);
        $request->setBizContent($paramsJson);
        $response = self::$aopClient->execute($request, null, $app_auth_token);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $responseData = json_decode(json_encode($response->$responseNode), true);
        $this->logger(["params" => $params, "response" => $responseData], 'alipay.trade.create', true);
        if ($responseData['code'] == 10000) {
            return $this->returnRes(true, $responseData['msg'], $responseData);
        } else {
            return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
        }
    }

    /**
     * alipay.trade.query(统一收单交易查询)
     * @param string $auth_token 用户授权令牌，同 access_token（用户访问令牌）。针对用户授权接口，获取用户相关数据时，用于标识用户授权关系。需使用 auth_code（用户授权码）换取此令牌
     * @param string $app_auth_token 应用授权（详见应用授权概述https://opendocs.alipay.com/isv/10467/xldcyq）
     */
    public function tradeCommonQueryPay($out_trade_no = "", $trade_no = "", $app_auth_token)
    {
        $params["out_trade_no"] = $out_trade_no;
        $params["trade_no"] = $trade_no;

        $request = new \AlipayTradeQueryRequest();
        $paramsJson = json_encode($params);
        $request->setBizContent($paramsJson);
        $response = self::$aopClient->execute($request, null, $app_auth_token);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $responseData = json_decode(json_encode($response->$responseNode), true);
        $this->logger(["params" => $params, "response" => $responseData], 'alipay.trade.query', true);
        if ($responseData['code'] == 10000) {
            return $this->returnRes(true, $responseData['msg'], $responseData);
        } else {
            return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
        }
    }

    /**
     * alipay.trade.refund(统一收单交易退款接口)
     * @param $out_trade_no string 商户订单号
     * @param $refund_amount string 退款金额
     * @param $refund_reason string 退款原因说明。商家自定义，将在会在商户和用户的pc退款账单详情中展示
     * @param $out_request_no string 退款请求号。
     * @param string $app_auth_token 应用授权（详见应用授权概述https://opendocs.alipay.com/isv/10467/xldcyq）
     * @return array
     */
    public function alipayTradeRefundRequest($out_trade_no, $refund_amount, $refund_reason, $out_request_no, $app_auth_token)
    {
        $params["out_trade_no"] = $out_trade_no;
        $params["refund_amount"] = $refund_amount;
        $params["refund_reason"] = $refund_reason;
        $params["out_request_no"] = $out_request_no;

        $request = new \AlipayTradeRefundRequest();
        $paramsJson = json_encode($params);
        $request->setBizContent($paramsJson);
        $response = self::$aopClient->execute($request, null, $app_auth_token);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $responseData = json_decode(json_encode($response->$responseNode), true);
        $this->logger(["params" => $params, "response" => $responseData], 'alipay.trade.refund', true);
        if ($responseData['code'] == 10000) {
            return $this->returnRes(true, $responseData['msg'], $responseData);
        } else {
            return $this->returnRes(false, ($responseData['sub_msg'] ?? $responseData['msg']), $responseData);
        }
    }

}