Magento 2 Custom Payment Module – Fix Drop Down List Issue

custom-optionsmagento2modulepayment-methods

Please check my Custom payment Module, I was able to display the list in drop down in Payment method, But when i select and place order it is not working as expected.

Please download the complete module here for more details.

app\code\K2B\PickPay\view\frontend\layout\checkout_index_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn: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="pickpay-payments" xsi:type="array">
                                                                    <item name="component" xsi:type="string">K2B_PickPay/js/view/payment/offline-payments</item>

                                                                    <item name="methods" xsi:type="array">
                                                                        <item name="pickpay" 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>

\app\code\K2B\PickPay\Model\Pickpay.php

namespace K2B\PickPay\Model;
use Magento\Framework\DataObject;
use Magento\Quote\Api\Data\PaymentInterface;
/**
 * Pay In Store payment method model
 */
class Pickpay extends \Magento\Payment\Model\Method\AbstractMethod
{
    const PAYMENT_METHOD_PICKPAY_CODE = 'pickpay';
    /**
     * Payment code
     *
     * @var string
     */
    protected $_code = self::PAYMENT_METHOD_PICKPAY_CODE;
    /**
     * Availability option
     *
     * @var bool
     */
    protected $_isOffline = true;
     /**
     * @var string
     */
    protected $_formBlockType = 'K2B\PickPay\Block\Form\Pickpay';

    /**
     * @var string
     */
    protected $_infoBlockType = 'K2B\PickPay\Block\Info\Pickpay';



    /**
     * Assign data to info model instance
     *
     * @param \Magento\Framework\DataObject|mixed $data
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function assignData(\Magento\Framework\DataObject $data)
    {
        $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
        if (!is_object($additionalData)) {
            $additionalData = new DataObject($additionalData ?: []);
        }       
        /*$myfile = fopen("./var/log/pickpay.txt", "a");    

        $txt = "getPickpayLocation:".$additionalData->getPickpayLocation();     
        fwrite($myfile, "\n". $txt);
        fclose($myfile);*/
        $this->getInfoInstance()->setPickpayLocation($additionalData->getPickpayLocation());
        return $this;
    }

}

\app\code\K2B\PickPay\Setup\UpgradeSchema.php

<?php
namespace K2B\PickPay\Setup;
use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

class UpgradeSchema implements UpgradeSchemaInterface
{   
    /**
     * {@inheritdoc}
     */
    public function upgrade(
        SchemaSetupInterface $setup,
        ModuleContextInterface $context
    ) {
        $installer = $setup;

        $installer->startSetup();       
        if (version_compare($context->getVersion(), '2.0.1', '<')) {            
          $installer->getConnection()->addColumn(
                $installer->getTable('quote_payment'),
                'pickpay_location',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                    'length' => 255,
                    'comment' => 'Pay and Pick Store Location'
                ]
            );
          $installer->getConnection()->addColumn(
                $installer->getTable('sales_order_payment'),
                'pickpay_location',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                    'length' => 255,
                    'comment' => 'Pay and Pick Store Location'
                ]
            );
        }

        $installer->endSetup();
    }
}

app\code\K2B\PickPay\view\frontend\templates\form\pickpay.phtml

