MercadoPagoTransparent - Version 2.6.3

Version Notes

Added Uruguay support
Added cron for order status updates
Added translations
Bug fixing

Download this release

Release Info

Developer MercadoPago
Extension MercadoPagoTransparent
Version 2.6.3
Comparing to
See all releases


Code changes from version 2.4.1 to 2.6.3

Files changed (45) hide show
  1. app/code/community/MercadoPago/Core/Block/Calculator/CalculatorForm.php +61 -0
  2. app/code/community/MercadoPago/Core/Block/Calculator/CalculatorLink.php +65 -0
  3. app/code/community/MercadoPago/Core/Block/Recurring/Form.php +12 -0
  4. app/code/community/MercadoPago/Core/Block/Recurring/Info.php +25 -0
  5. app/code/community/MercadoPago/Core/Block/Recurring/Pay.php +12 -0
  6. app/code/community/MercadoPago/Core/Block/Recurring/Success.php +12 -0
  7. app/code/community/MercadoPago/Core/Helper/Data.php +57 -9
  8. app/code/community/MercadoPago/Core/Helper/Response.php +4 -0
  9. app/code/community/MercadoPago/Core/Helper/StatusUpdate.php +149 -30
  10. app/code/community/MercadoPago/Core/Model/Core.php +40 -11
  11. app/code/community/MercadoPago/Core/Model/Cron/Order.php +97 -0
  12. app/code/community/MercadoPago/Core/Model/Custom/Payment.php +93 -19
  13. app/code/community/MercadoPago/Core/Model/CustomTicket/Payment.php +3 -1
  14. app/code/community/MercadoPago/Core/Model/Observer.php +104 -57
  15. app/code/community/MercadoPago/Core/Model/Recurring/Payment.php +303 -0
  16. app/code/community/MercadoPago/Core/Model/Source/Country.php +1 -0
  17. app/code/community/MercadoPago/Core/Model/Source/ListPages.php +28 -0
  18. app/code/community/MercadoPago/Core/Model/Source/Order/Status.php +2 -2
  19. app/code/community/MercadoPago/Core/controllers/CalculatorPaymentController.php +11 -0
  20. app/code/community/MercadoPago/Core/controllers/NotificationsController.php +126 -59
  21. app/code/community/MercadoPago/Core/controllers/RecurringPaymentController.php +27 -0
  22. app/code/community/MercadoPago/Core/etc/config.xml +40 -1
  23. app/code/community/MercadoPago/Core/etc/jstranslator.xml +17 -0
  24. app/code/community/MercadoPago/Core/etc/system.xml +272 -52
  25. app/code/community/MercadoPago/MercadoEnvios/etc/config.xml +1 -1
  26. app/code/community/MercadoPago/MercadoEnvios/etc/system.xml +1 -1
  27. app/code/community/MercadoPago/OneStepCheckout/etc/config.xml +1 -1
  28. app/code/community/MercadoPago/OneStepCheckout/etc/system.xml +1 -1
  29. app/design/frontend/base/default/layout/mercadopago.xml +39 -0
  30. app/design/frontend/base/default/template/mercadopago/calculator/calculatorForm.phtml +110 -0
  31. app/design/frontend/base/default/template/mercadopago/calculator/calculatorLink.phtml +12 -0
  32. app/design/frontend/base/default/template/mercadopago/custom/form.phtml +78 -79
  33. app/design/frontend/base/default/template/mercadopago/custom/secondCard.phtml +147 -0
  34. app/design/frontend/base/default/template/mercadopago/custom/success.phtml +11 -3
  35. app/design/frontend/base/default/template/mercadopago/custom_ticket/success.phtml +6 -0
  36. app/design/frontend/base/default/template/mercadopago/standard/success.phtml +7 -1
  37. app/locale/en_US/MercadoPago_Core.csv +7 -1
  38. app/locale/es_AR/MercadoPago_Core.csv +200 -22
  39. js/mercadopago/mercadopago.js +758 -25
  40. js/mercadopago/mercadopago_calculator.js +263 -0
  41. package.xml +8 -5
  42. skin/frontend/base/default/mercadopago/css/style-calculator.css +276 -0
  43. skin/frontend/base/default/mercadopago/css/style-success.css +27 -3
  44. skin/frontend/base/default/mercadopago/css/style.css +267 -36
  45. skin/frontend/base/default/mercadopago/images/logo.png +0 -0
app/code/community/MercadoPago/Core/Block/Calculator/CalculatorForm.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MercadoPago_Core_Block_Calculator_CalculatorForm
4
+ extends Mage_Core_Block_Template
5
+ {
6
+
7
+ const CALCULATOR_JS = 'mercadopago/mercadopago_calculator.js';
8
+
9
+ /**
10
+ * @var $helperData MercadoPago_Core_Helper_Data
11
+ */
12
+ protected $_helperData;
13
+
14
+ protected function _construct()
15
+ {
16
+ parent::_construct();
17
+ $this->setTemplate('mercadopago/calculator/calculatorForm.phtml');
18
+ $this->_helperData = Mage::helper('mercadopago/data');
19
+ }
20
+
21
+ protected function getCalculatorJs()
22
+ {
23
+ return (Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_JS, true) . self::CALCULATOR_JS);
24
+ }
25
+
26
+ protected function getTinyUrl()
27
+ {
28
+ return Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_JS, true) . 'mercadopago/tiny.min.js';
29
+ }
30
+
31
+ protected function getTinyJUrl()
32
+ {
33
+ return Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_JS, true) . 'mercadopago/tinyJ.js';
34
+ }
35
+
36
+ protected function getPublicKey()
37
+ {
38
+ return Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_PUBLIC_KEY);
39
+ }
40
+
41
+ /**
42
+ * return the Payment methods token configured
43
+ *
44
+ * @return string
45
+ */
46
+ protected function getPaymentMethods()
47
+ {
48
+ return $this->_helperData->getMercadoPagoPaymentMethods(Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_ACCESS_TOKEN));
49
+ }
50
+
51
+ /**
52
+ * return the current value of amount
53
+ *
54
+ * @return mixed|bool
55
+ */
56
+ protected function getAmount()
57
+ {
58
+ return $this->getRequest()->getParam('currentAmount');
59
+ }
60
+
61
+ }
app/code/community/MercadoPago/Core/Block/Calculator/CalculatorLink.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MercadoPago_Core_Block_Calculator_CalculatorLink
4
+ extends Mage_Core_Block_Template
5
+ {
6
+
7
+ const PAGE_PDP = 'product.info.calculator';
8
+ const PAGE_CART = 'checkout.cart.calculator';
9
+
10
+ /**
11
+ * @var $helperData MercadoPago_Core_Helper_Data
12
+ */
13
+ protected $_helperData;
14
+
15
+ protected function _construct()
16
+ {
17
+ parent::_construct();
18
+ $this->_helperData = Mage::helper('mercadopago/data');
19
+ }
20
+
21
+
22
+ /**
23
+ * Check if the access token is valid, if the API is not down and if the configuration is enabled
24
+ *
25
+ * @return bool
26
+ */
27
+ protected function isAvailableCalculator(){
28
+
29
+ $isValidAccessToken = $this->_helperData->isValidAccessToken(Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_ACCESS_TOKEN));
30
+ $pk = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_PUBLIC_KEY);
31
+ return ($isValidAccessToken & !empty($pk) & $this->_helperData->isAvailableCalculator());
32
+
33
+ }
34
+
35
+ /**
36
+ * @param $nameLayoutConteiner string
37
+ * @return bool
38
+ */
39
+ protected function isPageToShow($nameLayoutConteiner){
40
+
41
+ $valueConfig = $this->_helperData->getPagesToShow();
42
+ $pages = explode(',', $valueConfig);
43
+
44
+ return in_array($nameLayoutConteiner, $pages);
45
+ }
46
+
47
+ /**
48
+ * @param $nameLayoutConteiner string
49
+ * @return bool
50
+ */
51
+ protected function inPagePDP($nameLayoutConteiner){
52
+
53
+ return $nameLayoutConteiner === self::PAGE_PDP;
54
+ }
55
+
56
+ /**
57
+ * @param $nameLayoutConteiner string
58
+ * @return bool
59
+ */
60
+ protected function inPageCheckoutCart($nameLayoutConteiner){
61
+
62
+ return $nameLayoutConteiner === self::PAGE_CART;
63
+ }
64
+
65
+ }
app/code/community/MercadoPago/Core/Block/Recurring/Form.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MercadoPago_Core_Block_Recurring_Form
4
+ extends Mage_Payment_Block_Form_Cc
5
+ {
6
+ protected function _construct()
7
+ {
8
+ parent::_construct();
9
+
10
+ $this->setTemplate('mercadopago/standard/form.phtml');
11
+ }
12
+ }
app/code/community/MercadoPago/Core/Block/Recurring/Info.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MercadoPago_Core_Block_Recurring_Info
4
+ extends Mage_Payment_Block_Info_Cc
5
+ {
6
+ protected function _construct()
7
+ {
8
+ parent::_construct();
9
+ $this->setTemplate('mercadopago/standard/info.phtml');
10
+ }
11
+
12
+
13
+ public function getOrder()
14
+ {
15
+ return $this->getInfo();
16
+ }
17
+
18
+ public function getInfoPayment()
19
+ {
20
+ $orderId = $this->getInfo()->getOrder()->getIncrementId();
21
+ $infoPayments = Mage::getModel('mercadopago/core')->getInfoPaymentByOrder($orderId);
22
+
23
+ return $infoPayments;
24
+ }
25
+ }
app/code/community/MercadoPago/Core/Block/Recurring/Pay.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MercadoPago_Core_Block_Recurring_Pay
4
+ extends Mage_Core_Block_Template
5
+ {
6
+ protected function _construct()
7
+ {
8
+ parent::_construct();
9
+
10
+ $this->setTemplate('mercadopago/standard/pay.phtml');
11
+ }
12
+ }
app/code/community/MercadoPago/Core/Block/Recurring/Success.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MercadoPago_Core_Block_Recurring_Success
4
+ extends MercadoPago_Core_Block_AbstractSuccess
5
+ {
6
+ protected function _construct()
7
+ {
8
+ parent::_construct();
9
+ $this->setTemplate('mercadopago/standard/success.phtml');
10
+ }
11
+
12
+ }
app/code/community/MercadoPago/Core/Helper/Data.php CHANGED
@@ -27,6 +27,14 @@ class MercadoPago_Core_Helper_Data
27
  const PLATFORM_DESKTOP = 'Desktop';
