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();
 | 
						|
}
 |