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;
}