28
  const TYPE = 'magento';
29
 
 
 
 
 
 
 
 
 
30
  protected $_apiInstance;
31
 
32
  protected $_website;
@@ -73,12 +81,15 @@ class MercadoPago_Core_Helper_Data
73
  public function isValidAccessToken($accessToken)
74
  {
75
  $mp = Mage::helper('mercadopago')->getApiInstance($accessToken);
76
- $response = $mp->get("/v1/payment_methods");
77
- if ($response['status'] == 401 || $response['status'] == 400) {
 
 
 
 
 
78
  return false;
79
  }
80
-
81
- return true;
82
  }
83
 
84
  public function isValidClientCredentials($clientId, $clientSecret)
@@ -136,6 +147,7 @@ class MercadoPago_Core_Helper_Data
136
  if (!Mage::getStoreConfigFlag('payment/mercadopago/financing_cost')) {
137
  $order->setGrandTotal($order->getGrandTotal() - $balance);
138
  $order->setBaseGrandTotal($order->getBaseGrandTotal() - $balance);
 
139
  return;
140
  }
141
 
@@ -152,11 +164,11 @@ class MercadoPago_Core_Helper_Data
152
  */
153
  public function setPayerInfo(&$payment)
154
  {
155
- $payment["trunc_card"] = "xxxx xxxx xxxx " . $payment['card']["last_four_digits"];
156
- $payment["cardholder_name"] = $payment['card']["cardholder"]["name"];
157
- $payment['payer_first_name'] = $payment['payer']['first_name'];
158
- $payment['payer_last_name'] = $payment['payer']['last_name'];
159
- $payment['payer_email'] = $payment['payer']['email'];
160
 
161
  return $payment;
162
  }
@@ -212,4 +224,40 @@ class MercadoPago_Core_Helper_Data
212
  return $this->_website;
213
  }
214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  }
27
  const PLATFORM_DESKTOP = 'Desktop';
28
  const TYPE = 'magento';
29
 
30
+ //calculator
31
+ const XML_PATH_CALCULATOR_AVAILABLE = 'payment/mercadopago/calculalator_available';
32
+ const XML_PATH_CALCULATOR_PAGES = 'payment/mercadopago/show_in_pages';
33
+
34
+ const STATUS_ACTIVE = 'active';
35
+ const PAYMENT_TYPE_CREDIT_CARD = 'credit_card';
36
+
37
+
38
  protected $_apiInstance;
39
 
40
  protected $_website;
81
  public function isValidAccessToken($accessToken)
82
  {
83
  $mp = Mage::helper('mercadopago')->getApiInstance($accessToken);
84
+ try{
85
+ $response = $mp->get("/v1/payment_methods");
86
+ if ($response['status'] == 401 || $response['status'] == 400) {
87
+ return false;
88
+ }
89
+ return true;
90
+ } catch (\Exception $e){
91
  return false;
92
  }
 
 
93
  }
94
 
95
  public function isValidClientCredentials($clientId, $clientSecret)
147
  if (!Mage::getStoreConfigFlag('payment/mercadopago/financing_cost')) {
148
  $order->setGrandTotal($order->getGrandTotal() - $balance);
149
  $order->setBaseGrandTotal($order->getBaseGrandTotal() - $balance);
150
+
151
  return;
152
  }
153
 
164
  */
165
  public function setPayerInfo(&$payment)
166
  {
167
+ $payment["trunc_card"] = (isset($payment['card']["last_four_digits"])) ? "xxxx xxxx xxxx " . $payment['card']["last_four_digits"] : '';
168
+ $payment["cardholder_name"] = (isset($payment['card']["cardholder"]["name"])) ? $payment['card']["cardholder"]["name"] : '';
169
+ $payment['payer_first_name'] = (isset($payment['payer']['first_name'])) ? $payment['payer']['first_name'] : '';
170
+ $payment['payer_last_name'] = (isset($payment['payer']['last_name'])) ? $payment['payer']['last_name'] : '';
171
+ $payment['payer_email'] = (isset($payment['payer']['email'])) ? $payment['payer']['email'] : '';
172
 
173
  return $payment;
174
  }
224
  return $this->_website;
225
  }
226
 
227
+ /**
228
+ *
229
+ * @return boolean
230
+ */
231
+ public function isAvailableCalculator()
232
+ {
233
+ return Mage::getStoreConfig(self::XML_PATH_CALCULATOR_AVAILABLE);
234
+ }
235
+
236
+ /**
237
+ *
238
+ * @return mixed
239
+ */
240
+ public function getPagesToShow()
241
+ {
242
+ return Mage::getStoreConfig(self::XML_PATH_CALCULATOR_PAGES);
243
+ }
244
+
245
+ /**
246
+ * return the list of payment methods or null
247
+ *
248
+ * @param mixed|null $accessToken
249
+ *
250
+ * @return mixed
251
+ */
252
+ public function getMercadoPagoPaymentMethods($accessToken)
253
+ {
254
+ $mp = Mage::helper('mercadopago')->getApiInstance($accessToken);
255
+ $response = $mp->get("/v1/payment_methods");
256
+ if ($response['status'] == 401 || $response['status'] == 400) {
257
+ return false;
258
+ }
259
+
260
+ return $response['response'];
261
+ }
262
+
263
  }
app/code/community/MercadoPago/Core/Helper/Response.php CHANGED
@@ -34,6 +34,10 @@ class MercadoPago_Core_Helper_Response
34
  const INFO_MERCHANT_ORDER_NOT_FOUND = 'Merchant Order not found';
35
  const INFO_STATUS_NOT_FINAL = 'Status not final';
36
  const INFO_EXTERNAL_REFERENCE_NOT_FOUND = 'External reference not found';
 
 
 
 
37
 
38
 
39
  }
34
  const INFO_MERCHANT_ORDER_NOT_FOUND = 'Merchant Order not found';
35
  const INFO_STATUS_NOT_FINAL = 'Status not final';
36
  const INFO_EXTERNAL_REFERENCE_NOT_FOUND = 'External reference not found';
37
+ const INFO_ORDER_CANCELED = 'The order is canceled';
38
+
39
+ const TOPIC_RECURRING_PAYMENT = 'preapproval';
40
+ const TOPIC_PAYMENT = 'payment';
41
 
42
 
43
  }
app/code/community/MercadoPago/Core/Helper/StatusUpdate.php CHANGED
@@ -21,24 +21,41 @@ class MercadoPago_Core_Helper_StatusUpdate
21
  return $this->_statusUpdatedFlag;
22
  }
23
 
24
- public function setStatusUpdated($notificationData, $order)
25
  {
26
  $this->_order = $order;
27
  $status = $notificationData['status'];
28
  $statusDetail = $notificationData['status_detail'];
29
  $currentStatus = $this->_order->getPayment()->getAdditionalInformation('status');
30
  $currentStatusDetail = $this->_order->getPayment()->getAdditionalInformation('status_detail');
 
 
 
 
 
 
 
 
 
31
  if ($status == $currentStatus && $statusDetail == $currentStatusDetail) {
32
  $this->_statusUpdatedFlag = true;
33
  }
34
  }
35
 
 
 
 
 
 
 
 
36
  protected function _updateStatus($status, $message, $statusDetail)
37
  {
38
- if ($this->_order->getState() !== Mage_Sales_Model_Order::STATE_COMPLETE) {
 
39
  $statusOrder = $this->getStatusOrder($status, $statusDetail);
40
 
41
- if (isset($statusOrder)) {
42
  $this->_order->setState($this->_getAssignedState($statusOrder));
43
  $this->_order->addStatusToHistory($statusOrder, $message, true);
44
  $this->_order->sendOrderUpdateEmail(true, $message);
@@ -72,7 +89,8 @@ class MercadoPago_Core_Helper_StatusUpdate
72
  }
73
  }
74
 
75
- protected function _createCreditmemo ($data) {
 
76
  /**
77
  * @var $creditmemo Mage_Sales_Model_Order_Creditmemo
78
  */
@@ -116,11 +134,45 @@ class MercadoPago_Core_Helper_StatusUpdate
116
  }
117
  }
118
 
119
- public function update($payment, $message) {
120
- $status = $payment['status'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  $statusDetail = $payment['status_detail'];
 
 
 
 
122
 
123
- if ($status == 'approved') {
124
  Mage::helper('mercadopago')->setOrderSubtotals($payment, $this->_order);
125
  $this->_createInvoice($this->_order, $message);
126
  //Associate card to customer
@@ -130,40 +182,31 @@ class MercadoPago_Core_Helper_StatusUpdate
130
  }
131
  }
132
 
 
 
 
 
 
 
133
  if (isset($payment['amount_refunded']) && $payment['amount_refunded'] > 0) {
134
  $this->_generateCreditMemo($payment);
135
  } elseif ($status == 'cancelled') {
136
  Mage::register('mercadopago_cancellation', true);
137
  $this->_order->cancel();
138
- }
139
- else {
140
  //if state is not complete updates according to setting
141
  $this->_updateStatus($status, $message, $statusDetail);
142
  }
 
143
  return $this->_order->save();
144
  }
145
 
