Search code examples
phpcurlpaypal

Paypal v2 PHP curl Capture Order


My curl seems to be malformed or the header is missing some elements when I try to run it with PHP.

I have run this curl successfully in Postman:

curl -v -X POST https://api-m.paypal.com/v2/checkout/orders/MyOrderId/capture \
-H "Content-Type: application/json" \
-H "Authorization: Bearer MyToken" \
-H "PayPal-Request-Id: MyRequestId" \
-H "Prefer: return=representation" \
-H "PayPal-Client-Metadata-Id: MyMetaDataId"

But when I want to run it in PHP, it tells me the header is missing information.

Here is the PHP code:

<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);

require_once 'generateAccessToken.php';

$orderID = $_GET['orderID'] ?? '';

if (empty($orderID)) {
    http_response_code(400);
    echo json_encode(['error' => 'Missing order ID']);
    exit;
}

$accessToken = generateAccessToken();
if (empty($accessToken)) {
    http_response_code(500);
    echo json_encode(['error' => 'Failed to obtain access token']);
    exit;
}

$url = "https://api-m.paypal.com/v2/checkout/orders/{$orderID}/capture";

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => $url,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => array(
    "Authorization: Bearer " . $accessToken,
    "Content-Type: application/json",
    "PayPal-Request-Id: " . uniqid(),
    "Prefer: return=representation",
    "PayPal-Client-Metadata-Id: " . time() . "-" . $orderID
  ),
));

$response = curl_exec($curl);
$httpStatusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$curlError = curl_error($curl);

curl_close($curl);

if ($curlError) {
    echo json_encode(['error' => 'cURL Error: ' . $curlError]);
    exit;
}

if ($response === false) {
    http_response_code(500);
    echo json_encode(['error' => 'Failed to capture order. No response data from PayPal.']);
    exit;
}

$responseData = json_decode($response, true);

if (!$responseData) {
    http_response_code(500);
    echo json_encode(['error' => 'Failed to capture order. Invalid JSON response.']);
    exit;
}

if (isset($responseData['id']) && isset($responseData['status']) && $responseData['status'] == 'COMPLETED') {
    echo json_encode(['success' => true, 'id' => $responseData['id'], 'status' => $responseData['status']]);
} else {
    http_response_code($httpStatusCode);
    echo json_encode(['error' => 'Failed to capture order.', 'details' => $responseData]);
}
?>

Here is the error I'm getting:

HTTP/1.1 400 Invalid Request Connection: close Content-Length: 28 content-type: text/plain; charset=utf-8 x-served-by: cache-lon420138 broken content-length header

Solution

  • I actually fixed the problem lol. I took the

        curl -v -X POST https://api-m.paypal.com/v2/checkout/orders/MyOrderId/capture
    -H "Content-Type: application/json"
    -H "Authorization: Bearer MyToken"
    -H "PayPal-Request-Id: MyRequestId"
    -H "Prefer: return=representation"
    -H "PayPal-Client-Metadata-Id: MyMetaDataId"
    

    command, I posted it in postman, and I converted it to PHP -cURL, and I took that whole command, and I ran it, and I eventually got a success!!!

    Here is how the source code looks:

    <?php
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    
    require_once 'generateAccessToken.php';
    
    $orderID = $_GET['orderID'] ?? '';
    
    if (empty($orderID)) {
        http_response_code(400);
        echo json_encode(['error' => 'Missing order ID']);
        exit;
    }
    
    $accessToken = generateAccessToken();
    if (empty($accessToken)) {
        http_response_code(500);
        echo json_encode(['error' => 'Failed to obtain access token']);
        exit;
    }
    
    $url = "https://api-m.paypal.com/v2/checkout/orders/{$orderID}/capture";
    $requestId = uniqid();
    $uniqueOrderID = $orderID; // This should ideally come from your order system.
    $paypalClientMetadataId = time() . "-" . $uniqueOrderID;
    
    $curl = curl_init();
    
    curl_setopt_array($curl, array(
      CURLOPT_URL => $url,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_ENCODING => '',
      CURLOPT_MAXREDIRS => 10,
      CURLOPT_TIMEOUT => 0,
      CURLOPT_FOLLOWLOCATION => true,
      CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
      CURLOPT_CUSTOMREQUEST => 'POST',
      CURLOPT_HTTPHEADER => array(
        'Content-Type: application/json',
        'Authorization: Bearer '.$accessToken,
        'PayPal-Request-Id: '.$requestId,
        'Prefer: return=representation',
        'PayPal-Client-Metadata-Id: '.$paypalClientMetadataId
      ),
    ));
    
    $response = curl_exec($curl);
    
    curl_close($curl);
    
    
    if ($response === false) {
        http_response_code(500);
        echo json_encode(['error' => 'Failed to capture order. No response data from PayPal.']);
        exit;
    }
    
    $responseData = json_decode($response, true);
    
    if (!$responseData) {
        http_response_code(500);
        echo json_encode(['error' => 'Failed to capture order. Invalid JSON response.']);
        exit;
    }
    
    if (isset($responseData['id']) && isset($responseData['status']) && $responseData['status'] == 'COMPLETED') {
        echo json_encode(['success' => true, 'id' => $responseData['id'], 'status' => $responseData['status']]);
    } else {
        http_response_code($httpStatusCode);
        echo json_encode(['error' => 'Failed to capture order.', 'details' => $responseData]);
    }
    ?>