<?php
$methodCode = $block->escapeHtml($block->getMethodCode());
$location = $block->escapeHtml($block->getInfoData('pickpay_location'));
?>
<fieldset class="fieldset items <?php /* @noEscape */ echo $methodCode ?>" id="payment_form_<?php /* @noEscape */ echo $methodCode ?>" style="display: none">
    <div class="field number required">
        <label for="pickpay_location" class="label"><span><?php echo $block->escapeHtml(__('
        Choose your Click & Collect Store Location')) ?></span></label>
        <div class="control">
            <select id="pickpay_location" name="payment[pickpay_location]"  class="required-entry">             
                <option value="CENTRAL SUPER MARKET" <?php echo  ($location == 'CENTRAL SUPER MARKET')?'selected="selected"':''?>>CENTRAL SUPER MARKET</option>
                <option value="ZAKHER BRANCH" <?php echo  ($location == 'ZAKHER BRANCH')?'selected="selected"':''?>>ZAKHER BRANCH</option>
                <option value="MAZYED BRANCH" <?php echo  ($location == 'MAZYED BRANCH')?'selected="selected"':''?>>MAZYED BRANCH</option>
                <option value="MARKHANIYA BRANCH" <?php echo  ($location == 'MARKHANIYA BRANCH')?'selected="selected"':''?>>MARKHANIYA BRANCH</option>
                <option value="AL MAQAM BRANCH" <?php echo  ($location == 'AL MAQAM BRANCH')?'selected="selected"':''?>>AL MAQAM BRANCH</option>
                <option value="AL MAQAM BRANCH" <?php echo  ($location == 'AL MAQAM BRANCH')?'selected="selected"':''?>>AL MAQAM BRANCH</option>
                <option value="AL MANASIR BRANCH" <?php echo  ($location == 'AL MANASIR BRANCH')?'selected="selected"':''?>>AL MANASIR BRANCH</option>
                <option value="AL HAYER BRANCH" <?php echo  ($location == 'AL HAYER BRANCH')?'selected="selected"':''?>>AL HAYER BRANCH</option>
                <option value="AL YAHAR BRANCH" <?php echo  ($location == 'AL YAHAR BRANCH')?'selected="selected"':''?>>AL YAHAR BRANCH</option>
                <option value="TAWAM BRANCH" <?php echo  ($location == 'TAWAM BRANCH')?'selected="selected"':''?>>TAWAM BRANCH</option>
                <option value="TOWAYYA HABOI BRANCH" <?php echo  ($location == 'TOWAYYA HABOI BRANCH')?'selected="selected"':''?>>TOWAYYA HABOI BRANCH</option>
                <option value="HILLI KHALEEF BRANCH" <?php echo  ($location == 'HILLI KHALEEF BRANCH')?'selected="selected"':''?>>HILLI KHALEEF BRANCH</option>
                <option value="SHOIBA BRANCH" <?php echo  ($location == 'SHOIBA BRANCH')?'selected="selected"':''?>>SHOIBA BRANCH</option>
                <option value="KHALIDIYA BRANCH" <?php echo  ($location == 'KHALIDIYA BRANCH')?'selected="selected"':''?>>KHALIDIYA BRANCH</option>
                <option value="FALAJ HAZZA BRANCH" <?php echo  ($location == 'FALAJ HAZZA BRANCH')?'selected="selected"':''?>>FALAJ HAZZA BRANCH</option>
                <option value="MASOUDI BRANCH" <?php echo  ($location == 'MASOUDI BRANCH')?'selected="selected"':''?>>MASOUDI BRANCH</option>
                <option value="AL BATEEN BRANCH" <?php echo  ($location == 'AL BATEEN BRANCH')?'selected="selected"':''?>>AL BATEEN BRANCH</option>
                <option value="NAHEL BRANCH" <?php echo  ($location == 'NAHEL BRANCH')?'selected="selected"':''?>>NAHEL BRANCH</option>
                <option value="FAQAA BRANCH" <?php echo  ($location == 'FAQAA BRANCH')?'selected="selected"':''?>>FAQAA BRANCH</option>
                <option value="UM GHAFA BRANCH" <?php echo  ($location == 'UM GHAFA BRANCH')?'selected="selected"':''?>>UM GHAFA BRANCH</option>
                <option value="SALAMAT BRANCH" <?php echo  ($location == 'SALAMAT BRANCH')?'selected="selected"':''?>>SALAMAT BRANCH</option>
                <option value="SUWIHAN BRANCH" <?php echo  ($location == 'SUWIHAN BRANCH')?'selected="selected"':''?>>SUWIHAN BRANCH</option>
                <option value="SHUWAIB BRANCH" <?php echo  ($location == 'SHUWAIB BRANCH')?'selected="selected"':''?>>SHUWAIB BRANCH</option>
                <option value="ALIAH MALL" <?php echo  ($location == 'ALIAH MALL')?'selected="selected"':''?>>ALIAH MALL</option>
                <option value="AL NAYFA SUPERMARKET" <?php echo  ($location == 'AL NAYFA SUPERMARKET')?'selected="selected"':''?>>AL NAYFA SUPERMARKET</option>
            </select>

        </div>
    </div>
</fieldset>

\app\code\K2B\PickPay\view\frontend\web\js\view\payment\method-renderer\pickpay.js

define(
    [
        'Magento_Checkout/js/view/payment/default',
        'jquery',
        "mage/validation"
    ],
    function (Component, $) {
        'use strict';
        return Component.extend({
            defaults: {
                template: 'K2B_PickPay/payment/pickpay-form',
                purchaseOrderNumber: ''
            },
            initObservable: function () {
                this._super()
                    .observe('pickpayLocation');
                return this;
            },
            getData: function () {
                return {
                    "method": this.item.method,
                    'pickpay_location': this.pickpayLocation(),
                    "additional_data": null
                };

            },
            validate: function () {
                var form = 'form[data-role=pickpay-form]';
                return $(form).validation() && $(form).validation('isValid');
            }
        });
    }
);

\app\code\K2B\PickPay\view\frontend\web\js\view\payment\offline-payments.js

 define(
        [
            'uiComponent',
            'Magento_Checkout/js/model/payment/renderer-list'
        ],
        function (
            Component,
            rendererList
        ) {
            'use strict';
            rendererList.push(
                {
                    type: 'pickpay',
                    component: 'K2B_PickPay/js/view/payment/method-renderer/pickpay'
                }
            );
            return Component.extend({
                getData: function() {
                return {
                    'method': this.item.method,
                    'additional_data': {
                        'pickpay_location': this.pickPayLocation()
                    }
                };
            }
            });
        }
    );

\app\code\K2B\PickPay\view\frontend\web\template\payment\pickpay-form.html

<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">
        <form id="pickpay-form" class="form form-pickpay" data-role="pickpay-form">
            <fieldset class="fieldset payment method" data-bind='attr: {id: "payment_form_" + getCode()}'>
                <div class="field field-number required">
                    <label for="pickpay_location" class="label">
                        <span><!-- ko i18n: 'Click & Collect Store Location'--><!-- /ko --></span>
                    </label>
                    <div class="control">
                        <select id="pickpay_location"
                               name="payment[pickpay_location]"
                               data-validate="{required:true}"
                               data-bind='
                                attr: {title: $t("Click & Collect Store Location")},
                                value: pickpayLocation'>
                            <option value="CENTRAL SUPER MARKET">CENTRAL SUPER MARKET</option>
                            <option value="ZAKHER BRANCH">ZAKHER BRANCH</option>
                            <option value="MAZYED BRANCH">MAZYED BRANCH</option>
                            <option value="MARKHANIYA BRANCH">MARKHANIYA BRANCH</option>
                            <option value="AL MAQAM BRANCH">AL MAQAM BRANCH</option>
                            <option value="AL MAQAM BRANCH">AL MAQAM BRANCH</option>
                            <option value="AL MANASIR BRANCH">AL MANASIR BRANCH</option>
                            <option value="AL HAYER BRANCH">AL HAYER BRANCH</option>
                            <option value="AL YAHAR BRANCH">AL YAHAR BRANCH</option>
                            <option value="TAWAM BRANCH">TAWAM BRANCH</option>
                            <option value="TOWAYYA HABOI BRANCH">TOWAYYA HABOI BRANCH</option>
                            <option value="HILLI KHALEEF BRANCH">HILLI KHALEEF BRANCH</option>
                            <option value="SHOIBA BRANCH">SHOIBA BRANCH</option>
                            <option value="KHALIDIYA BRANCH">KHALIDIYA BRANCH</option>
                            <option value="FALAJ HAZZA BRANCH">FALAJ HAZZA BRANCH</option>
                            <option value="MASOUDI BRANCH">MASOUDI BRANCH</option>
                            <option value="AL BATEEN BRANCH">AL BATEEN BRANCH</option>
                            <option value="NAHEL BRANCH">NAHEL BRANCH</option>
                            <option value="FAQAA BRANCH">FAQAA BRANCH</option>
                            <option value="UM GHAFA BRANCH">UM GHAFA BRANCH</option>
                            <option value="SALAMAT BRANCH">SALAMAT BRANCH</option>
                            <option value="SUWIHAN BRANCH">SUWIHAN BRANCH</option>
                            <option value="SHUWAIB BRANCH">SHUWAIB BRANCH</option>
                            <option value="ALIAH MALL">ALIAH MALL</option>
                            <option value="AL NAYFA SUPERMARKET">AL NAYFA SUPERMARKET</option>
                        </select>

                    </div>
                </div>
            </fieldset>
        </form>
        <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="i18n: 'Place Order'"></span>
                </button>
            </div>
        </div>
    </div>
</div>

please check the module here for more details.

after installing module- I am getting following Issue
enter image description here

Best Answer

You need to update and create some files in your module which are here:

Create this requirejs-config.js file in your module root :

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/place-order': {
                'K2B_PickPay/js/model/place-order-mixin': true
            },
            'Magento_Checkout/js/action/set-payment-information': {
                'K2B_PickPay/js/model/set-payment-information-mixin': true
            }
        }
    }
};