146
- public function setStatusOrder($payment)
147
  {
148
- $helper = Mage::helper('mercadopago');
149
-
150
- $status = $this->getStatus($payment);
151
- $message = $this->getMessage($status, $payment);
152
- if ($this->isStatusUpdated() && isset ($payment['amount_refunded']) && !($payment['amount_refunded'] > 0)) {
153
- return ['body' => $message, 'code' => MercadoPago_Core_Helper_Response::HTTP_OK];
154
- }
155
-
156
- try {
157
- $statusSave = $this->update($payment, $message);
158
-
159
- $helper->log("Update order", 'mercadopago.log', $statusSave->getData());
160
- $helper->log($message, 'mercadopago.log');
161
-
162
- return ['body' => $message, 'code' => MercadoPago_Core_Helper_Response::HTTP_OK];
163
- } catch (Exception $e) {
164
- $helper->log("error in set order status: " . $e, 'mercadopago.log');
165
-
166
- return ['body' => $e, 'code' => MercadoPago_Core_Helper_Response::HTTP_BAD_REQUEST];
167
  }
168
  }
169
 
@@ -193,7 +236,7 @@ class MercadoPago_Core_Helper_StatusUpdate
193
 
194
  public function getStatusOrder($status, $statusDetail)
195
  {
196
- switch ($status) {
197
  case 'approved': {
198
  $status = Mage::getStoreConfig('payment/mercadopago/order_status_approved');
199
 
@@ -308,4 +351,80 @@ class MercadoPago_Core_Helper_StatusUpdate
308
  }
309
  }
310
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  }
21
  return $this->_statusUpdatedFlag;
22
  }
23
 
24
+ public function setStatusUpdated($notificationData, $order, $isPayment = false)
25
  {
26
  $this->_order = $order;
27
  $status = $notificationData['status'];
28
  $statusDetail = $notificationData['status_detail'];
29
  $currentStatus = $this->_order->getPayment()->getAdditionalInformation('status');
30
  $currentStatusDetail = $this->_order->getPayment()->getAdditionalInformation('status_detail');
31
+ if ($isPayment) {
32
+ $currentStatus = $this->_getMulticardLastValue($currentStatus);
33
+ $currentStatusDetail = $this->_getMulticardLastValue($currentStatusDetail);
34
+ }
35
+ if (!is_null($order->getPayment()) && $order->getPayment()->getAdditionalInformation('is_second_card_used')) {
36
+ $this->_statusUpdatedFlag = false;
37
+
38
+ return;
39
+ }
40
  if ($status == $currentStatus && $statusDetail == $currentStatusDetail) {
41
  $this->_statusUpdatedFlag = true;
42
  }
43
  }
44
 
45
+ protected function _getMulticardLastValue($value)
46
+ {
47
+ $statuses = explode('|', $value);
48
+
49
+ return str_replace(' ', '', array_pop($statuses));
50
+ }
51
+
52
  protected function _updateStatus($status, $message, $statusDetail)
53
  {
54
+ if ($this->_order->getState() !== Mage_Sales_Model_Order::STATE_COMPLETE
55
+ ) {
56
  $statusOrder = $this->getStatusOrder($status, $statusDetail);
57
 
58
+ if (isset($statusOrder) && ($this->_order->getStatus() !== $statusOrder)) {
59
  $this->_order->setState($this->_getAssignedState($statusOrder));
60
  $this->_order->addStatusToHistory($statusOrder, $message, true);
61
  $this->_order->sendOrderUpdateEmail(true, $message);
89
  }
90
  }
91
 
92
+ protected function _createCreditmemo($data)
93
+ {
94
  /**
95
  * @var $creditmemo Mage_Sales_Model_Order_Creditmemo
96
  */
134
  }
135
  }
136
 
137
+ public function setStatusOrder($payment)
138
+ {
139
+ $helper = Mage::helper('mercadopago');
140
+ $status = $this->getStatus($payment);
141
+
142
+ $message = $this->getMessage($status, $payment);
143
+ if ($this->isStatusUpdated()) {
144
+ if (!(isset($payment['amount_refunded']) && ($payment['amount_refunded'] > 0))) {
145
+ if (!(isset($payment['refunds']) && count($payment['refunds']) > 0)) {
146
+ if ($this->_order->getPayment()->getAdditionalInformation('is_second_card_used')) {
147
+ //if status is updated, there are no refunds and no custom payments with two cards.
148
+ return ['body' => $message, 'code' => MercadoPago_Core_Helper_Response::HTTP_OK];
149
+ }
150
+ }
151
+ }
152
+ }
153
+
154
+ try {
155
+ $statusSave = $this->update($payment, $message);
156
+
157
+ $helper->log("Update order", 'mercadopago.log', $statusSave->getData());
158
+ $helper->log($message, 'mercadopago.log');
159
+
160
+ return ['body' => $message, 'code' => MercadoPago_Core_Helper_Response::HTTP_OK];
161
+ } catch (Exception $e) {
162
+ $helper->log("error in set order status: " . $e, 'mercadopago.log');
163
+
164
+ return ['body' => $e, 'code' => MercadoPago_Core_Helper_Response::HTTP_BAD_REQUEST];
165
+ }
166
+ }
167
+
168
+ public function update($payment, $message)
169
+ {
170
  $statusDetail = $payment['status_detail'];
171
+ $status = $payment['status'];
172
+ $infoPayments = $this->_order->getPayment()->getAdditionalInformation();
173
+ if ($this->_getMulticardLastValue($status) == 'approved') {
174
+ $this->_handleTwoCards($payment, $infoPayments);
175
 
 
176
  Mage::helper('mercadopago')->setOrderSubtotals($payment, $this->_order);
177
  $this->_createInvoice($this->_order, $message);
178
  //Associate card to customer
182
  }
183
  }
184
 
185
+ if (isset($infoPayments['first_payment_id']) &&
186
+ !($infoPayments['first_payment_status'] == 'approved' && $infoPayments['second_payment_status'] == 'approved')
187
+ ) {
188
+ return $this->_order->save();
189
+ }
190
+
191
  if (isset($payment['amount_refunded']) && $payment['amount_refunded'] > 0) {
192
  $this->_generateCreditMemo($payment);
193
  } elseif ($status == 'cancelled') {
194
  Mage::register('mercadopago_cancellation', true);
195
  $this->_order->cancel();
196
+ } else {
 
197
  //if state is not complete updates according to setting
198
  $this->_updateStatus($status, $message, $statusDetail);
199
  }
200
+
201
  return $this->_order->save();
202
  }
203
 
204
+ protected function _handleTwoCards(&$payment, $infoPayments)
205
  {
206
+ if (isset($infoPayments['is_second_card_used']) && $infoPayments['is_second_card_used'] === "true") {
207
+ $payment['total_paid_amount'] = $infoPayments['total_paid_amount'];
208
+ $payment['transaction_amount'] = $infoPayments['transaction_amount'];
209
+ $payment['status'] = $infoPayments['status'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  }
211
  }
212
 
236
 
237
  public function getStatusOrder($status, $statusDetail)
238
  {
239
+ switch ($this->_getMulticardLastValue($status)) {
240
  case 'approved': {
241
  $status = Mage::getStoreConfig('payment/mercadopago/order_status_approved');
242
 
351
  }
352
  }
353
 
354
+ /**
355
+ * @param $data
356
+ * @param $payment
357
+ * @param $logFile
358
+ *
359
+ * Update $data with the information in the payment.
360
+ * if it has more than one payment, the information is concatenated by separating the data with a '|'
361
+ *
362
+ * @return mixed
363
+ */
364
+ public function formatArrayPayment($data, $payment, $logFile)
365
+ {
366
+ Mage::helper('mercadopago')->log("Format Array", $logFile);
367
+
368
+ $fields = [
369
+ "status",
370
+ "status_detail",
371
+ "payment_id_detail",
372
+ "id",
373
+ "payment_method_id",
374
+ "transaction_amount",
375
+ "total_paid_amount",
376
+ "coupon_amount",
377
+ "installments",
378
+ "shipping_cost",
379
+ "amount_refunded"
380
+ ];
381
+
382
+ foreach ($fields as $field) {
383
+ if (isset($payment[$field])) {
384
+ if (isset($data[$field])) {
385
+ $data[$field] .= " | " . $payment[$field];
386
+ } else {
387
+ $data[$field] = $payment[$field];
388
+ }
389
+ }
390
+ }
391
+ $data = $this->_updateAtributesData($data, $payment);
392
+
393
+ $data['external_reference'] = $payment['external_reference'];
394
+ $data['payer_first_name'] = $payment['payer']['first_name'];
395
+ $data['payer_last_name'] = $payment['payer']['last_name'];
396
+ $data['payer_email'] = $payment['payer']['email'];
397
+
398
+ return $data;
399
+ }
400
+
401
+ protected function _updateAtributesData($data, $payment){
402
+ if (isset($payment["last_four_digits"])) {
403
+ if (isset($data["trunc_card"])) {
404
+ $data["trunc_card"] .= " | " . "xxxx xxxx xxxx " . $payment["last_four_digits"];
405
+ } else {
406
+ $data["trunc_card"] = "xxxx xxxx xxxx " . $payment["last_four_digits"];
407
+ }
408
+ }
409
+
410
+ if (isset($payment['cardholder']['name'])) {
411
+ if (isset($data["cardholder_name"])) {
412
+ $data["cardholder_name"] .= " | " . $payment["cardholder"]["name"];
413
+ } else {
414
+ $data["cardholder_name"] = $payment["cardholder"]["name"];
415
+ }
416
+ }
417
+
418
+ if (isset($payment['statement_descriptor'])) {
419
+ $data['statement_descriptor'] = $payment['statement_descriptor'];
420
+ }
421
+
422
+ if (isset($payment['merchant_order_id'])) {
423
+ $data['merchant_order_id'] = $payment['merchant_order_id'];
424
+ }
425
+
426
+ return $data;
427
+ }
428
+
429
+
430
  }
app/code/community/MercadoPago/Core/Model/Core.php CHANGED
@@ -26,7 +26,7 @@ class MercadoPago_Core_Model_Core
26
  protected $_canOrder = true;
27
  protected $_canRefund = true;
28
  protected $_canVoid = true;
29
- protected $_canUseInternal = true;
30
  protected $_canUseCheckout = true;
31
  protected $_canUseForMultishipping = true;
32
  protected $_canFetchTransactionInfo = true;
@@ -103,6 +103,8 @@ class MercadoPago_Core_Model_Core
103
  ["field" => "status_detail", "title" => "Payment Detail: %s"],
104
  ["field" => "activation_uri", "title" => "Generate Ticket"],
105
  ["field" => "payment_id_detail", "title" => "Mercado Pago Payment Id: %s"],
 
 
106
  ];
