Change eWAY processor to use guzzle, fix style issues and update info.xml and add...
[civicrm-core.git] / ext / ewaysingle / CRM / Core / Payment / eWAY.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
f452d72c 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
f452d72c
CW
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035 11
6a488035
TO
12/*
13 +--------------------------------------------------------------------+
775788cf 14 | eWAY Core Payment Module for CiviCRM version 5 & 1.9 |
6a488035
TO
15 +--------------------------------------------------------------------+
16 | Licensed to CiviCRM under the Academic Free License version 3.0 |
17 | |
18 | Written & Contributed by Dolphin Software P/L - March 2008 |
19 +--------------------------------------------------------------------+
20 | |
21 | This file is a part of CiviCRM. |
22 | |
23 | This code was initially based on the recent PayJunction module |
24 | contributed by Phase2 Technology, and then plundered bits from |
25 | the AuthorizeNet module contributed by Ideal Solution, and |
26 | referenced the eWAY code in Drupal 5.7's ecommerce-5.x-3.4 and |
27 | ecommerce-5.x-4.x-dev modules. |
28 | |
29 | Plus a bit of our own code of course - Peter Barwell |
30 | contact PB@DolphinSoftware.com.au if required. |
31 | |
b44e3f84 32 | NOTE: This initial eWAY module does not yet allow for recurring |
6a488035
TO
33 | payments - contact Peter Barwell or add yourself (or both) |
34 | |
35 | NOTE: The eWAY gateway only allows a single currency per account |
36 | (per eWAY CustomerID) ie you can only have one currency per |
37 | added Payment Processor. |
38 | The only way to add multi-currency is to code it so that a |
39 | different CustomerID is used per currency. |
40 | |
41 +--------------------------------------------------------------------+
e70a7fc0 42 */
6a488035
TO
43
44/**
353ffa53
TO
45 * -----------------------------------------------------------------------------------------------
46 * From the eWAY supplied 'Web.config' dated 25-Sep-2006 - check date and update links if required
47 * -----------------------------------------------------------------------------------------------
48 *
49 * LIVE gateway with CVN
50 * https://www.eway.com.au/gateway_cvn/xmlpayment.asp
51 *
52 * LIVE gateway without CVN
53 * https://www.eway.com.au/gateway/xmlpayment.asp
54 *
55 *
56 * Test gateway with CVN
57 * https://www.eway.com.au/gateway_cvn/xmltest/TestPage.asp
58 *
59 * Test gateway without CVN
60 * https://www.eway.com.au/gateway/xmltest/TestPage.asp
61 *
62 *
63 * LIVE gateway for Stored Transactions
64 * https://www.eway.com.au/gateway/xmlstored.asp
65 *
66 *
67 * -----------------------------------------------------------------------------------------------
68 * From the eWAY web-site - http://www.eway.com.au/Support/Developer/PaymentsRealTime.aspx
69 * -----------------------------------------------------------------------------------------------
70 * The test Customer ID is 87654321 - this is the only ID that will work on the test gateway.
71 * The test Credit Card number is 4444333322221111
72 * - this is the only credit card number that will work on the test gateway.
73 * The test Total Amount should end in 00 or 08 to get a successful response (e.g. $10.00 or $10.08)
74 * ie - all other amounts will return a failed response.
75 *
76 * -----------------------------------------------------------------------------------------------
c301f76e 77 */
404d48bf 78
1aaa2dcb 79use Civi\Payment\Exception\PaymentProcessorException;
ae1baeec 80use CRM_Ewaysingle_ExtensionUtil as E;
1aaa2dcb 81
404d48bf 82// require Standard eWAY API libraries
ae1baeec
SL
83require_once E::path('lib/eWAY/eWAY_GatewayRequest.php');
84require_once E::path('lib/eWAY/eWAY_GatewayResponse.php');
404d48bf 85
8246bca4 86/**
87 * Class CRM_Core_Payment_eWAY.
88 */
6a488035 89class CRM_Core_Payment_eWAY extends CRM_Core_Payment {
6a488035 90
68f481e6
SL
91 /**
92 * @var GuzzleHttp\Client
93 */
94 protected $guzzleClient;
95
c301f76e 96 /**
97 * *******************************************************
6a488035
TO
98 * Constructor
99 *
6a0b768e
TO
100 * @param string $mode
101 * The mode of operation: live or test.
6a488035 102 *
c301f76e 103 * @param int $paymentProcessor
dd244018 104 *
c301f76e 105 * *******************************************************
dd244018 106 */
00be9182 107 public function __construct($mode, &$paymentProcessor) {
6a488035
TO
108
109 // live or test
110 $this->_mode = $mode;
111 $this->_paymentProcessor = $paymentProcessor;
6a488035
TO
112 }
113
68f481e6
SL
114 /**
115 * @return \GuzzleHttp\Client
116 */
117 public function getGuzzleClient(): \GuzzleHttp\Client {
118 return $this->guzzleClient ?? new \GuzzleHttp\Client();
119 }
120
121 /**
122 * @param \GuzzleHttp\Client $guzzleClient
123 */
124 public function setGuzzleClient(\GuzzleHttp\Client $guzzleClient) {
125 $this->guzzleClient = $guzzleClient;
126 }
127
c301f76e 128 /**
ad37ac8e 129 * Sends request and receive response from eWAY payment process.
130 *
131 * @param array $params
132 *
133 * @return array|object
134 * @throws \Exception
c301f76e 135 */
00be9182 136 public function doDirectPayment(&$params) {
d597ad57 137 if (CRM_Utils_Array::value('is_recur', $params) == TRUE) {
2d296f18 138 throw new CRM_Core_Exception(ts('eWAY - recurring payments not implemented'));
6a488035
TO
139 }
140
141 if (!defined('CURLOPT_SSLCERT')) {
2d296f18 142 throw new CRM_Core_Exception(ts('eWAY - Gateway requires curl with SSL support'));
6a488035
TO
143 }
144
145 // eWAY Client ID
146 $ewayCustomerID = $this->_paymentProcessor['user_name'];
147 // eWAY Gateway URL
148 $gateway_URL = $this->_paymentProcessor['url_site'];
149
150 //------------------------------------
151 // create eWAY gateway objects
152 //------------------------------------
c301f76e 153 $eWAYRequest = new GatewayRequest();
6a488035
TO
154
155 if (($eWAYRequest == NULL) || (!($eWAYRequest instanceof GatewayRequest))) {
1aaa2dcb 156 throw new PaymentProcessorException('Error: Unable to create eWAY Request object.', 9001);
6a488035
TO
157 }
158
c301f76e 159 $eWAYResponse = new GatewayResponse();
6a488035
TO
160
161 if (($eWAYResponse == NULL) || (!($eWAYResponse instanceof GatewayResponse))) {
1aaa2dcb 162 throw new PaymentProcessorException(9002, 'Error: Unable to create eWAY Response object.', 9002);
6a488035
TO
163 }
164
165 /*
e70a7fc0
TO
166 //-------------------------------------------------------------
167 // NOTE: eWAY Doesn't use the following at the moment:
168 //-------------------------------------------------------------
169 $creditCardType = $params['credit_card_type'];
170 $currentcyID = $params['currencyID'];
171 $country = $params['country'];
172 */
6a488035 173
6a488035
TO
174 //-------------------------------------------------------------
175 // Prepare some composite data from _paymentProcessor fields
176 //-------------------------------------------------------------
177 $fullAddress = $params['street_address'] . ", " . $params['city'] . ", " . $params['state_province'] . ".";
353ffa53 178 $expireYear = substr($params['year'], 2, 2);
6a488035 179 $expireMonth = sprintf('%02d', (int) $params['month']);
6a488035
TO
180 $description = $params['description'];
181 $txtOptions = "";
182
183 $amountInCents = round(((float) $params['amount']) * 100);
184
185 $credit_card_name = $params['first_name'] . " ";
186 if (strlen($params['middle_name']) > 0) {
187 $credit_card_name .= $params['middle_name'] . " ";
188 }
189 $credit_card_name .= $params['last_name'];
190
191 //----------------------------------------------------------------------------------------------------
192 // We use CiviCRM's param's 'invoiceID' as the unique transaction token to feed to eWAY
193 // Trouble is that eWAY only accepts 16 chars for the token, while CiviCRM's invoiceID is an 32.
194 // As its made from a "$invoiceID = md5(uniqid(rand(), true));" then using the fierst 16 chars
195 // should be alright
196 //----------------------------------------------------------------------------------------------------
197 $uniqueTrnxNum = substr($params['invoiceID'], 0, 16);
198
199 //----------------------------------------------------------------------------------------------------
200 // OPTIONAL: If TEST Card Number force an Override of URL and CutomerID.
201 // During testing CiviCRM once used the LIVE URL.
202 // This code can be uncommented to override the LIVE URL that if CiviCRM does that again.
203 //----------------------------------------------------------------------------------------------------
204 // if ( ( $gateway_URL == "https://www.eway.com.au/gateway_cvn/xmlpayment.asp")
205 // && ( $params['credit_card_number'] == "4444333322221111" ) ) {
206 // $ewayCustomerID = "87654321";
207 // $gateway_URL = "https://www.eway.com.au/gateway_cvn/xmltest/testpage.asp";
208 // }
209
210 //----------------------------------------------------------------------------------------------------
211 // Now set the payment details - see http://www.eway.com.au/Support/Developer/PaymentsRealTime.aspx
212 //----------------------------------------------------------------------------------------------------
213 // 8 Chars - ewayCustomerID - Required
214 $eWAYRequest->EwayCustomerID($ewayCustomerID);
215 // 12 Chars - ewayTotalAmount (in cents) - Required
216 $eWAYRequest->InvoiceAmount($amountInCents);
217 // 50 Chars - ewayCustomerFirstName
218 $eWAYRequest->PurchaserFirstName($params['first_name']);
219 // 50 Chars - ewayCustomerLastName
220 $eWAYRequest->PurchaserLastName($params['last_name']);
221 // 50 Chars - ewayCustomerEmail
222 $eWAYRequest->PurchaserEmailAddress($params['email']);
223 // 255 Chars - ewayCustomerAddress
224 $eWAYRequest->PurchaserAddress($fullAddress);
225 // 6 Chars - ewayCustomerPostcode
226 $eWAYRequest->PurchaserPostalCode($params['postal_code']);
227 // 1000 Chars - ewayCustomerInvoiceDescription
228 $eWAYRequest->InvoiceDescription($description);
229 // 50 Chars - ewayCustomerInvoiceRef
230 $eWAYRequest->InvoiceReference($params['invoiceID']);
231 // 50 Chars - ewayCardHoldersName - Required
232 $eWAYRequest->CardHolderName($credit_card_name);
233 // 20 Chars - ewayCardNumber - Required
234 $eWAYRequest->CardNumber($params['credit_card_number']);
235 // 2 Chars - ewayCardExpiryMonth - Required
236 $eWAYRequest->CardExpiryMonth($expireMonth);
237 // 2 Chars - ewayCardExpiryYear - Required
238 $eWAYRequest->CardExpiryYear($expireYear);
239 // 4 Chars - ewayCVN - Required if CVN Gateway used
240 $eWAYRequest->CVN($params['cvv2']);
241 // 16 Chars - ewayTrxnNumber
242 $eWAYRequest->TransactionNumber($uniqueTrnxNum);
243 // 255 Chars - ewayOption1
244 $eWAYRequest->EwayOption1($txtOptions);
245 // 255 Chars - ewayOption2
246 $eWAYRequest->EwayOption2($txtOptions);
247 // 255 Chars - ewayOption3
248 $eWAYRequest->EwayOption3($txtOptions);
249
250 $eWAYRequest->CustomerIPAddress($params['ip_address']);
251 $eWAYRequest->CustomerBillingCountry($params['country']);
252
253 // Allow further manipulation of the arguments via custom hooks ..
254 CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $eWAYRequest);
255
256 //----------------------------------------------------------------------------------------------------
257 // Check to see if we have a duplicate before we send
258 //----------------------------------------------------------------------------------------------------
d253aeb8 259 if ($this->checkDupe($params['invoiceID'], CRM_Utils_Array::value('contributionID', $params))) {
1aaa2dcb 260 throw new PaymentProcessorException('It appears that this transaction is a duplicate. Have you already submitted the form once? If so there may have been a connection problem. Check your email for a receipt from eWAY. If you do not receive a receipt within 2 hours you can try your transaction again. If you continue to have problems please contact the site administrator.', 9003);
6a488035
TO
261 }
262
263 //----------------------------------------------------------------------------------------------------
264 // Convert to XML and send the payment information
265 //----------------------------------------------------------------------------------------------------
266 $requestxml = $eWAYRequest->ToXML();
267
68f481e6
SL
268 $responseData = (string) $this->getGuzzleClient()->post($this->_paymentProcessor['url_site'], [
269 'body' => $requestxml,
270 'curl' => [
271 CURLOPT_RETURNTRANSFER => TRUE,
272 CURLOPT_SSL_VERIFYPEER => Civi::settings()->get('verifySSL'),
273 ],
274 ])->getBody();
6a488035
TO
275
276 //----------------------------------------------------------------------------------------------------
277 // If null data returned - tell 'em and bail out
278 //
279 // NOTE: You will not necessarily get a string back, if the request failed for
280 // any reason, the return value will be the boolean false.
281 //----------------------------------------------------------------------------------------------------
282 if (($responseData === FALSE) || (strlen($responseData) == 0)) {
1aaa2dcb 283 throw new PaymentProcessorException('Error: Connection to payment gateway failed - no data returned.', 9006);
6a488035
TO
284 }
285
286 //----------------------------------------------------------------------------------------------------
287 // If gateway returned no data - tell 'em and bail out
288 //----------------------------------------------------------------------------------------------------
289 if (empty($responseData)) {
1aaa2dcb 290 throw new PaymentProcessorException('Error: No data returned from payment gateway.', 9007);
6a488035
TO
291 }
292
6a488035 293 //----------------------------------------------------------------------------------------------------
ceb10dc7 294 // Payment successfully sent to gateway - process the response now
6a488035
TO
295 //----------------------------------------------------------------------------------------------------
296 $eWAYResponse->ProcessResponse($responseData);
297
298 //----------------------------------------------------------------------------------------------------
299 // See if we got an OK result - if not tell 'em and bail out
300 //----------------------------------------------------------------------------------------------------
301 if (self::isError($eWAYResponse)) {
302 $eWayTrxnError = $eWAYResponse->Error();
09e49db4 303 CRM_Core_Error::debug_var('eWay Error', $eWayTrxnError, TRUE, TRUE);
1aaa2dcb 304 if (substr($eWayTrxnError, 0, 6) === 'Error:') {
305 throw new PaymentProcessorException($eWayTrxnError, 9008);
6a488035
TO
306 }
307 $eWayErrorCode = substr($eWayTrxnError, 0, 2);
308 $eWayErrorDesc = substr($eWayTrxnError, 3);
309
1aaa2dcb 310 throw new PaymentProcessorException('Error: [' . $eWayErrorCode . "] - " . $eWayErrorDesc . '.', 9008);
e70a7fc0 311 }
6a488035 312
6a488035
TO
313 //=============
314 // Success !
315 //=============
316 $beaglestatus = $eWAYResponse->BeagleScore();
317 if (!empty($beaglestatus)) {
1aaa2dcb 318 $beaglestatus = ': ' . $beaglestatus;
6a488035
TO
319 }
320 $params['trxn_result_code'] = $eWAYResponse->Status() . $beaglestatus;
6a488035
TO
321 $params['trxn_id'] = $eWAYResponse->TransactionNumber();
322
323 return $params;
324 }
518fa0ee 325
c301f76e 326 /**
ad37ac8e 327 * Checks the eWAY response status - returning a boolean false if status != 'true'.
328 *
329 * @param object $response
330 *
331 * @return bool
c301f76e 332 */
00be9182 333 public function isError(&$response) {
6a488035
TO
334 $status = $response->Status();
335
1aaa2dcb 336 if ((stripos($status, 'true')) === FALSE) {
6a488035
TO
337 return TRUE;
338 }
339 return FALSE;
340 }
341
c301f76e 342 /**
6a488035
TO
343 * This public function checks to see if we have the right processor config values set
344 *
345 * NOTE: Called by Events and Contribute to check config params are set prior to trying
346 * register any credit card details
347 *
77b97be7 348 * @return null|string
1aaa2dcb 349 * returns string $errorMsg if any errors found - null if OK
77b97be7 350 */
00be9182 351 public function checkConfig() {
be2fb01f 352 $errorMsg = [];
6a488035
TO
353
354 if (empty($this->_paymentProcessor['user_name'])) {
355 $errorMsg[] = ts('eWAY CustomerID is not set for this payment processor');
356 }
357
358 if (empty($this->_paymentProcessor['url_site'])) {
359 $errorMsg[] = ts('eWAY Gateway URL is not set for this payment processor');
360 }
361
362 if (!empty($errorMsg)) {
363 return implode('<p>', $errorMsg);
364 }
1aaa2dcb 365 return NULL;
6a488035
TO
366 }
367
6a488035 368}