Jean Paul
Jean Paul

Reputation: 41

WooCommerce custom bacs payment gateway not saving bank account details

I build a plugin-based upon gateway BACS, I followed this guide https://docs.woocommerce.com/document/payment-gateway-api/ I also found some other examples which are used some code from, maybe not a good idea. The plugin works, it shows op as a payment method, click manage and I go the admin page, can change, update the fields and this is saved but the problem is the bank accounts table at the bottom, these are not saved and I cannot find out why.

Here is my code, please keep in mind, writing plugins is not my profession so if the mistakes are stupid, it is due to my lack of knowledge. Any help would be appreciated.


if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {

add_action('plugins_loaded', 'init_gateway_revolut_class');
function init_gateway_revolut_class()
{
  /**
 * Custom Payment Gateway.
 *
 * Provides a Custom Payment Gateway, to modify revolut formatting.
 */
class WC_Gateway_Revolut extends WC_Payment_Gateway
{

    //        public $domain;
    public $locale;
    /**
     * Referral Url.
     *
     * @var string
     */
    public $revolut_url;
    /**
     * Constructor for the gateway.
     */
    public function __construct()
    {


        $this->id                 = 'revolut';
        $this->icon               = apply_filters('woocommerce_revolut_icon', '');
        $this->has_fields         = false;
        $this->method_title       = __('Revolut Multi Currency', 'woocommerce');
        $this->method_description = __('Allows payments in different currencies to your Revolut bank account, more commonly known as direct bank/wire transfer.', 'woocommerce');

        // Load the settings.
        $this->init_form_fields();
        $this->init_settings();

        // Define user set variables
        $this->title         = $this->get_option('title');
        $this->description   = $this->get_option('description');
        $this->instructions  = $this->get_option('instructions');
        $this->referral_text = $this->get_option('referral_text');
        $this->referral_link = $this->get_option('referral_link');
        $this->revolut_url   = $this->revolut_url;
        $this->order_status  = $this->get_option('order_status');
        $this->status_text   = $this->get_option('status_text');

        if (!empty($this->referral_link)) {
            $this->description .= ' ' . $this->get_referral_link();
            // $this->description  = trim( $this->description );
        }
        // revolut account fields shown on the thanks page and in emails
        $this->account_details = get_option('woocommerce_revolut_accounts', array(
            array(
                'currency' => $this->get_option('currency'),
                'account_name' => $this->get_option('account_name'),
                'account_number' => $this->get_option('account_number'),
                'bank_name' => $this->get_option('bank_name'),
                'sort_code' => $this->get_option('sort_code'),
                'iban' => $this->get_option('iban'),
                'bic' => $this->get_option('bic')
            )
        ));

        // Actions
        add_action('woocommerce_update_options_payment_gateways_' . $this->id, array(
            $this,
            'process_admin_options'
        ));
        add_action('woocommerce_update_options_payment_gateways_' . $this->id, array(
            $this,
            'save_account_details'
        ));


        add_action('woocommerce_thankyou_direct_deposit', array(
            $this,
            'thankyou_page'
        ));

        // Customer Emails
        add_action('woocommerce_email_before_order_table', array(
            $this,
            'email_instructions'
        ), 10, 3);
    }

    /**
     * Initialise Gateway Settings Form Fields.
     */
    public function init_form_fields()
    {

        $this->form_fields = array(
            'enabled' => array(
                'title' => __('Enable/Disable', 'woocommerce'),
                'type' => 'checkbox',
                'label' => __('Enable Bank Transfer', 'woocommerce'),
                'default' => 'no'
            ),
            'title' => array(
                'title' => __('Title', 'woocommerce'),
                'type' => 'text',
                'description' => __('This controls the title which the user sees during checkout.', 'woocommerce'),
                'default' => __('Revolut Direct Bank Transfer', 'woocommerce'),
                'desc_tip' => true
            ),
            'description' => array(
                'title' => __('Description', 'woocommerce'),
                'type' => 'textarea',
                'description' => __('Payment method description that the customer will see on your checkout. Link to open new account will be added.', 'woocommerce'),
                'default' => __('Do your payment directly into TeCuro\'s Ltd. bank account. If you are a Revolut account holder, payment will be instant. If you open a new account you will receive an extra discount.', 'woocommerce'),
                'desc_tip' => true
            ),
            'instructions' => array(
                'title' => __('Instructions', 'woocommerce'),
                'type' => 'textarea',
                'description' => __('Instructions that will be added to the thank you page and emails.', 'woocommerce'),
                'default' => __('Please use your Order ID as the payment reference. When the funds have cleared in our account your order will be shipped.', 'woocommerce'),
                'desc_tip' => true
            ),
            'referral_text' => array(
                'title' => __('Referal Link', 'woocommerce'),
                'type' => 'text',
                'description' => __('This is the text link to Revolut.', 'woocommerce'),
                'default' => __('Click here to open a free account with Revolut', 'woocommerce'),
                'desc_tip' => true
            ),
            'referral_link' => array(
                'title' => __('Referal Link', 'woocommerce'),
                'type' => 'text',
                'description' => __('Please paste your referal code you received from Revolut. When not empty referral link will be added.', 'woocommerce'),
                'default' => '',
                'desc_tip' => true
            ),
            'order_status' => array(
                'title' => __('Order Status', 'woocommerce'),
                'type' => 'select',
                'description' => __('Choose whether order status you wish after checkout.', 'woocommerce'),
                'default' => 'wc-on-hold',
                'desc_tip' => true,
                'class' => 'wc-enhanced-select',
                'options' => wc_get_order_statuses()
            ),
            'status_text' => array(
                'title' => __('Order Status Text', 'woocommerce'),
                'type' => 'text',
                'description' => __('Set the text for the selected order status.', 'woocommerce'),
                'default' => __('Awaiting Revolut payment', 'woocommerce'),
                'desc_tip' => true
            ),
            'account_details' => array(
                'type' => 'account_details'
            )
        );

    }

    /**
     * Generate account details html.
     *
     * @return string
     */
    public function generate_account_details_html()
    {

        ob_start();

        $country = WC()->countries->get_base_country();
        $locale  = $this->get_country_locale();

        // Get sortcode label in the $locale array and use appropriate one
        $sortcode = isset($locale[$country]['sortcode']['label']) ? $locale[$country]['sortcode']['label'] : __('Sort Code', 'woocommerce');

            ?>
                <tr valign="top">
                    <th scope="row" class="titledesc"><?php _e('Account Details', 'woocommerce');?>:</th>
                    <td class="forminp" id="revolut_accounts">
                     <div class="wc_input_table_wrapper">
                        <table class="widefat wc_input_table sortable" cellspacing="0">
                            <thead>
                                <tr>
                                    <th class="sort">&nbsp;</th>
                                    <th><?php  _e('Currency', 'woocommerce');?></th>
                                    <th><?php _e('Account Name', 'woocommerce');?></th>
                                    <th><?php _e('Account Number', 'woocommerce');?></th>
                                    <th><?php _e('Bank', 'woocommerce');?></th>
                                    <th><?php echo $sortcode;?></th>
                                    <th><?php _e('IBAN', 'woocommerce');?></th>
                                    <th><?php _e('BIC / Swift', 'woocommerce');?></th>
                                </tr>
                            </thead>
                            <tbody class="accounts">
                                <?php
        $i = -1;
        if ($this->account_details) {
            foreach ($this->account_details as $account) {
                $i++;

                echo '<tr class="account">
                                        <td class="sort"></td>
                                        <td><select class="wc-enhanced-select" name="revolut_currency[' . $i . ']"  id="revolut_currency">
                                        <option value="">Select</option>
                                        <option ' . ($account['currency'] == 'AUD') ? 'selected' : '' . ' value="AUD">AUD</option>
                                        <option ' . ($account['currency'] == 'BGN') ? 'selected' : '' . ' value="BGN">BGN</option>
                                        <option ' . ($account['currency'] == 'CAD') ? 'selected' : '' . ' value="CAD">CAD</option>
                                        <option ' . ($account['currency'] == 'CHF') ? 'selected' : '' . ' value="CHF">CHF</option>
                                        <option ' . ($account['currency'] == 'CZK') ? 'selected' : '' . ' value="CZK">CZK</option>
                                        <option ' . ($account['currency'] == 'CHF') ? 'selected' : '' . ' value="CHF">CHF</option>
                                        <option ' . ($account['currency'] == 'DKK') ? 'selected' : '' . ' value="DKK">DKK</option>
                                        <option ' . ($account['currency'] == 'EUR') ? 'selected' : '' . ' value="EUR">EUR</option>
                                        <option ' . ($account['currency'] == 'GBP') ? 'selected' : '' . ' value="GBP">GBP</option>
                                        <option ' . ($account['currency'] == 'HKD') ? 'selected' : '' . ' value="HKD">HKD</option>
                                        <option ' . ($account['currency'] == 'HRK') ? 'selected' : '' . ' value="HRK">HRK</option>
                                        <option ' . ($account['currency'] == 'HUF') ? 'selected' : '' . ' value="HUF">HUF</option>
                                        <option ' . ($account['currency'] == 'JPY') ? 'selected' : '' . ' value="JPY">JPY</option>
                                        <option ' . ($account['currency'] == 'NOK') ? 'selected' : '' . ' value="NOK">NOK</option>
                                        <option ' . ($account['currency'] == 'PLN') ? 'selected' : '' . ' value="PLN">PLN</option>
                                        <option ' . ($account['currency'] == 'RON') ? 'selected' : '' . ' value="RON">RON</option>
                                        <option ' . ($account['currency'] == 'SEK') ? 'selected' : '' . ' value="SEK">SEK</option>
                                        <option ' . ($account['currency'] == 'USD') ? 'selected' : '' . ' value="USD">USD</option>
                                        <option ' . ($account['currency'] == 'ZAR') ? 'selected' : '' . ' value="ZAR">ZAR</option>
                                        </select></td>
                                        <td><input type="text" value="' . esc_attr(wp_unslash($account['account_name'])) . '" name="revolut_account_name[' . $i . ']" /></td>
                                        <td><input type="text" value="' . esc_attr($account['account_number']) . '" name="revolut_account_number[' . $i . ']" /></td>
                                        <td><input type="text" value="' . esc_attr(wp_unslash($account['bank_name'])) . '" name="revolut_bank_name[' . $i . ']" /></td>
                                        <td><input type="text" value="' . esc_attr($account['sort_code']) . '" name="revolut_sort_code[' . $i . ']" /></td>
                                        <td><input type="text" value="' . esc_attr($account['iban']) . '" name="revolut_iban[' . $i . ']" /></td>
                                        <td><input type="text" value="' . esc_attr($account['bic']) . '" name="revolut_bic[' . $i . ']" /></td>
                                    </tr>';
            }
        }
                                    ?>
                           </tbody>
                            <tfoot>
                                <tr>
                                    <th colspan="8"><a href="#" class="add button"><?php _e('+ Add Account', 'woocommerce');?></a> 
                                    <a href="#" class="remove_rows button"><?php  _e('Remove selected account(s)', 'woocommerce');?></a></th>
                                </tr>
                            </tfoot>
                        </table>
                        </div>
                        <script type="text/javascript">
                            jQuery(function() {
                                jQuery('#revolut_accounts').on( 'click', 'a.add', function(){

                                    var size = jQuery('#revolut_accounts').find('tbody .account').length;

                                    var accountname =  jQuery("#revolut_accounts tr:nth-child(1) td:nth-child(3) input[type='text']").val();                                
                                    if(accountname == null){
                                        accountname = '';
                                    } else{
                                        accountname = accountname;
                                    }

                                    jQuery('<tr class="account">\
                                            <td class="sort"></td>\
                                            <td><select class="wc-enhanced-select" name="revolut_currency[' + size + ']">\
                                            <option value="">&#8595;</option>\
                                            <option value="AUD">AUD</option>\
                                            <option value="BGN">BGN</option>\
                                            <option value="CAD">CAD</option>\
                                            <option value="CHF">CHF</option>\
                                            <option value="CZK">CZK</option>\
                                            <option value="CHF">CHF</option>\
                                            <option value="DKK">DKK</option>\
                                            <option value="EUR">EUR</option>\
                                            <option value="GBP">GBP</option>\
                                            <option value="HKD">HKD</option>\
                                            <option value="HRK">HRK</option>\
                                            <option value="HUF">HUF</option>\
                                            <option value="JPY">JPY</option>\
                                            <option value="NOK">NOK</option>\
                                            <option value="PLN">PLN</option>\
                                            <option value="RON">RON</option>\
                                            <option value="SEK">SEK</option>\
                                            <option value="USD">USD</option>\
                                            <option value="ZAR">ZAR</option>\
                                            </select>\
                                            </td>\
                                            <td><input type="text" value="' + accountname + '" name="revolut_account_name[' + size + ']" /></td>\
                                            <td><input type="text" name="revolut_account_number[' + size + ']" /></td>\
                                            <td><input type="text" value="REVOLUT" name="revolut_bank_name[' + size + ']"/></td>\
                                            <td><input type="text" name="revolut_sort_code[' + size + ']" /></td>\
                                            <td><input type="text" name="revolut_iban[' + size + ']" /></td>\
                                            <td><input type="text" value="REVOGB21" name="revolut_bic[' + size + ']" /></td>\
                                        </tr>').appendTo('#revolut_accounts table tbody');

                                    return false;
                                });
                            });
                        </script>
                    </td>
                </tr>
                <?php
        return ob_get_clean();

    }


    /**
     * Save account details table.
     */
    public function save_account_details()
    {

        $accounts = array();

        if (isset($_POST['revolut_currency']) && isset($_POST['revolut_account_name']) && isset($_POST['revolut_account_number']) && isset($_POST['revolut_bank_name']) && isset($_POST['revolut_sort_code']) && isset($_POST['revolut_iban']) && isset($_POST['revolut_bic'])) {

            $currencies      = array_map('wc_clean', $_POST['revolut_currency']);
            $account_names   = array_map('wc_clean', $_POST['revolut_account_name']);
            $account_numbers = array_map('wc_clean', $_POST['revolut_account_number']);
            $bank_names      = array_map('wc_clean', $_POST['revolut_bank_name']);
            $sort_codes      = array_map('wc_clean', $_POST['revolut_sort_code']);
            $ibans           = array_map('wc_clean', $_POST['revolut_iban']);
            $bics            = array_map('wc_clean', $_POST['revolut_bic']);

            foreach ($account_names as $i => $name) {
                if (!isset($account_names[$i])) {
                    continue;
                }

                $accounts[] = array(
                    'currency' => $currencies[$i],
                    'account_name' => $account_names[$i],
                    'account_number' => $account_numbers[$i],
                    'bank_name' => $bank_names[$i],
                    'sort_code' => $sort_codes[$i],
                    'iban' => $ibans[$i],
                    'bic' => $bics[$i]

                );
            }
        }

        update_option('woocommerce_revolut_accounts', $accounts);

    }

    /**
     * Return the referral_link for admin screens.
     *
     * @return url
     */
    public function get_referral_link()
    {
        $link = $this->referral_link; //get_option( 'referral_link', true );
        $text = $this->referral_text; //get_option( 'referral_text', true );
        if (!empty($this->referral_link)) {
            $revolut_url = sprintf('<a href="https://www.revolut.com/referral/%s1" title="Revolut" target="_blank">%s</a>', $link, $text);
        } else {
            $revolut_url = sprintf('<a href="https://www.revolut.com/" title="Revolut" target="_blank">%s</a>', $text);
        }
        return $revolut_url;
    }
    // apply_filters( 'woocommerce_get_referral_link',  $referral_link );
     /**
     * Output the input fields in checkout.
     * todo: add input box for return code Revolut
     */
    /*



    /**
     * Output for the order received page.
     *
     * @param int $order_id
     */
    public function thankyou_page($order_id)
    {

        if ($this->instructions) {
            echo wpautop(wptexturize(wp_kses_post($this->instructions)));
        }
        $this->bank_details($order_id);

    }

    /**
     * Add content to the WC emails.
     *
     * @param WC_Order $order
     * @param bool $sent_to_admin
     * @param bool $plain_text
     */
    public function email_instructions($order, $sent_to_admin, $plain_text = false)
    {
        /*
        if ( ! $sent_to_admin && 'revolut' === $order->payment_method && $order->has_status( 'on-hold' ) ) {
        if ( $this->instructions ) {
        echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL;
        }
        $this->bank_details( $order->id );
        }
        */
        if ($this->instructions && !$sent_to_admin && $this->id === $order->get_payment_method() && $order->has_status($this->order_status)) {
            echo wpautop(wptexturize($this->instructions)) . PHP_EOL;
        }
        $this->bank_details($order->id);
    }

    /**
     * Get bank details and place into a list format.
     *
     * @param int $order_id
     */
    private function bank_details($order_id = '')
    {

        if (empty($this->account_details)) {
            return;
        }

        // Get order and store in $order
        $order = wc_get_order($order_id);

        // Get the order country and country $locale
        $country = $order->billing_country;
        $locale  = $this->get_country_locale();

        // Get sortcode label in the $locale array and use appropriate one
        $sortcode = isset($locale[$country]['sortcode']['label']) ? $locale[$country]['sortcode']['label'] : __('Sort Code', 'woocommerce');

        $revolut_accounts = apply_filters('woocommerce_revolut_accounts', $this->account_details);

        if (!empty($revolut_accounts)) {
            echo '<h2 class="wc-revolut-bank-details-heading">' . __('Our Bank Details', 'woocommerce') . '</h2>' . PHP_EOL;

            foreach ($revolut_accounts as $revolut_account) {

                $revolut_account = (object) $revolut_account;

                if ($revolut_account->account_name || $revolut_account->bank_name) {
                    echo '<h3>' . wp_unslash(implode(' - ', array_filter(array(
                        $revolut_account->account_name,
                        $revolut_account->bank_name
                    )))) . '</h3>' . PHP_EOL;
                }

                echo '<ul class="wc-revolut-bank-details order_details revolut_details">' . PHP_EOL;

                //echo 'PAYMENT DETAILS RIGHT HERE!!!';

                // revolut account fields shown on the thanks page and in emails
                $account_fields = apply_filters('woocommerce_revolut_account_fields', array(
                    'currency' => array(
                        'label' => __('Currency', 'woocommerce'),
                        'value' => $revolut_account->currency
                    ),
                    'bank_name' => array(
                        'label' => __('Bank Name', 'woocommerce'),
                        'value' => $revolut_account->bank_name
                    ),
                    'sort_code' => array(
                        'label' => $sortcode,
                        'value' => $revolut_account->sort_code
                    ),
                    'account_name' => array(
                        'label' => __('Account Name', 'woocommerce'),
                        'value' => $revolut_account->account_name
                    ),
                    'account_number' => array(
                        'label' => __('Account Number', 'woocommerce'),
                        'value' => $revolut_account->account_number
                    ),
                    'iban' => array(
                        'label' => __('IBAN', 'woocommerce'),
                        'value' => $revolut_account->iban
                    ),
                    'bic' => array(
                        'label' => __('BIC', 'woocommerce'),
                        'value' => $revolut_account->bic
                    )
                ), $order_id);

                foreach ($account_fields as $field_key => $field) {
                    if (!empty($field['value'])) {
                        echo '<li class="' . esc_attr($field_key) . '">' . esc_attr($field['label']) . ': <strong>' . wptexturize($field['value']) . '</strong></li>' . PHP_EOL;
                    }
                }

                echo '</ul>';
            }
        }

    }

    /**
     * Process the payment and return the result.
     *
     * @param int $order_id
     * @return array
     */
    public function process_payment($order_id)
    {

        $order = wc_get_order($order_id);

        // Mark as on-hold (we're awaiting the payment)
        //$order->update_status( 'on-hold', __( 'Awaiting Revolut payment', 'woocommerce' ) );

        if ($order->get_total() > 0) {
            // Mark as on-hold (we're awaiting the payment).
            // $order->update_status( apply_filters( 'woocommerce_bacs_process_payment_order_status', 'on-hold', $order ), __( 'Awaiting BACS payment', 'woocommerce' ) );
            $order->update_status($this->order_status, $this->status_text);
        } else {
            $order->payment_complete();
        }

        // Reduce stock levels
        //$order->reduce_order_stock();
        wc_reduce_stock_levels($order->get_id());
        // Remove cart
        WC()->cart->empty_cart();

        // Return thankyou redirect
        return array(
            'result' => 'success',
            'redirect' => $this->get_return_url($order)
        );

    }

    /**
     * Get country locale if localized.
     *
     * @return array
     */
    public function get_country_locale()
    {

        if (empty($this->locale)) {

            // Locale information to be used - only those that are not 'Sort Code'
            $this->locale = apply_filters('woocommerce_get_revolut_locale', array(
                'AU' => array(
                    'sortcode' => array(
                        'label' => __('BSB', 'woocommerce')
                    )
                ),
                'CA' => array(
                    'sortcode' => array(
                        'label' => __('Bank Transit Number', 'woocommerce')
                    )
                ),
                'IN' => array(
                    'sortcode' => array(
                        'label' => __('IFSC', 'woocommerce')
                    )
                ),
                'IT' => array(
                    'sortcode' => array(
                        'label' => __('Branch Sort', 'woocommerce')
                    )
                ),
                'NZ' => array(
                    'sortcode' => array(
                        'label' => __('Bank Code', 'woocommerce')
                    )
                ),
                'SE' => array(
                    'sortcode' => array(
                        'label' => __('Bank Code', 'woocommerce')
                    )
                ),
                'US' => array(
                    'sortcode' => array(
                        'label' => __('Routing Number', 'woocommerce')
                    )
                ),
                'ZA' => array(
                    'sortcode' => array(
                        'label' => __('Branch Code', 'woocommerce')
                    )
                )
            ));

        }

        return $this->locale;

    }
} 
}

add_filter('woocommerce_payment_gateways', 'add_gateway_revolut_class');
function add_gateway_revolut_class($methods)
{
    $methods[] = 'WC_Gateway_Revolut';
    return $methods;
}
}

Upvotes: 1

Views: 2114

Answers (1)

Jean Paul
Jean Paul

Reputation: 41

Okay found the mistake, the select is not working, changed it to input with a datalist. Works now and accounts are saved.

Upvotes: 1

Related Questions