PluginProbe
Gravity Forms Eway / 1.5.12
Gravity Forms Eway v1.5.12
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 / class.GFEwayPayment.php

class.GFEwayPayment.php in Gravity Forms Eway 1.5.12, at class.GFEwayPayment.php

438 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Classes for dealing with eWAY payments
4 *
5 * NB: for testing, the only card number seen as valid is '4444333322221111'
6 *
7 * @link http://www.eway.com.au/developers/api/direct-payments
8 * @link http://www.eway.com.au/developers/api/beagle-lite
9 *
10 * copyright (c) 2008-2014 WebAware Pty Ltd, released under GPL v2.1
11 */
12
13 /**
14 * Class for dealing with an eWAY payment
15 */
16 class GFEwayPayment {
17 // environment / website specific members
18 /**
19 * default FALSE, use eWAY sandbox unless set to TRUE
20 * @var boolean
21 */
22 public $isLiveSite;
23
24 /**
25 * default TRUE, whether to validate the remote SSL certificate
26 * @var boolean
27 */
28 public $sslVerifyPeer;
29
30 // payment specific members
31 /**
32 * account name / email address at eWAY
33 * @var string max. 8 characters
34 */
35 public $accountID;
36
37 /**
38 * an invoice reference to track by (NB: see transactionNumber which is intended for invoice number or similar)
39 * @var string max. 50 characters
40 */
41 public $invoiceReference;
42
43 /**
44 * description of what is being purchased / paid for
45 * @var string max. 10000 characters
46 */
47 public $invoiceDescription;
48
49 /**
50 * total amount of payment, in dollars and cents as a floating-point number (will be converted to just cents for transmission)
51 * @var float
52 */
53 public $amount;
54
55 /**
56 * customer's first name
57 * @var string max. 50 characters
58 */
59 public $firstName;
60
61 /**
62 * customer's last name
63 * @var string max. 50 characters
64 */
65 public $lastName;
66
67 /**
68 * customer's email address
69 * @var string max. 50 characters
70 */
71 public $emailAddress;
72
73 /**
74 * customer's address, including state, city and country
75 * @var string max. 255 characters
76 */
77 public $address;
78
79 /**
80 * customer's postcode
81 * @var string max. 6 characters
82 */
83 public $postcode;
84
85 /**
86 * name on credit card
87 * @var string max. 50 characters
88 */
89 public $cardHoldersName;
90
91 /**
92 * credit card number, with no spaces
93 * @var string max. 20 characters
94 */
95 public $cardNumber;
96
97 /**
98 * month of expiry, numbered from 1=January
99 * @var integer max. 2 digits
100 */
101 public $cardExpiryMonth;
102
103 /**
104 * year of expiry
105 * @var integer will be truncated to 2 digits, can accept 4 digits
106 */
107 public $cardExpiryYear;
108
109 /**
110 * CVN (Creditcard Verification Number) for verifying physical card is held by buyer
111 * @var string max. 3 or 4 characters (depends on type of card)
112 */
113 public $cardVerificationNumber;
114
115 /**
116 * eWAYTrxnNumber - This value is returned to your website.
117 *
118 * You can pass a unique transaction number from your site. You can update and track the status of a transaction when eWAY
119 * returns to your site.
120 *
121 * NB. This number is returned as 'ewayTrxnReference', member transactionReference of GFEwayResponse.
122 *
123 * @var string max. 16 characters
124 */
125 public $transactionNumber;
126
127 /**
128 * optional additional information for use in shopping carts, etc.
129 * @var string max. 255 characters
130 */
131 public $option1;
132
133 /**
134 * optional additional information for use in shopping carts, etc.
135 * @var string max. 255 characters
136 */
137 public $option2;
138
139 /**
140 * optional additional information for use in shopping carts, etc.
141 * @var string max. 255 characters
142 */
143 public $option3;
144
145 /**
146 * Beagle: country code for billing address
147 * @var string 2 characters
148 */
149 public $customerCountryCode;
150
151 /**
152 * Beagle: IP address of purchaser (from REMOTE_ADDR)
153 * @var string max. 15 characters
154 */
155 public $customerIP;
156
157 /** host for the eWAY Real Time API in the developer sandbox environment */
158 const REALTIME_API_SANDBOX = 'https://www.eway.com.au/gateway/xmltest/testpage.asp';
159 /** host for the eWAY Real Time API in the production environment */
160 const REALTIME_API_LIVE = 'https://www.eway.com.au/gateway/xmlpayment.asp';
161 /** host for the eWAY Real Time API with CVN verification in the developer sandbox environment */
162 const REALTIME_CVN_API_SANDBOX = 'https://www.eway.com.au/gateway_cvn/xmltest/testpage.asp';
163 /** host for the eWAY Real Time API with CVN verification in the production environment */
164 const REALTIME_CVN_API_LIVE = 'https://www.eway.com.au/gateway_cvn/xmlpayment.asp';
165 /** host for the eWAY Beagle API in the developer sandbox environment */
166 const REALTIME_BEAGLE_API_SANDBOX = 'https://www.eway.com.au/gateway_cvn/xmltest/BeagleTest.aspx';
167 /** host for the eWAY Beagle API in the production environment */
168 const REALTIME_BEAGLE_API_LIVE = 'https://www.eway.com.au/gateway_cvn/xmlbeagle.asp';
169
170 /**
171 * populate members with defaults, and set account and environment information
172 *
173 * @param string $accountID eWAY account ID
174 * @param boolean $isLiveSite running on the live (production) website
175 */
176 public function __construct($accountID, $isLiveSite = FALSE) {
177 $this->sslVerifyPeer = TRUE;
178 $this->isLiveSite = $isLiveSite;
179 $this->accountID = $accountID;
180 }
181
182 /**
183 * process a payment against eWAY; throws exception on error with error described in exception message.
184 */
185 public function processPayment() {
186 $this->validate();
187 $xml = $this->getPaymentXML();
188 return $this->sendPayment($xml);
189 }
190
191 /**
192 * validate the data members to ensure that sufficient and valid information has been given
193 */
194 private function validate() {
195 $errmsg = '';
196
197 if (strlen($this->accountID) === 0)
198 $errmsg .= "accountID cannot be empty.\n";
199 if (!is_numeric($this->amount) || $this->amount <= 0)
200 $errmsg .= "amount must be given as a number in dollars and cents.\n";
201 else if (!is_float($this->amount))
202 $this->amount = (float) $this->amount;
203 if (strlen($this->cardHoldersName) === 0)
204 $errmsg .= "card holder's name cannot be empty.\n";
205 if (strlen($this->cardNumber) === 0)
206 $errmsg .= "card number cannot be empty.\n";
207
208 // make sure that card expiry month is a number from 1 to 12
209 if (gettype($this->cardExpiryMonth) != 'integer') {
210 if (strlen($this->cardExpiryMonth) === 0)
211 $errmsg .= "card expiry month cannot be empty.\n";
212 else if (!is_numeric($this->cardExpiryMonth))
213 $errmsg .= "card expiry month must be a number between 1 and 12.\n";
214 else
215 $this->cardExpiryMonth = intval($this->cardExpiryMonth);
216 }
217 if (gettype($this->cardExpiryMonth) == 'integer') {
218 if ($this->cardExpiryMonth < 1 || $this->cardExpiryMonth > 12)
219 $errmsg .= "card expiry month must be a number between 1 and 12.\n";
220 }
221
222 // make sure that card expiry year is a 2-digit or 4-digit year >= this year
223 if (gettype($this->cardExpiryYear) != 'integer') {
224 if (strlen($this->cardExpiryYear) === 0)
225 $errmsg .= "card expiry year cannot be empty.\n";
226 else if (!preg_match('/^\d\d(\d\d)?$/', $this->cardExpiryYear))
227 $errmsg .= "card expiry year must be a two or four digit year.\n";
228 else
229 $this->cardExpiryYear = intval($this->cardExpiryYear);
230 }
231 if (gettype($this->cardExpiryYear) == 'integer') {
232 $thisYear = intval(date_create()->format('Y'));
233 if ($this->cardExpiryYear < 0 || $this->cardExpiryYear >= 100 && $this->cardExpiryYear < 2000 || $this->cardExpiryYear > $thisYear + 20)
234 $errmsg .= "card expiry year must be a two or four digit year.\n";
235 else {
236 if ($this->cardExpiryYear > 100 && $this->cardExpiryYear < $thisYear)
237 $errmsg .= "card expiry year can't be in the past.\n";
238 else if ($this->cardExpiryYear < 100 && $this->cardExpiryYear < ($thisYear - 2000))
239 $errmsg .= "card expiry year can't be in the past.\n";
240 }
241 }
242
243 if (strlen($errmsg) > 0)
244 throw new GFEwayException($errmsg);
245 }
246
247 /**
248 * create XML request document for payment parameters
249 *
250 * @return string
251 */
252 public function getPaymentXML() {
253 $xml = new XMLWriter();
254 $xml->openMemory();
255 $xml->startDocument('1.0', 'UTF-8');
256 $xml->startElement('ewaygateway');
257
258 $xml->writeElement('ewayCustomerID', $this->accountID);
259 $xml->writeElement('ewayTotalAmount', number_format($this->amount * 100, 0, '', ''));
260 $xml->writeElement('ewayCustomerFirstName', $this->firstName);
261 $xml->writeElement('ewayCustomerLastName', $this->lastName);
262 $xml->writeElement('ewayCustomerEmail', $this->emailAddress);
263 $xml->writeElement('ewayCustomerAddress', $this->address);
264 $xml->writeElement('ewayCustomerPostcode', $this->postcode);
265 $xml->writeElement('ewayCustomerInvoiceDescription', $this->invoiceDescription);
266 $xml->writeElement('ewayCustomerInvoiceRef', $this->invoiceReference);
267 $xml->writeElement('ewayCardHoldersName', $this->cardHoldersName);
268 $xml->writeElement('ewayCardNumber', $this->cardNumber);
269 $xml->writeElement('ewayCardExpiryMonth', sprintf('%02d', $this->cardExpiryMonth));
270 $xml->writeElement('ewayCardExpiryYear', sprintf('%02d', $this->cardExpiryYear % 100));
271 $xml->writeElement('ewayTrxnNumber', $this->transactionNumber);
272 $xml->writeElement('ewayOption1', $this->option1);
273 $xml->writeElement('ewayOption2', $this->option2);
274 $xml->writeElement('ewayOption3', $this->option3);
275 $xml->writeElement('ewayCVN', $this->cardVerificationNumber);
276
277 // Beagle data
278 if (!empty($this->customerCountryCode)) {
279 if (empty($this->customerIP)) {
280 $this->customerIP = GFEwayPlugin::getCustomerIP();
281 }
282 $xml->writeElement('ewayCustomerIPAddress', $this->customerIP);
283 $xml->writeElement('ewayCustomerBillingCountry', $this->customerCountryCode);
284 }
285
286 $xml->endElement(); // ewaygateway
287
288 return $xml->outputMemory();
289 }
290
291 /**
292 * send the eWAY payment request and retrieve and parse the response
293 *
294 * @return GFEwayResponse
295 * @param string $xml eWAY payment request as an XML document, per eWAY specifications
296 */
297 private function sendPayment($xml) {
298 // select endpoint URL, use sandbox if not from live website
299 if (!empty($this->customerCountryCode)) {
300 // use Beagle anti-fraud endpoints
301 $url = $this->isLiveSite ? self::REALTIME_BEAGLE_API_LIVE : self::REALTIME_BEAGLE_API_SANDBOX;
302 }
303 else if (empty($this->cardVerificationNumber)) {
304 // no CVN -- do these endpoints still work?
305 $url = $this->isLiveSite ? self::REALTIME_API_LIVE : self::REALTIME_API_SANDBOX;
306 }
307 else {
308 // normal Direct Payments endpoints with CVN verification
309 $url = $this->isLiveSite ? self::REALTIME_CVN_API_LIVE : self::REALTIME_CVN_API_SANDBOX;
310 }
311
312 //~ error_log(__METHOD__ . ": url = $url");
313
314 // execute the cURL request, and retrieve the response
315 try {
316 $responseXML = GFEwayPlugin::curlSendRequest($url, $xml, $this->sslVerifyPeer);
317 }
318 catch (GFEwayCurlException $e) {
319 throw new GFEwayException("Error posting eWAY payment to $url: " . $e->getMessage());
320 }
321
322 $response = new GFEwayResponse();
323 $response->loadResponseXML($responseXML);
324 return $response;
325 }
326 }
327
328 /**
329 * Class for dealing with an eWAY payment response
330 */
331 class GFEwayResponse {
332 /**
333 * For a successful transaction "True" is passed and for a failed transaction "False" is passed.
334 * @var boolean
335 */
336 public $status;
337
338 /**
339 * eWAYTrxnNumber
340 * @var string max. 16 characters
341 */
342 public $transactionNumber;
343
344 /**
345 * eWAYTrxnNumber referenced in transaction (e.g. invoice number)
346 * @var string max. 16 characters
347 */
348 public $transactionReference;
349
350 /**
351 * optional additional information for use in shopping carts, etc.
352 * @var string max. 255 characters
353 */
354 public $option1;
355
356 /**
357 * optional additional information for use in shopping carts, etc.
358 * @var string max. 255 characters
359 */
360 public $option2;
361
362 /**
363 * optional additional information for use in shopping carts, etc.
364 * @var string max. 255 characters
365 */
366 public $option3;
367
368 /**
369 * If the transaction is successful, this is the bank authorisation number. This is also sent in the email receipt.
370 * @var string max. 6 characters
371 */
372 public $authCode;
373
374 /**
375 * total amount of payment as processed, in dollars and cents as a floating-point number
376 * @var float
377 */
378 public $amount;
379
380 /**
381 * the response returned by the bank, and can be related to both successful and failed transactions.
382 * @var string max. 100 characters
383 */
384 public $error;
385
386 /**
387 * load eWAY response data as XML string
388 *
389 * @param string $response eWAY response as a string (hopefully of XML data)
390 */
391 public function loadResponseXML($response) {
392 try {
393 // prevent XML injection attacks, and handle errors without warnings
394 $oldDisableEntityLoader = libxml_disable_entity_loader(TRUE);
395 $oldUseInternalErrors = libxml_use_internal_errors(TRUE);
396
397 //~ error_log(__METHOD__ . "\n" . $response);
398
399 $xml = simplexml_load_string($response);
400 if ($xml === false) {
401 $errmsg = '';
402 foreach (libxml_get_errors() as $error) {
403 $errmsg .= $error->message;
404 }
405 throw new Exception($errmsg);
406 }
407
408 $this->status = (strcasecmp((string) $xml->ewayTrxnStatus, 'true') === 0);
409 $this->transactionNumber = (string) $xml->ewayTrxnNumber;
410 $this->transactionReference = (string) $xml->ewayTrxnReference;
411 $this->option1 = (string) $xml->ewayTrxnOption1;
412 $this->option2 = (string) $xml->ewayTrxnOption2;
413 $this->option3 = (string) $xml->ewayTrxnOption3;
414 $this->authCode = (string) $xml->ewayAuthCode;
415 $this->error = (string) $xml->ewayTrxnError;
416
417 $this->beagleScore = (string) $xml->ewayBeagleScore;
418
419 // if we got an amount, convert it back into dollars.cents from just cents
420 if (!empty($xml->ewayReturnAmount))
421 $this->amount = floatval($xml->ewayReturnAmount) / 100.0;
422 else
423 $this->amount = NULL;
424
425 // restore old libxml settings
426 libxml_disable_entity_loader($oldDisableEntityLoader);
427 libxml_use_internal_errors($oldUseInternalErrors);
428 }
429 catch (Exception $e) {
430 // restore old libxml settings
431 libxml_disable_entity_loader($oldDisableEntityLoader);
432 libxml_use_internal_errors($oldUseInternalErrors);
433
434 throw new GFEwayException('Error parsing eWAY response: ' . $e->getMessage());
435 }
436 }
437 }
438