"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) { $game_id = $_POST["game_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 || $response_code === 201) { header("Content-Type: application/json"); $order_data = json_decode($response); http_response_code($response_code); $transaction_id = $order_data->purchase_units[0]->payments->captures[0]->id ?? ($order_data->purchase_units[0]->payments->authorizations[0]->id ?? "_"); update_submission($game_id, $transaction_id); echo $response; die(); } else { header("Content-Type: application/json"); http_response_code($response_code); echo $response; die(); } } /** * @param string game_id * @param string transaction_id */ function update_submission($game_id, $transaction_id) { global $db; $sql = "UPDATE submissions SET transaction_id = :transaction_id WHERE game_id = :game_id AND member_id = :member_id"; $stmt = $db["data"]->prepare($sql); $stmt->execute([ "game_id" => $game_id, "member_id" => $_SESSION["account"]->id, "transaction_id" => $transaction_id, ]); } 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(); }