I have finally gave up. I spent 2 whole days trying to do this but I finally could not.
I am developing a custom payment method which needs to show instructions for the customer before the actual purchase.
That simple thing could not be made.
First, this is the layout definition (checkout_index_index.xml):
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="checkout.root"> <arguments> <argument name="jsLayout" xsi:type="array"> <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> <item name="children" xsi:type="array"> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> <item name="billing-step" xsi:type="array"> <item name="component" xsi:type="string">uiComponent</item> <item name="children" xsi:type="array"> <item name="payment" xsi:type="array"> <item name="children" xsi:type="array"> <item name="renders" xsi:type="array"> <!-- merge payment method renders here --> <item name="children" xsi:type="array"> <item name="desytec_transbank_methods" xsi:type="array"> <item name="component" xsi:type="string">Desytec_Transbank/js/view/payment/method-renderer</item> <item name="methods" xsi:type="array"> <item name="webpay" xsi:type="array"> <item name="isBillingAddressRequired" xsi:type="boolean">true</item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </body> </page>
The renderer is:
define(
[
'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list'
],
function (
Component,
rendererList
) {
'use strict';
rendererList.push(
{
type: 'webpay',
component: 'Desytec_Transbank/js/view/payment/method-renderer/webpay'
}
);
return Component.extend({});
}
);
And the webpay renderer is:
/*browser:true*/
/*global define*/
define(
[
'ko',
'Magento_Checkout/js/view/payment/default',
],
function (ko, Component) {
return Component.extend({
defaults: {
template: 'Desytec_Transbank/payment/webpay'
},
/**
* Get value of instruction field.
* @returns {String}
*/
getInstructions: function () {
return window.checkoutConfig.payment.instructions[this.item.method];
}
});
}
);
The template is:
<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
<div class="payment-method-title field choice">
<input type="radio"
name="payment[method]"
class="radio"
data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
<label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label>
</div>
<div class="payment-method-content">
<div class="payment-method-billing-address">
<!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<p data-bind="html: getInstructions()"></p>
<div class="checkout-agreements-block">
<!-- ko foreach: $parent.getRegion('before-place-order') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<div class="actions-toolbar">
<div class="primary">
<button class="action primary checkout"
type="submit"
data-bind="
click: placeOrder,
attr: {title: $t('Place Order')},
css: {disabled: !isPlaceOrderActionAllowed()},
enable: (getCode() == isChecked())
"
disabled>
<span data-bind="text: $t('Place Order')"></span>
</button>
</div>
</div>
</div>
</div>
And finally, this is the block:
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Desytec\Transbank\Block\Form;
/**
* Abstract class for Cash On Delivery and Bank Transfer payment method form
*/
abstract class Transbank extends \Magento\Payment\Block\Form
{
/**
* Instructions text
*
* @var string
*/
protected $_instructions;
protected $_template = 'form/webpay.phtml';
/**
* Get instructions text from config
*
* @return null|string
*/
public function getInstructions()
{
if ($this->_instructions === null) {
/** @var \Magento\Payment\Model\Method\AbstractMethod $method */
$method = $this->getMethod();
$this->_instructions = $method->getConfigData('instructions');
}
return $this->_instructions;
}
}
What is missing here?
Regards
Jaime
As you can see from your code, the instructions are not passed from PHP (server) to JavaScript (browser).
You should pass it through a config provider: https://mage2.pro/t/630
https://mage2.pro/tags/checkout-config-provider
Thanks, it does not work, or it is not clear at all.
I have added a di.xml file:
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Model\CompositeConfigProvider">
<arguments>
<argument name="configProviders" xsi:type="array">
<item name="offline_payment_instructions_config_provider" xsi:type="object">Desytec\Transbank\Model\InstructionsConfigProvider</item>
</argument>
</arguments>
</type>
</config>Then, I added the model:
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Desytec\Transbank\Model;
use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Framework\Escaper;
use Magento\Payment\Helper\Data as PaymentHelper;
class InstructionsConfigProvider implements ConfigProviderInterface
{
/**
* @var string[]
*/
protected $methodCodes = [
WebPay::CODE,
];
/**
* @var \Magento\Payment\Model\Method\AbstractMethod[]
*/
protected $methods = [];
/**
* @var Escaper
*/
protected $escaper;
/**
* @param PaymentHelper $paymentHelper
* @param Escaper $escaper
*/
public function __construct(
PaymentHelper $paymentHelper,
Escaper $escaper
) {
$this->escaper = $escaper;
foreach ($this->methodCodes as $code) {
$this->methods[$code] = $paymentHelper->getMethodInstance($code);
}
}
/**
* {@inheritdoc}
*/
public function getConfig()
{
$config = [];
foreach ($this->methodCodes as $code) {
if ($this->methods[$code]->isAvailable()) {
$config['payment']['instructions'][$code] = $this->getInstructions($code);
}
}
return $config;
}
/**
* Get instructions text from config
*
* @param string $code
* @return string
*/
protected function getInstructions($code)
{
return nl2br($this->escaper->escapeHtml($this->methods[$code]->getInstructions()));
}
}I have copied them from banktransfer payment method. Other code that your page shows is not really useful, since they belong to magento2 core.
I think a little explanation is missing besides just put some lines of code.
Thanks
And finally, I gave up again. It was impossible.
How can I expose getInstructions() method to JS? it seems it is defined in Magento core as a default implementation, but how can I actually call it?
Thanks
Jaime
I had the same mistake as you and finally found where I was wrong.
In fact, I've put the di.xml file (with config provider path) into etc folder. But to make it work, this file has to be in etc/frontend folder.
Hope this helps !
Hi,
I know this thread is a little old, but do you have the complete working code. I have to do something similar and I am missing something following what you wrote.
Thanks!