diff --git a/app/code/community/Mollie/Mpm/Block/Payment/Form/CreditcardComponents.php b/app/code/community/Mollie/Mpm/Block/Payment/Form/CreditcardComponents.php
new file mode 100644
index 00000000..82d5cdd1
--- /dev/null
+++ b/app/code/community/Mollie/Mpm/Block/Payment/Form/CreditcardComponents.php
@@ -0,0 +1,11 @@
+setTemplate('mollie/mpm/payment/form/creditcard-components.phtml');
+ }
+}
\ No newline at end of file
diff --git a/app/code/community/Mollie/Mpm/Model/Client/Orders.php b/app/code/community/Mollie/Mpm/Model/Client/Orders.php
index 82dbf4b8..e28e82f8 100644
--- a/app/code/community/Mollie/Mpm/Model/Client/Orders.php
+++ b/app/code/community/Mollie/Mpm/Model/Client/Orders.php
@@ -110,6 +110,10 @@ public function startTransaction(Mage_Sales_Model_Order $order)
$orderData['payment']['dueDate'] = $this->mollieHelper->getBanktransferDueDate($storeId);
}
+ if ($method == 'creditcard' && isset($additionalData['card_token'])) {
+ $orderData['payment']['cardToken'] = $additionalData['card_token'];
+ }
+
if (isset($additionalData['limited_methods'])) {
$orderData['method'] = $additionalData['limited_methods'];
}
diff --git a/app/code/community/Mollie/Mpm/Model/Client/Payments.php b/app/code/community/Mollie/Mpm/Model/Client/Payments.php
index 52eb8a37..cd2a2efa 100644
--- a/app/code/community/Mollie/Mpm/Model/Client/Payments.php
+++ b/app/code/community/Mollie/Mpm/Model/Client/Payments.php
@@ -98,6 +98,10 @@ public function startTransaction(Mage_Sales_Model_Order $order)
$paymentData['billingEmail'] = $order->getCustomerEmail();
}
+ if ($method == 'creditcard' && isset($additionalData['card_token'])) {
+ $paymentData['cardToken'] = $additionalData['card_token'];
+ }
+
if (!$order->getIsVirtual() && $order->hasData('shipping_address_id')) {
$paymentData['shippingAddress'] = $this->getAddressLine($order->getShippingAddress());
}
diff --git a/app/code/community/Mollie/Mpm/Model/Method/Abstract.php b/app/code/community/Mollie/Mpm/Model/Method/Abstract.php
index 1fe95548..30b747fe 100644
--- a/app/code/community/Mollie/Mpm/Model/Method/Abstract.php
+++ b/app/code/community/Mollie/Mpm/Model/Method/Abstract.php
@@ -70,6 +70,7 @@ public function assignData($data)
{
parent::assignData($data);
$this->getInfoInstance()->setAdditionalInformation('selected_issuer', null);
+ $this->getInfoInstance()->setAdditionalInformation('card_token', null);
return $this;
}
}
\ No newline at end of file
diff --git a/app/code/community/Mollie/Mpm/Model/Method/Creditcard.php b/app/code/community/Mollie/Mpm/Model/Method/Creditcard.php
index 3d01c673..2005db8a 100644
--- a/app/code/community/Mollie/Mpm/Model/Method/Creditcard.php
+++ b/app/code/community/Mollie/Mpm/Model/Method/Creditcard.php
@@ -49,4 +49,26 @@ class Mollie_Mpm_Model_Method_Creditcard extends Mollie_Mpm_Model_Method_Abstrac
*/
protected $_paymentMethod = self::PAYMENT_METHOD;
+ /**
+ * Type of block that generates method form
+ *
+ * @var string
+ */
+ protected $_formBlockType = 'mpm/payment_form_creditcardComponents';
+
+ /**
+ * @param mixed $data
+ *
+ * @return $this|Mage_Payment_Model_Info
+ * @throws Mage_Core_Exception
+ */
+ public function assignData($data)
+ {
+ parent::assignData($data);
+
+ $cardToken = Mage::app()->getRequest()->getParam('cardToken');
+ $this->getInfoInstance()->setAdditionalInformation('card_token', $cardToken);
+
+ return $this;
+ }
}
diff --git a/app/code/community/Mollie/Mpm/Model/Observer.php b/app/code/community/Mollie/Mpm/Model/Observer.php
index 13b31920..7e37d8d9 100644
--- a/app/code/community/Mollie/Mpm/Model/Observer.php
+++ b/app/code/community/Mollie/Mpm/Model/Observer.php
@@ -159,4 +159,28 @@ public function restoreQuoteWhenReturningFromMollie(Varien_Event_Observer $obser
Mage::logException($e);
}
}
+
+ /**
+ * The Mollie javascript library conflicts with he ancient prototype.js library, that's why we load the library
+ * as soon as possible. When adding the script using xml it is always added to late. That's why we do it by
+ * manipulating the html.
+ *
+ * @param Varien_Event_Observer $observer
+ */
+ public function injectMollieComponentsJs(Varien_Event_Observer $observer)
+ {
+ /** @var Mage_Core_Block_Template $block */
+ $block = $observer->getBlock();
+
+ if (!$block instanceof Mage_Page_Block_Html_Head) {
+ return;
+ }
+
+ /** @var \Varient_Object $transport */
+ $transport = $observer->getData('transport');
+ $html = $transport->getHtml();
+ $html = preg_replace('##', '' . PHP_EOL . '', $html, 1);
+
+ $transport->setHtml($html);
+ }
}
diff --git a/app/code/community/Mollie/Mpm/controllers/ApiController.php b/app/code/community/Mollie/Mpm/controllers/ApiController.php
index b1b80ca9..52461878 100644
--- a/app/code/community/Mollie/Mpm/controllers/ApiController.php
+++ b/app/code/community/Mollie/Mpm/controllers/ApiController.php
@@ -92,8 +92,8 @@ public function paymentAction()
}
$methodInstance = $order->getPayment()->getMethodInstance();
- $redirectUrl = $methodInstance->startTransaction($order);
- if (!empty($redirectUrl)) {
+ $redirectUrl = $this->getRedirectUrl($methodInstance, $order);
+ if ($redirectUrl) {
$this->_redirectUrl($redirectUrl);
return;
} else {
@@ -239,4 +239,20 @@ public function redirectAction()
$this->loadLayout();
$this->renderLayout();
}
+
+ /**
+ * @param Mage_Payment_Model_Method_Abstract $methodInstance
+ * @param Mage_Sales_Model_Order $order
+ * @return string|null
+ */
+ private function getRedirectUrl(Mage_Payment_Model_Method_Abstract $methodInstance, Mage_Sales_Model_Order $order)
+ {
+ $redirectUrl = $methodInstance->startTransaction($order);
+
+ if (!$redirectUrl && $methodInstance instanceof Mollie_Mpm_Model_Method_Creditcard) {
+ $redirectUrl = Mage::getUrl('checkout/onepage/success');
+ }
+
+ return $redirectUrl;
+ }
}
diff --git a/app/code/community/Mollie/Mpm/etc/config.xml b/app/code/community/Mollie/Mpm/etc/config.xml
index 57663635..7347bc12 100644
--- a/app/code/community/Mollie/Mpm/etc/config.xml
+++ b/app/code/community/Mollie/Mpm/etc/config.xml
@@ -145,6 +145,15 @@
+
+
+
+ singleton
+ Mollie_Mpm_Model_Observer
+ injectMollieComponentsJs
+
+
+
diff --git a/app/code/community/Mollie/Mpm/etc/system.xml b/app/code/community/Mollie/Mpm/etc/system.xml
index 35fb0236..09e64200 100644
--- a/app/code/community/Mollie/Mpm/etc/system.xml
+++ b/app/code/community/Mollie/Mpm/etc/system.xml
@@ -93,10 +93,20 @@
1
+
+
+ 12
+ 1
+ 1
+ 1
+
+ 1
+
+
text
- 12
+ 13
1
1
1
@@ -107,7 +117,7 @@
text
- 12
+ 14
1
1
1
@@ -119,7 +129,7 @@
button
mpm/adminhtml_system_config_form_apitest_button
- 13
+ 15
1
1
1
@@ -131,7 +141,7 @@
button
mpm/adminhtml_system_config_form_apitest_result
- 14
+ 16
1
1
1
@@ -168,7 +178,7 @@
select
adminhtml/system_config_source_yesno
- 22
+ 23
1
1
1
@@ -181,7 +191,7 @@
select
adminhtml/system_config_source_order_status_new
- 23
+ 24
1
1
1
@@ -194,7 +204,7 @@
select
mpm/adminhtml_system_config_source_processing
- 24
+ 25
1
1
1
@@ -207,7 +217,7 @@
select
adminhtml/system_config_source_yesno
- 25
+ 26
1
1
1
@@ -220,7 +230,7 @@
select
mpm/adminhtml_system_config_source_locale
- 26
+ 27
1
1
1
@@ -233,7 +243,7 @@
select
adminhtml/system_config_source_yesno
- 27
+ 28
1
1
1
@@ -246,7 +256,7 @@
select
adminhtml/system_config_source_yesno
- 27
+ 29
1
1
1
@@ -259,7 +269,7 @@
select
adminhtml/system_config_source_yesno
- 28
+ 30
1
1
1
@@ -764,10 +774,23 @@
1
+
+
+ select
+ adminhtml/system_config_source_yesno
+ 5
+ 1
+ 1
+ 1
+ Note: You need to enter your Profile ID in the general section of this extension configuration to use Mollie Components.]]>
+
+ 1
+
+
text
- 4
+ 6
1
1
1
@@ -786,7 +809,7 @@
allowspecific
- 5
+ 7
adminhtml/system_config_source_payment_allspecificcountries
1
1
@@ -798,7 +821,7 @@
multiselect
- 6
+ 8
adminhtml/system_config_source_country
1
1
@@ -811,7 +834,7 @@
text
- 7
+ 9
1
1
1
@@ -822,7 +845,7 @@
text
- 8
+ 10
1
1
1
@@ -833,7 +856,7 @@
text
- 9
+ 11
1
1
1
diff --git a/app/design/frontend/base/default/layout/mollie_mpm.xml b/app/design/frontend/base/default/layout/mollie_mpm.xml
index 3d9bba70..af218b2f 100644
--- a/app/design/frontend/base/default/layout/mollie_mpm.xml
+++ b/app/design/frontend/base/default/layout/mollie_mpm.xml
@@ -112,4 +112,20 @@
+
+
+
+
+ skin_js
+ js/mollie/mpm/creditcard-components.js
+
+
+ mollie/mpm/style.css
+
+
+
+
+
+
+
diff --git a/app/design/frontend/base/default/template/mollie/mpm/payment/after_body_start.phtml b/app/design/frontend/base/default/template/mollie/mpm/payment/after_body_start.phtml
new file mode 100644
index 00000000..55b2bf0d
--- /dev/null
+++ b/app/design/frontend/base/default/template/mollie/mpm/payment/after_body_start.phtml
@@ -0,0 +1,13 @@
+
+
+
\ No newline at end of file
diff --git a/app/design/frontend/base/default/template/mollie/mpm/payment/form/creditcard-components.phtml b/app/design/frontend/base/default/template/mollie/mpm/payment/form/creditcard-components.phtml
new file mode 100644
index 00000000..16c26b1e
--- /dev/null
+++ b/app/design/frontend/base/default/template/mollie/mpm/payment/form/creditcard-components.phtml
@@ -0,0 +1,32 @@
+
+
+getMethodCode();
+?>
+
+
+
+
+
\ No newline at end of file
diff --git a/modman b/modman
index c410ae51..48539aee 100644
--- a/modman
+++ b/modman
@@ -19,4 +19,5 @@ app/design/adminhtml/default/default/template/mollie/mpm app/design/ad
lib/Mollie lib/Mollie
# skin
skin/frontend/base/default/mollie skin/frontend/base/default/mollie
+skin/frontend/base/default/js/mollie skin/frontend/base/default/js/mollie
skin/adminhtml/default/default/mollie skin/adminhtml/default/default/mollie
diff --git a/skin/frontend/base/default/js/mollie/mpm/creditcard-components.js b/skin/frontend/base/default/js/mollie/mpm/creditcard-components.js
new file mode 100644
index 00000000..3e7467f0
--- /dev/null
+++ b/skin/frontend/base/default/js/mollie/mpm/creditcard-components.js
@@ -0,0 +1,73 @@
+var MollieComponents = Class.create();
+MollieComponents.prototype = {
+ components: {},
+
+ initialize: function (profile_id, testmode, locale) {
+ if (!window.Nodelist && !window.NodeList.prototype.each && window.NodeList.prototype.forEach) {
+ NodeList.prototype.each = NodeList.prototype.forEach;
+ }
+
+ try {
+ this.mollie = Mollie(profile_id, {
+ testMode: testmode,
+ locale: locale
+ });
+
+ this.components.cardHolder = this.mollie.createComponent('cardHolder');
+ this.components.cardNumber = this.mollie.createComponent('cardNumber');
+ this.components.expiryDate = this.mollie.createComponent('expiryDate');
+ this.components.verificationCode = this.mollie.createComponent('verificationCode');
+ } catch (error) {
+ console.error(error);
+ }
+ },
+
+ getMollieToken: function() {
+ if ($$('input:checked[name=payment[method]]')[0].value !== 'mollie_creditcard') {
+ return this.parentSave();
+ }
+
+ this.mollie.createToken().then( function (result) {
+ if (result.error) {
+ alert(result.error.message);
+ return false;
+ }
+
+ var tokenFields = $$('[name=cardToken]');
+ if (result.token && tokenFields && tokenFields.length) {
+ var tokenField = tokenFields.shift();
+ tokenField.removeAttribute('disabled');
+ tokenField.value = result.token;
+ }
+
+ this.parentSave();
+ }.bind(this));
+ },
+
+ mount: function () {
+ payment.addAfterInitFunction('mollie_components', function () {
+ this.parentSave = payment.save.bind(payment);
+ payment.save = this.getMollieToken.bind(this);
+ }.bind(this));
+
+ this.mountElement(this.components.cardHolder, '#card-holder');
+ this.mountElement(this.components.cardNumber, '#card-number');
+ this.mountElement(this.components.expiryDate, '#expiry-date');
+ this.mountElement(this.components.verificationCode, '#verification-code');
+ },
+
+ mountElement: function (element, id) {
+ element.mount(id);
+
+ var errorElement = document.querySelector(id + '-error');
+ element.addEventListener('change', function (event) {
+ if (event.error && event.touched) {
+ errorElement.textContent = event.error;
+ errorElement.style.display = 'block';
+ } else {
+ errorElement.textContent = '';
+ errorElement.style.display = 'none';
+ }
+ });
+ }
+};
diff --git a/skin/frontend/base/default/mollie/mpm/style.css b/skin/frontend/base/default/mollie/mpm/style.css
index 10cf96d0..a38b8852 100644
--- a/skin/frontend/base/default/mollie/mpm/style.css
+++ b/skin/frontend/base/default/mollie/mpm/style.css
@@ -66,4 +66,38 @@
100% {
transform: rotate(360deg);
}
+}
+
+.mollie-component {
+ width: 90%;
+ background-color: #FFF;
+ padding: 10px 15px;
+ border-radius: 6px;
+ color: #222;
+ transition: all .05s ease;
+ box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.1), 0px 1px 3px 0px rgba(0, 0, 0, 0.1), 0px 0px 0px 1px rgba(0, 0, 0, 0.05);
+ margin-bottom: 10px;
+ margin-top: 5px;
+}
+
+.mollie-component.is-invalid {
+ background-color: #FFF0F0;
+ box-shadow: 0px 1px 1px 0px rgba(255, 51, 68, 0.1), 0px 1px 3px 0px rgba(255, 51, 68, 0.1);
+}
+
+.payment-method-content .card-container {
+ max-width: 400px;
+ overflow: auto;
+ background-color: #FFF;
+ border-radius: 10px;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ display: block;
+ padding: 20px;
+ margin-bottom: 10px;
+}
+
+.component-error {
+ color: #FF0000;
+ display: none;
+ margin-bottom: 10px;
}
\ No newline at end of file