666999 - Version 0.3.9

Version Notes

Implements 3D Secure payment feature.

Download this release

Release Info

Developer Demac Media
Extension 666999
Version 0.3.9
Comparing to
See all releases


Code changes from version 0.3.8 to 0.3.9

app/code/community/Demac/.DS_Store ADDED
Binary file
app/code/community/Demac/Optimal/Block/Navigation.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Demac_Optimal_Block_Navigation extends Mage_Customer_Block_Account_Navigation
4
+ {
5
+ public function getLinks()
6
+ {
7
+ if (!Mage::helper('optimal')->canShow()) {
8
+ if (isset($this->_links['optimal_profiles'])) {
9
+ unset($this->_links['optimal_profiles']);
10
+ }
11
+ }
12
+
13
+ return parent::getLinks();
14
+ }
15
+ }
app/code/community/Demac/Optimal/Helper/Data.php CHANGED
@@ -123,35 +123,65 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
123
 
124
  $customerProfile['lastName'] = (string) $customerData['lastname'];
125
  $customerProfile['firstName'] = (string) $customerData['firstname'];
 
 
 
 
126
 
127
  if (!$customerData['is_guest']) {
128
- // Check if there is a profile_id being passed
129
- if (!empty($customerData['profile_id'])) {
130
- $profile = Mage::getModel('optimal/creditcard')->load((int)$customerData['profile_id']);
 
 
 
 
 
 
 
131
  if ($profile->getProfileId()) {
132
- $customerProfile['id'] = (string)$profile->getProfileId();
133
 
134
- // In case the profile exists
135
- if (!$saveCard) {
136
- $customerProfile['paymentToken'] = (string)$profile->getPaymentToken();
137
- }
138
- } else {
139
- Mage::throwException($this->__("The select profile does not exists."));
140
  }
141
- } elseif($saveCard) {
142
 
143
- // Check for existing profile id
144
- $customerId = Mage::getSingleton('customer/session')->getId();
145
- $merchantCustomerId = $this->getMerchantCustomerId($customerId);
146
- $merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
147
- $profile = Mage::getModel('optimal/creditcard')->loadByMerchantCustomerId($merchantCustomerId);
148
-
149
- if($profile->getProfileId()) {
150
- $customerProfile['id'] = (string)$profile->getProfileId();
151
- }else {
152
- $customerProfile['merchantCustomerId'] = $merchantCustomerId;
153
  }
154
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
156
  }
157
 
@@ -178,7 +208,7 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
178
  break;
179
  }
180
 
181
- $skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D');
182
 
183
  if($skip3d)
184
  {
@@ -186,11 +216,21 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
186
  'key' => (string) 'skip3D',
187
  'value' => true
188
  );
 
 
 
 
 
189
  } else {
190
  $extendedOptionsArray[] = array(
191
  'key' => (string) 'skip3D',
192
  'value' => false
193
  );
 
 
 
 
 
194
  }
195
 
196
  $addendumDataArray = array();
@@ -311,55 +351,37 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
311
  'transaction.status'
312
  ),
313
  'synchronous' => true,
314
- 'uri' => Mage::getBaseUrl()
315
  );
316
 
317
  // Callback information
318
  $redirectArray = array();
 
 
319
  $redirectArray[] = array(
320
  'rel' => (string) 'on_success',
321
- 'returnKeys' => array(
322
- 'id',
323
- 'transaction.confirmationNumber',
324
- 'transaction.status'
325
- ),
326
- 'uri' => Mage::getBaseUrl()
327
  );
328
  $redirectArray[] = array(
329
  'rel' => (string) 'on_error',
330
- 'returnKeys' => array(
331
- 'id',
332
- 'transaction.confirmationNumber',
333
- 'transaction.status'
334
- ),
335
- 'uri' => Mage::getBaseUrl()
336
  );
337
  $redirectArray[] = array(
338
  'rel' => (string) 'on_decline',
339
- 'returnKeys' => array(
340
- 'id',
341
- 'transaction.confirmationNumber',
342
- 'transaction.status'
343
- ),
344
- 'uri' => Mage::getBaseUrl()
345
  );
346
  $redirectArray[] = array(
347
  'rel' => (string) 'on_timeout',
348
- 'returnKeys' => array(
349
- 'id',
350
- 'transaction.confirmationNumber',
351
- 'transaction.status'
352
- ),
353
- 'uri' => Mage::getBaseUrl()
354
  );
355
  $redirectArray[] = array(
356
  'rel' => (string) 'on_hold',
357
- 'returnKeys' => array(
358
- 'id',
359
- 'transaction.confirmationNumber',
360
- 'transaction.status'
361
- ),
362
- 'uri' => Mage::getBaseUrl()
363
  );
364
 
365
  // Add extra information to the order Data
@@ -372,8 +394,8 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
372
  $data['extendedOptions'] = $extendedOptionsArray;
373
  $data['addendumData'] = $addendumDataArray;
374
 
 
375
  return $data;
376
-
377
  }
378
 
379
  public function getMsgByCode($code = null)
@@ -393,4 +415,31 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
393
  return $msg;
394
  }
395
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  }
123
 
124
  $customerProfile['lastName'] = (string) $customerData['lastname'];
125
  $customerProfile['firstName'] = (string) $customerData['firstname'];
126
+ $merchantCustomerId = null;
127
+
128
+ $skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
129
+ $profilesEnabled = Mage::getStoreConfig('payment/optimal_profiles/active', Mage::app()->getStore()->getStoreId());
130
 
131
  if (!$customerData['is_guest']) {
132
+
133
+ if (!isset($customerId)) {
134
+ $customerId = Mage::getSingleton('customer/session')->getId();
135
+ }
136
+
137
+ $profile = Mage::getModel('optimal/creditcard')->load($customerId, 'customer_id');
138
+
139
+ // If not skipping 3D and CreateProfiles is TRUE
140
+ if (!$skip3d && $profilesEnabled) {
141
+
142
  if ($profile->getProfileId()) {
 
143
 
144
+ $customerProfile['id'] = (string) $profile->getProfileId();
145
+
146
+ } elseif (!isset($merchantCustomerId)) {
147
+ $merchantCustomerId = $this->getMerchantCustomerId($customerId);
148
+ $merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
149
+ $customerProfile['merchantCustomerId'] = $merchantCustomerId;
150
  }
 
151
 
152
+ } elseif (!$skip3d && !$profilesEnabled) {
153
+
154
+ if ($profile->getProfileId()) {
155
+ $customerProfile['id'] = $profile->getProfileId();
 
 
 
 
 
 
156
  }
157
 
158
+ } else {
159
+ if (!empty($customerData['profile_id'])) { // Check if there is a profile_id being passed
160
+ $profile = Mage::getModel('optimal/creditcard')->load((int)$customerData['profile_id']);
161
+ if ($profile->getProfileId()) {
162
+ $customerProfile['id'] = (string)$profile->getProfileId();
163
+
164
+ // In case the profile exists
165
+ if (!$saveCard) {
166
+ $customerProfile['paymentToken'] = (string)$profile->getPaymentToken();
167
+ }
168
+ } else {
169
+ Mage::throwException($this->__("The select profile does not exists."));
170
+ }
171
+ } elseif($saveCard) {
172
+
173
+ // Check for existing profile id
174
+ $customerId = Mage::getSingleton('customer/session')->getId();
175
+ $merchantCustomerId = $this->getMerchantCustomerId($customerId);
176
+ $merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
177
+ $profile = Mage::getModel('optimal/creditcard')->loadByMerchantCustomerId($merchantCustomerId);
178
+
179
+ if($profile->getProfileId()) {
180
+ $customerProfile['id'] = (string)$profile->getProfileId();
181
+ }else {
182
+ $customerProfile['merchantCustomerId'] = $merchantCustomerId;
183
+ }
184
+ }
185
  }
186
  }
187
 
208
  break;
209
  }
210
 
211
+ $skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
212
 
213
  if($skip3d)
214
  {
216
  'key' => (string) 'skip3D',
217
  'value' => true
218
  );
219
+ // since we are skipping 3D-Secure check, hence we can process the order via Silent Post
220
+ $extendedOptionsArray[] = array(
221
+ 'key' => 'silentPost',
222
+ 'value' => true
223
+ );
224
  } else {
225
  $extendedOptionsArray[] = array(
226
  'key' => (string) 'skip3D',
227
  'value' => false
228
  );
229
+
230
+ $extendedOptionsArray[] = array(
231
+ 'key' => 'disablePaymentPageEditing',
232
+ 'value' => true
233
+ );
234
  }
235
 
236
  $addendumDataArray = array();
351
  'transaction.status'
352
  ),
353
  'synchronous' => true,
354
+ 'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
355
  );
356
 
357
  // Callback information
358
  $redirectArray = array();
359
+ $returnKeys = array('id', 'transaction.confirmationNumber', 'transaction.status');
360
+
361
  $redirectArray[] = array(
362
  'rel' => (string) 'on_success',
363
+ 'returnKeys' => $returnKeys,
364
+ 'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
 
 
 
 
365
  );
366
  $redirectArray[] = array(
367
  'rel' => (string) 'on_error',
368
+ 'returnKeys' => $returnKeys,
369
+ 'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
 
 
 
 
370
  );
