<?php

namespace App\Services;

use App\Util;
use DateTime;
use DateTimeZone;

class KaroPay
{
    /**
     * 生成随机字符串
     * @param int $length
     * @return string
     */
    public function getNonceStr($length = 16)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 生成认证头信息
     * @param string $appId 应用ID
     * @param string $signKey 签名密钥
     * @return array 包含Authorization、AppId和UtcTime的头信息数组
     */
    public function buildAuthorizationHeader($appId, $signKey)
    {
        $utcTime = $this->getUtcTimeString();
        $md5SignKey = md5($signKey);
        
        // 连接appId、md5后的signKey和utcTime
        $value = $appId . ":" . $md5SignKey . ":" . $utcTime;
        $authorization = md5($value);
        
        Util::WriteLog('KaroPay', '认证信息生成: appId=' . $appId . ', utcTime=' . $utcTime . ', authorization=' . $authorization);
        
        return [
            'Authorization' => $authorization,
            'AppId' => $appId,
            'UtcTime' => $utcTime
        ];
    }

    /**
     * 获取UTC时间字符串
     * @return string 格式为yyyyMMddHHmmss的UTC时间字符串
     */
    public function getUtcTimeString()
    {
        return gmdate('YmdHis');
    }

    /**
     * 发送POST请求
     * @param string $url 请求地址
     * @param array $post_data 请求参数
     * @param array $headers 请求头信息
     * @param int $timeout 超时时间
     * @return bool|string
     */
    public function curlPost($url, $post_data = array(), $headers = array(), $timeout = 20)
    {
        $post_string = json_encode($post_data);
        
        $header_array = [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($post_string)
        ];
        
        if (!empty($headers)) {
            foreach ($headers as $key => $value) {
                $header_array[] = $key . ': ' . $value;
            }
        }
        
        Util::WriteLog('KaroPay', 'KaroPay请求: ' . $url . " | " . $post_string);
        Util::WriteLog('KaroPay', 'KaroPay请求头: ' . json_encode($header_array));
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header_array);
        
        $result = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        if ($httpCode == 200) {
            Util::WriteLog('KaroPay', 'KaroPay响应: ' . $result);
        } else {
            Util::WriteLog('KaroPay_error', 'HTTP状态码错误: ' . $httpCode);
            Util::WriteLog('KaroPay_error', 'curl错误: ' . curl_error($ch));
            $result = false;
        }
        
        curl_close($ch);
        return $result;
    }
    
    /**
     * 发送GET请求
     * @param string $url 请求地址
     * @param array $headers 请求头信息
     * @param int $timeout 超时时间
     * @return bool|string
     */
    public function curlGet($url, $headers = array(), $timeout = 20)
    {
        $header_array = [
            'Content-Type: application/json'
        ];
        
        if (!empty($headers)) {
            foreach ($headers as $key => $value) {
                $header_array[] = $key . ': ' . $value;
            }
        }
        
        Util::WriteLog('KaroPay', 'KaroPay GET请求: ' . $url);
        Util::WriteLog('KaroPay', 'KaroPay请求头: ' . json_encode($header_array));
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header_array);
        
        $result = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        if ($httpCode == 200) {
            Util::WriteLog('KaroPay', 'KaroPay响应: ' . $result);
        } else {
            Util::WriteLog('KaroPay_error', 'HTTP状态码错误: ' . $httpCode);
            Util::WriteLog('KaroPay_error', 'curl错误: ' . curl_error($ch));
            $result = false;
        }
        
        curl_close($ch);
        return $result;
    }

    /**
     * 生成签名
     * @param array $params 参数数组
     * @param string $signKey 签名密钥
     * @return string 签名结果
     */
    public function sign($params, $signKey)
    {
        // 移除sign参数
        $newParams = $params;
        if (isset($newParams['sign'])) {
            unset($newParams['sign']);
        }
        
        // 按ASCII码升序排序
        ksort($newParams);
        
        // 拼接参数
        $stringA = '';
        foreach ($newParams as $k => $v) {
            if ($v !== '' && $v !== null && !is_array($v)) {
                $stringA .= $k . '=' . $v . '&';
            }
        }
        
        // 拼接key
        $stringSignTemp = $stringA . 'key=' . md5($signKey);
        
        // md5加密
        $sign = md5($stringSignTemp);
        
        return $sign;
    }
    
    /**
     * 验证签名
     * @param array $params 参数数组
     * @param string $signKey 签名密钥
     * @return bool 验证结果
     */
    public function verifySign($params, $signKey)
    {
        if (!isset($params['sign'])) {
            return false;
        }
        
        $sign = $params['sign'];
        $generatedSign = $this->sign($params, $signKey);
        
        return $sign === $generatedSign;
    }
} 