Changeset 2797338
- Timestamp:
- 10/11/2022 03:54:40 PM (3 years ago)
- Location:
- cryptapi-payment-gateway-for-woocommerce
- Files:
-
- 10 edited
- 1 copied
-
tags/4.6.5 (copied) (copied from cryptapi-payment-gateway-for-woocommerce/trunk)
-
tags/4.6.5/CryptAPI.php (modified) (1 diff)
-
tags/4.6.5/README.md (modified) (1 diff)
-
tags/4.6.5/controllers/CryptAPI.php (modified) (9 diffs)
-
tags/4.6.5/define.php (modified) (1 diff)
-
tags/4.6.5/readme.txt (modified) (2 diffs)
-
trunk/CryptAPI.php (modified) (1 diff)
-
trunk/README.md (modified) (1 diff)
-
trunk/controllers/CryptAPI.php (modified) (9 diffs)
-
trunk/define.php (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/CryptAPI.php
r2791382 r2797338 4 4 Plugin URI: https://github.com/cryptapi/woocommerce-cryptapi 5 5 Description: Accept cryptocurrency payments on your WooCommerce website 6 Version: 4.6. 46 Version: 4.6.5 7 7 Requires at least: 5 8 8 Tested up to: 6.0.2 -
cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/README.md
r2791382 r2797338 286 286 * Minor fixes 287 287 288 #### 4.6.5 289 * Added option to check for failed callbacks 290 * Minor fixes 291 288 292 ### Upgrade Notice 289 293 #### 4.3 -
cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/controllers/CryptAPI.php
r2791382 r2797338 3 3 use Cryptapi\Helper; 4 4 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 ?> 5 class 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 ?> 83 84 <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" ); ?> 85 86 </div> 86 87 <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" ) ?> 88 89 </div> 89 90 <div style="margin-top: 1.5rem"> … … 165 166 </a> 166 167 </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() { ?> 406 402 <div class="form-row form-row-wide"> 407 <p><?php echo $this->description; ?></p>403 <p><?php echo esc_attr( $this->description ); ?></p> 408 404 <ul style="margin-top: 7px; list-style: none outside;"> 409 <?php410 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 ?> 413 409 <li> 414 410 <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 <?php417 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; ?>" <?php422 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 <?php428 }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 ?> 431 427 </select> 432 428 </li> 433 <?php434 } ?>429 <?php 430 } ?> 435 431 </ul> 436 432 </div> 437 <?php438 if ($this->show_crypto_logos) {439 ?>433 <?php 434 if ( $this->show_crypto_logos ) { 435 ?> 440 436 <script> 441 437 if (typeof jQuery.fn.selectWoo !== 'undefined') { … … 458 454 } 459 455 </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 } 461 703 } 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 ) ?>"> 856 853 <div class="ca_payment_details"> 857 <?php858 if ($total > 0) {859 ?>854 <?php 855 if ( $total > 0 ) { 856 ?> 860 857 <div class="ca_payments_wrapper"> 861 858 <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 <?php869 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 ?> 871 868 <div class="inner-wrapper"> 872 869 <figure> 873 <?php874 if ($qr_code_setting != 'hide_ammount') {875 ?>870 <?php 871 if ( $qr_code_setting != 'hide_ammount' ) { 872 ?> 876 873 <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 <?php882 }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 ?> 885 882 <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 <?php892 }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 ?> 894 891 </figure> 895 <?php896 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 ?> 898 895 <div class="ca_qrcode_buttons"> 899 <?php900 if ($qr_code_setting != 'hide_without_ammount') {901 ?>902 <button class="ca_qrcode_btn no_value <?php903 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' ) ); ?> 908 905 </button> 909 <?php910 }911 if ($qr_code_setting != 'hide_ammount') {912 ?>906 <?php 907 } 908 if ( $qr_code_setting != 'hide_ammount' ) { 909 ?> 913 910 <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' ) ); ?> 919 916 </button> 920 917 </div> 921 <?php922 }923 }924 ?>918 <?php 919 } 920 } 921 ?> 925 922 </div> 926 <?php927 } else {928 ?>923 <?php 924 } else { 925 ?> 929 926 <div class="inner-wrapper"> 930 927 <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' ) ); ?>"/> 933 930 </figure> 934 931 <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' ) ); ?> 937 934 </button> 938 935 </div> 939 936 </div> 940 937 941 <?php942 }943 ?>938 <?php 939 } 940 ?> 944 941 </div> 945 942 <div class="ca_details_box"> 946 943 <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> 953 950 </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> 955 952 </div> 956 953 <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 ); ?> 960 957 </div> 961 958 <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 ); ?> 966 963 </div> 967 <?php968 if (intval($this->refresh_value_interval) != 0) {969 ?>964 <?php 965 if ( intval( $this->refresh_value_interval ) != 0 ) { 966 ?> 970 967 <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> 976 973 </div> 977 <?php978 }979 ?>974 <?php 975 } 976 ?> 980 977 <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> 985 982 </button> 986 983 <div class="ca_loader"></div> 987 984 </div> 988 985 </div> 989 <?php990 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>' ); ?> 994 991 </span> 995 <?php996 }997 ?>992 <?php 993 } 994 ?> 998 995 <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 <?php1001 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"; 1003 1000 } 1004 ?>"><?php echo __( 'Open QR CODE', 'cryptapi'); ?></span>1005 <span class="ca_show_qr_close <?php1006 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> 1010 1007 </a> 1011 1008 </div> 1012 <?php1013 if ($this->show_branding) {1014 ?>1009 <?php 1010 if ( $this->show_branding ) { 1011 ?> 1015 1012 <div class="ca_branding"> 1016 1013 <a href="https://cryptapi.io/" target="_blank"> 1017 1014 <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"/> 1019 1016 </a> 1020 1017 </div> 1021 <?php1022 }1023 ?>1018 <?php 1019 } 1020 ?> 1024 1021 </div> 1025 <?php1026 }1027 if ($total == 0) {1028 ?>1022 <?php 1023 } 1024 if ( $total == 0 ) { 1025 ?> 1029 1026 <style> 1030 1027 .ca_payment_confirmed { … … 1033 1030 } 1034 1031 </style> 1035 <?php1036 }1037 ?>1032 <?php 1033 } 1034 ?> 1038 1035 <div class="ca_payment_processing" style="display: none;"> 1039 1036 <div class="ca_payment_processing_icon"> 1040 1037 <div class="ca_loader_payment_processing"></div> 1041 1038 </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> 1044 1041 </div> 1045 1042 … … 1051 1048 </svg> 1052 1049 </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> 1054 1051 </div> 1055 1052 … … 1061 1058 </svg> 1062 1059 </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> 1064 1061 </div> 1065 1062 <div class="ca_history" style="display: none;"> 1066 1063 <table class="ca_history_fill"> 1067 1064 <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> 1071 1068 </tr> 1072 1069 </table> 1073 1070 </div> 1074 <?php1075 if ($total > 0) {1076 ?>1071 <?php 1072 if ( $total > 0 ) { 1073 ?> 1077 1074 <div class="ca_progress"> 1078 1075 <div class="ca_progress_icon waiting_payment done"> … … 1081 1078 fill="#0B4B70"/> 1082 1079 </svg> 1083 <p><?php echo __('Waiting for payment', 'cryptapi'); ?></p>1080 <p><?php echo esc_attr( __( 'Waiting for payment', 'cryptapi' ) ); ?></p> 1084 1081 </div> 1085 1082 <div class="ca_progress_icon waiting_network"> … … 1088 1085 fill="#0B4B70"/> 1089 1086 </svg> 1090 <p><?php echo __('Waiting for network confirmation', 'cryptapi'); ?></p>1087 <p><?php echo esc_attr( __( 'Waiting for network confirmation', 'cryptapi' ) ); ?></p> 1091 1088 </div> 1092 1089 <div class="ca_progress_icon payment_done"> … … 1095 1092 fill="#0B4B70"/> 1096 1093 </svg> 1097 <p><?php echo __('Payment confirmed', 'cryptapi'); ?></p>1094 <p><?php echo esc_attr( __( 'Payment confirmed', 'cryptapi' ) ); ?></p> 1098 1095 </div> 1099 1096 </div> 1100 <?php1101 }1102 ?>1097 <?php 1098 } 1099 ?> 1103 1100 </div> 1104 1101 </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 ?> 1285 1273 <tr valign="top"> 1286 1274 <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'] ) ?>"> 1288 1276 <p> 1289 1277 <strong> 1290 <?php echo __('Addresses', 'cryptapi'); ?>1278 <?php echo esc_attr( __( 'Addresses', 'cryptapi' ) ); ?> 1291 1279 </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/>' ); ?> 1293 1281 </p> 1294 1282 </td> 1295 1283 </tr> 1296 <?php1297 }1298 ?>1284 <?php 1285 } 1286 ?> 1299 1287 <tr valign="top"> 1300 1288 1301 1289 <th scope="row" class="titledesc"> 1302 1290 <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> 1311 1299 </label> 1312 1300 </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 ?> /> 1319 1307 </td> 1320 1308 </tr> 1321 1309 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( " 1423 1405 SELECT * 1424 1406 FROM $table_perfixed 1425 1407 WHERE `comment_post_ID` = $order_id 1426 1408 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; 1436 1430 } 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 } 1439 1465 } -
cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/define.php
r2791382 r2797338 1 1 <?php 2 2 3 define('CRYPTAPI_PLUGIN_VERSION', '4.6. 4');3 define('CRYPTAPI_PLUGIN_VERSION', '4.6.5'); 4 4 define('CRYPTAPI_PLUGIN_PATH', plugin_dir_path(__FILE__)); 5 5 define('CRYPTAPI_PLUGIN_URL', plugin_dir_url(__FILE__)); -
cryptapi-payment-gateway-for-woocommerce/tags/4.6.5/readme.txt
r2791382 r2797338 4 4 Requires at least: 5 5 5 Tested up to: 6.0.2 6 Stable tag: 4.6. 46 Stable tag: 4.6.5 7 7 Requires PHP: 7.2 8 8 WC requires at least: 5.8 … … 296 296 * Minor fixes 297 297 298 = 4.6.5 = 299 * Added option to check for failed callbacks 300 * Minor fixes 301 298 302 == Upgrade Notice == 299 303 -
cryptapi-payment-gateway-for-woocommerce/trunk/CryptAPI.php
r2791382 r2797338 4 4 Plugin URI: https://github.com/cryptapi/woocommerce-cryptapi 5 5 Description: Accept cryptocurrency payments on your WooCommerce website 6 Version: 4.6. 46 Version: 4.6.5 7 7 Requires at least: 5 8 8 Tested up to: 6.0.2 -
cryptapi-payment-gateway-for-woocommerce/trunk/README.md
r2791382 r2797338 286 286 * Minor fixes 287 287 288 #### 4.6.5 289 * Added option to check for failed callbacks 290 * Minor fixes 291 288 292 ### Upgrade Notice 289 293 #### 4.3 -
cryptapi-payment-gateway-for-woocommerce/trunk/controllers/CryptAPI.php
r2791382 r2797338 3 3 use Cryptapi\Helper; 4 4 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 ?> 5 class 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 ?> 83 84 <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" ); ?> 85 86 </div> 86 87 <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" ) ?> 88 89 </div> 89 90 <div style="margin-top: 1.5rem"> … … 165 166 </a> 166 167 </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() { ?> 406 402 <div class="form-row form-row-wide"> 407 <p><?php echo $this->description; ?></p>403 <p><?php echo esc_attr( $this->description ); ?></p> 408 404 <ul style="margin-top: 7px; list-style: none outside;"> 409 <?php410 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 ?> 413 409 <li> 414 410 <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 <?php417 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; ?>" <?php422 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 <?php428 }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 ?> 431 427 </select> 432 428 </li> 433 <?php434 } ?>429 <?php 430 } ?> 435 431 </ul> 436 432 </div> 437 <?php438 if ($this->show_crypto_logos) {439 ?>433 <?php 434 if ( $this->show_crypto_logos ) { 435 ?> 440 436 <script> 441 437 if (typeof jQuery.fn.selectWoo !== 'undefined') { … … 458 454 } 459 455 </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 } 461 703 } 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 ) ?>"> 856 853 <div class="ca_payment_details"> 857 <?php858 if ($total > 0) {859 ?>854 <?php 855 if ( $total > 0 ) { 856 ?> 860 857 <div class="ca_payments_wrapper"> 861 858 <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 <?php869 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 ?> 871 868 <div class="inner-wrapper"> 872 869 <figure> 873 <?php874 if ($qr_code_setting != 'hide_ammount') {875 ?>870 <?php 871 if ( $qr_code_setting != 'hide_ammount' ) { 872 ?> 876 873 <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 <?php882 }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 ?> 885 882 <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 <?php892 }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 ?> 894 891 </figure> 895 <?php896 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 ?> 898 895 <div class="ca_qrcode_buttons"> 899 <?php900 if ($qr_code_setting != 'hide_without_ammount') {901 ?>902 <button class="ca_qrcode_btn no_value <?php903 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' ) ); ?> 908 905 </button> 909 <?php910 }911 if ($qr_code_setting != 'hide_ammount') {912 ?>906 <?php 907 } 908 if ( $qr_code_setting != 'hide_ammount' ) { 909 ?> 913 910 <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' ) ); ?> 919 916 </button> 920 917 </div> 921 <?php922 }923 }924 ?>918 <?php 919 } 920 } 921 ?> 925 922 </div> 926 <?php927 } else {928 ?>923 <?php 924 } else { 925 ?> 929 926 <div class="inner-wrapper"> 930 927 <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' ) ); ?>"/> 933 930 </figure> 934 931 <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' ) ); ?> 937 934 </button> 938 935 </div> 939 936 </div> 940 937 941 <?php942 }943 ?>938 <?php 939 } 940 ?> 944 941 </div> 945 942 <div class="ca_details_box"> 946 943 <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> 953 950 </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> 955 952 </div> 956 953 <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 ); ?> 960 957 </div> 961 958 <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 ); ?> 966 963 </div> 967 <?php968 if (intval($this->refresh_value_interval) != 0) {969 ?>964 <?php 965 if ( intval( $this->refresh_value_interval ) != 0 ) { 966 ?> 970 967 <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> 976 973 </div> 977 <?php978 }979 ?>974 <?php 975 } 976 ?> 980 977 <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> 985 982 </button> 986 983 <div class="ca_loader"></div> 987 984 </div> 988 985 </div> 989 <?php990 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>' ); ?> 994 991 </span> 995 <?php996 }997 ?>992 <?php 993 } 994 ?> 998 995 <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 <?php1001 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"; 1003 1000 } 1004 ?>"><?php echo __( 'Open QR CODE', 'cryptapi'); ?></span>1005 <span class="ca_show_qr_close <?php1006 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> 1010 1007 </a> 1011 1008 </div> 1012 <?php1013 if ($this->show_branding) {1014 ?>1009 <?php 1010 if ( $this->show_branding ) { 1011 ?> 1015 1012 <div class="ca_branding"> 1016 1013 <a href="https://cryptapi.io/" target="_blank"> 1017 1014 <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"/> 1019 1016 </a> 1020 1017 </div> 1021 <?php1022 }1023 ?>1018 <?php 1019 } 1020 ?> 1024 1021 </div> 1025 <?php1026 }1027 if ($total == 0) {1028 ?>1022 <?php 1023 } 1024 if ( $total == 0 ) { 1025 ?> 1029 1026 <style> 1030 1027 .ca_payment_confirmed { … … 1033 1030 } 1034 1031 </style> 1035 <?php1036 }1037 ?>1032 <?php 1033 } 1034 ?> 1038 1035 <div class="ca_payment_processing" style="display: none;"> 1039 1036 <div class="ca_payment_processing_icon"> 1040 1037 <div class="ca_loader_payment_processing"></div> 1041 1038 </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> 1044 1041 </div> 1045 1042 … … 1051 1048 </svg> 1052 1049 </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> 1054 1051 </div> 1055 1052 … … 1061 1058 </svg> 1062 1059 </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> 1064 1061 </div> 1065 1062 <div class="ca_history" style="display: none;"> 1066 1063 <table class="ca_history_fill"> 1067 1064 <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> 1071 1068 </tr> 1072 1069 </table> 1073 1070 </div> 1074 <?php1075 if ($total > 0) {1076 ?>1071 <?php 1072 if ( $total > 0 ) { 1073 ?> 1077 1074 <div class="ca_progress"> 1078 1075 <div class="ca_progress_icon waiting_payment done"> … … 1081 1078 fill="#0B4B70"/> 1082 1079 </svg> 1083 <p><?php echo __('Waiting for payment', 'cryptapi'); ?></p>1080 <p><?php echo esc_attr( __( 'Waiting for payment', 'cryptapi' ) ); ?></p> 1084 1081 </div> 1085 1082 <div class="ca_progress_icon waiting_network"> … … 1088 1085 fill="#0B4B70"/> 1089 1086 </svg> 1090 <p><?php echo __('Waiting for network confirmation', 'cryptapi'); ?></p>1087 <p><?php echo esc_attr( __( 'Waiting for network confirmation', 'cryptapi' ) ); ?></p> 1091 1088 </div> 1092 1089 <div class="ca_progress_icon payment_done"> … … 1095 1092 fill="#0B4B70"/> 1096 1093 </svg> 1097 <p><?php echo __('Payment confirmed', 'cryptapi'); ?></p>1094 <p><?php echo esc_attr( __( 'Payment confirmed', 'cryptapi' ) ); ?></p> 1098 1095 </div> 1099 1096 </div> 1100 <?php1101 }1102 ?>1097 <?php 1098 } 1099 ?> 1103 1100 </div> 1104 1101 </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 ?> 1285 1273 <tr valign="top"> 1286 1274 <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'] ) ?>"> 1288 1276 <p> 1289 1277 <strong> 1290 <?php echo __('Addresses', 'cryptapi'); ?>1278 <?php echo esc_attr( __( 'Addresses', 'cryptapi' ) ); ?> 1291 1279 </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/>' ); ?> 1293 1281 </p> 1294 1282 </td> 1295 1283 </tr> 1296 <?php1297 }1298 ?>1284 <?php 1285 } 1286 ?> 1299 1287 <tr valign="top"> 1300 1288 1301 1289 <th scope="row" class="titledesc"> 1302 1290 <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> 1311 1299 </label> 1312 1300 </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 ?> /> 1319 1307 </td> 1320 1308 </tr> 1321 1309 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( " 1423 1405 SELECT * 1424 1406 FROM $table_perfixed 1425 1407 WHERE `comment_post_ID` = $order_id 1426 1408 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; 1436 1430 } 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 } 1439 1465 } -
cryptapi-payment-gateway-for-woocommerce/trunk/define.php
r2791382 r2797338 1 1 <?php 2 2 3 define('CRYPTAPI_PLUGIN_VERSION', '4.6. 4');3 define('CRYPTAPI_PLUGIN_VERSION', '4.6.5'); 4 4 define('CRYPTAPI_PLUGIN_PATH', plugin_dir_path(__FILE__)); 5 5 define('CRYPTAPI_PLUGIN_URL', plugin_dir_url(__FILE__)); -
cryptapi-payment-gateway-for-woocommerce/trunk/readme.txt
r2791382 r2797338 4 4 Requires at least: 5 5 5 Tested up to: 6.0.2 6 Stable tag: 4.6. 46 Stable tag: 4.6.5 7 7 Requires PHP: 7.2 8 8 WC requires at least: 5.8 … … 296 296 * Minor fixes 297 297 298 = 4.6.5 = 299 * Added option to check for failed callbacks 300 * Minor fixes 301 298 302 == Upgrade Notice == 299 303
Note: See TracChangeset
for help on using the changeset viewer.