
At the moment, PayPal is the most popular electronic payment platform. Exactly how easy it is to open an account and start receiving funds for it, compared to traditional methods of receiving payments, is the reason # 1 for its extreme popularity. The second reason many would agree with me is the powerful API provided by PayPal. In this topic, I will decompose in order all the methods and tricks associated with the work of PayPal API, so that you avoid problems with its integration.
Warning: PayPal API is one of the most disgusting that I have ever seen. Inaccurate, in some places incomplete or inconsistent documentation, unpredictable failures and a significant difference between the work of the API in real conditions and in the sandbox, all this is essentially a pain in the ass that you have to deal with.

PayPal offers a whole range of payment methods, which is bound to confuse a person unfamiliar with PP:
')
Express paymentThe main service from a variety of similar ones offered by PayPal. An express payment will allow you to receive funds without having a merchant account, and in general, no special requirements whatsoever, except for a banal account confirmation (either through a bank account or through a credit / debit card), no. Previously, users could only accept express payments from other PayPal users, but since the system introduced the ability to pay directly from a bank card for those who do not have an account, it is possible to receive payments from almost everyone who has a card. Please note that express payments are entirely made on PayPal, so this method cannot be fully integrated into your website.
Direct paymentThis method will allow you to receive payments from bank cards through a simple API call. This will allow you to fully integrate the entire translation process into your website, which, in some cases, will make shopping for your users more convenient. There is another variation of the direct payment, which will allow you to authorize the transfer and execute it only after a certain period of time. The postpone method is available only to users from the United States, Canada and the United Kingdom.
Recurring paymentThis method will allow you to re-withdraw funds from the user's account (for example, it is used in the monthly payment for any subscription).
Bulk paymentMass payment will allow you to divide the funds received between multiple accounts.
Adaptive PaymentsThis option basically performs the same function as the previous one, but with some differences (I’ve already mentioned that PayPal API is confusing and full of excesses).
This list can not be called complete, but it lists the most popular ways to receive funds (Want more - welcome to the
documentation ).