107
 
108
  foreach ($fields as $field) {
@@ -255,7 +257,11 @@ class MercadoPago_Core_Model_Core
255
 
256
  $preference['notification_url'] = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK) . "mercadopago/notifications/custom";
257
  $preference['description'] = Mage::helper('mercadopago')->__("Order # %s in store %s", $orderId, Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true));
258
- $preference['transaction_amount'] = (float)$this->getAmount();
 
 
 
 
259
 
260
  $preference['external_reference'] = $orderId;
261
  $preference['payer']['email'] = $customerInfo['email'];
@@ -478,15 +484,10 @@ class MercadoPago_Core_Model_Core
478
  'trunc_card',
479
  'id'
480
  ];
481
-
482
- foreach ($additionalFields as $field) {
483
- if (isset($data[$field])) {
484
- $paymentOrder->setAdditionalInformation($field, $data[$field]);
485
- }
486
- }
487
-
488
- if (isset($data['payment_method_id'])) {
489
- $paymentOrder->setAdditionalInformation('payment_method', $data['payment_method_id']);
490
  }
491
 
492
  $paymentStatus = $paymentOrder->save();
@@ -502,6 +503,23 @@ class MercadoPago_Core_Model_Core
502
  }
503
  }
504
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  protected function _saveTransaction($data, $paymentOrder)
506
  {
507
  try {
@@ -516,4 +534,15 @@ class MercadoPago_Core_Model_Core
516
  }
517
  }
518
 
 
 
 
 
 
 
 
 
 
 
 
519
  }
26
  protected $_canOrder = true;
27
  protected $_canRefund = true;
28
  protected $_canVoid = true;
29
+ protected $_canUseInternal = false;
30
  protected $_canUseCheckout = true;
31
  protected $_canUseForMultishipping = true;
32
  protected $_canFetchTransactionInfo = true;
103
  ["field" => "status_detail", "title" => "Payment Detail: %s"],
104
  ["field" => "activation_uri", "title" => "Generate Ticket"],
105
  ["field" => "payment_id_detail", "title" => "Mercado Pago Payment Id: %s"],
106
+ ["field" => "id", "title" => "Collection Id: %s"],
107
+
108
  ];
109
 
110
  foreach ($fields as $field) {
257
 
258
  $preference['notification_url'] = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK) . "mercadopago/notifications/custom";
259
  $preference['description'] = Mage::helper('mercadopago')->__("Order # %s in store %s", $orderId, Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true));
260
+ if (isset($paymentInfo['transaction_amount'])) {
261
+ $preference['transaction_amount'] = (float)$paymentInfo['transaction_amount'];
262
+ } else {
263
+ $preference['transaction_amount'] = (float)$this->getAmount();
264
+ }
265
 
266
  $preference['external_reference'] = $orderId;
267
  $preference['payer']['email'] = $customerInfo['email'];
484
  'trunc_card',
485
  'id'
486
  ];
487
+
488
+ $infoPayments = $paymentOrder->getAdditionalInformation();
489
+ if (!isset($infoPayments['first_payment_id'])) {
490
+ $paymentOrder = $this->_addAdditionalInformationToPaymentOrder($data, $additionalFields, $paymentOrder);
 
 
 
 
 
491
  }
492
 
493
  $paymentStatus = $paymentOrder->save();
503
  }
504
  }
505
 
506
+ protected function _addAdditionalInformationToPaymentOrder($data, $additionalFields, $paymentOrder){
507
+ foreach ($additionalFields as $field) {
508
+ if (isset($data[$field])) {
509
+ $paymentOrder->setAdditionalInformation($field, $data[$field]);
510
+ }
511
+ }
512
+
513
+ if (isset($data['payment_method_id'])) {
514
+ $paymentOrder->setAdditionalInformation('payment_method', $data['payment_method_id']);
515
+ }
516
+
517
+ if (isset($data['merchant_order_id'])) {
518
+ $paymentOrder->setAdditionalInformation('merchant_order_id', $data['merchant_order_id']);
519
+ }
520
+ return $paymentOrder;
521
+ }
522
+
523
  protected function _saveTransaction($data, $paymentOrder)
524
  {
525
  try {
534
  }
535
  }
536
 
537
+ public function getRecurringPayment($id)
538
+ {
539
+ if (!$this->_clientId || !$this->_clientSecret) {
540
+ $this->_clientId = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_ID);
541
+ $this->_clientSecret = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_SECRET);
542
+ }
543
+ $mp = Mage::helper('mercadopago')->getApiInstance($this->_clientId, $this->_clientSecret);
544
+
545
+ return $mp->get_preapproval_payment($id);
546
+ }
547
+
548
  }
