208 lines
6.7 KiB
PHP
208 lines
6.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Generate an OAuth 2.0 access token for authenticating with PayPal REST APIs.
|
|
*
|
|
* @see https://developer.paypal.com/api/rest/authentication/
|
|
* @return string|null
|
|
*/
|
|
function generateAccessToken()
|
|
{
|
|
if (!PAYPAL_CLIENT_ID || !PAYPAL_CLIENT_SECRET) {
|
|
throw new \Exception("MISSING_API_CREDENTIALS");
|
|
}
|
|
|
|
$url = PAYPAL_BASE_URL . "/v1/oauth2/token";
|
|
$payload = [
|
|
"grant_type" => "client_credentials",
|
|
];
|
|
$ch = curl_init();
|
|
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_POST, 1);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
|
|
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
"Content-Type: application/x-www-form-urlencoded",
|
|
"Authorization: Basic " .
|
|
base64_encode(PAYPAL_CLIENT_ID . ":" . PAYPAL_CLIENT_SECRET),
|
|
// Uncomment one of these to force an error for negative testing (in sandbox mode only).
|
|
]);
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
$response = curl_exec($ch);
|
|
$response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
// Further processing ...
|
|
if ($response_code === 200) {
|
|
return json_decode($response)->access_token;
|
|
} else {
|
|
header("Content-Type: application/json");
|
|
http_response_code($response_code);
|
|
echo $response;
|
|
die();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create an order to start the transaction.
|
|
*
|
|
* @see https://developer.paypal.com/docs/api/orders/v2/#orders_create
|
|
* @param array $cart
|
|
* @return array
|
|
*/
|
|
function createOrder($cart)
|
|
{
|
|
try {
|
|
$access_token = generateAccessToken();
|
|
if (!$access_token) {
|
|
http_response_code(500);
|
|
header("Content-Type: application/json");
|
|
echo json_encode(["error" => "Failed to obtain access token."]);
|
|
die();
|
|
}
|
|
|
|
$url = PAYPAL_BASE_URL . "/v2/checkout/orders";
|
|
|
|
$payload = [
|
|
"intent" => "CAPTURE",
|
|
"purchase_units" => [
|
|
[
|
|
"amount" => [
|
|
"currency_code" => $cart[0]->unit_amount->currency_code,
|
|
"value" => $cart[0]->unit_amount->value,
|
|
"breakdown" => [
|
|
"item_total" => [
|
|
"currency_code" =>
|
|
$cart[0]->unit_amount->currency_code,
|
|
"value" => $cart[0]->unit_amount->value,
|
|
],
|
|
],
|
|
],
|
|
"items" => [
|
|
[
|
|
"name" => $cart[0]->description,
|
|
"description" => $cart[0]->description,
|
|
"unit_amount" => [
|
|
"currency_code" =>
|
|
$cart[0]->unit_amount->currency_code,
|
|
"value" => $cart[0]->unit_amount->value,
|
|
],
|
|
"quantity" => 1,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$ch = curl_init();
|
|
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_POST, 1);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
|
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
"Content-Type: application/json",
|
|
"Authorization: Bearer $access_token",
|
|
]);
|
|
// Uncomment one of these to force an error for negative testing (in sandbox mode only).
|
|
// Documentation: https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/
|
|
// 'PayPal-Mock-Response' => '{"mock_application_codes": "MISSING_
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
$response = curl_exec($ch);
|
|
$response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
// Further processing ...
|
|
if ($response_code === 200) {
|
|
header("Content-Type: application/json");
|
|
http_response_code($response_code);
|
|
echo $response;
|
|
die();
|
|
} else {
|
|
header("Content-Type: application/json");
|
|
http_response_code($response_code);
|
|
echo $response;
|
|
die();
|
|
}
|
|
} catch (\Exception $error) {
|
|
header("Content-Type: application/json");
|
|
http_response_code(500);
|
|
echo json_encode(["error" => "Failed to create order."]);
|
|
die();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Capture payment for the given order
|
|
*
|
|
* @see https://developer.paypal.com/docs/api/orders/v2/#orders_capture
|
|
* @param array $cart
|
|
* @return array
|
|
*/
|
|
function captureOrder($order_id)
|
|
{
|
|
$url = PAYPAL_BASE_URL . "/v2/checkout/orders/{$order_id}/capture";
|
|
// Http::fake(function ($request) {
|
|
// // Capture and log request headers
|
|
// $headers = $request->headers();
|
|
|
|
// // Log headers for inspection
|
|
// \Log::info('Captured Request Headers', $headers);
|
|
|
|
// return Http::response('', 200, [
|
|
// 'X-Custom-Response-Header' => 'HeaderValue'
|
|
// ]);
|
|
// });
|
|
$auth = base64_encode(PAYPAL_CLIENT_ID . ":" . PAYPAL_CLIENT_SECRET);
|
|
|
|
$ch = curl_init();
|
|
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_POST, 1);
|
|
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
"Content-Type: application/json",
|
|
"Authorization: Basic $auth",
|
|
]);
|
|
// Uncomment one of these to force an error for negative testing (in sandbox mode only).
|
|
// Documentation: https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/
|
|
// 'PayPal-Mock-Response' => '{"mock_application_codes": "MISSING_
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
$response = curl_exec($ch);
|
|
$response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
// Further processing ...
|
|
if ($response_code === 200) {
|
|
header("Content-Type: application/json");
|
|
http_response_code($response_code);
|
|
echo $response;
|
|
die();
|
|
} else {
|
|
header("Content-Type: application/json");
|
|
http_response_code($response_code);
|
|
echo $response;
|
|
die();
|
|
}
|
|
}
|
|
|
|
if (
|
|
$_SERVER["REQUEST_METHOD"] === "POST" &&
|
|
$_SERVER["REQUEST_URI"] === "/api/orders"
|
|
) {
|
|
$body = file_get_contents("php://input");
|
|
$cart = json_decode($body)->cart;
|
|
createOrder($cart);
|
|
}
|
|
|
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
|
$order_id = substr($_SERVER["REQUEST_URI"], 12, 17);
|
|
captureOrder($order_id);
|
|
}
|
|
|
|
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
|
|
http_response_code(404);
|
|
die();
|
|
}
|