1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace OpenBuildings\PayPal; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* @abstract |
7
|
|
|
* @author Haralan Dobrev <[email protected]> |
8
|
|
|
* @copyright 2013 OpenBuildings, Inc. |
9
|
|
|
* @license http://spdx.org/licenses/BSD-3-Clause |
10
|
|
|
*/ |
11
|
|
|
abstract class Payment { |
12
|
|
|
|
13
|
|
|
const ENDPOINT_START = 'https://www.'; |
14
|
|
|
|
15
|
|
|
const WEBSCR_ENDPOINT_END = 'paypal.com/cgi-bin/webscr'; |
16
|
|
|
|
17
|
|
|
const MERCHANT_ENDPOINT_START = 'https://api-3t.'; |
18
|
|
|
|
19
|
|
|
const MERCHANT_ENDPOINT_END = 'paypal.com/nvp'; |
20
|
|
|
|
21
|
|
|
const ENVIRONMENT_LIVE = ''; |
22
|
|
|
|
23
|
|
|
const ENVIRONMENT_SANDBOX = 'sandbox.'; |
24
|
|
|
|
25
|
|
|
public static $instances = array(); |
26
|
|
|
|
27
|
|
|
public static $config = array( |
28
|
|
|
'app_id' => '', |
29
|
|
|
'username' => '', |
30
|
|
|
'password' => '', |
31
|
|
|
'signature' => '', |
32
|
|
|
'email' => '', |
33
|
|
|
'client_id' => '', |
34
|
|
|
'secret' => '', |
35
|
|
|
'currency' => 'USD', |
36
|
|
|
); |
37
|
|
|
|
38
|
|
|
protected static $_allowed_environments = array( |
39
|
|
|
self::ENVIRONMENT_LIVE, |
40
|
|
|
self::ENVIRONMENT_SANDBOX |
41
|
|
|
); |
42
|
|
|
|
43
|
|
|
private static $environment = self::ENVIRONMENT_SANDBOX; |
44
|
|
|
|
45
|
5 |
|
public static function instance($name, array $config = array()) |
46
|
|
|
{ |
47
|
5 |
|
if (empty(self::$instances[$name])) |
48
|
|
|
{ |
49
|
2 |
|
$class = "OpenBuildings\\PayPal\\Payment_$name"; |
50
|
2 |
|
self::$instances[$name] = new $class($config); |
51
|
|
|
} |
52
|
|
|
|
53
|
5 |
|
return self::$instances[$name]; |
54
|
|
|
} |
55
|
|
|
|
56
|
1 |
|
public static function merchant_endpoint_url() |
57
|
|
|
{ |
58
|
1 |
|
return self::MERCHANT_ENDPOINT_START.self::environment().self::MERCHANT_ENDPOINT_END; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Webscr url based on command, params and environment |
63
|
|
|
*/ |
64
|
1 |
|
public static function webscr_url($command = FALSE, array $params = array()) |
65
|
|
|
{ |
66
|
1 |
|
if ($command) |
67
|
|
|
{ |
68
|
1 |
|
$params = array_reverse($params, TRUE); |
69
|
1 |
|
$params['cmd'] = $command; |
70
|
1 |
|
$params = array_reverse($params, TRUE); |
71
|
|
|
} |
72
|
|
|
|
73
|
1 |
|
return self::ENDPOINT_START.self::environment().self::WEBSCR_ENDPOINT_END.($params ? '?'.http_build_query($params) : ''); |
74
|
|
|
} |
75
|
|
|
|
76
|
1 |
|
public static function environment($environment = NULL) |
77
|
|
|
{ |
78
|
1 |
|
if ($environment === NULL) |
79
|
1 |
|
return self::$environment; |
80
|
|
|
|
81
|
1 |
|
if ( ! in_array($environment, self::$_allowed_environments)) |
82
|
1 |
|
throw new Exception('PayPal environment ":environment" is not allowed!', array( |
83
|
1 |
|
':environment' => $environment |
84
|
|
|
)); |
85
|
|
|
|
86
|
1 |
|
self::$environment = $environment; |
87
|
1 |
|
} |
88
|
|
|
|
89
|
9 |
|
public static function parse_response($response_string, $url, $request_data) |
90
|
|
|
{ |
91
|
9 |
|
$response = Util::parse_str($response_string); |
92
|
|
|
|
93
|
9 |
|
if ( ! isset($response['ACK']) OR strpos($response['ACK'], 'Success') === FALSE) |
94
|
6 |
|
throw new Request_Exception('PayPal API request did not succeed for :url failed: :error:code.', $url, $request_data, array( |
95
|
6 |
|
':url' => $url, |
96
|
6 |
|
':error' => isset($response['L_LONGMESSAGE0']) ? $response['L_LONGMESSAGE0'] : 'Unknown error', |
97
|
6 |
|
':code' => isset($response['L_ERRORCODE0']) ? ' ('.$response['L_ERRORCODE0'].')' : '', |
98
|
6 |
|
), $response); |
99
|
|
|
|
100
|
3 |
|
return $response; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
protected $_config; |
104
|
|
|
|
105
|
|
|
protected $_order = array(); |
106
|
|
|
|
107
|
|
|
protected $_return_url = NULL; |
108
|
|
|
|
109
|
|
|
protected $_cancel_url = NULL; |
110
|
|
|
|
111
|
|
|
protected $_notify_url = NULL; |
112
|
|
|
|
113
|
2 |
|
public function __construct(array $config = array()) |
114
|
|
|
{ |
115
|
2 |
|
$this->config($config); |
116
|
2 |
|
} |
117
|
|
|
|
118
|
2 |
|
public function config($key, $value = NULL) |
119
|
|
|
{ |
120
|
2 |
|
if ($value === NULL AND ! is_array($key)) |
121
|
|
|
return (isset($this->_config[$key]) AND array_key_exists($key, $this->_config)) |
122
|
|
|
? $this->_config[$key] |
123
|
|
|
: NULL; |
124
|
|
|
|
125
|
2 |
|
if (is_array($key)) |
126
|
|
|
{ |
127
|
2 |
|
$this->_config = array_replace(self::$config, $key); |
128
|
|
|
} |
129
|
|
|
else |
130
|
|
|
{ |
131
|
|
|
$this->_config[$key] = $value; |
132
|
|
|
} |
133
|
|
|
|
134
|
2 |
|
return $this; |
135
|
|
|
} |
136
|
|
|
|
137
|
1 |
|
public function order(array $order = NULL) |
138
|
|
|
{ |
139
|
1 |
|
if ($order === NULL) |
140
|
1 |
|
return $this->_order; |
141
|
|
|
|
142
|
1 |
|
$this->_order = $order; |
143
|
|
|
|
144
|
1 |
|
return $this; |
145
|
|
|
} |
146
|
|
|
|
147
|
1 |
|
public function return_url($return_url = NULL) |
148
|
|
|
{ |
149
|
1 |
|
if ($return_url === NULL) |
150
|
1 |
|
return $this->_return_url; |
151
|
|
|
|
152
|
1 |
|
$this->_return_url = $return_url; |
153
|
|
|
|
154
|
1 |
|
return $this; |
155
|
|
|
} |
156
|
|
|
|
157
|
1 |
|
public function cancel_url($cancel_url = NULL) |
158
|
|
|
{ |
159
|
1 |
|
if ($cancel_url === NULL) |
160
|
1 |
|
return $this->_cancel_url; |
161
|
|
|
|
162
|
1 |
|
$this->_cancel_url = $cancel_url; |
163
|
|
|
|
164
|
1 |
|
return $this; |
165
|
|
|
} |
166
|
|
|
|
167
|
1 |
|
public function notify_url($notify_url = NULL) |
168
|
|
|
{ |
169
|
1 |
|
if ($notify_url === NULL) |
170
|
1 |
|
return $this->_notify_url; |
171
|
|
|
|
172
|
1 |
|
$this->_notify_url = $notify_url; |
173
|
|
|
|
174
|
1 |
|
return $this; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
public function request($url, array $request_data = array(), array $headers = array()) |
178
|
|
|
{ |
179
|
|
|
// Create a new curl instance |
180
|
|
|
$curl = curl_init(); |
181
|
|
|
|
182
|
|
|
$curl_options = array( |
183
|
|
|
CURLOPT_URL => $url, |
184
|
|
|
CURLOPT_POST => TRUE, |
185
|
|
|
CURLOPT_SSL_VERIFYPEER => FALSE, |
186
|
|
|
CURLOPT_SSL_VERIFYHOST => FALSE, |
187
|
|
|
CURLOPT_RETURNTRANSFER => TRUE, |
188
|
|
|
); |
189
|
|
|
|
190
|
|
|
if ($request_data) |
|
|
|
|
191
|
|
|
{ |
192
|
|
|
$curl_options[CURLOPT_POSTFIELDS] = http_build_query($request_data, NULL, '&'); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
if ($headers) |
|
|
|
|
196
|
|
|
{ |
197
|
|
|
$curl_options[CURLOPT_HTTPHEADER] = $headers; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
// Set curl options |
201
|
|
|
curl_setopt_array($curl, $curl_options); |
202
|
|
|
|
203
|
|
|
if (($response_string = curl_exec($curl)) === FALSE) |
204
|
|
|
{ |
205
|
|
|
// Get the error code and message |
206
|
|
|
$code = curl_errno($curl); |
207
|
|
|
$error = curl_error($curl); |
208
|
|
|
|
209
|
|
|
// Close curl |
210
|
|
|
curl_close($curl); |
211
|
|
|
|
212
|
|
|
throw new Request_Exception('PayPal API request for :url failed: :error (:code)', $url, $request_data, array( |
213
|
|
|
':url' => $url, |
214
|
|
|
':error' => $error, |
215
|
|
|
':code' => $code |
216
|
|
|
)); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
// Close curl |
220
|
|
|
curl_close($curl); |
221
|
|
|
|
222
|
|
|
return static::parse_response($response_string, $url, $request_data); |
223
|
|
|
} |
224
|
|
|
} |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.