Payment   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 214
Duplicated Lines 0 %

Coupling/Cohesion

Components 7
Dependencies 3

Test Coverage

Coverage 69.05%

Importance

Changes 0
Metric Value
wmc 33
lcom 7
cbo 3
dl 0
loc 214
ccs 58
cts 84
cp 0.6905
rs 9.76
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A instance() 0 10 2
A merchant_endpoint_url() 0 4 1
A webscr_url() 0 11 3
A environment() 0 12 3
A __construct() 0 4 1
A config() 0 18 6
A order() 0 9 2
A return_url() 0 9 2
A cancel_url() 0 9 2
A notify_url() 0 9 2
A request() 0 47 4
A parse_response() 0 13 5
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)
0 ignored issues
show
Bug Best Practice introduced by
The expression $request_data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
191
		{
192
			$curl_options[CURLOPT_POSTFIELDS] = http_build_query($request_data, NULL, '&');
193
		}
194
195
		if ($headers)
0 ignored issues
show
Bug Best Practice introduced by
The expression $headers of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
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
}