1

On my site user can fill their order basket with items.

Once this is finished they can click the checkout button.

I want them to checkout using PayPal.

Once the user click on the checkout button the user is redirected to PayPal and sees an overview of the products to pay for.

If the user goes through the payment process the user is redirected to my success page.

However I expect the success page to also receive the transaction id of the payment but paypal only sends back a token and a payerid.

My checkout form looks like this:

<form action="/en/checkout">
  <input type="submit" name="submit" value="Checkout">
</form>

My code that does the checkout is:

function checkoutAction()
{
    $request = $this->getRequest();

    require_once(LIB_PATH.'/MFW/Paypal/Flows/Paypal_NVP.php');
    $paypal_nvp = new MFW_Paypal_NVP();

    // this should normally be filled by looping though the basket items
    $data = array('L_PAYMENTREQUEST_0_NAME0'=>'Single License',
                  'L_PAYMENTREQUEST_0_NUMBER0'=>'1111-2222-3333-4444-5555-6666-7777-8888',
                  'L_PAYMENTREQUEST_0_AMT0'=>39.99, // or enterprise 299.00
                  'L_PAYMENTREQUEST_0_QTY0'=>1,
                  );

    $_SESSION['Payment_Amount'] = 39.99;

    $result = $paypal_nvp->CallShortcutExpressCheckout(59.98, $data);

    $ack = strtoupper($result['ACK']);
    if($ack == 'SUCCESS' || $ack == 'SUCCESSWITHWARNING') {
        $paypal->RedirectToPayPal($result['TOKEN']);
        exit();
    }
}

The code in the Paypal_NCP class:

function generate_nvp_string($total_value, $data = array())
{
    $params = array('PAYMENTREQUEST_0_AMT'=>$total_value,
                    'PAYMENTREQUEST_0_PAYMENTACTION'=>$this->payment_type,
                    'RETURNURL'=>$this->return_url,
                    'CANCELURL'=>$this->cancel_url,
                    'PAYMENTREQUEST_0_CURRENCYCODE'=>$this->currency,
                    );

    $params = array_merge($params, $data);

    $nvp_string = '';
    foreach($params as $name => $value) {
        $nvp_string.= '&'.$name.'='.$value;
    }

    // example string
    // &PAYMENTREQUEST_0_AMT=39.99&PAYMENTREQUEST_0_PAYMENTACTION=Sale&RETURNURL=http://return-address&CANCELURL=http://cancel-address&PAYMENTREQUEST_0_CURRENCYCODE=EUR&L_PAYMENTREQUEST_0_NAME0=Single License&L_PAYMENTREQUEST_0_NUMBER0=1111-2222-3333-4444-5555-6666-7777-8888&L_PAYMENTREQUEST_0_AMT0=39.99&L_PAYMENTREQUEST_0_QTY0=1

    return $nvp_string;
}

function CallShortcutExpressCheckout($total_value, $data = array())
{
    $_SESSION['currencyCodeType'] = $this->currency;
    $_SESSION['PaymentType'] = $this->payment_type;

    $result = $this->hash_call('SetExpressCheckout', $this->generate_nvp_string($total_value, $data));

    $ack = strtoupper($result['ACK']);
    if ($ack == 'SUCCESS' || $ack == 'SUCCESSWITHWARNING') {
        $_SESSION['TOKEN'] = urldecode($result['TOKEN']);
    }

    return $result;
}

So how do I get the information of the transaction for me to be able to process the payment in the backoffice? (I need an transaction ID for this)

PeeHaa
  • 71,436
  • 58
  • 190
  • 262

1 Answers1

1

You're only calling SetExpressCheckout. In order to finalize a transaction with Express Checkout, you must also call (optional) GetExpressCheckoutDetails to get the PayerID (a unique identifier of the buyer) and (required) DoExpressCheckoutPayment.

To recap:
To use Express Checkout, you would call the SetExpressCheckout API. In the API call, you specify the details of the products, amounts, and the RETURNURL. This is what you're doing in the code above.
Once you post this data to PayPal's API endpoint, you receive a token in return. You would then redirect the buyer, and append the token to the following URL: https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-XXXXXXX

Once the buyer has agreed to your purchase, he is redirected back to the URL you specified in the RETURNURL.
You should now show the order confirmation, and call the GetExpressCheckoutDetails API**. When calling GetExpressCheckoutDetails, supply the token. In the GetExpressCheckoutDetails API response you'll find a PayerID.

Now you're ready to call DoExpressCheckoutPayment, and charge the buyer. Remember to include both the token and the payerID when calling DoExpressCheckoutPayment.

With regards to IPN: You don't really need it anymore, as you'll also get the TransactionID back in the API response to DoExpressCheckoutPayment. IPN would be useful if you would subsequently want to 'keep track' of the transaction. E.g., get notified in case of any refunds / chargebacks, etc.
This simply requires setting up an IPN script and including NOTIFYURL=http://.... in both SetExpressCheckout and DoExpressCheckoutPayment.

** The PayerID is appended in the GET of your RETURNURL as well. So you could skip calling GetExpressCheckoutDetails if you wanted to.

(Partial copy of my answer at Why is DoExpressCheckoutPayment required for Paypal? )

Community
  • 1
  • 1
Robert
  • 19,326
  • 3
  • 58
  • 59
  • Haven't tried out what you have posted, but looks very promising. I will go try it out. I really hate to ask stupid question or RTFM manual questions. But the docs of PayPal are just the worst docs I've ever encountered in my life. Impossible to find anything there. Don't I still need IPN to check payment status of e.g. e-checks and stuff (which may take some time to process / validate)? – PeeHaa Nov 03 '11 at 19:38
  • 1
    Yes, to keep track of transactions after they've been created, you would use IPN. It's not required though. After you've called DoExpressCheckoutPayment and received an ACK=Success response, you'll also get PAYMENTSTATUS=Completed or Pending. – Robert Nov 03 '11 at 19:49