PluginProbe
Gravity Forms Eway / 2.2.1
Gravity Forms Eway v2.2.1
2.7.0 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.8.0 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 All 56 releases
gravityforms-eway / includes / class.GFEwayRapidAPI.php

class.GFEwayRapidAPI.php in Gravity Forms Eway 2.2.1, at includes/class.GFEwayRapidAPI.php

546 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * Class for dealing with an eWAY Rapid API payment
9 * @link https://eway.io/api-v3/
10 */
11 class GFEwayRapidAPI {
12
13 #region "constants"
14
15 // API hosts
16 const API_HOST_LIVE = 'https://api.ewaypayments.com';
17 const API_HOST_SANDBOX = 'https://api.sandbox.ewaypayments.com';
18
19 // API endpoints for REST/JSON
20 const API_DIRECT_PAYMENT = 'Transaction';
21
22 // valid actions
23 const METHOD_PAYMENT = 'ProcessPayment';
24 const METHOD_AUTHORISE = 'Authorise';
25
26 // valid transaction types
27 const TRANS_PURCHASE = 'Purchase';
28 const TRANS_RECURRING = 'Recurring';
29 const TRANS_MOTO = 'MOTO';
30
31 const PARTNER_ID = '4577fd8eb9014c7188d7be672c0e0d88';
32
33 #endregion // constants
34
35 #region "members"
36
37 #region "connection specific members"
38
39 /**
40 * use eWAY sandbox
41 * @var boolean
42 */
43 public $useSandbox;
44
45 /**
46 * capture payment (alternative is just authorise, no capture)
47 * @var boolean
48 */
49 public $capture;
50
51 /**
52 * default TRUE, whether to validate the remote SSL certificate
53 * @var boolean
54 */
55 public $sslVerifyPeer;
56
57 /**
58 * API key
59 * @var string
60 */
61 public $apiKey;
62
63 /**
64 * API password
65 * @var string
66 */
67 public $apiPassword;
68
69 /**
70 * Beagle: IP address of purchaser (from REMOTE_ADDR)
71 * @var string max. 50 characters
72 */
73 public $customerIP;
74
75 /**
76 * ID of device or application processing the transaction
77 * @var string max. 50 characters
78 */
79 public $deviceID;
80
81 #endregion // "connection specific members"
82
83 #region "payment specific members"
84
85 /**
86 * action to perform: one of the METHOD_* values
87 * @var string
88 */
89 public $method;
90
91 /**
92 * a unique transaction number from your site
93 * @var string max. 12 characters
94 */
95 public $transactionNumber;
96
97 /**
98 * an invoice reference to track by (NB: see transactionNumber which is intended for invoice number or similar)
99 * @var string max. 50 characters
100 */
101 public $invoiceReference;
102
103 /**
104 * description of what is being purchased / paid for
105 * @var string max. 64 characters
106 */
107 public $invoiceDescription;
108
109 /**
110 * total amount of payment, in dollars and cents as a floating-point number (will be converted to just cents for transmission)
111 * @var float
112 */
113 public $amount;
114
115 /**
116 * ISO 4217 currency code
117 * @var string 3 characters in uppercase
118 */
119 public $currencyCode;
120
121 // customer and billing details
122
123 /**
124 * customer's title
125 * @var string max. 5 characters
126 */
127 public $title;
128
129 /**
130 * customer's first name
131 * @var string max. 50 characters
132 */
133 public $firstName;
134
135 /**
136 * customer's last name
137 * @var string max. 50 characters
138 */
139 public $lastName;
140
141 /**
142 * customer's company name
143 * @var string max. 50 characters
144 */
145 public $companyName;
146
147 /**
148 * customer's job description (e.g. position)
149 * @var string max. 50 characters
150 */
151 public $jobDescription;
152
153 /**
154 * customer's address line 1
155 * @var string max. 50 characters
156 */
157 public $address1;
158
159 /**
160 * customer's address line 2
161 * @var string max. 50 characters
162 */
163 public $address2;
164
165 /**
166 * customer's suburb/city/town
167 * @var string max. 50 characters
168 */
169 public $suburb;
170
171 /**
172 * customer's state/province
173 * @var string max. 50 characters
174 */
175 public $state;
176
177 /**
178 * customer's postcode
179 * @var string max. 30 characters
180 */
181 public $postcode;
182
183 /**
184 * customer's country code
185 * @var string 2 characters lowercase
186 */
187 public $country;
188
189 /**
190 * customer's email address
191 * @var string max. 50 characters
192 */
193 public $emailAddress;
194
195 /**
196 * customer's phone number
197 * @var string max. 32 characters
198 */
199 public $phone;
200
201 /**
202 * customer's mobile phone number
203 * @var string max. 32 characters
204 */
205 public $mobile;
206
207 /**
208 * customer's fax number
209 * @var string max. 32 characters
210 */
211 public $fax;
212
213 /**
214 * customer's website URL
215 * @var string max. 512 characters
216 */
217 public $website;
218
219 /**
220 * comments about the customer
221 * @var string max. 255 characters
222 */
223 public $comments;
224
225 // card details
226
227 /**
228 * name on credit card
229 * @var string max. 50 characters
230 */
231 public $cardHoldersName;
232
233 /**
234 * credit card number, with no spaces
235 * @var string max. 50 characters
236 */
237 public $cardNumber;
238
239 /**
240 * month of expiry, numbered from 1=January
241 * @var integer max. 2 digits
242 */
243 public $cardExpiryMonth;
244
245 /**
246 * year of expiry
247 * @var integer will be truncated to 2 digits, can accept 4 digits
248 */
249 public $cardExpiryYear;
250
251 /**
252 * start month, numbered from 1=January
253 * @var integer max. 2 digits
254 */
255 public $cardStartMonth;
256
257 /**
258 * start year
259 * @var integer will be truncated to 2 digits, can accept 4 digits
260 */
261 public $cardStartYear;
262
263 /**
264 * card issue number
265 * @var string
266 */
267 public $cardIssueNumber;
268
269 /**
270 * CVN (Creditcard Verification Number) for verifying physical card is held by buyer
271 * @var string max. 3 or 4 characters (depends on type of card)
272 */
273 public $cardVerificationNumber;
274
275 /**
276 * optional additional information for use in shopping carts, etc.
277 * @var array[string] max. 254 characters each
278 */
279 public $options = array();
280
281 #endregion "payment specific members"
282
283 #endregion "members"
284
285 /**
286 * populate members with defaults, and set account and environment information
287 * @param string $apiKey eWAY API key
288 * @param string $apiPassword eWAY API password
289 * @param boolean $useSandbox use eWAY sandbox
290 * @param boolean $capture capture payment now, or authorise for later capture
291 */
292 public function __construct($apiKey, $apiPassword, $useSandbox = true, $capture = true) {
293 $this->apiKey = $apiKey;
294 $this->apiPassword = $apiPassword;
295 $this->useSandbox = $useSandbox;
296 $this->capture = $capture;
297 }
298
299 /**
300 * process a payment against eWAY; throws exception on error with error described in exception message.
301 * @throws GFEwayException
302 */
303 public function processPayment() {
304 $this->validate();
305 $json = $this->getPayment();
306 return $this->sendPaymentDirect($json);
307 }
308
309 /**
310 * validate the data members to ensure that sufficient and valid information has been given
311 */
312 protected function validate() {
313 $errors = array();
314
315 if (!is_numeric($this->amount) || $this->amount <= 0) {
316 $errors[] = __('amount must be given as a number in dollars and cents', 'gravityforms-eway');
317 }
318 else if (!is_float($this->amount)) {
319 $this->amount = (float) $this->amount;
320 }
321 if (strlen($this->cardHoldersName) === 0) {
322 $errors[] = __('cardholder name cannot be empty', 'gravityforms-eway');
323 }
324 if (strlen($this->cardNumber) === 0) {
325 $errors[] = __('card number cannot be empty', 'gravityforms-eway');
326 }
327
328 // make sure that card expiry month is a number from 1 to 12
329 if (!is_int($this->cardExpiryMonth)) {
330 if (strlen($this->cardExpiryMonth) === 0) {
331 $errors[] = __('card expiry month cannot be empty', 'gravityforms-eway');
332 }
333 elseif (!ctype_digit($this->cardExpiryMonth)) {
334 $errors[] = __('card expiry month must be a number between 1 and 12', 'gravityforms-eway');
335 }
336 else {
337 $this->cardExpiryMonth = intval($this->cardExpiryMonth);
338 }
339 }
340 if (is_int($this->cardExpiryMonth)) {
341 if ($this->cardExpiryMonth < 1 || $this->cardExpiryMonth > 12) {
342 $errors[] = __('card expiry month must be a number between 1 and 12', 'gravityforms-eway');
343 }
344 }
345
346 // make sure that card expiry year is a 2-digit or 4-digit year >= this year
347 if (!is_int($this->cardExpiryYear)) {
348 if (strlen($this->cardExpiryYear) === 0) {
349 $errors[] = __('card expiry year cannot be empty', 'gravityforms-eway');
350 }
351 elseif (!ctype_digit($this->cardExpiryYear)) {
352 $errors[] = __('card expiry year must be a two or four digit year', 'gravityforms-eway');
353 }
354 else {
355 $this->cardExpiryYear = intval($this->cardExpiryYear);
356 }
357 }
358 if (is_int($this->cardExpiryYear)) {
359 $thisYear = intval(date_create()->format('Y'));
360 if ($this->cardExpiryYear < 0 || $this->cardExpiryYear >= 100 && $this->cardExpiryYear < 2000 || $this->cardExpiryYear > $thisYear + 20) {
361 $errors[] = __('card expiry year must be a two or four digit year', 'gravityforms-eway');
362 }
363 else {
364 if ($this->cardExpiryYear > 100 && $this->cardExpiryYear < $thisYear) {
365 $errors[] = __("card expiry can't be in the past", 'gravityforms-eway');
366 }
367 else if ($this->cardExpiryYear < 100 && $this->cardExpiryYear < ($thisYear - 2000)) {
368 $errors[] = __("card expiry can't be in the past", 'gravityforms-eway');
369 }
370 }
371 }
372
373 if (count($errors) > 0) {
374 throw new GFEwayException(implode("\n", $errors));
375 }
376 }
377
378 /**
379 * create JSON request document for payment
380 * @return string
381 */
382 public function getPayment() {
383 $request = new stdClass();
384
385 $request->Customer = $this->getCustomerRecord();
386 $request->Payment = $this->getPaymentRecord();
387 $request->TransactionType = self::TRANS_PURCHASE;
388 $request->PartnerID = self::PARTNER_ID;
389 $request->Method = $this->capture ? self::METHOD_PAYMENT : self::METHOD_AUTHORISE;
390 $request->CustomerIP = $this->customerIP;
391
392 if (!empty($this->options)) {
393 $request->Options = $this->getOptionsRecord();
394 }
395
396 if (!empty($this->deviceID)) {
397 $request->DeviceID = substr($this->deviceID, 0, 50);
398 }
399
400 return wp_json_encode($request);
401 }
402
403 /**
404 * build Customer record for request
405 * @return stdClass
406 */
407 protected function getCustomerRecord() {
408 $record = new stdClass;
409
410 //~ $record->Reference = ''; // TODO: customer reference?
411 $record->Title = $this->title ? substr($this->title, 0, 5) : '';
412 $record->FirstName = $this->firstName ? substr($this->firstName, 0, 50) : '';
413 $record->LastName = $this->lastName ? substr($this->lastName, 0, 50) : '';
414 $record->Street1 = $this->address1 ? substr($this->address1, 0, 50) : '';
415 $record->Street2 = $this->address2 ? substr($this->address2, 0, 50) : '';
416 $record->City = $this->suburb ? substr($this->suburb, 0, 50) : '';
417 $record->State = $this->state ? substr($this->state, 0, 50) : '';
418 $record->PostalCode = $this->postcode ? substr($this->postcode, 0, 30) : '';
419 $record->Country = $this->country ? strtolower($this->country) : '';
420 $record->Email = $this->emailAddress ? substr($this->emailAddress, 0, 50) : '';
421 $record->CardDetails = $this->getCardDetailsRecord();
422
423 if (!empty($this->companyName)) {
424 $record->CompanyName = substr($this->companyName, 0, 50);
425 }
426
427 if (!empty($this->jobDescription)) {
428 $record->JobDescription = substr($this->jobDescription, 0, 50);
429 }
430
431 if (!empty($this->phone)) {
432 $record->Phone = substr($this->phone, 0, 32);
433 }
434
435 if (!empty($this->mobile)) {
436 $record->Mobile = substr($this->mobile, 0, 32);
437 }
438
439 if (!empty($this->fax)) {
440 $record->Fax = substr($this->fax, 0, 32);
441 }
442
443 if (!empty($this->website)) {
444 $record->Url = substr($this->website, 0, 512);
445 }
446
447 if (!empty($this->comments)) {
448 $record->Comments = substr($this->comments, 0, 255);
449 }
450
451 return $record;
452 }
453
454 /**
455 * build CardDetails record for request
456 * NB: TODO: does not currently handle StartMonth, StartYear, IssueNumber (used in UK)
457 * NB: card number and CVN can be very lengthy encrypted values
458 * @return stdClass
459 */
460 protected function getCardDetailsRecord() {
461 $record = new stdClass;
462
463 $record->Name = $this->cardHoldersName ? substr($this->cardHoldersName, 0, 50) : '';
464 $record->Number = $this->cardNumber ? $this->cardNumber : '';
465 $record->ExpiryMonth = sprintf('%02d', $this->cardExpiryMonth);
466 $record->ExpiryYear = sprintf('%02d', $this->cardExpiryYear % 100);
467 $record->CVN = $this->cardVerificationNumber ? $this->cardVerificationNumber : '';
468
469 return $record;
470 }
471
472 /**
473 * build Payment record for request
474 * @return stdClass
475 */
476 protected function getPaymentRecord() {
477 $record = new stdClass;
478
479 $record->TotalAmount = number_format($this->amount * 100, 0, '', '');
480 $record->InvoiceNumber = $this->transactionNumber ? substr($this->transactionNumber, 0, 12) : '';
481 $record->InvoiceDescription = $this->invoiceDescription ? substr($this->invoiceDescription, 0, 64) : '';
482 $record->InvoiceReference = $this->invoiceReference ? substr($this->invoiceReference, 0, 50) : '';
483 $record->CurrencyCode = $this->currencyCode ? substr($this->currencyCode, 0, 3) : '';
484
485 return $record;
486 }
487
488 /**
489 * build Options record for request
490 * @return array
491 */
492 protected function getOptionsRecord() {
493 $options = array();
494
495 foreach ($this->options as $option) {
496 if (!empty($option)) {
497 $options[] = array('Value' => substr($option, 0, 254));
498 }
499 }
500
501 return $options;
502 }
503
504 /**
505 * send the eWAY payment request and retrieve and parse the response
506 * @param string $request eWAY payment request as a JSON document, per eWAY specifications
507 * @return GFEwayRapidAPIResponse
508 * @throws GFEwayException
509 */
510 protected function sendPaymentDirect($request) {
511 // select host and endpoint
512 $host = $this->useSandbox ? self::API_HOST_SANDBOX : self::API_HOST_LIVE;
513 $endpoint = self::API_DIRECT_PAYMENT;
514 $url = "$host/$endpoint";
515
516 // execute the request, and retrieve the response
517 $response = wp_remote_post($url, array(
518 'user-agent' => 'Gravity Forms eWAY ' . GFEWAY_PLUGIN_VERSION,
519 'sslverify' => $this->sslVerifyPeer,
520 'timeout' => 60,
521 'headers' => array(
522 'Content-Type' => 'application/json',
523 'Authorization' => 'Basic ' . base64_encode("{$this->apiKey}:{$this->apiPassword}"),
524 ),
525 'body' => $request,
526 ));
527
528 if (is_wp_error($response)) {
529 $msg = $response->get_error_message();
530 throw new GFEwayException(sprintf(__('Error posting eWAY request: %s', 'gravityforms-eway'), $msg));
531 }
532
533 if (empty($response['response']['code']) || $response['response']['code'] !== 200) {
534 $msg = empty($response['response']['message']) ? $response['response']['code'] : $response['response']['message'];
535 throw new GFEwayException(sprintf(__('Error posting eWAY request: %s', 'gravityforms-eway'), $msg));
536 }
537
538 $responseJSON = $response['body'];
539
540 $response = new GFEwayRapidAPIResponse();
541 $response->loadResponse($responseJSON);
542 return $response;
543 }
544
545 }
546