<?php


namespace App\Services\pingxx;

use Api\PhpUtils\Log\FileLog;
use Pingpp\Order;
use Pingpp\Pingpp;
use Pingpp\OrderRefund;
use Api\PhpUtils\Common\IP;
use Api\PhpUtils\Mon\MonUtil;


class PingxxService
{
    private static $instance = null;

    private function __construct()
    {
        //$appId = \Yaf\Application::app()->getConfig()->get('pingxx.appid');
        Pingpp::setApiKey('sk_live_9q9iLCS4mvv1a9eTq190O8K4'); // 正式 API Key
        Pingpp::setPrivateKeyPath(ROOT_PATH . '/conf/your_rsa_private_key.pem'); // 设置私钥
        //Pingpp::setAppId($appId); // 设置 App ID
    }

    private function __clone() {}

    public static function getInstance($appId = '') {
        if(empty(self::$instance)) {
            self::$instance = new self;
        }

        if(empty($appId)) {
            $appId = \Yaf\Application::app()->getConfig()->get('pingxx.appid');
        }

        Pingpp::setAppId($appId); // 设置 App ID$app_id
        return self::$instance;
    }

    public function getAppId() {
        return Pingpp::getAppId();
    }

    /**
     * @param $order_item_id
     * @param $user_id
     * @throws RefundException
     * 发起退款请求
     */
    public function sendRefund($refundData) {

        try {
            $royalty_users = [];
            $start = microtime(true);
            $ret = OrderRefund::create(
                $refundData['id'],
                [
                    'charge' => $refundData['charge'],  //在该订单中，需要退款的 charge 对象 ID，默认全部退款。
                    'charge_amount' => $refundData['charge_amount'],    //charge 退款金额，默认为全额退款。必须和 charge 参数同时使用。单位：分。
                    'description' => '用户申请退款',    //退款附加说明。
                    'metadata' => $refundData['metadata'],
                    'refund_mode' => 'to_source',              //退款模式。原路退回：to_source，退至余额：to_balance。默认为原路返回。
                ]
            );
            //Mon 日志监控增加
            $end = microtime(true);      //计算结束时间
            FileLog::info('pingxx-sendRefund:' . '退款订单返回', json_encode(['req'=>$refundData, 'res'=>$ret], JSON_UNESCAPED_UNICODE));

            $total_time = round(($end - $start),4) * 1000; //计算耗时

            $url = 'pingxx/v1/refund/create';
            MonUtil::proxyMon($url, '200', 'bp-pay', $total_time);

            $response = json_decode($ret, true);

        } catch (\Pingpp\Error\Base $e) {

            // 捕获报错信息
            if ($e->getHttpStatus() != null) {
                $response = json_decode($e->getHttpBody(), true);

            } else {
                $response = [
                    'error'=>['message'=>$e->getMessage()],
                    'type'=>'http error',
                ];
            }
            FileLog::error('pingxx-sendRefund:' . '退款订单返回', json_encode(['req'=>$refundData, 'res'=>$response], JSON_UNESCAPED_UNICODE), $e);
        }

        return $response;

    }

    /**
     * @param $orderId ping++ 支付订单ID
     * @param $refundId ping++ 退款ID
     * @return mixed
     * 退款信息查询
     */
    public function getRefund($orderId, $refundId) {
        try {
            $start = microtime(true);
            $ret = OrderRefund::retrieve($orderId, $refundId);

            $end = microtime(true);      //计算结束时间
            FileLog::info('pingxx-getRefund:' . '退款查询返回', json_encode(['req'=>[$orderId, $refundId], 'res'=>$ret], JSON_UNESCAPED_UNICODE));

            $total_time = round(($end - $start),4) * 1000; //计算耗时
            $url = 'pingxx/v1/refund/get';
            MonUtil::proxyMon($url, '200', 'bp-pay', $total_time);

            $respose = json_decode($ret, true);

        } catch (\Pingpp\Error\Base $e) {
            // 捕获报错信息
            if ($e->getHttpStatus() != null) {
                $respose = json_decode($e->getHttpBody(), true);

            } else {
                $respose = [
                    'error'=>['message'=>$e->getMessage()],
                    'type'=>'http error',
                ];
            }
            FileLog::error('pingxx-getRefund:' . '退款查询返回', json_encode(['req'=>[$orderId, $refundId], 'res'=>$respose], JSON_UNESCAPED_UNICODE), $e);
        }
        return $respose;
    }

