Commit | Line | Data |
---|---|---|
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 | 79 | use Civi\Payment\Exception\PaymentProcessorException; |
ae1baeec | 80 | use CRM_Ewaysingle_ExtensionUtil as E; |
1aaa2dcb | 81 | |
404d48bf | 82 | // require Standard eWAY API libraries |
ae1baeec SL |
83 | require_once E::path('lib/eWAY/eWAY_GatewayRequest.php'); |
84 | require_once E::path('lib/eWAY/eWAY_GatewayResponse.php'); | |
404d48bf | 85 | |
8246bca4 | 86 | /** |
87 | * Class CRM_Core_Payment_eWAY. | |
88 | */ | |
6a488035 | 89 | class 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 | } |