371
  $redirectArray[] = array(
372
  'rel' => (string) 'on_decline',
373
+ 'returnKeys' => $returnKeys,
374
+ 'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
 
 
 
 
375
  );
376
  $redirectArray[] = array(
377
  'rel' => (string) 'on_timeout',
378
+ 'returnKeys' => $returnKeys,
379
+ 'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
 
 
 
 
380
  );
381
  $redirectArray[] = array(
382
  'rel' => (string) 'on_hold',
383
+ 'returnKeys' => $returnKeys,
384
+ 'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
 
 
 
 
385
  );
386
 
387
  // Add extra information to the order Data
394
  $data['extendedOptions'] = $extendedOptionsArray;
395
  $data['addendumData'] = $addendumDataArray;
396
 
397
+ Mage::log($data, null, 'NetBanxData.log');
398
  return $data;
 
399
  }
400
 
401
  public function getMsgByCode($code = null)
415
  return $msg;
416
  }
417
 
418
+ public function restoreQuote()
419
+ {
420
+ $checkoutSession = Mage::getSingleton('checkout/session');
421
+ $order = $checkoutSession->getLastRealOrder();
422
+ if ($order->getId()) {
423
+ $quote = Mage::getModel('sales/quote')->load($order->getQuoteId());
424
+ if ($quote->getId()) {
425
+ $quote->setIsActive(1)
426
+ ->setReservedOrderId(null)
427
+ ->save();
428
+ $checkoutSession->replaceQuote($quote)
429
+ ->unsLastRealOrderId();
430
+ return true;
431
+ }
432
+ }
433
+ return false;
434
+ }
435
+
436
+ public function canShow()
437
+ {
438
+ $skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
439
+ $profilesEnabled = Mage::getStoreConfig('payment/optimal_profiles/active', Mage::app()->getStore()->getStoreId());
440
+ $show = ($profilesEnabled && $skip3d);
441
+
442
+ return $show;
443
+ }
444
+
445
  }
app/code/community/Demac/Optimal/Model/Creditcard.php CHANGED
@@ -27,4 +27,11 @@ class Demac_Optimal_Model_Creditcard extends Mage_Core_Model_Abstract
27
  return $this;
28
 
29
  }
 
 
 
 
 
 
 
30
  }
27
  return $this;
28
 
29
  }
30
+
31
+ public function loadByCustomerId($customerId)
32
+ {
33
+ return $this->load($customerId, 'customer_id');
34
+ // $this->_getResource()->loadByCustomerId($this, $customerId);
35
+ // return $this;
36
+ }
37
  }
app/code/community/Demac/Optimal/Model/Hosted/Client.php CHANGED
@@ -199,30 +199,56 @@ class Demac_Optimal_Model_Hosted_Client extends Demac_Optimal_Model_Client_Abstr
199
  */
200
  protected function callApi($url, $method, $data = array())
201
  {
202
-
 
203
  $response = json_decode($this->_callApi($url,$method,$data));
 
 
 
 
 
 
 
 
204
 
205
  if (isset($response->error)) {
206
- Mage::helper('optimal')->cleanMerchantCustomerId(Mage::getSingleton('customer/session')->getId());
207
- $message = $this->_getMsgByCode($response->error->code);
208
- $message = ($message !== null) ? $message : $response->error->message;
 
 
 
 
 
 
209
 
210
  throw new Demac_Optimal_Model_Hosted_Exception($message);
211
- return false;
212
  }
213
 
214
  if (isset($response->transaction->errorCode)) {
215
- $message = $this->_getMsgByCode($response->transaction->errorCode);
216
- $message = ($message !== null) ? $message : $response->transaction->errorMessage;
 
 
 
 
 
 
 
 
 
 
 
 
 
217
 
218
- $session = Mage::getSingleton('customer/session');
219
  if (!$session->getCustomerId()) {
220
- Mage::getSingleton('customer/session')->addError($message);
221
  }
222
- Mage::helper('optimal')->cleanMerchantCustomerId(Mage::getSingleton('customer/session')->getId());
 
223
 
224
  throw new Demac_Optimal_Model_Hosted_Exception($message);
225
- return false;
226
  }
227
 
228
  return $response;
@@ -254,7 +280,6 @@ class Demac_Optimal_Model_Hosted_Client extends Demac_Optimal_Model_Client_Abstr
254
  */
255
  protected function _callApi($url,$mode,$data = array())
256
  {
257
- $helper = Mage::helper('optimal');
258
  $data = json_encode($data);
259
 
260
  try {
@@ -302,8 +327,8 @@ class Demac_Optimal_Model_Hosted_Client extends Demac_Optimal_Model_Client_Abstr
302
  Mage::logException($e);
303
  return false;
304
  }
305
- Mage::log('OPTIMAL RESPONSE (_callApi):');
306
- Mage::log($curl_response);
307
  return $curl_response;
308
  }
309
 
@@ -331,15 +356,20 @@ class Demac_Optimal_Model_Hosted_Client extends Demac_Optimal_Model_Client_Abstr
331
  $this->_checkCurlVerifyPeer($curl);
332
 
333
  //set the url, number of POST vars, POST data
334
- curl_setopt($curl,CURLOPT_URL, $url);
335
- curl_setopt($curl,CURLOPT_POST, true);
336
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
337
- curl_setopt($curl,CURLOPT_POSTFIELDS, $data_string);
 
338
  $curl_response = curl_exec($curl);
339
 
340
- Mage::log('OPTIMAL RESPONSE (submitPayment):');
341
- Mage::log($curl_response);
 
 
 
342
  curl_close($curl);
 
343
  return true;
344
 
345
  } catch (Exception $e) {
199
  */
200
  protected function callApi($url, $method, $data = array())
201
  {
202
+ $helper = Mage::helper('optimal');
203
+ $session = Mage::getSingleton('customer/session');
204
  $response = json_decode($this->_callApi($url,$method,$data));
205
+ $defaultMessage = 'Payment Gateway Error. Please contact the site admin.';
206
+
207
+ if (isset($response->error) && !isset($response->error->code)) {
208
+ Mage::log('Corrupt Response from Gateway:', null, 'demac_optimal.log');
209
+ Mage::log($response, null, 'demac_optimal.log');
210
+ $helper->cleanMerchantCustomerId($session->getId());
211
+ throw new Demac_Optimal_Model_Hosted_Exception($defaultMessage);
212
+ }
213
 
214
  if (isset($response->error)) {
215
+ $message = $helper->getMsgByCode($response->error->code);
216
+
217
+ if ($message === null && isset($response->error->message)) {
218
+ $message = $response->error->message;
219
+ } else {
220
+ $message = $defaultMessage;
221
+ }
222
+
223
+ $helper->cleanMerchantCustomerId($session->getId());
224
 
225
  throw new Demac_Optimal_Model_Hosted_Exception($message);
 
226
  }
227
 
228
  if (isset($response->transaction->errorCode)) {
229
+ $message = $helper->getMsgByCode($response->transaction->errorCode);
230
+
231
+ if ($message === null && !isset($response->transaction->errorCode)) {
232
+ Mage::log('Corrupt Response from Gateway (transaction):', null, 'demac_optimal.log');
233
+ Mage::log($response, null, 'demac_optimal.log');
234
+ throw new Demac_Optimal_Model_Hosted_Exception($defaultMessage);
235
+ }
236
+
237
+ if ($message === null) {
238
+ $message = $response->transaction->errorMessage;
239
+ }
240
+
241
+ if (empty($message)) {
242
+ $message = $defaultMessage;
243
+ }
244
 
 
245
  if (!$session->getCustomerId()) {
246
+ $session->addError($message);
247
  }
248
+
249
+ Mage::helper('optimal')->cleanMerchantCustomerId($session->getId());
250
 
251
  throw new Demac_Optimal_Model_Hosted_Exception($message);
 
252
  }
253
 
254
  return $response;
280
  */
281
  protected function _callApi($url,$mode,$data = array())
282
  {
 
283
  $data = json_encode($data);
284
 
285
  try {
327
  Mage::logException($e);
328
  return false;
329
  }
330
+ Mage::log('OPTIMAL RESPONSE (_callApi):', null, 'demac_optimal.log');
331
+ Mage::log($curl_response, null, 'demac_optimal.log');
332
  return $curl_response;
333
  }
334
 
356
  $this->_checkCurlVerifyPeer($curl);
357
 
358
  //set the url, number of POST vars, POST data
359
+ curl_setopt($curl, CURLOPT_URL, $url);
360
+ curl_setopt($curl, CURLOPT_POST, true);
361
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
362
+ curl_setopt($curl, CURLOPT_HEADER, true);
363
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
364
  $curl_response = curl_exec($curl);
365
 
366
+ $headers = substr($curl_response, 0, curl_getinfo($curl, CURLINFO_HEADER_SIZE));
367
+ $headers = explode("\n", $headers);
368
+
369
+ Mage::log('OPTIMAL RESPONSE (submitPayment):', null, 'demac_optimal.log');
370
+ Mage::log($curl_response, null, 'demac_optimal.log');
371
  curl_close($curl);
372
+
373
  return true;
374
 
375
  } catch (Exception $e) {
app/code/community/Demac/Optimal/Model/Method/Hosted.php CHANGED
@@ -145,6 +145,12 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
145
  */
146
  public function validate()
147
  {
 
 
 
 
 
 
148
  $info = $this->getInfoInstance();
149
  $errorMsg = false;
150
  $availableTypes = explode(',',$this->getConfigData('cctypes'));
@@ -231,8 +237,17 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
231
  $createProfile = $paymentData['optimal_create_profile'];
232
  }
233
 
234
- // Get customer information
235
- if ($customerSession->isLoggedIn()){
 
 
 
 
 
 
 
 
 
236
  $customerData = $customer->getData();
237
  $customerData['is_guest'] = false;
238
  $customerData['lastname'] = (string)$customer->getLastname();
@@ -273,6 +288,43 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
273
  Mage::throwException($this->__("There was a problem creating the order"));
274
  }
275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
 
277
  if(isset($postURL)) {
278
  $paymentData = $this->_preparePayment($payment->getData());
@@ -291,7 +343,7 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
291
 
292
  if (!isset($orderStatus->transaction))
293
  {
294
- Mage::log('Transaction Object not present in orderStatus ... ABORT');
295
  Mage::throwException('Something went wrong with your transaction. Please contact support.');
296
  }
297
 
@@ -300,69 +352,67 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
300
  // Now we need to check the payment status if the transaction is available
301
  if($transaction->status == 'declined' || $transaction->status == 'cancelled')
302
  {
303
- Mage::throwException($this->__("There was a processing your payment"));
304
- } else {
305
 
306
- // Check the order status for the profile information and try to save it
307
- if($createProfile){
308
- if(isset($orderStatus->profile)){
309
- $profile = Mage::getModel('optimal/creditcard');
310
- $merchantCustomerId = $orderStatus->profile->merchantCustomerId;
311
-
312
- if(!isset($merchantCustomerId))
313
- {
314
- $merchantCustomerId = Mage::helper('optimal')->getMerchantCustomerId($order->getCustomerId());
315
- $merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
316
- }
317
-
318
- // Set Profile Info
319
- $profile->setCustomerId($order->getCustomerId());
320
- $profile->setProfileId($orderStatus->profile->id);
321
- $profile->setMerchantCustomerId($merchantCustomerId);
322
- $profile->setPaymentToken($orderStatus->profile->paymentToken);
323
-
324
- // Set Nickname
325
- $cardName = $orderStatus->transaction->card->brand;
326
- $profile->setCardNickname(Mage::helper('optimal')->processCardNickname($cardName));
327
-
328
- // Set Nickname
329
- //$cardHolder = $payment->getCcOwner();
330
- $cardHolder = $customerData['firstname'] . ' ' . $customerData['lastname']; // $params['firstname'] . $params['lastname'];
331
- $profile->setCardHolder($cardHolder);
332
-
333
- // Set Card Info
334
- $lastfour = $payment->getCcLast4();
335
- $profile->setLastFourDigits($lastfour);
336
-
337
- // Format card expiration date [todo]: Make a helper function
338
- $expirationDate = sprintf("%02s", $paymentData['cardExpiryMonth']) . "/" . substr($paymentData['cardExpiryYear'], -2);
339
-
340
- $profile->setCardExpiration($expirationDate);
341
-
342
- $profile->save();
343
- }else {
344
- Mage::throwException($this->__("There was a problem saving your payment information."));
345
  }
346
- }
347
 
 
 
 
 
 
348
 
 
 
 
349
 
350
- $order->addStatusHistoryComment(
351
- 'Netbanks Order Id: ' . $orderStatus->id .'<br/>' .
352
- 'Reference: # ' . $orderStatus->merchantRefNum .'<br/>' .
353
- 'Transaction Id: ' . $transaction->confirmationNumber .'<br/>' .
354
- 'Status: ' . $transaction->status .'<br/>'
355
- );
356
 
357
- $payment->setStatus('APPROVED');
358
- $payment->setAdditionalInformation('order', serialize(array('id' => $orderStatus->id, 'optimal_profile_id' => $savedCreditCardProfileId)));
359
- $payment->setAdditionalInformation('transaction', serialize($transaction));
360
- $payment->setTransactionId($orderStatus->id);
361
- // magento will automatically close the transaction on auth preventing the invoice from being captured online.
362
- $payment->setIsTransactionClosed(false);
363
- $payment->setAdditionalInformation('payment_type', $this->getInfoInstance()->getCcType());
 
364
 
 
 
 
 
365
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  }
367
 
368
  return $this;
@@ -393,25 +443,28 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
393
 
394
  return $fPaymentData;
395
  }
396
-
 
 
 
 
397
  protected function _getOptimalOrderStatus($client, $id, $counter = 0)
398
  {
399
- if($counter >= 3){
400
- Mage::throwException('There was a problem retrieving the order information. Please contact support.');
401
- }
402
-
403
- Mage::log('Get-Optimal-Order-Status Try #: ' . ($counter + 1));
404
-
405
- try{
406
- return $client->retrieveOrder($id);
407
- } catch (Demac_Optimal_Model_Hosted_Exception $e) { // in case when Error is generated from Optimal
408
  Mage::throwException($e->getMessage());
409
- return;
410
  } catch(Exception $e) {
411
- $counter++;
412
- $this->_getOptimalOrderStatus($client, $id, $counter);
413
- }
414
-
415
  }
416
 
417
 
@@ -622,4 +675,55 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
622
  return $this;
623
  }
624
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
  }