app/code/community/MercadoPago/Core/Model/Cron/Order.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MercadoPago_Core_Model_Cron_Order
4
+ {
5
+ /**
6
+ * @var $_statusHelper MercadoPago_Core_Helper_StatusUpdate
7
+ */
8
+ protected $_statusHelper;
9
+
10
+ const LOG_FILE = 'mercadopago-order-synchronized.log';
11
+
12
+ public function updateOrderStatus(){
13
+ $this->_statusHelper = Mage::helper('mercadopago/statusUpdate');
14
+ $helper = Mage::helper('mercadopago');
15
+ $hours = Mage::getStoreConfig('payment/mercadopago/number_of_hours');
16
+
17
+ // filter to date:
18
+ $fromDate = date('Y-m-d H:i:s', strtotime('-'.$hours. ' hours'));
19
+ $toDate = date('Y-m-d H:i:s', strtotime("now"));
20
+
21
+ $collection = Mage::getModel('sales/order')->getCollection()
22
+ ->join(
23
+ array('payment' => 'sales/order_payment'),
24
+ 'main_table.entity_id=payment.parent_id',
25
+ array('payment_method' => 'payment.method')
26
+ )->addFieldToFilter('payment.method', array('in' => array(
27
+ 'mercadopago_custom',
28
+ 'mercadopago_customticket',
29
+ 'mercadopago_standard'))
30
+ )->addFieldToFilter('status', array('nin' => array(
31
+ 'canceled',
32
+ 'complete'))
33
+ )->addFieldToFilter('created_at', array('from'=>$fromDate, 'to'=>$toDate))
34
+ ;
35
+
36
+ // For all Orders to analyze
37
+ foreach($collection as $orderByPayment){
38
+ $order = $orderByPayment;
39
+ $paymentOrder = $order->getPayment();
40
+ $infoPayments = $paymentOrder->getAdditionalInformation();
41
+
42
+ if (isset($infoPayments['merchant_order_id']) && $order->getStatus() !== 'complete') {
43
+
44
+
45
+ $merchantOrderId = $infoPayments['merchant_order_id'];
46
+ $response = Mage::getModel('mercadopago/core')->getMerchantOrder($merchantOrderId);
47
+
48
+ if ($response['status'] == 201 || $response['status'] == 200) {
49
+ $merchantOrderData = $response['response'];
50
+
51
+ $paymentData = $this->getDataPayments($merchantOrderData);
52
+ $statusFinal = $this->_statusHelper->getStatusFinal($paymentData['status'], $merchantOrderData);
53
+ $statusDetail = $infoPayments['status_detail'];
54
+
55
+ $statusOrder = $this->_statusHelper->getStatusOrder($statusFinal, $statusDetail);
56
+ if (isset($statusOrder) && ($order->getStatus() !== $statusOrder)) {
57
+ $this->_updateOrder($order, $statusOrder, $paymentOrder);
58
+
59
+ }
60
+ } else{
61
+ $helper->log('Error updating status order using cron whit the merchantOrder num: '. $merchantOrderId .'mercadopago.log');
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ protected function _updateOrder($order, $statusOrder, $paymentOrder){
68
+ $order->setState($this->_statusHelper->_getAssignedState($statusOrder));
69
+ $order->addStatusToHistory($statusOrder, $this->_statusHelper->getMessage($statusOrder, $statusOrder), true);
70
+ $order->sendOrderUpdateEmail(true, $this->_statusHelper->getMessage($statusOrder, $paymentOrder));
71
+ $order->save();
72
+ }
73
+
74
+ protected function getDataPayments($merchantOrderData)
75
+ {
76
+ $data = array();
77
+ foreach ($merchantOrderData['payments'] as $payment) {
78
+ $data = $this->getFormattedPaymentData($payment['id'], $data);
79
+ }
80
+
81
+ return $data;
82
+ }
83
+
84
+ protected function getFormattedPaymentData($paymentId, $data = [])
85
+ {
86
+ $core = Mage::getModel('mercadopago/core');
87
+
88
+ $response = $core->getPayment($paymentId);
89
+ if ($response['status'] == 400 || $response['status'] == 401) {
90
+ return [];
91
+ }
92
+ $payment = $response['response']['collection'];
93
+
94
+ return $this->_statusHelper->formatArrayPayment($data, $payment, self::LOG_FILE);
95
+ }
96
+
97
+ }
app/code/community/MercadoPago/Core/Model/Custom/Payment.php CHANGED
@@ -42,24 +42,89 @@ class MercadoPago_Core_Model_Custom_Payment
42
  Mage::throwException(Mage::helper('mercadopago')->__('Verify the form data or wait until the validation of the payment data'));
43
  }
44
 
45
- $response = $this->preparePostPayment();
46
-
47
- if ($response) {
48
- $payment = $response['response'];
49
- //set status
50
- $this->getInfoInstance()->setAdditionalInformation('status', $payment['status']);
51
- $this->getInfoInstance()->setAdditionalInformation('payment_id_detail', $payment['id']);
52
- $this->getInfoInstance()->setAdditionalInformation('status_detail', $payment['status_detail']);
53
- $stateObject->setState(Mage::helper('mercadopago/statusUpdate')->_getAssignedState('pending_payment'));
54
- $stateObject->setStatus('pending_payment');
55
- $stateObject->setIsNotified(false);
56
-
57
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  }
59
 
60
  return false;
61
  }
62
 
 
 
 
 
 
 
 
 
63
  protected function cleanFieldsOcp($info)
64
  {
65
  foreach (self::$exclude_inputs_opc as $field) {
@@ -131,7 +196,7 @@ class MercadoPago_Core_Model_Custom_Payment
131
  return $payment_info;
132
  }
133
 
134
- public function preparePostPayment()
135
  {
136
  Mage::helper('mercadopago')->log("Credit Card -> init prepare post payment", self::LOG_FILE);
137
  $core = Mage::getModel('mercadopago/core');
@@ -142,11 +207,22 @@ class MercadoPago_Core_Model_Custom_Payment
142
  $payment = $order->getPayment();
143
  $payment_info = $this->getPaymentInfo($payment);
144
 
 
 
 
 
145
  $preference = $core->makeDefaultPreferencePaymentV1($payment_info);
146
 
147
- $preference['installments'] = (int)$payment->getAdditionalInformation("installments");
148
- $preference['payment_method_id'] = $payment->getAdditionalInformation("payment_method");
149
- $preference['token'] = $payment->getAdditionalInformation("token");
 
 
 
 
 
 
 
150
 
151
  if ($payment->getAdditionalInformation("issuer_id") != "") {
152
  $preference['issuer_id'] = (int)$payment->getAdditionalInformation("issuer_id");
@@ -164,8 +240,6 @@ class MercadoPago_Core_Model_Custom_Payment
164
  /* POST /v1/payments */
165
  $response = $core->postPaymentV1($preference);
166
 
167
- $order->save();
168
-
169
  return $response;
170
  }
171
 
42
  Mage::throwException(Mage::helper('mercadopago')->__('Verify the form data or wait until the validation of the payment data'));
43
  }
44
 
45
+ $useTwoCards = $this->getInfoInstance()->getAdditionalInformation('is_second_card_used');
46
+
47
+ if ($useTwoCards === "true") {
48
+ $usingSecondCardInfo['first_card']['amount'] = $this->getInfoInstance()->getAdditionalInformation('first_card_amount');
49
+ $usingSecondCardInfo['first_card']['installments'] = $this->getInfoInstance()->getAdditionalInformation('installments');
50
+ $usingSecondCardInfo['first_card']['payment_method_id'] = $this->getInfoInstance()->getAdditionalInformation('payment_method');
51
+ $usingSecondCardInfo['first_card']['token'] = $this->getInfoInstance()->getAdditionalInformation('token');
52
+
53
+ $usingSecondCardInfo['second_card']['amount'] = $this->getInfoInstance()->getAdditionalInformation('second_card_amount');
54
+ $usingSecondCardInfo['second_card']['installments'] = $this->getInfoInstance()->getAdditionalInformation('second_card_installments');
55
+ $usingSecondCardInfo['second_card']['payment_method_id'] = $this->getInfoInstance()->getAdditionalInformation('second_card_payment_method_id');
56
+ $usingSecondCardInfo['second_card']['token'] = $this->getInfoInstance()->getAdditionalInformation('second_card_token');
57
+
58
+ $responseFirstCard = $this->preparePostPayment($usingSecondCardInfo['first_card']);
59
+ if (isset($responseFirstCard) && ($responseFirstCard['response']['status'] == 'approved') ) {
60
+ $paymentFirstCard = $responseFirstCard['response'];
61
+ $responseSecondCard = $this->preparePostPayment($usingSecondCardInfo['second_card']);
62
+
63
+ if (isset($responseSecondCard) && ($responseSecondCard['response']['status'] == 'approved') ) {
64
+ $paymentSecondCard = $responseSecondCard['response'];
65
+ $this->getInfoInstance()->setAdditionalInformation('status', $paymentFirstCard['status'] . ' | ' . $paymentSecondCard['status']);
66
+ $this->getInfoInstance()->setAdditionalInformation('payment_id_detail', $paymentFirstCard['id'] . ' | ' . $paymentSecondCard['id']);
67
+ $this->getInfoInstance()->setAdditionalInformation('status_detail', $paymentFirstCard['status_detail'] . ' | ' . $paymentSecondCard['status_detail']);
68
+ $this->getInfoInstance()->setAdditionalInformation('installments', $paymentFirstCard['installments'] . ' | ' . $paymentSecondCard['installments']);
69
+ $this->getInfoInstance()->setAdditionalInformation('payment_method', $paymentFirstCard['payment_method_id'] . ' | ' . $paymentSecondCard['payment_method_id']);
70
+ $this->getInfoInstance()->setAdditionalInformation('first_payment_id', $paymentFirstCard['id']);
71
+ $this->getInfoInstance()->setAdditionalInformation('first_payment_status', $paymentFirstCard['status']);
72
+ $this->getInfoInstance()->setAdditionalInformation('first_payment_status_detail', $paymentFirstCard['status_detail']);
73
+ $this->getInfoInstance()->setAdditionalInformation('second_payment_id', $paymentSecondCard['id']);
74
+ $this->getInfoInstance()->setAdditionalInformation('second_payment_status', $paymentSecondCard['status']);
75
+ $this->getInfoInstance()->setAdditionalInformation('second_payment_status_detail', $paymentSecondCard['status_detail']);
76
+ $this->getInfoInstance()->setAdditionalInformation('total_paid_amount', $paymentFirstCard['transaction_details']['total_paid_amount'] . '|' . $paymentSecondCard['transaction_details']['total_paid_amount']);
77
+ $this->getInfoInstance()->setAdditionalInformation('transaction_amount', $paymentFirstCard['transaction_amount'] . '|' . $paymentSecondCard['transaction_amount']);
78
+ $stateObject->setState(Mage::helper('mercadopago/statusUpdate')->_getAssignedState('pending_payment'));
79
+ $stateObject->setStatus('pending_payment');
80
+ $stateObject->setIsNotified(false);
81
+ $this->saveOrder();
82
+ return true;
83
+ } else {
84
+ //second card payment failed, refund for first card
85
+ $accessToken = Mage::getStoreConfig(self::XML_PATH_ACCESS_TOKEN);
86
+ $mp = Mage::helper('mercadopago')->getApiInstance($accessToken);
87
+ $id = $paymentFirstCard['id'];
88
+ $refundResponse = $mp->post("/v1/payments/$id/refunds?access_token=$accessToken");
89
+ Mage::helper('mercadopago')->log("info form", self::LOG_FILE, $refundResponse);
90
+ return false;
91
+ }
92
+ } else {
93
+ return false;
94
+ }
95
+
96
+
97
+ } else {
98
+
99
+ $response = $this->preparePostPayment();
100
+
101
+ if ($response) {
102
+ $payment = $response['response'];
103
+ //set status
104
+ $this->getInfoInstance()->setAdditionalInformation('status', $payment['status']);
105
+ $this->getInfoInstance()->setAdditionalInformation('payment_id_detail', $payment['id']);
106
+ $this->getInfoInstance()->setAdditionalInformation('status_detail', $payment['status_detail']);
107
+ $stateObject->setState(Mage::helper('mercadopago/statusUpdate')->_getAssignedState('pending_payment'));
108
+ $stateObject->setStatus('pending_payment');
109
+ $stateObject->setIsNotified(false);
110
+
111
+ $this->saveOrder();
112
+
113
+ return true;
114
+ }
115
  }
116
 
117
  return false;
118
  }
119
 
120
+ protected function saveOrder() {
121
+ $quote = $this->_getQuote();
122
+ $order_id = $quote->getReservedOrderId();
123
+ $order = $this->_getOrder($order_id);
124
+ $order->save();
125
+ }
126
+
127
+
128
  protected function cleanFieldsOcp($info)
129
  {
130
  foreach (self::$exclude_inputs_opc as $field) {
196
  return $payment_info;
197
  }
198
 
199
+ public function preparePostPayment($usingSecondCardInfo = null)
200
  {
201
  Mage::helper('mercadopago')->log("Credit Card -> init prepare post payment", self::LOG_FILE);
202
  $core = Mage::getModel('mercadopago/core');
207
  $payment = $order->getPayment();
208
  $payment_info = $this->getPaymentInfo($payment);
209
 
210
+ if (isset($usingSecondCardInfo)) {
211
+ $payment_info['transaction_amount'] = $usingSecondCardInfo ['amount'];
212
+ }
213
+
214
  $preference = $core->makeDefaultPreferencePaymentV1($payment_info);
215
 
216
+ if (isset($usingSecondCardInfo)) {
217
+ $preference['installments'] = (int)$usingSecondCardInfo['installments'];
218
+ $preference['payment_method_id'] = $usingSecondCardInfo['payment_method_id'];
219
+ $preference['token'] = $usingSecondCardInfo['token'];
220
+ } else {
221
+ $preference['installments'] = (int)$payment->getAdditionalInformation("installments");
222
+ $preference['payment_method_id'] = $payment->getAdditionalInformation("payment_method");
223
+ $preference['token'] = $payment->getAdditionalInformation("token");
224
+ }
225
+
226
 
227
  if ($payment->getAdditionalInformation("issuer_id") != "") {
228
  $preference['issuer_id'] = (int)$payment->getAdditionalInformation("issuer_id");
240
  /* POST /v1/payments */
241
  $response = $core->postPaymentV1($preference);
242
 
 
 
243
  return $response;
244
  }
245
 
app/code/community/MercadoPago/Core/Model/CustomTicket/Payment.php CHANGED
@@ -36,7 +36,7 @@ class MercadoPago_Core_Model_CustomTicket_Payment
36
 
37
  if ($response !== false) {
38
  $this->getInfoInstance()->setAdditionalInformation('activation_uri', $response['response']['transaction_details']['external_resource_url']);
39
-
40
  return true;
41
  }
42
 
@@ -58,6 +58,8 @@ class MercadoPago_Core_Model_CustomTicket_Payment
58
  $info = $this->getInfoInstance();
59
  $info->setAdditionalInformation('payment_method', $infoForm['payment_method_ticket']);
60
 
 
 
61
  if (isset($infoForm['coupon_code'])) {
62
  $info->setAdditionalInformation('coupon_code', $infoForm['coupon_code']);
63
  }
36
 
37
  if ($response !== false) {
38
  $this->getInfoInstance()->setAdditionalInformation('activation_uri', $response['response']['transaction_details']['external_resource_url']);
39
+ $this->getInfoInstance()->setAdditionalInformation('payment_id_detail', $response['response']['id']);
40
  return true;
41
  }
42
 
58
  $info = $this->getInfoInstance();
59
  $info->setAdditionalInformation('payment_method', $infoForm['payment_method_ticket']);
60
 
61
+
62
+
63
  if (isset($infoForm['coupon_code'])) {
64
  $info->setAdditionalInformation('coupon_code', $infoForm['coupon_code']);
65
  }
app/code/community/MercadoPago/Core/Model/Observer.php CHANGED
@@ -66,6 +66,8 @@ class MercadoPago_Core_Model_Observer
66
 
67
  $this->validateClientCredentials();
68
 
 
 
69
  $this->setSponsor();
70
 
71
  $this->availableCheckout();
@@ -133,7 +135,7 @@ class MercadoPago_Core_Model_Observer
133
  $user = $mp->get("/users/me");
134
  Mage::helper('mercadopago')->log("API Users response", self::LOG_FILE, $user);
135
 
136
- if ($user['status'] == 200 && !in_array("test_user", $user['response']['tags'])) {
137
  $sponsors = [
138
  'MLA' => 186172525,
139
  'MLB' => 186175129,
@@ -142,15 +144,16 @@ class MercadoPago_Core_Model_Observer
142
  'MLC' => 206959756,
143
  'MLV' => 206960619,
144
  'MPE' => 217178514,
 
145
  ];
146
  $countryCode = $user['response']['site_id'];
147
-
148
  if (isset($sponsors[$countryCode])) {
149
  $sponsorId = $sponsors[$countryCode];
150
  } else {
151
  $sponsorId = "";
152
  }
153
-
154
  Mage::helper('mercadopago')->log("Sponsor id set", self::LOG_FILE, $sponsorId);
155
  }
156
  $this->_saveWebsiteConfig('payment/mercadopago/sponsor_id', $sponsorId);
@@ -191,44 +194,55 @@ class MercadoPago_Core_Model_Observer
191
  public function salesOrderBeforeCancel (Varien_Event_Observer $observer) {
192
  $orderID = (int) $observer->getEvent()->getControllerAction()->getRequest()->getParam('order_id');
193
  $order = Mage::getModel('sales/order')->load($orderID);
194
- if ($order->getExternalRequest()) {
 
 
 
195
  return;
196
  }
197
  $orderStatus = $order->getData('status');
198
  $orderPaymentStatus = $order->getPayment()->getData('additional_information')['status'];
199
 
200
- $paymentID = $order->getPayment()->getData('additional_information')['id'];
201
- $paymentMethod = $order->getPayment()->getMethodInstance()->getCode();
202
 
203
- $isValidBasicData = $this->checkCancelationBasicData ($paymentID, $paymentMethod);
204
- $isValidaData = $this->checkCancelationData ($orderStatus, $orderPaymentStatus);
205
 
206
- if ($isValidBasicData && $isValidaData) {
207
- $clientId = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_ID);
208
- $clientSecret = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_SECRET);
209
 
210
- $mp = Mage::helper('mercadopago')->getApiInstance($clientId, $clientSecret);
211
- $response = null;
 
 
 
 
212
 
213
- $access_token = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_ACCESS_TOKEN);
 
 
214
 
215
- if ($paymentMethod == 'mercadopago_standard') {
216
- $response = $mp->cancel_payment($paymentID);
217
- } else {
218
- $data = [
219
- "status" => 'cancelled',
220
- ];
221
- $response = $mp->put("/v1/payments/$paymentID?access_token=$access_token", $data);
222
- }
223
 
224
- if ($response['status'] == 200) {
225
- Mage::register('mercadopago_cancellation', true);
226
- $this->_getSession()->addSuccess(__('Cancellation made by Mercado Pago'));
227
- } else {
228
- $this->_getSession()->addError(__('Failed to make the cancellation by Mercado Pago'));
229
- $this->_getSession()->addError($response['status'] . ' ' . $response['response']['message']);
230
- $this->throwCancelationException();
231
- }
 
 
 
 
 
 
 
 
 
 
232
  }
233
  }
234
 
@@ -239,13 +253,13 @@ class MercadoPago_Core_Model_Observer
239
  }
