captureOrder($orderId); // Check capture status if ($captureResult['status'] !== 'COMPLETED') { throw new Exception('Payment was not completed. Status: ' . $captureResult['status']); } // Extract payment details $purchaseUnit = $captureResult['purchase_units'][0] ?? []; $capture = $purchaseUnit['payments']['captures'][0] ?? []; $txnId = $capture['id'] ?? $orderId; $amount = $capture['amount']['value'] ?? 0; $currency = $capture['amount']['currency_code'] ?? ''; $customId = $purchaseUnit['custom_id'] ?? $expectedTrxnum; // This is your TRXnum $payerEmail = $captureResult['payer']['email_address'] ?? ''; $payerName = ($captureResult['payer']['name']['given_name'] ?? '') . ' ' . ($captureResult['payer']['name']['surname'] ?? ''); // Get fee info if available $fee = 0; if (isset($capture['seller_receivable_breakdown']['paypal_fee']['value'])) { $fee = floatval($capture['seller_receivable_breakdown']['paypal_fee']['value']); } // Validate amount matches what we expected if ($expectedAmount && abs(floatval($amount) - floatval($expectedAmount)) > 0.01) { // Log this discrepancy but still process (PayPal has already captured) error_log("PayPal amount mismatch: expected $expectedAmount, got $amount"); } // ========================================================================= // UPDATE YOUR DATABASE // This follows the same pattern as ppPayment.php but adapted for REST API // ========================================================================= $TRXnum = intval($customId); $ptime = time(); if ($TRXnum > 0 && function_exists('db_query')) { // Get user info from online payments record $query = "SELECT * FROM user_online_payments WHERE record_num = $TRXnum"; $r = db_query($query); if (db_num_rows($r) == 1) { $paymentRow = db_fetch_assoc($r); $p_school_num = $paymentRow['school_num']; $p_user_num = $paymentRow['user_num']; // Update user_online_payments $query = "UPDATE user_online_payments SET status = 'Paid', payment_amount = balance_owing, reference = '$txnId', trx_fee = $fee, completed_time = $ptime WHERE record_num = $TRXnum"; db_query($query); // Get school info for timezone $schoolRow = db_fetch_assoc(db_query("SELECT * FROM schools WHERE record_num = $p_school_num")); $timezone = $schoolRow['timezone'] ?? 'Canada/Pacific'; if (function_exists('mapTimeZone')) { date_default_timezone_set(mapTimeZone($timezone)); } $today = date("Y-m-d", $ptime); $trx_time = date("Y-m-d H:i:s", $ptime); // Update hotlunch_order_header - mark orders as paid $query = "SELECT hloh.* FROM hotlunch_order_header as hloh, people as p " . "WHERE hloh.school_num = $p_school_num " . "AND ordered_by_num = p.record_num " . "AND p.user_num = $p_user_num " . "AND hloh.status NOT IN ('Paid','Complimentary','Concession')"; $orders = db_query($query); $order_payments = ""; $snum = 0; if (db_num_rows($orders) > 0) { while ($row = db_fetch_array($orders)) { $onum = $row['record_num']; $ototal = $row['order_total']; $opaid = $row['amount_paid']; $snum = $row['schedule_num']; $amt = number_format($ototal - $opaid, 2, '.', ''); if (strlen($order_payments) > 0) $order_payments .= "|"; $order_payments .= "{" . $onum . ":" . $amt . "}"; $query = "UPDATE hotlunch_order_header SET amount_paid = order_total, status = 'Paid', paid_date = '$today', payment_method = 'PayPal' WHERE record_num = $onum"; db_query($query); } } // Check for duplicate entry in user_account $query = "SELECT * FROM user_account WHERE school_num = $p_school_num AND user_num = $p_user_num AND payment_reference = '$txnId'"; $existing = db_query($query); if (db_num_rows($existing) == 0) { // Post payment to user_account $paymentAmount = floatval($amount) * -1; $query = "INSERT INTO user_account (school_num, user_num, schedule_num, transaction_datetime, transaction_type, note, transaction_amount, transaction_fee, payment_method, payment_reference, order_payments, deleted, entered_time) " . "VALUES ($p_school_num, $p_user_num, $snum, '$trx_time', 'Payment', 'PayPal Checkout Payment', $paymentAmount, $fee, 'PayPal', '$txnId', '$order_payments', 'N', $ptime)"; db_query($query); // Close all open transactions $query = "UPDATE user_account SET transaction_status = 'Closed' WHERE school_num = $p_school_num AND user_num = $p_user_num AND transaction_status != 'Closed'"; db_query($query); // Reset user flags $query = "UPDATE users SET trx_status = NULL, can_order = 'Yes' WHERE school_num = $p_school_num AND record_num = $p_user_num AND can_order = 'Balance'"; db_query($query); } } } // Clear session variables unset($_SESSION['paypal_order_id']); unset($_SESSION['paypal_order_trxnum']); unset($_SESSION['paypal_order_amount']); // Return success response echo json_encode([ 'success' => true, 'transactionId' => $txnId, 'amount' => $amount, 'currency' => $currency, 'status' => $captureResult['status'], 'payerEmail' => $payerEmail, 'payerName' => trim($payerName) ]); } catch (Exception $e) { http_response_code(500); echo json_encode([ 'success' => false, 'error' => $e->getMessage() ]); } captureOrder($orderId); // Check capture status if ($captureResult['status'] !== 'COMPLETED') { throw new Exception('Payment was not completed. Status: ' . $captureResult['status']); } // Extract payment details $purchaseUnit = $captureResult['purchase_units'][0] ?? []; $capture = $purchaseUnit['payments']['captures'][0] ?? []; $txnId = $capture['id'] ?? $orderId; $amount = $capture['amount']['value'] ?? 0; $currency = $capture['amount']['currency_code'] ?? ''; $customId = $purchaseUnit['custom_id'] ?? $expectedTrxnum; // This is your TRXnum $payerEmail = $captureResult['payer']['email_address'] ?? ''; $payerName = ($captureResult['payer']['name']['given_name'] ?? '') . ' ' . ($captureResult['payer']['name']['surname'] ?? ''); // Get fee info if available $fee = 0; if (isset($capture['seller_receivable_breakdown']['paypal_fee']['value'])) { $fee = floatval($capture['seller_receivable_breakdown']['paypal_fee']['value']); } // Validate amount matches what we expected if ($expectedAmount && abs(floatval($amount) - floatval($expectedAmount)) > 0.01) { // Log this discrepancy but still process (PayPal has already captured) error_log("PayPal amount mismatch: expected $expectedAmount, got $amount"); } // ========================================================================= // UPDATE YOUR DATABASE // This follows the same pattern as ppPayment.php but adapted for REST API // ========================================================================= $TRXnum = intval($customId); $ptime = time(); $time = date("Y-m-d H:i:s", $ptime); $trxID = null; // Will hold record_num from user_paypal_transactions if ($TRXnum > 0 && function_exists('db_query')) { // Get user info from online payments record $query = "SELECT * FROM user_online_payments WHERE record_num = $TRXnum"; $r = db_query($query); if (db_num_rows($r) == 1) { $paymentRow = db_fetch_assoc($r); $p_school_num = $paymentRow['school_num']; $p_user_num = $paymentRow['user_num']; // ===================================================================== // INSERT INTO user_paypal_transactions (same as ppPayment.php) // ===================================================================== $payment_type = 'instant'; $payment_status = $captureResult['status']; // COMPLETED // Check for duplicate in user_paypal_transactions $escapedTxnId = function_exists('db_escape_string') ? db_escape_string($txnId) : addslashes($txnId); $dupQuery = "SELECT * FROM user_paypal_transactions WHERE school_num = $p_school_num AND payment_type = '$payment_type' AND payment_status = '$payment_status' AND txn_id = '$escapedTxnId' AND current_year != 'N'"; $dupResult = db_query($dupQuery); if (db_num_rows($dupResult) == 0) { // Build insert for user_paypal_transactions following ppPayment.php pattern $escPayerEmail = function_exists('db_escape_string') ? db_escape_string($payerEmail) : addslashes($payerEmail); $escPayerName = function_exists('db_escape_string') ? db_escape_string($payerName) : addslashes($payerName); $firstName = function_exists('db_escape_string') ? db_escape_string($captureResult['payer']['name']['given_name'] ?? '') : addslashes($captureResult['payer']['name']['given_name'] ?? ''); $lastName = function_exists('db_escape_string') ? db_escape_string($captureResult['payer']['name']['surname'] ?? '') : addslashes($captureResult['payer']['name']['surname'] ?? ''); $receiverEmail = function_exists('db_escape_string') ? db_escape_string($captureResult['purchase_units'][0]['payee']['email_address'] ?? '') : addslashes($captureResult['purchase_units'][0]['payee']['email_address'] ?? ''); $trxInsertQuery = "INSERT INTO user_paypal_transactions (school_num, user_num, trx_num, posting_time, ptime, error_handled, transaction_subject, payment_date, txn_type, first_name, last_name, payer_email, payer_status, item_name, business, receiver_email, mc_currency, mc_gross, mc_fee, reference, payment_type, payment_status, pending_reason, txn_id, receipt_id, current_year, posting_result, posting_message) VALUES ($p_school_num, $p_user_num, $TRXnum, '$time', $ptime, 'N', 'PayPal Checkout Payment', '$time', 'capture', '$firstName', '$lastName', '$escPayerEmail', 'verified', 'Order Payment', '', '$receiverEmail', '$currency', $amount, $fee, '$escapedTxnId', '$payment_type', '$payment_status', '', '$escapedTxnId', '', 'Y', 'Posted', 'Payment processed ok')"; db_query($trxInsertQuery); $trxID = function_exists('db_insert_id') ? db_insert_id() : null; } // Update user_online_payments $query = "UPDATE user_online_payments SET status = 'Paid', payment_amount = balance_owing, reference = '$txnId', trx_fee = $fee, completed_time = $ptime WHERE record_num = $TRXnum"; db_query($query); // Get school info for timezone $schoolRow = db_fetch_assoc(db_query("SELECT * FROM schools WHERE record_num = $p_school_num")); $timezone = $schoolRow['timezone'] ?? 'Canada/Pacific'; if (function_exists('mapTimeZone')) { date_default_timezone_set(mapTimeZone($timezone)); } $today = date("Y-m-d", $ptime); $trx_time = date("Y-m-d H:i:s", $ptime); // Update hotlunch_order_header - mark orders as paid $query = "SELECT hloh.* FROM hotlunch_order_header as hloh, people as p " . "WHERE hloh.school_num = $p_school_num " . "AND ordered_by_num = p.record_num " . "AND p.user_num = $p_user_num " . "AND hloh.status NOT IN ('Paid','Complimentary','Concession')"; $orders = db_query($query); $order_payments = ""; $snum = 0; if (db_num_rows($orders) > 0) { while ($row = db_fetch_array($orders)) { $onum = $row['record_num']; $ototal = $row['order_total']; $opaid = $row['amount_paid']; $snum = $row['schedule_num']; $amt = number_format($ototal - $opaid, 2, '.', ''); if (strlen($order_payments) > 0) $order_payments .= "|"; $order_payments .= "{" . $onum . ":" . $amt . "}"; $query = "UPDATE hotlunch_order_header SET amount_paid = order_total, status = 'Paid', paid_date = '$today', payment_method = 'PayPal' WHERE record_num = $onum"; db_query($query); } } // Check for duplicate entry in user_account $query = "SELECT * FROM user_account WHERE school_num = $p_school_num AND user_num = $p_user_num AND payment_reference = '$txnId'"; $existing = db_query($query); if (db_num_rows($existing) == 0) { // Post payment to user_account $paymentAmount = floatval($amount) * -1; $query = "INSERT INTO user_account (school_num, user_num, schedule_num, transaction_datetime, transaction_type, note, transaction_amount, transaction_fee, payment_method, payment_reference, order_payments, deleted, entered_time) " . "VALUES ($p_school_num, $p_user_num, $snum, '$trx_time', 'Payment', 'PayPal Checkout Payment', $paymentAmount, $fee, 'PayPal', '$txnId', '$order_payments', 'N', $ptime)"; db_query($query); // Close all open transactions $query = "UPDATE user_account SET transaction_status = 'Closed' WHERE school_num = $p_school_num AND user_num = $p_user_num AND transaction_status != 'Closed'"; db_query($query); // Reset user flags $query = "UPDATE users SET trx_status = NULL, can_order = 'Yes' WHERE school_num = $p_school_num AND record_num = $p_user_num AND can_order = 'Balance'"; db_query($query); } } } // Clear session variables unset($_SESSION['paypal_order_id']); unset($_SESSION['paypal_order_trxnum']); unset($_SESSION['paypal_order_amount']); // Return success response echo json_encode([ 'success' => true, 'transactionId' => $txnId, 'amount' => $amount, 'currency' => $currency, 'status' => $captureResult['status'], 'payerEmail' => $payerEmail, 'payerName' => trim($payerName) ]); } catch (Exception $e) { http_response_code(500); echo json_encode([ 'success' => false, 'error' => $e->getMessage() ]); }