145
  */
146
  public function validate()
147
  {
148
+ $skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
149
+
150
+ if (!$skip3d) {
151
+ return $this;
152
+ }
153
+
154
  $info = $this->getInfoInstance();
155
  $errorMsg = false;
156
  $availableTypes = explode(',',$this->getConfigData('cctypes'));
237
  $createProfile = $paymentData['optimal_create_profile'];
238
  }
239
 
240
+ $checkoutMethod = Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod();
241
+
242
+ if ($checkoutMethod != 'guest') {
243
+ $quote = Mage::getSingleton('sales/quote')->load($order->getQuoteId());
244
+ $billing = $quote->getBillingAddress();
245
+ $customerData['is_guest'] = false;
246
+ $customerData['lastname'] = (string)$billing->getLastname();
247
+ $customerData['firstname'] = (string)$billing->getFirstname();
248
+ $customerData['email'] = (string)$billing->getEmail();
249
+
250
+ } elseif ($customerSession->isLoggedIn()){ // Get customer information
251
  $customerData = $customer->getData();
252
  $customerData['is_guest'] = false;
253
  $customerData['lastname'] = (string)$customer->getLastname();
288
  Mage::throwException($this->__("There was a problem creating the order"));
289
  }
290
 
291
+ $skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
292
+ // Redirect the Customer if 3D-Secure verification is turned on
293
+ if (isset($postURL) && !$skip3d) {
294
+
295
+ try {
296
+ $order->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT);
297
+ $order->setStatus('pending_payment');
298
+ $order->addStatusHistoryComment('Redirecting the Customer to Optimal Payments for Payment Authorisation', 'pending_payment');
299
+ $order->addStatusHistoryComment(
300
+ 'Netbanks Order Id: ' . $response->id .'<br/>' .
301
+ 'Reference: # ' . $response->merchantRefNum .'<br/>'
302
+ );
303
+ $order->setIsNotified(false);
304
+ $order->save();
305
+ $checkoutSess = Mage::getSingleton('checkout/session');
306
+ $checkoutSess->unsQuoteId();
307
+ $checkoutSess->unsRedirectUrl();
308
+
309
+ $payment->setStatus('PENDING');
310
+ $payment->setAdditionalInformation('order', serialize(array('id' => $response->id)));
311
+ $payment->setTransactionId($response->id);
312
+ // magento will automatically close the transaction on auth preventing the invoice from being captured online.
313
+ $payment->setIsTransactionClosed(false);
314
+ $payment->save();
315
+
316
+ $this->orderRedirectUrl($postURL);
317
+
318
+ } catch (Exception $e) {
319
+ Mage::log($e->getMessage(), null, 'demac_optimal.log');
320
+ Mage::logException($e);
321
+ $checkoutSess->addError($this->__('An error was encountered while redirecting to the payment gateway, please try again later.'));
322
+ $this->_handlePaymentFailure();
323
+ $this->orderRedirectUrl(Mage::getBaseUrl() . 'checkout/cart');
324
+ }
325
+
326
+ return $this;
327
+ }
328
 