240
 
241
  if (!($paymentMethod == 'mercadopago_standard' || $paymentMethod == 'mercadopago_custom')) {
242
- $this->_getSession()->addError(__('Order payment wasn\'t made by Mercado Pago. The cancellation will be made through Magento'));
243
  return false;
244
  }
245
 
246
  $refundAvailable = Mage::getStoreConfig('payment/mercadopago/refund_available');
247
  if (!$refundAvailable) {
248
- $this->_getSession()->addError(__('Mercado Pago cancellations are disabled. The cancellation will be made through Magento'));
249
  return false;
250
  }
251
 
@@ -273,7 +287,9 @@ class MercadoPago_Core_Model_Observer
273
  }
274
 
275
  protected function throwCancelationException () {
276
- Mage::register('cancel_exception', true);
 
 
277
  }
278
 
279
  protected function _getSession() {
@@ -306,15 +322,17 @@ class MercadoPago_Core_Model_Observer
306
  {
307
  $creditMemo = $observer->getData('creditmemo');
308
  $order = $creditMemo->getOrder();
309
- if ($order->getExternalRequest()) {
 
 
 
310
  return; // si la peticion de crear un credit memo viene de mercado pago, no hace falta mandar el request nuevamente
311
  }
312
 
313
  $orderStatus = $order->getData('status');
314
  $orderPaymentStatus = $order->getPayment()->getData('additional_information')['status'];
315
  $payment = $order->getPayment();
316
- $paymentID = $order->getPayment()->getData('additional_information')['payment_id_detail'];
317
- $paymentMethod = $order->getPayment()->getMethodInstance()->getCode();
318
  $orderStatusHistory = $order->getAllStatusHistory();
319
  $isCreditCardPayment = ($order->getPayment()->getData('additional_information')['installments'] != null ? true : false);
320
 
@@ -326,17 +344,18 @@ class MercadoPago_Core_Model_Observer
326
  }
327
  }
328
  $isValidBasicData = $this->checkRefundBasicData ($paymentMethod, $paymentDate);
329
- $isValidaData = $this->checkRefundData ($isCreditCardPayment,
330
- $orderStatus,
331
- $orderPaymentStatus,
332
- $paymentDate,
333
- $order);
334
-
335
- $isTotalRefund = $payment->getAmountPaid() == $payment->getAmountRefunded();
336
- if ($isValidBasicData && $isValidaData) {
337
- $this->sendRefundRequest($order, $creditMemo, $paymentMethod, $isTotalRefund, $paymentID);
 
 
338
  }
339
-
340
  }
341
 
342
  protected function checkRefundBasicData ($paymentMethod, $paymentDate) {
@@ -348,12 +367,12 @@ class MercadoPago_Core_Model_Observer
348
  }
349
 
350
  if (!($paymentMethod == 'mercadopago_standard' || $paymentMethod == 'mercadopago_custom')) {
351
- $this->_getSession()->addError(__('Order payment wasn\'t made by Mercado Pago. The refund will be made through Magento'));
352
  return false;
353
  }
354
 
355
  if (!$refundAvailable) {
356
- $this->_getSession()->addError(__('Mercado Pago refunds are disabled. The refund will be made through Magento'));
357
  return false;
358
  }
359
 
@@ -405,15 +424,15 @@ class MercadoPago_Core_Model_Observer
405
  return $isValidaData;
406
  }
407
 
408
- protected function sendRefundRequest ($order, $creditMemo, $paymentMethod, $isTotalRefund, $paymentID) {
409
- $clientId = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_ID);
410
- $clientSecret = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_SECRET);
411
 
412
- $mp = Mage::helper('mercadopago')->getApiInstance($clientId, $clientSecret);
413
  $response = null;
414
  $amount = $creditMemo->getGrandTotal();
415
- $access_token = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_ACCESS_TOKEN);
416
  if ($paymentMethod == 'mercadopago_standard') {
 
 
 
 
417
  if ($isTotalRefund) {
418
  $response = $mp->refund_payment($paymentID);
419
  $order->setMercadoPagoRefundType('total');
@@ -427,16 +446,19 @@ class MercadoPago_Core_Model_Observer
427
  "amount" => $amount,
428
  "metadata" => $metadata,
429
  ];
430
- $response = $mp->post("/collections/$paymentID/refunds?access_token=$access_token", $params);
431
  }
