?
| Current Path : /home/webyoo/www/leumi/site/ |
| Current File : /home/webyoo/www/leumi/site/agent-paypal-webhook.php |
<?php
// =====================================================================
// WEBHOOK PayPal — met à jour sub_status automatiquement
// (renouvellement mensuel, annulation, suspension, échec de paiement)
//
// À configurer dans PayPal : Developer > (ton app) > Webhooks >
// URL = https://ton-site/agent-paypal-webhook.php
// Événements à cocher :
// - BILLING.SUBSCRIPTION.ACTIVATED
// - BILLING.SUBSCRIPTION.CANCELLED
// - BILLING.SUBSCRIPTION.SUSPENDED
// - BILLING.SUBSCRIPTION.EXPIRED
// - PAYMENT.SALE.COMPLETED (= paiement mensuel encaissé)
// Puis copie le "Webhook ID" fourni par PayPal dans $WEBHOOK_ID ci-dessous.
// =====================================================================
include "start.php";
// ---- CONFIG (mêmes identifiants que paypal_create_plan.php) ----------
$MODE = 'live';
$CLIENT_ID = 'BAAzaApYYAx5QNj4Kb_HeB3gZARKntyYL97XCpDvnb66rF7-2obBll2pBfeuS8HhtEIn4cUt03qskR-4f8';
$SECRET = 'EAGmK0PQb7XHP-dxCBgMsCt2qN-qqVmqKv-ZYyRGmz4IKW-UaFRM5SBCZNZ2WRTaAXJdh_lcv-R6jPaR'; // Secret Live
$WEBHOOK_ID = '2NS02231WC320640B';
// ---------------------------------------------------------------------
$BASE = ($MODE === 'live') ? 'https://api-m.paypal.com' : 'https://api-m.sandbox.paypal.com';
$raw = file_get_contents('php://input');
$event = json_decode($raw, true);
if (!$event || empty($event['event_type'])) {
http_response_code(400);
exit('bad payload');
}
// ---- Vérification de la signature (recommandé) ----
function pp_token($base, $id, $secret) {
$ch = curl_init("$base/v1/oauth2/token");
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_USERPWD => $id . ':' . $secret,
CURLOPT_HTTPHEADER => array('Accept: application/json'),
CURLOPT_POSTFIELDS => 'grant_type=client_credentials'
));
$r = json_decode(curl_exec($ch), true);
curl_close($ch);
return isset($r['access_token']) ? $r['access_token'] : null;
}
$verified = false;
if ($WEBHOOK_ID !== 'REMPLACER_WEBHOOK_ID' && $CLIENT_ID !== 'REMPLACER_CLIENT_ID') {
$access = pp_token($BASE, $CLIENT_ID, $SECRET);
if ($access) {
$verifyBody = json_encode(array(
'transmission_id' => isset($_SERVER['HTTP_PAYPAL_TRANSMISSION_ID']) ? $_SERVER['HTTP_PAYPAL_TRANSMISSION_ID'] : '',
'transmission_time' => isset($_SERVER['HTTP_PAYPAL_TRANSMISSION_TIME']) ? $_SERVER['HTTP_PAYPAL_TRANSMISSION_TIME'] : '',
'cert_url' => isset($_SERVER['HTTP_PAYPAL_CERT_URL']) ? $_SERVER['HTTP_PAYPAL_CERT_URL'] : '',
'auth_algo' => isset($_SERVER['HTTP_PAYPAL_AUTH_ALGO']) ? $_SERVER['HTTP_PAYPAL_AUTH_ALGO'] : '',
'transmission_sig' => isset($_SERVER['HTTP_PAYPAL_TRANSMISSION_SIG']) ? $_SERVER['HTTP_PAYPAL_TRANSMISSION_SIG'] : '',
'webhook_id' => $WEBHOOK_ID,
'webhook_event' => json_decode($raw)
));
$ch = curl_init("$BASE/v1/notifications/verify-webhook-signature");
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => array('Content-Type: application/json', 'Authorization: Bearer ' . $access),
CURLOPT_POSTFIELDS => $verifyBody
));
$vr = json_decode(curl_exec($ch), true);
curl_close($ch);
$verified = (isset($vr['verification_status']) && $vr['verification_status'] === 'SUCCESS');
}
if (!$verified) {
http_response_code(400);
exit('signature not verified');
}
}
// ---- Identifier l'abonnement concerné ----
$type = $event['event_type'];
$res = isset($event['resource']) ? $event['resource'] : array();
$subId = '';
if (isset($res['billing_agreement_id'])) {
$subId = $res['billing_agreement_id']; // PAYMENT.SALE.COMPLETED
} elseif (isset($res['id'])) {
$subId = $res['id']; // BILLING.SUBSCRIPTION.*
}
if ($subId === '') {
http_response_code(200);
exit('no subscription id');
}
$subEsc = mysqli_real_escape_string($link, $subId);
// ---- Appliquer l'effet de l'événement ----
switch ($type) {
case 'BILLING.SUBSCRIPTION.ACTIVATED':
case 'PAYMENT.SALE.COMPLETED':
// Activation / renouvellement : prolonge d'un mois
mysqli_query($link,
"UPDATE rent_users
SET sub_status = 'active',
sub_until = DATE_ADD(GREATEST(CURDATE(), COALESCE(sub_until, CURDATE())), INTERVAL 1 MONTH)
WHERE sub_payer_id = '".$subEsc."' AND fk_type = 3");
break;
case 'BILLING.SUBSCRIPTION.CANCELLED':
case 'BILLING.SUBSCRIPTION.SUSPENDED':
case 'BILLING.SUBSCRIPTION.EXPIRED':
// Fin de l'abonnement : la vitrine agent est désactivée (biens restent visibles comme un particulier)
mysqli_query($link,
"UPDATE rent_users
SET sub_status = 'expired'
WHERE sub_payer_id = '".$subEsc."' AND fk_type = 3");
break;
default:
// autres événements : ignorés
break;
}
http_response_code(200);
echo 'ok';