Plugin Directory

Changeset 2797338


Ignore:
Timestamp:
10/11/2022 03:54:40 PM (3 years ago)
Author:
cryptapi
Message:

v4.6.5 - new features

Location:
cryptapi-payment-gateway-for-woocommerce
Files:
10 edited
1 copied

Legend:

Unmodified
Added
Removed
  • cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/CryptAPI.php

    r2791382 r2797338  
    44Plugin URI: https://github.com/cryptapi/woocommerce-cryptapi
    55Description: Accept cryptocurrency payments on your WooCommerce website
    6 Version: 4.6.4
     6Version: 4.6.5
    77Requires at least: 5
    88Tested up to: 6.0.2
  • cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/README.md

    r2791382 r2797338  
    286286* Minor fixes
    287287
     288#### 4.6.5
     289* Added option to check for failed callbacks
     290* Minor fixes
     291
    288292### Upgrade Notice
    289293#### 4.3
  • cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/controllers/CryptAPI.php

    r2791382 r2797338  
    33use Cryptapi\Helper;
    44
    5 class WC_CryptAPI_Gateway extends WC_Payment_Gateway
    6 {
    7     private static $HAS_TRIGGERED = false;
    8     private static $COIN_OPTIONS = [];
    9 
    10     function __construct()
    11     {
    12         $this->id = 'cryptapi';
    13         $this->icon = CRYPTAPI_PLUGIN_URL . 'static/files/200_logo_ca.png';
    14         $this->has_fields = true;
    15         $this->method_title = 'CryptAPI';
    16         $this->method_description = __('CryptAPI allows customers to pay in cryptocurrency', 'cryptapi');
    17 
    18         $this->supports = array(
    19             'products',
    20             'tokenization',
    21             'add_payment_method',
    22             'subscriptions',
    23             'subscription_cancellation',
    24             'subscription_amount_changes',
    25             'subscription_suspension',
    26             'subscription_reactivation',
    27             'subscription_date_changes',
    28             'multiple_subscriptions',
    29         );
    30 
    31         $this->load_coins();
    32 
    33         $this->init_form_fields();
    34         $this->init_settings();
    35         $this->ca_settings();
    36 
    37         add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options'));
    38         add_action('woocommerce_thankyou_' . $this->id, array($this, 'thankyou_page'));
    39         add_action('woocommerce_api_wc_gateway_' . $this->id, array($this, 'validate_payment'));
    40 
    41         add_action('woocommerce_scheduled_subscription_payment_' . $this->id, array($this, 'scheduled_subscription_mail'), 10, 2);
    42 
    43         add_action('wcs_create_pending_renewal', array($this, 'subscription_send_email'));
    44 
    45         add_action('wp_ajax_nopriv_' . $this->id . '_order_status', array($this, 'order_status'));
    46         add_action('wp_ajax_' . $this->id . '_order_status', array($this, 'order_status'));
    47 
    48         add_action('cryptapi_cronjob', array($this, 'ca_cronjob'), 10, 3);
    49 
    50         add_action('woocommerce_cart_calculate_fees', array($this, 'handling_fee'));
    51 
    52         add_action('woocommerce_checkout_update_order_review', array($this, 'chosen_currency_value_to_wc_session'));
    53 
    54         add_action('wp_footer', array($this, 'refresh_checkout'));
    55 
    56         add_action('woocommerce_email_order_details', array($this, 'add_email_link'), 2, 4);
    57 
    58         add_filter('woocommerce_my_account_my_orders_actions', array($this, 'add_order_link'), 10, 2);
    59     }
    60 
    61     function load_coins()
    62     {
    63         if (!empty(WC_CryptAPI_Gateway::$COIN_OPTIONS)) {
    64             return;
    65         }
    66 
    67         $transient = get_transient('cryptapi_coins');
    68         if (!empty($transient)) {
    69             WC_CryptAPI_Gateway::$COIN_OPTIONS = $transient;
    70 
    71             return;
    72         }
    73 
    74         $coins = CryptAPI\Helper::get_supported_coins();
    75         set_transient('cryptapi_coins', $coins, 86400);
    76         WC_CryptAPI_Gateway::$COIN_OPTIONS = $coins;
    77     }
    78 
    79     function admin_options()
    80     {
    81         parent::admin_options();
    82         ?>
     5class WC_CryptAPI_Gateway extends WC_Payment_Gateway {
     6    private static $HAS_TRIGGERED = false;
     7    private static $COIN_OPTIONS = [];
     8
     9    function __construct() {
     10        $this->id                 = 'cryptapi';
     11        $this->icon               = CRYPTAPI_PLUGIN_URL . 'static/files/200_logo_ca.png';
     12        $this->has_fields         = true;
     13        $this->method_title       = 'CryptAPI';
     14        $this->method_description = esc_attr( __( 'CryptAPI allows customers to pay in cryptocurrency', 'cryptapi' ) );
     15
     16        $this->supports = array(
     17            'products',
     18            'tokenization',
     19            'add_payment_method',
     20            'subscriptions',
     21            'subscription_cancellation',
     22            'subscription_amount_changes',
     23            'subscription_suspension',
     24            'subscription_reactivation',
     25            'subscription_date_changes',
     26            'multiple_subscriptions',
     27        );
     28
     29        $this->load_coins();
     30
     31        $this->init_form_fields();
     32        $this->init_settings();
     33        $this->ca_settings();
     34
     35        add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
     36        add_action( 'woocommerce_thankyou_' . $this->id, array( $this, 'thankyou_page' ) );
     37        add_action( 'woocommerce_api_wc_gateway_' . $this->id, array( $this, 'validate_payment' ) );
     38
     39        add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, array( $this, 'scheduled_subscription_mail' ), 10, 2 );
     40
     41        add_action( 'wcs_create_pending_renewal', array( $this, 'subscription_send_email' ) );
     42
     43        add_action( 'wp_ajax_nopriv_' . $this->id . '_order_status', array( $this, 'order_status' ) );
     44        add_action( 'wp_ajax_' . $this->id . '_order_status', array( $this, 'order_status' ) );
     45
     46        add_action( 'wp_ajax_' . $this->id . '_validate_logs', array( $this, 'validate_logs' ) );
     47
     48        add_action( 'cryptapi_cronjob', array( $this, 'ca_cronjob' ), 10, 3 );
     49
     50        add_action( 'woocommerce_cart_calculate_fees', array( $this, 'handling_fee' ) );
     51
     52        add_action( 'woocommerce_checkout_update_order_review', array( $this, 'chosen_currency_value_to_wc_session' ) );
     53
     54        add_action( 'wp_footer', array( $this, 'refresh_checkout' ) );
     55
     56        add_action( 'woocommerce_email_order_details', array( $this, 'add_email_link' ), 2, 4 );
     57
     58        add_filter( 'woocommerce_my_account_my_orders_actions', array( $this, 'add_order_link' ), 10, 2 );
     59
     60        add_action( 'woocommerce_admin_order_data_after_order_details', array( $this, 'order_detail_validate_logs' ) );
     61
     62    }
     63
     64    function load_coins() {
     65        if ( ! empty( WC_CryptAPI_Gateway::$COIN_OPTIONS ) ) {
     66            return;
     67        }
     68
     69        $transient = get_transient( 'cryptapi_coins' );
     70        if ( ! empty( $transient ) ) {
     71            WC_CryptAPI_Gateway::$COIN_OPTIONS = $transient;
     72
     73            return;
     74        }
     75
     76        $coins = CryptAPI\Helper::get_supported_coins();
     77        set_transient( 'cryptapi_coins', $coins, 86400 );
     78        WC_CryptAPI_Gateway::$COIN_OPTIONS = $coins;
     79    }
     80
     81    function admin_options() {
     82        parent::admin_options();
     83        ?>
    8384        <div style='margin-top: 2rem;'>
    84             <?php echo __("If you need any help or have any suggestion, contact us via the <b>live chat</b> on our <b><a href='https://cryptapi.io' target='_blank'>website</a></b> or join our <b><a href='https://discord.gg/cryptapi' target='_blank'>Discord server</a></b>", "cryptapi") ?>
     85            <?php echo __( "If you need any help or have any suggestion, contact us via the <b>live chat</b> on our <b><a href='https://cryptapi.io' target='_blank'>website</a></b> or join our <b><a href='https://discord.gg/cryptapi' target='_blank'>Discord server</a></b>", "cryptapi" ); ?>
    8586        </div>
    8687        <div style='margin-top: .5rem;'>
    87             <?php echo __("If you enjoy this plugin please <b><a href='https://wordpress.org/support/plugin/cryptapi-payment-gateway-for-woocommerce/reviews/#new-post' target='_blank'>rate and review it</a></b>!", "cryptapi") ?>
     88            <?php echo __( "If you enjoy this plugin please <b><a href='https://wordpress.org/support/plugin/cryptapi-payment-gateway-for-woocommerce/reviews/#new-post' target='_blank'>rate and review it</a></b>!", "cryptapi" ) ?>
    8889        </div>
    8990        <div style="margin-top: 1.5rem">
     
    165166            </a>
    166167        </div>
    167         <?php
    168     }
    169 
    170     private function ca_settings()
    171     {
    172         $this->enabled = $this->get_option('enabled');
    173         $this->title = $this->get_option('title');
    174         $this->description = $this->get_option('description');
    175         $this->api_key = $this->get_option('api_key');
    176         $this->qrcode_size = $this->get_option('qrcode_size');
    177         $this->qrcode_default = $this->get_option('qrcode_default') === 'yes';
    178         $this->qrcode_setting = $this->get_option('qrcode_setting');
    179         $this->coins = $this->get_option('coins');
    180         $this->show_branding = $this->get_option('show_branding') === 'yes';
    181         $this->show_crypto_logos = $this->get_option('show_crypto_logos') === 'yes';
    182         $this->color_scheme = $this->get_option('color_scheme');
    183         $this->refresh_value_interval = $this->get_option('refresh_value_interval');
    184         $this->order_cancelation_timeout = $this->get_option('order_cancelation_timeout');
    185         $this->add_blockchain_fee = $this->get_option('add_blockchain_fee') === 'yes';
    186         $this->fee_order_percentage = $this->get_option('fee_order_percentage');
    187         $this->virtual_complete = $this->get_option('virtual_complete') === 'yes';
    188         $this->disable_conversion = $this->get_option('disable_conversion') === 'yes';
    189         $this->icon = '';
    190 
    191         if (!empty(WC_CryptAPI_Gateway::$COIN_OPTIONS)) {
    192             foreach (array_keys(WC_CryptAPI_Gateway::$COIN_OPTIONS) as $coin) {
    193                 $this->{$coin . '_address'} = $this->get_option($coin . '_address');
    194             }
    195         }
    196     }
    197 
    198     function init_form_fields()
    199     {
    200 
    201         if (!empty(WC_CryptAPI_Gateway::$COIN_OPTIONS)) {
    202             $this->form_fields = array(
    203                 'enabled' => array(
    204                     'title' => __('Enabled', 'cryptapi'),
    205                     'type' => 'checkbox',
    206                     'label' => __('Enable CryptAPI Payments', 'cryptapi'),
    207                     'default' => 'yes'
    208                 ),
    209                 'title' => array(
    210                     'title' => __('Title', 'cryptapi'),
    211                     'type' => 'text',
    212                     'description' => __('This controls the title which the user sees during checkout.', 'cryptapi'),
    213                     'default' => __('Cryptocurrency', 'cryptapi'),
    214                     'desc_tip' => true,
    215                 ),
    216                 'description' => array(
    217                     'title' => __('Description', 'cryptapi'),
    218                     'type' => 'textarea',
    219                     'default' => '',
    220                     'description' => __('Payment method description that the customer will see on your checkout', 'cryptapi')
    221                 ),
    222                 'show_branding' => array(
    223                     'title' => __('Show CryptAPI branding', 'cryptapi'),
    224                     'type' => 'checkbox',
    225                     'label' => __('Show CryptAPI logo and credits below the QR code', 'cryptapi'),
    226                     'default' => 'yes'
    227                 ),
    228                 'show_crypto_logos' => array(
    229                     'title' => __('Show crypto logos in checkout', 'cryptapi'),
    230                     'type' => 'checkbox',
    231                     'label' => sprintf(__('Enable this to show the cryptocurrencies logos in the checkout %1$s %2$s Notice: %3$s It may break in some templates. Use at your own risk.', 'cryptapi'), '<br/>', '<strong>', '</strong>'),
    232                     'default' => 'no'
    233                 ),
    234                 'add_blockchain_fee' => array(
    235                     'title' => __('Add the blockchain fee to the order', 'cryptapi'),
    236                     'type' => 'checkbox',
    237                     'label' => __("This will add an estimation of the blockchain fee to the order value", 'cryptapi'),
    238                     'default' => 'no'
    239                 ),
    240                 'fee_order_percentage' => array(
    241                     'title' => __('Service fee manager', 'cryptapi'),
    242                     'type' => 'select',
    243                     'default' => 'none',
    244                     'options' => array(
    245                         '0.05' => '5%',
    246                         '0.048' => '4.8%',
    247                         '0.045' => '4.5%',
    248                         '0.042' => '4.2%',
    249                         '0.04' => '4%',
    250                         '0.038' => '3.8%',
    251                         '0.035' => '3.5%',
    252                         '0.032' => '3.2%',
    253                         '0.03' => '3%',
    254                         '0.028' => '2.8%',
    255                         '0.025' => '2.5%',
    256                         '0.022' => '2.2%',
    257                         '0.02' => '2%',
    258                         '0.018' => '1.8%',
    259                         '0.015' => '1.5%',
    260                         '0.012' => '1.2%',
    261                         '0.01' => '1%',
    262                         '0.0090' => '0.90%',
    263                         '0.0085' => '0.85%',
    264                         '0.0080' => '0.80%',
    265                         '0.0075' => '0.75%',
    266                         '0.0070' => '0.70%',
    267                         '0.0065' => '0.65%',
    268                         '0.0060' => '0.60%',
    269                         '0.0055' => '0.55%',
    270                         '0.0050' => '0.50%',
    271                         '0.0040' => '0.40%',
    272                         '0.0030' => '0.30%',
    273                         '0.0025' => '0.25%',
    274                         'none' => '0%',
    275                     ),
    276                     'description' => sprintf(__('Set the CryptAPI service fee you want to charge the costumer. %1$s %2$s Note: %3$s Fee you want to charge your costumers (to cover CryptAPI\'s fees fully or partially).', 'cryptapi'), '<br/>', '<strong>', '</strong>')
    277                 ),
    278                 'qrcode_default' => array(
    279                     'title' => __('QR Code by default', 'cryptapi'),
    280                     'type' => 'checkbox',
    281                     'label' => __('Show the QR Code by default', 'cryptapi'),
    282                     'default' => 'yes'
    283                 ),
    284                 'qrcode_size' => array(
    285                     'title' => __('QR Code size', 'cryptapi'),
    286                     'type' => 'number',
    287                     'default' => 300,
    288                     'description' => __('QR code image size', 'cryptapi')
    289                 ),
    290                 'qrcode_setting' => array(
    291                     'title' => __('QR Code to show', 'cryptapi'),
    292                     'type' => 'select',
    293                     'default' => 'ammount',
    294                     'options' => array(
    295                         'without_ammount' => __('Default Without Amount', 'cryptapi'),
    296                         'ammount' => __('Default Amount', 'cryptapi'),
    297                         'hide_ammount' => __('Hide Amount', 'cryptapi'),
    298                         'hide_without_ammount' => __('Hide Without Amount', 'cryptapi'),
    299                     ),
    300                     'description' => __('Select how you want to show the QR Code to the user. Either select a default to show first, or hide one of them.', 'cryptapi')
    301                 ),
    302                 'color_scheme' => array(
    303                     'title' => __('Color Scheme', 'cryptapi'),
    304                     'type' => 'select',
    305                     'default' => 'light',
    306                     'description' => __('Selects the color scheme of the plugin to match your website (Light, Dark and Auto to automatically detect it)', 'cryptapi'),
    307                     'options' => array(
    308                         'light' => __('Light', 'cryptapi'),
    309                         'dark' => __('Dark', 'cryptapi'),
    310                         'auto' => __('Auto', 'cryptapi'),
    311                     ),
    312                 ),
    313                 'refresh_value_interval' => array(
    314                     'title' => __('Refresh converted value', 'cryptapi'),
    315                     'type' => 'select',
    316                     'default' => '300',
    317                     'options' => array(
    318                         '0' => __('Never', 'cryptapi'),
    319                         '300' => __('Every 5 Minutes', 'cryptapi'),
    320                         '600' => __('Every 10 Minutes', 'cryptapi'),
    321                         '900' => __('Every 15 Minutes', 'cryptapi'),
    322                         '1800' => __('Every 30 Minutes', 'cryptapi'),
    323                         '2700' => __('Every 45 Minutes', 'cryptapi'),
    324                         '3600' => __('Every 60 Minutes', 'cryptapi'),
    325                     ),
    326                     'description' => sprintf(__('The system will automatically update the conversion value of the invoices (with real-time data), every X minutes. %1$s This feature is helpful whenever a customer takes long time to pay a generated invoice and the selected crypto a volatile coin/token (not stable coin). %1$s %4$s Warning: %3$s Setting this setting to none might create conversion issues, as we advise you to keep it at 5 minutes. %3$s', 'cryptapi'), '<br/>', '<strong>', '</strong>', '<strong style="color: #f44336;">'),
    327                 ),
    328                 'order_cancelation_timeout' => array(
    329                     'title' => __('Order cancelation timeout', 'cryptapi'),
    330                     'type' => 'select',
    331                     'default' => '0',
    332                     'options' => array(
    333                         '0' => __('Never', 'cryptapi'),
    334                         '3600' => __('1 Hour', 'cryptapi'),
    335                         '21600' => __('6 Hours', 'cryptapi'),
    336                         '43200' => __('12 Hours', 'cryptapi'),
    337                         '64800' => __('18 Hours', 'cryptapi'),
    338                         '86400' => __('24 Hours', 'cryptapi'),
    339                     ),
    340                     'description' => sprintf(__('Selects the amount of time the user has to  pay for the order. %1$s When this time is over, order will be marked as "Cancelled" and every paid value will be ignored. %1$s %2$s Notice: %3$s If the user still sends money to the generated address, value will still be redirected to you. %1$s %4$s Warning: %3$s We do not advice more than 1 Hour.', 'cryptapi'), '<br/>', '<strong>', '</strong>', '<strong style="color: #f44336;">'),
    341                 ),
    342                 'virtual_complete' => array(
    343                     'title' => __('Completed status for virtual products', 'cryptapi'),
    344                     'type' => 'checkbox',
    345                     'label' => sprintf(__('When this setting is enabled, the plugin will mark the order as "completed" then payment is received. %1$s Only for virtual products %2$s.', 'cryptapi'), '<strong>', '</strong>'),
    346                     'default' => 'no'
    347                 ),
    348                 'disable_conversion' => array(
    349                     'title' => __('Disable price conversion', 'cryptapi'),
    350                     'type' => 'checkbox',
    351                     'label' => sprintf(__('%2$s Attention: This option will disable the price conversion for ALL cryptocurrencies! %3$s %1$s If you check this, pricing will not be converted from the currency of your shop to the cryptocurrency selected by the user, and users will be requested to pay the same value as shown on your shop, regardless of the cryptocurrency selected', 'cryptapi'), '<br/>', '<strong>', '</strong>'),
    352                     'default' => 'no'
    353                 ),
    354                 'api_key' => array(
    355                     'title' => __('API Key', 'cryptapi'),
    356                     'type' => 'text',
    357                     'default' => '',
    358                     'description' => sprintf(__('Insert here your BlockBee API Key. You can get one here: %1$s', 'cryptapi'), '<a href="https://dash.blockbee.io/" target="_blank">https://dash.blockbee.io/</a>')
    359                 ),
    360             );
    361 
    362             $coin_description = __('Insert your %s address here. Leave the checkbox unselected if you want to skip this cryptocurrency', 'cryptapi');
    363 
    364             $c = 0;
    365             foreach (WC_CryptAPI_Gateway::$COIN_OPTIONS as $ticker => $coin) {
    366                 $this->form_fields["{$ticker}_address"] = array(
    367                     'title' => is_array($coin) ? $coin['name'] : $coin,
    368                     'type' => 'cryptocurrency',
    369                     'description' => sprintf($coin_description, is_array($coin) ? $coin['name'] : $coin),
    370                     'desc_tip' => true,
    371                     'custom_attributes' => array(
    372                         'counter' => $c++,
    373                     )
    374                 );
    375 
    376             }
    377 
    378         }
    379     }
    380 
    381     function needs_setup()
    382     {
    383         if (empty($this->coins) || !is_array($this->coins)) {
    384             return true;
    385         }
    386 
    387         foreach ($this->coins as $val) {
    388             if (!empty($this->{$val . '_address'})) {
    389                 return false;
    390             }
    391         }
    392 
    393         return true;
    394     }
    395 
    396     public function get_icon()
    397     {
    398 
    399         $icon = $this->show_branding ? '<img style="top: -5px; position:relative" width="120" src="' . plugin_dir_url(dirname(__FILE__)) . 'static/files/200_logo_ca.png' . '" alt="' . esc_attr($this->get_title()) . '" />' : '';
    400 
    401         return apply_filters('woocommerce_gateway_icon', $icon, $this->id);
    402     }
    403 
    404     function payment_fields()
    405     { ?>
     168        <?php
     169    }
     170
     171    private function ca_settings() {
     172        $this->enabled                   = $this->get_option( 'enabled' );
     173        $this->title                     = $this->get_option( 'title' );
     174        $this->description               = $this->get_option( 'description' );
     175        $this->api_key                   = $this->get_option( 'api_key' );
     176        $this->qrcode_size               = $this->get_option( 'qrcode_size' );
     177        $this->qrcode_default            = $this->get_option( 'qrcode_default' ) === 'yes';
     178        $this->qrcode_setting            = $this->get_option( 'qrcode_setting' );
     179        $this->coins                     = $this->get_option( 'coins' );
     180        $this->show_branding             = $this->get_option( 'show_branding' ) === 'yes';
     181        $this->show_crypto_logos         = $this->get_option( 'show_crypto_logos' ) === 'yes';
     182        $this->color_scheme              = $this->get_option( 'color_scheme' );
     183        $this->refresh_value_interval    = $this->get_option( 'refresh_value_interval' );
     184        $this->order_cancelation_timeout = $this->get_option( 'order_cancelation_timeout' );
     185        $this->add_blockchain_fee        = $this->get_option( 'add_blockchain_fee' ) === 'yes';
     186        $this->fee_order_percentage      = $this->get_option( 'fee_order_percentage' );
     187        $this->virtual_complete          = $this->get_option( 'virtual_complete' ) === 'yes';
     188        $this->disable_conversion        = $this->get_option( 'disable_conversion' ) === 'yes';
     189        $this->icon                      = '';
     190
     191        if ( ! empty( WC_CryptAPI_Gateway::$COIN_OPTIONS ) ) {
     192            foreach ( array_keys( WC_CryptAPI_Gateway::$COIN_OPTIONS ) as $coin ) {
     193                $this->{$coin . '_address'} = $this->get_option( $coin . '_address' );
     194            }
     195        }
     196    }
     197
     198    function init_form_fields() {
     199
     200        if ( ! empty( WC_CryptAPI_Gateway::$COIN_OPTIONS ) ) {
     201            $this->form_fields = array(
     202                'enabled'                   => array(
     203                    'title'   => esc_attr( __( 'Enabled', 'cryptapi' ) ),
     204                    'type'    => 'checkbox',
     205                    'label'   => esc_attr( __( 'Enable CryptAPI Payments', 'cryptapi' ) ),
     206                    'default' => 'yes'
     207                ),
     208                'title'                     => array(
     209                    'title'       => esc_attr( __( 'Title', 'cryptapi' ) ),
     210                    'type'        => 'text',
     211                    'description' => esc_attr( __( 'This controls the title which the user sees during checkout.', 'cryptapi' ) ),
     212                    'default'     => esc_attr( __( 'Cryptocurrency', 'cryptapi' ) ),
     213                    'desc_tip'    => true,
     214                ),
     215                'description'               => array(
     216                    'title'       => esc_attr( __( 'Description', 'cryptapi' ) ),
     217                    'type'        => 'textarea',
     218                    'default'     => '',
     219                    'description' => esc_attr( __( 'Payment method description that the customer will see on your checkout', 'cryptapi' ) )
     220                ),
     221                'show_branding'             => array(
     222                    'title'   => esc_attr( __( 'Show CryptAPI branding', 'cryptapi' ) ),
     223                    'type'    => 'checkbox',
     224                    'label'   => esc_attr( __( 'Show CryptAPI logo and credits below the QR code', 'cryptapi' ) ),
     225                    'default' => 'yes'
     226                ),
     227                'show_crypto_logos'         => array(
     228                    'title'   => esc_attr( __( 'Show crypto logos in checkout', 'cryptapi' ) ),
     229                    'type'    => 'checkbox',
     230                    'label'   => sprintf( esc_attr( __( 'Enable this to show the cryptocurrencies logos in the checkout %1$s %2$s Notice: %3$s It may break in some templates. Use at your own risk.', 'cryptapi' ) ), '<br/>', '<strong>', '</strong>' ),
     231                    'default' => 'no'
     232                ),
     233                'add_blockchain_fee'        => array(
     234                    'title'   => esc_attr( __( 'Add the blockchain fee to the order', 'cryptapi' ) ),
     235                    'type'    => 'checkbox',
     236                    'label'   => esc_attr( __( "This will add an estimation of the blockchain fee to the order value", 'cryptapi' ) ),
     237                    'default' => 'no'
     238                ),
     239                'fee_order_percentage'      => array(
     240                    'title'       => esc_attr( __( 'Service fee manager', 'cryptapi' ) ),
     241                    'type'        => 'select',
     242                    'default'     => 'none',
     243                    'options'     => array(
     244                        '0.05'   => '5%',
     245                        '0.048'  => '4.8%',
     246                        '0.045'  => '4.5%',
     247                        '0.042'  => '4.2%',
     248                        '0.04'   => '4%',
     249                        '0.038'  => '3.8%',
     250                        '0.035'  => '3.5%',
     251                        '0.032'  => '3.2%',
     252                        '0.03'   => '3%',
     253                        '0.028'  => '2.8%',
     254                        '0.025'  => '2.5%',
     255                        '0.022'  => '2.2%',
     256                        '0.02'   => '2%',
     257                        '0.018'  => '1.8%',
     258                        '0.015'  => '1.5%',
     259                        '0.012'  => '1.2%',
     260                        '0.01'   => '1%',
     261                        '0.0090' => '0.90%',
     262                        '0.0085' => '0.85%',
     263                        '0.0080' => '0.80%',
     264                        '0.0075' => '0.75%',
     265                        '0.0070' => '0.70%',
     266                        '0.0065' => '0.65%',
     267                        '0.0060' => '0.60%',
     268                        '0.0055' => '0.55%',
     269                        '0.0050' => '0.50%',
     270                        '0.0040' => '0.40%',
     271                        '0.0030' => '0.30%',
     272                        '0.0025' => '0.25%',
     273                        'none'   => '0%',
     274                    ),
     275                    'description' => sprintf( esc_attr( __( 'Set the CryptAPI service fee you want to charge the costumer. %1$s %2$s Note: %3$s Fee you want to charge your costumers (to cover CryptAPI\'s fees fully or partially).', 'cryptapi' ) ), '<br/>', '<strong>', '</strong>' )
     276                ),
     277                'qrcode_default'            => array(
     278                    'title'   => esc_attr( __( 'QR Code by default', 'cryptapi' ) ),
     279                    'type'    => 'checkbox',
     280                    'label'   => esc_attr( __( 'Show the QR Code by default', 'cryptapi' ) ),
     281                    'default' => 'yes'
     282                ),
     283                'qrcode_size'               => array(
     284                    'title'       => esc_attr( __( 'QR Code size', 'cryptapi' ) ),
     285                    'type'        => 'number',
     286                    'default'     => 300,
     287                    'description' => esc_attr( __( 'QR code image size', 'cryptapi' ) )
     288                ),
     289                'qrcode_setting'            => array(
     290                    'title'       => esc_attr( __( 'QR Code to show', 'cryptapi' ) ),
     291                    'type'        => 'select',
     292                    'default'     => 'without_ammount',
     293                    'options'     => array(
     294                        'without_ammount'      => esc_attr( __( 'Default Without Amount', 'cryptapi' ) ),
     295                        'ammount'              => esc_attr( __( 'Default Amount', 'cryptapi' ) ),
     296                        'hide_ammount'         => esc_attr( __( 'Hide Amount', 'cryptapi' ) ),
     297                        'hide_without_ammount' => esc_attr( __( 'Hide Without Amount', 'cryptapi' ) ),
     298                    ),
     299                    'description' => esc_attr( __( 'Select how you want to show the QR Code to the user. Either select a default to show first, or hide one of them.', 'cryptapi' ) )
     300                ),
     301                'color_scheme'              => array(
     302                    'title'       => esc_attr( __( 'Color Scheme', 'cryptapi' ) ),
     303                    'type'        => 'select',
     304                    'default'     => 'light',
     305                    'description' => esc_attr( __( 'Selects the color scheme of the plugin to match your website (Light, Dark and Auto to automatically detect it)', 'cryptapi' ) ),
     306                    'options'     => array(
     307                        'light' => esc_attr( __( 'Light', 'cryptapi' ) ),
     308                        'dark'  => esc_attr( __( 'Dark', 'cryptapi' ) ),
     309                        'auto'  => esc_attr( __( 'Auto', 'cryptapi' ) ),
     310                    ),
     311                ),
     312                'refresh_value_interval'    => array(
     313                    'title'       => esc_attr( __( 'Refresh converted value', 'cryptapi' ) ),
     314                    'type'        => 'select',
     315                    'default'     => '300',
     316                    'options'     => array(
     317                        '0'    => esc_attr( __( 'Never', 'cryptapi' ) ),
     318                        '300'  => esc_attr( __( 'Every 5 Minutes', 'cryptapi' ) ),
     319                        '600'  => esc_attr( __( 'Every 10 Minutes', 'cryptapi' ) ),
     320                        '900'  => esc_attr( __( 'Every 15 Minutes', 'cryptapi' ) ),
     321                        '1800' => esc_attr( __( 'Every 30 Minutes', 'cryptapi' ) ),
     322                        '2700' => esc_attr( __( 'Every 45 Minutes', 'cryptapi' ) ),
     323                        '3600' => esc_attr( __( 'Every 60 Minutes', 'cryptapi' ) ),
     324                    ),
     325                    'description' => sprintf( esc_attr( __( 'The system will automatically update the conversion value of the invoices (with real-time data), every X minutes. %1$s This feature is helpful whenever a customer takes long time to pay a generated invoice and the selected crypto a volatile coin/token (not stable coin). %1$s %4$s Warning: %3$s Setting this setting to none might create conversion issues, as we advise you to keep it at 5 minutes. %3$s', 'cryptapi' ) ), '<br/>', '<strong>', '</strong>', '<strong style="color: #f44336;">' ),
     326                ),
     327                'order_cancelation_timeout' => array(
     328                    'title'       => esc_attr( __( 'Order cancelation timeout', 'cryptapi' ) ),
     329                    'type'        => 'select',
     330                    'default'     => '0',
     331                    'options'     => array(
     332                        '0'     => esc_attr( __( 'Never', 'cryptapi' ) ),
     333                        '3600'  => esc_attr( __( '1 Hour', 'cryptapi' ) ),
     334                        '21600' => esc_attr( __( '6 Hours', 'cryptapi' ) ),
     335                        '43200' => esc_attr( __( '12 Hours', 'cryptapi' ) ),
     336                        '64800' => esc_attr( __( '18 Hours', 'cryptapi' ) ),
     337                        '86400' => esc_attr( __( '24 Hours', 'cryptapi' ) ),
     338                    ),
     339                    'description' => sprintf( esc_attr( __( 'Selects the amount of time the user has to  pay for the order. %1$s When this time is over, order will be marked as "Cancelled" and every paid value will be ignored. %1$s %2$s Notice: %3$s If the user still sends money to the generated address, value will still be redirected to you. %1$s %4$s Warning: %3$s We do not advice more than 1 Hour.', 'cryptapi' ) ), '<br/>', '<strong>', '</strong>', '<strong style="color: #f44336;">' ),
     340                ),
     341                'virtual_complete'          => array(
     342                    'title'   => esc_attr( __( 'Completed status for virtual products', 'cryptapi' ) ),
     343                    'type'    => 'checkbox',
     344                    'label'   => sprintf( __( 'When this setting is enabled, the plugin will mark the order as "completed" then payment is received. %1$s Only for virtual products %2$s.', 'cryptapi' ), '<strong>', '</strong>' ),
     345                    'default' => 'no'
     346                ),
     347                'disable_conversion'        => array(
     348                    'title'   => esc_attr( __( 'Disable price conversion', 'cryptapi' ) ),
     349                    'type'    => 'checkbox',
     350                    'label'   => sprintf( __( '%2$s Attention: This option will disable the price conversion for ALL cryptocurrencies! %3$s %1$s If you check this, pricing will not be converted from the currency of your shop to the cryptocurrency selected by the user, and users will be requested to pay the same value as shown on your shop, regardless of the cryptocurrency selected', 'cryptapi' ), '<br/>', '<strong>', '</strong>' ),
     351                    'default' => 'no'
     352                ),
     353                'api_key'                   => array(
     354                    'title'       => esc_attr( __( 'API Key', 'cryptapi' ) ),
     355                    'type'        => 'text',
     356                    'default'     => '',
     357                    'description' => sprintf( esc_attr( __( 'Insert here your BlockBee API Key. You can get one here: %1$s', 'cryptapi' ) ), '<a href="https://dash.blockbee.io/" target="_blank">https://dash.blockbee.io/</a>' )
     358                ),
     359            );
     360
     361            $coin_description = esc_attr( __( 'Insert your %s address here. Leave the checkbox unselected if you want to skip this cryptocurrency', 'cryptapi' ) );
     362
     363            $c = 0;
     364            foreach ( WC_CryptAPI_Gateway::$COIN_OPTIONS as $ticker => $coin ) {
     365                $this->form_fields["{$ticker}_address"] = array(
     366                    'title'             => is_array( $coin ) ? $coin['name'] : $coin,
     367                    'type'              => 'cryptocurrency',
     368                    'description'       => sprintf( $coin_description, is_array( $coin ) ? $coin['name'] : $coin ),
     369                    'desc_tip'          => true,
     370                    'custom_attributes' => array(
     371                        'counter' => $c ++,
     372                    )
     373                );
     374
     375            }
     376
     377        }
     378    }
     379
     380    function needs_setup() {
     381        if ( empty( $this->coins ) || ! is_array( $this->coins ) ) {
     382            return true;
     383        }
     384
     385        foreach ( $this->coins as $val ) {
     386            if ( ! empty( $this->{$val . '_address'} ) ) {
     387                return false;
     388            }
     389        }
     390
     391        return true;
     392    }
     393
     394    public function get_icon() {
     395
     396        $icon = $this->show_branding ? '<img style="top: -5px; position:relative" width="120" src="' . esc_url( plugin_dir_url( dirname( __FILE__ ) ) ) . 'static/files/200_logo_ca.png' . '" alt="' . esc_attr( $this->get_title() ) . '" />' : '';
     397
     398        return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
     399    }
     400
     401    function payment_fields() { ?>
    406402        <div class="form-row form-row-wide">
    407             <p><?php echo $this->description; ?></p>
     403            <p><?php echo esc_attr( $this->description ); ?></p>
    408404            <ul style="margin-top: 7px; list-style: none outside;">
    409                 <?php
    410                 if (!empty($this->coins) && is_array($this->coins)) {
    411                     $selected = WC()->session->get('cryptapi_coin');
    412                     ?>
     405                <?php
     406                if ( ! empty( $this->coins ) && is_array( $this->coins ) ) {
     407                    $selected = WC()->session->get( 'cryptapi_coin' );
     408                    ?>
    413409                    <li>
    414410                        <select name="cryptapi_coin" id="payment_cryptapi_coin" class="input-control" style="display:block; margin-top: 10px">
    415                             <option value="none"><?php echo __('Please select a Cryptocurrency', 'cryptapi') ?></option>
    416                             <?php
    417                             foreach ($this->coins as $val) {
    418                                 $addr = $this->{$val . '_address'};
    419                                 $apikey = $this->api_key;
    420                                 if (!empty($addr) || !empty($apikey)) { ?>
    421                                     <option data-image="<?php echo WC_CryptAPI_Gateway::$COIN_OPTIONS[$val]['logo']; ?>" value="<?php echo $val; ?>" <?php
    422                                     if (!empty($selected) && $selected === $val) {
    423                                         echo " selected='true'";
    424                                     }
    425                                     $crypto_name = is_array(WC_CryptAPI_Gateway::$COIN_OPTIONS[$val]) ? WC_CryptAPI_Gateway::$COIN_OPTIONS[$val]['name'] : WC_CryptAPI_Gateway::$COIN_OPTIONS[$val];
    426                                     ?>> <?php echo __('Pay with', 'cryptapi') . ' ' . $crypto_name; ?></option>
    427                                     <?php
    428                                 }
    429                             }
    430                             ?>
     411                            <option value="none"><?php echo esc_attr( __( 'Please select a Cryptocurrency', 'cryptapi' ) ) ?></option>
     412                            <?php
     413                            foreach ( $this->coins as $val ) {
     414                                $addr  = $this->{$val . '_address'};
     415                                $apikey = $this->api_key;
     416                                if ( ! empty( $addr ) || ! empty( $apikey ) ) { ?>
     417                                    <option data-image="<?php echo esc_url( WC_CryptAPI_Gateway::$COIN_OPTIONS[ $val ]['logo'] ); ?>" value="<?php echo esc_attr( $val ); ?>" <?php
     418                                    if ( ! empty( $selected ) && $selected === $val ) {
     419                                        echo esc_attr( "selected='true'" );
     420                                    }
     421                                    $crypto_name = is_array( WC_CryptAPI_Gateway::$COIN_OPTIONS[ $val ] ) ? WC_CryptAPI_Gateway::$COIN_OPTIONS[ $val ]['name'] : WC_CryptAPI_Gateway::$COIN_OPTIONS[ $val ];
     422                                    ?>> <?php echo esc_attr( __( 'Pay with', 'cryptapi' ) . ' ' . $crypto_name ); ?></option>
     423                                    <?php
     424                                }
     425                            }
     426                            ?>
    431427                        </select>
    432428                    </li>
    433                     <?php
    434                 } ?>
     429                    <?php
     430                } ?>
    435431            </ul>
    436432        </div>
    437         <?php
    438         if ($this->show_crypto_logos) {
    439             ?>
     433        <?php
     434        if ( $this->show_crypto_logos ) {
     435            ?>
    440436            <script>
    441437                if (typeof jQuery.fn.selectWoo !== 'undefined') {
     
    458454                }
    459455            </script>
    460             <?php
     456            <?php
     457        }
     458    }
     459
     460    function validate_fields() {
     461        return array_key_exists( sanitize_text_field( $_POST['cryptapi_coin'] ), WC_CryptAPI_Gateway::$COIN_OPTIONS );
     462    }
     463
     464    function process_payment( $order_id ) {
     465        global $woocommerce;
     466
     467        $selected = sanitize_text_field( $_POST['cryptapi_coin'] );
     468
     469        if ( $selected === 'none' ) {
     470            wc_add_notice( __( 'Payment error: ', 'woocommerce' ) . ' ' . __( 'Please choose a cryptocurrency', 'cryptapi' ), 'error' );
     471
     472            return null;
     473        }
     474
     475        $api_key = $this->api_key;
     476        $addr    = $this->{$selected . '_address'};
     477
     478        if ( ! empty( $addr ) || ! empty( $api_key ) ) {
     479
     480            $nonce = $this->generate_nonce();
     481
     482            $callback_url = str_replace( 'https:', 'http:', add_query_arg( array(
     483                'wc-api'   => 'WC_Gateway_CryptAPI',
     484                'order_id' => $order_id,
     485                'nonce'    => $nonce,
     486            ), home_url( '/' ) ) );
     487
     488            try {
     489                $order = new WC_Order( $order_id );
     490
     491                if ( in_array( 'woocommerce-subscriptions/woocommerce-subscriptions.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
     492
     493                    if ( wcs_order_contains_subscription( $order_id ) ) {
     494
     495                        $sign_up_fee      = ( WC_Subscriptions_Order::get_sign_up_fee( $order ) ) ? 0 : WC_Subscriptions_Order::get_sign_up_fee( $order );
     496                        $initial_payment  = ( WC_Subscriptions_Order::get_total_initial_payment( $order ) ) ? 0 : WC_Subscriptions_Order::get_total_initial_payment( $order );
     497                        $price_per_period = ( WC_Subscriptions_Order::get_recurring_total( $order ) ) ? 0 : WC_Subscriptions_Order::get_recurring_total( $order );
     498
     499                        $total = $sign_up_fee + $initial_payment + $price_per_period + $order->get_total( 'edit' );
     500
     501                        if ( $total == 0 ) {
     502                            $order->add_meta_data( 'cryptapi_currency', $selected );
     503                            $order->save_meta_data();
     504                            $order->payment_complete();
     505                            $woocommerce->cart->empty_cart();
     506
     507                            return array(
     508                                'result'   => 'success',
     509                                'redirect' => $this->get_return_url( $order )
     510                            );
     511                        }
     512                    }
     513                }
     514
     515                $total = $order->get_total( 'edit' );
     516
     517                $currency = get_woocommerce_currency();
     518
     519                $info   = CryptAPI\Helper::get_info( $selected );
     520                $min_tx = CryptAPI\Helper::sig_fig( $info->minimum_transaction_coin, 6 );
     521
     522                $crypto_total = CryptAPI\Helper::get_conversion( $currency, $selected, $total, $this->disable_conversion );
     523
     524                if ( $crypto_total < $min_tx ) {
     525                    wc_add_notice( __( 'Payment error:', 'woocommerce' ) . ' ' . __( 'Value too low, minimum is', 'cryptapi' ) . ' ' . $min_tx . ' ' . strtoupper( $selected ), 'error' );
     526
     527                    return null;
     528                }
     529
     530                $ca = new CryptAPI\Helper( $selected, $addr, $api_key, $callback_url, [], true );
     531
     532                $addr_in = $ca->get_address();
     533
     534                if ( empty( $addr_in ) ) {
     535                    wc_add_notice( __( 'Payment error:', 'woocommerce' ) . ' ' . __( 'There was an error with the payment. Please try again.', 'cryptapi' ) );
     536
     537                    return null;
     538                }
     539
     540                $qr_code_data_value = CryptAPI\Helper::get_static_qrcode( $addr_in, $selected, $crypto_total, $this->qrcode_size );
     541                $qr_code_data       = CryptAPI\Helper::get_static_qrcode( $addr_in, $selected, '', $this->qrcode_size );
     542
     543                $order->add_meta_data( 'cryptapi_nonce', $nonce );
     544                $order->add_meta_data( 'cryptapi_address', $addr_in );
     545                $order->add_meta_data( 'cryptapi_total', CryptAPI\Helper::sig_fig( $crypto_total, 6 ) );
     546                $order->add_meta_data( 'cryptapi_total_fiat', $total );
     547                $order->add_meta_data( 'cryptapi_currency', $selected );
     548                $order->add_meta_data( 'cryptapi_qr_code_value', $qr_code_data_value['qr_code'] );
     549                $order->add_meta_data( 'cryptapi_qr_code', $qr_code_data['qr_code'] );
     550                $order->add_meta_data( 'cryptapi_last_price_update', time() );
     551                $order->add_meta_data( 'cryptapi_cancelled', '0' );
     552                $order->add_meta_data( 'cryptapi_min', $min_tx );
     553                $order->add_meta_data( 'cryptapi_history', json_encode( [] ) );
     554                $order->add_meta_data( 'cryptapi_callback_url', $callback_url );
     555                $order->add_meta_data( 'cryptapi_last_checked', $order->get_date_created()->getTimestamp() );
     556                $order->save_meta_data();
     557
     558                $order->update_status( 'on-hold', __( 'Awaiting payment', 'cryptapi' ) . ': ' . WC_CryptAPI_Gateway::$COIN_OPTIONS[ $selected ] );
     559                $woocommerce->cart->empty_cart();
     560
     561                return array(
     562                    'result'   => 'success',
     563                    'redirect' => $this->get_return_url( $order )
     564                );
     565
     566            } catch ( Exception $e ) {
     567                wc_add_notice( __( 'Payment error:', 'cryptapi' ) . 'Unknown coin', 'error' );
     568
     569                return null;
     570            }
     571        }
     572
     573        wc_add_notice( __( 'Payment error:', 'woocommerce' ) . __( 'Payment could not be processed, please try again', 'cryptapi' ), 'error' );
     574
     575        return null;
     576    }
     577
     578    function validate_payment() {
     579        $data = CryptAPI\Helper::process_callback( $_GET );
     580
     581        $order = new WC_Order( $data['order_id'] );
     582
     583        if ( $order->is_paid() || $order->get_status() === 'cancelled' || $data['nonce'] != $order->get_meta( 'cryptapi_nonce' ) ) {
     584            die( "*ok*" );
     585        }
     586
     587        $order->update_meta_data( 'cryptapi_last_checked', time() );
     588        $order->save_meta_data();
     589
     590        // Actually process the callback data
     591        $this->process_callback_data( $data, $order );
     592    }
     593
     594    function order_status() {
     595        $order_id = sanitize_text_field( $_REQUEST['order_id'] );
     596
     597        try {
     598            $order = new WC_Order( $order_id );
     599
     600            $showMinFee = '0';
     601
     602            $history = json_decode( $order->get_meta( 'cryptapi_history' ), true );
     603
     604            $calc = $this->calc_order( $history, $order->get_meta( 'cryptapi_total' ), $order->get_meta( 'cryptapi_total_fiat' ) );
     605
     606            $already_paid      = $calc['already_paid'];
     607            $already_paid_fiat = $calc['already_paid_fiat'];
     608
     609            $min_tx = floatval( $order->get_meta( 'cryptapi_min' ) );
     610
     611            $remaining_pending = $calc['remaining_pending'];
     612            $remaining_fiat    = $calc['remaining_fiat'];
     613
     614            $cryptapi_pending = 0;
     615
     616            $counter_calc = (int) $order->get_meta( 'cryptapi_last_price_update' ) + (int) $this->refresh_value_interval - time();
     617
     618            if ( $remaining_pending <= 0 && ! $order->is_paid() ) {
     619                $cryptapi_pending = 1;
     620            }
     621
     622            if ( $counter_calc <= 0 && ! $order->is_paid() ) {
     623                $this->ca_cronjob();
     624            }
     625
     626            if ( $remaining_pending <= $min_tx && $remaining_pending > 0 ) {
     627                $remaining_pending = $min_tx;
     628                $showMinFee        = 1;
     629            }
     630
     631            $data = [
     632                'is_paid'           => $order->is_paid(),
     633                'is_pending'        => $cryptapi_pending,
     634                'qr_code_value'     => $order->get_meta( 'cryptapi_qr_code_value' ),
     635                'cancelled'         => (int) $order->get_meta( 'cryptapi_cancelled' ),
     636                'coin'              => strtoupper( $order->get_meta( 'cryptapi_currency' ) ),
     637                'show_min_fee'      => $showMinFee,
     638                'order_history'     => json_decode( $order->get_meta( 'cryptapi_history' ), true ),
     639                'counter'           => (string) $counter_calc,
     640                'crypto_total'      => floatval( $order->get_meta( 'cryptapi_total' ) ),
     641                'already_paid'      => $already_paid,
     642                'remaining'         => $remaining_pending <= 0 ? 0 : $remaining_pending,
     643                'fiat_remaining'    => $remaining_fiat <= 0 ? 0 : $remaining_fiat,
     644                'already_paid_fiat' => floatval( $already_paid_fiat ) <= 0 ? 0 : floatval( $already_paid_fiat ),
     645                'fiat_symbol'       => get_woocommerce_currency_symbol(),
     646            ];
     647
     648            echo json_encode( $data );
     649            die();
     650
     651        } catch ( Exception $e ) {
     652            //
     653        }
     654
     655        echo json_encode( [ 'status' => 'error', 'error' => 'Not a valid order_id' ] );
     656        die();
     657    }
     658
     659    function validate_logs() {
     660        $order_id = sanitize_text_field( $_REQUEST['order_id'] );
     661        $order = new WC_Order($order_id);
     662
     663        try {
     664
     665            $callbacks = CryptAPI\Helper::check_logs( $order->get_meta( 'cryptapi_callback_url' ), $order->get_meta( 'cryptapi_currency' ) );
     666
     667            $order->update_meta_data( 'cryptapi_last_checked', time() );
     668            $order->save_meta_data();
     669
     670            if($callbacks) {
     671                foreach ( $callbacks as $callback ) {
     672                    $logs        = $callback->logs;
     673                    $request_url = parse_url( $logs[0]->request_url );
     674                    parse_str( $request_url['query'], $data );
     675
     676                    if ( empty( $history[ $data->uuid ] ) || ( ! empty( $history[ $data->uuid ] ) && (int) $history[ $data->uuid ]['pending'] === 1 && (int) $data['pending'] === 0 ) ) {
     677                        $this->process_callback_data( $data, $order, true );
     678                    }
     679                }
     680            }
     681            die();
     682        } catch ( Exception $e ) {
     683            //
     684        }
     685        die();
     686    }
     687
     688    function process_callback_data( $data, $order, $validation = false ) {
     689        $paid = floatval( $data['value_coin'] );
     690
     691        $min_tx = floatval( $order->get_meta( 'cryptapi_min' ) );
     692
     693        $crypto_coin = strtoupper( $order->get_meta( 'cryptapi_currency' ) );
     694
     695        $history = json_decode( $order->get_meta( 'cryptapi_history' ), true );
     696
     697        if(!$data['uuid']) {
     698            if ( ! $validation ) {
     699                die( "*ok*" );
     700            } else {
     701                return;
     702            }
    461703        }
    462     }
    463 
    464     function validate_fields()
    465     {
    466         return array_key_exists(sanitize_text_field($_POST['cryptapi_coin']), WC_CryptAPI_Gateway::$COIN_OPTIONS);
    467     }
    468 
    469     function process_payment($order_id)
    470     {
    471         global $woocommerce;
    472 
    473         $selected = sanitize_text_field($_POST['cryptapi_coin']);
    474 
    475         if ($selected === 'none') {
    476             wc_add_notice(__('Payment error: ', 'woocommerce') . ' ' . __('Please choose a cryptocurrency', 'cryptapi'), 'error');
    477 
    478             return null;
    479         }
    480 
    481         $api_key = $this->api_key;
    482         $addr = $this->{$selected . '_address'};
    483 
    484         if (!empty($addr) || !empty($api_key)) {
    485 
    486             $nonce = $this->generate_nonce();
    487 
    488             $callback_url = str_replace('https:', 'http:', add_query_arg(array(
    489                 'wc-api' => 'WC_Gateway_CryptAPI',
    490                 'order_id' => $order_id,
    491                 'nonce' => $nonce,
    492             ), home_url('/')));
    493 
    494             try {
    495                 $order = new WC_Order($order_id);
    496 
    497                 if (in_array('woocommerce-subscriptions/woocommerce-subscriptions.php', apply_filters('active_plugins', get_option('active_plugins')))) {
    498 
    499                     if (wcs_order_contains_subscription($order_id)) {
    500 
    501                         $sign_up_fee = (WC_Subscriptions_Order::get_sign_up_fee($order)) ? 0 : WC_Subscriptions_Order::get_sign_up_fee($order);
    502                         $initial_payment = (WC_Subscriptions_Order::get_total_initial_payment($order)) ? 0 : WC_Subscriptions_Order::get_total_initial_payment($order);
    503                         $price_per_period = (WC_Subscriptions_Order::get_recurring_total($order)) ? 0 : WC_Subscriptions_Order::get_recurring_total($order);
    504 
    505                         $total = $sign_up_fee + $initial_payment + $price_per_period + $order->get_total('edit');
    506 
    507                         if ($total == 0) {
    508                             $order->add_meta_data('cryptapi_currency', $selected);
    509                             $order->save_meta_data();
    510                             $order->payment_complete();
    511                             $woocommerce->cart->empty_cart();
    512 
    513                             return array(
    514                                 'result' => 'success',
    515                                 'redirect' => $this->get_return_url($order)
    516                             );
    517                         }
    518                     }
    519                 }
    520 
    521                 $total = $order->get_total('edit');
    522 
    523                 $currency = get_woocommerce_currency();
    524 
    525                 $info = CryptAPI\Helper::get_info($selected);
    526                 $min_tx = CryptAPI\Helper::sig_fig($info->minimum_transaction_coin, 6);
    527 
    528                 $crypto_total = CryptAPI\Helper::get_conversion($currency, $selected, $total, $this->disable_conversion);
    529 
    530                 if ($crypto_total < $min_tx) {
    531                     wc_add_notice(__('Payment error:', 'woocommerce') . ' ' . __('Value too low, minimum is', 'cryptapi') . ' ' . $min_tx . ' ' . strtoupper($selected), 'error');
    532 
    533                     return null;
    534                 }
    535 
    536                 $ca = new CryptAPI\Helper($selected, $addr, $api_key, $callback_url, [], true);
    537 
    538                 $addr_in = $ca->get_address();
    539 
    540                 if (empty($addr_in)) {
    541                     wc_add_notice(__('Payment error:', 'woocommerce') . ' ' . __('There was an error with the payment. Please try again.', 'cryptapi'));
    542 
    543                     return null;
    544                 }
    545 
    546                 $qr_code_data_value = CryptAPI\Helper::get_static_qrcode($addr_in, $selected, $crypto_total, $this->qrcode_size);
    547                 $qr_code_data = CryptAPI\Helper::get_static_qrcode($addr_in, $selected, '', $this->qrcode_size);
    548 
    549                 $order->add_meta_data('cryptapi_nonce', $nonce);
    550                 $order->add_meta_data('cryptapi_address', $addr_in);
    551                 $order->add_meta_data('cryptapi_total', CryptAPI\Helper::sig_fig($crypto_total, 6));
    552                 $order->add_meta_data('cryptapi_total_fiat', $total);
    553                 $order->add_meta_data('cryptapi_currency', $selected);
    554                 $order->add_meta_data('cryptapi_qr_code_value', $qr_code_data_value['qr_code']);
    555                 $order->add_meta_data('cryptapi_qr_code', $qr_code_data['qr_code']);
    556                 $order->add_meta_data('cryptapi_last_price_update', time());
    557                 $order->add_meta_data('cryptapi_cancelled', '0');
    558                 $order->add_meta_data('cryptapi_min', $min_tx);
    559                 $order->add_meta_data('cryptapi_history', json_encode([]));
    560                 $order->add_meta_data('cryptapi_callback_url', $callback_url);
    561                 $order->add_meta_data('cryptapi_last_checked', $order->get_date_created()->getTimestamp());
    562                 $order->save_meta_data();
    563 
    564                 $order->update_status('on-hold', __('Awaiting payment', 'cryptapi') . ': ' . WC_CryptAPI_Gateway::$COIN_OPTIONS[$selected]);
    565                 $woocommerce->cart->empty_cart();
    566 
    567                 return array(
    568                     'result' => 'success',
    569                     'redirect' => $this->get_return_url($order)
    570                 );
    571 
    572             } catch (Exception $e) {
    573                 wc_add_notice(__('Payment error:', 'cryptapi') . 'Unknown coin', 'error');
    574 
    575                 return null;
    576             }
    577         }
    578 
    579         wc_add_notice(__('Payment error:', 'woocommerce') . __('Payment could not be processed, please try again', 'cryptapi'), 'error');
    580 
    581         return null;
    582     }
    583 
    584     function validate_payment()
    585     {
    586         $data = CryptAPI\Helper::process_callback($_GET);
    587 
    588         $order = new WC_Order($data['order_id']);
    589 
    590         if ($order->is_paid() || $order->get_status() === 'cancelled' || $data['nonce'] != $order->get_meta('cryptapi_nonce')) {
    591             die("*ok*");
    592         }
    593 
    594         $order->update_meta_data('cryptapi_last_checked', time());
    595         $order->save_meta_data();
    596 
    597         // Actually process the callback data
    598         $this->process_callback_data($data, $order);
    599     }
    600 
    601     function order_status()
    602     {
    603         $order_id = sanitize_text_field($_REQUEST['order_id']);
    604 
    605         try {
    606             $order = new WC_Order($order_id);
    607 
    608             $showMinFee = '0';
    609 
    610             $history = json_decode($order->get_meta('cryptapi_history'), true);
    611 
    612             $calc = $this->calc_order($history, $order->get_meta('cryptapi_total'), $order->get_meta('cryptapi_total_fiat'));
    613 
    614             $already_paid = $calc['already_paid'];
    615             $already_paid_fiat = $calc['already_paid_fiat'];
    616 
    617             $min_tx = floatval($order->get_meta('cryptapi_min'));
    618 
    619             $remaining_pending = $calc['remaining_pending'];
    620             $remaining_fiat = $calc['remaining_fiat'];
    621 
    622             $cryptapi_pending = 0;
    623 
    624             $counter_calc = (int)$order->get_meta('cryptapi_last_price_update') + (int)$this->refresh_value_interval - time();
    625 
    626             if ($remaining_pending <= 0 && !$order->is_paid()) {
    627                 $cryptapi_pending = 1;
    628             }
    629 
    630             if ($counter_calc <= 0 && !$order->is_paid()) {
    631                 $this->ca_cronjob();
    632             }
    633 
    634             if ($remaining_pending <= $min_tx && $remaining_pending > 0) {
    635                 $remaining_pending = $min_tx;
    636                 $showMinFee = 1;
    637             }
    638 
    639             if (((int)$order->get_meta('cryptapi_last_checked') + 60) < time() && (int)$order->get_meta('cryptapi_cancelled') === 0 && !$order->is_paid()) {
    640                 $this->validate_logs($order, $history);
    641             }
    642 
    643             $data = [
    644                 'is_paid' => $order->is_paid(),
    645                 'is_pending' => $cryptapi_pending,
    646                 'qr_code_value' => $order->get_meta('cryptapi_qr_code_value'),
    647                 'cancelled' => (int)$order->get_meta('cryptapi_cancelled'),
    648                 'coin' => strtoupper($order->get_meta('cryptapi_currency')),
    649                 'show_min_fee' => $showMinFee,
    650                 'order_history' => json_decode($order->get_meta('cryptapi_history'), true),
    651                 'counter' => (string)$counter_calc,
    652                 'crypto_total' => floatval($order->get_meta('cryptapi_total')),
    653                 'already_paid' => $already_paid,
    654                 'remaining' => $remaining_pending <= 0 ? 0 : $remaining_pending,
    655                 'fiat_remaining' => $remaining_fiat <= 0 ? 0 : $remaining_fiat,
    656                 'already_paid_fiat' => floatval($already_paid_fiat) <= 0 ? 0 : floatval($already_paid_fiat),
    657                 'fiat_symbol' => get_woocommerce_currency_symbol(),
    658             ];
    659 
    660             echo json_encode($data);
    661             die();
    662 
    663         } catch (Exception $e) {
    664             //
    665         }
    666 
    667         echo json_encode(['status' => 'error', 'error' => 'Not a valid order_id']);
    668         die();
    669     }
    670 
    671     function validate_logs($order, $history)
    672     {
    673         $callbacks = CryptAPI\Helper::check_logs($order->get_meta('cryptapi_callback_url'), $order->get_meta('cryptapi_currency'));
    674 
    675         $order->update_meta_data('cryptapi_last_checked', time());
    676         $order->save_meta_data();
    677 
    678         foreach ($callbacks as $callback) {
    679             $logs = $callback->logs;
    680             $request_url = parse_url($logs[0]->request_url);
    681             parse_str($request_url['query'], $data);
    682 
    683             if (empty($history[$data->uuid]) || (!empty($history[$data->uuid]) && (int)$history[$data->uuid]['pending'] === 1 && (int)$data['pending'] === 0)) {
    684                 $this->process_callback_data($data, $order, true);
    685             }
    686         }
    687     }
    688 
    689     function process_callback_data($data, $order, $validation = false)
    690     {
    691         $paid = floatval($data['value_coin']);
    692 
    693         $min_tx = floatval($order->get_meta('cryptapi_min'));
    694 
    695         $crypto_coin = strtoupper($order->get_meta('cryptapi_currency'));
    696 
    697         $history = json_decode($order->get_meta('cryptapi_history'), true);
    698 
    699         if (empty($history[$data['uuid']])) {
    700             $conversion = json_decode(stripcslashes($data['value_coin_convert']), true);
    701 
    702             $history[$data['uuid']] = [
    703                 'timestamp' => time(),
    704                 'value_paid' => CryptAPI\Helper::sig_fig($paid, 6),
    705                 'value_paid_fiat' => $conversion[get_woocommerce_currency()],
    706                 'pending' => $data['pending']
    707             ];
    708         } else {
    709             $history[$data['uuid']]['pending'] = $data['pending'];
    710         }
    711 
    712         $order->update_meta_data('cryptapi_history', json_encode($history));
    713         $order->save_meta_data();
    714 
    715         $calc = $this->calc_order(json_decode($order->get_meta('cryptapi_history'), true), $order->get_meta('cryptapi_total'), $order->get_meta('cryptapi_total_fiat'));
    716 
    717         $remaining = $calc['remaining'];
    718         $remaining_pending = $calc['remaining_pending'];
    719 
    720         $order_notes = $this->get_private_order_notes($order->get_id());
    721 
    722         $has_pending = false;
    723         $has_confirmed = false;
    724 
    725         foreach ($order_notes as $note) {
    726             $note_content = $note['note_content'];
    727 
    728             if (strpos((string)$note_content, 'PENDING') && strpos((string)$note_content, $data['txid_in'])) {
    729                 $has_pending = true;
    730             }
    731 
    732             if (strpos((string)$note_content, 'CONFIRMED') && strpos((string)$note_content, $data['txid_in'])) {
    733                 $has_confirmed = true;
    734             }
    735         }
    736 
    737         if (!$has_pending) {
    738             $order->add_order_note(
    739                 '[PENDING] ' .
    740                 __('User sent a payment of', 'cryptapi') . ' ' .
    741                 $paid . ' ' . $crypto_coin .
    742                 '. TXID: ' . $data['txid_in']
    743             );
    744         }
    745 
    746         if (!$has_confirmed && (int)$data['pending'] === 0) {
    747             $order->add_order_note(
    748                 '[CONFIRMED] ' . __('User sent a payment of', 'cryptapi') . ' ' .
    749                 $paid . ' ' . $crypto_coin .
    750                 '. TXID: ' . $data['txid_in']
    751             );
    752 
    753             if ($remaining > 0) {
    754                 if ($remaining < $min_tx) {
    755                     $order->add_order_note(__('Payment detected and confirmed. Customer still need to send', 'cryptapi') . ' ' . $min_tx . $crypto_coin, false);
    756                 } else {
    757                     $order->add_order_note(__('Payment detected and confirmed. Customer still need to send', 'cryptapi') . ' ' . $remaining . $crypto_coin, false);
    758                 }
    759             }
    760         }
    761 
    762         if ($remaining_pending <= 0) {
    763             if ($remaining <= 0) {
    764                 $order->payment_complete($data['address_in']);
    765                 if ($this->virtual_complete) {
    766                     $count_products = count($order->get_items());
    767                     $count_virtual = 0;
    768                     foreach ($order->get_items() as $order_item) {
    769                         $item = wc_get_product($order_item->get_product_id());
    770                         $item_obj = $item->get_type() === 'variable' ? wc_get_product($order_item['variation_id']) : $item;
    771 
    772                         if ($item_obj->is_virtual()) {
    773                             $count_virtual += 1;
    774                         }
    775                     }
    776                     if ($count_virtual === $count_products) {
    777                         $order->update_status('completed');
    778                     }
    779                 }
    780                 $order->save();
    781             }
    782             if (!$validation) {
    783                 die("*ok*");
    784             } else {
    785                 return;
    786             }
    787         }
    788 
    789         if ($remaining_pending < $min_tx) {
    790             $order->update_meta_data('cryptapi_qr_code_value', CryptAPI\Helper::get_static_qrcode($order->get_meta('cryptapi_address'), $order->get_meta('cryptapi_currency'), $min_tx, $this->qrcode_size)['qr_code']);
    791         } else {
    792             $order->update_meta_data('cryptapi_qr_code_value', CryptAPI\Helper::get_static_qrcode($order->get_meta('cryptapi_address'), $order->get_meta('cryptapi_currency'), $remaining_pending, $this->qrcode_size)['qr_code']);
    793         }
    794         $order->save_meta_data();
    795 
    796         if (!$validation) {
    797             die("*ok*");
    798         }
    799     }
    800 
    801     function thankyou_page($order_id)
    802     {
    803         if (WC_CryptAPI_Gateway::$HAS_TRIGGERED) {
    804             return;
    805         }
    806         WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
    807 
    808         $order = new WC_Order($order_id);
    809         $total = $order->get_total();
    810         $currency_symbol = get_woocommerce_currency_symbol();
    811         $address_in = $order->get_meta('cryptapi_address');
    812         $crypto_value = $order->get_meta('cryptapi_total');
    813         $crypto_coin = $order->get_meta('cryptapi_currency');
    814         $qr_code_img_value = $order->get_meta('cryptapi_qr_code_value');
    815         $qr_code_img = $order->get_meta('cryptapi_qr_code');
    816         $qr_code_setting = $this->get_option('qrcode_setting');
    817         $color_scheme = $this->get_option('color_scheme');
    818         $min_tx = $order->get_meta('cryptapi_min');
    819 
    820         $ajax_url = add_query_arg(array(
    821             'action' => 'cryptapi_order_status',
    822             'order_id' => $order_id,
    823         ), home_url('/wp-admin/admin-ajax.php'));
    824 
    825         wp_enqueue_script('ca-payment', CRYPTAPI_PLUGIN_URL . 'static/payment.js', array(), CRYPTAPI_PLUGIN_VERSION, true);
    826         wp_add_inline_script('ca-payment', "jQuery(function() {let ajax_url = '{$ajax_url}'; setTimeout(function(){check_status(ajax_url)}, 500)})");
    827         wp_enqueue_style('ca-loader-css', CRYPTAPI_PLUGIN_URL . 'static/cryptapi.css', false, CRYPTAPI_PLUGIN_VERSION);
    828 
    829         $allowed_to_value = array(
    830             'btc',
    831             'eth',
    832             'bch',
    833             'ltc',
    834             'miota',
    835             'xmr',
    836         );
    837 
    838         $crypto_allowed_value = false;
    839 
    840         $conversion_timer = ((int)$order->get_meta('cryptapi_last_price_update') + (int)$this->refresh_value_interval) - time();
    841         $cancel_timer = $order->get_date_created()->getTimestamp() + (int)$this->order_cancelation_timeout - time();
    842 
    843         if (in_array($crypto_coin, $allowed_to_value, true)) {
    844             $crypto_allowed_value = true;
    845         }
    846         ?>
    847         <div class="ca_payment-panel<?php
    848         if ($color_scheme == 'auto') {
    849             echo ' auto';
    850         } elseif ($color_scheme == 'light') {
    851             echo ' light';
    852         } else {
    853             echo ' dark';
    854         }
    855         ?>">
     704
     705        if ( empty( $history[ $data['uuid'] ] ) ) {
     706            $conversion = json_decode( stripcslashes( $data['value_coin_convert'] ), true );
     707
     708            $history[ $data['uuid'] ] = [
     709                'timestamp'       => time(),
     710                'value_paid'      => CryptAPI\Helper::sig_fig( $paid, 6 ),
     711                'value_paid_fiat' => $conversion[ get_woocommerce_currency() ],
     712                'pending'         => $data['pending']
     713            ];
     714        } else {
     715            $history[ $data['uuid'] ]['pending'] = $data['pending'];
     716        }
     717
     718        $order->update_meta_data( 'cryptapi_history', json_encode( $history ) );
     719        $order->save_meta_data();
     720
     721        $calc = $this->calc_order( json_decode( $order->get_meta( 'cryptapi_history' ), true ), $order->get_meta( 'cryptapi_total' ), $order->get_meta( 'cryptapi_total_fiat' ) );
     722
     723        $remaining         = $calc['remaining'];
     724        $remaining_pending = $calc['remaining_pending'];
     725
     726        $order_notes = $this->get_private_order_notes( $order->get_id() );
     727
     728        $has_pending   = false;
     729        $has_confirmed = false;
     730
     731        foreach ( $order_notes as $note ) {
     732            $note_content = $note['note_content'];
     733
     734            if ( strpos( (string) $note_content, 'PENDING' ) && strpos( (string) $note_content, $data['txid_in'] ) ) {
     735                $has_pending = true;
     736            }
     737
     738            if ( strpos( (string) $note_content, 'CONFIRMED' ) && strpos( (string) $note_content, $data['txid_in'] ) ) {
     739                $has_confirmed = true;
     740            }
     741        }
     742
     743        if ( ! $has_pending ) {
     744            $order->add_order_note(
     745                '[PENDING] ' .
     746                __( 'User sent a payment of', 'cryptapi' ) . ' ' .
     747                $paid . ' ' . $crypto_coin .
     748                '. TXID: ' . $data['txid_in']
     749            );
     750        }
     751
     752        if ( ! $has_confirmed && (int) $data['pending'] === 0 ) {
     753            $order->add_order_note(
     754                '[CONFIRMED] ' . __( 'User sent a payment of', 'cryptapi' ) . ' ' .
     755                $paid . ' ' . $crypto_coin .
     756                '. TXID: ' . $data['txid_in']
     757            );
     758
     759            if ( $remaining > 0 ) {
     760                if ( $remaining < $min_tx ) {
     761                    $order->add_order_note( __( 'Payment detected and confirmed. Customer still need to send', 'cryptapi' ) . ' ' . $min_tx . $crypto_coin, false );
     762                } else {
     763                    $order->add_order_note( __( 'Payment detected and confirmed. Customer still need to send', 'cryptapi' ) . ' ' . $remaining . $crypto_coin, false );
     764                }
     765            }
     766        }
     767
     768        if ( $remaining_pending <= 0 ) {
     769            if ( $remaining <= 0 ) {
     770                $order->payment_complete( $data['address_in'] );
     771                if ( $this->virtual_complete ) {
     772                    $count_products = count( $order->get_items() );
     773                    $count_virtual  = 0;
     774                    foreach ( $order->get_items() as $order_item ) {
     775                        $item     = wc_get_product( $order_item->get_product_id() );
     776                        $item_obj = $item->get_type() === 'variable' ? wc_get_product( $order_item['variation_id'] ) : $item;
     777
     778                        if ( $item_obj->is_virtual() ) {
     779                            $count_virtual += 1;
     780                        }
     781                    }
     782                    if ( $count_virtual === $count_products ) {
     783                        $order->update_status( 'completed' );
     784                    }
     785                }
     786                $order->save();
     787            }
     788            if ( ! $validation ) {
     789                die( "*ok*" );
     790            } else {
     791                return;
     792            }
     793        }
     794
     795        if ( $remaining_pending < $min_tx ) {
     796            $order->update_meta_data( 'cryptapi_qr_code_value', CryptAPI\Helper::get_static_qrcode( $order->get_meta( 'cryptapi_address' ), $order->get_meta( 'cryptapi_currency' ), $min_tx, $this->qrcode_size )['qr_code'] );
     797        } else {
     798            $order->update_meta_data( 'cryptapi_qr_code_value', CryptAPI\Helper::get_static_qrcode( $order->get_meta( 'cryptapi_address' ), $order->get_meta( 'cryptapi_currency' ), $remaining_pending, $this->qrcode_size )['qr_code'] );
     799        }
     800        $order->save_meta_data();
     801
     802        if ( ! $validation ) {
     803            die( "*ok*" );
     804        }
     805    }
     806
     807    function thankyou_page( $order_id ) {
     808        if ( WC_CryptAPI_Gateway::$HAS_TRIGGERED ) {
     809            return;
     810        }
     811        WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
     812
     813        $order             = new WC_Order( $order_id );
     814        $total             = $order->get_total();
     815        $currency_symbol   = get_woocommerce_currency_symbol();
     816        $address_in        = $order->get_meta( 'cryptapi_address' );
     817        $crypto_value      = $order->get_meta( 'cryptapi_total' );
     818        $crypto_coin       = $order->get_meta( 'cryptapi_currency' );
     819        $qr_code_img_value = $order->get_meta( 'cryptapi_qr_code_value' );
     820        $qr_code_img       = $order->get_meta( 'cryptapi_qr_code' );
     821        $qr_code_setting   = $this->get_option( 'qrcode_setting' );
     822        $color_scheme      = $this->get_option( 'color_scheme' );
     823        $min_tx            = $order->get_meta( 'cryptapi_min' );
     824
     825        $ajax_url = add_query_arg( array(
     826            'action'   => 'cryptapi_order_status',
     827            'order_id' => $order_id,
     828        ), home_url( '/wp-admin/admin-ajax.php' ) );
     829
     830        wp_enqueue_script( 'ca-payment', CRYPTAPI_PLUGIN_URL . 'static/payment.js', array(), CRYPTAPI_PLUGIN_VERSION, true );
     831        wp_add_inline_script( 'ca-payment', "jQuery(function() {let ajax_url = '{$ajax_url}'; setTimeout(function(){check_status(ajax_url)}, 500)})" );
     832        wp_enqueue_style( 'ca-loader-css', CRYPTAPI_PLUGIN_URL . 'static/cryptapi.css', false, CRYPTAPI_PLUGIN_VERSION );
     833
     834        $allowed_to_value = array(
     835            'btc',
     836            'eth',
     837            'bch',
     838            'ltc',
     839            'miota',
     840            'xmr',
     841        );
     842
     843        $crypto_allowed_value = false;
     844
     845        $conversion_timer = ( (int) $order->get_meta( 'cryptapi_last_price_update' ) + (int) $this->refresh_value_interval ) - time();
     846        $cancel_timer     = $order->get_date_created()->getTimestamp() + (int) $this->order_cancelation_timeout - time();
     847
     848        if ( in_array( $crypto_coin, $allowed_to_value, true ) ) {
     849            $crypto_allowed_value = true;
     850        }
     851        ?>
     852        <div class="ca_payment-panel<?php esc_attr( $color_scheme ) ?>">
    856853            <div class="ca_payment_details">
    857                 <?php
    858                 if ($total > 0) {
    859                     ?>
     854                <?php
     855                if ( $total > 0 ) {
     856                    ?>
    860857                    <div class="ca_payments_wrapper">
    861858                        <div class="ca_qrcode_wrapper" style="<?php
    862                         if ($this->qrcode_default) {
    863                             echo 'display: block';
    864                         } else {
    865                             echo 'display: none';
    866                         }
    867                         ?>; width: <?php echo intval($this->qrcode_size) + 20; ?>px;">
    868                             <?php
    869                             if ($crypto_allowed_value == true) {
    870                                 ?>
     859                        if ( $this->qrcode_default ) {
     860                            echo 'display: block';
     861                        } else {
     862                            echo 'display: none';
     863                        }
     864                        ?>; width: <?php echo intval( $this->qrcode_size ) + 20; ?>px;">
     865                            <?php
     866                            if ( $crypto_allowed_value == true ) {
     867                                ?>
    871868                                <div class="inner-wrapper">
    872869                                    <figure>
    873                                         <?php
    874                                         if ($qr_code_setting != 'hide_ammount') {
    875                                             ?>
     870                                        <?php
     871                                        if ( $qr_code_setting != 'hide_ammount' ) {
     872                                            ?>
    876873                                            <img class="ca_qrcode no_value" <?php
    877                                             if ($qr_code_setting == 'ammount') {
    878                                                 echo 'style="display:none;"';
    879                                             }
    880                                             ?> src="data:image/png;base64,<?php echo $qr_code_img; ?>" alt="<?php echo __('QR Code without value', 'cryptapi'); ?>"/>
    881                                             <?php
    882                                         }
    883                                         if ($qr_code_setting != 'hide_without_ammount') {
    884                                             ?>
     874                                            if ( $qr_code_setting == 'ammount' ) {
     875                                                echo 'style="display:none;"';
     876                                            }
     877                                            ?> src="data:image/png;base64,<?php echo $qr_code_img; ?>" alt="<?php echo esc_attr( __( 'QR Code without value', 'cryptapi' ) ); ?>"/>
     878                                            <?php
     879                                        }
     880                                        if ( $qr_code_setting != 'hide_without_ammount' ) {
     881                                            ?>
    885882                                            <img class="ca_qrcode value" <?php
    886                                             if ($qr_code_setting == 'without_ammount') {
    887                                                 echo 'style="display:none;"';
    888                                             }
    889                                             ?> src="data:image/png;base64,<?php echo $qr_code_img_value; ?>"
    890                                                  alt="<?php echo __('QR Code with value', 'cryptapi'); ?>"/>
    891                                             <?php
    892                                         }
    893                                         ?>
     883                                            if ( $qr_code_setting == 'without_ammount' ) {
     884                                                echo 'style="display:none;"';
     885                                            }
     886                                            ?> src="data:image/png;base64,<?php echo $qr_code_img_value; ?>"
     887                                                 alt="<?php echo esc_attr( __( 'QR Code with value', 'cryptapi' ) ); ?>"/>
     888                                            <?php
     889                                        }
     890                                        ?>
    894891                                    </figure>
    895                                     <?php
    896                                     if ($qr_code_setting != 'hide_ammount' && $qr_code_setting != 'hide_without_ammount') {
    897                                         ?>
     892                                    <?php
     893                                    if ( $qr_code_setting != 'hide_ammount' && $qr_code_setting != 'hide_without_ammount' ) {
     894                                        ?>
    898895                                        <div class="ca_qrcode_buttons">
    899                                         <?php
    900                                         if ($qr_code_setting != 'hide_without_ammount') {
    901                                             ?>
    902                                             <button class="ca_qrcode_btn no_value<?php
    903                                             if ($qr_code_setting == 'without_ammount') {
    904                                                 echo ' active';
    905                                             }
    906                                             ?>" aria-label="<?php echo __('Show QR Code without value', 'cryptapi'); ?>">
    907                                                 <?php echo __('ADDRESS', 'cryptapi'); ?>
     896                                        <?php
     897                                        if ( $qr_code_setting != 'hide_without_ammount' ) {
     898                                            ?>
     899                                            <button class="ca_qrcode_btn no_value <?php
     900                                            if ( $qr_code_setting == 'without_ammount' ) {
     901                                                echo " active";
     902                                            }
     903                                            ?>" aria-label="<?php echo esc_attr( __( 'Show QR Code without value', 'cryptapi' ) ); ?>">
     904                                                <?php echo esc_attr( __( 'ADDRESS', 'cryptapi' ) ); ?>
    908905                                            </button>
    909                                             <?php
    910                                         }
    911                                         if ($qr_code_setting != 'hide_ammount') {
    912                                             ?>
     906                                            <?php
     907                                        }
     908                                        if ( $qr_code_setting != 'hide_ammount' ) {
     909                                            ?>
    913910                                            <button class="ca_qrcode_btn value<?php
    914                                             if ($qr_code_setting == 'ammount') {
    915                                                 echo ' active';
    916                                             }
    917                                             ?>" aria-label="<?php echo __('Show QR Code with value', 'cryptapi'); ?>">
    918                                                 <?php echo __('WITH AMOUNT', 'cryptapi'); ?>
     911                                            if ( $qr_code_setting == 'ammount' ) {
     912                                                echo " active";
     913                                            }
     914                                            ?>" aria-label="<?php echo esc_attr( __( 'Show QR Code with value', 'cryptapi' ) ); ?>">
     915                                                <?php echo esc_attr( __( 'WITH AMOUNT', 'cryptapi' ) ); ?>
    919916                                            </button>
    920917                                            </div>
    921                                             <?php
    922                                         }
    923                                     }
    924                                     ?>
     918                                            <?php
     919                                        }
     920                                    }
     921                                    ?>
    925922                                </div>
    926                                 <?php
    927                             } else {
    928                                 ?>
     923                                <?php
     924                            } else {
     925                                ?>
    929926                                <div class="inner-wrapper">
    930927                                    <figure>
    931                                         <img class="ca_qrcode no_value" src="data:image/png;base64,<?php echo $qr_code_img; ?>"
    932                                              alt="<?php echo __('QR Code without value', 'cryptapi'); ?>"/>
     928                                        <img class="ca_qrcode no_value" src="data:image/png;base64,<?php echo esc_attr( $qr_code_img ); ?>"
     929                                             alt="<?php echo esc_attr( __( 'QR Code without value', 'cryptapi' ) ); ?>"/>
    933930                                    </figure>
    934931                                    <div class="ca_qrcode_buttons">
    935                                         <button class="ca_qrcode_btn no_value active" aria-label="<?php echo __('Show QR Code without value', 'cryptapi'); ?>">
    936                                             <?php echo __('ADDRESS', 'cryptapi'); ?>
     932                                        <button class="ca_qrcode_btn no_value active" aria-label="<?php echo esc_attr( __( 'Show QR Code without value', 'cryptapi' ) ); ?>">
     933                                            <?php echo esc_attr( __( 'ADDRESS', 'cryptapi' ) ); ?>
    937934                                        </button>
    938935                                    </div>
    939936                                </div>
    940937
    941                                 <?php
    942                             }
    943                             ?>
     938                                <?php
     939                            }
     940                            ?>
    944941                        </div>
    945942                        <div class="ca_details_box">
    946943                            <div class="ca_details_text">
    947                                 <?php echo __('PLEASE SEND', 'cryptapi') ?>
    948                                 <button class="ca_copy ca_details_copy" data-tocopy="<?php echo $crypto_value; ?>">
    949                                     <span><b class="ca_value"><?php echo $crypto_value ?></b></span>
    950                                     <span><b><?php echo strtoupper($crypto_coin) ?></b></span>
    951                                     <span class="ca_tooltip ca_copy_icon_tooltip tip"><?php echo __('COPY', 'cryptapi'); ?></span>
    952                                     <span class="ca_tooltip ca_copy_icon_tooltip success" style="display: none"><?php echo __('COPIED!', 'cryptapi'); ?></span>
     944                                <?php echo esc_attr( __( 'PLEASE SEND', 'cryptapi' ) ) ?>
     945                                <button class="ca_copy ca_details_copy" data-tocopy="<?php echo esc_attr( $crypto_value ); ?>">
     946                                    <span><b class="ca_value"><?php echo esc_attr( $crypto_value ) ?></b></span>
     947                                    <span><b><?php echo strtoupper( esc_attr( $crypto_coin ) ) ?></b></span>
     948                                    <span class="ca_tooltip ca_copy_icon_tooltip tip"><?php echo esc_attr( __( 'COPY', 'cryptapi' ) ); ?></span>
     949                                    <span class="ca_tooltip ca_copy_icon_tooltip success" style="display: none"><?php echo esc_attr( __( 'COPIED!', 'cryptapi' ) ); ?></span>
    953950                                </button>
    954                                 <strong>(<?php echo "{$currency_symbol}" . " <span class='ca_fiat_total'>" . $total . "</span>"; ?>)</strong>
     951                                <strong>(<?php echo esc_attr( $currency_symbol ) . " <span class='ca_fiat_total'>" . esc_attr( $total ) . "</span>"; ?>)</strong>
    955952                            </div>
    956953                            <div class="ca_payment_notification ca_notification_payment_received" style="display: none;">
    957                                 <?php echo sprintf(__('So far you sent %1s. Please send a new payment to complete the order, as requested above', 'cryptapi'),
    958                                     '<strong><span class="ca_notification_ammount"></span></strong>'
    959                                 ); ?>
     954                                <?php echo sprintf( esc_attr( __( 'So far you sent %1s. Please send a new payment to complete the order, as requested above', 'cryptapi' ) ),
     955                                    '<strong><span class="ca_notification_ammount"></span></strong>'
     956                                ); ?>
    960957                            </div>
    961958                            <div class="ca_payment_notification ca_notification_remaining" style="display: none">
    962                                 <?php echo '<strong>' . __('Notice', 'cryptapi') . '</strong>: ' . sprintf(__('For technical reasons, the minimum amount for each transaction is %1s, so we adjusted the value by adding the remaining to it.', 'cryptapi'),
    963                                         $min_tx . ' ' . strtoupper($crypto_coin),
    964                                         '<span class="ca_notification_remaining"></span>'
    965                                     ); ?>
     959                                <?php echo '<strong>' . esc_attr( __( 'Notice', 'cryptapi' ) ) . '</strong>: ' . sprintf( esc_attr( __( 'For technical reasons, the minimum amount for each transaction is %1s, so we adjusted the value by adding the remaining to it.', 'cryptapi' ) ),
     960                                        $min_tx . ' ' . strtoupper( $crypto_coin ),
     961                                        '<span class="ca_notification_remaining"></span>'
     962                                    ); ?>
    966963                            </div>
    967                             <?php
    968                             if (intval($this->refresh_value_interval) != 0) {
    969                                 ?>
     964                            <?php
     965                            if ( intval( $this->refresh_value_interval ) != 0 ) {
     966                                ?>
    970967                                <div class="ca_time_refresh">
    971                                     <?php echo sprintf(__('The %1s conversion rate will be adjusted in', 'cryptapi'),
    972                                         strtoupper($crypto_coin)
    973                                     ); ?>
    974                                     <span class="ca_time_seconds_count" data-soon="<?php echo __('a moment', 'cryptapi'); ?>"
    975                                           data-seconds="<?php echo $conversion_timer; ?>"><?php echo date('i:s', $conversion_timer); ?></span>
     968                                    <?php echo sprintf( esc_attr( __( 'The %1s conversion rate will be adjusted in', 'cryptapi' ) ),
     969                                        strtoupper( $crypto_coin )
     970                                    ); ?>
     971                                    <span class="ca_time_seconds_count" data-soon="<?php echo esc_attr( __( 'a moment', 'cryptapi' ) ); ?>"
     972                                          data-seconds="<?php echo esc_attr( $conversion_timer ); ?>"><?php echo esc_attr( date( 'i:s', $conversion_timer ) ); ?></span>
    976973                                </div>
    977                                 <?php
    978                             }
    979                             ?>
     974                                <?php
     975                            }
     976                            ?>
    980977                            <div class="ca_details_input">
    981                                 <span><?php echo $address_in ?></span>
    982                                 <button class="ca_copy ca_copy_icon" data-tocopy="<?php echo $address_in; ?>">
    983                                     <span class="ca_tooltip ca_copy_icon_tooltip tip"><?php echo __('COPY', 'cryptapi'); ?></span>
    984                                     <span class="ca_tooltip ca_copy_icon_tooltip success" style="display: none"><?php echo __('COPIED!', 'cryptapi'); ?></span>
     978                                <span><?php echo esc_attr( $address_in ) ?></span>
     979                                <button class="ca_copy ca_copy_icon" data-tocopy="<?php echo esc_attr( $address_in ); ?>">
     980                                    <span class="ca_tooltip ca_copy_icon_tooltip tip"><?php echo esc_attr( __( 'COPY', 'cryptapi' ) ); ?></span>
     981                                    <span class="ca_tooltip ca_copy_icon_tooltip success" style="display: none"><?php echo esc_attr( __( 'COPIED!', 'cryptapi' ) ); ?></span>
    985982                                </button>
    986983                                <div class="ca_loader"></div>
    987984                            </div>
    988985                        </div>
    989                         <?php
    990                         if (intval($this->order_cancelation_timeout) != 0) {
    991                             ?>
    992                             <span class="ca_notification_cancel" data-text="<?php echo __('Order will be cancelled in less than a minute.', 'cryptapi'); ?>">
    993                                     <?php echo sprintf(__('This order will be valid for %s', 'cryptapi'), '<strong><span class="ca_cancel_timer" data-timestamp="' . $cancel_timer . '">' . date('H:i', $cancel_timer) . '</span></strong>'); ?>
     986                        <?php
     987                        if ( intval( $this->order_cancelation_timeout ) != 0 ) {
     988                            ?>
     989                            <span class="ca_notification_cancel" data-text="<?php echo __( 'Order will be cancelled in less than a minute.', 'cryptapi' ); ?>">
     990                                    <?php echo sprintf( esc_attr( __( 'This order will be valid for %s', 'cryptapi' ) ), '<strong><span class="ca_cancel_timer" data-timestamp="' . $cancel_timer . '">' . date( 'H:i', $cancel_timer ) . '</span></strong>' ); ?>
    994991                                </span>
    995                             <?php
    996                         }
    997                         ?>
     992                            <?php
     993                        }
     994                        ?>
    998995                        <div class="ca_buttons_container">
    999                             <a class="ca_show_qr" href="#" aria-label="<?php echo __('Show the QR code', 'cryptapi'); ?>">
    1000                                 <span class="ca_show_qr_open<?php
    1001                                 if (!$this->qrcode_default) {
    1002                                     echo ' active';
     996                            <a class="ca_show_qr" href="#" aria-label="<?php echo esc_attr( __( 'Show the QR code', 'cryptapi' ) ); ?>">
     997                                <span class="ca_show_qr_open <?php
     998                                if ( ! $this->qrcode_default ) {
     999                                    echo " active";
    10031000                                }
    1004                                 ?>"><?php echo __('Open QR CODE', 'cryptapi'); ?></span>
    1005                                 <span class="ca_show_qr_close<?php
    1006                                 if ($this->qrcode_default) {
    1007                                     echo ' active';
    1008                                 }
    1009                                 ?>"><?php echo __('Close QR CODE', 'cryptapi'); ?></span>
     1001                                ?>"><?php echo __( 'Open QR CODE', 'cryptapi' ); ?></span>
     1002                                <span class="ca_show_qr_close <?php
     1003                                if ( $this->qrcode_default ) {
     1004                                    echo " active";
     1005                                }
     1006                                ?>"><?php echo esc_attr( __( 'Close QR CODE', 'cryptapi' ) ); ?></span>
    10101007                            </a>
    10111008                        </div>
    1012                         <?php
    1013                         if ($this->show_branding) {
    1014                             ?>
     1009                        <?php
     1010                        if ( $this->show_branding ) {
     1011                            ?>
    10151012                            <div class="ca_branding">
    10161013                                <a href="https://cryptapi.io/" target="_blank">
    10171014                                    <span>Powered by</span>
    1018                                     <img width="94" class="img-fluid" src="<?php echo CRYPTAPI_PLUGIN_URL . 'static/files/200_logo_ca.png' ?>" alt="Cryptapi Logo"/>
     1015                                    <img width="94" class="img-fluid" src="<?php echo esc_attr( CRYPTAPI_PLUGIN_URL . 'static/files/200_logo_ca.png' ) ?>" alt="Cryptapi Logo"/>
    10191016                                </a>
    10201017                            </div>
    1021                             <?php
    1022                         }
    1023                         ?>
     1018                            <?php
     1019                        }
     1020                        ?>
    10241021                    </div>
    1025                     <?php
    1026                 }
    1027                 if ($total == 0) {
    1028                     ?>
     1022                    <?php
     1023                }
     1024                if ( $total == 0 ) {
     1025                    ?>
    10291026                    <style>
    10301027                        .ca_payment_confirmed {
     
    10331030                        }
    10341031                    </style>
    1035                     <?php
    1036                 }
    1037                 ?>
     1032                    <?php
     1033                }
     1034                ?>
    10381035                <div class="ca_payment_processing" style="display: none;">
    10391036                    <div class="ca_payment_processing_icon">
    10401037                        <div class="ca_loader_payment_processing"></div>
    10411038                    </div>
    1042                     <h2><?php echo __('Your payment is being processed!', 'cryptapi'); ?></h2>
    1043                     <h5><?php echo __('Processing can take some time depending on the blockchain.', 'cryptapi'); ?></h5>
     1039                    <h2><?php echo esc_attr( __( 'Your payment is being processed!', 'cryptapi' ) ); ?></h2>
     1040                    <h5><?php echo esc_attr( __( 'Processing can take some time depending on the blockchain.', 'cryptapi' ) ); ?></h5>
    10441041                </div>
    10451042
     
    10511048                        </svg>
    10521049                    </div>
    1053                     <h2><?php echo __('Your payment has been confirmed!', 'cryptapi'); ?></h2>
     1050                    <h2><?php echo esc_attr( __( 'Your payment has been confirmed!', 'cryptapi' ) ); ?></h2>
    10541051                </div>
    10551052
     
    10611058                        </svg>
    10621059                    </div>
    1063                     <h2><?php echo __('Order has been cancelled due to lack of payment. Please don\'t send any payment to the address.', 'cryptapi'); ?></h2>
     1060                    <h2><?php echo esc_attr( __( 'Order has been cancelled due to lack of payment. Please don\'t send any payment to the address.', 'cryptapi' ) ); ?></h2>
    10641061                </div>
    10651062                <div class="ca_history" style="display: none;">
    10661063                    <table class="ca_history_fill">
    10671064                        <tr class="ca_history_header">
    1068                             <th><strong><?php echo __('Time', 'cryptapi'); ?></strong></th>
    1069                             <th><strong><?php echo __('Value Paid', 'cryptapi'); ?></strong></th>
    1070                             <th><strong><?php echo __('FIAT Value', 'cryptapi'); ?></strong></th>
     1065                            <th><strong><?php echo esc_attr( __( 'Time', 'cryptapi' ) ); ?></strong></th>
     1066                            <th><strong><?php echo esc_attr( __( 'Value Paid', 'cryptapi' ) ); ?></strong></th>
     1067                            <th><strong><?php echo esc_attr( __( 'FIAT Value', 'cryptapi' ) ); ?></strong></th>
    10711068                        </tr>
    10721069                    </table>
    10731070                </div>
    1074                 <?php
    1075                 if ($total > 0) {
    1076                     ?>
     1071                <?php
     1072                if ( $total > 0 ) {
     1073                    ?>
    10771074                    <div class="ca_progress">
    10781075                        <div class="ca_progress_icon waiting_payment done">
     
    10811078                                      fill="#0B4B70"/>
    10821079                            </svg>
    1083                             <p><?php echo __('Waiting for payment', 'cryptapi'); ?></p>
     1080                            <p><?php echo esc_attr( __( 'Waiting for payment', 'cryptapi' ) ); ?></p>
    10841081                        </div>
    10851082                        <div class="ca_progress_icon waiting_network">
     
    10881085                                      fill="#0B4B70"/>
    10891086                            </svg>
    1090                             <p><?php echo __('Waiting for network confirmation', 'cryptapi'); ?></p>
     1087                            <p><?php echo esc_attr( __( 'Waiting for network confirmation', 'cryptapi' ) ); ?></p>
    10911088                        </div>
    10921089                        <div class="ca_progress_icon payment_done">
     
    10951092                                      fill="#0B4B70"/>
    10961093                            </svg>
    1097                             <p><?php echo __('Payment confirmed', 'cryptapi'); ?></p>
     1094                            <p><?php echo esc_attr( __( 'Payment confirmed', 'cryptapi' ) ); ?></p>
    10981095                        </div>
    10991096                    </div>
    1100                     <?php
    1101                 }
    1102                 ?>
     1097                    <?php
     1098                }
     1099                ?>
    11031100            </div>
    11041101        </div>
    1105         <?php
    1106     }
    1107 
    1108     /**
    1109      *  Cronjob
    1110      */
    1111     function ca_cronjob()
    1112     {
    1113         $order_timeout = intval($this->order_cancelation_timeout);
    1114         $value_refresh = intval($this->refresh_value_interval);
    1115 
    1116         if ($order_timeout === 0 && $value_refresh === 0) {
    1117             return;
    1118         }
    1119 
    1120         $orders = wc_get_orders(array(
    1121             'status' => array('wc-on-hold'),
    1122             'payment_method' => 'cryptapi',
    1123         ));
    1124 
    1125         if (empty($orders)) {
    1126             return;
    1127         }
    1128 
    1129         $woocommerce_currency = get_woocommerce_currency();
    1130 
    1131         foreach ($orders as $order) {
    1132             $last_price_update = $order->get_meta('cryptapi_last_price_update');
    1133 
    1134             $history = json_decode($order->get_meta('cryptapi_history'), true);
    1135 
    1136             $min_tx = floatval($order->get_meta('cryptapi_min'));
    1137 
    1138             $calc = $this->calc_order($history, $order->get_meta('cryptapi_total'), $order->get_meta('cryptapi_total_fiat'));
    1139 
    1140             $remaining = $calc['remaining'];
    1141             $remaining_pending = $calc['remaining_pending'];
    1142             $already_paid = $calc['already_paid'];
    1143 
    1144             $order_timestamp = $order->get_date_created()->getTimestamp();
    1145 
    1146             if ((int)$order->get_meta('cryptapi_cancelled') === 0 && ($order_timestamp + 86400) > time()) {
    1147                 $this->validate_logs($order, $history);
    1148             }
    1149 
    1150             if ($value_refresh !== 0 && ((int)$last_price_update + (int)$value_refresh < time()) && !empty($last_price_update)) {
    1151                 if ($remaining === $remaining_pending && $remaining_pending > 0) {
    1152                     $cryptapi_coin = $order->get_meta('cryptapi_currency');
    1153 
    1154                     $crypto_total = CryptAPI\Helper::sig_fig(CryptAPI\Helper::get_conversion($woocommerce_currency, $cryptapi_coin, $order->get_total('edit'), $this->disable_conversion), 6);
    1155                     $order->update_meta_data('cryptapi_total', $crypto_total);
    1156 
    1157                     $calc_cron = $this->calc_order($history, $order->get_meta('cryptapi_total'), $order->get_meta('cryptapi_total_fiat'));
    1158                     $crypto_remaining_total = $calc_cron['remaining_pending'];
    1159 
    1160                     if ($remaining_pending <= $min_tx && !$remaining_pending <= 0) {
    1161                         $qr_code_data_value = CryptAPI\Helper::get_static_qrcode($order->get_meta('cryptapi_address'), $cryptapi_coin, $min_tx, $this->qrcode_size);
    1162                     } else {
    1163                         $qr_code_data_value = CryptAPI\Helper::get_static_qrcode($order->get_meta('cryptapi_address'), $cryptapi_coin, $crypto_remaining_total, $this->qrcode_size);
    1164                     }
    1165 
    1166                     $order->update_meta_data('cryptapi_qr_code_value', $qr_code_data_value['qr_code']);
    1167                 }
    1168 
    1169                 $order->update_meta_data('cryptapi_last_price_update', time());
    1170                 $order->save();
    1171             }
    1172 
    1173             if ($order_timeout !== 0 && ($order_timestamp + $order_timeout) <= time() && $already_paid <= 0 && (int)$order->get_meta('cryptapi_cancelled') === 0) {
    1174                 $order->update_status('cancelled', __('Order cancelled due to lack of payment.', 'cryptapi'));
    1175                 $order->update_meta_data('cryptapi_cancelled', '1');
    1176                 $order->save();
    1177             }
    1178         }
    1179     }
    1180 
    1181     function calc_order($history, $total, $total_fiat)
    1182     {
    1183         $already_paid = 0;
    1184         $already_paid_fiat = 0;
    1185         $remaining = $total;
    1186         $remaining_pending = $total;
    1187         $remaining_fiat = $total_fiat;
    1188 
    1189         if (!empty($history)) {
    1190             foreach ($history as $uuid => $item) {
    1191                 if ((int)$item['pending'] === 0) {
    1192                     $remaining = bcsub(CryptAPI\Helper::sig_fig($remaining, 6), $item['value_paid'], 8);
    1193                 }
    1194 
    1195                 $remaining_pending = bcsub(CryptAPI\Helper::sig_fig($remaining_pending, 6), $item['value_paid'], 8);
    1196                 $remaining_fiat = bcsub(CryptAPI\Helper::sig_fig($remaining_fiat, 6), $item['value_paid_fiat'], 8);
    1197 
    1198                 $already_paid = bcadd(CryptAPI\Helper::sig_fig($already_paid, 6), $item['value_paid'], 8);
    1199                 $already_paid_fiat = bcadd(CryptAPI\Helper::sig_fig($already_paid_fiat, 6), $item['value_paid_fiat'], 8);
    1200             }
    1201         }
    1202 
    1203         return [
    1204             'already_paid' => floatval($already_paid),
    1205             'already_paid_fiat' => floatval($already_paid_fiat),
    1206             'remaining' => floatval($remaining),
    1207             'remaining_pending' => floatval($remaining_pending),
    1208             'remaining_fiat' => floatval($remaining_fiat)
    1209         ];
    1210     }
    1211 
    1212     /**
    1213      * WooCommerce Subscriptions Integration
    1214      */
    1215     function scheduled_subscription_mail($amount, $renewal_order)
    1216     {
    1217 
    1218         $order = $renewal_order;
    1219 
    1220         $costumer_id = get_post_meta($order->get_id(), '_customer_user', true);
    1221         $customer = new WC_Customer($costumer_id);
    1222 
    1223         if (empty($order->get_meta('cryptapi_paid'))) {
    1224             $mailer = WC()->mailer();
    1225 
    1226             $recipient = $customer->get_email();
    1227 
    1228             $subject = sprintf('[%s] %s', get_bloginfo('name'), __('Please renew your subscription', 'cryptapi'));
    1229             $headers = 'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>' . '\r\n';
    1230 
    1231             $content = wc_get_template_html('emails/renewal-email.php', array(
    1232                 'order' => $order,
    1233                 'email_heading' => get_bloginfo('name'),
    1234                 'sent_to_admin' => false,
    1235                 'plain_text' => false,
    1236                 'email' => $mailer
    1237             ), plugin_dir_path(dirname(__FILE__)), plugin_dir_path(dirname(__FILE__)));
    1238 
    1239             $mailer->send($recipient, $subject, $content, $headers);
    1240 
    1241             $order->add_meta_data('cryptapi_paid', '1');
    1242             $order->save_meta_data();
    1243         }
    1244     }
    1245 
    1246     private function generate_nonce($len = 32)
    1247     {
    1248         $data = str_split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
    1249 
    1250         $nonce = [];
    1251         for ($i = 0; $i < $len; $i++) {
    1252             $nonce[] = $data[mt_rand(0, sizeof($data) - 1)];
    1253         }
    1254 
    1255         return implode('', $nonce);
    1256     }
    1257 
    1258     public function generate_cryptocurrency_html($key, $data)
    1259     {
    1260         $field_key = $this->get_field_key($key);
    1261         $defaults = array(
    1262             'title' => '',
    1263             'disabled' => false,
    1264             'class' => '',
    1265             'css' => '',
    1266             'placeholder' => '',
    1267             'type' => 'text',
    1268             'desc_tip' => false,
    1269             'description' => '',
    1270             'custom_attributes' => array(),
    1271         );
    1272 
    1273         $data = wp_parse_args($data, $defaults);
    1274 
    1275         ob_start();
    1276 
    1277         $token = str_replace('_address', '', $key);
    1278         $token_option = $this->get_option('coins');
    1279         if (!empty($token_option)) {
    1280             $token_search = array_search($token, $token_option);
    1281         }
    1282 
    1283         if ($data['custom_attributes']['counter'] === 0) {
    1284             ?>
     1102        <?php
     1103    }
     1104
     1105    /**
     1106     *  Cronjob
     1107     */
     1108    function ca_cronjob() {
     1109        $order_timeout = intval( $this->order_cancelation_timeout );
     1110        $value_refresh = intval( $this->refresh_value_interval );
     1111
     1112        if ( $order_timeout === 0 && $value_refresh === 0 ) {
     1113            return;
     1114        }
     1115
     1116        $orders = wc_get_orders( array(
     1117            'status'         => array( 'wc-on-hold' ),
     1118            'payment_method' => 'cryptapi',
     1119        ) );
     1120
     1121        if ( empty( $orders ) ) {
     1122            return;
     1123        }
     1124
     1125        $woocommerce_currency = get_woocommerce_currency();
     1126
     1127        foreach ( $orders as $order ) {
     1128            $last_price_update = $order->get_meta( 'cryptapi_last_price_update' );
     1129
     1130            $history = json_decode( $order->get_meta( 'cryptapi_history' ), true );
     1131
     1132            $min_tx = floatval( $order->get_meta( 'cryptapi_min' ) );
     1133
     1134            $calc = $this->calc_order( $history, $order->get_meta( 'cryptapi_total' ), $order->get_meta( 'cryptapi_total_fiat' ) );
     1135
     1136            $remaining         = $calc['remaining'];
     1137            $remaining_pending = $calc['remaining_pending'];
     1138            $already_paid      = $calc['already_paid'];
     1139
     1140            $order_timestamp = $order->get_date_created()->getTimestamp();
     1141
     1142            if ( $value_refresh !== 0 && ( (int) $last_price_update + (int) $value_refresh < time() ) && ! empty( $last_price_update ) ) {
     1143                if ( $remaining === $remaining_pending && $remaining_pending > 0 ) {
     1144                    $cryptapi_coin = $order->get_meta( 'cryptapi_currency' );
     1145
     1146                    $crypto_total = CryptAPI\Helper::sig_fig( CryptAPI\Helper::get_conversion( $woocommerce_currency, $cryptapi_coin, $order->get_total( 'edit' ), $this->disable_conversion ), 6 );
     1147                    $order->update_meta_data( 'cryptapi_total', $crypto_total );
     1148
     1149                    $calc_cron              = $this->calc_order( $history, $order->get_meta( 'cryptapi_total' ), $order->get_meta( 'cryptapi_total_fiat' ) );
     1150                    $crypto_remaining_total = $calc_cron['remaining_pending'];
     1151
     1152                    if ( $remaining_pending <= $min_tx && ! $remaining_pending <= 0 ) {
     1153                        $qr_code_data_value = CryptAPI\Helper::get_static_qrcode( $order->get_meta( 'cryptapi_address' ), $cryptapi_coin, $min_tx, $this->qrcode_size );
     1154                    } else {
     1155                        $qr_code_data_value = CryptAPI\Helper::get_static_qrcode( $order->get_meta( 'cryptapi_address' ), $cryptapi_coin, $crypto_remaining_total, $this->qrcode_size );
     1156                    }
     1157
     1158                    $order->update_meta_data( 'cryptapi_qr_code_value', $qr_code_data_value['qr_code'] );
     1159                }
     1160
     1161                $order->update_meta_data( 'cryptapi_last_price_update', time() );
     1162                $order->save();
     1163            }
     1164
     1165            if ( $order_timeout !== 0 && ( $order_timestamp + $order_timeout ) <= time() && $already_paid <= 0 && (int) $order->get_meta( 'cryptapi_cancelled' ) === 0 ) {
     1166                $order->update_status( 'cancelled', __( 'Order cancelled due to lack of payment.', 'cryptapi' ) );
     1167                $order->update_meta_data( 'cryptapi_cancelled', '1' );
     1168                $order->save();
     1169            }
     1170        }
     1171    }
     1172
     1173    function calc_order( $history, $total, $total_fiat ) {
     1174        $already_paid      = 0;
     1175        $already_paid_fiat = 0;
     1176        $remaining         = $total;
     1177        $remaining_pending = $total;
     1178        $remaining_fiat    = $total_fiat;
     1179
     1180        if ( ! empty( $history ) ) {
     1181            foreach ( $history as $uuid => $item ) {
     1182                if ( (int) $item['pending'] === 0 ) {
     1183                    $remaining = bcsub( CryptAPI\Helper::sig_fig( $remaining, 6 ), $item['value_paid'], 8 );
     1184                }
     1185
     1186                $remaining_pending = bcsub( CryptAPI\Helper::sig_fig( $remaining_pending, 6 ), $item['value_paid'], 8 );
     1187                $remaining_fiat    = bcsub( CryptAPI\Helper::sig_fig( $remaining_fiat, 6 ), $item['value_paid_fiat'], 8 );
     1188
     1189                $already_paid      = bcadd( CryptAPI\Helper::sig_fig( $already_paid, 6 ), $item['value_paid'], 8 );
     1190                $already_paid_fiat = bcadd( CryptAPI\Helper::sig_fig( $already_paid_fiat, 6 ), $item['value_paid_fiat'], 8 );
     1191            }
     1192        }
     1193
     1194        return [
     1195            'already_paid'      => floatval( $already_paid ),
     1196            'already_paid_fiat' => floatval( $already_paid_fiat ),
     1197            'remaining'         => floatval( $remaining ),
     1198            'remaining_pending' => floatval( $remaining_pending ),
     1199            'remaining_fiat'    => floatval( $remaining_fiat )
     1200        ];
     1201    }
     1202
     1203    /**
     1204     * WooCommerce Subscriptions Integration
     1205     */
     1206    function scheduled_subscription_mail( $amount, $renewal_order ) {
     1207
     1208        $order = $renewal_order;
     1209
     1210        $costumer_id = get_post_meta( $order->get_id(), '_customer_user', true );
     1211        $customer    = new WC_Customer( $costumer_id );
     1212
     1213        if ( empty( $order->get_meta( 'cryptapi_paid' ) ) ) {
     1214            $mailer = WC()->mailer();
     1215
     1216            $recipient = $customer->get_email();
     1217
     1218            $subject = sprintf( '[%s] %s', get_bloginfo( 'name' ), __( 'Please renew your subscription', 'cryptapi' ) );
     1219            $headers = 'From: ' . get_bloginfo( 'name' ) . ' <' . get_option( 'admin_email' ) . '>' . '\r\n';
     1220
     1221            $content = wc_get_template_html( 'emails/renewal-email.php', array(
     1222                'order'         => $order,
     1223                'email_heading' => get_bloginfo( 'name' ),
     1224                'sent_to_admin' => false,
     1225                'plain_text'    => false,
     1226                'email'         => $mailer
     1227            ), plugin_dir_path( dirname( __FILE__ ) ), plugin_dir_path( dirname( __FILE__ ) ) );
     1228
     1229            $mailer->send( $recipient, $subject, $content, $headers );
     1230
     1231            $order->add_meta_data( 'cryptapi_paid', '1' );
     1232            $order->save_meta_data();
     1233        }
     1234    }
     1235
     1236    private function generate_nonce( $len = 32 ) {
     1237        $data = str_split( 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' );
     1238
     1239        $nonce = [];
     1240        for ( $i = 0; $i < $len; $i ++ ) {
     1241            $nonce[] = $data[ mt_rand( 0, sizeof( $data ) - 1 ) ];
     1242        }
     1243
     1244        return implode( '', $nonce );
     1245    }
     1246
     1247    public function generate_cryptocurrency_html( $key, $data ) {
     1248        $field_key = $this->get_field_key( $key );
     1249        $defaults  = array(
     1250            'title'             => '',
     1251            'disabled'          => false,
     1252            'class'             => '',
     1253            'css'               => '',
     1254            'placeholder'       => '',
     1255            'type'              => 'text',
     1256            'desc_tip'          => false,
     1257            'description'       => '',
     1258            'custom_attributes' => array(),
     1259        );
     1260
     1261        $data = wp_parse_args( $data, $defaults );
     1262
     1263        ob_start();
     1264
     1265        $token        = str_replace( '_address', '', $key );
     1266        $token_option = $this->get_option( 'coins' );
     1267        if ( ! empty( $token_option ) ) {
     1268            $token_search = array_search( $token, $token_option );
     1269        }
     1270
     1271        if ( $data['custom_attributes']['counter'] === 0 ) {
     1272            ?>
    12851273            <tr valign="top">
    12861274                <th scope="row" class="titledesc"></th>
    1287                 <td class="forminp forminp-<?php echo esc_attr($data['type']) ?>">
     1275                <td class="forminp forminp-<?php echo esc_attr( $data['type'] ) ?>">
    12881276                    <p>
    12891277                        <strong>
    1290                             <?php echo __('Addresses', 'cryptapi'); ?>
     1278                            <?php echo esc_attr( __( 'Addresses', 'cryptapi' ) ); ?>
    12911279                        </strong><br/>
    1292                         <?php echo sprintf(__('If you are using BlockBee you can choose if setting the receiving addresses here bellow or in your BlockBee settings page. %1$s - In order to set the addresses on plugin settings, you need to select “Address Override” while creating the API key. %1$s - In order to set the addresses on BlockBee settings, you need to NOT select “Address Override” while creating the API key.', 'cryptapi'), '<br/>'); ?>
     1280                        <?php echo sprintf( esc_attr( __( 'If you are using BlockBee you can choose if setting the receiving addresses here bellow or in your BlockBee settings page. %1$s - In order to set the addresses on plugin settings, you need to select “Address Override” while creating the API key. %1$s - In order to set the addresses on BlockBee settings, you need to NOT select “Address Override” while creating the API key.', 'cryptapi' ) ), '<br/>' ); ?>
    12931281                    </p>
    12941282                </td>
    12951283            </tr>
    1296             <?php
    1297         }
    1298         ?>
     1284            <?php
     1285        }
     1286        ?>
    12991287        <tr valign="top">
    13001288
    13011289            <th scope="row" class="titledesc">
    13021290                <input style="display: inline-block; margin-bottom: -4px;" type="checkbox"
    1303                        name="coins[]" id="<?php echo esc_attr('coins_' . $token); ?>"
    1304                        value="<?php echo str_replace('_address', '', $key); ?>"
    1305                     <?php if (!empty($token_option) && $this->get_option('coins')[$token_search] === $token) {
    1306                         echo 'checked="true" ';
    1307                     } ?> />
    1308                 <label style="display: inline-block; width: 80%;" for="<?php echo esc_attr('coins_' . $token); ?>">
    1309                     <?php echo esc_html($data['title']); ?>
    1310                     <span class="woocommerce-help-tip" data-tip="<?php echo esc_html($data['description']); ?>"></span>
     1291                       name="coins[]" id="<?php echo esc_attr( 'coins_' . $token ); ?>"
     1292                       value="<?php echo str_replace( '_address', '', $key ); ?>"
     1293                    <?php if ( ! empty( $token_option ) && $this->get_option( 'coins' )[ $token_search ] === $token ) {
     1294                        echo 'checked="true" ';
     1295                    } ?> />
     1296                <label style="display: inline-block; width: 80%;" for="<?php echo esc_attr( 'coins_' . $token ); ?>">
     1297                    <?php echo esc_html( $data['title'] ); ?>
     1298                    <span class="woocommerce-help-tip" data-tip="<?php echo esc_html( $data['description'] ); ?>"></span>
    13111299                </label>
    13121300            </th>
    1313             <td class="forminp forminp-<?php echo esc_attr($data['type']) ?>">
    1314                 <input class="input-text regular-input <?php echo esc_attr($data['class']); ?>" type="text" name="<?php echo esc_attr($field_key); ?>"
    1315                        id="<?php echo esc_attr($field_key); ?>" style="<?php echo esc_attr($data['css']); ?>"
    1316                        value="<?php echo $this->get_option($key); ?>"
    1317                        placeholder="<?php echo esc_attr($data['placeholder']); ?>" <?php disabled($data['disabled'], true); ?> <?php echo $this->get_custom_attribute_html($data); // WPCS: XSS ok.
    1318                 ?> />
     1301            <td class="forminp forminp-<?php echo esc_attr( $data['type'] ) ?>">
     1302                <input class="input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field_key ); ?>"
     1303                       id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>"
     1304                       value="<?php echo $this->get_option( $key ); ?>"
     1305                       placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok.
     1306                ?> />
    13191307            </td>
    13201308        </tr>
    13211309
    1322         <?php
    1323         return ob_get_clean();
    1324     }
    1325 
    1326     function handling_fee()
    1327     {
    1328         if (is_admin() && !defined('DOING_AJAX')) {
    1329             return;
    1330         }
    1331 
    1332         $chosen_payment_id = WC()->session->get('chosen_payment_method');
    1333 
    1334         if ($chosen_payment_id != 'cryptapi') {
    1335             return;
    1336         }
    1337 
    1338         $total_fee = $this->get_option('fee_order_percentage') == 'none' ? 0 : $this->get_option('fee_order_percentage');
    1339 
    1340         $fee_order = WC()->cart->subtotal * $total_fee;
    1341 
    1342         if ($total_fee !== 'none' || $this->add_blockchain_fee) {
    1343 
    1344             $selected = WC()->session->get('cryptapi_coin');
    1345 
    1346             if ($selected === 'none') {
    1347                 return;
    1348             }
    1349 
    1350             if (!empty($selected) && $selected != 'none' && $this->add_blockchain_fee) {
    1351                 $est = CryptAPI\Helper::get_estimate($selected);
    1352 
    1353                 $fee_order += (float)$est->{get_woocommerce_currency()};
    1354             }
    1355 
    1356             if (empty($fee_order)) {
    1357                 return;
    1358             }
    1359 
    1360             WC()->cart->add_fee(__('Service Fee', 'cryptapi'), $fee_order, true);
    1361         }
    1362     }
    1363 
    1364     function refresh_checkout()
    1365     {
    1366         if (WC_CryptAPI_Gateway::$HAS_TRIGGERED) {
    1367             return;
    1368         }
    1369         WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
    1370         if (is_checkout()) {
    1371             wp_register_script('cryptapi-checkout', '');
    1372             wp_enqueue_script('cryptapi-checkout');
    1373             wp_add_inline_script('cryptapi-checkout', "jQuery(function ($) { $('form.checkout').on('change', 'input[name=payment_method], #payment_cryptapi_coin', function () { $(document.body).trigger('update_checkout');});});");
    1374         }
    1375     }
    1376 
    1377     function chosen_currency_value_to_wc_session($posted_data)
    1378     {
    1379         parse_str($posted_data, $fields);
    1380 
    1381         if (isset($fields['cryptapi_coin'])) {
    1382             WC()->session->set('cryptapi_coin', $fields['cryptapi_coin']);
    1383         }
    1384     }
    1385 
    1386     public function process_admin_options()
    1387     {
    1388         parent::update_option('coins', $_POST['coins']);
    1389         parent::process_admin_options();
    1390     }
    1391 
    1392     function add_email_link($order, $sent_to_admin, $plain_text, $email)
    1393     {
    1394         if (WC_CryptAPI_Gateway::$HAS_TRIGGERED) {
    1395             return;
    1396         }
    1397 
    1398         if ($email->id == 'customer_on_hold_order') {
    1399             WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
    1400             echo '<a style="display:block;text-align:center;margin: 40px auto; font-size: 16px; font-weight: bold;" href="' . $this->get_return_url($order) . '" target="_blank">' . __('Check your payment status', 'cryptapi') . '</a>';
    1401         }
    1402     }
    1403 
    1404     function add_order_link($actions, $order)
    1405     {
    1406         if ($order->has_status('on-hold')) {
    1407             $action_slug = 'ca_payment_url';
    1408 
    1409             $actions[$action_slug] = array(
    1410                 'url' => $this->get_return_url($order),
    1411                 'name' => __('Pay', 'cryptapi'),
    1412             );
    1413         }
    1414         return $actions;
    1415     }
    1416 
    1417     function get_private_order_notes($order_id)
    1418     {
    1419         global $wpdb;
    1420 
    1421         $table_perfixed = $wpdb->prefix . 'comments';
    1422         $results = $wpdb->get_results("
     1310        <?php
     1311        return ob_get_clean();
     1312    }
     1313
     1314    function handling_fee() {
     1315        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
     1316            return;
     1317        }
     1318
     1319        $chosen_payment_id = WC()->session->get( 'chosen_payment_method' );
     1320
     1321        if ( $chosen_payment_id != 'cryptapi' ) {
     1322            return;
     1323        }
     1324
     1325        $total_fee = $this->get_option( 'fee_order_percentage' ) == 'none' ? 0 : $this->get_option( 'fee_order_percentage' );
     1326
     1327        $fee_order = WC()->cart->subtotal * $total_fee;
     1328
     1329        if ( $total_fee !== 'none' || $this->add_blockchain_fee ) {
     1330
     1331            $selected = WC()->session->get( 'cryptapi_coin' );
     1332
     1333            if ( $selected === 'none' ) {
     1334                return;
     1335            }
     1336
     1337            if ( ! empty( $selected ) && $selected != 'none' && $this->add_blockchain_fee ) {
     1338                $est = CryptAPI\Helper::get_estimate( $selected );
     1339
     1340                $fee_order += (float) $est->{get_woocommerce_currency()};
     1341            }
     1342
     1343            if ( empty( $fee_order ) ) {
     1344                return;
     1345            }
     1346
     1347            WC()->cart->add_fee( __( 'Service Fee', 'cryptapi' ), $fee_order, true );
     1348        }
     1349    }
     1350
     1351    function refresh_checkout() {
     1352        if ( WC_CryptAPI_Gateway::$HAS_TRIGGERED ) {
     1353            return;
     1354        }
     1355        WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
     1356        if ( is_checkout() ) {
     1357            wp_register_script( 'cryptapi-checkout', '' );
     1358            wp_enqueue_script( 'cryptapi-checkout' );
     1359            wp_add_inline_script( 'cryptapi-checkout', "jQuery(function ($) { $('form.checkout').on('change', 'input[name=payment_method], #payment_cryptapi_coin', function () { $(document.body).trigger('update_checkout');});});" );
     1360        }
     1361    }
     1362
     1363    function chosen_currency_value_to_wc_session( $posted_data ) {
     1364        parse_str( $posted_data, $fields );
     1365
     1366        if ( isset( $fields['cryptapi_coin'] ) ) {
     1367            WC()->session->set( 'cryptapi_coin', $fields['cryptapi_coin'] );
     1368        }
     1369    }
     1370
     1371    public function process_admin_options() {
     1372        parent::update_option( 'coins', $_POST['coins'] );
     1373        parent::process_admin_options();
     1374    }
     1375
     1376    function add_email_link( $order, $sent_to_admin, $plain_text, $email ) {
     1377        if ( WC_CryptAPI_Gateway::$HAS_TRIGGERED ) {
     1378            return;
     1379        }
     1380
     1381        if ( $email->id == 'customer_on_hold_order' ) {
     1382            WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
     1383            echo '<a style="display:block;text-align:center;margin: 40px auto; font-size: 16px; font-weight: bold;" href="' . esc_url( $this->get_return_url( $order ) ) . '" target="_blank">' . __( 'Check your payment status', 'cryptapi' ) . '</a>';
     1384        }
     1385    }
     1386
     1387    function add_order_link( $actions, $order ) {
     1388        if ( $order->has_status( 'on-hold' ) ) {
     1389            $action_slug = 'ca_payment_url';
     1390
     1391            $actions[ $action_slug ] = array(
     1392                'url'  => $this->get_return_url( $order ),
     1393                'name' => __( 'Pay', 'cryptapi' ),
     1394            );
     1395        }
     1396
     1397        return $actions;
     1398    }
     1399
     1400    function get_private_order_notes( $order_id ) {
     1401        global $wpdb;
     1402
     1403        $table_perfixed = $wpdb->prefix . 'comments';
     1404        $results        = $wpdb->get_results( "
    14231405        SELECT *
    14241406        FROM $table_perfixed
    14251407        WHERE  `comment_post_ID` = $order_id
    14261408        AND  `comment_type` LIKE  'order_note'
    1427     ");
    1428 
    1429         foreach ($results as $note) {
    1430             $order_note[] = array(
    1431                 'note_id' => $note->comment_ID,
    1432                 'note_date' => $note->comment_date,
    1433                 'note_author' => $note->comment_author,
    1434                 'note_content' => $note->comment_content,
    1435             );
     1409    " );
     1410
     1411        foreach ( $results as $note ) {
     1412            $order_note[] = array(
     1413                'note_id'      => $note->comment_ID,
     1414                'note_date'    => $note->comment_date,
     1415                'note_author'  => $note->comment_author,
     1416                'note_content' => $note->comment_content,
     1417            );
     1418        }
     1419
     1420        return $order_note;
     1421    }
     1422
     1423    function order_detail_validate_logs($order) {
     1424        if ( WC_CryptAPI_Gateway::$HAS_TRIGGERED ) {
     1425            return;
     1426        }
     1427
     1428        if($order->is_paid()) {
     1429            return;
    14361430        }
    1437         return $order_note;
    1438     }
     1431
     1432        $ajax_url = add_query_arg( array(
     1433            'action' => 'cryptapi_validate_logs',
     1434            'order_id' => $order->get_ID(),
     1435        ), home_url( '/wp-admin/admin-ajax.php' ) );
     1436        ?>
     1437       <p class="form-field form-field-wide wc-customer-user">
     1438           <small style="display: block;">
     1439               <?php echo sprintf(esc_attr( __( 'If the order is not being updated, your ISP is probably blocking our IPs (%1$s and %2$s): please try to get them whitelisted and feel free to contact us anytime to get support (link to our contact page). In the meantime you can refresh the status of any payment by clicking this button below:', 'cryptapi' ) ), '145.239.119.223', '135.125.112.47'); ?>
     1440           </small>
     1441       </p>
     1442        <a style="margin-top: 1rem;margin-bottom: 1rem;" id="validate_callbacks" class="button action" href="#">
     1443            <?php echo esc_attr( __( 'Check for Callbacks', 'cryptapi' ) ); ?>
     1444        </a>
     1445        <script>
     1446            jQuery(function () {
     1447                const validate_button = jQuery('#validate_callbacks');
     1448
     1449                validate_button.on('click', function (e) {
     1450                    e.preventDefault();
     1451                    validate_callbacks();
     1452                    validate_button.html('<?php echo esc_attr( __( 'Checking', 'cryptapi' ) );?>');
     1453                })
     1454
     1455                function validate_callbacks() {
     1456                    jQuery.getJSON('<?php echo $ajax_url?>').always(function () {
     1457                        window.location.reload();
     1458                    })
     1459                }
     1460            })
     1461        </script>
     1462        <?php
     1463        WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
     1464    }
    14391465}
  • cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/define.php

    r2791382 r2797338  
    11<?php
    22
    3 define('CRYPTAPI_PLUGIN_VERSION', '4.6.4');
     3define('CRYPTAPI_PLUGIN_VERSION', '4.6.5');
    44define('CRYPTAPI_PLUGIN_PATH', plugin_dir_path(__FILE__));
    55define('CRYPTAPI_PLUGIN_URL', plugin_dir_url(__FILE__));
  • cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/readme.txt

    r2791382 r2797338  
    44Requires at least: 5
    55Tested up to: 6.0.2
    6 Stable tag: 4.6.4
     6Stable tag: 4.6.5
    77Requires PHP: 7.2
    88WC requires at least: 5.8
     
    296296* Minor fixes
    297297
     298= 4.6.5 =
     299* Added option to check for failed callbacks
     300* Minor fixes
     301
    298302== Upgrade Notice ==
    299303
  • cryptapi-payment-gateway-for-woocommerce/trunk/CryptAPI.php

    r2791382 r2797338  
    44Plugin URI: https://github.com/cryptapi/woocommerce-cryptapi
    55Description: Accept cryptocurrency payments on your WooCommerce website
    6 Version: 4.6.4
     6Version: 4.6.5
    77Requires at least: 5
    88Tested up to: 6.0.2
  • cryptapi-payment-gateway-for-woocommerce/trunk/README.md

    r2791382 r2797338  
    286286* Minor fixes
    287287
     288#### 4.6.5
     289* Added option to check for failed callbacks
     290* Minor fixes
     291
    288292### Upgrade Notice
    289293#### 4.3
  • cryptapi-payment-gateway-for-woocommerce/trunk/controllers/CryptAPI.php

    r2791382 r2797338  
    33use Cryptapi\Helper;
    44
    5 class WC_CryptAPI_Gateway extends WC_Payment_Gateway
    6 {
    7     private static $HAS_TRIGGERED = false;
    8     private static $COIN_OPTIONS = [];
    9 
    10     function __construct()
    11     {
    12         $this->id = 'cryptapi';
    13         $this->icon = CRYPTAPI_PLUGIN_URL . 'static/files/200_logo_ca.png';
    14         $this->has_fields = true;
    15         $this->method_title = 'CryptAPI';
    16         $this->method_description = __('CryptAPI allows customers to pay in cryptocurrency', 'cryptapi');
    17 
    18         $this->supports = array(
    19             'products',
    20             'tokenization',
    21             'add_payment_method',
    22             'subscriptions',
    23             'subscription_cancellation',
    24             'subscription_amount_changes',
    25             'subscription_suspension',
    26             'subscription_reactivation',
    27             'subscription_date_changes',
    28             'multiple_subscriptions',
    29         );
    30 
    31         $this->load_coins();
    32 
    33         $this->init_form_fields();
    34         $this->init_settings();
    35         $this->ca_settings();
    36 
    37         add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options'));
    38         add_action('woocommerce_thankyou_' . $this->id, array($this, 'thankyou_page'));
    39         add_action('woocommerce_api_wc_gateway_' . $this->id, array($this, 'validate_payment'));
    40 
    41         add_action('woocommerce_scheduled_subscription_payment_' . $this->id, array($this, 'scheduled_subscription_mail'), 10, 2);
    42 
    43         add_action('wcs_create_pending_renewal', array($this, 'subscription_send_email'));
    44 
    45         add_action('wp_ajax_nopriv_' . $this->id . '_order_status', array($this, 'order_status'));
    46         add_action('wp_ajax_' . $this->id . '_order_status', array($this, 'order_status'));
    47 
    48         add_action('cryptapi_cronjob', array($this, 'ca_cronjob'), 10, 3);
    49 
    50         add_action('woocommerce_cart_calculate_fees', array($this, 'handling_fee'));
    51 
    52         add_action('woocommerce_checkout_update_order_review', array($this, 'chosen_currency_value_to_wc_session'));
    53 
    54         add_action('wp_footer', array($this, 'refresh_checkout'));
    55 
    56         add_action('woocommerce_email_order_details', array($this, 'add_email_link'), 2, 4);
    57 
    58         add_filter('woocommerce_my_account_my_orders_actions', array($this, 'add_order_link'), 10, 2);
    59     }
    60 
    61     function load_coins()
    62     {
    63         if (!empty(WC_CryptAPI_Gateway::$COIN_OPTIONS)) {
    64             return;
    65         }
    66 
    67         $transient = get_transient('cryptapi_coins');
    68         if (!empty($transient)) {
    69             WC_CryptAPI_Gateway::$COIN_OPTIONS = $transient;
    70 
    71             return;
    72         }
    73 
    74         $coins = CryptAPI\Helper::get_supported_coins();
    75         set_transient('cryptapi_coins', $coins, 86400);
    76         WC_CryptAPI_Gateway::$COIN_OPTIONS = $coins;
    77     }
    78 
    79     function admin_options()
    80     {
    81         parent::admin_options();
    82         ?>
     5class WC_CryptAPI_Gateway extends WC_Payment_Gateway {
     6    private static $HAS_TRIGGERED = false;
     7    private static $COIN_OPTIONS = [];
     8
     9    function __construct() {
     10        $this->id                 = 'cryptapi';
     11        $this->icon               = CRYPTAPI_PLUGIN_URL . 'static/files/200_logo_ca.png';
     12        $this->has_fields         = true;
     13        $this->method_title       = 'CryptAPI';
     14        $this->method_description = esc_attr( __( 'CryptAPI allows customers to pay in cryptocurrency', 'cryptapi' ) );
     15
     16        $this->supports = array(
     17            'products',
     18            'tokenization',
     19            'add_payment_method',
     20            'subscriptions',
     21            'subscription_cancellation',
     22            'subscription_amount_changes',
     23            'subscription_suspension',
     24            'subscription_reactivation',
     25            'subscription_date_changes',
     26            'multiple_subscriptions',
     27        );
     28
     29        $this->load_coins();
     30
     31        $this->init_form_fields();
     32        $this->init_settings();
     33        $this->ca_settings();
     34
     35        add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
     36        add_action( 'woocommerce_thankyou_' . $this->id, array( $this, 'thankyou_page' ) );
     37        add_action( 'woocommerce_api_wc_gateway_' . $this->id, array( $this, 'validate_payment' ) );
     38
     39        add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, array( $this, 'scheduled_subscription_mail' ), 10, 2 );
     40
     41        add_action( 'wcs_create_pending_renewal', array( $this, 'subscription_send_email' ) );
     42
     43        add_action( 'wp_ajax_nopriv_' . $this->id . '_order_status', array( $this, 'order_status' ) );
     44        add_action( 'wp_ajax_' . $this->id . '_order_status', array( $this, 'order_status' ) );
     45
     46        add_action( 'wp_ajax_' . $this->id . '_validate_logs', array( $this, 'validate_logs' ) );
     47
     48        add_action( 'cryptapi_cronjob', array( $this, 'ca_cronjob' ), 10, 3 );
     49
     50        add_action( 'woocommerce_cart_calculate_fees', array( $this, 'handling_fee' ) );
     51
     52        add_action( 'woocommerce_checkout_update_order_review', array( $this, 'chosen_currency_value_to_wc_session' ) );
     53
     54        add_action( 'wp_footer', array( $this, 'refresh_checkout' ) );
     55
     56        add_action( 'woocommerce_email_order_details', array( $this, 'add_email_link' ), 2, 4 );
     57
     58        add_filter( 'woocommerce_my_account_my_orders_actions', array( $this, 'add_order_link' ), 10, 2 );
     59
     60        add_action( 'woocommerce_admin_order_data_after_order_details', array( $this, 'order_detail_validate_logs' ) );
     61
     62    }
     63
     64    function load_coins() {
     65        if ( ! empty( WC_CryptAPI_Gateway::$COIN_OPTIONS ) ) {
     66            return;
     67        }
     68
     69        $transient = get_transient( 'cryptapi_coins' );
     70        if ( ! empty( $transient ) ) {
     71            WC_CryptAPI_Gateway::$COIN_OPTIONS = $transient;
     72
     73            return;
     74        }
     75
     76        $coins = CryptAPI\Helper::get_supported_coins();
     77        set_transient( 'cryptapi_coins', $coins, 86400 );
     78        WC_CryptAPI_Gateway::$COIN_OPTIONS = $coins;
     79    }
     80
     81    function admin_options() {
     82        parent::admin_options();
     83        ?>
    8384        <div style='margin-top: 2rem;'>
    84             <?php echo __("If you need any help or have any suggestion, contact us via the <b>live chat</b> on our <b><a href='https://cryptapi.io' target='_blank'>website</a></b> or join our <b><a href='https://discord.gg/cryptapi' target='_blank'>Discord server</a></b>", "cryptapi") ?>
     85            <?php echo __( "If you need any help or have any suggestion, contact us via the <b>live chat</b> on our <b><a href='https://cryptapi.io' target='_blank'>website</a></b> or join our <b><a href='https://discord.gg/cryptapi' target='_blank'>Discord server</a></b>", "cryptapi" ); ?>
    8586        </div>
    8687        <div style='margin-top: .5rem;'>
    87             <?php echo __("If you enjoy this plugin please <b><a href='https://wordpress.org/support/plugin/cryptapi-payment-gateway-for-woocommerce/reviews/#new-post' target='_blank'>rate and review it</a></b>!", "cryptapi") ?>
     88            <?php echo __( "If you enjoy this plugin please <b><a href='https://wordpress.org/support/plugin/cryptapi-payment-gateway-for-woocommerce/reviews/#new-post' target='_blank'>rate and review it</a></b>!", "cryptapi" ) ?>
    8889        </div>
    8990        <div style="margin-top: 1.5rem">
     
    165166            </a>
    166167        </div>
    167         <?php
    168     }
    169 
    170     private function ca_settings()
    171     {
    172         $this->enabled = $this->get_option('enabled');
    173         $this->title = $this->get_option('title');
    174         $this->description = $this->get_option('description');
    175         $this->api_key = $this->get_option('api_key');
    176         $this->qrcode_size = $this->get_option('qrcode_size');
    177         $this->qrcode_default = $this->get_option('qrcode_default') === 'yes';
    178         $this->qrcode_setting = $this->get_option('qrcode_setting');
    179         $this->coins = $this->get_option('coins');
    180         $this->show_branding = $this->get_option('show_branding') === 'yes';
    181         $this->show_crypto_logos = $this->get_option('show_crypto_logos') === 'yes';
    182         $this->color_scheme = $this->get_option('color_scheme');
    183         $this->refresh_value_interval = $this->get_option('refresh_value_interval');
    184         $this->order_cancelation_timeout = $this->get_option('order_cancelation_timeout');
    185         $this->add_blockchain_fee = $this->get_option('add_blockchain_fee') === 'yes';
    186         $this->fee_order_percentage = $this->get_option('fee_order_percentage');
    187         $this->virtual_complete = $this->get_option('virtual_complete') === 'yes';
    188         $this->disable_conversion = $this->get_option('disable_conversion') === 'yes';
    189         $this->icon = '';
    190 
    191         if (!empty(WC_CryptAPI_Gateway::$COIN_OPTIONS)) {
    192             foreach (array_keys(WC_CryptAPI_Gateway::$COIN_OPTIONS) as $coin) {
    193                 $this->{$coin . '_address'} = $this->get_option($coin . '_address');
    194             }
    195         }
    196     }
    197 
    198     function init_form_fields()
    199     {
    200 
    201         if (!empty(WC_CryptAPI_Gateway::$COIN_OPTIONS)) {
    202             $this->form_fields = array(
    203                 'enabled' => array(
    204                     'title' => __('Enabled', 'cryptapi'),
    205                     'type' => 'checkbox',
    206                     'label' => __('Enable CryptAPI Payments', 'cryptapi'),
    207                     'default' => 'yes'
    208                 ),
    209                 'title' => array(
    210                     'title' => __('Title', 'cryptapi'),
    211                     'type' => 'text',
    212                     'description' => __('This controls the title which the user sees during checkout.', 'cryptapi'),
    213                     'default' => __('Cryptocurrency', 'cryptapi'),
    214                     'desc_tip' => true,
    215                 ),
    216                 'description' => array(
    217                     'title' => __('Description', 'cryptapi'),
    218                     'type' => 'textarea',
    219                     'default' => '',
    220                     'description' => __('Payment method description that the customer will see on your checkout', 'cryptapi')
    221                 ),
    222                 'show_branding' => array(
    223                     'title' => __('Show CryptAPI branding', 'cryptapi'),
    224                     'type' => 'checkbox',
    225                     'label' => __('Show CryptAPI logo and credits below the QR code', 'cryptapi'),
    226                     'default' => 'yes'
    227                 ),
    228                 'show_crypto_logos' => array(
    229                     'title' => __('Show crypto logos in checkout', 'cryptapi'),
    230                     'type' => 'checkbox',
    231                     'label' => sprintf(__('Enable this to show the cryptocurrencies logos in the checkout %1$s %2$s Notice: %3$s It may break in some templates. Use at your own risk.', 'cryptapi'), '<br/>', '<strong>', '</strong>'),
    232                     'default' => 'no'
    233                 ),
    234                 'add_blockchain_fee' => array(
    235                     'title' => __('Add the blockchain fee to the order', 'cryptapi'),
    236                     'type' => 'checkbox',
    237                     'label' => __("This will add an estimation of the blockchain fee to the order value", 'cryptapi'),
    238                     'default' => 'no'
    239                 ),
    240                 'fee_order_percentage' => array(
    241                     'title' => __('Service fee manager', 'cryptapi'),
    242                     'type' => 'select',
    243                     'default' => 'none',
    244                     'options' => array(
    245                         '0.05' => '5%',
    246                         '0.048' => '4.8%',
    247                         '0.045' => '4.5%',
    248                         '0.042' => '4.2%',
    249                         '0.04' => '4%',
    250                         '0.038' => '3.8%',
    251                         '0.035' => '3.5%',
    252                         '0.032' => '3.2%',
    253                         '0.03' => '3%',
    254                         '0.028' => '2.8%',
    255                         '0.025' => '2.5%',
    256                         '0.022' => '2.2%',
    257                         '0.02' => '2%',
    258                         '0.018' => '1.8%',
    259                         '0.015' => '1.5%',
    260                         '0.012' => '1.2%',
    261                         '0.01' => '1%',
    262                         '0.0090' => '0.90%',
    263                         '0.0085' => '0.85%',
    264                         '0.0080' => '0.80%',
    265                         '0.0075' => '0.75%',
    266                         '0.0070' => '0.70%',
    267                         '0.0065' => '0.65%',
    268                         '0.0060' => '0.60%',
    269                         '0.0055' => '0.55%',
    270                         '0.0050' => '0.50%',
    271                         '0.0040' => '0.40%',
    272                         '0.0030' => '0.30%',
    273                         '0.0025' => '0.25%',
    274                         'none' => '0%',
    275                     ),
    276                     'description' => sprintf(__('Set the CryptAPI service fee you want to charge the costumer. %1$s %2$s Note: %3$s Fee you want to charge your costumers (to cover CryptAPI\'s fees fully or partially).', 'cryptapi'), '<br/>', '<strong>', '</strong>')
    277                 ),
    278                 'qrcode_default' => array(
    279                     'title' => __('QR Code by default', 'cryptapi'),
    280                     'type' => 'checkbox',
    281                     'label' => __('Show the QR Code by default', 'cryptapi'),
    282                     'default' => 'yes'
    283                 ),
    284                 'qrcode_size' => array(
    285                     'title' => __('QR Code size', 'cryptapi'),
    286                     'type' => 'number',
    287                     'default' => 300,
    288                     'description' => __('QR code image size', 'cryptapi')
    289                 ),
    290                 'qrcode_setting' => array(
    291                     'title' => __('QR Code to show', 'cryptapi'),
    292                     'type' => 'select',
    293                     'default' => 'ammount',
    294                     'options' => array(
    295                         'without_ammount' => __('Default Without Amount', 'cryptapi'),
    296                         'ammount' => __('Default Amount', 'cryptapi'),
    297                         'hide_ammount' => __('Hide Amount', 'cryptapi'),
    298                         'hide_without_ammount' => __('Hide Without Amount', 'cryptapi'),
    299                     ),
    300                     'description' => __('Select how you want to show the QR Code to the user. Either select a default to show first, or hide one of them.', 'cryptapi')
    301                 ),
    302                 'color_scheme' => array(
    303                     'title' => __('Color Scheme', 'cryptapi'),
    304                     'type' => 'select',
    305                     'default' => 'light',
    306                     'description' => __('Selects the color scheme of the plugin to match your website (Light, Dark and Auto to automatically detect it)', 'cryptapi'),
    307                     'options' => array(
    308                         'light' => __('Light', 'cryptapi'),
    309                         'dark' => __('Dark', 'cryptapi'),
    310                         'auto' => __('Auto', 'cryptapi'),
    311                     ),
    312                 ),
    313                 'refresh_value_interval' => array(
    314                     'title' => __('Refresh converted value', 'cryptapi'),
    315                     'type' => 'select',
    316                     'default' => '300',
    317                     'options' => array(
    318                         '0' => __('Never', 'cryptapi'),
    319                         '300' => __('Every 5 Minutes', 'cryptapi'),
    320                         '600' => __('Every 10 Minutes', 'cryptapi'),
    321                         '900' => __('Every 15 Minutes', 'cryptapi'),
    322                         '1800' => __('Every 30 Minutes', 'cryptapi'),
    323                         '2700' => __('Every 45 Minutes', 'cryptapi'),
    324                         '3600' => __('Every 60 Minutes', 'cryptapi'),
    325                     ),
    326                     'description' => sprintf(__('The system will automatically update the conversion value of the invoices (with real-time data), every X minutes. %1$s This feature is helpful whenever a customer takes long time to pay a generated invoice and the selected crypto a volatile coin/token (not stable coin). %1$s %4$s Warning: %3$s Setting this setting to none might create conversion issues, as we advise you to keep it at 5 minutes. %3$s', 'cryptapi'), '<br/>', '<strong>', '</strong>', '<strong style="color: #f44336;">'),
    327                 ),
    328                 'order_cancelation_timeout' => array(
    329                     'title' => __('Order cancelation timeout', 'cryptapi'),
    330                     'type' => 'select',
    331                     'default' => '0',
    332                     'options' => array(
    333                         '0' => __('Never', 'cryptapi'),
    334                         '3600' => __('1 Hour', 'cryptapi'),
    335                         '21600' => __('6 Hours', 'cryptapi'),
    336                         '43200' => __('12 Hours', 'cryptapi'),
    337                         '64800' => __('18 Hours', 'cryptapi'),
    338                         '86400' => __('24 Hours', 'cryptapi'),
    339                     ),
    340                     'description' => sprintf(__('Selects the amount of time the user has to  pay for the order. %1$s When this time is over, order will be marked as "Cancelled" and every paid value will be ignored. %1$s %2$s Notice: %3$s If the user still sends money to the generated address, value will still be redirected to you. %1$s %4$s Warning: %3$s We do not advice more than 1 Hour.', 'cryptapi'), '<br/>', '<strong>', '</strong>', '<strong style="color: #f44336;">'),
    341                 ),
    342                 'virtual_complete' => array(
    343                     'title' => __('Completed status for virtual products', 'cryptapi'),
    344                     'type' => 'checkbox',
    345                     'label' => sprintf(__('When this setting is enabled, the plugin will mark the order as "completed" then payment is received. %1$s Only for virtual products %2$s.', 'cryptapi'), '<strong>', '</strong>'),
    346                     'default' => 'no'
    347                 ),
    348                 'disable_conversion' => array(
    349                     'title' => __('Disable price conversion', 'cryptapi'),
    350                     'type' => 'checkbox',
    351                     'label' => sprintf(__('%2$s Attention: This option will disable the price conversion for ALL cryptocurrencies! %3$s %1$s If you check this, pricing will not be converted from the currency of your shop to the cryptocurrency selected by the user, and users will be requested to pay the same value as shown on your shop, regardless of the cryptocurrency selected', 'cryptapi'), '<br/>', '<strong>', '</strong>'),
    352                     'default' => 'no'
    353                 ),
    354                 'api_key' => array(
    355                     'title' => __('API Key', 'cryptapi'),
    356                     'type' => 'text',
    357                     'default' => '',
    358                     'description' => sprintf(__('Insert here your BlockBee API Key. You can get one here: %1$s', 'cryptapi'), '<a href="https://dash.blockbee.io/" target="_blank">https://dash.blockbee.io/</a>')
    359                 ),
    360             );
    361 
    362             $coin_description = __('Insert your %s address here. Leave the checkbox unselected if you want to skip this cryptocurrency', 'cryptapi');
    363 
    364             $c = 0;
    365             foreach (WC_CryptAPI_Gateway::$COIN_OPTIONS as $ticker => $coin) {
    366                 $this->form_fields["{$ticker}_address"] = array(
    367                     'title' => is_array($coin) ? $coin['name'] : $coin,
    368                     'type' => 'cryptocurrency',
    369                     'description' => sprintf($coin_description, is_array($coin) ? $coin['name'] : $coin),
    370                     'desc_tip' => true,
    371                     'custom_attributes' => array(
    372                         'counter' => $c++,
    373                     )
    374                 );
    375 
    376             }
    377 
    378         }
    379     }
    380 
    381     function needs_setup()
    382     {
    383         if (empty($this->coins) || !is_array($this->coins)) {
    384             return true;
    385         }
    386 
    387         foreach ($this->coins as $val) {
    388             if (!empty($this->{$val . '_address'})) {
    389                 return false;
    390             }
    391         }
    392 
    393         return true;
    394     }
    395 
    396     public function get_icon()
    397     {
    398 
    399         $icon = $this->show_branding ? '<img style="top: -5px; position:relative" width="120" src="' . plugin_dir_url(dirname(__FILE__)) . 'static/files/200_logo_ca.png' . '" alt="' . esc_attr($this->get_title()) . '" />' : '';
    400 
    401         return apply_filters('woocommerce_gateway_icon', $icon, $this->id);
    402     }
    403 
    404     function payment_fields()
    405     { ?>
     168        <?php
     169    }
     170
     171    private function ca_settings() {
     172        $this->enabled                   = $this->get_option( 'enabled' );
     173        $this->title                     = $this->get_option( 'title' );
     174        $this->description               = $this->get_option( 'description' );
     175        $this->api_key                   = $this->get_option( 'api_key' );
     176        $this->qrcode_size               = $this->get_option( 'qrcode_size' );
     177        $this->qrcode_default            = $this->get_option( 'qrcode_default' ) === 'yes';
     178        $this->qrcode_setting            = $this->get_option( 'qrcode_setting' );
     179        $this->coins                     = $this->get_option( 'coins' );
     180        $this->show_branding             = $this->get_option( 'show_branding' ) === 'yes';
     181        $this->show_crypto_logos         = $this->get_option( 'show_crypto_logos' ) === 'yes';
     182        $this->color_scheme              = $this->get_option( 'color_scheme' );
     183        $this->refresh_value_interval    = $this->get_option( 'refresh_value_interval' );
     184        $this->order_cancelation_timeout = $this->get_option( 'order_cancelation_timeout' );
     185        $this->add_blockchain_fee        = $this->get_option( 'add_blockchain_fee' ) === 'yes';
     186        $this->fee_order_percentage      = $this->get_option( 'fee_order_percentage' );
     187        $this->virtual_complete          = $this->get_option( 'virtual_complete' ) === 'yes';
     188        $this->disable_conversion        = $this->get_option( 'disable_conversion' ) === 'yes';
     189        $this->icon                      = '';
     190
     191        if ( ! empty( WC_CryptAPI_Gateway::$COIN_OPTIONS ) ) {
     192            foreach ( array_keys( WC_CryptAPI_Gateway::$COIN_OPTIONS ) as $coin ) {
     193                $this->{$coin . '_address'} = $this->get_option( $coin . '_address' );
     194            }
     195        }
     196    }
     197
     198    function init_form_fields() {
     199
     200        if ( ! empty( WC_CryptAPI_Gateway::$COIN_OPTIONS ) ) {
     201            $this->form_fields = array(
     202                'enabled'                   => array(
     203                    'title'   => esc_attr( __( 'Enabled', 'cryptapi' ) ),
     204                    'type'    => 'checkbox',
     205                    'label'   => esc_attr( __( 'Enable CryptAPI Payments', 'cryptapi' ) ),
     206                    'default' => 'yes'
     207                ),
     208                'title'                     => array(
     209                    'title'       => esc_attr( __( 'Title', 'cryptapi' ) ),
     210                    'type'        => 'text',
     211                    'description' => esc_attr( __( 'This controls the title which the user sees during checkout.', 'cryptapi' ) ),
     212                    'default'     => esc_attr( __( 'Cryptocurrency', 'cryptapi' ) ),
     213                    'desc_tip'    => true,
     214                ),
     215                'description'               => array(
     216                    'title'       => esc_attr( __( 'Description', 'cryptapi' ) ),
     217                    'type'        => 'textarea',
     218                    'default'     => '',
     219                    'description' => esc_attr( __( 'Payment method description that the customer will see on your checkout', 'cryptapi' ) )
     220                ),
     221                'show_branding'             => array(
     222                    'title'   => esc_attr( __( 'Show CryptAPI branding', 'cryptapi' ) ),
     223                    'type'    => 'checkbox',
     224                    'label'   => esc_attr( __( 'Show CryptAPI logo and credits below the QR code', 'cryptapi' ) ),
     225                    'default' => 'yes'
     226                ),
     227                'show_crypto_logos'         => array(
     228                    'title'   => esc_attr( __( 'Show crypto logos in checkout', 'cryptapi' ) ),
     229                    'type'    => 'checkbox',
     230                    'label'   => sprintf( esc_attr( __( 'Enable this to show the cryptocurrencies logos in the checkout %1$s %2$s Notice: %3$s It may break in some templates. Use at your own risk.', 'cryptapi' ) ), '<br/>', '<strong>', '</strong>' ),
     231                    'default' => 'no'
     232                ),
     233                'add_blockchain_fee'        => array(
     234                    'title'   => esc_attr( __( 'Add the blockchain fee to the order', 'cryptapi' ) ),
     235                    'type'    => 'checkbox',
     236                    'label'   => esc_attr( __( "This will add an estimation of the blockchain fee to the order value", 'cryptapi' ) ),
     237                    'default' => 'no'
     238                ),
     239                'fee_order_percentage'      => array(
     240                    'title'       => esc_attr( __( 'Service fee manager', 'cryptapi' ) ),
     241                    'type'        => 'select',
     242                    'default'     => 'none',
     243                    'options'     => array(
     244                        '0.05'   => '5%',
     245                        '0.048'  => '4.8%',
     246                        '0.045'  => '4.5%',
     247                        '0.042'  => '4.2%',
     248                        '0.04'   => '4%',
     249                        '0.038'  => '3.8%',
     250                        '0.035'  => '3.5%',
     251                        '0.032'  => '3.2%',
     252                        '0.03'   => '3%',
     253                        '0.028'  => '2.8%',
     254                        '0.025'  => '2.5%',
     255                        '0.022'  => '2.2%',
     256                        '0.02'   => '2%',
     257                        '0.018'  => '1.8%',
     258                        '0.015'  => '1.5%',
     259                        '0.012'  => '1.2%',
     260                        '0.01'   => '1%',
     261                        '0.0090' => '0.90%',
     262                        '0.0085' => '0.85%',
     263                        '0.0080' => '0.80%',
     264                        '0.0075' => '0.75%',
     265                        '0.0070' => '0.70%',
     266                        '0.0065' => '0.65%',
     267                        '0.0060' => '0.60%',
     268                        '0.0055' => '0.55%',
     269                        '0.0050' => '0.50%',
     270                        '0.0040' => '0.40%',
     271                        '0.0030' => '0.30%',
     272                        '0.0025' => '0.25%',
     273                        'none'   => '0%',
     274                    ),
     275                    'description' => sprintf( esc_attr( __( 'Set the CryptAPI service fee you want to charge the costumer. %1$s %2$s Note: %3$s Fee you want to charge your costumers (to cover CryptAPI\'s fees fully or partially).', 'cryptapi' ) ), '<br/>', '<strong>', '</strong>' )
     276                ),
     277                'qrcode_default'            => array(
     278                    'title'   => esc_attr( __( 'QR Code by default', 'cryptapi' ) ),
     279                    'type'    => 'checkbox',
     280                    'label'   => esc_attr( __( 'Show the QR Code by default', 'cryptapi' ) ),
     281                    'default' => 'yes'
     282                ),
     283                'qrcode_size'               => array(
     284                    'title'       => esc_attr( __( 'QR Code size', 'cryptapi' ) ),
     285                    'type'        => 'number',
     286                    'default'     => 300,
     287                    'description' => esc_attr( __( 'QR code image size', 'cryptapi' ) )
     288                ),
     289                'qrcode_setting'            => array(
     290                    'title'       => esc_attr( __( 'QR Code to show', 'cryptapi' ) ),
     291                    'type'        => 'select',
     292                    'default'     => 'without_ammount',
     293                    'options'     => array(
     294                        'without_ammount'      => esc_attr( __( 'Default Without Amount', 'cryptapi' ) ),
     295                        'ammount'              => esc_attr( __( 'Default Amount', 'cryptapi' ) ),
     296                        'hide_ammount'         => esc_attr( __( 'Hide Amount', 'cryptapi' ) ),
     297                        'hide_without_ammount' => esc_attr( __( 'Hide Without Amount', 'cryptapi' ) ),
     298                    ),
     299                    'description' => esc_attr( __( 'Select how you want to show the QR Code to the user. Either select a default to show first, or hide one of them.', 'cryptapi' ) )
     300                ),
     301                'color_scheme'              => array(
     302                    'title'       => esc_attr( __( 'Color Scheme', 'cryptapi' ) ),
     303                    'type'        => 'select',
     304                    'default'     => 'light',
     305                    'description' => esc_attr( __( 'Selects the color scheme of the plugin to match your website (Light, Dark and Auto to automatically detect it)', 'cryptapi' ) ),
     306                    'options'     => array(
     307                        'light' => esc_attr( __( 'Light', 'cryptapi' ) ),
     308                        'dark'  => esc_attr( __( 'Dark', 'cryptapi' ) ),
     309                        'auto'  => esc_attr( __( 'Auto', 'cryptapi' ) ),
     310                    ),
     311                ),
     312                'refresh_value_interval'    => array(
     313                    'title'       => esc_attr( __( 'Refresh converted value', 'cryptapi' ) ),
     314                    'type'        => 'select',
     315                    'default'     => '300',
     316                    'options'     => array(
     317                        '0'    => esc_attr( __( 'Never', 'cryptapi' ) ),
     318                        '300'  => esc_attr( __( 'Every 5 Minutes', 'cryptapi' ) ),
     319                        '600'  => esc_attr( __( 'Every 10 Minutes', 'cryptapi' ) ),
     320                        '900'  => esc_attr( __( 'Every 15 Minutes', 'cryptapi' ) ),
     321                        '1800' => esc_attr( __( 'Every 30 Minutes', 'cryptapi' ) ),
     322                        '2700' => esc_attr( __( 'Every 45 Minutes', 'cryptapi' ) ),
     323                        '3600' => esc_attr( __( 'Every 60 Minutes', 'cryptapi' ) ),
     324                    ),
     325                    'description' => sprintf( esc_attr( __( 'The system will automatically update the conversion value of the invoices (with real-time data), every X minutes. %1$s This feature is helpful whenever a customer takes long time to pay a generated invoice and the selected crypto a volatile coin/token (not stable coin). %1$s %4$s Warning: %3$s Setting this setting to none might create conversion issues, as we advise you to keep it at 5 minutes. %3$s', 'cryptapi' ) ), '<br/>', '<strong>', '</strong>', '<strong style="color: #f44336;">' ),
     326                ),
     327                'order_cancelation_timeout' => array(
     328                    'title'       => esc_attr( __( 'Order cancelation timeout', 'cryptapi' ) ),
     329                    'type'        => 'select',
     330                    'default'     => '0',
     331                    'options'     => array(
     332                        '0'     => esc_attr( __( 'Never', 'cryptapi' ) ),
     333                        '3600'  => esc_attr( __( '1 Hour', 'cryptapi' ) ),
     334                        '21600' => esc_attr( __( '6 Hours', 'cryptapi' ) ),
     335                        '43200' => esc_attr( __( '12 Hours', 'cryptapi' ) ),
     336                        '64800' => esc_attr( __( '18 Hours', 'cryptapi' ) ),
     337                        '86400' => esc_attr( __( '24 Hours', 'cryptapi' ) ),
     338                    ),
     339                    'description' => sprintf( esc_attr( __( 'Selects the amount of time the user has to  pay for the order. %1$s When this time is over, order will be marked as "Cancelled" and every paid value will be ignored. %1$s %2$s Notice: %3$s If the user still sends money to the generated address, value will still be redirected to you. %1$s %4$s Warning: %3$s We do not advice more than 1 Hour.', 'cryptapi' ) ), '<br/>', '<strong>', '</strong>', '<strong style="color: #f44336;">' ),
     340                ),
     341                'virtual_complete'          => array(
     342                    'title'   => esc_attr( __( 'Completed status for virtual products', 'cryptapi' ) ),
     343                    'type'    => 'checkbox',
     344                    'label'   => sprintf( __( 'When this setting is enabled, the plugin will mark the order as "completed" then payment is received. %1$s Only for virtual products %2$s.', 'cryptapi' ), '<strong>', '</strong>' ),
     345                    'default' => 'no'
     346                ),
     347                'disable_conversion'        => array(
     348                    'title'   => esc_attr( __( 'Disable price conversion', 'cryptapi' ) ),
     349                    'type'    => 'checkbox',
     350                    'label'   => sprintf( __( '%2$s Attention: This option will disable the price conversion for ALL cryptocurrencies! %3$s %1$s If you check this, pricing will not be converted from the currency of your shop to the cryptocurrency selected by the user, and users will be requested to pay the same value as shown on your shop, regardless of the cryptocurrency selected', 'cryptapi' ), '<br/>', '<strong>', '</strong>' ),
     351                    'default' => 'no'
     352                ),
     353                'api_key'                   => array(
     354                    'title'       => esc_attr( __( 'API Key', 'cryptapi' ) ),
     355                    'type'        => 'text',
     356                    'default'     => '',
     357                    'description' => sprintf( esc_attr( __( 'Insert here your BlockBee API Key. You can get one here: %1$s', 'cryptapi' ) ), '<a href="https://dash.blockbee.io/" target="_blank">https://dash.blockbee.io/</a>' )
     358                ),
     359            );
     360
     361            $coin_description = esc_attr( __( 'Insert your %s address here. Leave the checkbox unselected if you want to skip this cryptocurrency', 'cryptapi' ) );
     362
     363            $c = 0;
     364            foreach ( WC_CryptAPI_Gateway::$COIN_OPTIONS as $ticker => $coin ) {
     365                $this->form_fields["{$ticker}_address"] = array(
     366                    'title'             => is_array( $coin ) ? $coin['name'] : $coin,
     367                    'type'              => 'cryptocurrency',
     368                    'description'       => sprintf( $coin_description, is_array( $coin ) ? $coin['name'] : $coin ),
     369                    'desc_tip'          => true,
     370                    'custom_attributes' => array(
     371                        'counter' => $c ++,
     372                    )
     373                );
     374
     375            }
     376
     377        }
     378    }
     379
     380    function needs_setup() {
     381        if ( empty( $this->coins ) || ! is_array( $this->coins ) ) {
     382            return true;
     383        }
     384
     385        foreach ( $this->coins as $val ) {
     386            if ( ! empty( $this->{$val . '_address'} ) ) {
     387                return false;
     388            }
     389        }
     390
     391        return true;
     392    }
     393
     394    public function get_icon() {
     395
     396        $icon = $this->show_branding ? '<img style="top: -5px; position:relative" width="120" src="' . esc_url( plugin_dir_url( dirname( __FILE__ ) ) ) . 'static/files/200_logo_ca.png' . '" alt="' . esc_attr( $this->get_title() ) . '" />' : '';
     397
     398        return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
     399    }
     400
     401    function payment_fields() { ?>
    406402        <div class="form-row form-row-wide">
    407             <p><?php echo $this->description; ?></p>
     403            <p><?php echo esc_attr( $this->description ); ?></p>
    408404            <ul style="margin-top: 7px; list-style: none outside;">
    409                 <?php
    410                 if (!empty($this->coins) && is_array($this->coins)) {
    411                     $selected = WC()->session->get('cryptapi_coin');
    412                     ?>
     405                <?php
     406                if ( ! empty( $this->coins ) && is_array( $this->coins ) ) {
     407                    $selected = WC()->session->get( 'cryptapi_coin' );
     408                    ?>
    413409                    <li>
    414410                        <select name="cryptapi_coin" id="payment_cryptapi_coin" class="input-control" style="display:block; margin-top: 10px">
    415                             <option value="none"><?php echo __('Please select a Cryptocurrency', 'cryptapi') ?></option>
    416                             <?php
    417                             foreach ($this->coins as $val) {
    418                                 $addr = $this->{$val . '_address'};
    419                                 $apikey = $this->api_key;
    420                                 if (!empty($addr) || !empty($apikey)) { ?>
    421                                     <option data-image="<?php echo WC_CryptAPI_Gateway::$COIN_OPTIONS[$val]['logo']; ?>" value="<?php echo $val; ?>" <?php
    422                                     if (!empty($selected) && $selected === $val) {
    423                                         echo " selected='true'";
    424                                     }
    425                                     $crypto_name = is_array(WC_CryptAPI_Gateway::$COIN_OPTIONS[$val]) ? WC_CryptAPI_Gateway::$COIN_OPTIONS[$val]['name'] : WC_CryptAPI_Gateway::$COIN_OPTIONS[$val];
    426                                     ?>> <?php echo __('Pay with', 'cryptapi') . ' ' . $crypto_name; ?></option>
    427                                     <?php
    428                                 }
    429                             }
    430                             ?>
     411                            <option value="none"><?php echo esc_attr( __( 'Please select a Cryptocurrency', 'cryptapi' ) ) ?></option>
     412                            <?php
     413                            foreach ( $this->coins as $val ) {
     414                                $addr  = $this->{$val . '_address'};
     415                                $apikey = $this->api_key;
     416                                if ( ! empty( $addr ) || ! empty( $apikey ) ) { ?>
     417                                    <option data-image="<?php echo esc_url( WC_CryptAPI_Gateway::$COIN_OPTIONS[ $val ]['logo'] ); ?>" value="<?php echo esc_attr( $val ); ?>" <?php
     418                                    if ( ! empty( $selected ) && $selected === $val ) {
     419                                        echo esc_attr( "selected='true'" );
     420                                    }
     421                                    $crypto_name = is_array( WC_CryptAPI_Gateway::$COIN_OPTIONS[ $val ] ) ? WC_CryptAPI_Gateway::$COIN_OPTIONS[ $val ]['name'] : WC_CryptAPI_Gateway::$COIN_OPTIONS[ $val ];
     422                                    ?>> <?php echo esc_attr( __( 'Pay with', 'cryptapi' ) . ' ' . $crypto_name ); ?></option>
     423                                    <?php
     424                                }
     425                            }
     426                            ?>
    431427                        </select>
    432428                    </li>
    433                     <?php
    434                 } ?>
     429                    <?php
     430                } ?>
    435431            </ul>
    436432        </div>
    437         <?php
    438         if ($this->show_crypto_logos) {
    439             ?>
     433        <?php
     434        if ( $this->show_crypto_logos ) {
     435            ?>
    440436            <script>
    441437                if (typeof jQuery.fn.selectWoo !== 'undefined') {
     
    458454                }
    459455            </script>
    460             <?php
     456            <?php
     457        }
     458    }
     459
     460    function validate_fields() {
     461        return array_key_exists( sanitize_text_field( $_POST['cryptapi_coin'] ), WC_CryptAPI_Gateway::$COIN_OPTIONS );
     462    }
     463
     464    function process_payment( $order_id ) {
     465        global $woocommerce;
     466
     467        $selected = sanitize_text_field( $_POST['cryptapi_coin'] );
     468
     469        if ( $selected === 'none' ) {
     470            wc_add_notice( __( 'Payment error: ', 'woocommerce' ) . ' ' . __( 'Please choose a cryptocurrency', 'cryptapi' ), 'error' );
     471
     472            return null;
     473        }
     474
     475        $api_key = $this->api_key;
     476        $addr    = $this->{$selected . '_address'};
     477
     478        if ( ! empty( $addr ) || ! empty( $api_key ) ) {
     479
     480            $nonce = $this->generate_nonce();
     481
     482            $callback_url = str_replace( 'https:', 'http:', add_query_arg( array(
     483                'wc-api'   => 'WC_Gateway_CryptAPI',
     484                'order_id' => $order_id,
     485                'nonce'    => $nonce,
     486            ), home_url( '/' ) ) );
     487
     488            try {
     489                $order = new WC_Order( $order_id );
     490
     491                if ( in_array( 'woocommerce-subscriptions/woocommerce-subscriptions.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
     492
     493                    if ( wcs_order_contains_subscription( $order_id ) ) {
     494
     495                        $sign_up_fee      = ( WC_Subscriptions_Order::get_sign_up_fee( $order ) ) ? 0 : WC_Subscriptions_Order::get_sign_up_fee( $order );
     496                        $initial_payment  = ( WC_Subscriptions_Order::get_total_initial_payment( $order ) ) ? 0 : WC_Subscriptions_Order::get_total_initial_payment( $order );
     497                        $price_per_period = ( WC_Subscriptions_Order::get_recurring_total( $order ) ) ? 0 : WC_Subscriptions_Order::get_recurring_total( $order );
     498
     499                        $total = $sign_up_fee + $initial_payment + $price_per_period + $order->get_total( 'edit' );
     500
     501                        if ( $total == 0 ) {
     502                            $order->add_meta_data( 'cryptapi_currency', $selected );
     503                            $order->save_meta_data();
     504                            $order->payment_complete();
     505                            $woocommerce->cart->empty_cart();
     506
     507                            return array(
     508                                'result'   => 'success',
     509                                'redirect' => $this->get_return_url( $order )
     510                            );
     511                        }
     512                    }
     513                }
     514
     515                $total = $order->get_total( 'edit' );
     516
     517                $currency = get_woocommerce_currency();
     518
     519                $info   = CryptAPI\Helper::get_info( $selected );
     520                $min_tx = CryptAPI\Helper::sig_fig( $info->minimum_transaction_coin, 6 );
     521
     522                $crypto_total = CryptAPI\Helper::get_conversion( $currency, $selected, $total, $this->disable_conversion );
     523
     524                if ( $crypto_total < $min_tx ) {
     525                    wc_add_notice( __( 'Payment error:', 'woocommerce' ) . ' ' . __( 'Value too low, minimum is', 'cryptapi' ) . ' ' . $min_tx . ' ' . strtoupper( $selected ), 'error' );
     526
     527                    return null;
     528                }
     529
     530                $ca = new CryptAPI\Helper( $selected, $addr, $api_key, $callback_url, [], true );
     531
     532                $addr_in = $ca->get_address();
     533
     534                if ( empty( $addr_in ) ) {
     535                    wc_add_notice( __( 'Payment error:', 'woocommerce' ) . ' ' . __( 'There was an error with the payment. Please try again.', 'cryptapi' ) );
     536
     537                    return null;
     538                }
     539
     540                $qr_code_data_value = CryptAPI\Helper::get_static_qrcode( $addr_in, $selected, $crypto_total, $this->qrcode_size );
     541                $qr_code_data       = CryptAPI\Helper::get_static_qrcode( $addr_in, $selected, '', $this->qrcode_size );
     542
     543                $order->add_meta_data( 'cryptapi_nonce', $nonce );
     544                $order->add_meta_data( 'cryptapi_address', $addr_in );
     545                $order->add_meta_data( 'cryptapi_total', CryptAPI\Helper::sig_fig( $crypto_total, 6 ) );
     546                $order->add_meta_data( 'cryptapi_total_fiat', $total );
     547                $order->add_meta_data( 'cryptapi_currency', $selected );
     548                $order->add_meta_data( 'cryptapi_qr_code_value', $qr_code_data_value['qr_code'] );
     549                $order->add_meta_data( 'cryptapi_qr_code', $qr_code_data['qr_code'] );
     550                $order->add_meta_data( 'cryptapi_last_price_update', time() );
     551                $order->add_meta_data( 'cryptapi_cancelled', '0' );
     552                $order->add_meta_data( 'cryptapi_min', $min_tx );
     553                $order->add_meta_data( 'cryptapi_history', json_encode( [] ) );
     554                $order->add_meta_data( 'cryptapi_callback_url', $callback_url );
     555                $order->add_meta_data( 'cryptapi_last_checked', $order->get_date_created()->getTimestamp() );
     556                $order->save_meta_data();
     557
     558                $order->update_status( 'on-hold', __( 'Awaiting payment', 'cryptapi' ) . ': ' . WC_CryptAPI_Gateway::$COIN_OPTIONS[ $selected ] );
     559                $woocommerce->cart->empty_cart();
     560
     561                return array(
     562                    'result'   => 'success',
     563                    'redirect' => $this->get_return_url( $order )
     564                );
     565
     566            } catch ( Exception $e ) {
     567                wc_add_notice( __( 'Payment error:', 'cryptapi' ) . 'Unknown coin', 'error' );
     568
     569                return null;
     570            }
     571        }
     572
     573        wc_add_notice( __( 'Payment error:', 'woocommerce' ) . __( 'Payment could not be processed, please try again', 'cryptapi' ), 'error' );
     574
     575        return null;
     576    }
     577
     578    function validate_payment() {
     579        $data = CryptAPI\Helper::process_callback( $_GET );
     580
     581        $order = new WC_Order( $data['order_id'] );
     582
     583        if ( $order->is_paid() || $order->get_status() === 'cancelled' || $data['nonce'] != $order->get_meta( 'cryptapi_nonce' ) ) {
     584            die( "*ok*" );
     585        }
     586
     587        $order->update_meta_data( 'cryptapi_last_checked', time() );
     588        $order->save_meta_data();
     589
     590        // Actually process the callback data
     591        $this->process_callback_data( $data, $order );
     592    }
     593
     594    function order_status() {
     595        $order_id = sanitize_text_field( $_REQUEST['order_id'] );
     596
     597        try {
     598            $order = new WC_Order( $order_id );
     599
     600            $showMinFee = '0';
     601
     602            $history = json_decode( $order->get_meta( 'cryptapi_history' ), true );
     603
     604            $calc = $this->calc_order( $history, $order->get_meta( 'cryptapi_total' ), $order->get_meta( 'cryptapi_total_fiat' ) );
     605
     606            $already_paid      = $calc['already_paid'];
     607            $already_paid_fiat = $calc['already_paid_fiat'];
     608
     609            $min_tx = floatval( $order->get_meta( 'cryptapi_min' ) );
     610
     611            $remaining_pending = $calc['remaining_pending'];
     612            $remaining_fiat    = $calc['remaining_fiat'];
     613
     614            $cryptapi_pending = 0;
     615
     616            $counter_calc = (int) $order->get_meta( 'cryptapi_last_price_update' ) + (int) $this->refresh_value_interval - time();
     617
     618            if ( $remaining_pending <= 0 && ! $order->is_paid() ) {
     619                $cryptapi_pending = 1;
     620            }
     621
     622            if ( $counter_calc <= 0 && ! $order->is_paid() ) {
     623                $this->ca_cronjob();
     624            }
     625
     626            if ( $remaining_pending <= $min_tx && $remaining_pending > 0 ) {
     627                $remaining_pending = $min_tx;
     628                $showMinFee        = 1;
     629            }
     630
     631            $data = [
     632                'is_paid'           => $order->is_paid(),
     633                'is_pending'        => $cryptapi_pending,
     634                'qr_code_value'     => $order->get_meta( 'cryptapi_qr_code_value' ),
     635                'cancelled'         => (int) $order->get_meta( 'cryptapi_cancelled' ),
     636                'coin'              => strtoupper( $order->get_meta( 'cryptapi_currency' ) ),
     637                'show_min_fee'      => $showMinFee,
     638                'order_history'     => json_decode( $order->get_meta( 'cryptapi_history' ), true ),
     639                'counter'           => (string) $counter_calc,
     640                'crypto_total'      => floatval( $order->get_meta( 'cryptapi_total' ) ),
     641                'already_paid'      => $already_paid,
     642                'remaining'         => $remaining_pending <= 0 ? 0 : $remaining_pending,
     643                'fiat_remaining'    => $remaining_fiat <= 0 ? 0 : $remaining_fiat,
     644                'already_paid_fiat' => floatval( $already_paid_fiat ) <= 0 ? 0 : floatval( $already_paid_fiat ),
     645                'fiat_symbol'       => get_woocommerce_currency_symbol(),
     646            ];
     647
     648            echo json_encode( $data );
     649            die();
     650
     651        } catch ( Exception $e ) {
     652            //
     653        }
     654
     655        echo json_encode( [ 'status' => 'error', 'error' => 'Not a valid order_id' ] );
     656        die();
     657    }
     658
     659    function validate_logs() {
     660        $order_id = sanitize_text_field( $_REQUEST['order_id'] );
     661        $order = new WC_Order($order_id);
     662
     663        try {
     664
     665            $callbacks = CryptAPI\Helper::check_logs( $order->get_meta( 'cryptapi_callback_url' ), $order->get_meta( 'cryptapi_currency' ) );
     666
     667            $order->update_meta_data( 'cryptapi_last_checked', time() );
     668            $order->save_meta_data();
     669
     670            if($callbacks) {
     671                foreach ( $callbacks as $callback ) {
     672                    $logs        = $callback->logs;
     673                    $request_url = parse_url( $logs[0]->request_url );
     674                    parse_str( $request_url['query'], $data );
     675
     676                    if ( empty( $history[ $data->uuid ] ) || ( ! empty( $history[ $data->uuid ] ) && (int) $history[ $data->uuid ]['pending'] === 1 && (int) $data['pending'] === 0 ) ) {
     677                        $this->process_callback_data( $data, $order, true );
     678                    }
     679                }
     680            }
     681            die();
     682        } catch ( Exception $e ) {
     683            //
     684        }
     685        die();
     686    }
     687
     688    function process_callback_data( $data, $order, $validation = false ) {
     689        $paid = floatval( $data['value_coin'] );
     690
     691        $min_tx = floatval( $order->get_meta( 'cryptapi_min' ) );
     692
     693        $crypto_coin = strtoupper( $order->get_meta( 'cryptapi_currency' ) );
     694
     695        $history = json_decode( $order->get_meta( 'cryptapi_history' ), true );
     696
     697        if(!$data['uuid']) {
     698            if ( ! $validation ) {
     699                die( "*ok*" );
     700            } else {
     701                return;
     702            }
    461703        }
    462     }
    463 
    464     function validate_fields()
    465     {
    466         return array_key_exists(sanitize_text_field($_POST['cryptapi_coin']), WC_CryptAPI_Gateway::$COIN_OPTIONS);
    467     }
    468 
    469     function process_payment($order_id)
    470     {
    471         global $woocommerce;
    472 
    473         $selected = sanitize_text_field($_POST['cryptapi_coin']);
    474 
    475         if ($selected === 'none') {
    476             wc_add_notice(__('Payment error: ', 'woocommerce') . ' ' . __('Please choose a cryptocurrency', 'cryptapi'), 'error');
    477 
    478             return null;
    479         }
    480 
    481         $api_key = $this->api_key;
    482         $addr = $this->{$selected . '_address'};
    483 
    484         if (!empty($addr) || !empty($api_key)) {
    485 
    486             $nonce = $this->generate_nonce();
    487 
    488             $callback_url = str_replace('https:', 'http:', add_query_arg(array(
    489                 'wc-api' => 'WC_Gateway_CryptAPI',
    490                 'order_id' => $order_id,
    491                 'nonce' => $nonce,
    492             ), home_url('/')));
    493 
    494             try {
    495                 $order = new WC_Order($order_id);
    496 
    497                 if (in_array('woocommerce-subscriptions/woocommerce-subscriptions.php', apply_filters('active_plugins', get_option('active_plugins')))) {
    498 
    499                     if (wcs_order_contains_subscription($order_id)) {
    500 
    501                         $sign_up_fee = (WC_Subscriptions_Order::get_sign_up_fee($order)) ? 0 : WC_Subscriptions_Order::get_sign_up_fee($order);
    502                         $initial_payment = (WC_Subscriptions_Order::get_total_initial_payment($order)) ? 0 : WC_Subscriptions_Order::get_total_initial_payment($order);
    503                         $price_per_period = (WC_Subscriptions_Order::get_recurring_total($order)) ? 0 : WC_Subscriptions_Order::get_recurring_total($order);
    504 
    505                         $total = $sign_up_fee + $initial_payment + $price_per_period + $order->get_total('edit');
    506 
    507                         if ($total == 0) {
    508                             $order->add_meta_data('cryptapi_currency', $selected);
    509                             $order->save_meta_data();
    510                             $order->payment_complete();
    511                             $woocommerce->cart->empty_cart();
    512 
    513                             return array(
    514                                 'result' => 'success',
    515                                 'redirect' => $this->get_return_url($order)
    516                             );
    517                         }
    518                     }
    519                 }
    520 
    521                 $total = $order->get_total('edit');
    522 
    523                 $currency = get_woocommerce_currency();
    524 
    525                 $info = CryptAPI\Helper::get_info($selected);
    526                 $min_tx = CryptAPI\Helper::sig_fig($info->minimum_transaction_coin, 6);
    527 
    528                 $crypto_total = CryptAPI\Helper::get_conversion($currency, $selected, $total, $this->disable_conversion);
    529 
    530                 if ($crypto_total < $min_tx) {
    531                     wc_add_notice(__('Payment error:', 'woocommerce') . ' ' . __('Value too low, minimum is', 'cryptapi') . ' ' . $min_tx . ' ' . strtoupper($selected), 'error');
    532 
    533                     return null;
    534                 }
    535 
    536                 $ca = new CryptAPI\Helper($selected, $addr, $api_key, $callback_url, [], true);
    537 
    538                 $addr_in = $ca->get_address();
    539 
    540                 if (empty($addr_in)) {
    541                     wc_add_notice(__('Payment error:', 'woocommerce') . ' ' . __('There was an error with the payment. Please try again.', 'cryptapi'));
    542 
    543                     return null;
    544                 }
    545 
    546                 $qr_code_data_value = CryptAPI\Helper::get_static_qrcode($addr_in, $selected, $crypto_total, $this->qrcode_size);
    547                 $qr_code_data = CryptAPI\Helper::get_static_qrcode($addr_in, $selected, '', $this->qrcode_size);
    548 
    549                 $order->add_meta_data('cryptapi_nonce', $nonce);
    550                 $order->add_meta_data('cryptapi_address', $addr_in);
    551                 $order->add_meta_data('cryptapi_total', CryptAPI\Helper::sig_fig($crypto_total, 6));
    552                 $order->add_meta_data('cryptapi_total_fiat', $total);
    553                 $order->add_meta_data('cryptapi_currency', $selected);
    554                 $order->add_meta_data('cryptapi_qr_code_value', $qr_code_data_value['qr_code']);
    555                 $order->add_meta_data('cryptapi_qr_code', $qr_code_data['qr_code']);
    556                 $order->add_meta_data('cryptapi_last_price_update', time());
    557                 $order->add_meta_data('cryptapi_cancelled', '0');
    558                 $order->add_meta_data('cryptapi_min', $min_tx);
    559                 $order->add_meta_data('cryptapi_history', json_encode([]));
    560                 $order->add_meta_data('cryptapi_callback_url', $callback_url);
    561                 $order->add_meta_data('cryptapi_last_checked', $order->get_date_created()->getTimestamp());
    562                 $order->save_meta_data();
    563 
    564                 $order->update_status('on-hold', __('Awaiting payment', 'cryptapi') . ': ' . WC_CryptAPI_Gateway::$COIN_OPTIONS[$selected]);
    565                 $woocommerce->cart->empty_cart();
    566 
    567                 return array(
    568                     'result' => 'success',
    569                     'redirect' => $this->get_return_url($order)
    570                 );
    571 
    572             } catch (Exception $e) {
    573                 wc_add_notice(__('Payment error:', 'cryptapi') . 'Unknown coin', 'error');
    574 
    575                 return null;
    576             }
    577         }
    578 
    579         wc_add_notice(__('Payment error:', 'woocommerce') . __('Payment could not be processed, please try again', 'cryptapi'), 'error');
    580 
    581         return null;
    582     }
    583 
    584     function validate_payment()
    585     {
    586         $data = CryptAPI\Helper::process_callback($_GET);
    587 
    588         $order = new WC_Order($data['order_id']);
    589 
    590         if ($order->is_paid() || $order->get_status() === 'cancelled' || $data['nonce'] != $order->get_meta('cryptapi_nonce')) {
    591             die("*ok*");
    592         }
    593 
    594         $order->update_meta_data('cryptapi_last_checked', time());
    595         $order->save_meta_data();
    596 
    597         // Actually process the callback data
    598         $this->process_callback_data($data, $order);
    599     }
    600 
    601     function order_status()
    602     {
    603         $order_id = sanitize_text_field($_REQUEST['order_id']);
    604 
    605         try {
    606             $order = new WC_Order($order_id);
    607 
    608             $showMinFee = '0';
    609 
    610             $history = json_decode($order->get_meta('cryptapi_history'), true);
    611 
    612             $calc = $this->calc_order($history, $order->get_meta('cryptapi_total'), $order->get_meta('cryptapi_total_fiat'));
    613 
    614             $already_paid = $calc['already_paid'];
    615             $already_paid_fiat = $calc['already_paid_fiat'];
    616 
    617             $min_tx = floatval($order->get_meta('cryptapi_min'));
    618 
    619             $remaining_pending = $calc['remaining_pending'];
    620             $remaining_fiat = $calc['remaining_fiat'];
    621 
    622             $cryptapi_pending = 0;
    623 
    624             $counter_calc = (int)$order->get_meta('cryptapi_last_price_update') + (int)$this->refresh_value_interval - time();
    625 
    626             if ($remaining_pending <= 0 && !$order->is_paid()) {
    627                 $cryptapi_pending = 1;
    628             }
    629 
    630             if ($counter_calc <= 0 && !$order->is_paid()) {
    631                 $this->ca_cronjob();
    632             }
    633 
    634             if ($remaining_pending <= $min_tx && $remaining_pending > 0) {
    635                 $remaining_pending = $min_tx;
    636                 $showMinFee = 1;
    637             }
    638 
    639             if (((int)$order->get_meta('cryptapi_last_checked') + 60) < time() && (int)$order->get_meta('cryptapi_cancelled') === 0 && !$order->is_paid()) {
    640                 $this->validate_logs($order, $history);
    641             }
    642 
    643             $data = [
    644                 'is_paid' => $order->is_paid(),
    645                 'is_pending' => $cryptapi_pending,
    646                 'qr_code_value' => $order->get_meta('cryptapi_qr_code_value'),
    647                 'cancelled' => (int)$order->get_meta('cryptapi_cancelled'),
    648                 'coin' => strtoupper($order->get_meta('cryptapi_currency')),
    649                 'show_min_fee' => $showMinFee,
    650                 'order_history' => json_decode($order->get_meta('cryptapi_history'), true),
    651                 'counter' => (string)$counter_calc,
    652                 'crypto_total' => floatval($order->get_meta('cryptapi_total')),
    653                 'already_paid' => $already_paid,
    654                 'remaining' => $remaining_pending <= 0 ? 0 : $remaining_pending,
    655                 'fiat_remaining' => $remaining_fiat <= 0 ? 0 : $remaining_fiat,
    656                 'already_paid_fiat' => floatval($already_paid_fiat) <= 0 ? 0 : floatval($already_paid_fiat),
    657                 'fiat_symbol' => get_woocommerce_currency_symbol(),
    658             ];
    659 
    660             echo json_encode($data);
    661             die();
    662 
    663         } catch (Exception $e) {
    664             //
    665         }
    666 
    667         echo json_encode(['status' => 'error', 'error' => 'Not a valid order_id']);
    668         die();
    669     }
    670 
    671     function validate_logs($order, $history)
    672     {
    673         $callbacks = CryptAPI\Helper::check_logs($order->get_meta('cryptapi_callback_url'), $order->get_meta('cryptapi_currency'));
    674 
    675         $order->update_meta_data('cryptapi_last_checked', time());
    676         $order->save_meta_data();
    677 
    678         foreach ($callbacks as $callback) {
    679             $logs = $callback->logs;
    680             $request_url = parse_url($logs[0]->request_url);
    681             parse_str($request_url['query'], $data);
    682 
    683             if (empty($history[$data->uuid]) || (!empty($history[$data->uuid]) && (int)$history[$data->uuid]['pending'] === 1 && (int)$data['pending'] === 0)) {
    684                 $this->process_callback_data($data, $order, true);
    685             }
    686         }
    687     }
    688 
    689     function process_callback_data($data, $order, $validation = false)
    690     {
    691         $paid = floatval($data['value_coin']);
    692 
    693         $min_tx = floatval($order->get_meta('cryptapi_min'));
    694 
    695         $crypto_coin = strtoupper($order->get_meta('cryptapi_currency'));
    696 
    697         $history = json_decode($order->get_meta('cryptapi_history'), true);
    698 
    699         if (empty($history[$data['uuid']])) {
    700             $conversion = json_decode(stripcslashes($data['value_coin_convert']), true);
    701 
    702             $history[$data['uuid']] = [
    703                 'timestamp' => time(),
    704                 'value_paid' => CryptAPI\Helper::sig_fig($paid, 6),
    705                 'value_paid_fiat' => $conversion[get_woocommerce_currency()],
    706                 'pending' => $data['pending']
    707             ];
    708         } else {
    709             $history[$data['uuid']]['pending'] = $data['pending'];
    710         }
    711 
    712         $order->update_meta_data('cryptapi_history', json_encode($history));
    713         $order->save_meta_data();
    714 
    715         $calc = $this->calc_order(json_decode($order->get_meta('cryptapi_history'), true), $order->get_meta('cryptapi_total'), $order->get_meta('cryptapi_total_fiat'));
    716 
    717         $remaining = $calc['remaining'];
    718         $remaining_pending = $calc['remaining_pending'];
    719 
    720         $order_notes = $this->get_private_order_notes($order->get_id());
    721 
    722         $has_pending = false;
    723         $has_confirmed = false;
    724 
    725         foreach ($order_notes as $note) {
    726             $note_content = $note['note_content'];
    727 
    728             if (strpos((string)$note_content, 'PENDING') && strpos((string)$note_content, $data['txid_in'])) {
    729                 $has_pending = true;
    730             }
    731 
    732             if (strpos((string)$note_content, 'CONFIRMED') && strpos((string)$note_content, $data['txid_in'])) {
    733                 $has_confirmed = true;
    734             }
    735         }
    736 
    737         if (!$has_pending) {
    738             $order->add_order_note(
    739                 '[PENDING] ' .
    740                 __('User sent a payment of', 'cryptapi') . ' ' .
    741                 $paid . ' ' . $crypto_coin .
    742                 '. TXID: ' . $data['txid_in']
    743             );
    744         }
    745 
    746         if (!$has_confirmed && (int)$data['pending'] === 0) {
    747             $order->add_order_note(
    748                 '[CONFIRMED] ' . __('User sent a payment of', 'cryptapi') . ' ' .
    749                 $paid . ' ' . $crypto_coin .
    750                 '. TXID: ' . $data['txid_in']
    751             );
    752 
    753             if ($remaining > 0) {
    754                 if ($remaining < $min_tx) {
    755                     $order->add_order_note(__('Payment detected and confirmed. Customer still need to send', 'cryptapi') . ' ' . $min_tx . $crypto_coin, false);
    756                 } else {
    757                     $order->add_order_note(__('Payment detected and confirmed. Customer still need to send', 'cryptapi') . ' ' . $remaining . $crypto_coin, false);
    758                 }
    759             }
    760         }
    761 
    762         if ($remaining_pending <= 0) {
    763             if ($remaining <= 0) {
    764                 $order->payment_complete($data['address_in']);
    765                 if ($this->virtual_complete) {
    766                     $count_products = count($order->get_items());
    767                     $count_virtual = 0;
    768                     foreach ($order->get_items() as $order_item) {
    769                         $item = wc_get_product($order_item->get_product_id());
    770                         $item_obj = $item->get_type() === 'variable' ? wc_get_product($order_item['variation_id']) : $item;
    771 
    772                         if ($item_obj->is_virtual()) {
    773                             $count_virtual += 1;
    774                         }
    775                     }
    776                     if ($count_virtual === $count_products) {
    777                         $order->update_status('completed');
    778                     }
    779                 }
    780                 $order->save();
    781             }
    782             if (!$validation) {
    783                 die("*ok*");
    784             } else {
    785                 return;
    786             }
    787         }
    788 
    789         if ($remaining_pending < $min_tx) {
    790             $order->update_meta_data('cryptapi_qr_code_value', CryptAPI\Helper::get_static_qrcode($order->get_meta('cryptapi_address'), $order->get_meta('cryptapi_currency'), $min_tx, $this->qrcode_size)['qr_code']);
    791         } else {
    792             $order->update_meta_data('cryptapi_qr_code_value', CryptAPI\Helper::get_static_qrcode($order->get_meta('cryptapi_address'), $order->get_meta('cryptapi_currency'), $remaining_pending, $this->qrcode_size)['qr_code']);
    793         }
    794         $order->save_meta_data();
    795 
    796         if (!$validation) {
    797             die("*ok*");
    798         }
    799     }
    800 
    801     function thankyou_page($order_id)
    802     {
    803         if (WC_CryptAPI_Gateway::$HAS_TRIGGERED) {
    804             return;
    805         }
    806         WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
    807 
    808         $order = new WC_Order($order_id);
    809         $total = $order->get_total();
    810         $currency_symbol = get_woocommerce_currency_symbol();
    811         $address_in = $order->get_meta('cryptapi_address');
    812         $crypto_value = $order->get_meta('cryptapi_total');
    813         $crypto_coin = $order->get_meta('cryptapi_currency');
    814         $qr_code_img_value = $order->get_meta('cryptapi_qr_code_value');
    815         $qr_code_img = $order->get_meta('cryptapi_qr_code');
    816         $qr_code_setting = $this->get_option('qrcode_setting');
    817         $color_scheme = $this->get_option('color_scheme');
    818         $min_tx = $order->get_meta('cryptapi_min');
    819 
    820         $ajax_url = add_query_arg(array(
    821             'action' => 'cryptapi_order_status',
    822             'order_id' => $order_id,
    823         ), home_url('/wp-admin/admin-ajax.php'));
    824 
    825         wp_enqueue_script('ca-payment', CRYPTAPI_PLUGIN_URL . 'static/payment.js', array(), CRYPTAPI_PLUGIN_VERSION, true);
    826         wp_add_inline_script('ca-payment', "jQuery(function() {let ajax_url = '{$ajax_url}'; setTimeout(function(){check_status(ajax_url)}, 500)})");
    827         wp_enqueue_style('ca-loader-css', CRYPTAPI_PLUGIN_URL . 'static/cryptapi.css', false, CRYPTAPI_PLUGIN_VERSION);
    828 
    829         $allowed_to_value = array(
    830             'btc',
    831             'eth',
    832             'bch',
    833             'ltc',
    834             'miota',
    835             'xmr',
    836         );
    837 
    838         $crypto_allowed_value = false;
    839 
    840         $conversion_timer = ((int)$order->get_meta('cryptapi_last_price_update') + (int)$this->refresh_value_interval) - time();
    841         $cancel_timer = $order->get_date_created()->getTimestamp() + (int)$this->order_cancelation_timeout - time();
    842 
    843         if (in_array($crypto_coin, $allowed_to_value, true)) {
    844             $crypto_allowed_value = true;
    845         }
    846         ?>
    847         <div class="ca_payment-panel<?php
    848         if ($color_scheme == 'auto') {
    849             echo ' auto';
    850         } elseif ($color_scheme == 'light') {
    851             echo ' light';
    852         } else {
    853             echo ' dark';
    854         }
    855         ?>">
     704
     705        if ( empty( $history[ $data['uuid'] ] ) ) {
     706            $conversion = json_decode( stripcslashes( $data['value_coin_convert'] ), true );
     707
     708            $history[ $data['uuid'] ] = [
     709                'timestamp'       => time(),
     710                'value_paid'      => CryptAPI\Helper::sig_fig( $paid, 6 ),
     711                'value_paid_fiat' => $conversion[ get_woocommerce_currency() ],
     712                'pending'         => $data['pending']
     713            ];
     714        } else {
     715            $history[ $data['uuid'] ]['pending'] = $data['pending'];
     716        }
     717
     718        $order->update_meta_data( 'cryptapi_history', json_encode( $history ) );
     719        $order->save_meta_data();
     720
     721        $calc = $this->calc_order( json_decode( $order->get_meta( 'cryptapi_history' ), true ), $order->get_meta( 'cryptapi_total' ), $order->get_meta( 'cryptapi_total_fiat' ) );
     722
     723        $remaining         = $calc['remaining'];
     724        $remaining_pending = $calc['remaining_pending'];
     725
     726        $order_notes = $this->get_private_order_notes( $order->get_id() );
     727
     728        $has_pending   = false;
     729        $has_confirmed = false;
     730
     731        foreach ( $order_notes as $note ) {
     732            $note_content = $note['note_content'];
     733
     734            if ( strpos( (string) $note_content, 'PENDING' ) && strpos( (string) $note_content, $data['txid_in'] ) ) {
     735                $has_pending = true;
     736            }
     737
     738            if ( strpos( (string) $note_content, 'CONFIRMED' ) && strpos( (string) $note_content, $data['txid_in'] ) ) {
     739                $has_confirmed = true;
     740            }
     741        }
     742
     743        if ( ! $has_pending ) {
     744            $order->add_order_note(
     745                '[PENDING] ' .
     746                __( 'User sent a payment of', 'cryptapi' ) . ' ' .
     747                $paid . ' ' . $crypto_coin .
     748                '. TXID: ' . $data['txid_in']
     749            );
     750        }
     751
     752        if ( ! $has_confirmed && (int) $data['pending'] === 0 ) {
     753            $order->add_order_note(
     754                '[CONFIRMED] ' . __( 'User sent a payment of', 'cryptapi' ) . ' ' .
     755                $paid . ' ' . $crypto_coin .
     756                '. TXID: ' . $data['txid_in']
     757            );
     758
     759            if ( $remaining > 0 ) {
     760                if ( $remaining < $min_tx ) {
     761                    $order->add_order_note( __( 'Payment detected and confirmed. Customer still need to send', 'cryptapi' ) . ' ' . $min_tx . $crypto_coin, false );
     762                } else {
     763                    $order->add_order_note( __( 'Payment detected and confirmed. Customer still need to send', 'cryptapi' ) . ' ' . $remaining . $crypto_coin, false );
     764                }
     765            }
     766        }
     767
     768        if ( $remaining_pending <= 0 ) {
     769            if ( $remaining <= 0 ) {
     770                $order->payment_complete( $data['address_in'] );
     771                if ( $this->virtual_complete ) {
     772                    $count_products = count( $order->get_items() );
     773                    $count_virtual  = 0;
     774                    foreach ( $order->get_items() as $order_item ) {
     775                        $item     = wc_get_product( $order_item->get_product_id() );
     776                        $item_obj = $item->get_type() === 'variable' ? wc_get_product( $order_item['variation_id'] ) : $item;
     777
     778                        if ( $item_obj->is_virtual() ) {
     779                            $count_virtual += 1;
     780                        }
     781                    }
     782                    if ( $count_virtual === $count_products ) {
     783                        $order->update_status( 'completed' );
     784                    }
     785                }
     786                $order->save();
     787            }
     788            if ( ! $validation ) {
     789                die( "*ok*" );
     790            } else {
     791                return;
     792            }
     793        }
     794
     795        if ( $remaining_pending < $min_tx ) {
     796            $order->update_meta_data( 'cryptapi_qr_code_value', CryptAPI\Helper::get_static_qrcode( $order->get_meta( 'cryptapi_address' ), $order->get_meta( 'cryptapi_currency' ), $min_tx, $this->qrcode_size )['qr_code'] );
     797        } else {
     798            $order->update_meta_data( 'cryptapi_qr_code_value', CryptAPI\Helper::get_static_qrcode( $order->get_meta( 'cryptapi_address' ), $order->get_meta( 'cryptapi_currency' ), $remaining_pending, $this->qrcode_size )['qr_code'] );
     799        }
     800        $order->save_meta_data();
     801
     802        if ( ! $validation ) {
     803            die( "*ok*" );
     804        }
     805    }
     806
     807    function thankyou_page( $order_id ) {
     808        if ( WC_CryptAPI_Gateway::$HAS_TRIGGERED ) {
     809            return;
     810        }
     811        WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
     812
     813        $order             = new WC_Order( $order_id );
     814        $total             = $order->get_total();
     815        $currency_symbol   = get_woocommerce_currency_symbol();
     816        $address_in        = $order->get_meta( 'cryptapi_address' );
     817        $crypto_value      = $order->get_meta( 'cryptapi_total' );
     818        $crypto_coin       = $order->get_meta( 'cryptapi_currency' );
     819        $qr_code_img_value = $order->get_meta( 'cryptapi_qr_code_value' );
     820        $qr_code_img       = $order->get_meta( 'cryptapi_qr_code' );
     821        $qr_code_setting   = $this->get_option( 'qrcode_setting' );
     822        $color_scheme      = $this->get_option( 'color_scheme' );
     823        $min_tx            = $order->get_meta( 'cryptapi_min' );
     824
     825        $ajax_url = add_query_arg( array(
     826            'action'   => 'cryptapi_order_status',
     827            'order_id' => $order_id,
     828        ), home_url( '/wp-admin/admin-ajax.php' ) );
     829
     830        wp_enqueue_script( 'ca-payment', CRYPTAPI_PLUGIN_URL . 'static/payment.js', array(), CRYPTAPI_PLUGIN_VERSION, true );
     831        wp_add_inline_script( 'ca-payment', "jQuery(function() {let ajax_url = '{$ajax_url}'; setTimeout(function(){check_status(ajax_url)}, 500)})" );
     832        wp_enqueue_style( 'ca-loader-css', CRYPTAPI_PLUGIN_URL . 'static/cryptapi.css', false, CRYPTAPI_PLUGIN_VERSION );
     833
     834        $allowed_to_value = array(
     835            'btc',
     836            'eth',
     837            'bch',
     838            'ltc',
     839            'miota',
     840            'xmr',
     841        );
     842
     843        $crypto_allowed_value = false;
     844
     845        $conversion_timer = ( (int) $order->get_meta( 'cryptapi_last_price_update' ) + (int) $this->refresh_value_interval ) - time();
     846        $cancel_timer     = $order->get_date_created()->getTimestamp() + (int) $this->order_cancelation_timeout - time();
     847
     848        if ( in_array( $crypto_coin, $allowed_to_value, true ) ) {
     849            $crypto_allowed_value = true;
     850        }
     851        ?>
     852        <div class="ca_payment-panel<?php esc_attr( $color_scheme ) ?>">
    856853            <div class="ca_payment_details">
    857                 <?php
    858                 if ($total > 0) {
    859                     ?>
     854                <?php
     855                if ( $total > 0 ) {
     856                    ?>
    860857                    <div class="ca_payments_wrapper">
    861858                        <div class="ca_qrcode_wrapper" style="<?php
    862                         if ($this->qrcode_default) {
    863                             echo 'display: block';
    864                         } else {
    865                             echo 'display: none';
    866                         }
    867                         ?>; width: <?php echo intval($this->qrcode_size) + 20; ?>px;">
    868                             <?php
    869                             if ($crypto_allowed_value == true) {
    870                                 ?>
     859                        if ( $this->qrcode_default ) {
     860                            echo 'display: block';
     861                        } else {
     862                            echo 'display: none';
     863                        }
     864                        ?>; width: <?php echo intval( $this->qrcode_size ) + 20; ?>px;">
     865                            <?php
     866                            if ( $crypto_allowed_value == true ) {
     867                                ?>
    871868                                <div class="inner-wrapper">
    872869                                    <figure>
    873                                         <?php
    874                                         if ($qr_code_setting != 'hide_ammount') {
    875                                             ?>
     870                                        <?php
     871                                        if ( $qr_code_setting != 'hide_ammount' ) {
     872                                            ?>
    876873                                            <img class="ca_qrcode no_value" <?php
    877                                             if ($qr_code_setting == 'ammount') {
    878                                                 echo 'style="display:none;"';
    879                                             }
    880                                             ?> src="data:image/png;base64,<?php echo $qr_code_img; ?>" alt="<?php echo __('QR Code without value', 'cryptapi'); ?>"/>
    881                                             <?php
    882                                         }
    883                                         if ($qr_code_setting != 'hide_without_ammount') {
    884                                             ?>
     874                                            if ( $qr_code_setting == 'ammount' ) {
     875                                                echo 'style="display:none;"';
     876                                            }
     877                                            ?> src="data:image/png;base64,<?php echo $qr_code_img; ?>" alt="<?php echo esc_attr( __( 'QR Code without value', 'cryptapi' ) ); ?>"/>
     878                                            <?php
     879                                        }
     880                                        if ( $qr_code_setting != 'hide_without_ammount' ) {
     881                                            ?>
    885882                                            <img class="ca_qrcode value" <?php
    886                                             if ($qr_code_setting == 'without_ammount') {
    887                                                 echo 'style="display:none;"';
    888                                             }
    889                                             ?> src="data:image/png;base64,<?php echo $qr_code_img_value; ?>"
    890                                                  alt="<?php echo __('QR Code with value', 'cryptapi'); ?>"/>
    891                                             <?php
    892                                         }
    893                                         ?>
     883                                            if ( $qr_code_setting == 'without_ammount' ) {
     884                                                echo 'style="display:none;"';
     885                                            }
     886                                            ?> src="data:image/png;base64,<?php echo $qr_code_img_value; ?>"
     887                                                 alt="<?php echo esc_attr( __( 'QR Code with value', 'cryptapi' ) ); ?>"/>
     888                                            <?php
     889                                        }
     890                                        ?>
    894891                                    </figure>
    895                                     <?php
    896                                     if ($qr_code_setting != 'hide_ammount' && $qr_code_setting != 'hide_without_ammount') {
    897                                         ?>
     892                                    <?php
     893                                    if ( $qr_code_setting != 'hide_ammount' && $qr_code_setting != 'hide_without_ammount' ) {
     894                                        ?>
    898895                                        <div class="ca_qrcode_buttons">
    899                                         <?php
    900                                         if ($qr_code_setting != 'hide_without_ammount') {
    901                                             ?>
    902                                             <button class="ca_qrcode_btn no_value<?php
    903                                             if ($qr_code_setting == 'without_ammount') {
    904                                                 echo ' active';
    905                                             }
    906                                             ?>" aria-label="<?php echo __('Show QR Code without value', 'cryptapi'); ?>">
    907                                                 <?php echo __('ADDRESS', 'cryptapi'); ?>
     896                                        <?php
     897                                        if ( $qr_code_setting != 'hide_without_ammount' ) {
     898                                            ?>
     899                                            <button class="ca_qrcode_btn no_value <?php
     900                                            if ( $qr_code_setting == 'without_ammount' ) {
     901                                                echo " active";
     902                                            }
     903                                            ?>" aria-label="<?php echo esc_attr( __( 'Show QR Code without value', 'cryptapi' ) ); ?>">
     904                                                <?php echo esc_attr( __( 'ADDRESS', 'cryptapi' ) ); ?>
    908905                                            </button>
    909                                             <?php
    910                                         }
    911                                         if ($qr_code_setting != 'hide_ammount') {
    912                                             ?>
     906                                            <?php
     907                                        }
     908                                        if ( $qr_code_setting != 'hide_ammount' ) {
     909                                            ?>
    913910                                            <button class="ca_qrcode_btn value<?php
    914                                             if ($qr_code_setting == 'ammount') {
    915                                                 echo ' active';
    916                                             }
    917                                             ?>" aria-label="<?php echo __('Show QR Code with value', 'cryptapi'); ?>">
    918                                                 <?php echo __('WITH AMOUNT', 'cryptapi'); ?>
     911                                            if ( $qr_code_setting == 'ammount' ) {
     912                                                echo " active";
     913                                            }
     914                                            ?>" aria-label="<?php echo esc_attr( __( 'Show QR Code with value', 'cryptapi' ) ); ?>">
     915                                                <?php echo esc_attr( __( 'WITH AMOUNT', 'cryptapi' ) ); ?>
    919916                                            </button>
    920917                                            </div>
    921                                             <?php
    922                                         }
    923                                     }
    924                                     ?>
     918                                            <?php
     919                                        }
     920                                    }
     921                                    ?>
    925922                                </div>
    926                                 <?php
    927                             } else {
    928                                 ?>
     923                                <?php
     924                            } else {
     925                                ?>
    929926                                <div class="inner-wrapper">
    930927                                    <figure>
    931                                         <img class="ca_qrcode no_value" src="data:image/png;base64,<?php echo $qr_code_img; ?>"
    932                                              alt="<?php echo __('QR Code without value', 'cryptapi'); ?>"/>
     928                                        <img class="ca_qrcode no_value" src="data:image/png;base64,<?php echo esc_attr( $qr_code_img ); ?>"
     929                                             alt="<?php echo esc_attr( __( 'QR Code without value', 'cryptapi' ) ); ?>"/>
    933930                                    </figure>
    934931                                    <div class="ca_qrcode_buttons">
    935                                         <button class="ca_qrcode_btn no_value active" aria-label="<?php echo __('Show QR Code without value', 'cryptapi'); ?>">
    936                                             <?php echo __('ADDRESS', 'cryptapi'); ?>
     932                                        <button class="ca_qrcode_btn no_value active" aria-label="<?php echo esc_attr( __( 'Show QR Code without value', 'cryptapi' ) ); ?>">
     933                                            <?php echo esc_attr( __( 'ADDRESS', 'cryptapi' ) ); ?>
    937934                                        </button>
    938935                                    </div>
    939936                                </div>
    940937
    941                                 <?php
    942                             }
    943                             ?>
     938                                <?php
     939                            }
     940                            ?>
    944941                        </div>
    945942                        <div class="ca_details_box">
    946943                            <div class="ca_details_text">
    947                                 <?php echo __('PLEASE SEND', 'cryptapi') ?>
    948                                 <button class="ca_copy ca_details_copy" data-tocopy="<?php echo $crypto_value; ?>">
    949                                     <span><b class="ca_value"><?php echo $crypto_value ?></b></span>
    950                                     <span><b><?php echo strtoupper($crypto_coin) ?></b></span>
    951                                     <span class="ca_tooltip ca_copy_icon_tooltip tip"><?php echo __('COPY', 'cryptapi'); ?></span>
    952                                     <span class="ca_tooltip ca_copy_icon_tooltip success" style="display: none"><?php echo __('COPIED!', 'cryptapi'); ?></span>
     944                                <?php echo esc_attr( __( 'PLEASE SEND', 'cryptapi' ) ) ?>
     945                                <button class="ca_copy ca_details_copy" data-tocopy="<?php echo esc_attr( $crypto_value ); ?>">
     946                                    <span><b class="ca_value"><?php echo esc_attr( $crypto_value ) ?></b></span>
     947                                    <span><b><?php echo strtoupper( esc_attr( $crypto_coin ) ) ?></b></span>
     948                                    <span class="ca_tooltip ca_copy_icon_tooltip tip"><?php echo esc_attr( __( 'COPY', 'cryptapi' ) ); ?></span>
     949                                    <span class="ca_tooltip ca_copy_icon_tooltip success" style="display: none"><?php echo esc_attr( __( 'COPIED!', 'cryptapi' ) ); ?></span>
    953950                                </button>
    954                                 <strong>(<?php echo "{$currency_symbol}" . " <span class='ca_fiat_total'>" . $total . "</span>"; ?>)</strong>
     951                                <strong>(<?php echo esc_attr( $currency_symbol ) . " <span class='ca_fiat_total'>" . esc_attr( $total ) . "</span>"; ?>)</strong>
    955952                            </div>
    956953                            <div class="ca_payment_notification ca_notification_payment_received" style="display: none;">
    957                                 <?php echo sprintf(__('So far you sent %1s. Please send a new payment to complete the order, as requested above', 'cryptapi'),
    958                                     '<strong><span class="ca_notification_ammount"></span></strong>'
    959                                 ); ?>
     954                                <?php echo sprintf( esc_attr( __( 'So far you sent %1s. Please send a new payment to complete the order, as requested above', 'cryptapi' ) ),
     955                                    '<strong><span class="ca_notification_ammount"></span></strong>'
     956                                ); ?>
    960957                            </div>
    961958                            <div class="ca_payment_notification ca_notification_remaining" style="display: none">
    962                                 <?php echo '<strong>' . __('Notice', 'cryptapi') . '</strong>: ' . sprintf(__('For technical reasons, the minimum amount for each transaction is %1s, so we adjusted the value by adding the remaining to it.', 'cryptapi'),
    963                                         $min_tx . ' ' . strtoupper($crypto_coin),
    964                                         '<span class="ca_notification_remaining"></span>'
    965                                     ); ?>
     959                                <?php echo '<strong>' . esc_attr( __( 'Notice', 'cryptapi' ) ) . '</strong>: ' . sprintf( esc_attr( __( 'For technical reasons, the minimum amount for each transaction is %1s, so we adjusted the value by adding the remaining to it.', 'cryptapi' ) ),
     960                                        $min_tx . ' ' . strtoupper( $crypto_coin ),
     961                                        '<span class="ca_notification_remaining"></span>'
     962                                    ); ?>
    966963                            </div>
    967                             <?php
    968                             if (intval($this->refresh_value_interval) != 0) {
    969                                 ?>
     964                            <?php
     965                            if ( intval( $this->refresh_value_interval ) != 0 ) {
     966                                ?>
    970967                                <div class="ca_time_refresh">
    971                                     <?php echo sprintf(__('The %1s conversion rate will be adjusted in', 'cryptapi'),
    972                                         strtoupper($crypto_coin)
    973                                     ); ?>
    974                                     <span class="ca_time_seconds_count" data-soon="<?php echo __('a moment', 'cryptapi'); ?>"
    975                                           data-seconds="<?php echo $conversion_timer; ?>"><?php echo date('i:s', $conversion_timer); ?></span>
     968                                    <?php echo sprintf( esc_attr( __( 'The %1s conversion rate will be adjusted in', 'cryptapi' ) ),
     969                                        strtoupper( $crypto_coin )
     970                                    ); ?>
     971                                    <span class="ca_time_seconds_count" data-soon="<?php echo esc_attr( __( 'a moment', 'cryptapi' ) ); ?>"
     972                                          data-seconds="<?php echo esc_attr( $conversion_timer ); ?>"><?php echo esc_attr( date( 'i:s', $conversion_timer ) ); ?></span>
    976973                                </div>
    977                                 <?php
    978                             }
    979                             ?>
     974                                <?php
     975                            }
     976                            ?>
    980977                            <div class="ca_details_input">
    981                                 <span><?php echo $address_in ?></span>
    982                                 <button class="ca_copy ca_copy_icon" data-tocopy="<?php echo $address_in; ?>">
    983                                     <span class="ca_tooltip ca_copy_icon_tooltip tip"><?php echo __('COPY', 'cryptapi'); ?></span>
    984                                     <span class="ca_tooltip ca_copy_icon_tooltip success" style="display: none"><?php echo __('COPIED!', 'cryptapi'); ?></span>
     978                                <span><?php echo esc_attr( $address_in ) ?></span>
     979                                <button class="ca_copy ca_copy_icon" data-tocopy="<?php echo esc_attr( $address_in ); ?>">
     980                                    <span class="ca_tooltip ca_copy_icon_tooltip tip"><?php echo esc_attr( __( 'COPY', 'cryptapi' ) ); ?></span>
     981                                    <span class="ca_tooltip ca_copy_icon_tooltip success" style="display: none"><?php echo esc_attr( __( 'COPIED!', 'cryptapi' ) ); ?></span>
    985982                                </button>
    986983                                <div class="ca_loader"></div>
    987984                            </div>
    988985                        </div>
    989                         <?php
    990                         if (intval($this->order_cancelation_timeout) != 0) {
    991                             ?>
    992                             <span class="ca_notification_cancel" data-text="<?php echo __('Order will be cancelled in less than a minute.', 'cryptapi'); ?>">
    993                                     <?php echo sprintf(__('This order will be valid for %s', 'cryptapi'), '<strong><span class="ca_cancel_timer" data-timestamp="' . $cancel_timer . '">' . date('H:i', $cancel_timer) . '</span></strong>'); ?>
     986                        <?php
     987                        if ( intval( $this->order_cancelation_timeout ) != 0 ) {
     988                            ?>
     989                            <span class="ca_notification_cancel" data-text="<?php echo __( 'Order will be cancelled in less than a minute.', 'cryptapi' ); ?>">
     990                                    <?php echo sprintf( esc_attr( __( 'This order will be valid for %s', 'cryptapi' ) ), '<strong><span class="ca_cancel_timer" data-timestamp="' . $cancel_timer . '">' . date( 'H:i', $cancel_timer ) . '</span></strong>' ); ?>
    994991                                </span>
    995                             <?php
    996                         }
    997                         ?>
     992                            <?php
     993                        }
     994                        ?>
    998995                        <div class="ca_buttons_container">
    999                             <a class="ca_show_qr" href="#" aria-label="<?php echo __('Show the QR code', 'cryptapi'); ?>">
    1000                                 <span class="ca_show_qr_open<?php
    1001                                 if (!$this->qrcode_default) {
    1002                                     echo ' active';
     996                            <a class="ca_show_qr" href="#" aria-label="<?php echo esc_attr( __( 'Show the QR code', 'cryptapi' ) ); ?>">
     997                                <span class="ca_show_qr_open <?php
     998                                if ( ! $this->qrcode_default ) {
     999                                    echo " active";
    10031000                                }
    1004                                 ?>"><?php echo __('Open QR CODE', 'cryptapi'); ?></span>
    1005                                 <span class="ca_show_qr_close<?php
    1006                                 if ($this->qrcode_default) {
    1007                                     echo ' active';
    1008                                 }
    1009                                 ?>"><?php echo __('Close QR CODE', 'cryptapi'); ?></span>
     1001                                ?>"><?php echo __( 'Open QR CODE', 'cryptapi' ); ?></span>
     1002                                <span class="ca_show_qr_close <?php
     1003                                if ( $this->qrcode_default ) {
     1004                                    echo " active";
     1005                                }
     1006                                ?>"><?php echo esc_attr( __( 'Close QR CODE', 'cryptapi' ) ); ?></span>
    10101007                            </a>
    10111008                        </div>
    1012                         <?php
    1013                         if ($this->show_branding) {
    1014                             ?>
     1009                        <?php
     1010                        if ( $this->show_branding ) {
     1011                            ?>
    10151012                            <div class="ca_branding">
    10161013                                <a href="https://cryptapi.io/" target="_blank">
    10171014                                    <span>Powered by</span>
    1018                                     <img width="94" class="img-fluid" src="<?php echo CRYPTAPI_PLUGIN_URL . 'static/files/200_logo_ca.png' ?>" alt="Cryptapi Logo"/>
     1015                                    <img width="94" class="img-fluid" src="<?php echo esc_attr( CRYPTAPI_PLUGIN_URL . 'static/files/200_logo_ca.png' ) ?>" alt="Cryptapi Logo"/>
    10191016                                </a>
    10201017                            </div>
    1021                             <?php
    1022                         }
    1023                         ?>
     1018                            <?php
     1019                        }
     1020                        ?>
    10241021                    </div>
    1025                     <?php
    1026                 }
    1027                 if ($total == 0) {
    1028                     ?>
     1022                    <?php
     1023                }
     1024                if ( $total == 0 ) {
     1025                    ?>
    10291026                    <style>
    10301027                        .ca_payment_confirmed {
     
    10331030                        }
    10341031                    </style>
    1035                     <?php
    1036                 }
    1037                 ?>
     1032                    <?php
     1033                }
     1034                ?>
    10381035                <div class="ca_payment_processing" style="display: none;">
    10391036                    <div class="ca_payment_processing_icon">
    10401037                        <div class="ca_loader_payment_processing"></div>
    10411038                    </div>
    1042                     <h2><?php echo __('Your payment is being processed!', 'cryptapi'); ?></h2>
    1043                     <h5><?php echo __('Processing can take some time depending on the blockchain.', 'cryptapi'); ?></h5>
     1039                    <h2><?php echo esc_attr( __( 'Your payment is being processed!', 'cryptapi' ) ); ?></h2>
     1040                    <h5><?php echo esc_attr( __( 'Processing can take some time depending on the blockchain.', 'cryptapi' ) ); ?></h5>
    10441041                </div>
    10451042
     
    10511048                        </svg>
    10521049                    </div>
    1053                     <h2><?php echo __('Your payment has been confirmed!', 'cryptapi'); ?></h2>
     1050                    <h2><?php echo esc_attr( __( 'Your payment has been confirmed!', 'cryptapi' ) ); ?></h2>
    10541051                </div>
    10551052
     
    10611058                        </svg>
    10621059                    </div>
    1063                     <h2><?php echo __('Order has been cancelled due to lack of payment. Please don\'t send any payment to the address.', 'cryptapi'); ?></h2>
     1060                    <h2><?php echo esc_attr( __( 'Order has been cancelled due to lack of payment. Please don\'t send any payment to the address.', 'cryptapi' ) ); ?></h2>
    10641061                </div>
    10651062                <div class="ca_history" style="display: none;">
    10661063                    <table class="ca_history_fill">
    10671064                        <tr class="ca_history_header">
    1068                             <th><strong><?php echo __('Time', 'cryptapi'); ?></strong></th>
    1069                             <th><strong><?php echo __('Value Paid', 'cryptapi'); ?></strong></th>
    1070                             <th><strong><?php echo __('FIAT Value', 'cryptapi'); ?></strong></th>
     1065                            <th><strong><?php echo esc_attr( __( 'Time', 'cryptapi' ) ); ?></strong></th>
     1066                            <th><strong><?php echo esc_attr( __( 'Value Paid', 'cryptapi' ) ); ?></strong></th>
     1067                            <th><strong><?php echo esc_attr( __( 'FIAT Value', 'cryptapi' ) ); ?></strong></th>
    10711068                        </tr>
    10721069                    </table>
    10731070                </div>
    1074                 <?php
    1075                 if ($total > 0) {
    1076                     ?>
     1071                <?php
     1072                if ( $total > 0 ) {
     1073                    ?>
    10771074                    <div class="ca_progress">
    10781075                        <div class="ca_progress_icon waiting_payment done">
     
    10811078                                      fill="#0B4B70"/>
    10821079                            </svg>
    1083                             <p><?php echo __('Waiting for payment', 'cryptapi'); ?></p>
     1080                            <p><?php echo esc_attr( __( 'Waiting for payment', 'cryptapi' ) ); ?></p>
    10841081                        </div>
    10851082                        <div class="ca_progress_icon waiting_network">
     
    10881085                                      fill="#0B4B70"/>
    10891086                            </svg>
    1090                             <p><?php echo __('Waiting for network confirmation', 'cryptapi'); ?></p>
     1087                            <p><?php echo esc_attr( __( 'Waiting for network confirmation', 'cryptapi' ) ); ?></p>
    10911088                        </div>
    10921089                        <div class="ca_progress_icon payment_done">
     
    10951092                                      fill="#0B4B70"/>
    10961093                            </svg>
    1097                             <p><?php echo __('Payment confirmed', 'cryptapi'); ?></p>
     1094                            <p><?php echo esc_attr( __( 'Payment confirmed', 'cryptapi' ) ); ?></p>
    10981095                        </div>
    10991096                    </div>
    1100                     <?php
    1101                 }
    1102                 ?>
     1097                    <?php
     1098                }
     1099                ?>
    11031100            </div>
    11041101        </div>
    1105         <?php
    1106     }
    1107 
    1108     /**
    1109      *  Cronjob
    1110      */
    1111     function ca_cronjob()
    1112     {
    1113         $order_timeout = intval($this->order_cancelation_timeout);
    1114         $value_refresh = intval($this->refresh_value_interval);
    1115 
    1116         if ($order_timeout === 0 && $value_refresh === 0) {
    1117             return;
    1118         }
    1119 
    1120         $orders = wc_get_orders(array(
    1121             'status' => array('wc-on-hold'),
    1122             'payment_method' => 'cryptapi',
    1123         ));
    1124 
    1125         if (empty($orders)) {
    1126             return;
    1127         }
    1128 
    1129         $woocommerce_currency = get_woocommerce_currency();
    1130 
    1131         foreach ($orders as $order) {
    1132             $last_price_update = $order->get_meta('cryptapi_last_price_update');
    1133 
    1134             $history = json_decode($order->get_meta('cryptapi_history'), true);
    1135 
    1136             $min_tx = floatval($order->get_meta('cryptapi_min'));
    1137 
    1138             $calc = $this->calc_order($history, $order->get_meta('cryptapi_total'), $order->get_meta('cryptapi_total_fiat'));
    1139 
    1140             $remaining = $calc['remaining'];
    1141             $remaining_pending = $calc['remaining_pending'];
    1142             $already_paid = $calc['already_paid'];
    1143 
    1144             $order_timestamp = $order->get_date_created()->getTimestamp();
    1145 
    1146             if ((int)$order->get_meta('cryptapi_cancelled') === 0 && ($order_timestamp + 86400) > time()) {
    1147                 $this->validate_logs($order, $history);
    1148             }
    1149 
    1150             if ($value_refresh !== 0 && ((int)$last_price_update + (int)$value_refresh < time()) && !empty($last_price_update)) {
    1151                 if ($remaining === $remaining_pending && $remaining_pending > 0) {
    1152                     $cryptapi_coin = $order->get_meta('cryptapi_currency');
    1153 
    1154                     $crypto_total = CryptAPI\Helper::sig_fig(CryptAPI\Helper::get_conversion($woocommerce_currency, $cryptapi_coin, $order->get_total('edit'), $this->disable_conversion), 6);
    1155                     $order->update_meta_data('cryptapi_total', $crypto_total);
    1156 
    1157                     $calc_cron = $this->calc_order($history, $order->get_meta('cryptapi_total'), $order->get_meta('cryptapi_total_fiat'));
    1158                     $crypto_remaining_total = $calc_cron['remaining_pending'];
    1159 
    1160                     if ($remaining_pending <= $min_tx && !$remaining_pending <= 0) {
    1161                         $qr_code_data_value = CryptAPI\Helper::get_static_qrcode($order->get_meta('cryptapi_address'), $cryptapi_coin, $min_tx, $this->qrcode_size);
    1162                     } else {
    1163                         $qr_code_data_value = CryptAPI\Helper::get_static_qrcode($order->get_meta('cryptapi_address'), $cryptapi_coin, $crypto_remaining_total, $this->qrcode_size);
    1164                     }
    1165 
    1166                     $order->update_meta_data('cryptapi_qr_code_value', $qr_code_data_value['qr_code']);
    1167                 }
    1168 
    1169                 $order->update_meta_data('cryptapi_last_price_update', time());
    1170                 $order->save();
    1171             }
    1172 
    1173             if ($order_timeout !== 0 && ($order_timestamp + $order_timeout) <= time() && $already_paid <= 0 && (int)$order->get_meta('cryptapi_cancelled') === 0) {
    1174                 $order->update_status('cancelled', __('Order cancelled due to lack of payment.', 'cryptapi'));
    1175                 $order->update_meta_data('cryptapi_cancelled', '1');
    1176                 $order->save();
    1177             }
    1178         }
    1179     }
    1180 
    1181     function calc_order($history, $total, $total_fiat)
    1182     {
    1183         $already_paid = 0;
    1184         $already_paid_fiat = 0;
    1185         $remaining = $total;
    1186         $remaining_pending = $total;
    1187         $remaining_fiat = $total_fiat;
    1188 
    1189         if (!empty($history)) {
    1190             foreach ($history as $uuid => $item) {
    1191                 if ((int)$item['pending'] === 0) {
    1192                     $remaining = bcsub(CryptAPI\Helper::sig_fig($remaining, 6), $item['value_paid'], 8);
    1193                 }
    1194 
    1195                 $remaining_pending = bcsub(CryptAPI\Helper::sig_fig($remaining_pending, 6), $item['value_paid'], 8);
    1196                 $remaining_fiat = bcsub(CryptAPI\Helper::sig_fig($remaining_fiat, 6), $item['value_paid_fiat'], 8);
    1197 
    1198                 $already_paid = bcadd(CryptAPI\Helper::sig_fig($already_paid, 6), $item['value_paid'], 8);
    1199                 $already_paid_fiat = bcadd(CryptAPI\Helper::sig_fig($already_paid_fiat, 6), $item['value_paid_fiat'], 8);
    1200             }
    1201         }
    1202 
    1203         return [
    1204             'already_paid' => floatval($already_paid),
    1205             'already_paid_fiat' => floatval($already_paid_fiat),
    1206             'remaining' => floatval($remaining),
    1207             'remaining_pending' => floatval($remaining_pending),
    1208             'remaining_fiat' => floatval($remaining_fiat)
    1209         ];
    1210     }
    1211 
    1212     /**
    1213      * WooCommerce Subscriptions Integration
    1214      */
    1215     function scheduled_subscription_mail($amount, $renewal_order)
    1216     {
    1217 
    1218         $order = $renewal_order;
    1219 
    1220         $costumer_id = get_post_meta($order->get_id(), '_customer_user', true);
    1221         $customer = new WC_Customer($costumer_id);
    1222 
    1223         if (empty($order->get_meta('cryptapi_paid'))) {
    1224             $mailer = WC()->mailer();
    1225 
    1226             $recipient = $customer->get_email();
    1227 
    1228             $subject = sprintf('[%s] %s', get_bloginfo('name'), __('Please renew your subscription', 'cryptapi'));
    1229             $headers = 'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>' . '\r\n';
    1230 
    1231             $content = wc_get_template_html('emails/renewal-email.php', array(
    1232                 'order' => $order,
    1233                 'email_heading' => get_bloginfo('name'),
    1234                 'sent_to_admin' => false,
    1235                 'plain_text' => false,
    1236                 'email' => $mailer
    1237             ), plugin_dir_path(dirname(__FILE__)), plugin_dir_path(dirname(__FILE__)));
    1238 
    1239             $mailer->send($recipient, $subject, $content, $headers);
    1240 
    1241             $order->add_meta_data('cryptapi_paid', '1');
    1242             $order->save_meta_data();
    1243         }
    1244     }
    1245 
    1246     private function generate_nonce($len = 32)
    1247     {
    1248         $data = str_split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
    1249 
    1250         $nonce = [];
    1251         for ($i = 0; $i < $len; $i++) {
    1252             $nonce[] = $data[mt_rand(0, sizeof($data) - 1)];
    1253         }
    1254 
    1255         return implode('', $nonce);
    1256     }
    1257 
    1258     public function generate_cryptocurrency_html($key, $data)
    1259     {
    1260         $field_key = $this->get_field_key($key);
    1261         $defaults = array(
    1262             'title' => '',
    1263             'disabled' => false,
    1264             'class' => '',
    1265             'css' => '',
    1266             'placeholder' => '',
    1267             'type' => 'text',
    1268             'desc_tip' => false,
    1269             'description' => '',
    1270             'custom_attributes' => array(),
    1271         );
    1272 
    1273         $data = wp_parse_args($data, $defaults);
    1274 
    1275         ob_start();
    1276 
    1277         $token = str_replace('_address', '', $key);
    1278         $token_option = $this->get_option('coins');
    1279         if (!empty($token_option)) {
    1280             $token_search = array_search($token, $token_option);
    1281         }
    1282 
    1283         if ($data['custom_attributes']['counter'] === 0) {
    1284             ?>
     1102        <?php
     1103    }
     1104
     1105    /**
     1106     *  Cronjob
     1107     */
     1108    function ca_cronjob() {
     1109        $order_timeout = intval( $this->order_cancelation_timeout );
     1110        $value_refresh = intval( $this->refresh_value_interval );
     1111
     1112        if ( $order_timeout === 0 && $value_refresh === 0 ) {
     1113            return;
     1114        }
     1115
     1116        $orders = wc_get_orders( array(
     1117            'status'         => array( 'wc-on-hold' ),
     1118            'payment_method' => 'cryptapi',
     1119        ) );
     1120
     1121        if ( empty( $orders ) ) {
     1122            return;
     1123        }
     1124
     1125        $woocommerce_currency = get_woocommerce_currency();
     1126
     1127        foreach ( $orders as $order ) {
     1128            $last_price_update = $order->get_meta( 'cryptapi_last_price_update' );
     1129
     1130            $history = json_decode( $order->get_meta( 'cryptapi_history' ), true );
     1131
     1132            $min_tx = floatval( $order->get_meta( 'cryptapi_min' ) );
     1133
     1134            $calc = $this->calc_order( $history, $order->get_meta( 'cryptapi_total' ), $order->get_meta( 'cryptapi_total_fiat' ) );
     1135
     1136            $remaining         = $calc['remaining'];
     1137            $remaining_pending = $calc['remaining_pending'];
     1138            $already_paid      = $calc['already_paid'];
     1139
     1140            $order_timestamp = $order->get_date_created()->getTimestamp();
     1141
     1142            if ( $value_refresh !== 0 && ( (int) $last_price_update + (int) $value_refresh < time() ) && ! empty( $last_price_update ) ) {
     1143                if ( $remaining === $remaining_pending && $remaining_pending > 0 ) {
     1144                    $cryptapi_coin = $order->get_meta( 'cryptapi_currency' );
     1145
     1146                    $crypto_total = CryptAPI\Helper::sig_fig( CryptAPI\Helper::get_conversion( $woocommerce_currency, $cryptapi_coin, $order->get_total( 'edit' ), $this->disable_conversion ), 6 );
     1147                    $order->update_meta_data( 'cryptapi_total', $crypto_total );
     1148
     1149                    $calc_cron              = $this->calc_order( $history, $order->get_meta( 'cryptapi_total' ), $order->get_meta( 'cryptapi_total_fiat' ) );
     1150                    $crypto_remaining_total = $calc_cron['remaining_pending'];
     1151
     1152                    if ( $remaining_pending <= $min_tx && ! $remaining_pending <= 0 ) {
     1153                        $qr_code_data_value = CryptAPI\Helper::get_static_qrcode( $order->get_meta( 'cryptapi_address' ), $cryptapi_coin, $min_tx, $this->qrcode_size );
     1154                    } else {
     1155                        $qr_code_data_value = CryptAPI\Helper::get_static_qrcode( $order->get_meta( 'cryptapi_address' ), $cryptapi_coin, $crypto_remaining_total, $this->qrcode_size );
     1156                    }
     1157
     1158                    $order->update_meta_data( 'cryptapi_qr_code_value', $qr_code_data_value['qr_code'] );
     1159                }
     1160
     1161                $order->update_meta_data( 'cryptapi_last_price_update', time() );
     1162                $order->save();
     1163            }
     1164
     1165            if ( $order_timeout !== 0 && ( $order_timestamp + $order_timeout ) <= time() && $already_paid <= 0 && (int) $order->get_meta( 'cryptapi_cancelled' ) === 0 ) {
     1166                $order->update_status( 'cancelled', __( 'Order cancelled due to lack of payment.', 'cryptapi' ) );
     1167                $order->update_meta_data( 'cryptapi_cancelled', '1' );
     1168                $order->save();
     1169            }
     1170        }
     1171    }
     1172
     1173    function calc_order( $history, $total, $total_fiat ) {
     1174        $already_paid      = 0;
     1175        $already_paid_fiat = 0;
     1176        $remaining         = $total;
     1177        $remaining_pending = $total;
     1178        $remaining_fiat    = $total_fiat;
     1179
     1180        if ( ! empty( $history ) ) {
     1181            foreach ( $history as $uuid => $item ) {
     1182                if ( (int) $item['pending'] === 0 ) {
     1183                    $remaining = bcsub( CryptAPI\Helper::sig_fig( $remaining, 6 ), $item['value_paid'], 8 );
     1184                }
     1185
     1186                $remaining_pending = bcsub( CryptAPI\Helper::sig_fig( $remaining_pending, 6 ), $item['value_paid'], 8 );
     1187                $remaining_fiat    = bcsub( CryptAPI\Helper::sig_fig( $remaining_fiat, 6 ), $item['value_paid_fiat'], 8 );
     1188
     1189                $already_paid      = bcadd( CryptAPI\Helper::sig_fig( $already_paid, 6 ), $item['value_paid'], 8 );
     1190                $already_paid_fiat = bcadd( CryptAPI\Helper::sig_fig( $already_paid_fiat, 6 ), $item['value_paid_fiat'], 8 );
     1191            }
     1192        }
     1193
     1194        return [
     1195            'already_paid'      => floatval( $already_paid ),
     1196            'already_paid_fiat' => floatval( $already_paid_fiat ),
     1197            'remaining'         => floatval( $remaining ),
     1198            'remaining_pending' => floatval( $remaining_pending ),
     1199            'remaining_fiat'    => floatval( $remaining_fiat )
     1200        ];
     1201    }
     1202
     1203    /**
     1204     * WooCommerce Subscriptions Integration
     1205     */
     1206    function scheduled_subscription_mail( $amount, $renewal_order ) {
     1207
     1208        $order = $renewal_order;
     1209
     1210        $costumer_id = get_post_meta( $order->get_id(), '_customer_user', true );
     1211        $customer    = new WC_Customer( $costumer_id );
     1212
     1213        if ( empty( $order->get_meta( 'cryptapi_paid' ) ) ) {
     1214            $mailer = WC()->mailer();
     1215
     1216            $recipient = $customer->get_email();
     1217
     1218            $subject = sprintf( '[%s] %s', get_bloginfo( 'name' ), __( 'Please renew your subscription', 'cryptapi' ) );
     1219            $headers = 'From: ' . get_bloginfo( 'name' ) . ' <' . get_option( 'admin_email' ) . '>' . '\r\n';
     1220
     1221            $content = wc_get_template_html( 'emails/renewal-email.php', array(
     1222                'order'         => $order,
     1223                'email_heading' => get_bloginfo( 'name' ),
     1224                'sent_to_admin' => false,
     1225                'plain_text'    => false,
     1226                'email'         => $mailer
     1227            ), plugin_dir_path( dirname( __FILE__ ) ), plugin_dir_path( dirname( __FILE__ ) ) );
     1228
     1229            $mailer->send( $recipient, $subject, $content, $headers );
     1230
     1231            $order->add_meta_data( 'cryptapi_paid', '1' );
     1232            $order->save_meta_data();
     1233        }
     1234    }
     1235
     1236    private function generate_nonce( $len = 32 ) {
     1237        $data = str_split( 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' );
     1238
     1239        $nonce = [];
     1240        for ( $i = 0; $i < $len; $i ++ ) {
     1241            $nonce[] = $data[ mt_rand( 0, sizeof( $data ) - 1 ) ];
     1242        }
     1243
     1244        return implode( '', $nonce );
     1245    }
     1246
     1247    public function generate_cryptocurrency_html( $key, $data ) {
     1248        $field_key = $this->get_field_key( $key );
     1249        $defaults  = array(
     1250            'title'             => '',
     1251            'disabled'          => false,
     1252            'class'             => '',
     1253            'css'               => '',
     1254            'placeholder'       => '',
     1255            'type'              => 'text',
     1256            'desc_tip'          => false,
     1257            'description'       => '',
     1258            'custom_attributes' => array(),
     1259        );
     1260
     1261        $data = wp_parse_args( $data, $defaults );
     1262
     1263        ob_start();
     1264
     1265        $token        = str_replace( '_address', '', $key );
     1266        $token_option = $this->get_option( 'coins' );
     1267        if ( ! empty( $token_option ) ) {
     1268            $token_search = array_search( $token, $token_option );
     1269        }
     1270
     1271        if ( $data['custom_attributes']['counter'] === 0 ) {
     1272            ?>
    12851273            <tr valign="top">
    12861274                <th scope="row" class="titledesc"></th>
    1287                 <td class="forminp forminp-<?php echo esc_attr($data['type']) ?>">
     1275                <td class="forminp forminp-<?php echo esc_attr( $data['type'] ) ?>">
    12881276                    <p>
    12891277                        <strong>
    1290                             <?php echo __('Addresses', 'cryptapi'); ?>
     1278                            <?php echo esc_attr( __( 'Addresses', 'cryptapi' ) ); ?>
    12911279                        </strong><br/>
    1292                         <?php echo sprintf(__('If you are using BlockBee you can choose if setting the receiving addresses here bellow or in your BlockBee settings page. %1$s - In order to set the addresses on plugin settings, you need to select “Address Override” while creating the API key. %1$s - In order to set the addresses on BlockBee settings, you need to NOT select “Address Override” while creating the API key.', 'cryptapi'), '<br/>'); ?>
     1280                        <?php echo sprintf( esc_attr( __( 'If you are using BlockBee you can choose if setting the receiving addresses here bellow or in your BlockBee settings page. %1$s - In order to set the addresses on plugin settings, you need to select “Address Override” while creating the API key. %1$s - In order to set the addresses on BlockBee settings, you need to NOT select “Address Override” while creating the API key.', 'cryptapi' ) ), '<br/>' ); ?>
    12931281                    </p>
    12941282                </td>
    12951283            </tr>
    1296             <?php
    1297         }
    1298         ?>
     1284            <?php
     1285        }
     1286        ?>
    12991287        <tr valign="top">
    13001288
    13011289            <th scope="row" class="titledesc">
    13021290                <input style="display: inline-block; margin-bottom: -4px;" type="checkbox"
    1303                        name="coins[]" id="<?php echo esc_attr('coins_' . $token); ?>"
    1304                        value="<?php echo str_replace('_address', '', $key); ?>"
    1305                     <?php if (!empty($token_option) && $this->get_option('coins')[$token_search] === $token) {
    1306                         echo 'checked="true" ';
    1307                     } ?> />
    1308                 <label style="display: inline-block; width: 80%;" for="<?php echo esc_attr('coins_' . $token); ?>">
    1309                     <?php echo esc_html($data['title']); ?>
    1310                     <span class="woocommerce-help-tip" data-tip="<?php echo esc_html($data['description']); ?>"></span>
     1291                       name="coins[]" id="<?php echo esc_attr( 'coins_' . $token ); ?>"
     1292                       value="<?php echo str_replace( '_address', '', $key ); ?>"
     1293                    <?php if ( ! empty( $token_option ) && $this->get_option( 'coins' )[ $token_search ] === $token ) {
     1294                        echo 'checked="true" ';
     1295                    } ?> />
     1296                <label style="display: inline-block; width: 80%;" for="<?php echo esc_attr( 'coins_' . $token ); ?>">
     1297                    <?php echo esc_html( $data['title'] ); ?>
     1298                    <span class="woocommerce-help-tip" data-tip="<?php echo esc_html( $data['description'] ); ?>"></span>
    13111299                </label>
    13121300            </th>
    1313             <td class="forminp forminp-<?php echo esc_attr($data['type']) ?>">
    1314                 <input class="input-text regular-input <?php echo esc_attr($data['class']); ?>" type="text" name="<?php echo esc_attr($field_key); ?>"
    1315                        id="<?php echo esc_attr($field_key); ?>" style="<?php echo esc_attr($data['css']); ?>"
    1316                        value="<?php echo $this->get_option($key); ?>"
    1317                        placeholder="<?php echo esc_attr($data['placeholder']); ?>" <?php disabled($data['disabled'], true); ?> <?php echo $this->get_custom_attribute_html($data); // WPCS: XSS ok.
    1318                 ?> />
     1301            <td class="forminp forminp-<?php echo esc_attr( $data['type'] ) ?>">
     1302                <input class="input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field_key ); ?>"
     1303                       id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>"
     1304                       value="<?php echo $this->get_option( $key ); ?>"
     1305                       placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok.
     1306                ?> />
    13191307            </td>
    13201308        </tr>
    13211309
    1322         <?php
    1323         return ob_get_clean();
    1324     }
    1325 
    1326     function handling_fee()
    1327     {
    1328         if (is_admin() && !defined('DOING_AJAX')) {
    1329             return;
    1330         }
    1331 
    1332         $chosen_payment_id = WC()->session->get('chosen_payment_method');
    1333 
    1334         if ($chosen_payment_id != 'cryptapi') {
    1335             return;
    1336         }
    1337 
    1338         $total_fee = $this->get_option('fee_order_percentage') == 'none' ? 0 : $this->get_option('fee_order_percentage');
    1339 
    1340         $fee_order = WC()->cart->subtotal * $total_fee;
    1341 
    1342         if ($total_fee !== 'none' || $this->add_blockchain_fee) {
    1343 
    1344             $selected = WC()->session->get('cryptapi_coin');
    1345 
    1346             if ($selected === 'none') {
    1347                 return;
    1348             }
    1349 
    1350             if (!empty($selected) && $selected != 'none' && $this->add_blockchain_fee) {
    1351                 $est = CryptAPI\Helper::get_estimate($selected);
    1352 
    1353                 $fee_order += (float)$est->{get_woocommerce_currency()};
    1354             }
    1355 
    1356             if (empty($fee_order)) {
    1357                 return;
    1358             }
    1359 
    1360             WC()->cart->add_fee(__('Service Fee', 'cryptapi'), $fee_order, true);
    1361         }
    1362     }
    1363 
    1364     function refresh_checkout()
    1365     {
    1366         if (WC_CryptAPI_Gateway::$HAS_TRIGGERED) {
    1367             return;
    1368         }
    1369         WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
    1370         if (is_checkout()) {
    1371             wp_register_script('cryptapi-checkout', '');
    1372             wp_enqueue_script('cryptapi-checkout');
    1373             wp_add_inline_script('cryptapi-checkout', "jQuery(function ($) { $('form.checkout').on('change', 'input[name=payment_method], #payment_cryptapi_coin', function () { $(document.body).trigger('update_checkout');});});");
    1374         }
    1375     }
    1376 
    1377     function chosen_currency_value_to_wc_session($posted_data)
    1378     {
    1379         parse_str($posted_data, $fields);
    1380 
    1381         if (isset($fields['cryptapi_coin'])) {
    1382             WC()->session->set('cryptapi_coin', $fields['cryptapi_coin']);
    1383         }
    1384     }
    1385 
    1386     public function process_admin_options()
    1387     {
    1388         parent::update_option('coins', $_POST['coins']);
    1389         parent::process_admin_options();
    1390     }
    1391 
    1392     function add_email_link($order, $sent_to_admin, $plain_text, $email)
    1393     {
    1394         if (WC_CryptAPI_Gateway::$HAS_TRIGGERED) {
    1395             return;
    1396         }
    1397 
    1398         if ($email->id == 'customer_on_hold_order') {
    1399             WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
    1400             echo '<a style="display:block;text-align:center;margin: 40px auto; font-size: 16px; font-weight: bold;" href="' . $this->get_return_url($order) . '" target="_blank">' . __('Check your payment status', 'cryptapi') . '</a>';
    1401         }
    1402     }
    1403 
    1404     function add_order_link($actions, $order)
    1405     {
    1406         if ($order->has_status('on-hold')) {
    1407             $action_slug = 'ca_payment_url';
    1408 
    1409             $actions[$action_slug] = array(
    1410                 'url' => $this->get_return_url($order),
    1411                 'name' => __('Pay', 'cryptapi'),
    1412             );
    1413         }
    1414         return $actions;
    1415     }
    1416 
    1417     function get_private_order_notes($order_id)
    1418     {
    1419         global $wpdb;
    1420 
    1421         $table_perfixed = $wpdb->prefix . 'comments';
    1422         $results = $wpdb->get_results("
     1310        <?php
     1311        return ob_get_clean();
     1312    }
     1313
     1314    function handling_fee() {
     1315        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
     1316            return;
     1317        }
     1318
     1319        $chosen_payment_id = WC()->session->get( 'chosen_payment_method' );
     1320
     1321        if ( $chosen_payment_id != 'cryptapi' ) {
     1322            return;
     1323        }
     1324
     1325        $total_fee = $this->get_option( 'fee_order_percentage' ) == 'none' ? 0 : $this->get_option( 'fee_order_percentage' );
     1326
     1327        $fee_order = WC()->cart->subtotal * $total_fee;
     1328
     1329        if ( $total_fee !== 'none' || $this->add_blockchain_fee ) {
     1330
     1331            $selected = WC()->session->get( 'cryptapi_coin' );
     1332
     1333            if ( $selected === 'none' ) {
     1334                return;
     1335            }
     1336
     1337            if ( ! empty( $selected ) && $selected != 'none' && $this->add_blockchain_fee ) {
     1338                $est = CryptAPI\Helper::get_estimate( $selected );
     1339
     1340                $fee_order += (float) $est->{get_woocommerce_currency()};
     1341            }
     1342
     1343            if ( empty( $fee_order ) ) {
     1344                return;
     1345            }
     1346
     1347            WC()->cart->add_fee( __( 'Service Fee', 'cryptapi' ), $fee_order, true );
     1348        }
     1349    }
     1350
     1351    function refresh_checkout() {
     1352        if ( WC_CryptAPI_Gateway::$HAS_TRIGGERED ) {
     1353            return;
     1354        }
     1355        WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
     1356        if ( is_checkout() ) {
     1357            wp_register_script( 'cryptapi-checkout', '' );
     1358            wp_enqueue_script( 'cryptapi-checkout' );
     1359            wp_add_inline_script( 'cryptapi-checkout', "jQuery(function ($) { $('form.checkout').on('change', 'input[name=payment_method], #payment_cryptapi_coin', function () { $(document.body).trigger('update_checkout');});});" );
     1360        }
     1361    }
     1362
     1363    function chosen_currency_value_to_wc_session( $posted_data ) {
     1364        parse_str( $posted_data, $fields );
     1365
     1366        if ( isset( $fields['cryptapi_coin'] ) ) {
     1367            WC()->session->set( 'cryptapi_coin', $fields['cryptapi_coin'] );
     1368        }
     1369    }
     1370
     1371    public function process_admin_options() {
     1372        parent::update_option( 'coins', $_POST['coins'] );
     1373        parent::process_admin_options();
     1374    }
     1375
     1376    function add_email_link( $order, $sent_to_admin, $plain_text, $email ) {
     1377        if ( WC_CryptAPI_Gateway::$HAS_TRIGGERED ) {
     1378            return;
     1379        }
     1380
     1381        if ( $email->id == 'customer_on_hold_order' ) {
     1382            WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
     1383            echo '<a style="display:block;text-align:center;margin: 40px auto; font-size: 16px; font-weight: bold;" href="' . esc_url( $this->get_return_url( $order ) ) . '" target="_blank">' . __( 'Check your payment status', 'cryptapi' ) . '</a>';
     1384        }
     1385    }
     1386
     1387    function add_order_link( $actions, $order ) {
     1388        if ( $order->has_status( 'on-hold' ) ) {
     1389            $action_slug = 'ca_payment_url';
     1390
     1391            $actions[ $action_slug ] = array(
     1392                'url'  => $this->get_return_url( $order ),
     1393                'name' => __( 'Pay', 'cryptapi' ),
     1394            );
     1395        }
     1396
     1397        return $actions;
     1398    }
     1399
     1400    function get_private_order_notes( $order_id ) {
     1401        global $wpdb;
     1402
     1403        $table_perfixed = $wpdb->prefix . 'comments';
     1404        $results        = $wpdb->get_results( "
    14231405        SELECT *
    14241406        FROM $table_perfixed
    14251407        WHERE  `comment_post_ID` = $order_id
    14261408        AND  `comment_type` LIKE  'order_note'
    1427     ");
    1428 
    1429         foreach ($results as $note) {
    1430             $order_note[] = array(
    1431                 'note_id' => $note->comment_ID,
    1432                 'note_date' => $note->comment_date,
    1433                 'note_author' => $note->comment_author,
    1434                 'note_content' => $note->comment_content,
    1435             );
     1409    " );
     1410
     1411        foreach ( $results as $note ) {
     1412            $order_note[] = array(
     1413                'note_id'      => $note->comment_ID,
     1414                'note_date'    => $note->comment_date,
     1415                'note_author'  => $note->comment_author,
     1416                'note_content' => $note->comment_content,
     1417            );
     1418        }
     1419
     1420        return $order_note;
     1421    }
     1422
     1423    function order_detail_validate_logs($order) {
     1424        if ( WC_CryptAPI_Gateway::$HAS_TRIGGERED ) {
     1425            return;
     1426        }
     1427
     1428        if($order->is_paid()) {
     1429            return;
    14361430        }
    1437         return $order_note;
    1438     }
     1431
     1432        $ajax_url = add_query_arg( array(
     1433            'action' => 'cryptapi_validate_logs',
     1434            'order_id' => $order->get_ID(),
     1435        ), home_url( '/wp-admin/admin-ajax.php' ) );
     1436        ?>
     1437       <p class="form-field form-field-wide wc-customer-user">
     1438           <small style="display: block;">
     1439               <?php echo sprintf(esc_attr( __( 'If the order is not being updated, your ISP is probably blocking our IPs (%1$s and %2$s): please try to get them whitelisted and feel free to contact us anytime to get support (link to our contact page). In the meantime you can refresh the status of any payment by clicking this button below:', 'cryptapi' ) ), '145.239.119.223', '135.125.112.47'); ?>
     1440           </small>
     1441       </p>
     1442        <a style="margin-top: 1rem;margin-bottom: 1rem;" id="validate_callbacks" class="button action" href="#">
     1443            <?php echo esc_attr( __( 'Check for Callbacks', 'cryptapi' ) ); ?>
     1444        </a>
     1445        <script>
     1446            jQuery(function () {
     1447                const validate_button = jQuery('#validate_callbacks');
     1448
     1449                validate_button.on('click', function (e) {
     1450                    e.preventDefault();
     1451                    validate_callbacks();
     1452                    validate_button.html('<?php echo esc_attr( __( 'Checking', 'cryptapi' ) );?>');
     1453                })
     1454
     1455                function validate_callbacks() {
     1456                    jQuery.getJSON('<?php echo $ajax_url?>').always(function () {
     1457                        window.location.reload();
     1458                    })
     1459                }
     1460            })
     1461        </script>
     1462        <?php
     1463        WC_CryptAPI_Gateway::$HAS_TRIGGERED = true;
     1464    }
    14391465}
  • cryptapi-payment-gateway-for-woocommerce/trunk/define.php

    r2791382 r2797338  
    11<?php
    22
    3 define('CRYPTAPI_PLUGIN_VERSION', '4.6.4');
     3define('CRYPTAPI_PLUGIN_VERSION', '4.6.5');
    44define('CRYPTAPI_PLUGIN_PATH', plugin_dir_path(__FILE__));
    55define('CRYPTAPI_PLUGIN_URL', plugin_dir_url(__FILE__));
  • cryptapi-payment-gateway-for-woocommerce/trunk/readme.txt

    r2791382 r2797338  
    44Requires at least: 5
    55Tested up to: 6.0.2
    6 Stable tag: 4.6.4
     6Stable tag: 4.6.5
    77Requires PHP: 7.2
    88WC requires at least: 5.8
     
    296296* Minor fixes
    297297
     298= 4.6.5 =
     299* Added option to check for failed callbacks
     300* Minor fixes
     301
    298302== Upgrade Notice ==
    299303
Note: See TracChangeset for help on using the changeset viewer.