-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpoundpay.php
More file actions
executable file
·252 lines (201 loc) · 7.46 KB
/
poundpay.php
File metadata and controls
executable file
·252 lines (201 loc) · 7.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
<?php
/**
* PoundPay API Client / Response / Signature Verifier
*
* TODO: give example usage
*
* @category APIClients
* @package poundpay
* @author PoundPay Inc.
* @version v1.0.3
* @link http://dev.poundpay.com/
* @requires php-curl, json
*/
// does curl extension exist?
if( !extension_loaded("curl") ) {
$error_msg = "Curl extension is required for PoundPayAPIClient to work";
throw(new Exception($error_msg));
}
// does the json extension exist?
if( !extension_loaded("json") ) {
$error_msg = "JSON extension is required for PoundPayAPIClient to work";
throw(new Exception($error_msg));
}
/*
* PoundPayAPIClient throws PoundPayAPIException on any errors
* encountered during a REST request.
* Catch this exception when making a request
*
*/
class PoundPayAPIException extends Exception {}
/*
* PoundPayAPIClient: the core API client, talks to the PoundPay REST API.
* @return
* Returns a PoundPayAPIResponse object for all responses if PoundPay's
* API was reachable.
* @throws
* Throws a PoundPayAPIException if PoundPay's API was unreachable
*
*/
class PoundPayAPIClient {
protected $developer_sid;
protected $auth_token;
protected $api_uri;
protected $version;
/*
* __construct
* $developer_sid : Your Developer SID
* $auth_token : Your account's auth_token
* $api_uri : The PoundPay REST Service URI, defaults to https://api.poundpay.com
* $version : The PoundPay API version
*/
public function __construct($developer_sid,
$auth_token,
$api_uri="https://api.poundpay.com",
$version='silver') {
$this->developer_sid = $developer_sid;
$this->auth_token = $auth_token;
$this->api_uri = $api_uri;
$this->version = $version;
}
/*
* request()
* Sends an HTTP Request to the PoundPay API
* $endpoint : the URL (relative to the endpoint URL, after the /{version})
* $method : the HTTP method to use, defaults to GET
* $vars : for POST or PUT, a key/value associative array of data to
* send, for GET will be appended to the URL as query params
*/
public function request($endpoint, $method="GET", $vars=array()) {
$fp = null;
$tmpfile = "";
$encoded = "";
foreach($vars AS $key => $value) {
$encoded .= "$key=" . urlencode($value) . "&";
}
$encoded = rtrim($encoded, "&");
// construct full url
$endpoint = rtrim($endpoint, "/"); // ensure that they're one slash at the end
$url = "{$this->api_uri}/{$this->version}{$endpoint}/";
// if GET and vars, append them
if($method == "GET") {
// checks to see if the path already has encoded attributes
// then just append the encoded string using & if it does or
// append post ?
$url .= (FALSE === strpos($path, '?') ? "?" : "&") . $encoded;
}
// initialize a new curl object
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
switch(strtoupper($method)) {
case "GET":
curl_setopt($curl, CURLOPT_HTTPGET, TRUE);
break;
case "POST":
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $encoded);
break;
case "PUT":
$tmpfile = tempnam("/tmp", "put_");
$fp = fopen($tmpfile, 'r');
curl_setopt($curl, CURLOPT_POSTFIELDS, $encoded);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
file_put_contents($tmpfile, $encoded);
curl_setopt($curl, CURLOPT_INFILE, $fp);
curl_setopt($curl, CURLOPT_INFILESIZE, filesize($tmpfile));
break;
case "DELETE":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
break;
default:
throw(new PoundPayAPIException("Unknown method $method"));
break;
}
// send credentials
curl_setopt($curl, CURLOPT_USERPWD, $pwd = "{$this->developer_sid}:{$this->auth_token}");
// do the request. If FALSE, then an exception occurred
if(FALSE === ($result = curl_exec($curl))) {
throw(new PoundPayAPIException("Curl failed with error " . curl_error($curl)));
}
// get result code
$response_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// unlink tmpfiles and clean up
if($fp) {
fclose($fp);
}
if(strlen($tmpfile)) {
unlink($tmpfile);
}
return new PoundPayAPIResponse($url, $result, $response_code);
}
}
/*
* PoundPayAPIResponse holds all the resource response data
* Before using the reponse, check $is_error to see if an exception
* occurred with the data sent to PoundPay.
* $response_json will contain a decoded json response object
* $response_text contains the raw string response
* $url and $query_string are from the original HTTP request
* $status_code is the response code of the request
*/
class PoundPayAPIResponse {
public $response_text;
public $response_json;
public $status_code;
public $url;
public $query_string;
public $is_error;
public $error_name;
public $error_msg;
public function __construct($url, $text, $status_code) {
$parsed_url = parse_url($url);
$this->url = $parsed_url["scheme"] . "//" . $parsed_url["host"];
$this->query_string = null;
if(array_key_exists("query", $parsed_url)){
$this->query_string = $parsed_url["query"];
}
$this->response_text = $text;
$this->status_code = $status_code;
if($status_code != 204) {
$this->response_json = json_decode($text);
}
$this->is_error = FALSE;
if($this->error_msg = ($status_code >= 400)) {
$this->is_error = TRUE;
$this->error_name = $this->response_json['error_name'];
$this->error_msg = $this->response_json['error_message'];
}
}
}
class PoundPaySignatureVerifier {
protected $developer_sid;
protected $auth_token;
function __construct($developer_sid, $auth_token) {
$this->auth_token = $auth_token;
$this->developer_sid = $developer_sid;
}
public function is_authentic_response($expected_signature, $url, $post_data = array()) {
$data_string = $this->build_data_string($url, $post_data);
$calculated_signature = $this->calculate_signature($data_string);
return $expected_signature == $calculated_signature;
}
public function build_data_string($url, $data) {
$data_string = $url;
// sort the array by keys
ksort($data);
// append them to the data string in order
// with no delimiters
foreach($data AS $key => $value) {
$data_string .= "{$key}{$value}";
}
return $data_string;
}
public function calculate_signature($data_string) {
// Note: hash_hmac requires PHP 5 >= 5.1.2 or PECL hash:1.1-1.5
// Or http://pear.php.net/package/Crypt_HMAC/
$signature = hash_hmac("sha1", $data_string, $this->auth_token, true);
// encode signature in base64
$encoded_signature = base64_encode($signature);
return $encoded_signature;
}
}