I am having issues with some simple PHP statements after receiving payment via crypto using Coinbase Commerce API. The payment is going through and the page is redirecting to the payment_complete page but it refuses to update the orders in my checkout
table…
I have tried adding some lines to log the bugs, but it’s also refusing to create the debug.log file… so I cannot see where the script is failing, and I can’t monitor console because it redirects etc.
The issue appears to be with the webhook script, for some reason its skipping past it and not updating the items in checkout
.
This is how I am rendering in the coinbase pay button:
<?php
$ch = curl_init();
try {
// Query to get the items from the checkout table for the current user
$stmt = $dbh->prepare("SELECT product FROM checkout WHERE userID = :userID");
$stmt->execute(['userID' => $userID]);
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Check if there are items in the cart
if (count($items) > 1) {
// For multiple items, join the titles into a single string separated by commas
$description = implode(', ', array_column($items, 'product'));
} elseif (count($items) === 1) {
// If there's only one item, use its title directly
$description = $items[0]['product'];
} else {
// If no items are found, set a default description
$description = "No items found";
}
} catch (PDOException $e) {
// Handle any errors in the connection or query
echo "Error: " . $e->getMessage();
exit();
}
// Set up the cURL request to the Coinbase API
// Set up the cURL request to the Coinbase API
curl_setopt($ch, CURLOPT_URL, 'https://api.commerce.coinbase.com/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(
array (
'name' => 'TL', // The name of your business or checkout
'description' => $description, // Dynamically generated description of the items
'local_price' =>
array (
'amount' => $totalprice['totPrice'], // Total price of all items (use your original total price variable)
'currency' => 'GBP', // Currency code
),
'pricing_type' => 'fixed_price', // Pricing model (fixed in this case)
'metadata' =>
array (
'customer_id' => $userID, // Pass the userID as requested
'customer_name' => $useremail, // Customer's email or identifier (from session or checkout)
),
'redirect_url' => 'https://www.my-site.co.uk/Checkout/payment_complete.php', // URL to redirect after successful payment
'cancel_url' => 'https://www.my-site.co.uk/Checkout/payment_cancelled.php', // URL to redirect if payment is canceled
'webhook_url' => 'https://www.my-site.co.uk/Checkout/PHP/coinbase_webhook.php' // Webhook URL for payment confirmation
)
));
// Set headers for the Coinbase API request
$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = 'X-Cc-Api-Key: MY-API-KEY'; // Your Coinbase API key
$headers[] = 'X-Cc-Version: 2018-03-22'; // Coinbase API version
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute the cURL request and get the response
$result = curl_exec($ch);
// Close the cURL session
curl_close($ch);
// Decode the JSON response from Coinbase
$response = json_decode($result, true);
// Extract the hosted URL from the response to redirect the user
$letssee = $response['data']['hosted_url'];
// Output the payment button/link to the user
echo "<a id='byee' class='leggo2' href='$letssee'><b>Pay with Crypto</b></a>";
?>
and this is my coinbase_webhook.php backend file for confirming transaction and updating item(s) in checkout
table:
<?php
session_start();
// DB connect //
require_once '/var/www/vhosts/my-site.co.uk/httpdocs/include/PHP/main.php';
// Set error handling
ini_set('display_errors', 0); // Disable error output to the client
ini_set('log_errors', 1); // Enable error logging
ini_set('error_log', '/var/www/vhosts/my-site.co.uk/httpdocs/Checkout/debug.log');
error_reporting(E_ALL); // Report all errors
// Log script start
file_put_contents('/var/www/vhosts/my-site.co.uk/httpdocs/Checkout/debug.log', "Script started at " . date('Y-m-d H:i:s') . "n", FILE_APPEND);
// Coinbase Webhook Listener to handle crypto payment confirmation
// Read the incoming webhook data
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_CC_WEBHOOK_SIGNATURE'];
// Verify the Coinbase signature to ensure it's a legit request
$shared_secret = 'MY-API-KEY'; // Get this from Coinbase Dashboard
$computed_signature = hash_hmac('sha256', $payload, $shared_secret);
if (hash_equals($signature, $computed_signature)) {
$event = json_decode($payload, true);
error_log("Received webhook event: " . print_r($event, true), 3, "/var/www/vhosts/my-site.co.uk/httpdocs/Checkout/debug.log");
// Check if the event is 'charge:confirmed'
if ($event['event']['type'] == 'charge:confirmed') {
$paymentDetails = $event['event']['data'];
// Extract necessary data
$orderID = 'TL-' . bin2hex(random_bytes(5)); // Generate unique order ID
$userID = $paymentDetails['metadata']['customer_id']; // Retrieve userID from metadata
$amount = $paymentDetails['pricing']['local']['amount'];
$currency = $paymentDetails['pricing']['local']['currency'];
// Connect to the database using PDO (ensure you have the $dbh variable defined)
try {
$userID = $_SESSION['sessionID'];
// Update the checkout records
$paytype = "Crypto";
$confirmationStatus = "Confirmed"; // This is what you want to store in the confirmation column
$ordprogress = "75"; // Update the order progress as needed
$updateStmt = $dbh->prepare("UPDATE checkout SET paytype = :paytype, confirmation = :confirmation, ordprogress = :ordprogress WHERE userID = :userID");
$updateStmt->bindParam(':paytype', $paytype, PDO::PARAM_STR);
$updateStmt->bindParam(':confirmation', $confirmationStatus, PDO::PARAM_STR);
$updateStmt->bindParam(':ordprogress', $ordprogress, PDO::PARAM_STR);
$updateStmt->bindParam(':userID', $userID, PDO::PARAM_STR);
// Attempt to execute the update statement
if (!$updateStmt->execute()) {
// Log the SQL error if the update fails
error_log("Failed to update checkout table. Error: " . implode(", ", $updateStmt->errorInfo()) . "n", 3, "/var/www/vhosts/my-site.co.uk/httpdocs/Checkout/debug.log");
throw new Exception("Failed to update checkout table.");
}
error_log("Checkout updated for userID: $userIDn", 3, "/var/www/vhosts/my-site.co.uk/httpdocs/Checkout/debug.log");
http_response_code(200); // Respond with 200 OK
} catch (Exception $e) {
error_log("Error occurred: " . $e->getMessage() . "n", 3, "/var/www/vhosts/my-site.co.uk/httpdocs/Checkout/debug.log");
http_response_code(500); // Internal server error
}
}
} else {
// Invalid signature, possible attack
error_log("Invalid signature receivedn", 3, "/var/www/vhosts/my-site.co.uk/httpdocs/Checkout/debug.log");
http_response_code(400); // Bad request
}
?>
9