Create this file set-payment-information-mixin.js at app/code/K2B/PickPay/view/frontend/web/js/model/ with this content :

define([
    'jquery',
    'mage/utils/wrapper',
    'K2B_PickPay/js/model/pick-pay-location-assigner'
], function ($, wrapper, pickPayLocationAssigner) {
    'use strict';

    return function (placeOrderAction) {

        /** Override place-order-mixin for set-payment-information action as they differs only by method signature */
        return wrapper.wrap(placeOrderAction, function (originalAction, messageContainer, paymentData) {
            pickPayLocationAssigner(paymentData);

            return originalAction(messageContainer, paymentData);
        });
    };
});

Create this file place-order-mixin.js at app/code/K2B/PickPay/view/frontend/web/js/model/ with this content :

define([
    'jquery',
    'mage/utils/wrapper',
    'K2B_PickPay/js/model/pick-pay-location-assigner'
], function ($, wrapper, pickPayLocationAssigner) {
    'use strict';

    return function (placeOrderAction) {

        /** Override default place order action and add agreement_ids to request */
        return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) {
            pickPayLocationAssigner(paymentData);

            return originalAction(paymentData, messageContainer);
        });
    };
});

Create this file pick-pay-location-assigner.js at app/code/K2B/PickPay/view/frontend/web/js/model/ with this content :

 define([
    'jquery'
], function ($) {
    'use strict';

    /** Override default place order action and add agreement_ids to request */
    return function (paymentData) {
        var pickPaForm,
            pickPaData;

        pickPaForm = $('form[data-role=pickpay-form] #pickpay_location');
        pickPaData = pickPaForm.val();

        if (paymentData['extension_attributes'] === undefined) {
            paymentData['extension_attributes'] = {};
        }

        paymentData['extension_attributes']['pickpay_location'] = pickPaData;
    };
});