    /**
     * @param $order
     * @return mixed
     * 创建订单
     */
    public function createOrder($order, $metadata) {
        try {

            $royalty_users = [];
            $start = microtime(true);
            $ret = Order::create(
                [
                    "amount" => $order['pay_amount'],
                    "app" => Pingpp::getAppId(),
                    "merchant_order_no" => $order['pay_order_id'],
                    "subject" => "用户购买",
                    "currency" => "cny",
                    "body" => "购买商品",
                    "uid" => $order['user_id'],
                    "client_ip" => IP::ip(),
                    "time_expire" => strtotime($order['expire_time']), //订单过期时间 expire_time
                    'receipt_app' => Pingpp::getAppId(),    // 收款方应用
                    'service_app' => Pingpp::getAppId(),    // 服务方应用
                    'metadata' => $metadata,    // 商户定制信息
                ]
            );

            $end = microtime(true);      //计算结束时间
            FileLog::info('pingxx-createOrder:' . '创建订单返回', json_encode(['req'=>[$order, $metadata], 'res'=>$ret], JSON_UNESCAPED_UNICODE));

            $total_time = round(($end - $start),4) * 1000; //计算耗时
            $url = 'pingxx/v1/order/create';
            MonUtil::proxyMon($url, '200', 'bp-pay', $total_time);

            $respose = json_decode($ret, true);

        } catch (\Pingpp\Error\Base $e) {
            // 捕获报错信息
            if ($e->getHttpStatus() != null) {
                $respose = json_decode($e->getHttpBody(), true);

            } else {
                $respose = [
                    'error'=>['message'=>$e->getMessage()],
                    'type'=>'http error',
                ];
            }
            FileLog::error('pingxx-createOrder:' . '创建订单返回', json_encode(['req'=>[$order, $metadata], 'res'=>$respose], JSON_UNESCAPED_UNICODE), $e);
            /**
            {
            "error": {
            "type": "invalid_request_error",
            "message": "缺少请求参数: merchant_order_no",
            "param": "merchant_order_no",
            "code": "request_param_error"
            }
            }
             */
        }
        return $respose;
    }

    public function pay($orderId, $pay) {

        try {
            $start = microtime(true);
            $ret = Order::pay($orderId, $pay);

            $end = microtime(true);      //计算结束时间
            FileLog::info('pingxx-pay:' . '订单pay返回', json_encode(['req'=>[$orderId, $pay], 'res'=>$ret], JSON_UNESCAPED_UNICODE));

            $total_time = round(($end - $start),4) * 1000; //计算耗时
            $url = 'pingxx/v1/order/pay';
            MonUtil::proxyMon($url, '200', 'bp-pay', $total_time);

            $respose = json_decode($ret, true);

        } catch (\Pingpp\Error\Base $e) {
            // 捕获报错信息
            if ($e->getHttpStatus() != null) {
                $respose = json_decode($e->getHttpBody(), true);

            } else {
                $respose = [
                    'error'=>['message'=>$e->getMessage()],
                    'type'=>'http error',
                ];
            }
            FileLog::error('pingxx-pay:' . '订单pay返回', json_encode(['req'=>[$orderId, $pay], 'res'=>$respose], JSON_UNESCAPED_UNICODE), $e);
        }

        return $respose;


    }

    /**
     * @param $orderId
     * 订单查询
     */
    public function getOrder($orderId) {

        try {
            $start = microtime(true);
            $ret = Order::retrieve($orderId);

            $end = microtime(true);      //计算结束时间
            FileLog::info('pingxx-pay:' . '查询订单返回', json_encode(['req'=>[$orderId], 'res'=>$ret], JSON_UNESCAPED_UNICODE));

            $total_time = round(($end - $start),4) * 1000; //计算耗时
            $url = 'pingxx/v1/order/get';
            MonUtil::proxyMon($url, '200', 'bp-pay', $total_time);

            $respose = json_decode($ret, true);

        } catch (\Pingpp\Error\Base $e) {
            // 捕获报错信息
            if ($e->getHttpStatus() != null) {
                $respose = json_decode($e->getHttpBody(), true);

            } else {
                $respose = [
                    'error'=>['message'=>$e->getMessage()],
                    'type'=>'http error',
                ];
            }
            FileLog::error('pingxx-pay:' . '查询订单返回', json_encode(['req'=>[$orderId], 'res'=>$respose], JSON_UNESCAPED_UNICODE), $e);
        }

        return $respose;
    }
}