Version Notes
version 1.0.7
Download this release
Release Info
Developer | Tales Galvao |
Extension | vindi-subscriptions-and-recurring-payments |
Version | 1.0.7 |
Comparing to | |
See all releases |
Version 1.0.7
- app/code/community/Vindi/Subscription/Block/Config/Information.php +50 -0
- app/code/community/Vindi/Subscription/Block/Form/BankSlip.php +14 -0
- app/code/community/Vindi/Subscription/Block/Form/Cc.php +125 -0
- app/code/community/Vindi/Subscription/Helper/Api.php +694 -0
- app/code/community/Vindi/Subscription/Helper/Data.php +36 -0
- app/code/community/Vindi/Subscription/Helper/WebhookHandler.php +471 -0
- app/code/community/Vindi/Subscription/Model/BankSlip.php +139 -0
- app/code/community/Vindi/Subscription/Model/Config/Installments.php +18 -0
- app/code/community/Vindi/Subscription/Model/Config/Shippingmethod.php +65 -0
- app/code/community/Vindi/Subscription/Model/CreditCard.php +272 -0
- app/code/community/Vindi/Subscription/Model/Observer.php +168 -0
- app/code/community/Vindi/Subscription/Model/Product/Attribute/Plan.php +30 -0
- app/code/community/Vindi/Subscription/Model/Product/Type.php +6 -0
- app/code/community/Vindi/Subscription/Trait/PaymentMethod.php +306 -0
- app/code/community/Vindi/Subscription/controllers/WebhookController.php +41 -0
- app/code/community/Vindi/Subscription/etc/adminhtml.xml +22 -0
- app/code/community/Vindi/Subscription/etc/config.xml +141 -0
- app/code/community/Vindi/Subscription/etc/system.xml +178 -0
- app/code/community/Vindi/Subscription/sql/vindi_subscription_setup/install-1.0.0.php +118 -0
- app/code/community/Vindi/Subscription/sql/vindi_subscription_setup/upgrade-1.0.0-1.0.1.php +53 -0
- app/code/community/Vindi/Subscription/sql/vindi_subscription_setup/upgrade-1.0.1-1.0.2.php +29 -0
- app/code/community/Vindi/Subscription/sql/vindi_subscription_setup/upgrade-1.0.4-1.0.5.php +68 -0
- app/design/adminhtml/base/default/layout/vindi_subscription.xml +15 -0
- app/design/adminhtml/base/default/template/vindi_subscription/payment/form/bankslip.phtml +6 -0
- app/design/adminhtml/base/default/template/vindi_subscription/payment/form/cc.phtml +166 -0
- app/design/frontend/base/default/layout/vindi_subscription.xml +78 -0
- app/design/frontend/base/default/template/vindi_subscription/payment/form/bankslip.phtml +6 -0
- app/design/frontend/base/default/template/vindi_subscription/payment/form/cc.phtml +163 -0
- app/etc/modules/Vindi_Subscription.xml +14 -0
- package.xml +18 -0
- skin/frontend/base/default/vindi_subscription/css/vindi_subscription.css +56 -0
- skin/frontend/base/default/vindi_subscription/js/vindi_subscription.js +99 -0
app/code/community/Vindi/Subscription/Block/Config/Information.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Block_Config_Information extends Mage_Core_Block_Template implements Varien_Data_Form_Element_Renderer_Interface
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param \Varien_Data_Form_Element_Abstract $element
|
7 |
+
*
|
8 |
+
* @return string
|
9 |
+
*/
|
10 |
+
public function render(Varien_Data_Form_Element_Abstract $element)
|
11 |
+
{
|
12 |
+
$helper = Mage::helper('vindi_subscription');
|
13 |
+
|
14 |
+
if(! $helper->getKey()) {
|
15 |
+
return '';
|
16 |
+
}
|
17 |
+
|
18 |
+
$html = '<tr><td colspan="4" class="label"><h3>Informações sobre a conta Vindi</h3></td></tr>';
|
19 |
+
|
20 |
+
/** @var Vindi_Subscription_Helper_API $api */
|
21 |
+
$api = Mage::helper('vindi_subscription/api');
|
22 |
+
|
23 |
+
$merchant = $api->getMerchant();
|
24 |
+
|
25 |
+
$html .= '<tr><td class="label">Conexão</td>';
|
26 |
+
|
27 |
+
if (! $merchant) {
|
28 |
+
$html .= '<td class=" value error-msg">Falha na Conexão!<br />Verifique sua conta e tente novamente!</td></tr>';
|
29 |
+
return $html;
|
30 |
+
}
|
31 |
+
$html .= '<td class="value success-msg">Conectado com Sucesso!</td></tr>';
|
32 |
+
|
33 |
+
$html .= '<tr><td class="label">Conta</td><td class="value">' . $merchant['name'] . '</td></tr>';
|
34 |
+
|
35 |
+
$status = $api->isMerchantStatusTrial() ? 'Trial' : 'Ativo';
|
36 |
+
$html .= '<tr><td class="label">Status</td><td class="value">'. $status .'</td></tr>';
|
37 |
+
|
38 |
+
$html .= '<tr><td colspan="4" class="label"><h3>Configuração dos Eventos da Vindi</h3></td></tr>';
|
39 |
+
|
40 |
+
$html .= '<tr>
|
41 |
+
<td class="label">URL dos Webhooks</td>
|
42 |
+
<td class="value">
|
43 |
+
<input type="text" value="' . $helper->getWebhookURL() .'" style="width:100%" readonly onclick="this.select();" />
|
44 |
+
<p class="note" style="width:100%"><span>Copie esse link e utilize-o para configurar os eventos nos Webhooks da Vindi.</span></p>
|
45 |
+
</td>
|
46 |
+
</tr>';
|
47 |
+
|
48 |
+
return $html;
|
49 |
+
}
|
50 |
+
}
|
app/code/community/Vindi/Subscription/Block/Form/BankSlip.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Block_Form_BankSlip extends Mage_Payment_Block_Form
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* Initialize block
|
7 |
+
*/
|
8 |
+
public function _construct()
|
9 |
+
{
|
10 |
+
parent::_construct();
|
11 |
+
$this->setTemplate('vindi_subscription/payment/form/bankslip.phtml');
|
12 |
+
}
|
13 |
+
|
14 |
+
}
|
app/code/community/Vindi/Subscription/Block/Form/Cc.php
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Block_Form_Cc extends Mage_Payment_Block_Form_Cc
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* Initialize block
|
7 |
+
*/
|
8 |
+
public function _construct()
|
9 |
+
{
|
10 |
+
parent::_construct();
|
11 |
+
$this->setTemplate('vindi_subscription/payment/form/cc.phtml');
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @return bool
|
16 |
+
*/
|
17 |
+
private function isAdmin()
|
18 |
+
{
|
19 |
+
return Mage::app()->getStore()->isAdmin();
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @return \Mage_Customer_Model_Customer
|
24 |
+
*/
|
25 |
+
private function getCustomer()
|
26 |
+
{
|
27 |
+
if ($this->isAdmin()) {
|
28 |
+
return Mage::getSingleton('adminhtml/session_quote')->getCustomer();
|
29 |
+
}
|
30 |
+
|
31 |
+
return Mage::getSingleton('customer/session')->getCustomer();
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @return \Mage_Sales_Model_Quote
|
36 |
+
*/
|
37 |
+
private function getQuote()
|
38 |
+
{
|
39 |
+
if ($this->isAdmin()) {
|
40 |
+
return Mage::getSingleton('adminhtml/session_quote')->getQuote();
|
41 |
+
}
|
42 |
+
|
43 |
+
return Mage::getSingleton('checkout/session')->getQuote();
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Retrieve available credit card types
|
48 |
+
*
|
49 |
+
* @return array
|
50 |
+
*/
|
51 |
+
public function getCcAvailableTypes()
|
52 |
+
{
|
53 |
+
return $this->api()->getCreditCardTypes();
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @return bool
|
58 |
+
*/
|
59 |
+
public function getSavedCc()
|
60 |
+
{
|
61 |
+
$customer = $this->getCustomer();
|
62 |
+
|
63 |
+
if (! $userCode = $customer->getVindiUserCode()) {
|
64 |
+
return false;
|
65 |
+
}
|
66 |
+
|
67 |
+
return $this->api()->getCustomerPaymentProfile($userCode);
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @return bool|string
|
72 |
+
*/
|
73 |
+
public function getInstallments()
|
74 |
+
{
|
75 |
+
$maxInstallmentsNumber = Mage::getStoreConfig('payment/vindi_creditcard/max_installments_number');
|
76 |
+
$minInstallmentsValue = Mage::getStoreConfig('payment/vindi_creditcard/min_installment_value');
|
77 |
+
// $quote = Mage::getSingleton('checkout/session')->getQuote();
|
78 |
+
$quote = $this->getQuote();
|
79 |
+
|
80 |
+
$installments = false;
|
81 |
+
|
82 |
+
if ($this->isSingleQuote($quote) && $maxInstallmentsNumber > 1) {
|
83 |
+
|
84 |
+
$total = $quote->getGrandTotal();
|
85 |
+
|
86 |
+
$installments = '<option value="">' . Mage::helper('catalog')->__('-- Please Select --') . '</option>';
|
87 |
+
for ($i = 1; $i <= $maxInstallmentsNumber; $i++) {
|
88 |
+
$value = ceil($total / $i * 100) / 100;
|
89 |
+
|
90 |
+
if ($value >= $minInstallmentsValue) {
|
91 |
+
$price = Mage::helper('core')->currency($value, true, false);
|
92 |
+
$installments .= '<option value="' . $i . '">' . sprintf('%dx de %s', $i, $price) . '</option>';
|
93 |
+
} else {
|
94 |
+
break;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
return $installments;
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* @param Mage_Sales_Model_Quote $quote
|
104 |
+
*
|
105 |
+
* @return bool
|
106 |
+
*/
|
107 |
+
protected function isSingleQuote($quote)
|
108 |
+
{
|
109 |
+
foreach ($quote->getAllVisibleItems() as $item) {
|
110 |
+
if (($product = $item->getProduct()) && ($product->getTypeId() === 'subscription')) {
|
111 |
+
return false;
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
return true;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* @return Vindi_Subscription_Helper_API
|
120 |
+
*/
|
121 |
+
private function api()
|
122 |
+
{
|
123 |
+
return Mage::helper('vindi_subscription/api');
|
124 |
+
}
|
125 |
+
}
|
app/code/community/Vindi/Subscription/Helper/Api.php
ADDED
@@ -0,0 +1,694 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Helper_API extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* @const string API base path.
|
8 |
+
*/
|
9 |
+
const BASE_PATH = 'https://app.vindi.com.br/api/v1/';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @var string
|
13 |
+
*/
|
14 |
+
public $lastError = '';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
private $version;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
private $key;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var bool
|
28 |
+
*/
|
29 |
+
private $acceptBankSlip;
|
30 |
+
|
31 |
+
public function __construct()
|
32 |
+
{
|
33 |
+
$this->version = (string) Mage::getConfig()->getModuleConfig('Vindi_Subscription')->version;
|
34 |
+
$this->key = Mage::helper('vindi_subscription')->getKey();
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @param string $message
|
39 |
+
* @param int|null $level
|
40 |
+
*/
|
41 |
+
private function log($message, $level = null)
|
42 |
+
{
|
43 |
+
Mage::log($message, $level, 'vindi_api.log');
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @return \Zend_Cache_Core
|
48 |
+
*/
|
49 |
+
private function cache()
|
50 |
+
{
|
51 |
+
return Mage::app()->getCache();
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Build HTTP Query.
|
56 |
+
*
|
57 |
+
* @param array $data
|
58 |
+
*
|
59 |
+
* @return string
|
60 |
+
*/
|
61 |
+
private function buildBody($data)
|
62 |
+
{
|
63 |
+
return json_encode($data);
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @param array $error
|
68 |
+
* @param $endpoint
|
69 |
+
*
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
private function getErrorMessage($error, $endpoint)
|
73 |
+
{
|
74 |
+
return "Erro em $endpoint: {$error['id']}: {$error['parameter']} - {$error['message']}";
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @param array $response
|
79 |
+
* @param $endpoint
|
80 |
+
*
|
81 |
+
* @return bool
|
82 |
+
*/
|
83 |
+
private function checkResponse($response, $endpoint)
|
84 |
+
{
|
85 |
+
if (isset($response['errors']) && ! empty($response['errors'])) {
|
86 |
+
foreach ($response['errors'] as $error) {
|
87 |
+
$message = $this->getErrorMessage($error, $endpoint);
|
88 |
+
|
89 |
+
Mage::getSingleton('core/session')->addError($message);
|
90 |
+
|
91 |
+
$this->lastError = $message;
|
92 |
+
}
|
93 |
+
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
|
97 |
+
$this->lastError = '';
|
98 |
+
|
99 |
+
return true;
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Perform request to API.
|
104 |
+
*
|
105 |
+
* @param string $endpoint
|
106 |
+
* @param string $method
|
107 |
+
* @param array $data
|
108 |
+
* @param null $dataToLog
|
109 |
+
*
|
110 |
+
* @return array|bool|mixed
|
111 |
+
*/
|
112 |
+
private function request($endpoint, $method = 'POST', $data = [], $dataToLog = null)
|
113 |
+
{
|
114 |
+
if (! $this->key) {
|
115 |
+
return false;
|
116 |
+
}
|
117 |
+
|
118 |
+
$url = static::BASE_PATH . $endpoint;
|
119 |
+
$body = $this->buildBody($data);
|
120 |
+
|
121 |
+
$requestId = rand();
|
122 |
+
|
123 |
+
$dataToLog = null !== $dataToLog ? $this->buildBody($dataToLog) : $body;
|
124 |
+
|
125 |
+
$this->log(sprintf("[Request #%s]: Novo Request para a API.\n%s %s\n%s", $requestId, $method, $url,
|
126 |
+
$dataToLog));
|
127 |
+
|
128 |
+
$ch = curl_init();
|
129 |
+
|
130 |
+
curl_setopt_array($ch, [
|
131 |
+
CURLOPT_HTTPHEADER => [
|
132 |
+
'Content-Type: application/json',
|
133 |
+
],
|
134 |
+
CURLOPT_TIMEOUT => 60,
|
135 |
+
CURLOPT_SSL_VERIFYPEER => true,
|
136 |
+
CURLOPT_HEADER => true,
|
137 |
+
CURLOPT_RETURNTRANSFER => true,
|
138 |
+
CURLOPT_USERAGENT => 'Vindi-Magento/' . $this->version,
|
139 |
+
CURLOPT_SSLVERSION => 'CURL_SSLVERSION_TLSv1_2',
|
140 |
+
CURLOPT_USERPWD => $this->key . ':',
|
141 |
+
CURLOPT_URL => $url,
|
142 |
+
CURLOPT_CUSTOMREQUEST => $method,
|
143 |
+
CURLOPT_POSTFIELDS => $body,
|
144 |
+
]);
|
145 |
+
|
146 |
+
$response = curl_exec($ch);
|
147 |
+
|
148 |
+
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
149 |
+
$body = substr($response, curl_getinfo($ch, CURLINFO_HEADER_SIZE));
|
150 |
+
|
151 |
+
if (curl_errno($ch) || $response === false) {
|
152 |
+
$this->log(sprintf("[Request #%s]: Erro ao fazer request!\n%s", $requestId, print_r($response, true)));
|
153 |
+
|
154 |
+
return false;
|
155 |
+
}
|
156 |
+
|
157 |
+
curl_close($ch);
|
158 |
+
|
159 |
+
$status = "HTTP Status: $statusCode";
|
160 |
+
$this->log(sprintf("[Request #%s]: Nova Resposta da API.\n%s\n%s", $requestId, $status, $body));
|
161 |
+
|
162 |
+
$responseBody = json_decode($body, true);
|
163 |
+
|
164 |
+
if (! $responseBody) {
|
165 |
+
$this->log(sprintf('[Request #%s]: Erro ao recuperar corpo do request! %s', $requestId,
|
166 |
+
print_r($body, true)));
|
167 |
+
|
168 |
+
return false;
|
169 |
+
}
|
170 |
+
|
171 |
+
if (! $this->checkResponse($responseBody, $endpoint)) {
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
|
175 |
+
return $responseBody;
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Make an API request to create a Customer.
|
180 |
+
*
|
181 |
+
* @param array $body (name, email, code)
|
182 |
+
*
|
183 |
+
* @return array|bool|mixed
|
184 |
+
*/
|
185 |
+
public function createCustomer($body)
|
186 |
+
{
|
187 |
+
if ($response = $this->request('customers', 'POST', $body)) {
|
188 |
+
return $response['customer']['id'];
|
189 |
+
}
|
190 |
+
|
191 |
+
return false;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Make an API request to retrieve an existing Customer.
|
196 |
+
*
|
197 |
+
* @param string $code
|
198 |
+
*
|
199 |
+
* @return array|bool|mixed
|
200 |
+
*/
|
201 |
+
public function findCustomerByCode($code)
|
202 |
+
{
|
203 |
+
$customerId = $this->cache()->load("vindi_customer_by_code_{$code}");
|
204 |
+
|
205 |
+
if ($customerId === false) {
|
206 |
+
$response = $this->request("customers/search?code={$code}", 'GET');
|
207 |
+
|
208 |
+
if ($response && (1 === count($response['customers'])) && isset($response['customers'][0]['id'])) {
|
209 |
+
$customerId = $response['customers'][0]['id'];
|
210 |
+
|
211 |
+
$this->cache()->save(serialize($customerId), "vindi_customer_by_code_{$code}", ['vindi_cache'],
|
212 |
+
5 * 60); // 5 minutes
|
213 |
+
}
|
214 |
+
} else {
|
215 |
+
$customerId = unserialize($customerId);
|
216 |
+
}
|
217 |
+
|
218 |
+
return $customerId;
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Make an API request to retrieve an existing Customer or to create one if not found.
|
223 |
+
*
|
224 |
+
* @param array $body (name, email, code)
|
225 |
+
*
|
226 |
+
* @return array|bool|mixed
|
227 |
+
*/
|
228 |
+
public function findOrCreateCustomer($body)
|
229 |
+
{
|
230 |
+
$customerId = $this->findCustomerByCode($body['code']);
|
231 |
+
// TODO update information
|
232 |
+
|
233 |
+
if (false === $customerId) {
|
234 |
+
return $this->createCustomer($body);
|
235 |
+
}
|
236 |
+
|
237 |
+
return $customerId;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Make an API request to create a Payment Profile to a Customer.
|
242 |
+
*
|
243 |
+
* @param $body (holder_name, card_expiration, card_number, card_cvv, customer_id)
|
244 |
+
*
|
245 |
+
* @return array|bool|mixed
|
246 |
+
*/
|
247 |
+
public function createCustomerPaymentProfile($body)
|
248 |
+
{
|
249 |
+
// Protect credit card number.
|
250 |
+
$dataToLog = $body;
|
251 |
+
$dataToLog['card_number'] = '**** *' . substr($dataToLog['card_number'], -3);
|
252 |
+
$dataToLog['card_cvv'] = '***';
|
253 |
+
|
254 |
+
$customerId = $body['customer_id'];
|
255 |
+
$this->cache()->remove("vindi_payment_profile_{$customerId}");
|
256 |
+
|
257 |
+
return $this->request('payment_profiles', 'POST', $body, $dataToLog);
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* @param $userCode
|
262 |
+
*
|
263 |
+
* @return bool
|
264 |
+
*/
|
265 |
+
public function getCustomerPaymentProfile($userCode)
|
266 |
+
{
|
267 |
+
$customerId = $this->findCustomerByCode($userCode);
|
268 |
+
|
269 |
+
if (false === $customerId) {
|
270 |
+
return false;
|
271 |
+
}
|
272 |
+
|
273 |
+
$paymentProfile = $this->cache()->load("vindi_payment_profile_{$customerId}");
|
274 |
+
|
275 |
+
if ($paymentProfile === false) {
|
276 |
+
$endpoint = 'payment_profiles?query=customer_id%3D' . $customerId
|
277 |
+
. '%20status%3Dactive%20type%3DPaymentProfile%3A%3ACreditCard';
|
278 |
+
|
279 |
+
$response = $this->request($endpoint, 'GET');
|
280 |
+
|
281 |
+
if ($response && $response['payment_profiles'] && count($response['payment_profiles'])) {
|
282 |
+
$paymentProfile = $response['payment_profiles'][0];
|
283 |
+
|
284 |
+
$this->cache()->save(serialize($paymentProfile), "vindi_payment_profile_{$customerId}", ['vindi_cache'],
|
285 |
+
5 * 60); // 5 minutes
|
286 |
+
}
|
287 |
+
} else {
|
288 |
+
$paymentProfile = unserialize($paymentProfile);
|
289 |
+
}
|
290 |
+
|
291 |
+
return $paymentProfile;
|
292 |
+
}
|
293 |
+
|
294 |
+
/**
|
295 |
+
* Make an API request to create a Subscription.
|
296 |
+
*
|
297 |
+
* @param $body (plan_id, customer_id, payment_method_code, product_items[{product_id}])
|
298 |
+
*
|
299 |
+
* @return array
|
300 |
+
*/
|
301 |
+
public function createSubscription($body)
|
302 |
+
{
|
303 |
+
if (($response = $this->request('subscriptions', 'POST', $body)) && isset($response['subscription']['id'])) {
|
304 |
+
|
305 |
+
$subscription = $response['subscription'];
|
306 |
+
$subscription['bill'] = $response['bill'];
|
307 |
+
|
308 |
+
return $subscription;
|
309 |
+
}
|
310 |
+
|
311 |
+
return false;
|
312 |
+
}
|
313 |
+
|
314 |
+
/**
|
315 |
+
* Make an API request to retrieve Payment Methods.
|
316 |
+
*
|
317 |
+
* @return array|bool
|
318 |
+
*/
|
319 |
+
public function getPaymentMethods()
|
320 |
+
{
|
321 |
+
$paymentMethods = $this->cache()->load('vindi_payment_methods');
|
322 |
+
|
323 |
+
if ($paymentMethods === false) {
|
324 |
+
|
325 |
+
$paymentMethods = [
|
326 |
+
'credit_card' => [],
|
327 |
+
'bank_slip' => false,
|
328 |
+
];
|
329 |
+
|
330 |
+
$response = $this->request('payment_methods', 'GET');
|
331 |
+
|
332 |
+
if (false === $response) {
|
333 |
+
return $this->acceptBankSlip = false;
|
334 |
+
}
|
335 |
+
|
336 |
+
foreach ($response['payment_methods'] as $method) {
|
337 |
+
if ('active' !== $method['status']) {
|
338 |
+
continue;
|
339 |
+
}
|
340 |
+
|
341 |
+
if ('PaymentMethod::CreditCard' === $method['type']) {
|
342 |
+
$paymentMethods['credit_card'] = array_merge($paymentMethods['credit_card'],
|
343 |
+
$method['payment_companies']);
|
344 |
+
} else {
|
345 |
+
if ('PaymentMethod::BankSlip' === $method['type']) {
|
346 |
+
$paymentMethods['bank_slip'] = true;
|
347 |
+
}
|
348 |
+
}
|
349 |
+
}
|
350 |
+
|
351 |
+
$this->cache()->save(serialize($paymentMethods), 'vindi_payment_methods', ['vindi_cache'],
|
352 |
+
12 * 60 * 60); // 12 hours
|
353 |
+
} else {
|
354 |
+
$paymentMethods = unserialize($paymentMethods);
|
355 |
+
}
|
356 |
+
|
357 |
+
$this->acceptBankSlip = $paymentMethods['bank_slip'];
|
358 |
+
|
359 |
+
return $paymentMethods;
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Retrieve Credit Card Types from Payment Methods.
|
364 |
+
*
|
365 |
+
* @return array
|
366 |
+
*/
|
367 |
+
public function getCreditCardTypes()
|
368 |
+
{
|
369 |
+
$methods = $this->getPaymentMethods();
|
370 |
+
$types = [];
|
371 |
+
|
372 |
+
foreach ($methods['credit_card'] as $type) {
|
373 |
+
$types[$type['code']] = $type['name'];
|
374 |
+
}
|
375 |
+
|
376 |
+
return $types;
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* @return bool|null
|
381 |
+
*/
|
382 |
+
public function acceptBankSlip()
|
383 |
+
{
|
384 |
+
if (null === $this->acceptBankSlip) {
|
385 |
+
$this->getPaymentMethods();
|
386 |
+
}
|
387 |
+
|
388 |
+
return $this->acceptBankSlip;
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* @param array $body
|
393 |
+
*
|
394 |
+
* @return int|bool
|
395 |
+
*/
|
396 |
+
public function createBill($body)
|
397 |
+
{
|
398 |
+
if ($response = $this->request('bills', 'POST', $body)) {
|
399 |
+
return $response['bill']['id'];
|
400 |
+
}
|
401 |
+
|
402 |
+
return false;
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* @param $billId
|
407 |
+
*
|
408 |
+
* @return array|bool|mixed
|
409 |
+
*/
|
410 |
+
public function approveBill($billId)
|
411 |
+
{
|
412 |
+
$response = $this->request("bills/{$billId}", 'GET');
|
413 |
+
|
414 |
+
if (false === $response || ! isset($response['bill'])) {
|
415 |
+
return false;
|
416 |
+
}
|
417 |
+
|
418 |
+
$bill = $response['bill'];
|
419 |
+
|
420 |
+
if ('review' !== $bill['status']) {
|
421 |
+
return true;
|
422 |
+
}
|
423 |
+
|
424 |
+
return $this->request("bills/{$billId}/approve", 'POST');
|
425 |
+
}
|
426 |
+
|
427 |
+
/**
|
428 |
+
* @param $billId
|
429 |
+
*
|
430 |
+
* @return string
|
431 |
+
*/
|
432 |
+
public function getBankSlipDownload($billId)
|
433 |
+
{
|
434 |
+
$response = $this->request("bills/{$billId}", 'GET');
|
435 |
+
|
436 |
+
if (false === $response) {
|
437 |
+
return false;
|
438 |
+
}
|
439 |
+
|
440 |
+
return $response['bill']['charges'][0]['print_url'];
|
441 |
+
}
|
442 |
+
|
443 |
+
/**
|
444 |
+
* @return array
|
445 |
+
*/
|
446 |
+
public function getProducts()
|
447 |
+
{
|
448 |
+
$list = [];
|
449 |
+
$response = $this->request('products?query=status:active', 'GET');
|
450 |
+
|
451 |
+
if ($products = $response['products']) {
|
452 |
+
foreach ($products as $product) {
|
453 |
+
$list[$product['id']] = "{$product['name']} ({$product['pricing_schema']['short_format']})";
|
454 |
+
}
|
455 |
+
}
|
456 |
+
|
457 |
+
return $list;
|
458 |
+
}
|
459 |
+
|
460 |
+
/**
|
461 |
+
* @param int $id
|
462 |
+
*
|
463 |
+
* @return array
|
464 |
+
*/
|
465 |
+
public function getPlanItems($id)
|
466 |
+
{
|
467 |
+
$list = [];
|
468 |
+
$response = $this->request("plans/{$id}", 'GET');
|
469 |
+
|
470 |
+
if ($plan = $response['plan']) {
|
471 |
+
foreach ($plan['plan_items'] as $item) {
|
472 |
+
if (isset($item['product'])) {
|
473 |
+
$list[] = $item['product']['id'];
|
474 |
+
}
|
475 |
+
}
|
476 |
+
}
|
477 |
+
|
478 |
+
return $list;
|
479 |
+
}
|
480 |
+
|
481 |
+
/**
|
482 |
+
* @param Mage_Sales_Model_Order $order
|
483 |
+
*
|
484 |
+
* @return array
|
485 |
+
*/
|
486 |
+
public function buildPlanItemsForSubscription($order)
|
487 |
+
{
|
488 |
+
$list = [];
|
489 |
+
$orderItems = $order->getItemsCollection();
|
490 |
+
$orderSubtotal = $order->getQuote()->getSubtotal();
|
491 |
+
$orderDiscount = $order->getDiscountAmount() * -1;
|
492 |
+
|
493 |
+
$discount = null;
|
494 |
+
if(!empty($orderDiscount)){
|
495 |
+
$discountPercentage = $orderDiscount * 100 / $orderSubtotal;
|
496 |
+
$discountPercentage = number_format(floor($discountPercentage*100)/100, 2);
|
497 |
+
|
498 |
+
$discount = [[
|
499 |
+
'discount_type' => 'percentage',
|
500 |
+
'percentage' => $discountPercentage
|
501 |
+
]];
|
502 |
+
}
|
503 |
+
|
504 |
+
foreach($orderItems as $item)
|
505 |
+
{
|
506 |
+
$product = Mage::getModel('catalog/product')->load($item->getProductId());
|
507 |
+
if ($product->getTypeID() !== 'subscription') {
|
508 |
+
Mage::throwException("O produto {$item->getName()} não é uma assinatura.");
|
509 |
+
|
510 |
+
return false;
|
511 |
+
}
|
512 |
+
|
513 |
+
$productVindiId = $this->findOrCreateProduct(array( 'sku' => $item->getSku(), 'name' => $item->getName()));
|
514 |
+
|
515 |
+
for ($i=1; $i <= $item->getQtyOrdered() ; $i++) {
|
516 |
+
$list[] = [
|
517 |
+
'product_id' => $productVindiId,
|
518 |
+
'pricing_schema' => ['price' => $item->getPrice()],
|
519 |
+
'discounts' => $discount,
|
520 |
+
];
|
521 |
+
}
|
522 |
+
}
|
523 |
+
|
524 |
+
// Create product for shipping
|
525 |
+
$productVindiId = $this->findOrCreateProduct(array( 'sku' => 'frete', 'name' => 'Frete'));
|
526 |
+
|
527 |
+
$list[] = [
|
528 |
+
'product_id' => $productVindiId,
|
529 |
+
'pricing_schema' => ['price' => $order->getShippingAmount()],
|
530 |
+
];
|
531 |
+
|
532 |
+
return $list;
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* @return array
|
537 |
+
*/
|
538 |
+
public function getPlans()
|
539 |
+
{
|
540 |
+
$list = $this->cache()->load('vindi_plans');
|
541 |
+
|
542 |
+
if (($list === false) || ! count($list = unserialize($list))) {
|
543 |
+
|
544 |
+
$list = [];
|
545 |
+
$response = $this->request('plans?query=status:active', 'GET');
|
546 |
+
|
547 |
+
if ($plans = $response['plans']) {
|
548 |
+
foreach ($plans as $plan) {
|
549 |
+
$list[$plan['id']] = $plan['name'];
|
550 |
+
}
|
551 |
+
}
|
552 |
+
$this->cache()->save(serialize($list), 'vindi_plans', ['vindi_cache'], 10 * 60); // 10 minutes
|
553 |
+
}
|
554 |
+
|
555 |
+
return $list;
|
556 |
+
}
|
557 |
+
|
558 |
+
/**
|
559 |
+
* Make an API request to create a Product.
|
560 |
+
*
|
561 |
+
* @param array $body (name, code, status, pricing_schema (price))
|
562 |
+
*
|
563 |
+
* @return array|bool|mixed
|
564 |
+
*/
|
565 |
+
public function createProduct($body)
|
566 |
+
{
|
567 |
+
if ($response = $this->request('products', 'POST', $body)) {
|
568 |
+
return $response['product']['id'];
|
569 |
+
}
|
570 |
+
|
571 |
+
return false;
|
572 |
+
}
|
573 |
+
|
574 |
+
/**
|
575 |
+
* Make an API request to retrieve an existing Product.
|
576 |
+
*
|
577 |
+
* @param string $code
|
578 |
+
*
|
579 |
+
* @return array|bool|mixed
|
580 |
+
*/
|
581 |
+
public function findProductByCode($code)
|
582 |
+
{
|
583 |
+
$response = $this->request("products?query=code%3D{$code}", 'GET');
|
584 |
+
|
585 |
+
if ($response && (1 === count($response['products'])) && isset($response['products'][0]['id'])) {
|
586 |
+
return $response['products'][0]['id'];
|
587 |
+
}
|
588 |
+
|
589 |
+
return false;
|
590 |
+
}
|
591 |
+
|
592 |
+
/**
|
593 |
+
* Make an API request to retrieve the Unique Payment Product or to create it if not found.
|
594 |
+
*
|
595 |
+
* @return array|bool|mixed
|
596 |
+
*/
|
597 |
+
public function findOrCreateUniquePaymentProduct()
|
598 |
+
{
|
599 |
+
$productId = $this->findProductByCode('mag-pagtounico');
|
600 |
+
if (false === $productId) {
|
601 |
+
return $this->createProduct([
|
602 |
+
'name' => 'Pagamento Único (não remover)',
|
603 |
+
'code' => 'mag-pagtounico',
|
604 |
+
'status' => 'active',
|
605 |
+
'pricing_schema' => [
|
606 |
+
'price' => 0,
|
607 |
+
],
|
608 |
+
]);
|
609 |
+
}
|
610 |
+
return $productId;
|
611 |
+
}
|
612 |
+
|
613 |
+
/**
|
614 |
+
* Make an API request to retrieve a Product or to create it if not found.
|
615 |
+
* @param array $product
|
616 |
+
*
|
617 |
+
* @return array|bool|mixed
|
618 |
+
*/
|
619 |
+
public function findOrCreateProduct($product)
|
620 |
+
{
|
621 |
+
//
|
622 |
+
$productId = $this->findProductByCode($product['sku']);
|
623 |
+
|
624 |
+
if (false === $productId) {
|
625 |
+
return $this->createProduct([
|
626 |
+
'name' => $product['name'],
|
627 |
+
'code' => $product['sku'],
|
628 |
+
'status' => 'active',
|
629 |
+
'pricing_schema' => [
|
630 |
+
'price' => 0,
|
631 |
+
],
|
632 |
+
]);
|
633 |
+
}
|
634 |
+
|
635 |
+
return $productId;
|
636 |
+
}
|
637 |
+
|
638 |
+
/**
|
639 |
+
* Make an API request to retrieve information about the Merchant.
|
640 |
+
*
|
641 |
+
* @return array|bool|mixed
|
642 |
+
*/
|
643 |
+
public function getMerchant()
|
644 |
+
{
|
645 |
+
$merchant = $this->cache()->load('vindi_merchant');
|
646 |
+
|
647 |
+
if ($merchant === false) {
|
648 |
+
|
649 |
+
$response = $this->request('merchant', 'GET');
|
650 |
+
|
651 |
+
if (! $response || ! isset($response['merchant'])) {
|
652 |
+
return false;
|
653 |
+
}
|
654 |
+
|
655 |
+
$merchant = $response['merchant'];
|
656 |
+
|
657 |
+
$this->cache()->save(serialize($merchant), 'vindi_merchant', ['vindi_cache'], 1 * 60 * 60); // 1 hour
|
658 |
+
} else {
|
659 |
+
$merchant = unserialize($merchant);
|
660 |
+
}
|
661 |
+
|
662 |
+
return $merchant;
|
663 |
+
}
|
664 |
+
|
665 |
+
/**
|
666 |
+
* Check to see if Merchant Status is Trial.
|
667 |
+
*
|
668 |
+
* @return boolean
|
669 |
+
*/
|
670 |
+
public function isMerchantStatusTrial()
|
671 |
+
{
|
672 |
+
if ($merchant = $this->getMerchant()) {
|
673 |
+
return 'trial' === $merchant['status'];
|
674 |
+
}
|
675 |
+
|
676 |
+
return false;
|
677 |
+
}
|
678 |
+
|
679 |
+
/**
|
680 |
+
* @param $billId
|
681 |
+
*
|
682 |
+
* @return array|bool
|
683 |
+
*/
|
684 |
+
public function getBill($billId)
|
685 |
+
{
|
686 |
+
$response = $this->request("bills/{$billId}", 'GET');
|
687 |
+
|
688 |
+
if (! $response || ! isset($response['bill'])) {
|
689 |
+
return false;
|
690 |
+
}
|
691 |
+
|
692 |
+
return $response['bill'];
|
693 |
+
}
|
694 |
+
}
|
app/code/community/Vindi/Subscription/Helper/Data.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Helper_Data extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* Return Vindi API Key from config or false otherwhise.
|
7 |
+
*
|
8 |
+
* @return string|bool
|
9 |
+
*/
|
10 |
+
public function getKey()
|
11 |
+
{
|
12 |
+
return Mage::getStoreConfig('vindi_subscription/general/api_key') ?: false;
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Generate an URL for webhooks to use.
|
17 |
+
*
|
18 |
+
* @return string
|
19 |
+
*/
|
20 |
+
public function getWebhookURL()
|
21 |
+
{
|
22 |
+
$key = $this->getHashKey();
|
23 |
+
|
24 |
+
return Mage::getUrl('vindi_subscription/webhook', compact('key'));
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Generate an uniform salted hash for using as webhook's security validation.
|
29 |
+
*
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
public function getHashKey()
|
33 |
+
{
|
34 |
+
return Mage::helper('core')->getHash('vindi-magento');
|
35 |
+
}
|
36 |
+
}
|
app/code/community/Vindi/Subscription/Helper/WebhookHandler.php
ADDED
@@ -0,0 +1,471 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Helper_WebhookHandler extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param string $message
|
7 |
+
* @param int|null $level
|
8 |
+
*/
|
9 |
+
public function log($message, $level = null)
|
10 |
+
{
|
11 |
+
Mage::log($message, $level, 'vindi_webhooks.log');
|
12 |
+
|
13 |
+
switch ($level) {
|
14 |
+
case 4:
|
15 |
+
http_response_code(422);
|
16 |
+
exit($message);
|
17 |
+
break;
|
18 |
+
case 5:
|
19 |
+
echo $message;
|
20 |
+
return false;
|
21 |
+
break;
|
22 |
+
default:
|
23 |
+
return true;
|
24 |
+
break;
|
25 |
+
}
|
26 |
+
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Handle incoming webhook.
|
31 |
+
*
|
32 |
+
* @param string $body
|
33 |
+
*
|
34 |
+
* @return bool
|
35 |
+
*/
|
36 |
+
public function handle($body)
|
37 |
+
{
|
38 |
+
try {
|
39 |
+
$jsonBody = json_decode($body, true);
|
40 |
+
|
41 |
+
if (! $jsonBody || ! isset($jsonBody['event'])) {
|
42 |
+
Mage::throwException('Evento do Webhook não encontrado!');
|
43 |
+
}
|
44 |
+
|
45 |
+
$type = $jsonBody['event']['type'];
|
46 |
+
$data = $jsonBody['event']['data'];
|
47 |
+
} catch (Exception $e) {
|
48 |
+
$this->log(sprintf('Falha ao interpretar JSON do webhook: %s', $e->getMessage()), 5);
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
|
52 |
+
switch ($type) {
|
53 |
+
// the webhook is being called before Order is actually placed.
|
54 |
+
// I'm sorry for this, not going to use queues for now, so the solution is to use sleep().
|
55 |
+
|
56 |
+
case 'test':
|
57 |
+
$this->log('Evento de teste do webhook.');
|
58 |
+
exit('1');
|
59 |
+
case 'bill_created':
|
60 |
+
return $this->billCreated($data);
|
61 |
+
case 'bill_paid':
|
62 |
+
return $this->billPaid($data);
|
63 |
+
case 'charge_rejected':
|
64 |
+
return $this->chargeRejected($data);
|
65 |
+
default:
|
66 |
+
$this->log(sprintf('Evento do webhook ignorado pelo plugin: "%s".', $type), 5);
|
67 |
+
exit('0');
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Handle 'bill_created' event.
|
73 |
+
* The bill can be related to a subscription or a single payment.
|
74 |
+
*
|
75 |
+
* @param array $data
|
76 |
+
*
|
77 |
+
* @return bool
|
78 |
+
*/
|
79 |
+
public function billCreated($data)
|
80 |
+
{
|
81 |
+
if (! ($bill = $data['bill'])) {
|
82 |
+
$this->log('Erro ao interpretar webhook "bill_created".', 5);
|
83 |
+
|
84 |
+
return false;
|
85 |
+
}
|
86 |
+
|
87 |
+
if (! isset($bill['subscription']) || is_null($bill['subscription'])) {
|
88 |
+
$this->log(sprintf('Ignorando o evento "bill_created" para venda avulsa.'), 5);
|
89 |
+
|
90 |
+
return false;
|
91 |
+
}
|
92 |
+
|
93 |
+
$period = intval($bill['period']['cycle']);
|
94 |
+
|
95 |
+
if (isset($bill['period']) && ($period === 1)) {
|
96 |
+
$this->log(sprintf('Ignorando o evento "bill_created" para o primeiro ciclo.'), 5);
|
97 |
+
|
98 |
+
return false;
|
99 |
+
}
|
100 |
+
|
101 |
+
if (($order = $this->getOrder($data))) {
|
102 |
+
$this->log(sprintf('Já existe o pedido %s para o evento "bill_created".', $order->getId()), 5);
|
103 |
+
|
104 |
+
return false;
|
105 |
+
}
|
106 |
+
|
107 |
+
$subscriptionId = $bill['subscription']['id'];
|
108 |
+
$lastPeriodOrder = $this->getOrderForPeriod($subscriptionId, $period - 1);
|
109 |
+
|
110 |
+
if (! $lastPeriodOrder || ! $lastPeriodOrder->getId()) {
|
111 |
+
$this->log('Pedido anterior não encontrado. Ignorando evento.', 4);
|
112 |
+
|
113 |
+
return false;
|
114 |
+
}
|
115 |
+
|
116 |
+
$vindiData = [
|
117 |
+
'bill' => [
|
118 |
+
'id' => $data['bill']['id'],
|
119 |
+
'amout' => $data['bill']['amount']
|
120 |
+
],
|
121 |
+
'products' => [],
|
122 |
+
'shipping' => [],
|
123 |
+
];
|
124 |
+
foreach ($data['bill']['bill_items'] as $billItem)
|
125 |
+
{
|
126 |
+
if($billItem['product']['code'] == 'frete')
|
127 |
+
{
|
128 |
+
$vindiData['shipping'] = $billItem;
|
129 |
+
}else{
|
130 |
+
$vindiData['products'][] = $billItem;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
$order = $this->createOrder($lastPeriodOrder, $vindiData);
|
135 |
+
|
136 |
+
if (! $order) {
|
137 |
+
$this->log('Impossível gerar novo pedido!', 4);
|
138 |
+
|
139 |
+
return false;
|
140 |
+
}
|
141 |
+
|
142 |
+
$this->log(sprintf('Novo pedido gerado: %s.', $order->getId()));
|
143 |
+
|
144 |
+
$order->setVindiSubscriptionId($subscriptionId);
|
145 |
+
$order->setVindiSubscriptionPeriod($period);
|
146 |
+
$order->save();
|
147 |
+
|
148 |
+
if(Mage::getStoreConfig('vindi_subscription/general/bankslip_link_in_order_comment'))
|
149 |
+
{
|
150 |
+
foreach ($data['bill']['charges'] as $charge)
|
151 |
+
{
|
152 |
+
if ($charge['payment_method']['type'] == 'PaymentMethod::BankSlip')
|
153 |
+
{
|
154 |
+
$order->addStatusHistoryComment(sprintf(
|
155 |
+
'<a target="_blank" href="%s">Clique aqui</a> para visualizar o boleto.',
|
156 |
+
$charge['print_url']
|
157 |
+
))
|
158 |
+
->setIsVisibleOnFront(true);
|
159 |
+
$order->save();
|
160 |
+
}
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
return true;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Handle 'bill_paid' event.
|
169 |
+
* The bill can be related to a subscription or a single payment.
|
170 |
+
*
|
171 |
+
* @param array $data
|
172 |
+
*
|
173 |
+
* @return bool
|
174 |
+
*/
|
175 |
+
public function billPaid($data)
|
176 |
+
{
|
177 |
+
if (! ($order = $this->getOrder($data))) {
|
178 |
+
$this->log(sprintf('Ainda não existe um pedido para ciclo %s da assinatura: %d.',
|
179 |
+
$data['bill']['period']['cycle'],
|
180 |
+
$data['bill']['subscription']['id']),
|
181 |
+
4
|
182 |
+
);
|
183 |
+
|
184 |
+
return false;
|
185 |
+
}
|
186 |
+
|
187 |
+
return $this->createInvoice($order);
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* @param array $data
|
192 |
+
*
|
193 |
+
* @return bool
|
194 |
+
* @throws \Exception
|
195 |
+
*/
|
196 |
+
public function chargeRejected($data)
|
197 |
+
{
|
198 |
+
$charge = $data['charge'];
|
199 |
+
|
200 |
+
if (! ($order = $this->getOrderFromBill($charge['bill']['id']))) {
|
201 |
+
$this->log('Pedido não encontrado.', 4);
|
202 |
+
|
203 |
+
return false;
|
204 |
+
}
|
205 |
+
|
206 |
+
$gatewayMessage = $charge['last_transaction']['gateway_message'];
|
207 |
+
$isLastAttempt = is_null($charge['next_attempt']);
|
208 |
+
|
209 |
+
if ($isLastAttempt) {
|
210 |
+
$order->setState(Mage_Sales_Model_Order::STATE_CANCELED, true, sprintf(
|
211 |
+
'Todas as tentativas de pagamento foram rejeitadas. Motivo: "%s".',
|
212 |
+
$gatewayMessage
|
213 |
+
), true);
|
214 |
+
$this->log(sprintf(
|
215 |
+
'Todas as tentativas de pagamento do pedido %s foram rejeitadas. Motivo: "%s".',
|
216 |
+
$order->getId(),
|
217 |
+
$gatewayMessage
|
218 |
+
));
|
219 |
+
} else {
|
220 |
+
$order->addStatusHistoryComment(sprintf(
|
221 |
+
'Tentativa de Pagamento rejeitada. Motivo: "%s". Uma nova tentativa será feita.',
|
222 |
+
$gatewayMessage
|
223 |
+
));
|
224 |
+
$this->log(sprintf(
|
225 |
+
'Tentativa de pagamento do pedido %s foi rejeitada. Motivo: "%s". Uma nova tentativa será feita.',
|
226 |
+
$order->getId(),
|
227 |
+
$gatewayMessage
|
228 |
+
));
|
229 |
+
}
|
230 |
+
|
231 |
+
$order->save();
|
232 |
+
|
233 |
+
return true;
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* @param Mage_Sales_Model_Order $order
|
238 |
+
*
|
239 |
+
* @return bool
|
240 |
+
*/
|
241 |
+
public function createInvoice($order)
|
242 |
+
{
|
243 |
+
if (! $order->getId()) {
|
244 |
+
return false;
|
245 |
+
}
|
246 |
+
|
247 |
+
$this->log(sprintf('Gerando fatura para o pedido: %s.', $order->getId()));
|
248 |
+
|
249 |
+
$order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true,
|
250 |
+
'O pagamento foi confirmado e o pedido está sendo processado.', true);
|
251 |
+
|
252 |
+
if (! $order->canInvoice()) {
|
253 |
+
$this->log(sprintf('Impossível gerar fatura para o pedido %s.', $order->getId()), 4);
|
254 |
+
|
255 |
+
// TODO define how to handle this
|
256 |
+
|
257 |
+
return false;
|
258 |
+
}
|
259 |
+
$invoice = $order->prepareInvoice();
|
260 |
+
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
|
261 |
+
$invoice->register();
|
262 |
+
Mage::getModel('core/resource_transaction')->addObject($invoice)->addObject($invoice->getOrder())->save();
|
263 |
+
$invoice->sendEmail(true);
|
264 |
+
$this->log('Fatura gerada com sucesso.');
|
265 |
+
|
266 |
+
return true;
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* @param array $data
|
271 |
+
*
|
272 |
+
* @return Mage_Sales_Model_Order|bool
|
273 |
+
*/
|
274 |
+
private function getOrder($data)
|
275 |
+
{
|
276 |
+
if (! isset($data['bill'])) {
|
277 |
+
return false;
|
278 |
+
}
|
279 |
+
|
280 |
+
if (isset($data['bill']['subscription']) && ($subscription = $data['bill']['subscription'])
|
281 |
+
&& ($subscriptionId = filter_var($subscription['id'], FILTER_SANITIZE_NUMBER_INT))
|
282 |
+
) {
|
283 |
+
$order = $this->getOrderForPeriod($subscriptionId, $data['bill']['period']['cycle']);
|
284 |
+
|
285 |
+
if (! $order || ! $order->getId()) {
|
286 |
+
$this->log(sprintf('Nenhum pedido encontrado para a assinatura: %d.', $subscriptionId));
|
287 |
+
|
288 |
+
return false;
|
289 |
+
}
|
290 |
+
|
291 |
+
return $order;
|
292 |
+
} else {
|
293 |
+
$order = $this->getSingleOrder($data['bill']['id']);
|
294 |
+
|
295 |
+
if (! $order || ! $order->getId()) {
|
296 |
+
$this->log(sprintf('Nenhum pedido encontrado para a fatura: %d.', $data['bill']['id']));
|
297 |
+
|
298 |
+
return false;
|
299 |
+
}
|
300 |
+
|
301 |
+
return $order;
|
302 |
+
}
|
303 |
+
}
|
304 |
+
|
305 |
+
/**
|
306 |
+
* @param int $billId
|
307 |
+
*
|
308 |
+
* @return bool|\Mage_Sales_Model_Order
|
309 |
+
*/
|
310 |
+
private function getOrderFromBill($billId)
|
311 |
+
{
|
312 |
+
/** @var Vindi_Subscription_Helper_API $api */
|
313 |
+
$api = Mage::helper('vindi_subscription/api');
|
314 |
+
|
315 |
+
if (! $bill = $api->getBill($billId)) {
|
316 |
+
return false;
|
317 |
+
}
|
318 |
+
|
319 |
+
return $this->getOrder(compact('bill'));
|
320 |
+
}
|
321 |
+
|
322 |
+
/**
|
323 |
+
* @param int $subscriptionId
|
324 |
+
* @param int $subscriptionPeriod
|
325 |
+
*
|
326 |
+
* @return Mage_Sales_Model_Order
|
327 |
+
*/
|
328 |
+
private function getOrderForPeriod($subscriptionId, $subscriptionPeriod)
|
329 |
+
{
|
330 |
+
return Mage::getModel('sales/order')->getCollection()
|
331 |
+
->addAttributeToSelect('*')
|
332 |
+
->addFieldToFilter('vindi_subscription_id', $subscriptionId)
|
333 |
+
->addFieldToFilter('vindi_subscription_period', $subscriptionPeriod)
|
334 |
+
->getFirstItem();
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* @param int $billId
|
339 |
+
*
|
340 |
+
* @return Mage_Sales_Model_Order
|
341 |
+
*/
|
342 |
+
private function getSingleOrder($billId)
|
343 |
+
{
|
344 |
+
return Mage::getModel('sales/order')->getCollection()
|
345 |
+
->addAttributeToSelect('*')
|
346 |
+
->addFieldToFilter('vindi_bill_id', $billId)
|
347 |
+
->getFirstItem();
|
348 |
+
}
|
349 |
+
|
350 |
+
/**
|
351 |
+
* Create a new order from an old one using reorder functionality.
|
352 |
+
*
|
353 |
+
* @param Mage_Sales_Model_Order $oldOrder
|
354 |
+
*
|
355 |
+
* @return Mage_Sales_Model_Order;
|
356 |
+
*/
|
357 |
+
private function createOrder($oldOrder, $vindiData)
|
358 |
+
{
|
359 |
+
$oldOrder->setReordered(true);
|
360 |
+
|
361 |
+
$model = Mage::getSingleton('adminhtml/sales_order_create');
|
362 |
+
|
363 |
+
/** @var Mage_Adminhtml_Model_Sales_Order_Create $order */
|
364 |
+
$order = $model->initFromOrder($oldOrder);
|
365 |
+
|
366 |
+
$quote = $order->getQuote();
|
367 |
+
|
368 |
+
// get shipping method
|
369 |
+
$shippingMethod = $oldOrder->getShippingMethod();
|
370 |
+
$activedShippingMethods = Mage::getSingleton('vindi_subscription/config_shippingmethod')->getActivedShippingMethodsValues();
|
371 |
+
|
372 |
+
// verify if current shipping method is active
|
373 |
+
if(!in_array($shippingMethod, $activedShippingMethods)){
|
374 |
+
$oldShippingMethod = $shippingMethod;
|
375 |
+
$shippingMethod = Mage::getStoreConfig('vindi_subscription/general/default_shipping_method');
|
376 |
+
$this->log(sprintf("Erro ao utilizar o método de envio %s alterado para o método padrão %s.",
|
377 |
+
$oldShippingMethod,
|
378 |
+
$shippingMethod
|
379 |
+
));
|
380 |
+
unset($oldShippingMethod);
|
381 |
+
}
|
382 |
+
|
383 |
+
// quote shipping method
|
384 |
+
$quote->getShippingAddress()
|
385 |
+
->setShippingMethod($shippingMethod)
|
386 |
+
->setCollectShippingRates(true)
|
387 |
+
->collectShippingRates()
|
388 |
+
->collectTotals();
|
389 |
+
|
390 |
+
if(isset($vindiData['shipping']['pricing_schema']['price']) && !empty(isset($vindiData['shipping']['pricing_schema']['price'])))
|
391 |
+
{
|
392 |
+
// set shipping price
|
393 |
+
$billShippingPrice = $vindiData['shipping']['pricing_schema']['price'];
|
394 |
+
|
395 |
+
$quote->setPrice($billShippingPrice)
|
396 |
+
->setCost($billShippingPrice);
|
397 |
+
|
398 |
+
$address = $quote->getShippingAddress();
|
399 |
+
$address->setShippingAmount($billShippingPrice);
|
400 |
+
$address->setBaseShippingAmount($billShippingPrice);
|
401 |
+
|
402 |
+
$rates = $address->collectShippingRates()
|
403 |
+
->getGroupedAllShippingRates();
|
404 |
+
foreach ($rates as $carrier) {
|
405 |
+
foreach ($carrier as $rate) {
|
406 |
+
$rate->setPrice($billShippingPrice);
|
407 |
+
$rate->save();
|
408 |
+
}
|
409 |
+
}
|
410 |
+
$address->save();
|
411 |
+
|
412 |
+
}
|
413 |
+
|
414 |
+
$quote->save();
|
415 |
+
|
416 |
+
foreach ($vindiData['products'] as $item) {
|
417 |
+
$magentoProduct = Mage::getModel('catalog/product')->loadByAttribute('vindi_product_id', $item['product']['id']);
|
418 |
+
if(!$magentoProduct)
|
419 |
+
{
|
420 |
+
$this->log(sprintf('O produto com ID Vindi #%s não existe no Magento.', $item['product']['id']), 5);
|
421 |
+
return false;
|
422 |
+
}
|
423 |
+
|
424 |
+
if(number_format($magentoProduct->getPrice(), 2) !== number_format($item['pricing_schema']['price'], 2)){
|
425 |
+
$this->log(sprintf("Divergencia de valores na fatura #%s: produto %s: ID Magento #%s , ID Vindi #%s: Valor Magento R$ %s , Valor Vindi R$ %s",
|
426 |
+
$vindiData['bill']['id'],
|
427 |
+
$magentoProduct->getName(),
|
428 |
+
$magentoProduct->getId(),
|
429 |
+
$item['product']['id'],
|
430 |
+
$magentoProduct->getPrice(),
|
431 |
+
$item['pricing_schema']['price'])
|
432 |
+
);
|
433 |
+
|
434 |
+
$quote->getItemByProduct($magentoProduct)
|
435 |
+
// ->setPrice($item['pricing_schema']['price'])
|
436 |
+
// ->setCost($item['pricing_schema']['price'])
|
437 |
+
->setOriginalCustomPrice($item['pricing_schema']['price'])
|
438 |
+
->setCustomPrice($item['pricing_schema']['price'])
|
439 |
+
->save();
|
440 |
+
|
441 |
+
}
|
442 |
+
}
|
443 |
+
|
444 |
+
$quote->setTotalsCollectedFlag(false)
|
445 |
+
->collectTotals()
|
446 |
+
->save();
|
447 |
+
|
448 |
+
$session = Mage::getSingleton('core/session');
|
449 |
+
$session->setData('vindi_is_reorder', true);
|
450 |
+
|
451 |
+
try {
|
452 |
+
$order = $order->createOrder();
|
453 |
+
} catch (Exception $e) {
|
454 |
+
$this->log("Erro ao criar pedido!");
|
455 |
+
|
456 |
+
if($e->getMessage()){
|
457 |
+
$this->log($e->getMessage(), 5);
|
458 |
+
}else{
|
459 |
+
$messages = $order->getSession()->getMessages(true);
|
460 |
+
foreach($messages->getItems() as $message)
|
461 |
+
{
|
462 |
+
$this->log($message->getText(), 5);
|
463 |
+
}
|
464 |
+
}
|
465 |
+
|
466 |
+
return false;
|
467 |
+
}
|
468 |
+
|
469 |
+
return $order;
|
470 |
+
}
|
471 |
+
}
|
app/code/community/Vindi/Subscription/Model/BankSlip.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Model_BankSlip extends Mage_Payment_Model_Method_Abstract
|
4 |
+
{
|
5 |
+
use Vindi_Subscription_Trait_PaymentMethod;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @var string
|
9 |
+
*/
|
10 |
+
protected $_code = 'vindi_bankslip';
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @var bool
|
14 |
+
*/
|
15 |
+
protected $_isGateway = true;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var bool
|
19 |
+
*/
|
20 |
+
protected $_canAuthorize = true;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var bool
|
24 |
+
*/
|
25 |
+
protected $_canCapture = true;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var bool
|
29 |
+
*/
|
30 |
+
protected $_canCapturePartial = false;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @var bool
|
34 |
+
*/
|
35 |
+
protected $_canRefund = false;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @var bool
|
39 |
+
*/
|
40 |
+
protected $_canVoid = false;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @var bool
|
44 |
+
*/
|
45 |
+
protected $_canUseInternal = true;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @var bool
|
49 |
+
*/
|
50 |
+
protected $_canUseCheckout = true;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @var bool
|
54 |
+
*/
|
55 |
+
protected $_canUseForMultishipping = false;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @var bool
|
59 |
+
*/
|
60 |
+
protected $_isInitializeNeeded = true;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @var bool
|
64 |
+
*/
|
65 |
+
protected $_canSaveCc = false;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @var string
|
69 |
+
*/
|
70 |
+
protected $_formBlockType = 'vindi_subscription/form_bankSlip';
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Assign data to info model instance
|
74 |
+
*
|
75 |
+
* @param mixed $data
|
76 |
+
*
|
77 |
+
* @return Mage_Payment_Model_Method_Abstract
|
78 |
+
*/
|
79 |
+
public function assignData($data)
|
80 |
+
{
|
81 |
+
return $this;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @param string $paymentAction
|
86 |
+
* @param object $stateObject
|
87 |
+
*
|
88 |
+
* @return bool|Mage_Payment_Model_Method_Abstract
|
89 |
+
*/
|
90 |
+
protected function processNewOrder($paymentAction, $stateObject)
|
91 |
+
{
|
92 |
+
$payment = $this->getInfoInstance();
|
93 |
+
$order = $payment->getOrder();
|
94 |
+
|
95 |
+
$customer = Mage::getModel('customer/customer');
|
96 |
+
|
97 |
+
$customerId = $this->createCustomer($order, $customer);
|
98 |
+
|
99 |
+
if ($this->isSingleOrder($order)) {
|
100 |
+
$result = $this->processSinglePayment($payment, $order, $customerId);
|
101 |
+
} else {
|
102 |
+
$result = $this->processSubscription($payment, $order, $customerId);
|
103 |
+
}
|
104 |
+
|
105 |
+
if (! $result) {
|
106 |
+
return false;
|
107 |
+
}
|
108 |
+
|
109 |
+
$stateObject->setStatus(Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW)
|
110 |
+
->setState(Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW);
|
111 |
+
|
112 |
+
return $this;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Check whether payment method can be used
|
117 |
+
*
|
118 |
+
* @param Mage_Sales_Model_Quote|null $quote
|
119 |
+
*
|
120 |
+
* @return bool
|
121 |
+
*/
|
122 |
+
public function isAvailable($quote = null)
|
123 |
+
{
|
124 |
+
/** @var Vindi_Subscription_Helper_API $api */
|
125 |
+
$api = Mage::helper('vindi_subscription/api');
|
126 |
+
|
127 |
+
return Mage::getStoreConfig('payment/vindi_bankslip/active')
|
128 |
+
&& $api->acceptBankSlip();
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* @return string
|
133 |
+
*/
|
134 |
+
protected function getPaymentMethodCode()
|
135 |
+
{
|
136 |
+
// TODO fix it to proper method code
|
137 |
+
return 'bank_slip';
|
138 |
+
}
|
139 |
+
}
|
app/code/community/Vindi/Subscription/Model/Config/Installments.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Model_Config_Installments
|
4 |
+
{
|
5 |
+
public function toOptionArray()
|
6 |
+
{
|
7 |
+
$list = [];
|
8 |
+
|
9 |
+
foreach (range(1, 12) as $i) {
|
10 |
+
$list[] = [
|
11 |
+
'value' => $i,
|
12 |
+
'label' => "{$i}x",
|
13 |
+
];
|
14 |
+
}
|
15 |
+
|
16 |
+
return $list;
|
17 |
+
}
|
18 |
+
}
|
app/code/community/Vindi/Subscription/Model/Config/Shippingmethod.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Model_Config_Shippingmethod
|
4 |
+
{
|
5 |
+
public function toOptionArray()
|
6 |
+
{
|
7 |
+
return $this->getActivedShippingMethods();
|
8 |
+
}
|
9 |
+
|
10 |
+
|
11 |
+
public function getActivedShippingMethods()
|
12 |
+
{
|
13 |
+
$methods = Mage::getSingleton('shipping/config')->getActiveCarriers();
|
14 |
+
|
15 |
+
$options = array();
|
16 |
+
$options[] = array('value' => '', 'label' => 'Nenhum');
|
17 |
+
|
18 |
+
foreach($methods as $_ccode => $_carrier)
|
19 |
+
{
|
20 |
+
$_methodOptions = array();
|
21 |
+
if($_methods = $_carrier->getAllowedMethods())
|
22 |
+
{
|
23 |
+
foreach($_methods as $_mcode => $_method)
|
24 |
+
{
|
25 |
+
$_code = $_ccode . '_' . $_mcode;
|
26 |
+
$_methodOptions[] = array('value' => $_code, 'label' => $_method);
|
27 |
+
}
|
28 |
+
|
29 |
+
if(!$_title = Mage::getStoreConfig("carriers/$_ccode/title"))
|
30 |
+
$_title = $_ccode;
|
31 |
+
|
32 |
+
$options[] = array('value' => $_methodOptions[0]['value'], 'label' => $_title);
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
return $options;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function getActivedShippingMethodsValues()
|
40 |
+
{
|
41 |
+
$methods = Mage::getSingleton('shipping/config')->getActiveCarriers();
|
42 |
+
|
43 |
+
$options = array();
|
44 |
+
|
45 |
+
foreach($methods as $_ccode => $_carrier)
|
46 |
+
{
|
47 |
+
$_methodOptions = array();
|
48 |
+
if($_methods = $_carrier->getAllowedMethods())
|
49 |
+
{
|
50 |
+
foreach($_methods as $_mcode => $_method)
|
51 |
+
{
|
52 |
+
$_code = $_ccode . '_' . $_mcode;
|
53 |
+
$_methodOptions[] = array('value' => $_code, 'label' => $_method);
|
54 |
+
}
|
55 |
+
|
56 |
+
if(!$_title = Mage::getStoreConfig("carriers/$_ccode/title"))
|
57 |
+
$_title = $_ccode;
|
58 |
+
|
59 |
+
$options[] = $_methodOptions[0]['value'];
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
return $options;
|
64 |
+
}
|
65 |
+
}
|
app/code/community/Vindi/Subscription/Model/CreditCard.php
ADDED
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Model_CreditCard extends Mage_Payment_Model_Method_Cc
|
4 |
+
{
|
5 |
+
use Vindi_Subscription_Trait_PaymentMethod;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @var string
|
9 |
+
*/
|
10 |
+
protected $_code = 'vindi_creditcard';
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @var bool
|
14 |
+
*/
|
15 |
+
protected $_isGateway = true;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var bool
|
19 |
+
*/
|
20 |
+
protected $_canAuthorize = true;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var bool
|
24 |
+
*/
|
25 |
+
protected $_canCapture = true;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var bool
|
29 |
+
*/
|
30 |
+
protected $_canCapturePartial = false;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @var bool
|
34 |
+
*/
|
35 |
+
protected $_canRefund = false;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @var bool
|
39 |
+
*/
|
40 |
+
protected $_canVoid = false;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @var bool
|
44 |
+
*/
|
45 |
+
protected $_canUseInternal = true;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @var bool
|
49 |
+
*/
|
50 |
+
protected $_canUseCheckout = true;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @var bool
|
54 |
+
*/
|
55 |
+
protected $_canUseForMultishipping = false;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @var bool
|
59 |
+
*/
|
60 |
+
protected $_isInitializeNeeded = true;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @var bool
|
64 |
+
*/
|
65 |
+
protected $_canSaveCc = false;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @var string
|
69 |
+
*/
|
70 |
+
protected $_formBlockType = 'vindi_subscription/form_cc';
|
71 |
+
|
72 |
+
/**
|
73 |
+
* @var string
|
74 |
+
*/
|
75 |
+
protected $_infoBlockType = 'payment/info_cc';
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Assign data to info model instance
|
79 |
+
*
|
80 |
+
* @param mixed $data
|
81 |
+
*
|
82 |
+
* @return Mage_Payment_Model_Method_Abstract
|
83 |
+
*/
|
84 |
+
public function assignData($data)
|
85 |
+
{
|
86 |
+
if (! ($data instanceof Varien_Object)) {
|
87 |
+
$data = new Varien_Object($data);
|
88 |
+
}
|
89 |
+
$info = $this->getInfoInstance();
|
90 |
+
$quote = $info->getQuote();
|
91 |
+
|
92 |
+
if ($this->isSingleOrder($quote)) {
|
93 |
+
$info->setAdditionalInformation('installments', $data->getCcInstallments());
|
94 |
+
}
|
95 |
+
|
96 |
+
if ($data->getCcChoice() === 'saved') {
|
97 |
+
$info->setAdditionalInformation('PaymentMethod', $this->_code)
|
98 |
+
->setAdditionalInformation('use_saved_cc', true);
|
99 |
+
|
100 |
+
return $this;
|
101 |
+
}
|
102 |
+
|
103 |
+
$info->setCcType($data->getCcType())
|
104 |
+
->setCcOwner($data->getCcOwner())
|
105 |
+
->setCcLast4(substr($data->getCcNumber(), -4))
|
106 |
+
->setCcNumber($data->getCcNumber())
|
107 |
+
->setCcCid($data->getCcCid())
|
108 |
+
->setCcExpMonth($data->getCcExpMonth())
|
109 |
+
->setCcExpYear($data->getCcExpYear())
|
110 |
+
->setCcSsIssue($data->getCcSsIssue())
|
111 |
+
->setCcSsStartMonth($data->getCcSsStartMonth())
|
112 |
+
->setCcSsStartYear($data->getCcSsStartYear())
|
113 |
+
->setAdditionalInformation('PaymentMethod', $this->_code)
|
114 |
+
->setAdditionalInformation('use_saved_cc', false);
|
115 |
+
|
116 |
+
return $this;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* @param string $paymentAction
|
121 |
+
* @param object $stateObject
|
122 |
+
*
|
123 |
+
* @return bool|Mage_Payment_Model_Method_Abstract
|
124 |
+
*/
|
125 |
+
protected function processNewOrder($paymentAction, $stateObject)
|
126 |
+
{
|
127 |
+
$payment = $this->getInfoInstance();
|
128 |
+
$order = $payment->getOrder();
|
129 |
+
|
130 |
+
$customer = Mage::getModel('customer/customer');
|
131 |
+
|
132 |
+
$customerId = $this->createCustomer($order, $customer);
|
133 |
+
|
134 |
+
if (! $payment->getAdditionalInformation('use_saved_cc')) {
|
135 |
+
$this->createPaymentProfile($customerId);
|
136 |
+
}
|
137 |
+
|
138 |
+
if ($this->isSingleOrder($order)) {
|
139 |
+
$result = $this->processSinglePayment($payment, $order, $customerId);
|
140 |
+
} else {
|
141 |
+
$result = $this->processSubscription($payment, $order, $customerId);
|
142 |
+
}
|
143 |
+
|
144 |
+
if (! $result) {
|
145 |
+
return false;
|
146 |
+
}
|
147 |
+
|
148 |
+
$stateObject->setStatus(Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW)
|
149 |
+
->setState(Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW);
|
150 |
+
|
151 |
+
return $this;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* @param int $customerId
|
156 |
+
*
|
157 |
+
* @return array|bool
|
158 |
+
*/
|
159 |
+
protected function createPaymentProfile($customerId)
|
160 |
+
{
|
161 |
+
$payment = $this->getInfoInstance();
|
162 |
+
|
163 |
+
$creditCardData = [
|
164 |
+
'holder_name' => $payment->getCcOwner(),
|
165 |
+
'card_expiration' => str_pad($payment->getCcExpMonth(), 2, '0', STR_PAD_LEFT)
|
166 |
+
. '/' . $payment->getCcExpYear(),
|
167 |
+
'card_number' => $payment->getCcNumber(),
|
168 |
+
'card_cvv' => $payment->getCcCid() ?: '000',
|
169 |
+
'customer_id' => $customerId,
|
170 |
+
'payment_company_code' => $payment->getCcType(),
|
171 |
+
];
|
172 |
+
|
173 |
+
$paymentProfileId = $this->api()->createCustomerPaymentProfile($creditCardData);
|
174 |
+
|
175 |
+
if ($paymentProfileId === false) {
|
176 |
+
Mage::throwException('Erro ao informar os dados de cartão de crédito. Verifique os dados e tente novamente!');
|
177 |
+
|
178 |
+
return false;
|
179 |
+
}
|
180 |
+
|
181 |
+
return $paymentProfileId;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Check whether payment method can be used
|
186 |
+
*
|
187 |
+
* @param Mage_Sales_Model_Quote|null $quote
|
188 |
+
*
|
189 |
+
* @return bool
|
190 |
+
*/
|
191 |
+
public function isAvailable($quote = null)
|
192 |
+
{
|
193 |
+
return Mage::getStoreConfig('payment/vindi_creditcard/active')
|
194 |
+
&& Mage::helper('vindi_subscription')->getKey();
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Validate payment method information object
|
199 |
+
*
|
200 |
+
* @return Mage_Payment_Model_Method_Abstract
|
201 |
+
*/
|
202 |
+
public function validate()
|
203 |
+
{
|
204 |
+
$info = $this->getInfoInstance();
|
205 |
+
|
206 |
+
$quote = $info->getQuote();
|
207 |
+
|
208 |
+
$maxInstallmentsNumber = Mage::getStoreConfig('payment/vindi_creditcard/max_installments_number');
|
209 |
+
|
210 |
+
if ($this->isSingleOrder($quote) && ($maxInstallmentsNumber > 1)) {
|
211 |
+
if (! $installments = $info->getAdditionalInformation('installments')) {
|
212 |
+
return $this->error('Você deve informar o número de parcelas.');
|
213 |
+
}
|
214 |
+
|
215 |
+
if ($installments > $maxInstallmentsNumber) {
|
216 |
+
return $this->error('O número de parcelas selecionado é inválido.');
|
217 |
+
}
|
218 |
+
|
219 |
+
$minInstallmentsValue = Mage::getStoreConfig('payment/vindi_creditcard/min_installment_value');
|
220 |
+
$installmentValue = ceil($quote->getGrandTotal() / $installments * 100) / 100;
|
221 |
+
|
222 |
+
if (($installmentValue < $minInstallmentsValue) || ($installments > $maxInstallmentsNumber)) {
|
223 |
+
return $this->error('O número de parcelas selecionado é inválido.');
|
224 |
+
}
|
225 |
+
}
|
226 |
+
|
227 |
+
if ($info->getAdditionalInformation('use_saved_cc')) {
|
228 |
+
return $this;
|
229 |
+
}
|
230 |
+
|
231 |
+
$availableTypes = $this->api()->getCreditCardTypes();
|
232 |
+
|
233 |
+
$ccNumber = $info->getCcNumber();
|
234 |
+
|
235 |
+
// remove credit card non-numbers
|
236 |
+
$ccNumber = preg_replace('/\D/', '', $ccNumber);
|
237 |
+
|
238 |
+
$info->setCcNumber($ccNumber);
|
239 |
+
|
240 |
+
if (! $this->_validateExpDate($info->getCcExpYear(), $info->getCcExpMonth())) {
|
241 |
+
return $this->error(Mage::helper('payment')->__('Incorrect credit card expiration date.'));
|
242 |
+
}
|
243 |
+
|
244 |
+
if (! array_key_exists($info->getCcType(), $availableTypes)) {
|
245 |
+
return $this->error(Mage::helper('payment')->__('Credit card type is not allowed for this payment method.'));
|
246 |
+
}
|
247 |
+
|
248 |
+
return $this;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* @param string $errorMsg
|
253 |
+
*
|
254 |
+
* @return bool
|
255 |
+
* @throws \Mage_Core_Exception
|
256 |
+
*/
|
257 |
+
private function error($errorMsg)
|
258 |
+
{
|
259 |
+
Mage::throwException($errorMsg);
|
260 |
+
|
261 |
+
return false;
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* @return string
|
266 |
+
*/
|
267 |
+
protected function getPaymentMethodCode()
|
268 |
+
{
|
269 |
+
// TODO fix it to proper method code
|
270 |
+
return 'credit_card';
|
271 |
+
}
|
272 |
+
}
|
app/code/community/Vindi/Subscription/Model/Observer.php
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Model_Observer
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @var \Vindi_Subscription_Helper_Data
|
7 |
+
*/
|
8 |
+
private $_helper;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Constructor.
|
12 |
+
*/
|
13 |
+
public function __construct()
|
14 |
+
{
|
15 |
+
$this->_helper = Mage::helper('vindi_subscription');
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param Varien_Event_Observer $observer
|
20 |
+
*/
|
21 |
+
public function updateItems($observer)
|
22 |
+
{
|
23 |
+
if (! $this->_helper->isModuleEnabled()) {
|
24 |
+
return;
|
25 |
+
}
|
26 |
+
|
27 |
+
$quote = Mage::getSingleton('checkout/session')->getQuote();
|
28 |
+
if (! $this->countSubscriptions($quote)) {
|
29 |
+
return;
|
30 |
+
}
|
31 |
+
|
32 |
+
$data = $observer->getEvent()->getInfo();
|
33 |
+
|
34 |
+
foreach ($data as $itemId => $itemInfo) {
|
35 |
+
$item = $quote->getItemById($itemId);
|
36 |
+
if (! $item || ! $this->isSubscription($item->getProduct())) {
|
37 |
+
continue;
|
38 |
+
}
|
39 |
+
|
40 |
+
if (! ($qty = isset($itemInfo['qty']) ? (float) $itemInfo['qty'] : false)) {
|
41 |
+
continue;
|
42 |
+
}
|
43 |
+
|
44 |
+
if ($qty > 1) {
|
45 |
+
$this->addNotice('Você pode fazer apenas uma assinatura por vez.<br />
|
46 |
+
Conclua a compra da assinatura ou remova-a do carrinho.');
|
47 |
+
}
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @param Varien_Event_Observer $observer
|
53 |
+
*/
|
54 |
+
public function addToCart($observer)
|
55 |
+
{
|
56 |
+
if (! $this->_helper->isModuleEnabled()) {
|
57 |
+
return;
|
58 |
+
}
|
59 |
+
|
60 |
+
$quote = Mage::getSingleton('checkout/session')->getQuote();
|
61 |
+
/** @var Mage_Catalog_Model_Product $product */
|
62 |
+
$product = $observer->getEvent()->getProduct();
|
63 |
+
|
64 |
+
$itemsCount = $quote->getItemsCount();
|
65 |
+
$itemsSummaryQty = $quote->getItemsSummaryQty();
|
66 |
+
|
67 |
+
if (! $itemsCount && ($itemsSummaryQty === 1)) {
|
68 |
+
return;
|
69 |
+
}
|
70 |
+
|
71 |
+
if ($this->isSubscription($product)) {
|
72 |
+
if ($this->countSubscriptions($quote) > 1) {
|
73 |
+
$this->addNotice('Você pode fazer apenas uma assinatura por vez.<br />
|
74 |
+
Conclua a compra da assinatura ou remova-a do carrinho.');
|
75 |
+
}
|
76 |
+
|
77 |
+
if (($itemsCount === 1) && ($itemsSummaryQty > 1)) {
|
78 |
+
$this->addNotice('Você pode fazer apenas uma assinatura por vez.<br />
|
79 |
+
Por favor, tente novamente.');
|
80 |
+
}
|
81 |
+
|
82 |
+
$this->addNotice('Você não pode adicionar assinaturas e outros tipos de produtos em um mesmo carrinho.<br />
|
83 |
+
Conclua a compra dos produtos ou remova-os do carrinho.');
|
84 |
+
|
85 |
+
}
|
86 |
+
|
87 |
+
if ($this->countSubscriptions($quote)) {
|
88 |
+
$this->addNotice('Você não pode adicionar assinaturas e outros tipos de produtos em um mesmo carrinho.<br />
|
89 |
+
Conclua a compra da assinatura ou remova-a do carrinho.');
|
90 |
+
}
|
91 |
+
|
92 |
+
return;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @param Varien_Event_Observer $observer
|
97 |
+
*/
|
98 |
+
public function validateAdminHtmlOrder($observer)
|
99 |
+
{
|
100 |
+
/** @var Mage_Adminhtml_Model_Sales_Order_Create $order */
|
101 |
+
$order = $observer['order_create_model'];
|
102 |
+
$quote = $order->getQuote();
|
103 |
+
$quote->collectTotals();
|
104 |
+
|
105 |
+
$itemsCount = $quote->getItemsCount();
|
106 |
+
$itemsSummaryQty = $quote->getItemsSummaryQty();
|
107 |
+
$subscriptionsCount = $this->countSubscriptions($quote);
|
108 |
+
|
109 |
+
if (! $subscriptionsCount) {
|
110 |
+
return;
|
111 |
+
}
|
112 |
+
|
113 |
+
if (($subscriptionsCount > 1)) {
|
114 |
+
Mage::throwException('Você pode fazer apenas uma assinatura por vez.<br />
|
115 |
+
Conclua a compra de uma única assinatura ou remova os excedentes dos itens.');
|
116 |
+
}
|
117 |
+
|
118 |
+
if (($itemsCount === 1) && ($itemsSummaryQty > 1)) {
|
119 |
+
Mage::throwException('Você pode fazer apenas uma assinatura por vez.<br />
|
120 |
+
Por favor, tente novamente.');
|
121 |
+
}
|
122 |
+
|
123 |
+
if ($itemsCount > 1) {
|
124 |
+
Mage::throwException('Você não pode adicionar assinaturas e outros tipos de produtos em um mesmo pedido.<br />
|
125 |
+
Conclua a compra da assinatura ou remova-a do carrinho.');
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* @param $message
|
131 |
+
*/
|
132 |
+
private function addNotice($message)
|
133 |
+
{
|
134 |
+
Mage::getSingleton('core/session')->addNotice($message);
|
135 |
+
Mage::app()->getFrontController()->getResponse()->setRedirect(Mage::getUrl('checkout/cart'));
|
136 |
+
Mage::app()->getResponse()->sendResponse();
|
137 |
+
exit;
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* @param Mage_Sales_Model_Quote $quote
|
142 |
+
*
|
143 |
+
* @return int
|
144 |
+
*/
|
145 |
+
private function countSubscriptions($quote)
|
146 |
+
{
|
147 |
+
$count = 0;
|
148 |
+
|
149 |
+
foreach ($quote->getAllVisibleItems() as $item) {
|
150 |
+
if (($product = $item->getProduct()) && $this->isSubscription($product)) {
|
151 |
+
$count++;
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
return $count;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* @param Mage_Catalog_Model_Product $product
|
160 |
+
*
|
161 |
+
* @return bool
|
162 |
+
*/
|
163 |
+
private function isSubscription($product)
|
164 |
+
{
|
165 |
+
return $product->getTypeId() === 'subscription';
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
app/code/community/Vindi/Subscription/Model/Product/Attribute/Plan.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Model_Product_Attribute_Plan extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* Get Plans from Vindi.
|
7 |
+
* @return array
|
8 |
+
*/
|
9 |
+
public function getAllOptions()
|
10 |
+
{
|
11 |
+
$this->_options = [
|
12 |
+
[
|
13 |
+
'value' => '',
|
14 |
+
'label' => Mage::helper('catalog')->__('-- Please Select --'),
|
15 |
+
],
|
16 |
+
];
|
17 |
+
|
18 |
+
/** @var Vindi_Subscription_Helper_API $api */
|
19 |
+
$api = Mage::helper('vindi_subscription/api');
|
20 |
+
|
21 |
+
foreach ($api->getPlans() as $id => $name) {
|
22 |
+
$this->_options[] = [
|
23 |
+
'value' => $id,
|
24 |
+
'label' => $name,
|
25 |
+
];
|
26 |
+
}
|
27 |
+
|
28 |
+
return $this->_options;
|
29 |
+
}
|
30 |
+
}
|
app/code/community/Vindi/Subscription/Model/Product/Type.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_Model_Product_Type extends Mage_Catalog_Model_Product_Type_Simple
|
4 |
+
{
|
5 |
+
|
6 |
+
}
|
app/code/community/Vindi/Subscription/Trait/PaymentMethod.php
ADDED
@@ -0,0 +1,306 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
trait Vindi_Subscription_Trait_PaymentMethod
|
4 |
+
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* @param string $paymentAction
|
8 |
+
* @param object $stateObject
|
9 |
+
*
|
10 |
+
* @return bool|Mage_Payment_Model_Method_Abstract
|
11 |
+
*/
|
12 |
+
public function initialize($paymentAction, $stateObject)
|
13 |
+
{
|
14 |
+
if ($this->checkForReorder()) {
|
15 |
+
return $this->processReorder($paymentAction, $stateObject);
|
16 |
+
}
|
17 |
+
|
18 |
+
return $this->processNewOrder($paymentAction, $stateObject);
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
+
protected function checkForReorder()
|
25 |
+
{
|
26 |
+
$session = Mage::getSingleton('core/session');
|
27 |
+
$isReorder = $session->getData('vindi_is_reorder', false);
|
28 |
+
$session->unsetData('vindi_is_reorder');
|
29 |
+
|
30 |
+
return $isReorder;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @param Mage_Customer_Model_Customer $customer
|
35 |
+
*
|
36 |
+
* @return bool|string
|
37 |
+
* @throws \Mage_Core_Exception
|
38 |
+
*/
|
39 |
+
protected function getCustomerTipoPessoa($customer)
|
40 |
+
{
|
41 |
+
$attribute = Mage::getSingleton('eav/config')->getAttribute('customer', 'tipopessoa');
|
42 |
+
|
43 |
+
$tipopessoa = $customer->getTipopessoa();
|
44 |
+
|
45 |
+
if ($attribute && $attribute->usesSource() && $tipopessoa) {
|
46 |
+
return $attribute->getSource()->getOptionText($tipopessoa);
|
47 |
+
}
|
48 |
+
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @param Mage_Sales_Model_Order $order
|
54 |
+
* @param Mage_Customer_Model_Customer $customer
|
55 |
+
*
|
56 |
+
* @return bool|int|null
|
57 |
+
*/
|
58 |
+
protected function createCustomer($order, $customer)
|
59 |
+
{
|
60 |
+
$billing = $order->getBillingAddress();
|
61 |
+
|
62 |
+
if (Mage::app()->getStore()->isAdmin()) {
|
63 |
+
$customer = Mage::getSingleton('adminhtml/session_quote')->getCustomer();
|
64 |
+
} else {
|
65 |
+
$customer->setWebsiteId(Mage::app()->getWebsite()->getId());
|
66 |
+
$customer->loadByEmail($billing->getEmail());
|
67 |
+
}
|
68 |
+
|
69 |
+
//TODO fix user being created again if validation fails
|
70 |
+
if (! ($userCode = $customer->getVindiUserCode())) {
|
71 |
+
$userCode = 'mag-' . $customer->getId() . '-' . time();
|
72 |
+
|
73 |
+
$customer->setVindiUserCode($userCode);
|
74 |
+
$customer->save();
|
75 |
+
}
|
76 |
+
|
77 |
+
$address = [
|
78 |
+
'street' => $billing->getStreet(1),
|
79 |
+
'number' => $billing->getStreet(2),
|
80 |
+
'additional_details' => $billing->getStreet(3),
|
81 |
+
'neighborhood' => $billing->getStreet(4),
|
82 |
+
'zipcode' => $billing->getPostcode(),
|
83 |
+
'city' => $billing->getCity(),
|
84 |
+
'state' => $billing->getRegionCode(),
|
85 |
+
'country' => $billing->getCountry(),
|
86 |
+
];
|
87 |
+
|
88 |
+
$customerVindi = [
|
89 |
+
'name' => $billing->getFirstname() . ' ' . $billing->getLastname(),
|
90 |
+
'email' => $order->getBillingAddress()->getEmail(),
|
91 |
+
'registry_code' => $order->getData('customer_taxvat'),
|
92 |
+
'code' => $userCode,
|
93 |
+
'address' => $address,
|
94 |
+
];
|
95 |
+
|
96 |
+
if (Mage::getStoreConfig('vindi_subscription/general/send_nfe_information')) {
|
97 |
+
switch ($this->getCustomerTipoPessoa($customer)) {
|
98 |
+
case "Física":
|
99 |
+
$customerVindi['metadata'] = [
|
100 |
+
'carteira_de_identidade' => $customer->getIe(),
|
101 |
+
];
|
102 |
+
break;
|
103 |
+
case "Jurídica":
|
104 |
+
$customerVindi['metadata'] = [
|
105 |
+
'inscricao_estadual' => $customer->getIe(),
|
106 |
+
];
|
107 |
+
break;
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
$customerId = $this->api()->findOrCreateCustomer($customerVindi);
|
112 |
+
|
113 |
+
if ($customerId === false) {
|
114 |
+
Mage::throwException('Falha ao registrar o usuário. Verifique os dados e tente novamente!');
|
115 |
+
}
|
116 |
+
|
117 |
+
return $customerId;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* @return Vindi_Subscription_Helper_API
|
122 |
+
*/
|
123 |
+
protected function api()
|
124 |
+
{
|
125 |
+
if (isset($this->vindiApi)) {
|
126 |
+
return $this->vindiApi;
|
127 |
+
}
|
128 |
+
|
129 |
+
return $this->vindiApi = Mage::helper('vindi_subscription/api');
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @param string $paymentAction
|
134 |
+
* @param object $stateObject
|
135 |
+
*
|
136 |
+
* @return bool|Mage_Payment_Model_Method_Abstract
|
137 |
+
*/
|
138 |
+
protected function processReorder($paymentAction, $stateObject)
|
139 |
+
{
|
140 |
+
$payment = $this->getInfoInstance();
|
141 |
+
$order = $payment->getOrder();
|
142 |
+
|
143 |
+
$payment->setAmount($order->getTotalDue());
|
144 |
+
$this->setStore($order->getStoreId());
|
145 |
+
|
146 |
+
$payment->setStatus(Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW, Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW,
|
147 |
+
'Novo período da assinatura criado', true);
|
148 |
+
$stateObject->setStatus(Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW)
|
149 |
+
->setState(Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW);
|
150 |
+
|
151 |
+
return $this;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* @param Mage_Payment_Model_Method_Abstract $payment
|
156 |
+
* @param Mage_Sales_Model_Order $order
|
157 |
+
* @param int $customerId
|
158 |
+
*
|
159 |
+
* @return bool
|
160 |
+
* @throws \Mage_Core_Exception
|
161 |
+
*/
|
162 |
+
protected function processSubscription($payment, $order, $customerId)
|
163 |
+
{
|
164 |
+
$subscription = $this->createSubscription($order, $customerId);
|
165 |
+
|
166 |
+
if ($subscription === false) {
|
167 |
+
Mage::throwException('Erro ao criar a assinatura. Verifique os dados e tente novamente!');
|
168 |
+
|
169 |
+
return false;
|
170 |
+
}
|
171 |
+
|
172 |
+
$payment->setAmount($order->getTotalDue());
|
173 |
+
$this->setStore($order->getStoreId());
|
174 |
+
|
175 |
+
$payment->setStatus(Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW, Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW,
|
176 |
+
'Assinatura criada', true);
|
177 |
+
|
178 |
+
return true;
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* @param Mage_Payment_Model_Method_Abstract $payment
|
183 |
+
* @param Mage_Sales_Model_Order $order
|
184 |
+
* @param int $customerId
|
185 |
+
*
|
186 |
+
* @return bool
|
187 |
+
* @throws \Mage_Core_Exception
|
188 |
+
*/
|
189 |
+
protected function processSinglePayment($payment, $order, $customerId)
|
190 |
+
{
|
191 |
+
$uniquePaymentProduct = $this->api()->findOrCreateUniquePaymentProduct();
|
192 |
+
|
193 |
+
$this->log(sprintf('Produto para pagamento único: %d.', $uniquePaymentProduct));
|
194 |
+
|
195 |
+
$body = [
|
196 |
+
'customer_id' => $customerId,
|
197 |
+
'payment_method_code' => $this->getPaymentMethodCode(),
|
198 |
+
'bill_items' => [
|
199 |
+
[
|
200 |
+
'product_id' => $uniquePaymentProduct,
|
201 |
+
'amount' => $order->getGrandTotal(),
|
202 |
+
],
|
203 |
+
],
|
204 |
+
];
|
205 |
+
|
206 |
+
if ($installments = $payment->getAdditionalInformation('installments')) {
|
207 |
+
$body['installments'] = (int) $installments;
|
208 |
+
}
|
209 |
+
|
210 |
+
$billId = $this->api()->createBill($body);
|
211 |
+
|
212 |
+
if (! $billId) {
|
213 |
+
$this->log(sprintf('Erro no pagamento do pedido %d.', $order->getId()));
|
214 |
+
|
215 |
+
$message = sprintf('Pagamento Falhou. (%s)', $this->api()->lastError);
|
216 |
+
$payment->setStatus(
|
217 |
+
Mage_Sales_Model_Order::STATE_CANCELED,
|
218 |
+
Mage_Sales_Model_Order::STATE_CANCELED,
|
219 |
+
$message,
|
220 |
+
true
|
221 |
+
);
|
222 |
+
|
223 |
+
Mage::throwException($message);
|
224 |
+
|
225 |
+
return false;
|
226 |
+
}
|
227 |
+
|
228 |
+
$order->setVindiBillId($billId);
|
229 |
+
$order->save();
|
230 |
+
|
231 |
+
return $billId;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* @param Mage_Sales_Model_Order $order
|
236 |
+
* @param int $customerId
|
237 |
+
*
|
238 |
+
* @return bool
|
239 |
+
*/
|
240 |
+
protected function createSubscription($order, $customerId)
|
241 |
+
{
|
242 |
+
$orderItems = $order->getItemsCollection();
|
243 |
+
$item = $orderItems->getFirstItem();
|
244 |
+
$product = Mage::getModel('catalog/product')->load($item->getProductId());
|
245 |
+
|
246 |
+
$plan = $product->getData('vindi_subscription_plan');
|
247 |
+
|
248 |
+
$productItems = $this->api()->buildPlanItemsForSubscription($order);
|
249 |
+
if(!$productItems){
|
250 |
+
return false;
|
251 |
+
}
|
252 |
+
|
253 |
+
$body = [
|
254 |
+
'customer_id' => $customerId,
|
255 |
+
'payment_method_code' => $this->getPaymentMethodCode(),
|
256 |
+
'plan_id' => $plan,
|
257 |
+
'code' => 'mag-' . $order->getIncrementId() . '-' . time(),
|
258 |
+
'product_items' => $productItems
|
259 |
+
];
|
260 |
+
|
261 |
+
$subscription = $this->api()->createSubscription($body);
|
262 |
+
|
263 |
+
if (! isset($subscription['id']) || empty($subscription['id'])) {
|
264 |
+
$message = sprintf('Pagamento Falhou. (%s)', $this->api()->lastError);
|
265 |
+
$this->log(sprintf('Erro no pagamento do pedido %s.\n%s', $order->getId(), $message));
|
266 |
+
|
267 |
+
Mage::throwException($message);
|
268 |
+
|
269 |
+
// TODO update order status?
|
270 |
+
return false;
|
271 |
+
}
|
272 |
+
|
273 |
+
$order->setVindiSubscriptionId($subscription['id']);
|
274 |
+
$order->setVindiSubscriptionPeriod(1);
|
275 |
+
$order->save();
|
276 |
+
|
277 |
+
return $subscription;
|
278 |
+
}
|
279 |
+
|
280 |
+
/**
|
281 |
+
* @param string $message
|
282 |
+
* @param int|null $level
|
283 |
+
*/
|
284 |
+
protected function log($message, $level = null)
|
285 |
+
{
|
286 |
+
Mage::log($message, $level, $this->_code . '.log');
|
287 |
+
}
|
288 |
+
|
289 |
+
/*
|
290 |
+
* @param Mage_Sales_Model_Order $order
|
291 |
+
*/
|
292 |
+
protected function isSingleOrder($order)
|
293 |
+
{
|
294 |
+
if (! $order) {
|
295 |
+
return false;
|
296 |
+
}
|
297 |
+
|
298 |
+
foreach ($order->getAllVisibleItems() as $item) {
|
299 |
+
if (($product = $item->getProduct()) && ($product->getTypeId() === 'subscription')) {
|
300 |
+
return false;
|
301 |
+
}
|
302 |
+
}
|
303 |
+
|
304 |
+
return true;
|
305 |
+
}
|
306 |
+
}
|
app/code/community/Vindi/Subscription/controllers/WebhookController.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Vindi_Subscription_WebhookController extends Mage_Core_Controller_Front_Action
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* The route that webhooks will use.
|
7 |
+
*/
|
8 |
+
public function indexAction()
|
9 |
+
{
|
10 |
+
/** @var Vindi_Subscription_Helper_WebhookHandler $handler */
|
11 |
+
$handler = Mage::helper('vindi_subscription/webhookHandler');
|
12 |
+
|
13 |
+
if (! $this->validateRequest()) {
|
14 |
+
$ip = Mage::helper('core/http')->getRemoteAddr();
|
15 |
+
|
16 |
+
$handler->log(sprintf('Invalid webhook attempt from IP %s', $ip), Zend_Log::WARN);
|
17 |
+
$this->norouteAction();
|
18 |
+
|
19 |
+
return false;
|
20 |
+
}
|
21 |
+
|
22 |
+
$body = file_get_contents('php://input');
|
23 |
+
$handler->log(sprintf("Novo evento dos webhooks!\n%s", $body));
|
24 |
+
|
25 |
+
return $handler->handle($body);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Validate the webhook for security reasons.
|
30 |
+
*
|
31 |
+
* @return bool
|
32 |
+
*/
|
33 |
+
private function validateRequest()
|
34 |
+
{
|
35 |
+
$systemKey = Mage::helper('vindi_subscription')->getHashKey();
|
36 |
+
$requestKey = $this->getRequest()->getParam('key');
|
37 |
+
|
38 |
+
return $systemKey === $requestKey;
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
app/code/community/Vindi/Subscription/etc/adminhtml.xml
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<config>
|
3 |
+
<acl>
|
4 |
+
<resources>
|
5 |
+
<admin>
|
6 |
+
<children>
|
7 |
+
<system>
|
8 |
+
<children>
|
9 |
+
<config>
|
10 |
+
<children>
|
11 |
+
<vindi_subscription translate="title" module="vindi_subscription">
|
12 |
+
<title>Vindi</title>
|
13 |
+
</vindi_subscription>
|
14 |
+
</children>
|
15 |
+
</config>
|
16 |
+
</children>
|
17 |
+
</system>
|
18 |
+
</children>
|
19 |
+
</admin>
|
20 |
+
</resources>
|
21 |
+
</acl>
|
22 |
+
</config>
|
app/code/community/Vindi/Subscription/etc/config.xml
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Vindi_Subscription>
|
5 |
+
<version>1.0.7</version>
|
6 |
+
</Vindi_Subscription>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<catalog>
|
10 |
+
<product>
|
11 |
+
<type>
|
12 |
+
<subscription translate="label" module="vindi_subscription">
|
13 |
+
<label>Assinatura Vindi</label>
|
14 |
+
<model>vindi_subscription/product_type</model>
|
15 |
+
<is_qty>0</is_qty>
|
16 |
+
<composite>0</composite>
|
17 |
+
<can_use_qty_decimals>0</can_use_qty_decimals>
|
18 |
+
</subscription>
|
19 |
+
</type>
|
20 |
+
</product>
|
21 |
+
</catalog>
|
22 |
+
<resources>
|
23 |
+
<vindi_subscription_setup>
|
24 |
+
<setup>
|
25 |
+
<module>Vindi_Subscription</module>
|
26 |
+
<class>Mage_Catalog_Model_Resource_Setup</class>
|
27 |
+
</setup>
|
28 |
+
</vindi_subscription_setup>
|
29 |
+
</resources>
|
30 |
+
<blocks>
|
31 |
+
<vindi_subscription>
|
32 |
+
<class>Vindi_Subscription_Block</class>
|
33 |
+
</vindi_subscription>
|
34 |
+
</blocks>
|
35 |
+
<helpers>
|
36 |
+
<vindi_subscription>
|
37 |
+
<class>Vindi_Subscription_Helper</class>
|
38 |
+
</vindi_subscription>
|
39 |
+
</helpers>
|
40 |
+
<models>
|
41 |
+
<vindi_subscription>
|
42 |
+
<class>Vindi_Subscription_Model</class>
|
43 |
+
</vindi_subscription>
|
44 |
+
</models>
|
45 |
+
<traits>
|
46 |
+
<vindi_subscription>
|
47 |
+
<class>Vindi_Subscription_Trait_PaymentMethod</class>
|
48 |
+
</vindi_subscription>
|
49 |
+
</traits>
|
50 |
+
</global>
|
51 |
+
<adminhtml>
|
52 |
+
<sales>
|
53 |
+
<order>
|
54 |
+
<create>
|
55 |
+
<available_product_types>
|
56 |
+
<subscription/>
|
57 |
+
</available_product_types>
|
58 |
+
</create>
|
59 |
+
</order>
|
60 |
+
</sales>
|
61 |
+
<layout>
|
62 |
+
<updates>
|
63 |
+
<vindi_subscription>
|
64 |
+
<file>vindi_subscription.xml</file>
|
65 |
+
</vindi_subscription>
|
66 |
+
</updates>
|
67 |
+
</layout>
|
68 |
+
<events>
|
69 |
+
<adminhtml_sales_order_create_process_data>
|
70 |
+
<observers>
|
71 |
+
<vindi_subscription_saveAdminHtmlOrder>
|
72 |
+
<class>vindi_subscription/observer</class>
|
73 |
+
<method>validateAdminHtmlOrder</method>
|
74 |
+
</vindi_subscription_saveAdminHtmlOrder>
|
75 |
+
</observers>
|
76 |
+
</adminhtml_sales_order_create_process_data>
|
77 |
+
</events>
|
78 |
+
</adminhtml>
|
79 |
+
<default>
|
80 |
+
<vindi_subscription>
|
81 |
+
<general>
|
82 |
+
<send_nfe_information>0</send_nfe_information>
|
83 |
+
</general>
|
84 |
+
</vindi_subscription>
|
85 |
+
<payment>
|
86 |
+
<vindi_bankslip>
|
87 |
+
<active>0</active>
|
88 |
+
<model>vindi_subscription/bankSlip</model>
|
89 |
+
<title>Boleto Bancário</title>
|
90 |
+
<payment_action>capture</payment_action>
|
91 |
+
<allowspecific>0</allowspecific>
|
92 |
+
</vindi_bankslip>
|
93 |
+
<vindi_creditcard>
|
94 |
+
<active>0</active>
|
95 |
+
<model>vindi_subscription/creditCard</model>
|
96 |
+
<title>Cartão de Crédito</title>
|
97 |
+
<payment_action>capture</payment_action>
|
98 |
+
<allowspecific>0</allowspecific>
|
99 |
+
<min_installment_value>5</min_installment_value>
|
100 |
+
<max_installments_number>1</max_installments_number>
|
101 |
+
</vindi_creditcard>
|
102 |
+
</payment>
|
103 |
+
</default>
|
104 |
+
<frontend>
|
105 |
+
<layout>
|
106 |
+
<updates>
|
107 |
+
<vindi_subscription>
|
108 |
+
<file>vindi_subscription.xml</file>
|
109 |
+
</vindi_subscription>
|
110 |
+
</updates>
|
111 |
+
</layout>
|
112 |
+
<routers>
|
113 |
+
<subscription>
|
114 |
+
<use>standard</use>
|
115 |
+
<args>
|
116 |
+
<module>Vindi_Subscription</module>
|
117 |
+
<frontName>vindi_subscription</frontName>
|
118 |
+
</args>
|
119 |
+
</subscription>
|
120 |
+
</routers>
|
121 |
+
<events>
|
122 |
+
<checkout_cart_update_items_before>
|
123 |
+
<observers>
|
124 |
+
<vindi_subscription_updateItems>
|
125 |
+
<class>vindi_subscription/observer</class>
|
126 |
+
<method>updateItems</method>
|
127 |
+
</vindi_subscription_updateItems>
|
128 |
+
</observers>
|
129 |
+
</checkout_cart_update_items_before>
|
130 |
+
<checkout_cart_product_add_after>
|
131 |
+
<observers>
|
132 |
+
<vindi_subscription_addToCart>
|
133 |
+
<class>vindi_subscription/observer</class>
|
134 |
+
<method>addToCart</method>
|
135 |
+
</vindi_subscription_addToCart>
|
136 |
+
</observers>
|
137 |
+
</checkout_cart_product_add_after>
|
138 |
+
</events>
|
139 |
+
</frontend>
|
140 |
+
</config>
|
141 |
+
|
app/code/community/Vindi/Subscription/etc/system.xml
ADDED
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<tabs>
|
4 |
+
<vindi translate="label" module="vindi_subscription">
|
5 |
+
<label>Vindi</label>
|
6 |
+
<sort_order>399</sort_order>
|
7 |
+
</vindi>
|
8 |
+
</tabs>
|
9 |
+
<sections>
|
10 |
+
<vindi_subscription translate="label" module="vindi_subscription">
|
11 |
+
<label>
|
12 |
+
<![CDATA[<img src="//www.vindi.com.br/image/favicon.png" style="float:left;margin-top:1px;width:16px;height:16px"/> Vindi Assinaturas]]></label>
|
13 |
+
<tab>vindi</tab>
|
14 |
+
<frontend_type>text</frontend_type>
|
15 |
+
<sort_order>10</sort_order>
|
16 |
+
<show_in_default>1</show_in_default>
|
17 |
+
<show_in_website>1</show_in_website>
|
18 |
+
<show_in_store>1</show_in_store>
|
19 |
+
<groups>
|
20 |
+
<general translate="label" module="vindi_subscription">
|
21 |
+
<label>Configuração</label>
|
22 |
+
<sort_order>10</sort_order>
|
23 |
+
<show_in_default>1</show_in_default>
|
24 |
+
<show_in_website>1</show_in_website>
|
25 |
+
<show_in_store>1</show_in_store>
|
26 |
+
<comment>
|
27 |
+
<![CDATA[<a href="https://app.vindi.com.br/prospects/new" target="_blank">Clique aqui para criar uma conta na Vindi.</a>]]></comment>
|
28 |
+
<fields>
|
29 |
+
<api_key>
|
30 |
+
<label>Chave da API</label>
|
31 |
+
<frontend_type>text</frontend_type>
|
32 |
+
<sort_order>1</sort_order>
|
33 |
+
<show_in_default>1</show_in_default>
|
34 |
+
<show_in_website>1</show_in_website>
|
35 |
+
<show_in_store>1</show_in_store>
|
36 |
+
</api_key>
|
37 |
+
<send_nfe_information>
|
38 |
+
<label>Enviar informações para emissão de NFe's</label>
|
39 |
+
<comment><![CDATA[
|
40 |
+
Envia informações de RG e Inscrição Estadual para Emissão de NFe's com nossos parceiros.
|
41 |
+
<a href="http://atendimento.vindi.com.br/hc/pt-br/articles/204450944-Notas-fiscais" target="_blank">Saiba mais</a>
|
42 |
+
]]></comment>
|
43 |
+
<frontend_type>select</frontend_type>
|
44 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
45 |
+
<sort_order>2</sort_order>
|
46 |
+
<show_in_default>1</show_in_default>
|
47 |
+
<show_in_website>1</show_in_website>
|
48 |
+
<show_in_store>1</show_in_store>
|
49 |
+
</send_nfe_information>
|
50 |
+
<default_shipping_method>
|
51 |
+
<label>Método de envio padrão</label>
|
52 |
+
<comment><![CDATA[
|
53 |
+
Utilizado na criacão de um novo ciclo.
|
54 |
+
Em caso de falha no método de envio do ciclo anterior o método padrão é definido para o novo pedido.
|
55 |
+
]]></comment>
|
56 |
+
<frontend_type>select</frontend_type>
|
57 |
+
<source_model>vindi_subscription/config_shippingmethod</source_model>
|
58 |
+
<sort_order>3</sort_order>
|
59 |
+
<show_in_default>1</show_in_default>
|
60 |
+
<show_in_website>1</show_in_website>
|
61 |
+
<show_in_store>1</show_in_store>
|
62 |
+
</default_shipping_method>
|
63 |
+
<bankslip_link_in_order_comment>
|
64 |
+
<label>Boleto bancário no histórico do pedido</label>
|
65 |
+
<comment><![CDATA[
|
66 |
+
Exibe o link para o boleto bancário nos comentários do pedido.
|
67 |
+
(Ao habilitar está opção certifique-se que a função "escapeHtml" foi removida da view no frontend)
|
68 |
+
]]></comment>
|
69 |
+
<frontend_type>select</frontend_type>
|
70 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
71 |
+
<sort_order>4</sort_order>
|
72 |
+
<show_in_default>1</show_in_default>
|
73 |
+
<show_in_website>1</show_in_website>
|
74 |
+
<show_in_store>1</show_in_store>
|
75 |
+
</bankslip_link_in_order_comment>
|
76 |
+
<information>
|
77 |
+
<label>Informações</label>
|
78 |
+
<frontend_model>vindi_subscription/config_information</frontend_model>
|
79 |
+
<sort_order>10</sort_order>
|
80 |
+
<show_in_default>1</show_in_default>
|
81 |
+
<show_in_website>1</show_in_website>
|
82 |
+
<show_in_store>1</show_in_store>
|
83 |
+
</information>
|
84 |
+
</fields>
|
85 |
+
</general>
|
86 |
+
</groups>
|
87 |
+
</vindi_subscription>
|
88 |
+
<payment>
|
89 |
+
<groups>
|
90 |
+
<vindi_creditcard translate="label" module="vindi_subscription">
|
91 |
+
<label>Vindi - Cartão de Crédito</label>
|
92 |
+
<sort_order>670</sort_order>
|
93 |
+
<show_in_default>1</show_in_default>
|
94 |
+
<show_in_website>1</show_in_website>
|
95 |
+
<show_in_store>0</show_in_store>
|
96 |
+
<comment>
|
97 |
+
<![CDATA[<a href="https://app.vindi.com.br/prospects/new" target="_blank">Clique aqui para criar uma conta na Vindi.</a>]]></comment>
|
98 |
+
<fields>
|
99 |
+
<active translate="label">
|
100 |
+
<label>Ativo</label>
|
101 |
+
<frontend_type>select</frontend_type>
|
102 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
103 |
+
<sort_order>1</sort_order>
|
104 |
+
<show_in_default>1</show_in_default>
|
105 |
+
<show_in_website>1</show_in_website>
|
106 |
+
<show_in_store>0</show_in_store>
|
107 |
+
</active>
|
108 |
+
<title translate="label">
|
109 |
+
<label>Título</label>
|
110 |
+
<frontend_type>text</frontend_type>
|
111 |
+
<sort_order>2</sort_order>
|
112 |
+
<show_in_default>1</show_in_default>
|
113 |
+
<show_in_website>1</show_in_website>
|
114 |
+
<show_in_store>0</show_in_store>
|
115 |
+
</title>
|
116 |
+
<installments_heading translate="label">
|
117 |
+
<label>Vendas Avulsas</label>
|
118 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
119 |
+
<sort_order>10</sort_order>
|
120 |
+
<show_in_default>1</show_in_default>
|
121 |
+
<show_in_website>1</show_in_website>
|
122 |
+
<show_in_store>0</show_in_store>
|
123 |
+
</installments_heading>
|
124 |
+
<min_installment_value translate="label">
|
125 |
+
<label>Valor mínimo da parcela</label>
|
126 |
+
<comment>Valor mínimo da parcela, não deve ser inferior a R$ 5,00.</comment>
|
127 |
+
<frontend_type>text</frontend_type>
|
128 |
+
<sort_order>11</sort_order>
|
129 |
+
<show_in_default>1</show_in_default>
|
130 |
+
<show_in_website>1</show_in_website>
|
131 |
+
<show_in_store>0</show_in_store>
|
132 |
+
</min_installment_value>
|
133 |
+
<max_installments_number translate="label">
|
134 |
+
<label>Número máximo de parcelas</label>
|
135 |
+
<comment>Número máximo de parcelas para vendas avulsas. Deixe em 1x para desativar o
|
136 |
+
parcelamento.
|
137 |
+
</comment>
|
138 |
+
<frontend_type>select</frontend_type>
|
139 |
+
<source_model>vindi_subscription/config_installments</source_model>
|
140 |
+
<sort_order>12</sort_order>
|
141 |
+
<show_in_default>1</show_in_default>
|
142 |
+
<show_in_website>1</show_in_website>
|
143 |
+
<show_in_store>0</show_in_store>
|
144 |
+
</max_installments_number>
|
145 |
+
</fields>
|
146 |
+
</vindi_creditcard>
|
147 |
+
<vindi_bankslip translate="label" module="vindi_subscription">
|
148 |
+
<label>Vindi - Boleto Bancário</label>
|
149 |
+
<sort_order>671</sort_order>
|
150 |
+
<show_in_default>1</show_in_default>
|
151 |
+
<show_in_website>1</show_in_website>
|
152 |
+
<show_in_store>0</show_in_store>
|
153 |
+
<comment>
|
154 |
+
<![CDATA[<a href="https://app.vindi.com.br/prospects/new" target="_blank">Clique aqui para criar uma conta na Vindi.</a>]]></comment>
|
155 |
+
<fields>
|
156 |
+
<active translate="label">
|
157 |
+
<label>Ativo</label>
|
158 |
+
<frontend_type>select</frontend_type>
|
159 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
160 |
+
<sort_order>1</sort_order>
|
161 |
+
<show_in_default>1</show_in_default>
|
162 |
+
<show_in_website>1</show_in_website>
|
163 |
+
<show_in_store>0</show_in_store>
|
164 |
+
</active>
|
165 |
+
<title translate="label">
|
166 |
+
<label>Título</label>
|
167 |
+
<frontend_type>text</frontend_type>
|
168 |
+
<sort_order>2</sort_order>
|
169 |
+
<show_in_default>1</show_in_default>
|
170 |
+
<show_in_website>1</show_in_website>
|
171 |
+
<show_in_store>0</show_in_store>
|
172 |
+
</title>
|
173 |
+
</fields>
|
174 |
+
</vindi_bankslip>
|
175 |
+
</groups>
|
176 |
+
</payment>
|
177 |
+
</sections>
|
178 |
+
</config>
|
app/code/community/Vindi/Subscription/sql/vindi_subscription_setup/install-1.0.0.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/** @var $installer Mage_Catalog_Model_Resource_Setup */
|
4 |
+
$installer = $this;
|
5 |
+
$installer->startSetup();
|
6 |
+
|
7 |
+
if (! $this->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'vindi_subscription_plan', 'attribute_id')) {
|
8 |
+
$installer->addAttribute(
|
9 |
+
Mage_Catalog_Model_Product::ENTITY,
|
10 |
+
'vindi_subscription_plan',
|
11 |
+
[
|
12 |
+
'type' => 'int',
|
13 |
+
'input' => 'select',
|
14 |
+
'backend' => '',
|
15 |
+
'frontend' => '',
|
16 |
+
'label' => 'Plano da Vindi',
|
17 |
+
'class' => '',
|
18 |
+
'source' => 'vindi_subscription/product_attribute_plan',
|
19 |
+
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
|
20 |
+
'visible' => true,
|
21 |
+
'required' => true,
|
22 |
+
'user_defined' => false,
|
23 |
+
'default' => '',
|
24 |
+
'searchable' => false,
|
25 |
+
'filterable' => false,
|
26 |
+
'comparable' => false,
|
27 |
+
'visible_on_front' => false,
|
28 |
+
'unique' => false,
|
29 |
+
'apply_to' => 'subscription',
|
30 |
+
'is_configurable' => false,
|
31 |
+
'used_in_product_listing' => false,
|
32 |
+
'option' => [
|
33 |
+
'values' => [],
|
34 |
+
],
|
35 |
+
]
|
36 |
+
);
|
37 |
+
|
38 |
+
$attributeId = $installer->getAttributeId(
|
39 |
+
Mage_Catalog_Model_Product::ENTITY,
|
40 |
+
'vindi_subscription_plan'
|
41 |
+
);
|
42 |
+
|
43 |
+
$defaultSetId = $installer->getAttributeSetId(Mage_Catalog_Model_Product::ENTITY, 'default');
|
44 |
+
|
45 |
+
$installer->addAttributeGroup(
|
46 |
+
Mage_Catalog_Model_Product::ENTITY,
|
47 |
+
$defaultSetId,
|
48 |
+
'Vindi'
|
49 |
+
);
|
50 |
+
|
51 |
+
//find out the id of the new group
|
52 |
+
$groupId = $installer->getAttributeGroup(
|
53 |
+
Mage_Catalog_Model_Product::ENTITY,
|
54 |
+
$defaultSetId,
|
55 |
+
'Vindi',
|
56 |
+
'attribute_group_id'
|
57 |
+
);
|
58 |
+
|
59 |
+
//assign the attribute to the group and set
|
60 |
+
if ($attributeId > 0) {
|
61 |
+
$installer->addAttributeToSet(
|
62 |
+
Mage_Catalog_Model_Product::ENTITY,
|
63 |
+
$defaultSetId,
|
64 |
+
$groupId,
|
65 |
+
$attributeId
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
$attributes = [
|
70 |
+
'price',
|
71 |
+
'special_price',
|
72 |
+
'special_from_date',
|
73 |
+
'special_to_date',
|
74 |
+
'minimal_price',
|
75 |
+
'cost',
|
76 |
+
'tier_price',
|
77 |
+
'weight',
|
78 |
+
'tax_class_id',
|
79 |
+
];
|
80 |
+
|
81 |
+
foreach ($attributes as $attributeCode) {
|
82 |
+
$applyTo = explode(
|
83 |
+
',',
|
84 |
+
$installer->getAttribute(
|
85 |
+
Mage_Catalog_Model_Product::ENTITY,
|
86 |
+
$attributeCode,
|
87 |
+
'apply_to'
|
88 |
+
)
|
89 |
+
);
|
90 |
+
|
91 |
+
if (! in_array('subscription', $applyTo)) {
|
92 |
+
$applyTo[] = 'subscription';
|
93 |
+
$installer->updateAttribute(
|
94 |
+
Mage_Catalog_Model_Product::ENTITY,
|
95 |
+
$attributeCode,
|
96 |
+
'apply_to',
|
97 |
+
join(',', $applyTo)
|
98 |
+
);
|
99 |
+
}
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
if (! $this->getAttribute('customer', 'vindi_user_code', 'attribute_id')) {
|
104 |
+
$installer->addAttribute('customer', 'vindi_user_code', [
|
105 |
+
'input' => 'text',
|
106 |
+
'type' => 'varchar',
|
107 |
+
'is_visible' => false,
|
108 |
+
'is_unique' => true,
|
109 |
+
'is_required' => false,
|
110 |
+
'sort_order' => 500,
|
111 |
+
'label' => 'Código do Cliente na Vindi',
|
112 |
+
'used_in_forms' => ['adminhtml_customer'],
|
113 |
+
'backend_type' => 'varchar',
|
114 |
+
'default_value' => '',
|
115 |
+
]);
|
116 |
+
}
|
117 |
+
|
118 |
+
$installer->endSetup();
|
app/code/community/Vindi/Subscription/sql/vindi_subscription_setup/upgrade-1.0.0-1.0.1.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$setup = new Mage_Sales_Model_Resource_Setup('core_setup');
|
4 |
+
|
5 |
+
if (! $this->getAttribute(Mage_Sales_Model_Order::ENTITY, 'vindi_subscription_id', 'attribute_id')) {
|
6 |
+
$setup->addAttribute(
|
7 |
+
Mage_Sales_Model_Order::ENTITY,
|
8 |
+
'vindi_subscription_id',
|
9 |
+
[
|
10 |
+
'type' => 'varchar',
|
11 |
+
'input' => 'text',
|
12 |
+
'backend' => '',
|
13 |
+
'frontend' => '',
|
14 |
+
'label' => 'Id da Assinatura Vindi',
|
15 |
+
'class' => '',
|
16 |
+
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
|
17 |
+
'visible' => false,
|
18 |
+
'required' => false,
|
19 |
+
'user_defined' => false,
|
20 |
+
'default' => '',
|
21 |
+
'searchable' => false,
|
22 |
+
'filterable' => false,
|
23 |
+
'comparable' => false,
|
24 |
+
'visible_on_front' => false,
|
25 |
+
'unique' => false,
|
26 |
+
]
|
27 |
+
);
|
28 |
+
}
|
29 |
+
if (! $this->getAttribute(Mage_Sales_Model_Order::ENTITY, 'vindi_subscription_period', 'attribute_id')) {
|
30 |
+
$setup->addAttribute(
|
31 |
+
Mage_Sales_Model_Order::ENTITY,
|
32 |
+
'vindi_subscription_period',
|
33 |
+
[
|
34 |
+
'type' => 'varchar',
|
35 |
+
'input' => 'text',
|
36 |
+
'backend' => '',
|
37 |
+
'frontend' => '',
|
38 |
+
'label' => 'Período da Assinatura Vindi',
|
39 |
+
'class' => '',
|
40 |
+
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
|
41 |
+
'visible' => false,
|
42 |
+
'required' => false,
|
43 |
+
'user_defined' => false,
|
44 |
+
'default' => '',
|
45 |
+
'searchable' => false,
|
46 |
+
'filterable' => false,
|
47 |
+
'comparable' => false,
|
48 |
+
'visible_on_front' => false,
|
49 |
+
'unique' => false,
|
50 |
+
]
|
51 |
+
);
|
52 |
+
}
|
53 |
+
$setup->endSetup();
|
app/code/community/Vindi/Subscription/sql/vindi_subscription_setup/upgrade-1.0.1-1.0.2.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$setup = new Mage_Sales_Model_Resource_Setup('core_setup');
|
4 |
+
|
5 |
+
if (! $this->getAttribute(Mage_Sales_Model_Order::ENTITY, 'vindi_bill_id', 'attribute_id')) {
|
6 |
+
$setup->addAttribute(
|
7 |
+
Mage_Sales_Model_Order::ENTITY,
|
8 |
+
'vindi_bill_id',
|
9 |
+
[
|
10 |
+
'type' => 'varchar',
|
11 |
+
'input' => 'text',
|
12 |
+
'backend' => '',
|
13 |
+
'frontend' => '',
|
14 |
+
'label' => 'Id da Fatura Vindi (vendas avulsas)',
|
15 |
+
'class' => '',
|
16 |
+
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
|
17 |
+
'visible' => false,
|
18 |
+
'required' => false,
|
19 |
+
'user_defined' => false,
|
20 |
+
'default' => '',
|
21 |
+
'searchable' => false,
|
22 |
+
'filterable' => false,
|
23 |
+
'comparable' => false,
|
24 |
+
'visible_on_front' => false,
|
25 |
+
'unique' => false,
|
26 |
+
]
|
27 |
+
);
|
28 |
+
}
|
29 |
+
$setup->endSetup();
|
app/code/community/Vindi/Subscription/sql/vindi_subscription_setup/upgrade-1.0.4-1.0.5.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$setup = $this;
|
4 |
+
$connection = $setup->getConnection();
|
5 |
+
$setup->startSetup();
|
6 |
+
|
7 |
+
if (! $this->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'vindi_product_id', 'attribute_id')) {
|
8 |
+
$setup->addAttribute(
|
9 |
+
Mage_Catalog_Model_Product::ENTITY,
|
10 |
+
'vindi_product_id',
|
11 |
+
[
|
12 |
+
'type' => 'int',
|
13 |
+
'input' => 'text',
|
14 |
+
'backend' => '',
|
15 |
+
'frontend' => '',
|
16 |
+
'label' => 'ID Vindi do produto',
|
17 |
+
'class' => '',
|
18 |
+
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
|
19 |
+
'visible' => true,
|
20 |
+
'required' => true,
|
21 |
+
'user_defined' => false,
|
22 |
+
'default' => '',
|
23 |
+
'searchable' => false,
|
24 |
+
'filterable' => false,
|
25 |
+
'comparable' => false,
|
26 |
+
'visible_on_front' => false,
|
27 |
+
'unique' => false,
|
28 |
+
'apply_to' => 'subscription',
|
29 |
+
'is_configurable' => false,
|
30 |
+
'used_in_product_listing' => false,
|
31 |
+
'option' => [
|
32 |
+
'values' => [],
|
33 |
+
],
|
34 |
+
]
|
35 |
+
);
|
36 |
+
|
37 |
+
$attributeId = $setup->getAttributeId(
|
38 |
+
Mage_Catalog_Model_Product::ENTITY,
|
39 |
+
'vindi_product_id'
|
40 |
+
);
|
41 |
+
|
42 |
+
$defaultSetId = $setup->getAttributeSetId(Mage_Catalog_Model_Product::ENTITY, 'default');
|
43 |
+
|
44 |
+
$setup->addAttributeGroup(
|
45 |
+
Mage_Catalog_Model_Product::ENTITY,
|
46 |
+
$defaultSetId,
|
47 |
+
'Vindi'
|
48 |
+
);
|
49 |
+
|
50 |
+
//find out the id of the new group
|
51 |
+
$groupId = $setup->getAttributeGroup(
|
52 |
+
Mage_Catalog_Model_Product::ENTITY,
|
53 |
+
$defaultSetId,
|
54 |
+
'Vindi',
|
55 |
+
'attribute_group_id'
|
56 |
+
);
|
57 |
+
|
58 |
+
//assign the attribute to the group and set
|
59 |
+
if ($attributeId > 0) {
|
60 |
+
$setup->addAttributeToSet(
|
61 |
+
Mage_Catalog_Model_Product::ENTITY,
|
62 |
+
$defaultSetId,
|
63 |
+
$groupId,
|
64 |
+
$attributeId
|
65 |
+
);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
$setup->endSetup();
|
app/design/adminhtml/base/default/layout/vindi_subscription.xml
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
+
<adminhtml_sales_order_create_index translate="label">
|
4 |
+
<reference name="head">
|
5 |
+
<action method="addItem">
|
6 |
+
<type>skin_css</type>
|
7 |
+
<name>vindi_subscription/css/vindi_subscription.css</name>
|
8 |
+
</action>
|
9 |
+
<action method="addItem">
|
10 |
+
<type>skin_js</type>
|
11 |
+
<name>vindi_subscription/js/vindi_subscription.js</name>
|
12 |
+
</action>
|
13 |
+
</reference>
|
14 |
+
</adminhtml_sales_order_create_index>
|
15 |
+
</layout>
|
app/design/adminhtml/base/default/template/vindi_subscription/payment/form/bankslip.phtml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php $_code = $this->getMethodCode() ?>
|
2 |
+
<div id="payment_form_<?php echo $_code ?>" style="display:none;">
|
3 |
+
<div class="block-payment-bankslip">
|
4 |
+
Um Boleto Bancário será enviado mensalmente para o seu endereço de e-mail.
|
5 |
+
</div>
|
6 |
+
</div>
|
app/design/adminhtml/base/default/template/vindi_subscription/payment/form/cc.phtml
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$code = $this->getMethodCode();
|
3 |
+
$class = 'required-entry';
|
4 |
+
?>
|
5 |
+
<ul class="form-list" id="payment_form_<?php echo $code ?>" style="display:none;">
|
6 |
+
<li>
|
7 |
+
<div class="payment-companies">
|
8 |
+
<?php foreach ($ccs = $this->getCcAvailableTypes() as $typeCode => $typeName) {
|
9 |
+
echo '<img alt="' . $typeName . '" title="' . $typeName . '"
|
10 |
+
src="https://s3.amazonaws.com/recurrent/payment_companies/' . $typeCode . '.png"/>';
|
11 |
+
}
|
12 |
+
?>
|
13 |
+
</div>
|
14 |
+
</li>
|
15 |
+
<?php if ($installments = $this->getInstallments()): ?>
|
16 |
+
<li>
|
17 |
+
<div id="<?php echo $code ?>_cc_type_installments_div" class="wide">
|
18 |
+
<label for="<?php echo $code ?>_cc_cid" class="required">
|
19 |
+
<em>*</em>Parcelas
|
20 |
+
</label>
|
21 |
+
|
22 |
+
<div class="input-box">
|
23 |
+
<select name="payment[cc_installments]" class="required-entry">
|
24 |
+
<?php echo $installments; ?>
|
25 |
+
</select>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
</li>
|
29 |
+
<?php endif; ?>
|
30 |
+
<?php if ($savedCc = $this->getSavedCc()): ?>
|
31 |
+
<?php $class = 'not-required-entry';?>
|
32 |
+
<li class="payment-choice-saved-cc payment-choice">
|
33 |
+
<label class="label-choice label-choice-saved-cc">
|
34 |
+
<input type="radio" name="payment[cc_choice]" checked="checked" value="saved"/>
|
35 |
+
Usar cartão salvo
|
36 |
+
</label>
|
37 |
+
|
38 |
+
<div class="block-choice-saved-cc block-choice">
|
39 |
+
<img alt="<?php echo $ccType = $savedCc['payment_company']['name']; ?>"
|
40 |
+
title="<?php echo $ccType; ?>"
|
41 |
+
src="https://s3.amazonaws.com/recurrent/payment_companies/<?php echo $savedCc['payment_company']['code']; ?>.png"/>
|
42 |
+
|
43 |
+
<div class="block-choice-saved-cc-details">
|
44 |
+
<div class="nowrap block-choice-saved-cc-holder-name">
|
45 |
+
<span class="text-upper">Portador</span>
|
46 |
+
<span title="<?php echo $name = $savedCc['holder_name']; ?>"><?php echo $name ?></span>
|
47 |
+
</div>
|
48 |
+
<span class="nowrap">
|
49 |
+
<span class="text-upper">Final</span>
|
50 |
+
<?php echo $savedCc['card_number_last_four']; ?>
|
51 |
+
</span>
|
52 |
+
<span class="nowrap">
|
53 |
+
<span class="text-upper">Validade</span>
|
54 |
+
<?php echo date("m/Y", strtotime($savedCc['card_expiration'])); ?>
|
55 |
+
</span>
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
</li>
|
59 |
+
<?php endif; ?>
|
60 |
+
<li class="payment-choice-new-cc payment-choice">
|
61 |
+
<?php if ($savedCc): ?>
|
62 |
+
|
63 |
+
<label class="label-choice label-choice-new-cc">
|
64 |
+
<input type="radio" name="payment[cc_choice]" value="new"/>
|
65 |
+
Novo cartão de crédito
|
66 |
+
</label>
|
67 |
+
<?php else : ?>
|
68 |
+
<input type="hidden" name="payment[cc_choice]" value="new"/>
|
69 |
+
<?php endif; ?>
|
70 |
+
|
71 |
+
<div class="block-choice-new-cc block-choice" <?php if ($savedCc): ?>style="display:none;"<?php endif; ?>>
|
72 |
+
<div class="wide">
|
73 |
+
<label for="<?php echo $code ?>_cc_owner" class="required">
|
74 |
+
<em>*</em><?php echo $this->__('Name on Card') ?>
|
75 |
+
</label>
|
76 |
+
|
77 |
+
<div class="input-box">
|
78 |
+
<input type="text" title="<?php echo $this->__('Name on Card') ?>"
|
79 |
+
class="input-text <?php echo $class; ?>"
|
80 |
+
id="<?php echo $code ?>_cc_owner" name="payment[cc_owner]"
|
81 |
+
value="<?php echo $this->escapeHtml($this->getInfoData('cc_owner')) ?>"/>
|
82 |
+
</div>
|
83 |
+
</div>
|
84 |
+
<div class="wide">
|
85 |
+
<label for="<?php echo $code ?>_cc_type" class="required">
|
86 |
+
<em>*</em><?php echo $this->__('Credit Card Type') ?>
|
87 |
+
</label>
|
88 |
+
|
89 |
+
<div class="input-box">
|
90 |
+
<select id="<?php echo $code ?>_cc_type" name="payment[cc_type]" class="<?php echo $class; ?>"
|
91 |
+
title="<?php echo $this->__('Credit Card Type') ?>">
|
92 |
+
<option value=""><?php echo $this->__('--Please Select--') ?></option>
|
93 |
+
<?php foreach ($this->getCcAvailableTypes() as $typeCode => $typeName): ?>
|
94 |
+
<option value="<?php echo $typeCode ?>">
|
95 |
+
<?php echo $typeName ?>
|
96 |
+
</option>
|
97 |
+
<?php endforeach ?>
|
98 |
+
</select>
|
99 |
+
</div>
|
100 |
+
</div>
|
101 |
+
<div class="wide">
|
102 |
+
<label for="<?php echo $code ?>_cc_number" class="required">
|
103 |
+
<em>*</em><?php echo $this->__('Credit Card Number') ?>
|
104 |
+
</label>
|
105 |
+
|
106 |
+
<div class="input-box">
|
107 |
+
<input type="text" id="<?php echo $code ?>_cc_number" name="payment[cc_number]"
|
108 |
+
title="<?php echo $this->__('Credit Card Number') ?>" class="input-text" value=""
|
109 |
+
placeholder="•••• •••• •••• ••••"/>
|
110 |
+
</div>
|
111 |
+
</div>
|
112 |
+
<div id="<?php echo $code ?>_cc_type_exp_div" class="wide">
|
113 |
+
<label for="<?php echo $code ?>_expiration" class="required">
|
114 |
+
<em>*</em><?php echo $this->__('Expiration Date') ?>
|
115 |
+
</label>
|
116 |
+
|
117 |
+
<div class="input-box">
|
118 |
+
<div class="v-fix">
|
119 |
+
<select id="<?php echo $code ?>_expiration" name="payment[cc_exp_month]"
|
120 |
+
class="month validate-cc-exp <?php echo $class; ?>">
|
121 |
+
<?php foreach ($this->getCcMonths() as $k => $v): ?>
|
122 |
+
<option value="<?php echo $k ? $k : '' ?>">
|
123 |
+
<?php echo $v ?>
|
124 |
+
</option>
|
125 |
+
<?php endforeach ?>
|
126 |
+
</select>
|
127 |
+
</div>
|
128 |
+
<div class="v-fix">
|
129 |
+
<select id="<?php echo $code ?>_expiration_yr" name="payment[cc_exp_year]"
|
130 |
+
class="year <?php echo $class; ?>">
|
131 |
+
<?php foreach ($this->getCcYears() as $k => $v): ?>
|
132 |
+
<option value="<?php echo $k ? $k : '' ?>">
|
133 |
+
<?php echo $v ?>
|
134 |
+
</option>
|
135 |
+
<?php endforeach ?>
|
136 |
+
</select>
|
137 |
+
</div>
|
138 |
+
</div>
|
139 |
+
</div>
|
140 |
+
<div id="<?php echo $code ?>_cc_type_cvv_div" class="wide">
|
141 |
+
<label for="<?php echo $code ?>_cc_cid" class="required">
|
142 |
+
<em>*</em>Número de Segurança
|
143 |
+
</label>
|
144 |
+
|
145 |
+
<div class="input-box">
|
146 |
+
<div class="v-fix">
|
147 |
+
<input type="text" title="Número de Segurança"
|
148 |
+
class="input-text cvv <?php echo $class; ?>" id="<?php echo $code ?>_cc_cid"
|
149 |
+
name="payment[cc_cid]" value=""/>
|
150 |
+
</div>
|
151 |
+
</div>
|
152 |
+
</div>
|
153 |
+
</div>
|
154 |
+
</li>
|
155 |
+
</ul>
|
156 |
+
|
157 |
+
<?php if ($savedCc): ?>
|
158 |
+
<script type="text/javascript">
|
159 |
+
var VindiSubscriptionCC = new VindiSubscriptionCreditCard({
|
160 |
+
paymentChoiceSavedCcSelector: '.payment-choice-new-cc',
|
161 |
+
paymentChoiceNewCcSelector: '.payment-choice-saved-cc',
|
162 |
+
blockChoiceSavedCcSelector: '.block-choice-saved-cc',
|
163 |
+
blockChoiceNewCcSelector: '.block-choice-new-cc',
|
164 |
+
});
|
165 |
+
</script>
|
166 |
+
<?php endif; ?>
|
app/design/frontend/base/default/layout/vindi_subscription.xml
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
+
<!--OSC 6-->
|
4 |
+
<onestepcheckout_index_index translate="label">
|
5 |
+
<reference name="head">
|
6 |
+
<action method="addItem">
|
7 |
+
<type>skin_css</type>
|
8 |
+
<name>vindi_subscription/css/vindi_subscription.css</name>
|
9 |
+
</action>
|
10 |
+
<action method="addItem">
|
11 |
+
<type>skin_js</type>
|
12 |
+
<name>vindi_subscription/js/vindi_subscription.js</name>
|
13 |
+
</action>
|
14 |
+
</reference>
|
15 |
+
</onestepcheckout_index_index>
|
16 |
+
<!--OSC 4-->
|
17 |
+
<onepagecheckout_index_index translate="label">
|
18 |
+
<reference name="head">
|
19 |
+
<action method="addItem">
|
20 |
+
<type>skin_css</type>
|
21 |
+
<name>vindi_subscription/css/vindi_subscription.css</name>
|
22 |
+
</action>
|
23 |
+
<action method="addItem">
|
24 |
+
<type>skin_js</type>
|
25 |
+
<name>vindi_subscription/js/vindi_subscription.js</name>
|
26 |
+
</action>
|
27 |
+
</reference>
|
28 |
+
</onepagecheckout_index_index>
|
29 |
+
<!--Native Checkout Page-->
|
30 |
+
<checkout_onepage_index translate="label">
|
31 |
+
<reference name="head">
|
32 |
+
<action method="addItem">
|
33 |
+
<type>skin_css</type>
|
34 |
+
<name>vindi_subscription/css/vindi_subscription.css</name>
|
35 |
+
</action>
|
36 |
+
<action method="addItem">
|
37 |
+
<type>skin_js</type>
|
38 |
+
<name>vindi_subscription/js/vindi_subscription.js</name>
|
39 |
+
</action>
|
40 |
+
</reference>
|
41 |
+
</checkout_onepage_index>
|
42 |
+
<customer_account_edit translate="label">
|
43 |
+
<reference name="head">
|
44 |
+
<action method="addItem">
|
45 |
+
<type>skin_css</type>
|
46 |
+
<name>vindi_subscription/css/vindi_subscription.css</name>
|
47 |
+
</action>
|
48 |
+
<action method="addItem">
|
49 |
+
<type>skin_js</type>
|
50 |
+
<name>vindi_subscription/js/vindi_subscription.js</name>
|
51 |
+
</action>
|
52 |
+
</reference>
|
53 |
+
</customer_account_edit>
|
54 |
+
<customer_address_form translate="label">
|
55 |
+
<reference name="head">
|
56 |
+
<action method="addItem">
|
57 |
+
<type>skin_css</type>
|
58 |
+
<name>vindi_subscription/css/vindi_subscription.css</name>
|
59 |
+
</action>
|
60 |
+
<action method="addItem">
|
61 |
+
<type>skin_js</type>
|
62 |
+
<name>vindi_subscription/js/vindi_subscription.js</name>
|
63 |
+
</action>
|
64 |
+
</reference>
|
65 |
+
</customer_address_form>
|
66 |
+
<customer_account_create>
|
67 |
+
<reference name="head">
|
68 |
+
<action method="addItem">
|
69 |
+
<type>skin_css</type>
|
70 |
+
<name>vindi_subscription/css/vindi_subscription.css</name>
|
71 |
+
</action>
|
72 |
+
<action method="addItem">
|
73 |
+
<type>skin_js</type>
|
74 |
+
<name>vindi_subscription/js/vindi_subscription.js</name>
|
75 |
+
</action>
|
76 |
+
</reference>
|
77 |
+
</customer_account_create>
|
78 |
+
</layout>
|
app/design/frontend/base/default/template/vindi_subscription/payment/form/bankslip.phtml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php $_code = $this->getMethodCode() ?>
|
2 |
+
<div id="payment_form_<?php echo $_code ?>" style="display:none;">
|
3 |
+
<div class="block-payment-bankslip">
|
4 |
+
Um Boleto Bancário será enviado mensalmente para o seu endereço de e-mail.
|
5 |
+
</div>
|
6 |
+
</div>
|
app/design/frontend/base/default/template/vindi_subscription/payment/form/cc.phtml
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php $code = $this->getMethodCode(); ?>
|
2 |
+
<ul class="form-list" id="payment_form_<?php echo $code ?>" style="display:none;">
|
3 |
+
<li>
|
4 |
+
<div class="payment-companies">
|
5 |
+
<?php foreach ($ccs = $this->getCcAvailableTypes() as $typeCode => $typeName) {
|
6 |
+
echo '<img alt="' . $typeName . '" title="' . $typeName . '"
|
7 |
+
src="https://s3.amazonaws.com/recurrent/payment_companies/' . $typeCode . '.png"/>';
|
8 |
+
}
|
9 |
+
?>
|
10 |
+
</div>
|
11 |
+
</li>
|
12 |
+
<?php if($installments = $this->getInstallments()): ?>
|
13 |
+
<li>
|
14 |
+
<div id="<?php echo $code ?>_cc_type_installments_div" class="wide">
|
15 |
+
<label for="<?php echo $code ?>_cc_cid" class="required">
|
16 |
+
<em>*</em>Parcelas
|
17 |
+
</label>
|
18 |
+
|
19 |
+
<div class="input-box">
|
20 |
+
<select name="payment[cc_installments]" class="required-entry">
|
21 |
+
<?php echo $installments; ?>
|
22 |
+
</select>
|
23 |
+
</div>
|
24 |
+
</div>
|
25 |
+
</li>
|
26 |
+
<?php endif; ?>
|
27 |
+
<?php if ($savedCc = $this->getSavedCc()): ?>
|
28 |
+
<li class="payment-choice-saved-cc payment-choice">
|
29 |
+
<label class="label-choice label-choice-saved-cc">
|
30 |
+
<input type="radio" name="payment[cc_choice]" checked="checked" value="saved"/>
|
31 |
+
Usar cartão salvo
|
32 |
+
</label>
|
33 |
+
|
34 |
+
<div class="block-choice-saved-cc block-choice">
|
35 |
+
<img alt="<?php echo $ccType = $savedCc['payment_company']['name']; ?>"
|
36 |
+
title="<?php echo $ccType; ?>"
|
37 |
+
src="https://s3.amazonaws.com/recurrent/payment_companies/<?php echo $savedCc['payment_company']['code']; ?>.png"/>
|
38 |
+
|
39 |
+
<div class="block-choice-saved-cc-details">
|
40 |
+
<div class="nowrap block-choice-saved-cc-holder-name">
|
41 |
+
<span class="text-upper">Portador</span>
|
42 |
+
<span title="<?php echo $name = $savedCc['holder_name']; ?>"><?php echo $name ?></span>
|
43 |
+
</div>
|
44 |
+
<span class="nowrap">
|
45 |
+
<span class="text-upper">Final</span>
|
46 |
+
<?php echo $savedCc['card_number_last_four']; ?>
|
47 |
+
</span>
|
48 |
+
<span class="nowrap">
|
49 |
+
<span class="text-upper">Validade</span>
|
50 |
+
<?php echo date("m/Y", strtotime($savedCc['card_expiration'])); ?>
|
51 |
+
</span>
|
52 |
+
</div>
|
53 |
+
</div>
|
54 |
+
</li>
|
55 |
+
<?php endif; ?>
|
56 |
+
<li class="payment-choice-new-cc payment-choice">
|
57 |
+
<?php if ($savedCc): ?>
|
58 |
+
|
59 |
+
<label class="label-choice label-choice-new-cc">
|
60 |
+
<input type="radio" name="payment[cc_choice]" value="new"/>
|
61 |
+
Novo cartão de crédito
|
62 |
+
</label>
|
63 |
+
<?php else : ?>
|
64 |
+
<input type="hidden" name="payment[cc_choice]" value="new"/>
|
65 |
+
<?php endif; ?>
|
66 |
+
|
67 |
+
<div class="block-choice-new-cc block-choice" <?php if ($savedCc): ?>style="display:none;"<?php endif; ?>>
|
68 |
+
<div class="wide">
|
69 |
+
<label for="<?php echo $code ?>_cc_owner" class="required">
|
70 |
+
<em>*</em><?php echo $this->__('Name on Card') ?>
|
71 |
+
</label>
|
72 |
+
|
73 |
+
<div class="input-box">
|
74 |
+
<input type="text" title="<?php echo $this->__('Name on Card') ?>"
|
75 |
+
class="input-text required-entry"
|
76 |
+
id="<?php echo $code ?>_cc_owner" name="payment[cc_owner]"
|
77 |
+
value="<?php echo $this->escapeHtml($this->getInfoData('cc_owner')) ?>"/>
|
78 |
+
</div>
|
79 |
+
</div>
|
80 |
+
<div class="wide">
|
81 |
+
<label for="<?php echo $code ?>_cc_type" class="required">
|
82 |
+
<em>*</em><?php echo $this->__('Credit Card Type') ?>
|
83 |
+
</label>
|
84 |
+
|
85 |
+
<div class="input-box">
|
86 |
+
<select id="<?php echo $code ?>_cc_type" name="payment[cc_type]" class="required-entry"
|
87 |
+
title="<?php echo $this->__('Credit Card Type') ?>">
|
88 |
+
<option value=""><?php echo $this->__('--Please Select--') ?></option>
|
89 |
+
<?php foreach ($this->getCcAvailableTypes() as $typeCode => $typeName): ?>
|
90 |
+
<option value="<?php echo $typeCode ?>">
|
91 |
+
<?php echo $typeName ?>
|
92 |
+
</option>
|
93 |
+
<?php endforeach ?>
|
94 |
+
</select>
|
95 |
+
</div>
|
96 |
+
</div>
|
97 |
+
<div class="wide">
|
98 |
+
<label for="<?php echo $code ?>_cc_number" class="required">
|
99 |
+
<em>*</em><?php echo $this->__('Credit Card Number') ?>
|
100 |
+
</label>
|
101 |
+
|
102 |
+
<div class="input-box">
|
103 |
+
<input type="text" id="<?php echo $code ?>_cc_number" name="payment[cc_number]"
|
104 |
+
title="<?php echo $this->__('Credit Card Number') ?>" class="input-text" value=""
|
105 |
+
placeholder="•••• •••• •••• ••••"/>
|
106 |
+
</div>
|
107 |
+
</div>
|
108 |
+
<div id="<?php echo $code ?>_cc_type_exp_div" class="wide">
|
109 |
+
<label for="<?php echo $code ?>_expiration" class="required">
|
110 |
+
<em>*</em><?php echo $this->__('Expiration Date') ?>
|
111 |
+
</label>
|
112 |
+
|
113 |
+
<div class="input-box">
|
114 |
+
<div class="v-fix">
|
115 |
+
<select id="<?php echo $code ?>_expiration" name="payment[cc_exp_month]"
|
116 |
+
class="month validate-cc-exp required-entry">
|
117 |
+
<?php foreach ($this->getCcMonths() as $k => $v): ?>
|
118 |
+
<option value="<?php echo $k ? $k : '' ?>">
|
119 |
+
<?php echo $v ?>
|
120 |
+
</option>
|
121 |
+
<?php endforeach ?>
|
122 |
+
</select>
|
123 |
+
</div>
|
124 |
+
<div class="v-fix">
|
125 |
+
<select id="<?php echo $code ?>_expiration_yr" name="payment[cc_exp_year]"
|
126 |
+
class="year required-entry">
|
127 |
+
<?php foreach ($this->getCcYears() as $k => $v): ?>
|
128 |
+
<option value="<?php echo $k ? $k : '' ?>">
|
129 |
+
<?php echo $v ?>
|
130 |
+
</option>
|
131 |
+
<?php endforeach ?>
|
132 |
+
</select>
|
133 |
+
</div>
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
<div id="<?php echo $code ?>_cc_type_cvv_div" class="wide">
|
137 |
+
<label for="<?php echo $code ?>_cc_cid" class="required">
|
138 |
+
<em>*</em><?php echo $this->__('Card Verification Number') ?>
|
139 |
+
</label>
|
140 |
+
|
141 |
+
<div class="input-box">
|
142 |
+
<div class="v-fix">
|
143 |
+
<input type="text" title="<?php echo $this->__('Card Verification Number') ?>"
|
144 |
+
class="input-text cvv required-entry" id="<?php echo $code ?>_cc_cid"
|
145 |
+
name="payment[cc_cid]" value=""/>
|
146 |
+
</div>
|
147 |
+
<a href="#" class="cvv-what-is-this"><?php echo $this->__('What is this?') ?></a>
|
148 |
+
</div>
|
149 |
+
</div>
|
150 |
+
</div>
|
151 |
+
</li>
|
152 |
+
</ul>
|
153 |
+
|
154 |
+
<?php if ($savedCc): ?>
|
155 |
+
<script type="text/javascript">
|
156 |
+
var VindiSubscriptionCC = new VindiSubscriptionCreditCard({
|
157 |
+
paymentChoiceSavedCcSelector: '.payment-choice-new-cc',
|
158 |
+
paymentChoiceNewCcSelector: '.payment-choice-saved-cc',
|
159 |
+
blockChoiceSavedCcSelector: '.block-choice-saved-cc',
|
160 |
+
blockChoiceNewCcSelector: '.block-choice-new-cc',
|
161 |
+
});
|
162 |
+
</script>
|
163 |
+
<?php endif; ?>
|
app/etc/modules/Vindi_Subscription.xml
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Vindi_Subscription>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
<depends>
|
8 |
+
<Mage_Payment/>
|
9 |
+
<Mage_Adminhtml/>
|
10 |
+
<Mage_Sales/>
|
11 |
+
</depends>
|
12 |
+
</Vindi_Subscription>
|
13 |
+
</modules>
|
14 |
+
</config>
|
package.xml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Vindi</name>
|
4 |
+
<version>1.0.7</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license>GPLv3</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>A integração do módulo da Vindi permite criação e gestão de planos e assinaturas através do Magento de forma transparente.</summary>
|
10 |
+
<description>A integração do módulo da Vindi permite criação e gestão de planos e assinaturas através do Magento de forma transparente.</description>
|
11 |
+
<notes>version 1.0.7</notes>
|
12 |
+
<authors><author><name>Tales Galvao</name><user>talesgalvao</user><email>tales.galvao@gmail.com</email></author><author><name>Erico Pedroso</name><user>ericopedroso</user><email>erico.pedroso@vindi.com.br</email></author></authors>
|
13 |
+
<date>2016-01-20</date>
|
14 |
+
<time>13:27:54</time>
|
15 |
+
<contents><target name="magecommunity"><dir name="Vindi"><dir name="Subscription"><dir name="Block"><dir name="Config"><file name="Information.php" hash="b324090de6fee25d09572d825709a6a9"/></dir><dir name="Form"><file name="BankSlip.php" hash="bce644dc03d2ed25389dceb21f9762ad"/><file name="Cc.php" hash="d95c0f954ea18ddc04fe0e34734eeae9"/></dir></dir><dir name="Helper"><file name="Api.php" hash="19f742ac0d9af9de02c0731391490026"/><file name="Data.php" hash="d1f0d18d79647a11c991bac60ee2ef44"/><file name="WebhookHandler.php" hash="6daa02ca4572ceedc274e12d92a5abed"/></dir><dir name="Model"><file name="BankSlip.php" hash="f00508693ad4a86ec43b373a5252e942"/><dir name="Config"><file name="Installments.php" hash="0f899e0267b0b0f1d17acaf06a65e493"/><file name="Shippingmethod.php" hash="5afab77a4c4e3a22992350ac41dc57b5"/></dir><file name="CreditCard.php" hash="cec7198003d7ad59fc1b5b45ff586e8f"/><file name="Observer.php" hash="e508b5c67b8a4a5db510939d41a67846"/><dir name="Product"><dir name="Attribute"><file name="Plan.php" hash="b1f3084edcd57f0d480d1376c4d90e4b"/></dir><file name="Type.php" hash="9bb3c00df44019ced9ad1682a2d3c2be"/></dir></dir><dir name="Trait"><file name="PaymentMethod.php" hash="092ecf2cf083bf4c7cc6cbf0d38ad6d3"/></dir><dir name="controllers"><file name="WebhookController.php" hash="d4886b956fe54d7ae8a38b3be22897d4"/></dir><dir name="etc"><file name="adminhtml.xml" hash="19f4eb5c16d561805f7b017186e2140b"/><file name="config.xml" hash="bcc392fdb18b50d0be8e4fd392f4e76f"/><file name="system.xml" hash="c660c9607f6dc584dd93247ef8c3aa7f"/></dir><dir name="sql"><dir name="vindi_subscription_setup"><file name="install-1.0.0.php" hash="cc7722665a2f587d8bf8310a94503353"/><file name="upgrade-1.0.0-1.0.1.php" hash="b4f107c231dd4cdb9e950a1c98c35a3d"/><file name="upgrade-1.0.1-1.0.2.php" hash="a018618fe25d0b3c45d1137a9b07aa7d"/><file name="upgrade-1.0.4-1.0.5.php" hash="acd0ba386942f42bad1ef792e8ac7aa1"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Vindi_Subscription.xml" hash="64a2addef728637da8dcd80a2b3c3415"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="vindi_subscription"><dir name="payment"><dir name="form"><file name="bankslip.phtml" hash="df328f9149c101a6ba5fada0bbca9ef4"/><file name="cc.phtml" hash="07d522a86a3cb64c8d912fd4d431f142"/></dir></dir></dir></dir><dir name="layout"><file name="vindi_subscription.xml" hash="f6aea64fedba97321b653f3ddc83ab11"/></dir></dir></dir></dir><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="template"><dir name="vindi_subscription"><dir name="payment"><dir name="form"><file name="bankslip.phtml" hash="df328f9149c101a6ba5fada0bbca9ef4"/><file name="cc.phtml" hash="3f2cc2ce886f9488a456b04e2c3a4c96"/></dir></dir></dir></dir><dir name="layout"><file name="vindi_subscription.xml" hash="ab06d89e538b954ce956f5a6674f83c0"/></dir></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="vindi_subscription"><dir name="css"><file name="vindi_subscription.css" hash="ac7c5eab0913804e1cb90d5e9474e6a0"/></dir><dir name="js"><file name="vindi_subscription.js" hash="7d33f5ced68caf2fbcc3147f32d5c8fb"/></dir></dir></dir></dir></dir></target></contents>
|
16 |
+
<compatible/>
|
17 |
+
<dependencies><required><php><min>5.5.0</min><max>7.0.1</max></php></required></dependencies>
|
18 |
+
</package>
|
skin/frontend/base/default/vindi_subscription/css/vindi_subscription.css
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.payment-companies {
|
2 |
+
margin: 10px 0;
|
3 |
+
text-align: center;
|
4 |
+
}
|
5 |
+
|
6 |
+
.payment-companies img {
|
7 |
+
width: 50px;
|
8 |
+
display: inline-block;
|
9 |
+
}
|
10 |
+
|
11 |
+
.block-choice {
|
12 |
+
margin: 10px auto;
|
13 |
+
}
|
14 |
+
|
15 |
+
.block-payment-bankslip, .block-choice-saved-cc {
|
16 |
+
font-weight: bold;
|
17 |
+
background-color: #eee;
|
18 |
+
padding: 10px;
|
19 |
+
border: 1px solid #ccc;
|
20 |
+
}
|
21 |
+
|
22 |
+
.block-choice-saved-cc {
|
23 |
+
position: relative;
|
24 |
+
overflow: hidden;
|
25 |
+
}
|
26 |
+
|
27 |
+
.block-choice-saved-cc img {
|
28 |
+
width: 50px;
|
29 |
+
margin: 5px 0;
|
30 |
+
position: absolute;
|
31 |
+
}
|
32 |
+
|
33 |
+
.block-choice-saved-cc .block-choice-saved-cc-details {
|
34 |
+
margin-left: 60px;
|
35 |
+
}
|
36 |
+
|
37 |
+
.block-choice-saved-cc-holder-name {
|
38 |
+
overflow: hidden;
|
39 |
+
text-overflow: ellipsis;
|
40 |
+
}
|
41 |
+
|
42 |
+
.payment-choice {
|
43 |
+
margin: 16px 0 !important;
|
44 |
+
background-color: inherit;
|
45 |
+
}
|
46 |
+
|
47 |
+
.label-choice {
|
48 |
+
font-weight: normal;
|
49 |
+
font-size: 1.1em;
|
50 |
+
}
|
51 |
+
|
52 |
+
.text-upper {
|
53 |
+
font-size: 0.8em;
|
54 |
+
text-transform: uppercase;
|
55 |
+
font-weight: normal;
|
56 |
+
}
|
skin/frontend/base/default/vindi_subscription/js/vindi_subscription.js
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
VindiSubscriptionCreditCard = Class.create();
|
2 |
+
VindiSubscriptionCreditCard.prototype = {
|
3 |
+
initialize: function (config) {
|
4 |
+
var self = this;
|
5 |
+
|
6 |
+
self.paymentChoiceSavedCc = $$(config.paymentChoiceSavedCcSelector).first();
|
7 |
+
self.paymentChoiceNewCc = $$(config.paymentChoiceNewCcSelector).first();
|
8 |
+
self.blockChoiceSavedCc = $$(config.blockChoiceSavedCcSelector).first();
|
9 |
+
self.blockChoiceNewCc = $$(config.blockChoiceNewCcSelector).first();
|
10 |
+
|
11 |
+
self.initObservers();
|
12 |
+
},
|
13 |
+
|
14 |
+
initObservers: function () {
|
15 |
+
var self = this;
|
16 |
+
|
17 |
+
self.paymentChoiceSavedCc.observe('change', self.onPaymentChoiceSaved.bind(self));
|
18 |
+
self.paymentChoiceNewCc.observe('change', self.onPaymentChoiceNew.bind(self));
|
19 |
+
},
|
20 |
+
|
21 |
+
onPaymentChoiceSaved: function () {
|
22 |
+
var self = this;
|
23 |
+
|
24 |
+
self.togglePaymentChoices(self.blockChoiceSavedCc, self.blockChoiceNewCc);
|
25 |
+
},
|
26 |
+
|
27 |
+
onPaymentChoiceNew: function () {
|
28 |
+
var self = this;
|
29 |
+
|
30 |
+
self.togglePaymentChoices(self.blockChoiceNewCc, self.blockChoiceSavedCc);
|
31 |
+
},
|
32 |
+
|
33 |
+
/*
|
34 |
+
======================================================
|
35 |
+
--------------------SHOW/HIDE functions---------------
|
36 |
+
======================================================
|
37 |
+
*/
|
38 |
+
togglePaymentChoices: function (hide, show) {
|
39 |
+
var self = this;
|
40 |
+
|
41 |
+
self.hideContainer(hide);
|
42 |
+
self.showContainer(show);
|
43 |
+
},
|
44 |
+
|
45 |
+
showContainer: function (container) {
|
46 |
+
var self = this;
|
47 |
+
|
48 |
+
container.setStyle({'display': ''});
|
49 |
+
var newHeight = self.getElementHeight(container);
|
50 |
+
this.applyEffect(container, newHeight, 0.5, function () {
|
51 |
+
container.setStyle({'height': ''});
|
52 |
+
});
|
53 |
+
},
|
54 |
+
|
55 |
+
hideContainer: function (container) {
|
56 |
+
var self = this;
|
57 |
+
|
58 |
+
self.applyEffect(container, 0, 0.5, function () {
|
59 |
+
container.setStyle({'display': 'none'});
|
60 |
+
});
|
61 |
+
},
|
62 |
+
|
63 |
+
applyEffect: function (element, newHeight, duration, afterFinish) {
|
64 |
+
if (element.effect) {
|
65 |
+
element.effect.cancel();
|
66 |
+
}
|
67 |
+
var afterFinishFn = afterFinish || Prototype.emptyFunction;
|
68 |
+
element.effect = new Effect.Morph(element, {
|
69 |
+
style: {
|
70 |
+
'height': newHeight + 'px'
|
71 |
+
},
|
72 |
+
duration: duration,
|
73 |
+
afterFinish: function () {
|
74 |
+
delete element.effect;
|
75 |
+
afterFinishFn();
|
76 |
+
}
|
77 |
+
});
|
78 |
+
},
|
79 |
+
|
80 |
+
getElementHeight: function (element) {
|
81 |
+
element = $(element);
|
82 |
+
var origDimensions = element.getDimensions();
|
83 |
+
var origHeight = element.style.height;
|
84 |
+
var origDisplay = element.style.display;
|
85 |
+
var origVisibility = element.style.visibility;
|
86 |
+
element.setStyle({
|
87 |
+
'height': '',
|
88 |
+
'display': '',
|
89 |
+
'visibility': 'hidden'
|
90 |
+
});
|
91 |
+
var height = Math.max(element.getDimensions()['height'], origDimensions['height']);
|
92 |
+
element.setStyle({
|
93 |
+
'height': origHeight,
|
94 |
+
'display': origDisplay,
|
95 |
+
'visibility': origVisibility
|
96 |
+
});
|
97 |
+
return height;
|
98 |
+
}
|
99 |
+
};
|