410 lines
18 KiB
PHP
410 lines
18 KiB
PHP
<?php
|
|
/**
|
|
* PayPal Checkout - Capture Payment Endpoint
|
|
*
|
|
* Called by the PayPal JS SDK after user approves payment.
|
|
* Captures the payment and updates your database.
|
|
*
|
|
* Returns JSON with transaction details or error
|
|
*/
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
// Start session if not already started
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
session_start();
|
|
}
|
|
|
|
// Include database and required files
|
|
if (file_exists(__DIR__ . '/db.php')) {
|
|
require_once __DIR__ . '/db.php';
|
|
}
|
|
|
|
if (file_exists(__DIR__ . '/include/school-functions.php')) {
|
|
include_once __DIR__ . '/include/school-functions.php';
|
|
}
|
|
|
|
if (file_exists(__DIR__ . '/include/date-time.php')) {
|
|
include_once __DIR__ . '/include/date-time.php';
|
|
}
|
|
|
|
require_once __DIR__ . '/paypal_checkout_api.php';
|
|
|
|
try {
|
|
// Get the order ID from the request
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$orderId = $input['orderID'] ?? $_POST['orderID'] ?? null;
|
|
|
|
if (!$orderId) {
|
|
throw new Exception('Order ID is required');
|
|
}
|
|
|
|
// Verify this is the order we created (prevent replay attacks)
|
|
if (!isset($_SESSION['paypal_order_id']) || $_SESSION['paypal_order_id'] !== $orderId) {
|
|
throw new Exception('Order ID mismatch. Please try again.');
|
|
}
|
|
|
|
$expectedTrxnum = $_SESSION['paypal_order_trxnum'] ?? null;
|
|
$expectedAmount = $_SESSION['paypal_order_amount'] ?? null;
|
|
|
|
// Capture the payment
|
|
$paypal = new PayPalCheckoutAPI();
|
|
$captureResult = $paypal->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()
|
|
]);
|
|
}
|
|
<?php
|
|
/**
|
|
* PayPal Checkout - Capture Payment Endpoint
|
|
*
|
|
* Called by the PayPal JS SDK after user approves payment.
|
|
* Captures the payment and updates your database.
|
|
*
|
|
* Returns JSON with transaction details or error
|
|
*/
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
// Start session if not already started
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
session_start();
|
|
}
|
|
|
|
// Include database and required files
|
|
if (file_exists(__DIR__ . '/db.php')) {
|
|
require_once __DIR__ . '/db.php';
|
|
}
|
|
|
|
if (file_exists(__DIR__ . '/include/school-functions.php')) {
|
|
include_once __DIR__ . '/include/school-functions.php';
|
|
}
|
|
|
|
if (file_exists(__DIR__ . '/include/date-time.php')) {
|
|
include_once __DIR__ . '/include/date-time.php';
|
|
}
|
|
|
|
require_once __DIR__ . '/paypal_checkout_api.php';
|
|
|
|
try {
|
|
// Get the order ID from the request
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$orderId = $input['orderID'] ?? $_POST['orderID'] ?? null;
|
|
|
|
if (!$orderId) {
|
|
throw new Exception('Order ID is required');
|
|
}
|
|
|
|
// Verify this is the order we created (prevent replay attacks)
|
|
if (!isset($_SESSION['paypal_order_id']) || $_SESSION['paypal_order_id'] !== $orderId) {
|
|
throw new Exception('Order ID mismatch. Please try again.');
|
|
}
|
|
|
|
$expectedTrxnum = $_SESSION['paypal_order_trxnum'] ?? null;
|
|
$expectedAmount = $_SESSION['paypal_order_amount'] ?? null;
|
|
|
|
// Capture the payment
|
|
$paypal = new PayPalCheckoutAPI();
|
|
$captureResult = $paypal->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()
|
|
]);
|
|
}
|