329
  if(isset($postURL)) {
330
  $paymentData = $this->_preparePayment($payment->getData());
343
 
344
  if (!isset($orderStatus->transaction))
345
  {
346
+ Mage::log('Aborting ... Transaction Object not present in orderStatus', null, 'demac_optimal.log');
347
  Mage::throwException('Something went wrong with your transaction. Please contact support.');
348
  }
349
 
352
  // Now we need to check the payment status if the transaction is available
353
  if($transaction->status == 'declined' || $transaction->status == 'cancelled')
354
  {
355
+ Mage::throwException($this->__("There was an error processing your payment"));
356
+ }
357
 
358
+ // Check the order status for the profile information and try to save it
359
+ if($createProfile){
360
+ if(isset($orderStatus->profile)){
361
+ $profile = Mage::getModel('optimal/creditcard');
362
+ $merchantCustomerId = $orderStatus->profile->merchantCustomerId;
363
+
364
+ if(!isset($merchantCustomerId))
365
+ {
366
+ $merchantCustomerId = Mage::helper('optimal')->getMerchantCustomerId($order->getCustomerId());
367
+ $merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  }
 
369
 
370
+ // Set Profile Info
371
+ $profile->setCustomerId($order->getCustomerId());
372
+ $profile->setProfileId($orderStatus->profile->id);
373
+ $profile->setMerchantCustomerId($merchantCustomerId);
374
+ $profile->setPaymentToken($orderStatus->profile->paymentToken);
375
 
376
+ // Set Nickname
377
+ $cardName = $orderStatus->transaction->card->brand;
378
+ $profile->setCardNickname(Mage::helper('optimal')->processCardNickname($cardName));
379
 
380
+ // Set Nickname
381
+ //$cardHolder = $payment->getCcOwner();
382
+ $cardHolder = $customerData['firstname'] . ' ' . $customerData['lastname']; // $params['firstname'] . $params['lastname'];
383
+ $profile->setCardHolder($cardHolder);
 
 
384
 
385
+ // Set Card Info
386
+ $lastfour = $payment->getCcLast4();
387
+ $profile->setLastFourDigits($lastfour);
388
+
389
+ // Format card expiration date [todo]: Make a helper function
390
+ $expirationDate = sprintf("%02s", $paymentData['cardExpiryMonth']) . "/" . substr($paymentData['cardExpiryYear'], -2);
391
+
392
+ $profile->setCardExpiration($expirationDate);
393
 
394
+ $profile->save();
395
+ }else {
396
+ Mage::throwException($this->__("There was a problem saving your payment information."));
397
+ }
398
  }
399
+
400
+
401
+
402
+ $order->addStatusHistoryComment(
403
+ 'Netbanks Order Id: ' . $orderStatus->id .'<br/>' .
404
+ 'Reference: # ' . $orderStatus->merchantRefNum .'<br/>' .
405
+ 'Transaction Id: ' . $transaction->confirmationNumber .'<br/>' .
406
+ 'Status: ' . $transaction->status .'<br/>'
407
+ );
408
+
409
+ $payment->setStatus('APPROVED');
410
+ $payment->setAdditionalInformation('order', serialize(array('id' => $orderStatus->id, 'optimal_profile_id' => $savedCreditCardProfileId)));
411
+ $payment->setAdditionalInformation('transaction', serialize($transaction));
412
+ $payment->setTransactionId($orderStatus->id);
413
+ // magento will automatically close the transaction on auth preventing the invoice from being captured online.
414
+ $payment->setIsTransactionClosed(false);
415
+ $payment->setAdditionalInformation('payment_type', $this->getInfoInstance()->getCcType());
416
  }
417
 
418
  return $this;
443
 
444
  return $fPaymentData;
445
  }
446
+
447
+ public function getOptimalOrderStatus($client, $id, $count = 0) {
448
+ return $this->_getOptimalOrderStatus($client, $id, $count);
449
+ }
450
+
451
  protected function _getOptimalOrderStatus($client, $id, $counter = 0)
452
  {
453
+ if($counter >= 3){
454
+ Mage::throwException('There was a problem retrieving the order information. Please contact support.');
455
+ }
456
+
457
+ Mage::log('Get-Optimal-Order-Status Try #: ' . ($counter + 1), null, 'demac_optimal.log');
458
+
459
+ try{
460
+ return $client->retrieveOrder($id);
461
+ } catch (Demac_Optimal_Model_Hosted_Exception $e) { // in case when Error is generated from Optimal
462
  Mage::throwException($e->getMessage());
 
463
  } catch(Exception $e) {
464
+ $counter++;
465
+ $this->_getOptimalOrderStatus($client, $id, $counter);
466
+ }
467
+
468
  }
469
 
470
 
675
  return $this;
676
  }
677
 
678
+ public function orderRedirectUrl($url = null)
679
+ {
680
+ static $gatewayUrl;
681
+
682
+ if (!$url) {
683
+ return $gatewayUrl;
684
+ }
685
+
686
+ $gatewayUrl = $url;
687
+
688
+ return $gatewayUrl;
689
+ }
690
+
691
+ public function getOrderPlaceRedirectUrl()
692
+ {
693
+ return $this->orderRedirectUrl();
694
+ }
695
+
696
+ /**
697
+ * Handle Payment Failure
698
+ * - Cancel the order
699
+ * - Restore the quote
700
+ *
701
+ * Cancel Order and attempt to restore cart.
702
+ *
703
+ */
704
+ protected function _handlePaymentFailure()
705
+ {
706
+ $session = Mage::getSingleton('checkout/session');
707
+
708
+ if ($session->getLastRealOrderId()) {
709
+ try {
710
+ $order = Mage::getModel('sales/order')->loadByIncrementId($session->getLastRealOrderId());
711
+ if ($order->getId()) {
712
+ $order->cancel()->save();
713
+ $quote = Mage::getModel('sales/quote')->load($order->getQuoteId());
714
+ if ($quote->getId()) {
715
+ $quote->setIsActive(1)
716
+ ->setReservedOrderId(null)
717
+ ->save();
718
+
719
+ $session->replaceQuote($quote)
720
+ ->unsLastRealOrderId();
721
+ }
722
+ }
723
+ } catch (Exception $e) {
724
+ Mage::logException($e);
725
+ }
726
+ }
727
+ }
728
+
729
  }
app/code/community/Demac/Optimal/Model/Observer.php CHANGED
@@ -24,6 +24,7 @@ class Demac_Optimal_Model_Observer
24
 
