<?php
/* *
 * 彩虹易支付SDK服务类
 * 说明：
 * 包含发起支付、查询订单、回调验证等功能
 */

 namespace app\common\service\pay;

use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Config;
use app\common\enum\AfterSaleLogEnum;
use app\common\enum\OrderEnum;
use app\common\enum\PayEnum;
use app\common\enum\UserTerminalEnum;
use app\common\logic\PayNotifyLogic;
use app\common\model\Order;
use app\common\model\PayConfig;
use app\common\model\RechargeOrder;
use app\common\service\after_sale\AfterSaleService;
use think\facade\Log;
use app\common\service\ConfigService;

class EPayService extends BasePayService
{

	private $pid;
	private $key;
	private $submit_url;
	private $mapi_url;
	private $api_url;
	private $sign_type = 'MD5';

	function __construct(){

        $api_url = ConfigService::get('epay', 'apiurl', '');
		$this->pid = ConfigService::get('epay', 'pid', '');
		$this->key = ConfigService::get('epay', 'key', '');
		$this->submit_url = $api_url.'submit.php';
		$this->mapi_url = $api_url.'mapi.php';
		$this->api_url =$api_url.'api.php';
	}

	// 发起支付（页面跳转）
	public function pagePay($param_tmp, $button='正在跳转'){
		$param_tmp['pid']=$this->pid;
		$param = $this->buildRequestParam($param_tmp);

		$html = '<form id="dopay" action="'.$this->submit_url.'" method="post">';
		foreach ($param as $k=>$v) {
			$html.= '<input type="hidden" name="'.$k.'" value="'.$v.'"/>';
		}
		$html .= '<input type="submit" value="'.$button.'"></form><script>document.getElementById("dopay").submit();</script>';

		return $html;
	}

	// 发起支付（获取链接）
	public function getPayLink($param_tmp){
		$param_tmp['pid']=$this->pid;
		$param = $this->buildRequestParam($param_tmp);
		$url = $this->submit_url.'?'.http_build_query($param);
		return $url;
	}

	// 发起支付（API接口）
	public function apiPay($param_tmp){
		$param_tmp['pid']=$this->pid;
		$param = $this->buildRequestParam($param_tmp);
		$response = $this->getHttpResponse($this->mapi_url, http_build_query($param));
		$arr = json_decode($response, true);
		return $arr;
	}

    	   /**
     * Notes: 支付回调
     * @param $data
     * @return bool(2021/3/22 17:22)
     */
    public function notify($data)
    {
        try {
            // dd($data);
            $from=$data['from'];
            unset($data['from']);
            $verify = $this->verifyNotify($data);
            // $data['from']=$from;

            if (false === $verify) {
                throw new \Exception('异步通知验签失败');
            }
            if (!in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
                return true;
            }
            $extra['transaction_id'] = $data['trade_no'];
            //验证订单是否已支付
            switch ($from) {
                case 'order':
                    $order = Order::where(['sn' => $data['out_trade_no']])->findOrEmpty();
                    if (!$order || $order['pay_status'] >= PayEnum::ISPAID) {
                        return true;
                    }

                    //特殊情况：用户在前端支付成功的情况下，调用回调接口之前，订单被关闭
                    if ($order['order_status'] == OrderEnum::STATUS_CLOSE) {
                        //更新订单支付状态为已支付
                        Order::update(['pay_status' => PayEnum::ISPAID],['id'=>$order['id']]);

                        //发起售后
                        AfterSaleService::orderRefund([
                            'order_id' => $order['id'],
                            'scene' =>  AfterSaleLogEnum::ORDER_CLOSE
                        ]);

                        return true;
                    }

                    PayNotifyLogic::handle('order', $data['out_trade_no'], $extra);
                    break;
                case 'recharge':
                    $order = RechargeOrder::where(['sn' => $data['out_trade_no']])->findOrEmpty();
                    if($order->isEmpty() || $order->pay_status == PayEnum::ISPAID) {
                        return true;
                    }
                    PayNotifyLogic::handle('recharge', $data['out_trade_no'], $extra);
                    break;
            }

            return true;
        } catch (\Exception $e) {
            // $record = [
            //     __CLASS__,
            //     __FUNCTION__,
            //     $e->getFile(),
            //     $e->getLine(),
            //     $e->getMessage()
            // ];
            // Log::write(implode('-', $record));
            // $this->setError($e->getMessage());
            // return false;
        }
    }


	// 异步回调验证
	public function verifyNotify($data){
		if(empty($data)) return false;

		$sign = $this->getSign($data);

		if($sign === $data['sign']){
			$signResult = true;
		}else{
			$signResult = false;
		}

		return $signResult;
	}

	// 同步回调验证
	public function verifyReturn(){
		if(empty($_GET)) return false;

		$sign = $this->getSign($_GET);

		if($sign === $_GET['sign']){
			$signResult = true;
		}else{
			$signResult = false;
		}

		return $signResult;
	}

	// 查询订单支付状态
	public function orderStatus($trade_no){
		$result = $this->queryOrder($trade_no);
		if($result['status']==1){
			return true;
		}else{
			return false;
		}
	}

	// 查询订单
	public function queryOrder($trade_no){
		$url = $this->api_url.'?act=order&pid=' . $this->pid . '&key=' . $this->key . '&trade_no=' . $trade_no;
		$response = $this->getHttpResponse($url);
		$arr = json_decode($response, true);
		return $arr;
	}

	// 订单退款
	public function refund($trade_no, $money){
		$url = $this->api_url.'?act=refund';
		$post = 'pid=' . $this->pid . '&key=' . $this->key . '&trade_no=' . $trade_no . '&money=' . $money;
		$response = $this->getHttpResponse($url, $post);
		$arr = json_decode($response, true);
		return $arr;
	}

	private function buildRequestParam($param){
		$mysign = $this->getSign($param);
		$param['sign'] = $mysign;
		$param['sign_type'] = $this->sign_type;
		return $param;
	}

	// 计算签名
	private function getSign($param){
		ksort($param);
		reset($param);
		$signstr = '';
	
		foreach($param as $k => $v){
			if($k != "sign" && $k != "sign_type" && $v!=''){
				$signstr .= $k.'='.$v.'&';
			}
		}
		$signstr = substr($signstr,0,-1);
		$signstr .= $this->key;
		$sign = md5($signstr);
		return $sign;
	}


	// 请求外部资源
	private function getHttpResponse($url, $post = false, $timeout = 10){
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
		$httpheader[] = "Accept: */*";
		$httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
		$httpheader[] = "Connection: close";
		curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		if($post){
			curl_setopt($ch, CURLOPT_POST, true);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
		}
		$response = curl_exec($ch);
		curl_close($ch);
		return $response;
	}


}
