File: /var/www/gurumedia_st_usr/data/www/gurumedia.store/frdsp/dp/page/frd-p-fbcapi/frdapi-IniCAPI.php
<?php
/**
* FRD CAPI API - VERSION 30 (SECURE)
* Author: Fazle Rabbi (Spider eCommerce)
* Updated: 2025-11-11
*
* SECURITY UPGRADE:
* - Removed wildcard (*) CORS fallback
* - Only allow requests from your defined $FRD_HURL
* - event_id logic fixed to match Pixel
*/
$FR_PATH_HD = "../../../../";
require_once($FR_PATH_HD."frd-src/abc/frd-config.php");//FRD CONFIG
require_once($FR_PATH_HD."frd-src/abc/frd-spider-function.php");//FRD SPIDER FUN PHP
require_once($FR_PATH_HD."frd-src/abc/frd-this-function.php");
header('Content-Type: application/json');
// === LOG FUNCTION ===
function log_error($msg) {
$file = __DIR__ . '/x_fb_capi_errors.txt';
$time = gmdate('Y-m-d H:i:s');
file_put_contents($file, "[$time] $msg\n", FILE_APPEND | LOCK_EX);
}
// === SECURE CORS: Only allow your eCommerce domain ===
if (empty($FRD_HURL)) {
log_error("EMPTY FRD HURL");
http_response_code(500);
exit(json_encode(["status" => 0, "error" => "CORS config missing"]));
}
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if ($origin === $FRD_HURL) {
header("Access-Control-Allow-Origin: $FRD_HURL");
} else {
log_error("ORGIN MOT MATCHED [$origin]");
http_response_code(403);
exit(json_encode(["status" => 0, "error" => "Forbidden origin"]));
}
// === FORCE UTC TIMEZONE ===
date_default_timezone_set('UTC');
// === READ INPUT (form or JSON) ===
$input = $_POST;
if (empty($input)) {
$raw = file_get_contents('php://input');
$json = json_decode($raw, true);
if (is_array($json)) $input = $json;
}
if (empty($input)) {
log_error("No POST/JSON data received");
http_response_code(400);
exit(json_encode(["status" => 0, "error" => "No data"]));
}
// === REQUIRED FIELDS ===
$required = ['event_name', 'event_id', 'external_id'];
foreach ($required as $field) {
if (empty($input[$field])) {
log_error("Missing required field: $field");
http_response_code(400);
exit(json_encode(["status" => 0, "error" => "Missing $field"]));
}
}
// === BASE VARIABLES ===
$event_time = time();
$event_name = trim($input['event_name']);
$event_id_raw = trim($input['event_id']); // use same ID as pixel
$external_id_raw = trim($input['external_id']);
$fbc = $input['fbc'] ?? $_COOKIE['_fbc'] ?? null;
$fbp = $input['fbp'] ?? $_COOKIE['_fbp'] ?? null;
$value = floatval($input['value'] ?? 0);
$order_id = $input['order_id'] ?? '';
$event_source_url = $input['event_source_url'] ?? '';
$ph_raw = $input['ph'] ?? '';
$ln_raw = $input['ln'] ?? '';
$country = $input['country'] ?? 'BD';
$num_items = intval($input['num_items'] ?? 1);
$content_type = $input['content_type'] ?? 'product';
$content_name = $input['content_name'] ?? 'Unknown Product';
$content_category = $input['content_category'] ?? 'Unknown Category';
// === content_ids parse ===
$content_ids = [];
if (!empty($input['content_ids'])) {
$decoded = is_string($input['content_ids']) ? json_decode($input['content_ids'], true) : $input['content_ids'];
if (is_array($decoded)) $content_ids = $decoded;
}
$content_ids = array_map('strval', $content_ids);
// === HASH only user data (Meta CAPI standard) ===
$ph = !empty($ph_raw) ? hash('sha256', preg_replace('/\D/', '', $ph_raw)) : null;
$ln = !empty($ln_raw) ? hash('sha256', strtolower(trim($ln_raw))) : null;
$country = !empty($country) ? hash('sha256', strtolower(trim($country))) : null;
// external_id (Pixel raw → CAPI hashed)
$external_id = hash('sha256', $external_id_raw);
// === USER DATA ===
$user_data = [
"client_ip_address" => $FRc_USER_IP ?? $_SERVER['REMOTE_ADDR'] ?? '',
"client_user_agent" => $FRc_USER_AGENT ?? $_SERVER['HTTP_USER_AGENT'] ?? '',
"external_id" => $external_id,
"fbc" => $fbc,
"fbp" => $fbp,
"country" => $country
];
if ($ph) $user_data['ph'] = $ph;
if ($ln) $user_data['ln'] = $ln;
$user_data = array_filter($user_data);
// === CUSTOM DATA ===
$custom_data = [
"currency" => "BDT",
"value" => 0,
"user_role" => 'guest',
"setup_by" => "spiderecommerce.com"
];
// === PURCHASE VALUE CHECK ===
if ($event_name === 'Purchase') {
if ($value <= 0) {
log_error("Purchase rejected: value <= 0 | Order: $order_id");
http_response_code(400);
exit(json_encode(["status" => 0, "error" => "Invalid value"]));
}
$custom_data['value'] = $value;
$custom_data['order_id'] = $order_id;
} else {
$custom_data['value'] = $value;
}
// === ADD product data ===
if (in_array($event_name, ['ViewContent', 'AddToCart', 'InitiateCheckout', 'Purchase'])) {
$custom_data += [
"content_type" => $content_type,
"content_ids" => $content_ids,
"content_name" => $content_name,
"content_category" => $content_category,
"num_items" => count($content_ids) ?: $num_items
];
}
// === DB CONFIG ===
try {
$FRQ = $FR_CONN->query("SELECT * FROM frd_capi WHERE fr_capi_id = 1");
$config = $FRQ->fetch(PDO::FETCH_ASSOC);
} catch (Exception $e) {
log_error("DB error: " . $e->getMessage());
http_response_code(500);
exit(json_encode(["status" => 0, "error" => "Config error"]));
}
if (!$config || empty($config['fr_capi_ds_id'])) {
log_error("CAPI config missing");
http_response_code(500);
exit(json_encode(["status" => 0, "error" => "Missing config"]));
}
extract($config, EXTR_SKIP);
// === FINAL event_id (must match Pixel) ===
$event_id_final = strtolower($event_name) . $event_id_raw;
// === FINAL PAYLOAD ===
$dataArray = [
"data" => [[
"event_name" => $event_name,
"event_time" => $event_time,
"event_id" => $event_id_final,
"event_source_url" => $event_source_url,
"action_source" => "website",
"user_data" => $user_data,
"custom_data" => $custom_data,
"opt_out" => false
]]
];
if (!empty($fr_capi_test_event_code)) {
$dataArray["test_event_code"] = $fr_capi_test_event_code;
}
// === SEND TO FACEBOOK ===
$api_url = rtrim($fr_capi_base_url, '/') . '/' . $fr_capi_ds_id . '/events';
$ch = curl_init($api_url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($dataArray),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
"Authorization: Bearer {$fr_capi_accesstoken}"
],
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true
]);
$response = curl_exec($ch);
$error = curl_error($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($error) {
log_error("cURL Error: $error");
http_response_code(502);
exit(json_encode(["status" => 0, "error" => "Network error"]));
}
$decoded = json_decode($response, true);
if (isset($decoded['events_received'])) {
// log_error("$event_name => EVENT RECEIVED: $response ");
// log_error("event_source_url: $event_source_url ");
// log_error("Payload Data: " . json_encode($dataArray));
echo json_encode(["status" => 1, "message" => "Success", "events_received" => $decoded['events_received']]);
exit;
}
log_error("FB API Error (HTTP $http): " . substr($response, 0, 400));
http_response_code(500);
exit(json_encode(["status" => 0, "error" => "FB rejected"]));