Update this file offline-payments.js with this content :

define([
        'uiComponent',
        'Magento_Checkout/js/model/payment/renderer-list'
    ], function ( Component, rendererList ) {
        'use strict';
        rendererList.push(
            {
                type: 'pickpay',
                component: 'K2B_PickPay/js/view/payment/method-renderer/pickpay'
            }
        );
        return Component.extend({});
    }
);

Update this file pickpay.js with this content :

    define([
        'Magento_Checkout/js/view/payment/default',
        'jquery',
        "mage/validation"
    ], function (Component, $) {
        'use strict';
        return Component.extend({
            defaults: {
                template: 'K2B_PickPay/payment/pickpay-form',
                pickpayLocation: ''
            },
            initObservable: function () {
                return this;
            },
            getData: function () {
                return {
                    "method": this.item.method
                };

            },
            validate: function () {
                var form = 'form[data-role=pickpay-form]';
                return $(form).validation() && $(form).validation('isValid');
            }
        });
});

Update this file app/code/K2B/PickPay/view/frontend/templates/info/pickpay.phtml this contetn :

<dl class="payment-method pickpay">
    <dt class="title"><?php echo $block->escapeHtml($block->getMethod()->getTitle()) ?></dt>
    <dd class="content">
        <strong><?php echo $block->escapeHtml(__('Click & Collect Store Location')) ?></strong>
        <span class="number"><?php echo $block->escapeHtml($block->getPickPayLocation()) ?></span>
    </dd>