432
  } else {
 
 
 
433
  if ($isTotalRefund) {
434
- $response = $mp->post("/v1/payments/$paymentID/refunds?access_token=$access_token");
435
  } else {
436
  $params = [
437
  "amount" => $amount,
438
  ];
439
- $response = $mp->post("/v1/payments/$paymentID/refunds?access_token=$access_token", $params);
440
  }
441
  }
442
 
@@ -453,7 +475,7 @@ class MercadoPago_Core_Model_Observer
453
  protected function throwRefundException () {
454
  Mage::throwException(Mage::helper('mercadopago')->__('Mercado Pago - Refund not made'));
455
  }
456
-
457
  private function daysSince($date)
458
  {
459
  $now = Mage::getModel('core/date')->timestamp(time());
@@ -476,4 +498,29 @@ class MercadoPago_Core_Model_Observer
476
  }
477
  }
478
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  }
66
 
67
  $this->validateClientCredentials();
68
 
69
+ $this->validateRecurringClientCredentials();
70
+
71
  $this->setSponsor();
72
 
73
  $this->availableCheckout();
135
  $user = $mp->get("/users/me");
136
  Mage::helper('mercadopago')->log("API Users response", self::LOG_FILE, $user);
137
 
138
+ if ($user['status'] == 200 && !in_array("test_user", $user['response']['tags']) && strpos($accessToken, 'TEST') === FALSE) {
139
  $sponsors = [
140
  'MLA' => 186172525,
141
  'MLB' => 186175129,
144
  'MLC' => 206959756,
145
  'MLV' => 206960619,
146
  'MPE' => 217178514,
147
+ 'MPU' => 247028139,
148
  ];
149
  $countryCode = $user['response']['site_id'];
150
+
151
  if (isset($sponsors[$countryCode])) {
152
  $sponsorId = $sponsors[$countryCode];
153
  } else {
154
  $sponsorId = "";
155
  }
156
+
157
  Mage::helper('mercadopago')->log("Sponsor id set", self::LOG_FILE, $sponsorId);
158
  }
159
  $this->_saveWebsiteConfig('payment/mercadopago/sponsor_id', $sponsorId);
194
  public function salesOrderBeforeCancel (Varien_Event_Observer $observer) {
195
  $orderID = (int) $observer->getEvent()->getControllerAction()->getRequest()->getParam('order_id');
196
  $order = Mage::getModel('sales/order')->load($orderID);
197
+
198
+ $paymentMethod = $order->getPayment()->getMethodInstance()->getCode();
199
+
200
+ if ($order->getExternalRequest() || !$this->_isMercadoPago($paymentMethod)) {
201
  return;
202
  }
203
  $orderStatus = $order->getData('status');
204
  $orderPaymentStatus = $order->getPayment()->getData('additional_information')['status'];
205
 
206
+ $paymentID = $order->getPayment()->getData('additional_information')['payment_id_detail'];
 
207
 
208
+ if (!($orderPaymentStatus == null || $paymentID == null)) {
 
209
 
210
+ $isValidBasicData = $this->checkCancelationBasicData($paymentID, $paymentMethod);
211
+ if ($isValidBasicData) {
212
+ $isValidaData = $this->checkCancelationData($orderStatus, $orderPaymentStatus);
213
 
214
+ if ($isValidBasicData && $isValidaData) {
215
+ $this->_sendCancellationRequest($paymentMethod, $paymentID);
216
+ }
217
+ }
218
+ }
219
+ }
220
 
221
+ protected function _sendCancellationRequest ($paymentMethod, $paymentID) {
222
+ $clientId = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_ID);
223
+ $clientSecret = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_SECRET);
224
 
225
+ $mp = Mage::helper('mercadopago')->getApiInstance($clientId, $clientSecret);
226
+ $response = null;
 
 
 
 
 
 
227
 
228
+ $access_token = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_ACCESS_TOKEN);
229
+
230
+ if ($paymentMethod == 'mercadopago_standard') {
231
+ $response = $mp->cancel_payment($paymentID);
232
+ } else {
233
+ $data = [
234
+ "status" => 'cancelled',
235
+ ];
236
+ $response = $mp->put("/v1/payments/$paymentID?access_token=$access_token", $data);
237
+ }
238
+
239
+ if ($response['status'] == 200) {
240
+ Mage::register('mercadopago_cancellation', true);
241
+ $this->_getSession()->addSuccess(__('Cancellation made by Mercado Pago'));
242
+ } else {
243
+ $this->_getSession()->addError(__('Failed to make the cancellation by Mercado Pago'));
244
+ $this->_getSession()->addError($response['status'] . ' ' . $response['response']['message']);
245
+ $this->throwCancelationException();
246
  }
247
  }
248
 
253
  }
254
 
255
  if (!($paymentMethod == 'mercadopago_standard' || $paymentMethod == 'mercadopago_custom')) {
256
+ $this->_getSession()->addWarning(__('Order payment wasn\'t made by Mercado Pago. The cancellation will be made through Magento'));
257
  return false;
258
  }
259
 
260
  $refundAvailable = Mage::getStoreConfig('payment/mercadopago/refund_available');
261
  if (!$refundAvailable) {
262
+ $this->_getSession()->addWarning(__('Mercado Pago cancellations are disabled. The cancellation will be made through Magento'));
263
  return false;
264
  }
265
 
287
  }
288
 
289
  protected function throwCancelationException () {
290
+ if (Mage::registry('cancel_exception') != null) {
291
+ Mage::register('cancel_exception', true);
292
+ }
293
  }
294
 
295
  protected function _getSession() {
322
  {
323
  $creditMemo = $observer->getData('creditmemo');
324
  $order = $creditMemo->getOrder();
325
+
326
+ $paymentMethod = $order->getPayment()->getMethodInstance()->getCode();
327
+
328
+ if ($order->getExternalRequest() || !$this->_isMercadoPago($paymentMethod)) {
329
  return; // si la peticion de crear un credit memo viene de mercado pago, no hace falta mandar el request nuevamente
330
  }
331
 
332
  $orderStatus = $order->getData('status');
333
  $orderPaymentStatus = $order->getPayment()->getData('additional_information')['status'];
334
  $payment = $order->getPayment();
335
+
 
336
  $orderStatusHistory = $order->getAllStatusHistory();
337
  $isCreditCardPayment = ($order->getPayment()->getData('additional_information')['installments'] != null ? true : false);
338
 
344
  }
345
  }
346
  $isValidBasicData = $this->checkRefundBasicData ($paymentMethod, $paymentDate);
347
+ if ($isValidBasicData) {
348
+ $isValidaData = $this->checkRefundData ($isCreditCardPayment,
349
+ $orderStatus,
350
+ $orderPaymentStatus,
351
+ $paymentDate,
352
+ $order);
353
+
354
+ $isTotalRefund = $payment->getAmountPaid() == $payment->getAmountRefunded();
355
+ if ($isValidBasicData && $isValidaData) {
356
+ $this->sendRefundRequest($order, $creditMemo, $paymentMethod, $isTotalRefund);
357
+ }
358
  }
 
359
  }
360
 
361
  protected function checkRefundBasicData ($paymentMethod, $paymentDate) {
367
  }
368
 
369
  if (!($paymentMethod == 'mercadopago_standard' || $paymentMethod == 'mercadopago_custom')) {
370
+ $this->_getSession()->addWarning(__('Order payment wasn\'t made by Mercado Pago. The refund will be made through Magento'));
371
  return false;
372
  }
373
 
374
  if (!$refundAvailable) {
375
+ $this->_getSession()->addWarning(__('Mercado Pago refunds are disabled. The refund will be made through Magento'));
376
  return false;
377
  }
378
 
424
  return $isValidaData;
425
  }
426
 
427
+ protected function sendRefundRequest ($order, $creditMemo, $paymentMethod, $isTotalRefund) {
 
 
428
 
 
429
  $response = null;
430
  $amount = $creditMemo->getGrandTotal();
 
431
  if ($paymentMethod == 'mercadopago_standard') {
432
+ $paymentID = $order->getPayment()->getData('additional_information')['id'];
433
+ $clientId = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_ID);
434
+ $clientSecret = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_SECRET);
435
+ $mp = Mage::helper('mercadopago')->getApiInstance($clientId, $clientSecret);
436
  if ($isTotalRefund) {
437
  $response = $mp->refund_payment($paymentID);
438
  $order->setMercadoPagoRefundType('total');
446
  "amount" => $amount,
447
  "metadata" => $metadata,
448
  ];
449
+ $response = $mp->post('/collections/' . $paymentID . '/refunds?access_token=' . $mp->get_access_token(), $params);
450
  }
451
  } else {
452
+ $paymentID = $order->getPayment()->getData('additional_information')['payment_id_detail'];
453
+ $accessToken = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_ACCESS_TOKEN);
454
+ $mp = Mage::helper('mercadopago')->getApiInstance($accessToken);
455
  if ($isTotalRefund) {
456
+ $response = $mp->post("/v1/payments/$paymentID/refunds?access_token=$accessToken", []);
457
  } else {
458
  $params = [
459
  "amount" => $amount,
460
  ];
461
+ $response = $mp->post("/v1/payments/$paymentID/refunds?access_token=$accessToken", $params);
462
  }
463
  }
464
 
475
  protected function throwRefundException () {
476
  Mage::throwException(Mage::helper('mercadopago')->__('Mercado Pago - Refund not made'));
477
  }
478
+
479
  private function daysSince($date)
480
  {
481
  $now = Mage::getModel('core/date')->timestamp(time());
498
  }
499
  }
500
  }
