1. Code
  2. WordPress
  3. Plugin Development

A Guide to the WordPress HTTP API: Payments With PayPal

Scroll to top
17 min read
This post is part of a series called A Guide to the WordPress HTTP API.
A Guide to the WordPress HTTP API: The Basics

In the first part, we touched on the basics of the WordPress HTTP API and how to make a simple GET request and read the response. In this tutorial, we'll learn about the PayPal Express Checkout API and how to build a class that uses the HTTP API to process payments with PayPal. Preferably, you will have some knowledge of what PayPal is and also a Sandbox account (which is free and easy to get). We've done this as a plugin to show how the PayPal class works and ease making the HTTP requests.


An Overview of the PayPal API

PayPal is an online payment processor. It's quite popular, and enables millions of professionals and businesses to exchange money online with just an email address. You may even already be using PayPal to receive payments from clients. Clients login to their PayPal account and send the money to your PayPal account using your email address.

This is good for personal and manual money sending. Businesses, however, need to automate the process. They usually setup a shopping cart where purchasers add items and then complete the purchase by entering their shipping details and payment information.

The PayPal team have put various procedures to automate payments. They are confusing at times; and to be honest, their documentation is a little messy. I have picked the Express CheckOut API for two reasons: It's quite simple and straightforward to implement; and it enables a very good degree of customization.

The Express Checkout Flow

The payment process begins from your website. After putting some items in their shopping cart, your visitor goes to the shopping cart page where they find the items they added and the total amount. You should also include the PayPal payment button.

When the user clicks the PayPal payment button, they get redirected to the PayPal login page. They need to enter their login details, and confirm the purchase. The PayPal login and confirmation page can be customized (by adding the order details and total amount to be paid) but it's optional. After confirming the payment, the user is returned to your website to a web page that you specify.