</dl>

Add this file app/code/K2B/PickPay/etc/extension_attributes.xml with this content :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\PaymentInterface">
        <attribute code="pickpay_location" type="string"/>
    </extension_attributes>
</config>

Update this file app/code/K2B/PickPay/Block/Info/Pickpay.php With this content:

<?php
namespace K2B\PickPay\Block\Info;

class Pickpay extends \Magento\Payment\Block\Info
{
    /**
     * @var string
     */
    protected $_template = 'K2B_PickPay::info/pickpay.phtml';

    /**
     * @return string
     */
    public function toPdf()
    {
        $this->setTemplate('K2B_PickPay::info/pdf/pickpay.phtml');
        return $this->toHtml();
    }

    public function getPickPayLocation()
    {
        return $this->getMethod()->getInfoInstance()->getPickpayLocation();
    }

}

Update this file app/code/K2B/PickPay/Model/Pickpay.php with this content:

<?php

namespace K2B\PickPay\Model;

/**
 * Pay In Store payment method model
 */
class Pickpay extends \Magento\Payment\Model\Method\AbstractMethod
{
    const PAYMENT_METHOD_PICKPAY_CODE = 'pickpay';
    /**
     * Payment code
     *
     * @var string
     */
    protected $_code = self::PAYMENT_METHOD_PICKPAY_CODE;
    /**
     * Availability option
     *
     * @var bool
     */
    protected $_isOffline = true;
     /**
     * @var string
     */
    protected $_formBlockType = \K2B\PickPay\Block\Form\Pickpay::class;

    /**
     * @var string
     */
    protected $_infoBlockType = \K2B\PickPay\Block\Info\Pickpay::class;

    public function assignData(\Magento\Framework\DataObject $data)
    {
        parent::assignData($data);
        $infoInstance = $this->getInfoInstance();
        if(is_array($data->getData('additional_data')))
        {
            $additionalData = $data->getData('additional_data');
            $pickPayLocation = ($extensionAttributes = $additionalData['extension_attributes'])?$extensionAttributes->getPickpayLocation():"";
            $infoInstance->setAdditionalInformation('pickpay_location', $pickPayLocation);
            $data->setPickpayLocation($pickPayLocation);
            $infoInstance->setPickpayLocation($pickPayLocation);
        }
        return $this;
    }

}

Add this file app/code/K2B/PickPay/etc/events.xml with this content:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_order_save_before">
        <observer name="pick_pay_payment_before_save" instance="K2B\PickPay\Observer\QuoteToOrderObserver" />
    </event>
</config>

Create this file app/code/K2B/PickPay/Observer/QuoteToOrderObserver.php with this content:

<?php
/**
 * Created by PhpStorm.
 * User: kunj
 * Date: 22/5/18
 * Time: 6:29 PM
 */

namespace K2B\PickPay\Observer;

use Magento\Framework\Event\ObserverInterface;

class QuoteToOrderObserver implements ObserverInterface
{
    protected $cart;

    public function __construct(
        \Magento\Checkout\Model\Cart $cart
    )
    {
        $this->cart = $cart;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Sales\Model\Order\Payment $payment */
        $quotePayment = $this->cart->getQuote()->getPayment();
        $payment = $observer->getEvent()->getOrder()->getPayment();
        if ($quotePayment->getMethod() === \K2B\PickPay\Model\Pickpay::PAYMENT_METHOD_PICKPAY_CODE) {
            if (!empty($quotePayment->getPickpayLocation())) {
                $payment->setPickpayLocation($quotePayment->getPickpayLocation());
            }
        }
    }
}

As per your request, you can download the updated module from here

Related Topic