<?php

namespace App\Libs\Pay\Merchants;

use Exception;
use GuzzleHttp\Client;

/**
 * 汇聚支付
 */
class JoinPay implements PayMerchantInterface
{
    private $make_order_url = 'https://www.joinpay.com/trade/uniPayApi.action';
    private $query_order_url = 'https://www.joinpay.com/trade/queryOrder.action';
    private $key = "0c855107fa394d62bd4b9803795f16ae";
    private $merchantNo = "888108800000947";
    private $version = "1.0";
    private $trade_type = "WEIXIN_GZH";
    private $return_url;
    private $notify_url;
    private $appId;

    public function __construct(array $config)
    {
        $this->appId = $config['appId'];
        $this->return_url = $config['return_url'];
        $this->notify_url = $config['notify_url'];
    }

    public function send(array $data)
    {
        $options = [
            'p0_Version' => $this->version,
            'p1_MerchantNo' => $this->merchantNo,
            'p2_OrderNo' => $data['trade_no'],
            'p3_Amount' => $data['price'],
            'p4_Cur' => '1',
            'p5_ProductName' => $data['body'],
            'p7_Mp' => $data['remark'],
            'p8_ReturnUrl' => $this->return_url,
            'p9_NotifyUrl' => $this->notify_url,
            'q1_FrpCode' => $this->trade_type,
        ];
        if ($this->trade_type == "WEIXIN_GZH" || $this->trade_type == "WEIXIN_XCX") {
            $options['q5_OpenId'] = $data['openId'];
        }
        $result = $this->request($this->make_order_url, $options);
        if ($result->ra_Code == 100) {
            return $result->rc_Result;
        } else {
            return false;
        }
    }

    public function query(string $trade_no)
    {
        $options = [
            'p1_MerchantNo' => $this->merchantNo,
            'p2_OrderNo' => $trade_no,
        ];
        $result = $this->request($this->query_order_url, $options);
        if ($result->ra_Code == 100 && $result->ra_Status == 100) {
            return true;
        } else {
            return false;
        }
    }

    public function notify(array $data)
    {
        if (isset($data['r6_Status']) && $data['r6_Status'] == 100) {
            if (isset($data['hmac']) && $data['hmac'] == $this->makeSign($data)) {
                return true;
            }
        }
        return false;
    }

    public function refund(array $data)
    { }


    public function makeSign(array $data)
    {
        //签名步骤一：按字典序排序参数
        ksort($data);
        $buff = "";
        foreach ($data as $k => $v) {
            if ($k != "hmac" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        //签名步骤二：在string后加入KEY
        $string = $buff . $this->key;
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    private function request(string $url, array $data)
    {
        try {
            $data['hmac'] = $this->makeSign($data);
            $client = new Client(['timeout' => 3]);
            $result = $client->request('post',  $url, ['json' => $data])->getBody()->getContents();
            if ($result) {
                $result = json_decode($result);
            }
            return $result;
        } catch (Exception $e) { }
    }
}