PayPal supports two formats of data transfer via the HTTP protocol: NVP and SOAP. NVP is an abbreviation for the Name-Value Pair, meanwhile SOAP stands for Simple Object Access Protocol. I’ll only talk about NVP, since it’s much more flexible than SOAP.
All methods listed in part 1 have their own parameters, but they all have several identical basic parameters that are passed to identify the API account and authorize the payment:
USER
The name of your PayPal API account;
PWD
Password for your PayPal API account;
VERSION
The version number of the NVP API, for example, 74.0 (the latest version at the time of this writing);
SIGNATURE
Electronic Signature PayPal API. The parameter should be used only if you use a certificate for authorization;
The last of the required parameters is
METHOD
, which announces what method of transfer of funds we will use.
Requests are transmitted using the HTTPS protocol. For example, we will use cURL to form our simple request, and then we will put the whole process into a separate class:
class Paypal { protected $_errors = array(); protected $_credentials = array( 'USER' => 'seller_1297608781_biz_api1.lionite.com', 'PWD' => '1297608792', 'SIGNATURE' => 'A3g66.FS3NAf4mkHn3BDQdpo6JD.ACcPc4wMrInvUEqO3Uapovity47p', ); protected $_endPoint = 'https://api-3t.sandbox.paypal.com/nvp'; protected $_version = '74.0'; public function request($method,$params = array()) { $this -> _errors = array(); if( empty($method) ) {
Please note that I used a CA certificate for SSL validation. The certificate file can be found on
the cURL website . Do not forget to change the path to the certificate in accordance with the location where you downloaded it.
The response to the request will be in NVP format, and I have broken it into an array. The
ACK
parameter indicates the result of processing the request:
Success
or
SuccessWithWarning
in case the request was successful,
Error
or
Warning
in case the request failed.
The request can be rejected for a variety of reasons, and for each method of payment has its own reasons, which are discussed in detail in the
documentation . A little later we will look at some of them and learn how to fix them. By the way, pay attention to the fact that all the parameters in the request are case-sensitive, which is often the reason for the failure.

One of the most popular ways to transfer funds is an express payment, which allows you to receive funds without opening a special account (Website Payments Pro), which is available only to US citizens, and the payment is made on the PayPal side, which does not require any protection.
The entire payment passes according to the following algorithm:
- We request access tokens from PayPal by sending transfer details;
- If the token is received, we redirect the user to the PayPal site using the received token;
- The user makes or cancels a payment on the PayPal platform, and then redirects back to our site;
- We complete the payment, either when the user is redirected back, or via Instant Payment Notification (IPN) .

The express payment process starts by sending payment data to the PayPal API, after which we get a token that identifies our transaction. This token will come in handy in the next step when we send the user to the PayPal platform.
The following parameters must be specified in the request:
METHOD
Here you need to specify which payment method we choose (for example, SetExpressCheckout
);
RETURNURL
The address to which the user will be redirected after a successful payment;
CANCELURL
The address to which the user will be redirected if an error occurred during the payment;
PAYMENTREQUEST_0_AMT
Total amount to transfer. You need to specify two decimal numbers separated by a dot ( .
). Optionally, you can use a comma ( ,
) to separate thousands;
PAYMENTREQUEST_0_ITEMAMT
The total cost, which does not include the commission, taxes, shipping costs and other additional. costs. If there is no such parameter, the value of this parameter must correspond to the value of PAYMENTREQUEST_0_AMT
.
We can also pass additional parameters that will allow us to expand the set of information about the payment, some of the parameters have default values:
PAYMENTREQUEST_0_CURRENCYCODE
This parameter defines the currency in which all transactions will be conducted. You need to specify a three-digit code . The default value is USD
;
PAYMENTREQUEST_0_SHIPPINGAMT
Shipping cost of the order;
PAYMENTREQUEST_0_TAXAMT
The total amount of all commissions (only necessary if there are several positions in the order and each commission has its own commission);
PAYMENTREQUEST_0_DESC
Description of the translation.
If the user pays for several products at once, then it is possible to make a list of products for convenience:
L_PAYMENTREQUEST_0_NAMEm
Product Name;
L_PAYMENTREQUEST_0_DESCm
Product description;
L_PAYMENTREQUEST_0_AMTm
Unit cost;
L_PAYMENTREQUEST_0_QTYm
Quantity of goods.
The variable
m
identifies a specific product (use the same variable index for the parameters applicable to the same product).
There is a whole host of optional parameters that you can easily find in the
documentation .
We use the function we wrote earlier in part 2 to form a
SetExpressCheckout
request:

If the request was successful, we will receive a token in the
TOKEN
parameter in the response from PayPal.
if(is_array($response) && $response['ACK'] == 'Success') {
Now the user is sent to the PayPal platform, where the entire transfer process will be processed. When the user successfully completes or cancels the payment, he will be sent to one of the relevant pages, which we indicated in the request.

Suppose a user has confirmed a transfer, after which he will be sent back to our website. At this very moment, we need to use two appropriate API functions:
DoExpressCheckoutPayment
will complete the transfer, but before that we need to get more information about the customer using
GetExpressCheckoutDetails
.
PayPal will redirect the user back to our website along with the token we will use to call these functions. The token will be listed in the URL in the
token
parameter. We will check its presence in the address to which the user is transferred and send the necessary requests to the API in case he is present.
The
GetExpressCheckoutDetails
function requires the transfer of a single token, and the
DoExpressCheckoutPayment
requires the specification of several additional parameters:
PAYMENTREQUEST_0_PAYMENTACTION
This parameter defines the action we need. Sale
must be specified in the value if we have not specified another action in the SetExpressCheckout
function ( Authorization
and Capture
among the possible values);
PAYERID
This parameter specifies the unique identifier for your PayPal account. It, like the token, will be returned in the URL when the user is redirected (in the PayerID
parameter).
if( isset($_GET['token']) && !empty($_GET['token']) ) {

Direct payment allows you to fully control the entire process of transferring funds right on your website. For some unknown reason, in this case, buyers without a PayPal account will not be able to pay for services and products on your site, but it will be possible to make the whole process as simple as possible, which will have a positive impact on users' opinions. Full control over the process actually allows us to optimize and increase sales.
This method is a bit simpler than an express payment, because all user interaction occurs on your website, and we will need to make only one request to the API:
DoDirectPayment
.
But you should pay attention to the fact that you will have to make a few more requests if you are going to debit money from the user's account after a certain period of time (for example, when you are waiting for the goods to be transferred to the delivery service). For this, we will use the methods of
Authorization
and
Capture
, about which I will not tell you, but you still need to know about their existence.

Direct payment, as was said earlier, requires the indication of completely different parameters. Despite the fact that the parameters indicating the details of the transfer are similar to the express payment (the same appointments, other names are more fun), this method requires information about the bank card and address.
The main parameters of direct payment:METHOD
Obviously, in this parameter, you must specify DoDirectPayment;
IPADDRESS
In this parameter, you must specify the IP address of the buyer. Using PHP, we can easily get it using $_SERVER['REMOTE_ADDR']
, however, we have to do a little more work if on your server PHP communicates with the outside world through an intermediary (for example, if you use nginx);
PAYMENTACTION
This parameter defines the desired action. As it was said several times before, we need to specify Sale
in it.
Bank card details:CREDITCARDTYPE
The type of bank card (for example, Visa, MasterCard and others);
ACCT
Bank card number (do you also like these wonderful abbreviations?);
EXPDATE
The expiration date of the card in the format MMYYYY (two digits per month, four digits a year);
CVV2
A three-four-digit code, also known as a security code. Indicated on the back of the card.
Information about the buyer:FIRSTNAME, LASTNAME
First and last name of the buyer, in separate fields. Optionally, you can also send the user's e-mail in the EMAIL parameter;
CITY, STATE, COUNTRYCODE, ZIP
City, state, two-digit country code , zip code, all these fields are required;
STREET, STREET2
Two lines for the address. Only the first is obligatory.
The address will be processed
by the address verification system (AVS) . You will be returned a specific error if the transaction was rejected due to an incorrect address.
The parameters for specifying payment details are similar to those for express payments, but with some differences in names (
AMT
,
ITEMAMT
,
CURRENCYCODE
,
SHIPPINGAMT
,
TAXAMT
and
DESC
should be used). See the documentation for details.
In the same way, to enter information about products, you must use the following parameters:
L_NAMEm
,
L_DESCm
,
L_AMTm
and
L_QTYm
. The variable m is used to delimit the parameters for each individual product (replace with 0, 1 and further for the numbered positions in the order). Consult the documentation for a
more complete list .

Sending a request using the function we wrote earlier is very similar to the case of express payment. We pass all parameters in exactly the same way, but specify
DoDirectPayment
as the method.
$requestParams = array( 'IPADDRESS' => $_SERVER['REMOTE_ADDR'], 'PAYMENTACTION' => 'Sale' ); $creditCardDetails = array( 'CREDITCARDTYPE' => 'Visa', 'ACCT' => '4929802607281663', 'EXPDATE' => '062012', 'CVV2' => '984' ); $payerDetails = array( 'FIRSTNAME' => 'John', 'LASTNAME' => 'Doe', 'COUNTRYCODE' => 'US', 'STATE' => 'NY', 'CITY' => 'New York', 'STREET' => '14 Argyle Rd.', 'ZIP' => '10010' ); $orderParams = array( 'AMT' => '500', 'ITEMAMT' => '496', 'SHIPPINGAMT' => '4', 'CURRENCYCODE' => 'GBP' ); $item = array( 'L_NAME0' => 'iPhone', 'L_DESC0' => 'White iPhone, 16GB', 'L_AMT0' => '496', 'L_QTY0' => '1' ); $paypal = new Paypal(); $response = $paypal -> request('DoDirectPayment', $requestParams + $creditCardDetails + $payerDetails + $orderParams + $item ); if( is_array($response) && $response['ACK'] == 'Success') { $transactionId = $response['TRANSACTIONID']; }

If we lived in an ideal world, this part would not exist. In reality, you will have to refer to this part or similar sections in other articles quite often. PayPal may refuse to make a payment for one of a whole bunch of errors, and the correction of some of them is not under our control.
The
$response
variable, which contains the response from the
paypalApiRequest()
function, may contain in the
ACK
parameter a value that does not correspond to
Success
, namely:
Success
The operation was successful;
SuccessWithWarning
The operation was successful, but not perfect. The API returned a message explaining what needs to be corrected;
Failure
The operation was not successful; there are error codes in the response explaining the failure;
FailureWithWarning
The operation was not successful, there are error codes and messages in response to which you should look.
It turns out that there are two successful statuses and two failures. All the code specified above works only with the status of success, but we can easily replace it with
SuccessWithWarning
, but do not forget to check what the matter is and what the warning is about. The most common error scenario for a direct payment is that the request was successfully accepted and verified, but the bank rejected the request to withdraw funds from the card.
The errors returned by PayPal are enclosed in four parameters in the response:
L_ERRORCODE0
The digital error code that can be decrypted using the PayPal error code list ;
L_SHORTMESSAGE0
A short message explaining the problem;
L_LONGMESSAGE0
A detailed message explaining the problem;
L_SEVERITYCODE0
Difficulty code. I have no idea why he is needed, the documentation about him is silent, well, okay, let's forget about him.
The variable
0
at the end of the parameters is the sequence number of the error that occurred (if there are several errors, then the variable will have 1, 2, and so on).
Here is a small list of the most common errors:
10002
API authorization data failed validation;
81***
One of the required parameters is missing;
104**
An incorrect value was passed in one of the parameters.

Some PayPal errors may contain private information in your description, which you hardly want to show to users. For this reason, users are advised to turn off error display, even if it may be useful.
In most cases, I would advise to do the following:
- Create a white list of errors that can be shown to users (for example, incorrect data on a bank card);
- Make it so that when returning errors, they are checked against the white list;
- If there is no error in this list, the user needs to display some general error, for example, “An error has occurred during the processing of your payment. Wait a few minutes or contact us to solve this problem. "

In this topic, I talked about the two most popular APIs and about working with errors. This should be enough so that you can start working with the most popular payment system on the network.
In the PayPal API, you can find a lot more methods and methods, more than one topic. Once you learn how to work with the two most popular ways, learning the rest will be much easier. I hope that this guide will give you a good start in using the API.

Original article:
Getting Started With The PayPal API , Eran Galperin, September 5, 2011.
I really hope that this translation will be really useful for the habrasoobshchestvo. In other words, I still do not lose hope for the holiday on September 24th. Wait and see.


This text is distributed under a
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 license .
You can copy, edit and use this text for non-commercial purposes with the obligatory indication of authorship and preservation of the original license.