25
  if ($payment->getMethod() == 'optimal_hosted') {
26
  $orderAdditionalInformation = $payment->getAdditionalInformation();
 
27
  $transaction = unserialize($orderAdditionalInformation['transaction']);
28
 
29
  if(!empty($transaction->riskReasonCode))
24
 
25
  if ($payment->getMethod() == 'optimal_hosted') {
26
  $orderAdditionalInformation = $payment->getAdditionalInformation();
27
+
28
  $transaction = unserialize($orderAdditionalInformation['transaction']);
29
 
30
  if(!empty($transaction->riskReasonCode))
app/code/community/Demac/Optimal/Test/Model/Hosted/Client.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Demac_Optimal_Test_Model_Hosted_Client extends EcomDev_PHPUnit_Test_Case
4
+ {
5
+
6
+
7
+ /**
8
+ * Test that the payment method can authorize
9
+ *
10
+ * @test
11
+ */
12
+ public function canAuthorize()
13
+ {
14
+ $this->assertEquals(true, false);
15
+ }
16
+ }
app/code/community/Demac/Optimal/Test/Model/Method/Hosted.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Demac_Optimal_Test_Model_Method_Hosted extends EcomDev_PHPUnit_Test_Case
4
+ {
5
+
6
+ /**
7
+ * Test that the payment method can authorize
8
+ *
9
+ * @test
10
+ */
11
+ public function canAuthorize()
12
+ {
13
+ $method = Mage::getModel('optimal/method_hosted');
14
+
15
+ $this->assertEquals(true, $method->canAuthorize());
16
+ }
17
+ }
app/code/community/Demac/Optimal/Test/Model/Observer.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Demac_Optimal_Test_Model_Observer extends EcomDev_PHPUnit_Test_Case
4
+ {
5
+ public function prepareOrderData()
6
+ {
7
+
8
+ }
9
+ }
app/code/community/Demac/Optimal/controllers/Frontend/OptimalController.php CHANGED
@@ -190,6 +190,19 @@ class Demac_Optimal_Frontend_OptimalController extends Mage_Core_Controller_Fron
190
  // Call the helper and get the data for netbanks
191
  $data = $helper->prepareNetbanksOrderData($orderData ,$customerData, $createProfile, 'authorize');
192
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  // Call Netbanks API and create the order
194
  $response = $client->createOrder($data);
195
  if (isset($response->link)) {
@@ -213,6 +226,7 @@ class Demac_Optimal_Frontend_OptimalController extends Mage_Core_Controller_Fron
213
  );
214
 
215
  $paymentResponse = $client->submitPayment($postURL,$paymentData);
 
216
  $orderStatus = $client->retrieveOrder($response->id);
217
  $transaction = $orderStatus->transaction;
218
 
190
  // Call the helper and get the data for netbanks
191
  $data = $helper->prepareNetbanksOrderData($orderData ,$customerData, $createProfile, 'authorize');
192
 
193
+ foreach ($data['extendedOptions'] as $index => $xOp) {
194
+ if ($xOp['key'] == 'skip3D') {
195
+ $data['extendedOptions'][$index]['value'] = true;
196
+ }
197
+ }
198
+
199
+ // $data['extendedOptions'][] = array(
200
+ // 'key' => 'storeCardIndicator',
201
+ // 'value' => true
202
+ // );
203
+
204
+ Mage::log($data, null, 'optimal-addcc.log');
205
+
206
  // Call Netbanks API and create the order
207
  $response = $client->createOrder($data);
208
  if (isset($response->link)) {
226
  );
227
 
228
  $paymentResponse = $client->submitPayment($postURL,$paymentData);
229
+ Mage::log($paymentResponse, null, 'optimnal-paymentrsp.log');
230
  $orderStatus = $client->retrieveOrder($response->id);
231
  $transaction = $orderStatus->transaction;
232
 
app/code/community/Demac/Optimal/controllers/HandlerController.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Demac_Optimal_HandlerController extends Mage_Core_Controller_Front_Action
4
+ {
5
+ /**
6
+ * Callback Action
7
+ *
8
+ * Handle Success/Failure response from Payment Gateway
9
+ */
10
+ public function callbackAction()
11
+ {
12
+ $params = $this->getRequest()->getParams();
13
+ $session = Mage::getSingleton('checkout/session');
14
+
15
+ $status = $params['transaction_status'];
16
+ $confirmation = $params['transaction_confirmationNumber'];
17
+ $optimalOrderId = $params['id'];
18
+
19
+ if ($status != 'success') {
20
+ $session->addError($this->__('Payment failed, please review your payment information and try again.'));
21
+ $this->_handlePaymentFailure();
22
+ $this->_redirect('checkout/cart');
23
+ return;
24
+ }
25
+
26
+ try {
27
+ $this->_handlePaymentSuccess($session, $params);
28
+ } catch (Mage_Core_Exception $e) {
29
+ Mage::logException($e);
30
+ $this->_handlePaymentFailure();
31
+ $this->_redirect('checkout/onepage/failure');
32
+ }
33
+
34
+ }
35
+
36
+ /**
37
+ * Handle Payment Failure
38
+ *
39
+ * Cancel Order and attempt to restore cart.
40
+ *
41
+ */
42
+ protected function _handlePaymentFailure()
43
+ {
44
+ $session = Mage::getSingleton('checkout/session');
45
+
46
+ if ($session->getLastRealOrderId()) {
47
+ try {
48
+ $order = Mage::getModel('sales/order')->loadByIncrementId($session->getLastRealOrderId());
49
+ if ($order->getId()) {
50
+ $order->cancel()->save();
51
+ }
52
+ Mage::helper('optimal')->restoreQuote();
53
+ } catch (Exception $e) {
54
+ Mage::logException($e);
55
+ }
56
+ }
57
+
58
+ }
59
+
60
+ /**
61
+ * Handle Payment Success
62
+ *
63
+ * Update Order status and create invoice
64
+ *
65
+ * @param $session
66
+ * @param $params
67
+ */
68
+ protected function _handlePaymentSuccess($session, $params)
69
+ {
70
+ $status = $params['transaction_status'];
71
+ $confirmation = $params['transaction_confirmationNumber'];
72
+ $optimalOrderId = $params['id'];
73
+
74
+ $order = Mage::getModel('sales/order')->loadByIncrementId($session->getLastRealOrderId());
75
+ $payment = $order->getPayment();
76
+
77
+ // Now let's get the Order's status from Optimal
78
+ $client = Mage::getModel('optimal/hosted_client');
79
+ $orderStatus = Mage::getModel('optimal/method_hosted')->getOptimalOrderStatus($client, $optimalOrderId);
80
+ $transaction = $orderStatus->transaction;
81
+
82
+ $customerSession = Mage::getSingleton('customer/session');
83
+ list($month, $year) = explode('/', $transaction->card->expiry);
84
+
85
+ if ($customerSession->isLoggedIn()) {
86
+ $customerId = $customerSession->getId();
87
+ $customerData = Mage::getModel('customer/customer')->load($customerId)->getData();
88
+ $Card = Mage::getModel('optimal/creditcard');
89
+ $digits = $transaction->card->lastDigits;
90
+
91
+ $expiration = $month . '/' . substr($year, -2);
92
+ $profile = $Card->getCollection()
93
+ ->addFieldToFilter('customer_id', $customerId)
94
+ ->addFieldToFilter('last_four_digits', $digits)
95
+ ->addFieldToFilter('card_expiration', $expiration)
96
+ ->getFirstItem();
97
+
98
+ $merchantCustomerId = Mage::helper('optimal')->getMerchantCustomerId($customerId);
99
+ $merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
100
+
101
+ // this means the CC is not saved
102
+ if (empty($profile)) {
103
+ $profile = Mage::getModel('optimal/creditcard');
104
+ }
105
+
106
+ // Set Profile Info
107
+ $profile->setCustomerId($customerId);
108
+ $profile->setProfileId($orderStatus->profile->id);
109
+ $profile->setMerchantCustomerId($merchantCustomerId);
110
+ $profile->setPaymentToken($orderStatus->profile->paymentToken);
111
+
112
+ // Set Nickname
113
+ $cardName = $orderStatus->transaction->card->brand;
114
+ $profile->setCardNickname(Mage::helper('optimal')->processCardNickname($cardName));
115
+
116
+ // Set Nickname
117
+ $cardHolder = $customerData['firstname'] . ' ' . $customerData['lastname']; // $params['firstname'] . $params['lastname'];
118
+ $profile->setCardHolder($cardHolder);
119
+
120
+ // Set Card Info
121
+ $profile->setLastFourDigits($transaction->card->lastDigits);
122
+
123
+ $profile->setCardExpiration($expiration);
124
+
125
+ $profile->save();
126
+ }
127
+
128
+ if (!isset($cardHolder)) {
129
+ $cardHolder = $orderStatus->profile->firstName . ' ' . $orderStatus->profile->lastName;
130
+ }
131
+
132
+ $order->addStatusHistoryComment(
133
+ 'Netbanks Order Id: ' . $orderStatus->id .'<br/>' .
134
+ 'Reference: # ' . $orderStatus->merchantRefNum .'<br/>' .
135
+ 'Transaction Id: ' . $transaction->confirmationNumber .'<br/>' .
136
+ 'Status: ' . $transaction->status .'<br/>'
137
+ );
138
+
139
+ $payment->setStatus('APPROVED');
140
+ $payment->setAdditionalInformation('order', serialize(array('id' => $optimalOrderId)));
141
+ $payment->setAdditionalInformation('transaction', serialize($transaction));
142
+ $payment->setTransactionId($optimalOrderId);
143
+ // magento will automatically close the transaction on auth preventing the invoice from being captured online.
144
+ $payment->setIsTransactionClosed(false);
145
+ $payment->setCcOwner($cardHolder)
146
+ ->setCcType(Mage::helper('optimal')->processCardNickname($transaction->card->brand))
147
+ ->setCcExpMonth($month)
148
+ ->setCcExpYear($year)
149
+ ->setCcLast4($transaction->card->lastDigits);
150
+ $payment->save();
151
+
152
+ $this->_redirect('checkout/onepage/success');
153
+ }
154
+ }
app/code/community/Demac/Optimal/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <Demac_Optimal>
5
- <version>0.3.8</version>
6
  </Demac_Optimal>
7
  </modules>
8
 
@@ -111,6 +111,11 @@
111
  <optimal>
112
  <class>Demac_Optimal_Block</class>
113
  </optimal>
 
 
 
 
 
114
  </blocks>
115
  <helpers>
116
  <optimal>
2
  <config>
3
  <modules>
4
  <Demac_Optimal>
5
+ <version>0.3.9</version>
6
  </Demac_Optimal>
7
  </modules>
8
 
111
  <optimal>
112
  <class>Demac_Optimal_Block</class>
113
  </optimal>
114
+ <customer>
115
+ <rewrite>
116
+ <account_navigation>Demac_Optimal_Block_Navigation</account_navigation>
117
+ </rewrite>
118
+ </customer>
119
  </blocks>
120
  <helpers>
121
  <optimal>
app/code/community/Demac/Optimal/sql/optimal_setup/install-0.3.5.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+
4
+ $installer->startSetup();
5
+
6
+ $installer->run("
7
+
8
+ DROP TABLE IF EXISTS `{$this->getTable('optimal/errorcode')}`;
9
+ CREATE TABLE IF NOT EXISTS `{$this->getTable('optimal/errorcode')}` (
10
+ `code` varchar(5) NOT NULL,
11
+ `created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
12
+ `updated_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
13
+ PRIMARY KEY (`code`)
14
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15
+
16
+ ");
17
+
18
+ $installer->endSetup();
app/code/community/Demac/Optimal/sql/optimal_setup/mysql4-install-0.3.5.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+
4
+ $installer->startSetup();
5
+
6
+ $installer->run("
7
+
8
+ DROP TABLE IF EXISTS `{$this->getTable('optimal/errorcode')}`;
9
+ CREATE TABLE IF NOT EXISTS `{$this->getTable('optimal/errorcode')}` (
10
+ `code` varchar(5) NOT NULL,
11
+ `created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
12
+ `updated_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
13
+ PRIMARY KEY (`code`)
14
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15
+
16
+ ");
17
+
18
+ $installer->endSetup();
app/code/community/Demac/Optimal/sql/optimal_setup/upgrade-0.3.4-0.3.5.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+
4
+ $installer->startSetup();
5
+
6
+ $installer->run("
7
+
8
+ DROP TABLE IF EXISTS `{$this->getTable('optimal/errorcode')}`;
9
+ CREATE TABLE IF NOT EXISTS `{$this->getTable('optimal/errorcode')}` (
10
+ `code` varchar(50) NOT NULL,
11
+ `message` varchar(555) NOT NULL,
12
+ `custom_message` varchar(555) NULL,
13
+ `active` tinyint(1) NOT NULL DEFAULT '0',
14
+ `created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
15
+ `updated_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
16
+ PRIMARY KEY (`code`)
17
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
18
+
19
+ ");
20
+
21
+ $installer->endSetup();
app/design/adminhtml/default/default/template/optimal/info/creditcard.phtml CHANGED
@@ -1,5 +1,8 @@
1
  <?php
2
  $info = $this->getCardInfo();
 
 
 
3
  ?>
4
 
5
  <?php if(isset($info)): ?>
1
  <?php
2
  $info = $this->getCardInfo();
3
+ if (!isset($info['name'])) {
4
+ $info['name'] = '';
5
+ }
6
  ?>
7
 
8
  <?php if(isset($info)): ?>
app/design/frontend/base/default/layout/optimal.xml CHANGED
@@ -1,5 +1,5 @@
1
  <?xml version="1.0"?>
2
- <layout version="0.1.0"> i
3
  <checkout_onepage_index translate="label" module="page">
4
  <reference name="before_body_end">
5
  <block type="optimal/threat" template="optimal/threatmeter.phtml" name="optimal_threat" as="optimal_threat"/>
1
  <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
  <checkout_onepage_index translate="label" module="page">
4
  <reference name="before_body_end">
5
  <block type="optimal/threat" template="optimal/threatmeter.phtml" name="optimal_threat" as="optimal_threat"/>
app/design/frontend/base/default/template/optimal/form/creditcard.phtml CHANGED
@@ -24,8 +24,16 @@
24
  * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
25
  */
26
  ?>
27
- <?php $_code=$this->getMethodCode() ?>
28
- <?php if($this->hasOptimalProfiles() === true): ?>
 
 
 
 
 
 
 
 
29
  <div id="select_card_form" >
30
  <ul class="profile_list form-list" id="payment_form_<?php echo $_code ?>" >
31
  <li class="wide">
@@ -178,7 +186,13 @@
178
 
179
 
180
  </script>
 
 
 
 
 
181
  <?php else: ?>
 
182
  <ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
183
  <li>
184
  <label for="<?php echo $_code ?>_cc_owner" class="required"><em>*</em><?php echo $this->__('Name on Card') ?></label>
24
  * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
25
  */
26
  ?>
27
+ <?php
28
+ $_code = $this->getMethodCode();
29
+
30
+ $skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D');
31
+ $profilesEnabled = ($this->hasOptimalProfiles() === true);
32
+
33
+ ?>
34
+
35
+
36
+ <?php if($profilesEnabled && $skip3d): ?>
37
  <div id="select_card_form" >
38
  <ul class="profile_list form-list" id="payment_form_<?php echo $_code ?>" >
39
  <li class="wide">
186
 
187
 
188
  </script>
189
+
190
+ <?php elseif (!$skip3d): ?>
191
+ <ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
192
+ <li>You will be redirected to Optimal Payments for payment authorisation.</li>
193
+ </ul>
194
  <?php else: ?>
195
+
196
  <ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
197
  <li>
198
  <label for="<?php echo $_code ?>_cc_owner" class="required"><em>*</em><?php echo $this->__('Name on Card') ?></label>
app/design/frontend/base/default/template/optimal/info/creditcard.phtml CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  $info = $this->getCardInfo();
3
  ?>
4
  <?php echo $this->__('Credit Card Type: %s', $this->htmlEscape(ucwords($info['card_type']))) ?><br />
1
  <?php
2
+ $skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D');
3
+ // if 3D-Secure check is enabled, only show the Payment Method Title
4
+ if (!$skip3d) {
5
+ echo Mage::getStoreConfig('payment/optimal_hosted/title');
6
+ return;
7
+ }
8
+
9
  $info = $this->getCardInfo();
10
  ?>
11
  <?php echo $this->__('Credit Card Type: %s', $this->htmlEscape(ucwords($info['card_type']))) ?><br />
package.xml CHANGED
@@ -1,24 +1,24 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>666999</name>
4
- <version>0.3.8</version>
5
- <stability>beta</stability>
6
- <license uri="http://opensource.org/licenses/gpl-license.php">GPL</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Securely access and process online payments with the NETBANX payment gateway.</summary>
10
- <description>The Optimal Payments NETBANX Hosted Payment Extension allows ecommerce businesses to securely accept and process online payments using Optimal&amp;#x2019;s NETBANX payment gateway and services. The integration is easy to implement and provides the ultimate in payment processing capabilities, fraud management, and reporting.&amp;#xD;&#xD;
11
- &amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;#xD;&#xD;
12
- The Optimal Payments extension uses a Silent Post integration to the merchant&amp;#x2019;s website. During checkout, payment information is entered on the merchant website and then transmitted securely via Silent Post for processing to the NETBANX payment gateway. The customer remains on the merchant&amp;#x2019;s website at all times allowing the merchant to manage the customer experience. When the customer clicks on the Pay button, payment data is transmitted directly to NETBANX using a PCI-compliant process without accessing any merchant servers.&amp;#xD;&#xD;
13
- &amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;#xD;&#xD;
14
- This integration significantly reduces PCI compliance requirements and liability as all of the credit card information is processed in Optimal Payments Level 1 PCI compliant environment and servers leaving no sensitive customer payment information stored locally on merchant servers.&amp;#xD;&#xD;
15
- &amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;#xD;&#xD;
16
  Through the Optimal integration merchants also have the option to enable Threatmetrix fraud detection and management services. ThreatMetrix works by collecting relevant data about the customer and the order, and validating this information during the checkout. Fully integrated into the NETBANX payment gateway, enabling the ThreatMetrix option will allow merchants to automatically hold and flag suspicious orders, drastically reducing any fraud occurrences. Depending on the Score returned by ThreatMetrix an order can be held and flagged or altogether denied during the checkout.</description>
17
- <notes>Introducing Custom Error Code management.</notes>
18
  <authors><author><name>Demac Media</name><user>demacmedia</user><email>support@demacmedia.com</email></author></authors>
19
- <date>2014-11-27</date>
20
- <time>22:51:30</time>
21
- <contents><target name="magecommunity"><dir name="Demac"><dir name="Optimal"><dir name="Block"><dir name="Adminhtml"><dir name="Errorcode"><dir name="Edit"><file name="Form.php" hash="56618ff0cc5f4c674f750412d0606aab"/></dir><file name="Edit.php" hash="8980988ca1324fac229b40f471d745c8"/><file name="Grid.php" hash="2d8ea2f836d380167e9b25a67acefd70"/></dir><file name="Errorcode.php" hash="9f0d3c6b0b51e3bedd239d3b727eff75"/><dir name="Risk"><dir name="Edit"><file name="Form.php" hash="25d4bcb59e33a94799bc9f6cb0509cc3"/><dir name="Tab"><file name="Form.php" hash="3731d284c28ed279eb5e00b41f494810"/></dir><file name="Tabs.php" hash="61a8d2ac9942356db313b423fc3c47c2"/></dir><file name="Edit.php" hash="959e8af1e6aae6d02560c98bcabea5ab"/><file name="Grid.php" hash="e999f01578aac6084520029f86852c09"/></dir><file name="Risk.php" hash="6bf5127ba14f9dd38519c6b62203f1f8"/></dir><dir name="Customer"><dir name="Cards"><file name="Form.php" hash="ce79e221d5caf995a10e47cbb4e51f8b"/><file name="Grid.php" hash="d14eb692082fe1299977e7b3ee75dcf3"/></dir><file name="Cards.php" hash="f99686c2296a850312713f6aadc4d04a"/></dir><dir name="Form"><file name="Creditcard.php" hash="d3642d432409cf55069253680bf9ee34"/></dir><dir name="Info"><file name="Creditcard.php" hash="7ba1df22bade177f4956ce9084fa98c6"/></dir><file name="Threat.php" hash="69605e0b8aacc80f47b5ed91e8631248"/></dir><dir name="Helper"><file name="Data.php" hash="4568216dd1e1e1a987df04e1bbf34d19"/></dir><dir name="Model"><dir name="Client"><file name="Abstract.php" hash="f83275be8d3b248eb145d45c2a926d84"/></dir><dir name="Config"><file name="Mode.php" hash="798d2a9bab2c0fc2749116ac1a3fc926"/><file name="Status.php" hash="767ba25406456aae4a0bd86b11023b45"/><file name="Transaction.php" hash="e83e8427e4b14c4d3cd83058c68f8965"/></dir><dir name="Creditcard"><file name="Client.php" hash="f1014811d23c1cf5efbccf61c3c6c80c"/></dir><file name="Creditcard.php" hash="26e89a35558c0692d5f90afdcad25c12"/><file name="Errorcode.php" hash="dae5fa1abb705961bd9f15abf3d65ec0"/><dir name="Hosted"><file name="Client.php" hash="902a0b5bd7333bb1a75dc7c7a076695c"/><file name="Exception.php" hash="dfca385bc45b1c055bbf2e8e7031230b"/></dir><dir name="Merchant"><file name="Customer.php" hash="be743a5c7aababb9752bf961570b0c27"/></dir><dir name="Method"><file name="Hosted.php" hash="c37cc40403506d4d6f519f4f7dba9787"/></dir><dir name="Mysql4"><dir name="Creditcard"><file name="Collection.php" hash="700985c287355082a3966d4b3f74838f"/></dir><file name="Creditcard.php" hash="a4e5ea4090d2f127edd19de9d2feb343"/><dir name="Errorcode"><file name="Collection.php" hash="075c7c98b606573f02aad1b096f13899"/></dir><file name="Errorcode.php" hash="0d19835b405402a5a5a7ae7c24a42c97"/><dir name="Merchant"><dir name="Customer"><file name="Collection.php" hash="aa0fbf9c0cc0a3207565443e35ae3779"/></dir><file name="Customer.php" hash="fe991d98537b7b3a07160d5b9b10802d"/></dir><dir name="Profile"><file name="Collection.php" hash="f5cd814fe62d2af8fbcc2214f94bfeb4"/></dir><file name="Profile.php" hash="6944c811248ef955a51357989ca11dd3"/><dir name="Risk"><file name="Collection.php" hash="558dc26690672dc09ae6fbfa8e780302"/></dir><file name="Risk.php" hash="5c77111382678451da4dde209a43b0fa"/></dir><file name="Observer.php" hash="32ded6b8987067943ac349b6bab4ccea"/><dir name="Profile"><file name="Client.php" hash="4358736ced5bdc7d2a7fbbf53e2ff07d"/></dir><file name="Profile.php" hash="798cef09bbc0556545edf1f00bae9bf0"/><dir name="Resource"><dir name="Mysql4"><file name="Setup.php" hash="e936830d9e4f74badc3b7663f60436dc"/></dir></dir><file name="Risk.php" hash="fab5519b0e257b8ef2f66f5f76d49f2b"/><dir name="Sales"><file name="Order.php" hash="32320888ae209b1ea3208da59312da5c"/></dir><dir name="Source"><file name="Cctype.php" hash="dd21379a29444a4c58e33e90ddeb300e"/></dir><dir name="Web"><file name="Client.php" hash="d565e254fc281e7c246cc9cfe8c2f39d"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="ErrorcodesController.php" hash="7149f83536e46413ddf5b159ae4ebf91"/><file name="ThreatController.php" hash="5db39713fbd0ae13e943a891940bb22c"/></dir><dir name="Frontend"><file name="OptimalController.php" hash="e38a9e3e12fb7a3fec988e0daba4489f"/></dir></dir><dir name="data"><dir name="optimal_setup"><dir name="csv"><file name="common-codes-0.3.3.csv" hash="e3c9195dbe01cfb5cf341378271b1240"/><file name="webservices-codes-0.3.3.csv" hash="8fc5562ff9bb3e5c3235fa6c7c21c0d5"/></dir><file name="data-upgrade-0.3.4-0.3.5.php" hash="4afe267d997446c46c0a1fcba771d1e1"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="30a4af4a510783219bbee940d185fb19"/><file name="config.xml" hash="3525775f0210314dda82a012803ed4c2"/><file name="system.xml" hash="4e28392139fad2a08d168d0b1381f081"/></dir><dir name="sql"><dir name="optimal_setup"><file name="install-0.1.1.php" hash="422b6afb2d2320f5d9c59cd5bff0dc3d"/><file name="install-0.2.0.php" hash="71dbb515c55c34f1910463d72f66f9d2"/><file name="install-0.2.1.php" hash="0bd65edba72966cffce19dd3c480863b"/><file name="install-0.2.2.php" hash="33bb51df7561eb747ee07d8e8aa43ce4"/><file name="install-0.2.3.php" hash="abafde589308828b601c306b45f1aa41"/><file name="install-0.2.4.php" hash="abafde589308828b601c306b45f1aa41"/><file name="install-0.2.5.php" hash="9a0bb5235e982cfc1794dd8d0172e26d"/><file name="install-0.2.6.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="install-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="install-0.2.9.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.1.1.php" hash="422b6afb2d2320f5d9c59cd5bff0dc3d"/><file name="mysql4-install-0.2.0.php" hash="71dbb515c55c34f1910463d72f66f9d2"/><file name="mysql4-install-0.2.1.php" hash="0bd65edba72966cffce19dd3c480863b"/><file name="mysql4-install-0.2.2.php" hash="33bb51df7561eb747ee07d8e8aa43ce4"/><file name="mysql4-install-0.2.3.php" hash="abafde589308828b601c306b45f1aa41"/><file name="mysql4-install-0.2.4.php" hash="abafde589308828b601c306b45f1aa41"/><file name="mysql4-install-0.2.5.php" hash="9a0bb5235e982cfc1794dd8d0172e26d"/><file name="mysql4-install-0.2.6.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.2.9.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-upgrade-0.1.1-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="upgrade-0.1.1-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="upgrade-0.2.9-0.3.0.php" hash="989e6c4043fccfa6cdcba0a09938dd07"/><file name="upgrade-0.3.1-0.3.2.php" hash="aea721b40772c92db786b96fbb9c8bda"/><file name="upgrade-0.3.7-0.3.8.php" hash="5283e3567c7d35e22b4c87bbc89a0eb3"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Demac_Optimal.xml" hash="2ebfc5a3a1c5688639c0cc5eb34fded0"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="optimal.xml" hash="d1154efa9a293770c76b98be4023ff08"/></dir><dir name="template"><dir name="optimal"><dir name="customer"><dir name="cards"><file name="form.phtml" hash="969544827b5e5765b6bb2bea2f62392a"/><file name="grid.phtml" hash="9a160522aa31ed44eb2f5751f40718c8"/></dir><file name="cards.phtml" hash="ed3f6e56b134674e7d8ddcb6a1deac59"/></dir><dir name="form"><file name="creditcard.phtml" hash="be04e0511fc1686ed7ea81c6e61e89ad"/></dir><dir name="info"><file name="creditcard.phtml" hash="d886bd24ae993548a3663b537e2456df"/></dir><file name="threatmeter.phtml" hash="3dd0ea7621038895aa1dd1e322ba7d99"/></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="optimal"><dir name="form"><file name="creditcard.phtml" hash="550c80a4e0dc4224946de029f4c3ecf6"/></dir><dir name="info"><file name="creditcard.phtml" hash="642dd94f8c1b1e43fe89226b3a0eb02a"/></dir></dir></dir></dir></dir></dir></target></contents>
22
  <compatible/>
23
- <dependencies><required><php><min>5.3.0</min><max>5.6.0</max></php></required></dependencies>
24
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>666999</name>
4
+ <version>0.3.9</version>
5
+ <stability>stable</stability>
6
+ <license>GPL</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Securely access and process online payments with the NETBANX payment gateway.</summary>
10
+ <description>The Optimal Payments NETBANX Hosted Payment Extension allows ecommerce businesses to securely accept and process online payments using Optimal&#x2019;s NETBANX payment gateway and services. The integration is easy to implement and provides the ultimate in payment processing capabilities, fraud management, and reporting.&#xD;
11
+ &lt;br /&gt; &lt;br /&gt;&#xD;
12
+ The Optimal Payments extension uses a Silent Post integration to the merchant&#x2019;s website. During checkout, payment information is entered on the merchant website and then transmitted securely via Silent Post for processing to the NETBANX payment gateway. The customer remains on the merchant&#x2019;s website at all times allowing the merchant to manage the customer experience. When the customer clicks on the Pay button, payment data is transmitted directly to NETBANX using a PCI-compliant process without accessing any merchant servers.&#xD;
13
+ &lt;br /&gt; &lt;br /&gt;&#xD;
14
+ This integration significantly reduces PCI compliance requirements and liability as all of the credit card information is processed in Optimal Payments Level 1 PCI compliant environment and servers leaving no sensitive customer payment information stored locally on merchant servers.&#xD;
15
+ &lt;br /&gt; &lt;br /&gt;&#xD;
16
  Through the Optimal integration merchants also have the option to enable Threatmetrix fraud detection and management services. ThreatMetrix works by collecting relevant data about the customer and the order, and validating this information during the checkout. Fully integrated into the NETBANX payment gateway, enabling the ThreatMetrix option will allow merchants to automatically hold and flag suspicious orders, drastically reducing any fraud occurrences. Depending on the Score returned by ThreatMetrix an order can be held and flagged or altogether denied during the checkout.</description>
17
+ <notes>Implements 3D Secure payment feature.</notes>
18
  <authors><author><name>Demac Media</name><user>demacmedia</user><email>support@demacmedia.com</email></author></authors>
19
+ <date>2015-02-25</date>
20
+ <time>22:57:49</time>
21
+ <contents><target name="magecommunity"><dir name="Demac"><dir name="Optimal"><dir name="Block"><dir name="Adminhtml"><dir name="Errorcode"><dir name="Edit"><file name="Form.php" hash="56618ff0cc5f4c674f750412d0606aab"/></dir><file name="Edit.php" hash="8980988ca1324fac229b40f471d745c8"/><file name="Grid.php" hash="2d8ea2f836d380167e9b25a67acefd70"/></dir><file name="Errorcode.php" hash="9f0d3c6b0b51e3bedd239d3b727eff75"/><dir name="Risk"><dir name="Edit"><file name="Form.php" hash="25d4bcb59e33a94799bc9f6cb0509cc3"/><dir name="Tab"><file name="Form.php" hash="3731d284c28ed279eb5e00b41f494810"/></dir><file name="Tabs.php" hash="61a8d2ac9942356db313b423fc3c47c2"/></dir><file name="Edit.php" hash="959e8af1e6aae6d02560c98bcabea5ab"/><file name="Grid.php" hash="e999f01578aac6084520029f86852c09"/></dir><file name="Risk.php" hash="6bf5127ba14f9dd38519c6b62203f1f8"/></dir><dir name="Customer"><dir name="Cards"><file name="Form.php" hash="ce79e221d5caf995a10e47cbb4e51f8b"/><file name="Grid.php" hash="d14eb692082fe1299977e7b3ee75dcf3"/></dir><file name="Cards.php" hash="f99686c2296a850312713f6aadc4d04a"/></dir><dir name="Form"><file name="Creditcard.php" hash="d3642d432409cf55069253680bf9ee34"/></dir><dir name="Info"><file name="Creditcard.php" hash="7ba1df22bade177f4956ce9084fa98c6"/></dir><file name="Navigation.php" hash="d3b7d8765356b8da18d300cc9b1a447e"/><file name="Threat.php" hash="69605e0b8aacc80f47b5ed91e8631248"/></dir><dir name="Helper"><file name="Data.php" hash="69b5b351ee4685e4f51e0e3213ecb80e"/></dir><dir name="Model"><dir name="Client"><file name="Abstract.php" hash="f83275be8d3b248eb145d45c2a926d84"/></dir><dir name="Config"><file name="Mode.php" hash="798d2a9bab2c0fc2749116ac1a3fc926"/><file name="Status.php" hash="767ba25406456aae4a0bd86b11023b45"/><file name="Transaction.php" hash="e83e8427e4b14c4d3cd83058c68f8965"/></dir><dir name="Creditcard"><file name="Client.php" hash="f1014811d23c1cf5efbccf61c3c6c80c"/></dir><file name="Creditcard.php" hash="4754639f6fb3d4e1f1af0fd429e46092"/><file name="Errorcode.php" hash="dae5fa1abb705961bd9f15abf3d65ec0"/><dir name="Hosted"><file name="Client.php" hash="043fdac7d3c1c4af09424488d5d1cb7f"/><file name="Exception.php" hash="dfca385bc45b1c055bbf2e8e7031230b"/></dir><dir name="Merchant"><file name="Customer.php" hash="be743a5c7aababb9752bf961570b0c27"/></dir><dir name="Method"><file name="Hosted.php" hash="9f7da28c1cb5a0a508d33e91cebb81f7"/></dir><dir name="Mysql4"><dir name="Creditcard"><file name="Collection.php" hash="700985c287355082a3966d4b3f74838f"/></dir><file name="Creditcard.php" hash="a4e5ea4090d2f127edd19de9d2feb343"/><dir name="Errorcode"><file name="Collection.php" hash="075c7c98b606573f02aad1b096f13899"/></dir><file name="Errorcode.php" hash="0d19835b405402a5a5a7ae7c24a42c97"/><dir name="Merchant"><dir name="Customer"><file name="Collection.php" hash="aa0fbf9c0cc0a3207565443e35ae3779"/></dir><file name="Customer.php" hash="fe991d98537b7b3a07160d5b9b10802d"/></dir><dir name="Profile"><file name="Collection.php" hash="f5cd814fe62d2af8fbcc2214f94bfeb4"/></dir><file name="Profile.php" hash="6944c811248ef955a51357989ca11dd3"/><dir name="Risk"><file name="Collection.php" hash="558dc26690672dc09ae6fbfa8e780302"/></dir><file name="Risk.php" hash="5c77111382678451da4dde209a43b0fa"/></dir><file name="Observer.php" hash="cd89f8b6b1275718617c9841a5a1bbfa"/><dir name="Profile"><file name="Client.php" hash="4358736ced5bdc7d2a7fbbf53e2ff07d"/></dir><file name="Profile.php" hash="798cef09bbc0556545edf1f00bae9bf0"/><dir name="Resource"><dir name="Mysql4"><file name="Setup.php" hash="e936830d9e4f74badc3b7663f60436dc"/></dir></dir><file name="Risk.php" hash="fab5519b0e257b8ef2f66f5f76d49f2b"/><dir name="Sales"><file name="Order.php" hash="32320888ae209b1ea3208da59312da5c"/></dir><dir name="Source"><file name="Cctype.php" hash="dd21379a29444a4c58e33e90ddeb300e"/></dir><dir name="Web"><file name="Client.php" hash="d565e254fc281e7c246cc9cfe8c2f39d"/></dir></dir><dir name="Test"><dir name="Model"><dir name="Hosted"><file name="Client.php" hash="8aa8bb4bc740daa59be041827f7cf614"/></dir><dir name="Method"><file name="Hosted.php" hash="9d39c78d0617d136c66c4c52185706a7"/></dir><file name="Observer.php" hash="345883a098197f64e2063a97d17e6274"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="ErrorcodesController.php" hash="7149f83536e46413ddf5b159ae4ebf91"/><file name="ThreatController.php" hash="5db39713fbd0ae13e943a891940bb22c"/></dir><dir name="Frontend"><file name="OptimalController.php" hash="b67878eb0dd4310fbb6f84723cd6ce43"/></dir><file name="HandlerController.php" hash="b854169efa286fb13918bc2162ffc9e8"/></dir><dir name="data"><dir name="optimal_setup"><dir name="csv"><file name="common-codes-0.3.3.csv" hash="e3c9195dbe01cfb5cf341378271b1240"/><file name="webservices-codes-0.3.3.csv" hash="8fc5562ff9bb3e5c3235fa6c7c21c0d5"/></dir><file name="data-upgrade-0.3.4-0.3.5.php" hash="4afe267d997446c46c0a1fcba771d1e1"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="30a4af4a510783219bbee940d185fb19"/><file name="config.xml" hash="0b4d3d285ff172135da38f3c396d4d7f"/><file name="system.xml" hash="4e28392139fad2a08d168d0b1381f081"/></dir><dir name="sql"><dir name="optimal_setup"><file name="install-0.1.1.php" hash="422b6afb2d2320f5d9c59cd5bff0dc3d"/><file name="install-0.2.0.php" hash="71dbb515c55c34f1910463d72f66f9d2"/><file name="install-0.2.1.php" hash="0bd65edba72966cffce19dd3c480863b"/><file name="install-0.2.2.php" hash="33bb51df7561eb747ee07d8e8aa43ce4"/><file name="install-0.2.3.php" hash="abafde589308828b601c306b45f1aa41"/><file name="install-0.2.4.php" hash="abafde589308828b601c306b45f1aa41"/><file name="install-0.2.5.php" hash="9a0bb5235e982cfc1794dd8d0172e26d"/><file name="install-0.2.6.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="install-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="install-0.2.9.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="install-0.3.5.php" hash="1ed21269279cd8b0f6c20394a91c9d3b"/><file name="mysql4-install-0.1.1.php" hash="422b6afb2d2320f5d9c59cd5bff0dc3d"/><file name="mysql4-install-0.2.0.php" hash="71dbb515c55c34f1910463d72f66f9d2"/><file name="mysql4-install-0.2.1.php" hash="0bd65edba72966cffce19dd3c480863b"/><file name="mysql4-install-0.2.2.php" hash="33bb51df7561eb747ee07d8e8aa43ce4"/><file name="mysql4-install-0.2.3.php" hash="abafde589308828b601c306b45f1aa41"/><file name="mysql4-install-0.2.4.php" hash="abafde589308828b601c306b45f1aa41"/><file name="mysql4-install-0.2.5.php" hash="9a0bb5235e982cfc1794dd8d0172e26d"/><file name="mysql4-install-0.2.6.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.2.9.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.3.5.php" hash="1ed21269279cd8b0f6c20394a91c9d3b"/><file name="mysql4-upgrade-0.1.1-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="upgrade-0.1.1-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="upgrade-0.2.9-0.3.0.php" hash="989e6c4043fccfa6cdcba0a09938dd07"/><file name="upgrade-0.3.1-0.3.2.php" hash="aea721b40772c92db786b96fbb9c8bda"/><file name="upgrade-0.3.4-0.3.5.php" hash="5283e3567c7d35e22b4c87bbc89a0eb3"/><file name="upgrade-0.3.7-0.3.8.php" hash="5283e3567c7d35e22b4c87bbc89a0eb3"/></dir></dir></dir><file name=".DS_Store" hash="274a24b68e17a80774c8065fa0e5d839"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="optimal.xml" hash="03c64fd49785bfca34ee3249cc9bc97d"/></dir><dir name="template"><dir name="optimal"><dir name="customer"><dir name="cards"><file name="form.phtml" hash="969544827b5e5765b6bb2bea2f62392a"/><file name="grid.phtml" hash="9a160522aa31ed44eb2f5751f40718c8"/></dir><file name="cards.phtml" hash="ed3f6e56b134674e7d8ddcb6a1deac59"/></dir><dir name="form"><file name="creditcard.phtml" hash="38c3799facc887179afd3efbabf8ec93"/></dir><dir name="info"><file name="creditcard.phtml" hash="8ed46f25ea6bd04a67317743d8502e69"/></dir><file name="threatmeter.phtml" hash="3dd0ea7621038895aa1dd1e322ba7d99"/></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="optimal"><dir name="form"><file name="creditcard.phtml" hash="550c80a4e0dc4224946de029f4c3ecf6"/></dir><dir name="info"><file name="creditcard.phtml" hash="b40291e8e97dbcb6b7cf2f4b8ffb93f5"/></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Demac_Optimal.xml" hash="2ebfc5a3a1c5688639c0cc5eb34fded0"/></dir></target></contents>
22
  <compatible/>
23
+ <dependencies><required><php><min>5.3.0</min><max>5.5.19</max></php></required></dependencies>
24
  </package>