<?php
namespace Core\Payment;

/**
 * 支付宝网关
 * - demo：返回模拟支付入口
 * - live：电脑网站支付（alipay.trade.page.pay），RSA2 签名
 */
class AlipayGateway extends Gateway
{
    public function pay(array $order): array
    {
        $simulate = site_url('order/demo/' . $order['order_no']);
        $hasCred = !empty($this->config['appid']) && !empty($this->config['private_key']);

        if ($this->isDemo() || !$hasCred) {
            return [
                'mode'           => 'demo',
                'channel'        => 'alipay',
                'simulate'       => $simulate,
                'config_missing' => !$hasCred,
            ];
        }

        $biz = [
            'out_trade_no' => $order['order_no'],
            'product_code' => 'FAST_INSTANT_TRADE_PAY',
            'total_amount' => $this->money($order['amount']),
            'subject'      => $order['product_name'] ?: '商品购买',
        ];
        $params = [
            'app_id'      => $this->config['appid'],
            'method'      => 'alipay.trade.page.pay',
            'format'      => 'JSON',
            'charset'     => 'utf-8',
            'sign_type'   => 'RSA2',
            'timestamp'   => date('Y-m-d H:i:s'),
            'version'     => '1.0',
            'notify_url'  => site_url('pay/notify/alipay'),
            'return_url'  => site_url('order/success/' . $order['order_no']),
            'biz_content' => json_encode($biz, JSON_UNESCAPED_UNICODE),
        ];
        $params['sign'] = $this->sign($params);
        $gateway = $this->config['gateway'] ?: 'https://openapi.alipay.com/gateway.do';
        return ['mode' => 'redirect', 'channel' => 'alipay', 'url' => $gateway . '?' . http_build_query($params)];
    }

    /** RSA2 签名 */
    private function sign(array $params): string
    {
        ksort($params);
        $str = '';
        foreach ($params as $k => $v) {
            if ($v === '' || $v === null) continue;
            $str .= $k . '=' . $v . '&';
        }
        $str = rtrim($str, '&');
        $key = $this->normalizeKey($this->config['private_key'] ?? '', false);
        openssl_sign($str, $sign, $key, OPENSSL_ALGO_SHA256);
        return base64_encode($sign);
    }

    private function normalizeKey(string $key, bool $isPublic): string
    {
        $key = trim($key);
        if (strpos($key, '-----BEGIN') === 0) return $key;
        $head = $isPublic ? "-----BEGIN PUBLIC KEY-----\n" : "-----BEGIN RSA PRIVATE KEY-----\n";
        $foot = $isPublic ? "\n-----END PUBLIC KEY-----" : "\n-----END RSA PRIVATE KEY-----";
        return $head . chunk_split($key, 64, "\n") . $foot;
    }

    public function verifyNotify(array $data): ?string
    {
        if (empty($data['out_trade_no'])) return null;
        $status = $data['trade_status'] ?? '';
        if ($status === 'TRADE_SUCCESS' || $status === 'TRADE_FINISHED') {
            // 生产环境应使用支付宝公钥对签名做严格验签后再返回
            return $data['out_trade_no'];
        }
        return null;
    }
}
