<?php

namespace App\Services;

use App\Util;

class SfPay
{
    public $config;
    public $merchantKey;
    public $aesKey;
    public $aesIv;
    public $apiUrl;

    public function __construct()
    {
        $payConfigService = new PayConfig();
        $this->config = $payConfigService->getConfig('SfPay');

        $this->merchantKey = $this->config['merchant_key'] ?? '';
        $this->aesKey      = $this->config['aes_key'] ?? '';
        $this->aesIv       = $this->config['aes_iv'] ?? '';
        $this->apiUrl      = $this->config['apiUrl'] ?? 'https://sfgateway.sforest.io';
    }

    /**
     * AES/CBC/PKCS5Padding 加密
     *
     * @param string $str 待加密JSON字符串
     * @return string base64编码的密文
     */
    public function encrypt($str)
    {
        return base64_encode(openssl_encrypt($str, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv));
    }

    /**
     * AES/CBC/PKCS5Padding 解密
     *
     * @param string $encrypted base64编码的密文
     * @return string 解密后的JSON字符串
     */
    public function decrypt($encrypted)
    {
        return openssl_decrypt(base64_decode($encrypted), 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv);
    }

    /**
     * 验证回调签名
     *
     * signature_n = MD5(merchantKey + message + amount + status + merchantOrderNo + orderNo + aeskey)
     *
     * 注意：如果amount为空，则拼接"null"字符串（代付回调可能出现amount为空的情况）
     *
     * @param array $data 回调data参数
     * @param string $signatureN 签名值
     * @return bool
     */
    public function verifySign($data, $signatureN)
    {
        $message        = $data['message'] ?? '';
        $amount         = $data['amount'] ?? '';
        $status         = $data['status'] ?? '';
        $merchantOrderNo = $data['merchantOrderNo'] ?? '';
        $orderNo        = $data['orderNo'] ?? '';

        // 代付回调中amount为空时，拼接"null"字符串
        if ($amount === '' || $amount === null) {
            $amount = 'null';
        }

        $signStr = $this->merchantKey . $message . $amount . $status . $merchantOrderNo . $orderNo . $this->aesKey;

        $expectedSign = md5($signStr);

        Util::WriteLog('SfPay', "待签名字符串: {$signStr}");
        Util::WriteLog('SfPay', "期望签名: {$expectedSign}, 实际签名: {$signatureN}");

        return strtolower($expectedSign) === strtolower($signatureN);
    }

    /**
     * POST JSON请求（SfPay格式：data字段AES加密，merchant_key放在header）
     *
     * @param string $url 请求地址
     * @param array $params 待加密的请求参数
     * @return string|false
     */
    public function curlPost($url, $params)
    {
        $timeout = 30;
        $jsonStr = json_encode($params, JSON_UNESCAPED_UNICODE);

        // AES加密
        $encrypted = $this->encrypt($jsonStr);
        $body = json_encode(['data' => $encrypted], JSON_UNESCAPED_UNICODE);

        $headers = [
            'Content-Type: application/json;charset=UTF-8',
            'merchant_key: ' . $this->merchantKey,
        ];

        Util::WriteLog('SfPay', "SfPay请求URL: {$url}");
        Util::WriteLog('SfPay', "SfPay请求明文: {$jsonStr}");
        Util::WriteLog('SfPay', "SfPay请求密文: {$body}");

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $result = curl_exec($ch);

        if (curl_errno($ch)) {
            $error = curl_error($ch);
            Util::WriteLog('SfPay_error', 'CURL Error: ' . $error);
            curl_close($ch);
            return false;
        }

        curl_close($ch);

        Util::WriteLog('SfPay', "SfPay响应: {$result}");

        return $result;
    }
}
