Question

I'm very new to paypal api, I've followed this tutorial and adapted the code to my needs.

I'd like to make a basic Authorization & Capture in 3 steps but I always fail in capturing

  1. Customer land to paypal_pay_redirect.php for login into paypal and make a paymet
  2. The payment is fine and we land to paypal_success.php, here I request the Authorization and keep the TRANSACTIONID for the next step
  3. paypal_capture.php I use the transactionid for capture the payment but I always get "10609: Transaction id is invalid"

here the code, where is the mistake?

thanks

paypal_lib.php

<?php
  // code from http://coding.smashingmagazine.com/2011/09/05/getting-started-with-the-paypal-api/
class Paypal {
  /**
   * Last error message(s)
   * @var array
   */
  protected $_errors = array();

  /**
   * API Credentials
   * Use the correct credentials for the environment in use (Live / Sandbox)
   * @var array
   */
  protected $_credentials = array(
                  'USER' => 'xxxxxxxxxxxxxxxxxxxx',
                  'PWD' => 'xxxxxxxxxxxxx',
                  'SIGNATURE' => 'xxxxxxxxxxxxxxxxxxxxxxxxx'
                  );
  /**
   * API endpoint
   * Live - https://api-3t.paypal.com/nvp
   * Sandbox - https://api-3t.sandbox.paypal.com/nvp
   * @var string
   */
  protected $_endPoint = 'https://api-3t.sandbox.paypal.com/nvp';

  /**
   * API Version
   * @var string
   */
  protected $_version = '74.0';

  /**
   * Make API request
   *
   * @param string $method string API method to request
   * @param array $params Additional request parameters
   * @return array / boolean Response array / boolean false on failure
   */
  public function request($method,$params = array()) {
    $this -> _errors = array();
    if( empty($method) ) { //Check if API method is not empty
      $this -> _errors = array('API method is missing');
      return false;
    }

    //Our request parameters
    $requestParams = array_merge(
                 array(
                       'METHOD' => $method,
                       'VERSION' => $this -> _version
                       ),
                 $this -> _credentials
                 );

    //Building our NVP string
    $request = http_build_query(array_merge($requestParams, $params));

    //cURL settings
    $curlOptions = array (
              CURLOPT_URL => $this -> _endPoint,
              CURLOPT_VERBOSE => 1,
              CURLOPT_SSL_VERIFYPEER => true,
              CURLOPT_SSL_VERIFYHOST => 2,
              CURLOPT_RETURNTRANSFER => 1,
              CURLOPT_POST => 1,
              CURLOPT_POSTFIELDS => $request
              );

    $ch = curl_init();
    curl_setopt_array($ch,$curlOptions);

    //Sending our request - $response will hold the API response
    $response = curl_exec($ch);

    //Checking for cURL errors
    if (curl_errno($ch)) {
      $this -> _errors = curl_error($ch);
      curl_close($ch);
      return false;
      //Handle errors
    } else {
      curl_close($ch);
      $responseArray = array();
      parse_str($response,$responseArray); // Break the NVP string to an array
      return $responseArray;
    }
  }
}

?>

paypal_pay_redirect.php

<?php
require("paypal_lib.php");

//Our request parameters
$requestParams = array(
               'RETURNURL' => 'https://www.domain.com/paypal_success.php',
               'CANCELURL' => 'https://www.domain.com/paypal_fail.php'
               );

$orderParams = array(
             'PAYMENTREQUEST_0_AMT' => "57.00",
             'PAYMENTREQUEST_0_SHIPPINGAMT' => '0',
             'PAYMENTREQUEST_0_CURRENCYCODE' => 'EUR',
   'PAYMENTREQUEST_0_ITEMAMT' => "57.00"
             );

$item = array(
          'L_PAYMENTREQUEST_0_NAME0' => 'xxxxxxxxxx',
          'L_PAYMENTREQUEST_0_DESC0' => 'xxxxxxxxxx',
          'L_PAYMENTREQUEST_0_AMT0' => "57.00",
   'L_PAYMENTREQUEST_0_QTY0' => '1'
          );

$paypal = new Paypal();
$response = $paypal -> request('SetExpressCheckout',$requestParams + $orderParams + $item);
if(is_array($response) && $response['ACK'] == 'Success') { //Request successful
  $token = $response['TOKEN'];
  header( 'Location: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . urlencode($token) );
 }


?>

paypal_success.php

<?php
require("paypal_lib.php");

if( isset($_GET['token']) && !empty($_GET['token']) ) { // Token parameter exists
  // Get checkout details, including buyer information.
  // We can save it for future reference or cross-check with the data we have
  $paypal = new Paypal();
  $checkoutDetails = $paypal -> request('GetExpressCheckoutDetails', array('TOKEN' => $_GET['token']));

  // Complete the checkout transaction
  $requestParams = array(
             'TOKEN' => $_GET['token'],
             'PAYMENTACTION' => 'Authorization',
             'PAYERID' => $_GET['PayerID'],
             'PAYMENTREQUEST_0_AMT' => '57', // Same amount as in the original request
             'PAYMENTREQUEST_0_CURRENCYCODE' => 'EUR' // Same currency as the original request
             );

  $response = $paypal -> request('DoExpressCheckoutPayment',$requestParams);
  if( is_array($response) && $response['ACK'] == 'Success') { // Payment successful
    // We'll fetch the transaction ID for internal bookkeeping
    $transactionId = $response['PAYMENTINFO_0_TRANSACTIONID'];
    echo "OK id: ".$transactionId;
    var_dump($response);
  }

 var_dump($checkoutDetails);

 }
?>

paypal_capture.php

<?php
require("paypal_lib.php");

$paypal = new Paypal();

// Complete the checkout transaction
$requestParams = array(
               'AMT' => '57.00',
               'AUTHORIZATIONID' => 'xxxxxxxxxxxxxxxxxxx', //what I get in paypal_success.php
               'CURRENCYCODE' => 'EUR',
               'COMPLETETYPE' => 'Complete', // Same amount as in the original request
               );

$response = $paypal -> request('DoCapture',$requestParams);

var_dump($response);

?>
Was it helpful?

Solution

Two things:

First, in paypal_pay_redirect.php, add PAYMENTREQUEST_0_PAYMENTACTION => 'Authorization' to $orderParams.

Second, in paypal_success.php, change PAYMENTACTION TO PAYMENTREQUEST_0_PAYMENTACTION.

Here's why:

In your SetExpressCheckout call, if you don't set PAYMENTREQUEST_0_PAYMENTACTION, PayPal assumes that it will be Sale. And if this is set to Sale in your SetExpressCheckout call, then PayPal will only allow you to set it to Sale on your DoExpressCheckoutPayment call.

Additionally, in your DoExpressCheckoutPayment call, you're mixing new and old-style variable names. (Some variables, such as PAYMENTACTION, were renamed when PayPal introduced parallel payments for Express Checkout. PAYMENTACTION is the old style; PAYMENTREQUEST_0_PAYMENTACTION is the new style.) When you mix old-style and new-style names like this, PayPal recognizes variables using one style, and ignores the other. In your case, PAYMENTREQUEST_0_AMT and PAYMENTREQUEST_0_CURRENCYCODE are being recognized, but PAYMENTACTION is being ignored.

The combination of these two factors means that your transaction is most likely being run as a Sale transaction, not an Authorization. Since you can't capture against a Sale transaction (since it's technically already captured), PayPal responds by saying that the transaction ID is invalid.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top