When the user is returned to your page, you complete the purchase order. First, you execute the payment order (charge the buyer's PayPal account), and when the transaction succeeds, you redirect the user to your product download page, or you notify your shipping department of the order.

What Does It Have to Do With HTTP?

Although it may not look like it, most of the stuff actually happens on your website and servers. To redirect the user to the PayPal page, you need first to get a "Token" key from PayPal. To get this key, you need to send a POST request to the PayPal Server API with your account and transaction details. If the request succeeds, PayPal will answer with a "Token" key.

When the user logs in to his PayPal account and confirms the payment, the payment isn't actually processed. In this step, the user only grants the right for your service to process the transaction. After the authorization, the buyer is returned to your website where you can complete the process and charge the user.

At least, you'll have two HTTP requests. The first one is to get the "Token" which you'll use to redirect the user to the payment page. The second is to complete processing the payment for the buyer. You can do additional requests before completing the payment in which you request the payer details (like the Shipping address), but it is optional.


The PayPal Gateway Class

To standardize and streamline the process, I have coded a PHP class which does the required requests by simply giving it the parameters. The class implements the 3 request methods supported by the PayPal API:

  1. setExpressCheckout – This request returns a "Token" key which will be used to redirect the user to a login page.
  2. getExpressCheckout – Use this request to get information about your buyer, like the shipping address or the payment status.
  3. doExpressCheckout – This request completes the payment and charges the user account.

These methods require some common parameters like the PayPal API version, your account username, password and also a signature. If you haven't already, sign up for the PayPal Sandbox which is a test platform that emulates the real PayPal. Our class will support the sandbox environment.

Making the HTTP Request

For the 3 methods mentioned above, I have found out that they share a good amount of code. They basically do the same request, but use different parameters for each.

  • Request type: POST
  • Request URL: The PayPal API server or the Sandbox PayPal API server
  • Timeout: 60 (a short timeout might result in an unsuccessful request)
  • SSL Verification: Default to false if the "https_local_ssl_verify" is not set
  • Request body: different from one method to another.

Using the Class

First, you'll need to have an idea about the required parameters. I'm going to summarize them here, but for more extensive and complete details, check out the PayPal Express Checkout documentation. The following table tries to summarize the required parameters for successful set, get and do requests.

1
2
// Loading the Class file

3
require_once ('paypal.php');
4
5
// Create a new PayPal class instance, and set the sandbox mode to true

6
$paypal = new wp_paypal_gateway (true);
7
8
// Common Parameters

9
$paypal->version = '84.00';
10
$paypal->user = 'sdk-three_api1.sdk.com';
11
$paypal->password = 'QFZCWN5HZM8VBG7Q';
12
$paypal->signature = 'A-IzJhZZjhg29XQ2qnhapuwxIDzyAZQ92FRP5dqBzVesOkzbdUONzmOU';
13
14
// Required Parameter for the getExpresscheckout

15
$param = array(
16
	'amount' => '20.00',
17
	'currency_code' => 'USD',
18
	'payment_action' => 'Sale',
19
	'return_url' => 'https://example.com/return',
20
	'cancel_url' => 'http://example.com/cancel'
21
);
22
23
// Display the response if successful or the debug info

24
if ($paypal->setExpressCheckout($param)) {
25
	print_r($paypal->getResponse());
26
} else {
27
	print_r($paypal->debug_info);
28
}

The Class Code

Step 1 The Class, Properties, and Methods

We start off with a class skeleton defining the properties, the constructor and the different methods. Each property and method is preceded with a comment section that has a description, the accepted parameters and the returned variable. The comments follow the PhpDoc guidelines.

1
2
class wp_paypal_gateway
3
{
4
    /**

5
     * PayPal API Version

6
     * @string

7
     */
8
    public $version;
9
10
    /**

11
     * PayPal account username

12
     * @string

13
     */
14
    public $user;
15
16
    /**

17
     * PayPal account password

18
     * @string

19
     */
20
    public $password;
21
22
    /**

23
     * PayPal account signature

24
     * @string

25
     */
26
    public $signature;
27
28
    /**

29
     * Period of time (in seconds) after which the connection ends

30
     * @integer

31
     */
32
    public $time_out = 60;
33
34
    /**

35
     * Requires SSL Verification

36
     * @boolean

37
     */
38
    public $ssl_verify;
39
40
    /**

41
     * PayPal API Server

42
     * @string

43
     */
44
    private $server;
45
46
    /**

47
     * PayPal API Redirect URL

48
     * @string

49
     */
50
    private $redirect_url;
51
52
    /**

53
     * Real world PayPal API Server

54
     * @string

55
     */
56
    private $real_server = 'https://api-3t.paypal.com/nvp';
57
58
    /**

59
     * Read world PayPal redirect URL

60
     * @string

61
     */
62
    private $real_redirect_url = 'https://www.paypal.com/cgi-bin/webscr';
63
64
    /**

65
     * Sandbox PayPal Server

66
     * @string

67
     */
68
    private $sandbox_server = 'https://api-3t.sandbox.paypal.com/nvp';
69
70
    /**

71
     * Sandbox PayPal redirect URL

72
     * @string

73
     */
74
    private $sandbox_redirect_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
75
76
    /**

77
     * Array representing the supported short-terms

78
     * @array

79
     */
80
    private $short_term = array(
81
        'amount' => 'PAYMENTREQUEST_0_AMT',
82
        'currency_code' => 'PAYMENTREQUEST_0_CURRENCYCODE',
83
        'return_url' => 'RETURNURL',
84
        'cancel_url' => 'CANCELURL',
85
        'payment_action' => 'PAYMENTREQUEST_0_PAYMENTACTION',
86
        'token' => 'TOKEN',
87
        'payer_id' => 'PAYERID'
88
    );
89
90
    /**

91
     * When something goes wrong, the debug_info variable will be set

92
     * with a string, array, or object explaining the problem

93
     * @mixed

94
     */
95
    public $debug_info;
96
97
    /**

98
     * Saves the full response once a request succeed

99
     * @mixed

100
     */
101
    public $full_response = false;
102
103
    /**

104
     * Creates a new PayPal gateway object

105
     * @param boolean $sandbox Set to true if you want to enable the Sandbox mode

106
     */
107
    public function __construct($sandbox = false)
108
    {
109
110
    }
111
112
    /**

113
     * Executes a setExpressCheckout command

114
     * @param array $param

115
     * @return boolean

116
     */
117
    public function setExpressCheckout($param)
118
    {
119
120
    }
121
122
    /**

123
     * Executes a getExpressCheckout command

124
     * @param array $param

125
     * @return boolean

126
     */
127
    public function getExpressCheckout($param)
128
    {
129
130
    }
131
132
    /**

133
     * Executes a doExpressCheckout command

134
     * @param array $param

135
     * @return boolean

136
     */
137
    public function doExpressCheckout($param)
138
    {
139
140
    }
141
142
    /**

143
     * @param string $type

144
     * @param array $param

145
     * @return boolean Specifies if the request is successful and the response property

146
     *                 is filled

147
     */
148
    private function requestExpressCheckout($type, $param)
149
    {
150
151
    }
152
153
    /**

154
     * Replace the Parameters short terms

155
     * @param array $param The given parameters array

156
     * @return array $param

157
     */
158
    private function replace_short_terms($param)
159
    {
160
161
    }
162
163
    /**

164
     * Builds the request array from the object, param and type parameters

165
     * @param string $type

166
     * @param array $param

167
     * @return array $body

168
     */
169
    private function build_request($type, $param)
170
    {
171
172
    }
173
174
    /**

175
     * Returns the PayPal Body response

176
     * @return array $reponse

177
     */
178
    public function getResponse()
179
    {
180
181
    }
182
183
    /**

184
     * Returns the redirect URL

185
     * @return string $url

186
     */
187
    public function getRedirectURL()
188
    {
189
190
    }
191
192
    /**

193
     * Returns the response Token

194
     * @return string $token

195
     */
196
    public function getToken()
197
    {
198
199
    }
200
}

Step 2 The Constructor

The constructor initiates a new instance of our class. It accepts one parameter which enables the sandbox mode if you pass "true" to it. The method will set the Server and Redirect URL following the sandbox argument. It'll also set the SSL Verify property applying the "https_local_ssl_verify" filter.

1
2
public function __construct($sandbox = false)
3
{
4
	// Set the Server and Redirect URL

5
	if ($sandbox) {
6
		$this->server = $this->sandbox_server;
7
		$this->redirect_url = $this->sandbox_redirect_url;
8
	} else {
9
		$this->server = $this->real_server;
10
		$this->redirect_url = $this->real_redirect_url;
11
	}
12
13
	// Set the SSL Verification

14
	$this->ssl_verify = apply_filters('https_local_ssl_verify', false);
15
}

Step 3 The Request Method

The class implements the 3 request methods as specified by the PayPal API: setExpressCheckout, getExpressCheckout, and doExpressCheckout. The common thing about these 3 functions is that they all do a POST request to the PayPal server.

To keep our code DRY, I have created a single function to make the other 3 helper functions that call our main function and specify the type of the request.

If our request is successful, the function will return "true" and save the request response to the "full_response" property. If our request fails for whatever reason, the function will return "false" and saves information about the error in the "debug_info" property.

1
2
private function requestExpressCheckout($type, $param)
3
{
4
	// Construct the request array

5
	$param = $this->replace_short_terms($param);
6
	$request = $this->build_request($type, $param);
7
8
	// Makes the HTTP request

9
	$response = wp_remote_post($this->server, $request);
10
11
	// HTTP Request fails

12
	if (is_wp_error($response)) {
13
		$this->debug_info = $response;
14
		return false;
15
	}
16
17
	// Status code returned other than 200

18
	if ($response['response']['code'] != 200) {
19
		$this->debug_info = 'Response code different than 200';
20
		return false;
21
	}
22
23
	// Saves the full response

24
	$this->full_response = $response;
25
26
	// Request succeeded

27
	return true;
28
}

Step 4 Utilities Functions

Our class makes use of two utility functions. The first function replaces the long PayPal parameters with short names. So instead of using "PAYMENTREQUEST_0_AMT" as your input key, you just put "amount"; a less cryptic and easier to remember word.

1
2
private function replace_short_terms($param)
3
{
4
	foreach ($this->short_term as $short_term => $long_term)
5
	{
6
		if (array_key_exists($short_term, $param)) {
7
			$param[$long_term] = $param[$short_term];
8
			unset($param[$short_term]);
9
		}
10
	}
11
	return $param;
12
}

The second function builds the request array. It's just added for separation of concerns; you can move it to the requestExpressCheckout.

1
2
private function build_request($type, $param)
3
{
4
	// Request Body

5
	$body = $param;
6
	$body['METHOD'] = $type;
7
	$body['VERSION'] = $this->version;
8
	$body['USER'] = $this->user;
9
	$body['PWD'] = $this->password;
10
	$body['SIGNATURE'] = $this->signature;
11
12
	// Request Array

13
	$request = array(
14
		'method' => 'POST',
15
		'body' => $body,
16
		'timeout' => $this->time_out,
17
		'sslverify' => $this->ssl_verify
18
	);
19
20
	return $request;
21
}

Step 5 The Response Methods

The request methods return the full, unaltered response. That's where our response methods come in handy. If the request is successful, PayPal will return the response in a URL like encoded string. The helper functions will decode and return only the required part and in a more accessible format.

getResponse – Returns an array of key/value pairs containing the full PayPal response.

1
2
public function getResponse()
3
{
4
	if ($this->full_response) {
5
		parse_str(urldecode($this->full_response['body']), $output);
6
		return $output;
7
	}
8
	return false;
9
}

getRedirectURL – Returns only the redirect URL to the payment page. This is available only after calling the setExpressCheckout function.

1
2
public function getRedirectURL()
3
{
4
	$output = $this->getResponse();
5
	if ($output['ACK'] === 'Success') {
6
		$query_data = array(
7
			'cmd' => '_express-checkout',
8
			'token' => $output['TOKEN']
9
		);
10
		$url = $this->redirect_url . '?' . http_build_query($query_data);
11
		return $url;
12
	}
13
	return false;
14
}

getToken – Returns the response token.

1
	
2
public function getToken()
3
{
4
	$output = $this->getResponse();
5
	if ($output['ACK'] === 'Success') {
6
		return $output['TOKEN'];
7
	}
8
	return false;
9
}

The Full Code

The full code is available also on GitHub. I have chosen not to license the code. Feel free to use it for any kind (free/commercial) projects. No attribution is required, but it'll be appreciated.

1
2
class wp_paypal_gateway
3
{
4
    /**

5
     * PayPal API Version

6
     * @string

7
     */
8
    public $version;
9
10
    /**

11
     * PayPal account username

12
     * @string

13
     */
14
    public $user;
15
16
    /**

17
     * PayPal account password

18
     * @string

19
     */
20
    public $password;
21
22
    /**

23
     * PayPal account signature

24
     * @string

25
     */
26
    public $signature;
27
28
    /**

29
     * Period of time (in seconds) after which the connection ends

30
     * @integer

31
     */
32
    public $time_out = 60;
33
34
    /**

35
     * Requires SSL Verification

36
     * @boolean

37
     */
38
    public $ssl_verify;
39
40
    /**

41
     * PayPal API Server

42
     * @string

43
     */
44
    private $server;
45
46
    /**

47
     * PayPal API Redirect URL

48
     * @string

49
     */
50
    private $redirect_url;
51
52
    /**

53
     * Real world PayPal API Server

54
     * @string

55
     */
56
    private $real_server = 'https://api-3t.paypal.com/nvp';
57
58
    /**

59
     * Read world PayPal redirect URL

60
     * @string

61
     */
62
    private $real_redirect_url = 'https://www.paypal.com/cgi-bin/webscr';
63
64
    /**

65
     * Sandbox PayPal Server

66
     * @string

67
     */
68
    private $sandbox_server = 'https://api-3t.sandbox.paypal.com/nvp';
69
70
    /**

71
     * Sandbox PayPal redirect URL

72
     * @string

73
     */
74
    private $sandbox_redirect_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
75
76
    /**

77
     * Array representing the supported short-terms

78
     * @array

79
     */
80
    private $short_term = array(
81
        'amount' => 'PAYMENTREQUEST_0_AMT',
82
        'currency_code' => 'PAYMENTREQUEST_0_CURRENCYCODE',
83
        'return_url' => 'RETURNURL',
84
        'cancel_url' => 'CANCELURL',
85
        'payment_action' => 'PAYMENTREQUEST_0_PAYMENTACTION',
86
        'token' => 'TOKEN',
87
        'payer_id' => 'PAYERID'
88
    );
89
90
    /**

91
     * When something goes wrong, the debug_info variable will be set

92
     * with a string, array, or object explaining the problem

93
     * @mixed

94
     */
95
    public $debug_info;
96
97
    /**

98
     * Saves the full response once a request succeed

99
     * @mixed

100
     */
101
    public $full_response = false;
102
103
    /**

104
     * Creates a new PayPal gateway object

105
     * @param boolean $sandbox Set to true if you want to enable the Sandbox mode

106
     */
107
    public function __construct($sandbox = false)
108
    {
109
        // Set the Server and Redirect URL

110
        if ($sandbox) {
111
            $this->server = $this->sandbox_server;
112
            $this->redirect_url = $this->sandbox_redirect_url;
113
        } else {
114
            $this->server = $this->real_server;
115
            $this->redirect_url = $this->real_redirect_url;
116
        }
117
118
        // Set the SSL Verification

119
        $this->ssl_verify = apply_filters('https_local_ssl_verify', false);
120
    }
121
122
    /**

123
     * Executes a setExpressCheckout command

124
     * @param array $param

125
     * @return boolean

126
     */
127
    public function setExpressCheckout($param)
128
    {
129
        return $this->requestExpressCheckout('SetExpressCheckout', $param);
130
    }
131
132
    /**

133
     * Executes a getExpressCheckout command

134
     * @param array $param

135
     * @return boolean

136
     */
137
    public function getExpressCheckout($param)
138
    {
139
        return $this->requestExpressCheckout('GetExpressCheckoutDetails', $param);
140
    }
141
142
    /**

143
     * Executes a doExpressCheckout command

144
     * @param array $param

145
     * @return boolean

146
     */
147
    public function doExpressCheckout($param)
148
    {
149
        return $this->requestExpressCheckout('DoExpressCheckoutPayment', $param);
150
    }
151
152
    /**

153
     * @param string $type

154
     * @param array $param

155
     * @return boolean Specifies if the request is successful and the response property

156
     *                 is filled

157
     */
158
    private function requestExpressCheckout($type, $param)
159
    {
160
        // Construct the request array

161
        $param = $this->replace_short_terms($param);
162
        $request = $this->build_request($type, $param);
163
164
        // Makes the HTTP request

165
        $response = wp_remote_post($this->server, $request);
166
167
        // HTTP Request fails

168
        if (is_wp_error($response)) {
169
            $this->debug_info = $response;
170
            return false;
171
        }
172
173
        // Status code returned other than 200

174
        if ($response['response']['code'] != 200) {
175
            $this->debug_info = 'Response code different than 200';
176
            return false;
177
        }
178
179
        // Saves the full response

180
        $this->full_response = $response;
181
182
        // Request succeeded

183
        return true;
184
    }
185
186
    /**

187
     * Replace the Parameters short terms

188
     * @param array $param The given parameters array

189
     * @return array $param

190
     */
191
    private function replace_short_terms($param)
192
    {
193
        foreach ($this->short_term as $short_term => $long_term)
194
        {
195
            if (array_key_exists($short_term, $param)) {
196
                $param[$long_term] = $param[$short_term];
197
                unset($param[$short_term]);
198
            }
199
        }
200
        return $param;
201
    }
202
203
    /**

204
     * Builds the request array from the object, param and type parameters

205
     * @param string $type

206
     * @param array $param

207
     * @return array $body

208
     */
209
    private function build_request($type, $param)
210
    {
211
        // Request Body

212
        $body = $param;
213
        $body['METHOD'] = $type;
214
        $body['VERSION'] = $this->version;
215
        $body['USER'] = $this->user;
216
        $body['PWD'] = $this->password;
217
        $body['SIGNATURE'] = $this->signature;
218
219
        // Request Array

220
        $request = array(
221
            'method' => 'POST',
222
            'body' => $body,
223
            'timeout' => $this->time_out,
224
            'sslverify' => $this->ssl_verify
225
        );
226
227
        return $request;
228
    }
229
230
    /**

231
     * Returns the PayPal Body response

232
     * @return array $reponse

233
     */
234
    public function getResponse()
235
    {
236
        if ($this->full_response) {
237
            parse_str(urldecode($this->full_response['body']), $output);
238
            return $output;
239
        }
240
        return false;
241
    }
242
243
    /**

244
     * Returns the redirect URL

245
     * @return string $url

246
     */
247
    public function getRedirectURL()
248
    {
249
        $output = $this->getResponse();
250
        if ($output['ACK'] === 'Success') {
251
            $query_data = array(
252
                'cmd' => '_express-checkout',
253
                'token' => $output['TOKEN']
254
            );
255
            $url = $this->redirect_url . '?' . http_build_query($query_data);
256
            return $url;
257
        }
258
        return false;
259
    }
260
261
    /**

262
     * Returns the response Token

263
     * @return string $token

264
     */
265
    public function getToken()
266
    {
267
        $output = $this->getResponse();
268
        if ($output['ACK'] === 'Success') {
269
            return $output['TOKEN'];
270
        }
271
        return false;
272
    }
273
}

The PayPal Test Plugin

To make the debugging and testing of the PHP class easier, I have created a WordPress plugin which offers a simple interface. You enter the required parameters for each type of the request, and you click the send button. The request will be processed with AJAX, no page reload is required. The request results will be displayed on the right of the forms.

The Plugin Code

The test plugin is made up of two components: The front-end which is a set of input boxes and the second is the back-end which handles the AJAX requests submitted by the plugin front-end.

Each request has common settings which are the same on every request, and specific settings which depends on its type. The front-end references the input boxes value, and groups them on objects. It also adds a click handler for every button which does a simple jQuery post request to the "ajaxurl" with the specified input.

The test plugin doesn't do any checking on the input. So make sure you are typing the correct parameters.

1
2
(function ($) {
3
    $(document).ready(function () {
4
        /**

5
         * Reference input boxes

6
         */
7
        var common_data = {
8
            version:$('#paypal_setec_version').val(),
9
            user:$('#paypal_setec_user').val(),
10
            password:$('#paypal_setec_password').val(),
11
            signature:$('#paypal_setec_signature').val()
12
        },
13
        setec_data = {
14
            amount:$('#paypal_setec_amount').val(),
15
            currency:$('#paypal_setec_currency').val(),
16
            returnurl:$('#paypal_setec_returnurl').val(),
17
            cancelurl:$('#paypal_setec_cancelurl').val(),
18
            paymentaction:$('#paypal_setec_paymentaction').val()
19
        },
20
        getec_data = {
21
            token:$('#paypal_getec_token').val()
22
        },
23
        doec_data = {
24
            token:$('#paypal_doec_token').val(),
25
            payerid:$('#paypal_doec_payerid').val(),
26
            amount:$('#paypal_doec_amount').val(),
27
            currency:$('#paypal_doec_currency').val(),
28
            paymentaction:$('#paypal_doec_paymentaction').val()
29
        },
30
        display_info = $('#display_debug_info');
31
32
        /**

33
         * setExpresscheckout form

34
         */
35
        $('#paypal_setec_send').on('click', function (e) {
36
            e.preventDefault();
37
            var data = {
38
                action:'pp_setec',
39
                common:common_data,
40
                setec:setec_data
41
            };
42
            $.post(ajaxurl, data, function (response) {
43
                display_info.html(response);
44
            });
45
        });
46
47
        /**

48
         * getExpresscheckout form

49
         */
50
        $('#paypal_getec_send').on('click', function (e) {
51
            e.preventDefault();
52
            var data = {
53
                action:'pp_getec',
54
                common:common_data,
55
                setec:getec_data
56
            };
57
            $.post(ajaxurl, data, function (response) {
58
                display_info.html(response);
59
            });
60
        });
61
62
        /**

63
         * doExpresscheckout form

64
         */
65
        $('#paypal_doec_send').on('click', function (e) {
66
            e.preventDefault();
67
            var data = {
68
                action:'pp_doec',
69
                common:common_data,
70
                setec:doec_data
71
            };
72
            $.post(ajaxurl, data, function (response) {
73
                display_info.html(response);
74
            });
75
        });
76
    });
77
})(jQuery);

On the back-end, the AJAX requests are handled using the "wp_ajax_" action. The function associated with the action will evaluate the global "$_POST" variable and create a new instance of the PayPal class.

If the ExpressCheckout request is successful, the full response is returned; otherwise, the debugging information will be returned.

1
2
add_action('wp_ajax_pp_setec', 'pp_ajax_setec');
3
/**

4
 * AJAX handler for the setExpressCheckout request

5
 */
6
function pp_ajax_setec()
7
{
8
    global $_POST;
9
    require_once ('paypal.php');
10
    $paypal = new wp_paypal_gateway (true);
11
    $paypal->version = $_POST['common']['version'];
12
    $paypal->user = $_POST['common']['user'];
13
    $paypal->password = $_POST['common']['password'];
14
    $paypal->signature = $_POST['common']['signature'];
15
    $param = array(
16
        'amount' => $_POST['setec']['amount'],
17
        'currency_code' => $_POST['setec']['currency'],
18
        'return_url' => $_POST['setec']['returnurl'],
19
        'cancel_url' => $_POST['setec']['cancelurl'],
20
        'payment_action' => $_POST['setec']['paymentaction']
21
    );
22
    if ($paypal->setExpressCheckout($param)) {
23
        var_dump($paypal->getResponse());
24
    } else {
25
        var_dump($paypal->debug_info);
26
    }
27
    die();
28
}
29
30
add_action('wp_ajax_pp_getec', 'pp_ajax_getec');
31
/**

32
 * AJAX handler for the getExpressCheckout request

33
 */
34
function pp_ajax_getec()
35
{
36
    global $_POST;
37
    require_once ('paypal.php');
38
    $paypal = new wp_paypal_gateway (true);
39
    $paypal->version = $_POST['common']['version'];
40
    $paypal->user = $_POST['common']['user'];
41
    $paypal->password = $_POST['common']['password'];
42
    $paypal->signature = $_POST['common']['signature'];
43
    $param = array(
44
        'amount' => $_POST['getec']['token']
45
    );
46
    if ($paypal->getExpressCheckout($param)) {
47
        print_r($paypal->getResponse());
48
    } else {
49
        print_r($paypal->debug_info);
50
    }
51
    die();
52
}
53
54
add_action('wp_ajax_pp_doec', 'pp_ajax_doec');
55
/**

56
 * AJAX handler for the doExpressCheckout request

57
 */
58
function pp_ajax_doec()
59
{
60
    global $_POST;
61
    require_once ('paypal.php');
62
    $paypal = new wp_paypal_gateway (true);
63
    $paypal->version = $_POST['common']['version'];
64
    $paypal->user = $_POST['common']['user'];
65
    $paypal->password = $_POST['common']['password'];
66
    $paypal->signature = $_POST['common']['signature'];
67
    $param = array(
68
        'amount' => $_POST['doec']['amount'],
69
        'currency_code' => $_POST['doec']['currency'],
70
        'payment_action' => $_POST['doec']['paymentaction'],
71
        'payer_id' => $_POST['doec']['payerid'],
72
        'token' => $_POST['doec']['token']
73
    );
74
    if ($paypal->doExpressCheckout($param)) {
75
        print_r($paypal->getResponse());
76
    } else {
77
        print_r($paypal->debug_info);
78
    }
79
    die();
80
}

Conclusion

In this tutorial, we learned some basics about the PayPal Express Checkout API; and also explored how to build a payment gateway class using the WordPress HTTP API. Now you can use this class to easily implement PayPal payments in your plugin.

In the next and final article in the series, we'll learn how to build a self-hosted plugin repository to enable automatic updates for plugins which are not hosted in the WordPress Plugins repository.