501
+
502
+ public function checkoutSubmitAllAfter (Varien_Event_Observer $observer) {
503
+ $recurringProfiles = $observer->getRecurringProfiles();
504
+ if (isset($recurringProfiles) && count($recurringProfiles) > 0) {
505
+ $checkoutSession = Mage::getSingleton('checkout/session');
506
+ $checkoutSession->setRedirectUrl(Mage::getUrl('mercadopago/recurringPayment'));
507
+ }
508
+ }
509
+
510
+ protected function validateRecurringClientCredentials()
511
+ {
512
+ $clientId = Mage::getStoreConfig('payment/mercadopago_recurring/client_id');
513
+ $clientSecret = Mage::getStoreConfig('payment/mercadopago_recurring/client_secret');
514
+ if (!empty($clientId) && !empty($clientSecret)) {
515
+ if (!Mage::helper('mercadopago')->isValidClientCredentials($clientId, $clientSecret)) {
516
+ Mage::throwException(Mage::helper('mercadopago')->__('Mercado Pago - Recurring Payment Checkout: Invalid client id or client secret'));
517
+ }
518
+ }
519
+ }
520
+
521
+ protected function _isMercadoPago($paymentMethod)
522
+ {
523
+ return ($paymentMethod == 'mercadopago_standard' || $paymentMethod == 'mercadopago_custom');
524
+ }
525
+
526
  }
app/code/community/MercadoPago/Core/Model/Recurring/Payment.php ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MercadoPago_Core_Model_Recurring_Payment
4
+ extends Mage_Payment_Model_Method_Abstract
5
+ implements Mage_Payment_Model_Recurring_Profile_MethodInterface
6
+ {
7
+ protected $_formBlockType = 'mercadopago/recurring_form';
8
+ protected $_infoBlockType = 'mercadopago/recurring_info';
9
+
10
+ protected $_code = 'mercadopago_recurring';
11
+
12
+ protected $_isGateway = true;
13
+ protected $_canOrder = true;
14
+ protected $_canAuthorize = true;
15
+
16
+ const LOG_FILE = 'mercadopago-recurring.log';
17
+
18
+ public function isAvailable($quote = null)
19
+ {
20
+ $parent = parent::isAvailable($quote);
21
+ $clientId = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_ID);
22
+ $clientSecret = Mage::getStoreConfig(MercadoPago_Core_Helper_Data::XML_PATH_CLIENT_SECRET);
23
+ $standard = (!empty($clientId) && !empty($clientSecret));
24
+
25
+ if (!$parent || !$standard) {
26
+ return false;
27
+ }
28
+
29
+ if ($quote != null) {
30
+ $enabled = Mage::getStoreConfig('payment/mercadopago_recurring/active');
31
+ if ($enabled) {
32
+ $items = $quote->getAllItems();
33
+ foreach ($items as $item) {
34
+ if (!$item->getIsNominal()) {
35
+ return false;
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ return Mage::helper('mercadopago')->isValidClientCredentials($clientId, $clientSecret);
42
+
43
+ }
44
+
45
+ public function validateRecurringProfile(Mage_Payment_Model_Recurring_Profile $profile)
46
+ {
47
+ $core = Mage::getModel('mercadopago/core');
48
+ $response = $core->getRecurringPayment($profile->getReferenceId());
49
+ if ($response['status'] == 201 || $response['status'] == 200) {
50
+ return true;
51
+ }
52
+ return false;
53
+ }
54
+
55
+ /**
56
+ * Submit to the gateway
57
+ *
58
+ * @param Mage_Payment_Model_Recurring_Profile $profile
59
+ * @param Mage_Payment_Model_Info $paymentInfo
60
+ */
61
+ public function submitRecurringProfile(Mage_Payment_Model_Recurring_Profile $profile, Mage_Payment_Model_Info $paymentInfo)
62
+ {
63
+ if ($profile == null || $paymentInfo == null) {
64
+ return;
65
+ }
66
+
67
+ $date = new DateTime($profile->getStartDatetime());
68
+ $date->modify('+3 minute');
69
+ $startDate = $date->format("Y-m-d\TH:i:s.mO");
70
+
71
+ $daysModifier = 1;
72
+ $end = null;
73
+ $periodUnit = null;
74
+ $periodFrequency = null;
75
+ switch ($profile->getPeriodUnit()) {
76
+ case Mage_Payment_Model_Recurring_Profile::PERIOD_UNIT_DAY:
77
+ $periodUnit = 'days';
78
+ $periodFrequency = $profile->getPeriodFrequency();
79
+ break;
80
+ case Mage_Payment_Model_Recurring_Profile::PERIOD_UNIT_WEEK:
81
+ $periodUnit = 'days';
82
+ $periodFrequency = $profile->getPeriodFrequency() * 7;
83
+ $daysModifier = 7;
84
+ break;
85
+ case Mage_Payment_Model_Recurring_Profile::PERIOD_UNIT_SEMI_MONTH:
86
+ $periodUnit = 'days';
87
+ $periodFrequency = $profile->getPeriodFrequency() * 14;
88
+ $daysModifier = 14;
89
+ break;
90
+ case Mage_Payment_Model_Recurring_Profile::PERIOD_UNIT_MONTH:
91
+ $periodUnit = 'months';
92
+ $periodFrequency = $profile->getPeriodFrequency();
93
+ $end = $date->modify('+' . $profile->getPeriodMaxCycles() . ' ' . $periodUnit);
94
+ break;
95
+ case Mage_Payment_Model_Recurring_Profile::PERIOD_UNIT_YEAR:
96
+ $periodUnit = 'days';
97
+ $periodFrequency = $profile->getPeriodFrequency() * 365;
98
+ $daysModifier = 365;
99
+ break;
100
+ }
101
+
102
+ if (!isset($end)) {
103
+ $end = $date->modify('+' . $profile->getPeriodMaxCycles() * $daysModifier . ' ' . $periodUnit);
104
+ }
105
+ $end->modify('-3 minute');
106
+
107
+ $endDate = $end->format("Y-m-d\TH:i:s.mO");
108
+
109
+ $backUrl = Mage::getStoreConfig('payment/mercadopago_recurring/back_url');
110
+
111
+ $preapprovalData = array(
112
+ "payer_email" => $profile->getOrderInfo()['customer_email'],
113
+ "back_url" => $backUrl,
114
+ "reason" => $profile->getScheduleDescription(),
115
+ "external_reference" => $profile->getId(),
116
+ "auto_recurring" => array(
117
+ "frequency" => $periodFrequency,
118
+ "frequency_type" => $periodUnit,
119
+ "transaction_amount" => $profile->getBillingAmount() + $profile->getShippingAmount(),
120
+ "currency_id" => $profile->getCurrencyCode(),
121
+ "start_date" => $startDate,
122
+ "end_date" => $endDate
123
+ )
124
+ );
125
+
126
+ $this->_sendPreapprovalPaymentRequest($profile, $preapprovalData);
127
+ }
128
+
129
+ protected function _sendPreapprovalPaymentRequest($profile, $preapproval_data) {
130
+ $clientId = Mage::getStoreConfig('payment/mercadopago_recurring/client_id');
131
+ $clientSecret = Mage::getStoreConfig('payment/mercadopago_recurring/client_secret');
132
+
133
+ $mp = Mage::helper('mercadopago')->getApiInstance($clientId, $clientSecret);
134
+ $sandbox = Mage::getStoreConfig('payment/mercadopago_recurring/sandbox_mode');
135
+
136
+ if ($sandbox) {
137
+ $mp->sandbox_mode(true);
138
+ }
139
+
140
+ $response = $mp->create_preapproval_payment($preapproval_data);
141
+ if ($response['status'] == 201 || $response['status'] == 200) {
142
+ if ($sandbox) {
143
+ $redirectUrl = $response['response']['sandbox_init_point'];
144
+ } else {
145
+ $redirectUrl = $response['response']['init_point'];
146
+ }
147
+ Mage::getSingleton('customer/session')->setInitPoint($redirectUrl);
148
+ $profile->setData('reference_id', $response['response']['id']);
149
+ $profile->setData('schedule_description', $redirectUrl);
150
+ $profile->setData('external_reference', $response['response']['id']);
151
+ } else {
152
+ Mage::throwException(Mage::helper('mercadopago')->__('Mercado Pago - Recurring Profile not created')
153
+ . "\n" . $response['response']['message']);
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Fetch details
159
+ *
160
+ * @param string $referenceId
161
+ * @param Varien_Object $result
162
+ */
163
+ public function getRecurringProfileDetails($referenceId, Varien_Object $result)
164
+ {
165
+ $core = Mage::getModel('mercadopago/core');
166
+ $response = $core->getRecurringPayment($referenceId);
167
+ $value = $response ['response']['status'];
168
+ switch ($value) {
169
+ case 'authorized':
170
+ $result->setIsProfileActive(true);
171
+ break;
172
+ case 'pending':
173
+ $result->setIsProfilePending(true);
174
+ break;
175
+ case 'cancelled':
176
+ $result->setIsProfileCanceled(true);
177
+ break;
178
+ case 'paused':
179
+ $result->setIsProfileSuspended(true);
180
+ break;
181
+ case 'expired':
182
+ $result->setIsProfileExpired(true);
183
+ break;
184
+ }
185
+
186
+ $profile = Mage::registry('current_recurring_profile');
187
+ $productId = $profile->getOrderItemInfo()['product_id'];
188
+ $product = Mage::getModel('catalog/product')->load($productId);
189
+
190
+ $actualAmount = $profile->getBillingAmount() + $profile->getShippingAmount();
191
+ $newAmount = $response ['response']['auto_recurring']['transaction_amount'];
192
+
193
+ if ($actualAmount != $newAmount) {
194
+ $billingAmount = $newAmount - $profile->getShippingAmount();
195
+ $profile->setBillingAmount($billingAmount);
196