80 lines
2.8 KiB
PHP
80 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once dirname(__DIR__) . '/includes/bootstrap.php';
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
$user = website_current_user();
|
|
if (!$user) {
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'login_required']);
|
|
exit;
|
|
}
|
|
|
|
$input = json_decode((string)file_get_contents('php://input'), true);
|
|
$invoiceId = (int)($input['invoice_id'] ?? 0);
|
|
$paypalOrderId = trim((string)($input['order_id'] ?? ''));
|
|
$config = website_paypal_config();
|
|
$db = website_db();
|
|
if (!$config['enabled'] || $paypalOrderId === '' || !$db instanceof mysqli) {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'invalid_request']);
|
|
exit;
|
|
}
|
|
|
|
$invoiceTable = website_table('billing_invoices');
|
|
$uid = (int)$user['user_id'];
|
|
$stmt = $db->prepare("SELECT * FROM `{$invoiceTable}` WHERE `invoice_id` = ? AND `user_id` = ? AND `status` = 'due' LIMIT 1");
|
|
$stmt->bind_param('ii', $invoiceId, $uid);
|
|
$stmt->execute();
|
|
$invoice = $stmt->get_result()->fetch_assoc();
|
|
$stmt->close();
|
|
if (!is_array($invoice) || (string)($invoice['paypal_order_id'] ?? '') !== $paypalOrderId) {
|
|
http_response_code(404);
|
|
echo json_encode(['error' => 'invoice_not_found']);
|
|
exit;
|
|
}
|
|
|
|
$access = website_paypal_oauth($config);
|
|
if (!$access) {
|
|
http_response_code(502);
|
|
echo json_encode(['error' => 'paypal_oauth_failed']);
|
|
exit;
|
|
}
|
|
|
|
$ch = curl_init(website_paypal_api_base($config) . '/v2/checkout/orders/' . rawurlencode($paypalOrderId) . '/capture');
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $access],
|
|
CURLOPT_TIMEOUT => 30,
|
|
]);
|
|
$response = curl_exec($ch);
|
|
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if (($http !== 200 && $http !== 201) || !is_string($response)) {
|
|
website_log('PayPal capture failed for invoice ' . $invoiceId);
|
|
http_response_code(502);
|
|
echo json_encode(['error' => 'paypal_capture_failed']);
|
|
exit;
|
|
}
|
|
|
|
$json = json_decode($response, true);
|
|
$status = (string)($json['status'] ?? '');
|
|
$capture = $json['purchase_units'][0]['payments']['captures'][0] ?? [];
|
|
$captureId = (string)($capture['id'] ?? '');
|
|
$payerEmail = (string)($json['payer']['email_address'] ?? '');
|
|
$paidAmount = (float)($capture['amount']['value'] ?? 0);
|
|
$currency = (string)($capture['amount']['currency_code'] ?? '');
|
|
|
|
if ($status !== 'COMPLETED' || $captureId === '' || abs($paidAmount - (float)$invoice['amount']) > 0.01 || $currency !== (string)$invoice['currency']) {
|
|
http_response_code(409);
|
|
echo json_encode(['error' => 'payment_not_verified']);
|
|
exit;
|
|
}
|
|
|
|
website_mark_invoice_paid($invoiceId, 'paypal', $paypalOrderId, $captureId, $payerEmail, ['paypal_status' => $status]);
|
|
echo json_encode(['status' => 'COMPLETED', 'invoice_id' => $invoiceId]);
|