Sanal postu entegre ediyorum ödeme ekranında şu şekil bir hata alıyorum. Ürünler dijital




<?php


session_start();
require_once 'includes/config.php';


ini_set('display_errors', 0);
ini_set('log_errors', 1);

header('Content-Type: application/json');


if (!isset($_SESSION['user_id'])) {
    echo json_encode(['success' => false, 'error' => 'Oturum kapalı. Lütfen giriş yapın.']);
    exit;
}

$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['csrf_token']) || !hash_equals($_SESSION['csrf_token'] ?? '', $input['csrf_token'])) {
    echo json_encode(['success' => false, 'error' => 'Güvenlik hatası (CSRF). Sayfayı yenileyin.']);
    exit;
}


$user_id    = $_SESSION['user_id'];
$package_id = intval($input['package_id'] ?? 0);

// Form verileri
$phone      = preg_replace('/[^0-9]/', '', $input['phone'] ?? '');
$firstname  = trim($input['firstname'] ?? '');
$surname    = trim($input['surname'] ?? '');
$address    = trim($input['address'] ?? '');
$city       = trim($input['city'] ?? '');
$state      = trim($input['state'] ?? '');
$zip        = trim($input['zip'] ?? '');


if (empty($firstname) || empty($surname) || empty($address) || empty($city) || empty($state) || empty($zip)) {
    echo json_encode(['success' => false, 'error' => 'Lütfen tüm adres alanlarını doldurun.']);
    exit;
}
if (strlen($phone) !== 10) {
    echo json_encode(['success' => false, 'error' => 'Telefon numarası başında 0 olmadan 10 haneli olmalıdır.']);
    exit;
}

try {
   
    $stmt = $db->prepare("SELECT email FROM users WHERE id = ?");
    $stmt->execute([$user_id]);
    $user = $stmt->fetch(PDO::FETCH_OBJ);
    if (!$user) throw new Exception('Kullanıcı bulunamadı.');

    $stmt = $db->prepare("SELECT * FROM credit_packages WHERE id = ? AND is_active = 1");
    $stmt->execute([$package_id]);
    $package = $stmt->fetch(PDO::FETCH_OBJ);
    if (!$package) throw new Exception('Paket bulunamadı.');

    $stmt = $db->query("SELECT * FROM shopinext_settings WHERE is_active = 1 LIMIT 1");
    $settings = $stmt->fetch(PDO::FETCH_OBJ);
    if (!$settings) throw new Exception('Ödeme sistemi ayarlanmamış.');

   
    $api_base = 'https://api.shopinext.com';
    $merchant_order_id = 'CB-' . strtoupper(substr(md5(uniqid()), 0, 8)) . '-' . time();
    $site_url = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
    $formatted_price = number_format((float)$package->price, 2, '.', '');

   
    $target_domain = 'e.com'; 
    if (!empty($settings->domain)) {
        $clean = preg_replace('#^https?://#', '', $settings->domain);
        $clean = str_replace('www.', '', $clean);
        $clean = rtrim($clean, '/');
        if (!empty($clean)) $target_domain = $clean;
    }

    // ─── ADIM 1: AUTHENTICATE ───
    $auth_response = sendShopinextRequest($api_base . '/authenticate', [
        'client_id'     => $settings->client_id, 
        'client_secret' => $settings->client_secret
    ], null, $target_domain);

    if (($auth_response->status ?? 0) != 1) {
        $err = $auth_response->error ?? $auth_response->message ?? 'Bilinmeyen Auth Hatası';
        throw new Exception("Giriş Hatası: " . $err);
    }
    
    $token = $auth_response->access_token;

    
    
    $payment_data = [
        "firstname"         => $firstname,
        "surname"           => $surname,
        "email"             => $user->email,
        "country_code"      => "+90",
        "phone"             => $phone,
        "amount"            => $formatted_price,
        "currency"          => "TRY",
        "max_installment"   => 1,
        "merchant_order_id" => $merchant_order_id,
        "is_digital"        => 1,
        // "client_ip" => ... // BU SATIR SİLİNDİ!
        
        "order_products"    => [[
            "name"     => $package->name,
            "quantity" => 1,
            "price"    => $formatted_price,
            "total"    => $formatted_price
        ]],

        "billing_info" => [
            "billing_firstname"   => $firstname,
            "billing_surname"     => $surname,
            "billing_address"     => $address,
            "billing_city"        => $city,
            "billing_state"       => $state,
            "billing_postal_code" => $zip,
            "billing_country"     => "TR",
            "billing_country_code"=> "+90",
            "billing_phone"       => $phone
        ],
        "shipping_info" => [
            "shipping_firstname"   => $firstname,
            "shipping_surname"     => $surname,
            "shipping_address"     => $address,
            "shipping_city"        => $city,
            "shipping_state"       => $state,
            "shipping_postal_code" => $zip,
            "shipping_country"     => "TR",
            "shipping_country_code"=> "+90",
            "shipping_phone"       => $phone
        ],
        
        "success_url"  => $site_url . '/payment_result.php?status=success',
        "fail_url"     => $site_url . '/payment_result.php?status=error',
        "callback_url" => $site_url . '/shopinext_webhook.php',
        "language"     => "TR"
    ];

    $pay_response = sendShopinextRequest($api_base . '/createPayment', $payment_data, $token, $target_domain);

    if (($pay_response->status ?? 0) != 1) {
        $err = $pay_response->error ?? $pay_response->message ?? 'Ödeme oluşturulamadı';
        throw new Exception("Ödeme Hatası: " . $err);
    }

    // ─── VERİTABANI KAYDI ───
    $stmt = $db->prepare("
        INSERT INTO payment_transactions 
        (user_id, package_id, payment_type, shopinext_payment_id, merchant_order_id, 
         amount, currency, credits_amount, status, redirect_url,
         customer_firstname, customer_surname, customer_email, customer_phone,
         created_at, updated_at)
        VALUES (?, ?, 'credit', ?, ?, ?, 'TRY', ?, 'processing', ?, ?, ?, ?, ?, NOW(), NOW())
    ");
    
    $stmt->execute([
        $user_id, 
        $package->id, 
        $pay_response->payment_id, 
        $merchant_order_id, 
        $package->price, 
        $package->credits, 
        $pay_response->redirect_url,
        $firstname, 
        $surname, 
        $user->email, 
        $phone
    ]);

    echo json_encode(['success' => true, 'redirect_url' => $pay_response->redirect_url]);

} catch (Exception $e) {
    echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}


function sendShopinextRequest($url, $data, $token = null, $domain = null) {
    $ch = curl_init($url);
    $headers = ['Content-Type: application/json', 'Accept: application/json'];
    
    if ($token) $headers[] = 'Authorization: Bearer ' . $token;
    if ($domain) $headers[] = 'Domain: ' . $domain;
    
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
    if ($domain) curl_setopt($ch, CURLOPT_REFERER, 'https://' . $domain);
    
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
   
    
    $response = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    
    if ($error) return (object)['status' => 0, 'error' => 'Bağlantı Hatası: ' . $error];
    
    $json = json_decode($response);
    
   
    if (!$json) {
        $clean_resp = strip_tags($response);
        if (strlen($clean_resp) > 150) $clean_resp = substr($clean_resp, 0, 150) . '...';
        return (object)['status' => 0, 'error' => 'Sunucu Yanıtı Geçersiz: ' . $clean_resp];
    }
    
    return $json;
}