Apparently this module relies on the user returning to the website to note the payment was a success and there is no webhook file which can result in an order being placed and paid for but not being recorded??
Stripe library has a "webhook.php" which apparently isn't the file i should point too in stripes dashboard under webhooks settings?
I have had a number of these unrecorded orders and always put it down to checkout rush but on another site with the same module and no checkout rush issues i found a revolut payment was taken from my customer but the system treated it like they had not paid and their basket remained filled with the items.
Do I set the url to '/checkout_success' or does this module require a "/stripe_webhook.php" as chatgpt suggests? (provided below but... the code it provided for this looks like it has placeholders and a few details wrong.. made up functions ect lol)
Code:<?php // /stripe_webhook.php // Minimal Stripe webhook for Zen Cart chdir(__DIR__); require 'includes/application_top.php'; // boot Zen Cart (DB, constants) require 'includes/modules/payment/stripepay/vendor/autoload.php'; $endpointSecret = getenv('STRIPE_WEBHOOK_SECRET') ?: 'whsec_PUT_YOUR_SECRET_HERE'; // Simple health-check for you if ($_SERVER['REQUEST_METHOD'] === 'GET') { header('Content-Type: text/plain'); echo "ok\n"; exit; } $payload = @file_get_contents('php://input'); $sig = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? ''; try { $event = \Stripe\Webhook::constructEvent($payload, $sig, $endpointSecret); } catch (\UnexpectedValueException $e) { http_response_code(400); echo 'Invalid payload'; exit; } catch (\Stripe\Exception\SignatureVerificationException $e) { http_response_code(400); echo 'Invalid signature'; exit; } $type = $event['type'] ?? ''; $object = $event['data']['object'] ?? []; function zc_log($m){ error_log('[stripewh] '.$m."\n", 3, __DIR__.'/logs/stripe_webhook.log'); } switch ($type) { case 'payment_intent.succeeded': $pi = $object; $txn = $pi['id'] ?? ''; $amt = isset($pi['amount_received']) ? ($pi['amount_received']/100.0) : 0; $cur = strtoupper($pi['currency'] ?? ''); $oid = $pi['metadata']['zc_order_id'] ?? $pi['metadata']['order_id'] ?? null; if ($oid) { $orders_id = (int)$oid; $rs = $db->Execute("SELECT orders_status FROM " . TABLE_ORDERS . " WHERE orders_id=$orders_id LIMIT 1"); if (!$rs->EOF) { $paid_status_id = defined('MODULE_PAYMENT_STRIPEPAY_ORDER_STATUS_PAID_ID') ? (int)MODULE_PAYMENT_STRIPEPAY_ORDER_STATUS_PAID_ID : 2; // adjust to your "Paid" status if ((int)$rs->fields['orders_status'] !== $paid_status_id) { $db->Execute("UPDATE " . TABLE_ORDERS . " SET orders_status=$paid_status_id, last_modified=NOW() WHERE orders_id=$orders_id"); $db->Execute("INSERT INTO " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added, customer_notified, comments) VALUES ($orders_id, $paid_status_id, NOW(), 0, 'Stripe PI ".$txn." ".$amt." ".$cur." (webhook)')"); } } else { zc_log("order $orders_id not found for txn $txn"); } } else { zc_log("no order_id metadata for txn $txn"); } break; case 'checkout.session.completed': $cs = $object; $oid = $cs['metadata']['zc_order_id'] ?? null; $txn = is_array($cs['payment_intent'] ?? null) ? ($cs['payment_intent']['id'] ?? '') : ($cs['payment_intent'] ?? ''); if ($oid) { $orders_id = (int)$oid; $paid_status_id = defined('MODULE_PAYMENT_STRIPEPAY_ORDER_STATUS_PAID_ID') ? (int)MODULE_PAYMENT_STRIPEPAY_ORDER_STATUS_PAID_ID : 2; $db->Execute("UPDATE " . TABLE_ORDERS . " SET orders_status=$paid_status_id, last_modified=NOW() WHERE orders_id=$orders_id"); $db->Execute("INSERT INTO " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added, customer_notified, comments) VALUES ($orders_id, $paid_status_id, NOW(), 0, 'Stripe Checkout ".$txn." (webhook)')"); } else { zc_log("checkout.session.completed without order id"); } break; default: // ignore others } http_response_code(200); echo 'ok';


Reply With Quote
