diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a681dcf --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +*.xml +*.iml diff --git a/monero/include/monero_payments.php b/monero/include/monero_payments.php index 60185cd..c8c362e 100644 --- a/monero/include/monero_payments.php +++ b/monero/include/monero_payments.php @@ -1,421 +1,407 @@ id = "monero_gateway"; - $this->method_title = __("Monero GateWay", 'monero_gateway'); - $this->method_description = __("Monero Payment Gateway Plug-in for WooCommerce. You can find more information about this payment gateway on our website. You'll need a daemon online for your address.", 'monero_gateway'); - $this->title = __("Monero Gateway", 'monero_gateway'); - $this->version = "0.2"; - // - $this->icon = apply_filters('woocommerce_offline_icon', ''); - $this->has_fields = false; - - $this->log = new WC_Logger(); - - $this->init_form_fields(); - $this->host = $this->get_option('daemon_host'); - $this->port = $this->get_option('daemon_port'); - $this->address = $this->get_option('monero_address'); - $this->username = $this->get_option('username'); - $this->password = $this->get_option('password'); - $this->discount = $this->get_option('discount'); - - // After init_settings() is called, you can get the settings and load them into variables, e.g: - // $this->title = $this->get_option('title' ); - $this->init_settings(); - - // Turn these settings into variables we can use - foreach ($this->settings as $setting_key => $value) { - $this->$setting_key = $value; - } - - add_action('admin_notices', array($this,'do_ssl_check')); - add_action('admin_notices', array($this,'validate_fields')); - add_action('woocommerce_thankyou_' . $this->id, array($this,'instruction')); - if (is_admin()) { - /* Save Settings */ - add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this,'process_admin_options' - )); - -add_filter( 'woocommerce_currencies', array($this,'add_my_currency') ); -add_filter('woocommerce_currency_symbol', 'add_my_currency_symbol', 10, 2); - add_action('woocommerce_email_before_order_table', array($this, 'email_instructions'), 10, 2); - - - - - } - $this->monero_daemon = new Monero_Library($this->host . ':' . $this->port . '/json_rpc', $this->username, $this->password); - } - - public function add_my_currency( $currencies ) { - $currencies['XMR'] = __('Monero','woocommerce'); - return $currencies; -} -public function add_my_currency_symbol( $currency_symbol, $currency ) { - switch( $currency ) { - case 'XMR': $currency_symbol = 'XMR'; break; - } - return $currency_symbol; -} - - - public function admin_options() - { - $this->log->add('Monero_gateway', '[SUCCESS] Monero Settings OK'); - - echo "

Monero Payment Gateway

"; - - echo "

Welcome to Monero Extension for WooCommerce. Getting started: Make a connection with daemon Contact Me"; - echo "

"; - $this->getamountinfo(); - echo "
"; - echo ""; - $this->generate_settings_html(); - echo "
"; - echo "

Learn more about using a password with the monero wallet-rpc here

"; - } - - - - public function init_form_fields() - { - $this->form_fields = array( - 'enabled' => array( - 'title' => __('Enable / Disable', 'monero_gateway'), - 'label' => __('Enable this payment gateway', 'monero_gateway'), - 'type' => 'checkbox', - 'default' => 'no' - ), - - 'title' => array( - 'title' => __('Title', 'monero_gateway'), - 'type' => 'text', - 'desc_tip' => __('Payment title the customer will see during the checkout process.', 'monero_gateway'), - 'default' => __('Monero XMR Payment', 'monero_gateway') - ), - 'description' => array( - 'title' => __('Description', 'monero_gateway'), - 'type' => 'textarea', - 'desc_tip' => __('Payment description the customer will see during the checkout process.', 'monero_gateway'), - 'default' => __('Pay securely using XMR.', 'monero_gateway') - - ), - 'monero_address' => array( - 'title' => __('Monero Address', 'monero_gateway'), - 'label' => __('Useful for people that have not a daemon online'), - 'type' => 'text', - 'desc_tip' => __('Monero Wallet Address', 'monero_gateway') - ), - 'daemon_host' => array( - 'title' => __('Daemon Host/ IP', 'monero_gateway'), - 'type' => 'text', - 'desc_tip' => __('This is the Daemon Host/IP to authorize the payment with port', 'monero_gateway'), - 'default' => 'localhost', - ), - 'daemon_port' => array( - 'title' => __('Daemon PORT', 'monero_gateway'), - 'type' => 'text', - 'desc_tip' => __('This is the Daemon Host/IP to authorize the payment with port', 'monero_gateway'), - 'default' => '18080', - ), - 'username' => array( - 'title' => __('Daemon username', 'monero_gateway'), - 'desc_tip' => __('This is the username that you used with your monero wallet-rpc', 'monero_gateway'), - 'type' => __('text'), - 'default' => __('username','monero_gateway'), - - ), - 'password' => array( - 'title' => __('Daemon password', 'monero_gateway'), - 'desc_tip' => __('This is the password that you used with your monero wallet-rpc', 'monero_gateway'), - 'description' => __('you can leave these fields empty if you did not set', 'monero_gateway'), - 'type' => __('text'), - 'default' => '' - - ), - 'discount' => array( - 'title' => __('% discount for using XMR', 'monero_gateway'), - - 'desc_tip' => __('Provide a discount to your customers for making a private payment with XMR!', 'monero_gateway'), - 'description' => __('Do you want to spread the word about Monero? Offer a small discount! Leave this empty if you do not wish to provide a discount', 'monero_gateway'), - 'type' => __('text'), - 'default' => '5%' - - ), - 'environment' => array( - 'title' => __(' Test Mode', 'monero_gateway'), - 'label' => __('Enable Test Mode', 'monero_gateway'), - 'type' => 'checkbox', - 'description' => __('Check this box if you are using testnet', 'monero_gateway'), - 'default' => 'no' - ), - ); - } - - - public function retriveprice($currency) - { - $xmr_price = file_get_contents('https://min-api.cryptocompare.com/data/price?fsym=XMR&tsyms=BTC,USD,EUR,CAD,INR,GBP&extraParams=monero_woocommerce'); - $price = json_decode($xmr_price, TRUE); - if(!isset($price)){ - $this->log->add('Monero_Gateway', '[ERROR] Unable to get the price of Monero'); - } - if ($currency == 'USD') { - return $price['USD']; - } - if ($currency == 'EUR') { - return $price['EUR']; - } - if ($currency == 'CAD'){ - return $price['CAD']; - } - if ($currency == 'GBP'){ - return $price['GBP']; - } - if ($currency == 'INR'){ - return $price['INR']; - } - if($currency == 'XMR'){ - $price = '1'; - return $price; - } - } - - public function changeto($amount, $currency, $payment_id) - { - global $wpdb; - // This will create a table named whatever the payment id is inside the database "WordPress" - $create_table = "CREATE TABLE IF NOT EXISTS $payment_id ( - rate INT - )"; - $wpdb->query($create_table); - $rows_num = $wpdb->get_results("SELECT count(*) as count FROM $payment_id"); - if($rows_num[0]->count > 0) // Checks if the row has already been created or not - { - $stored_rate = $wpdb->get_results("SELECT rate FROM $payment_id"); - - $stored_rate_transformed = $stored_rate[0]->rate / 100; //this will turn the stored rate back into a decimaled number - - if(isset($this->discount)) - { - $discount_decimal = $this->discount / 100; - $new_amount = $amount / $stored_rate_transformed; - $discount = $new_amount * $discount_decimal; - $final_amount = $new_amount - $discount; - $rounded_amount = round($final_amount, 12); - } - else{ - $new_amount = $amount / $stored_rate_transformed; - $rounded_amount = round($new_amount, 12); //the moneo wallet can't handle decimals smaller than 0.000000000001 - } - } - else // If the row has not been created then the live exchange rate will be grabbed and stored - { - $xmr_live_price = $this->retriveprice($currency); - $live_for_storing = $xmr_live_price * 100; //This will remove the decimal so that it can easily be stored as an integer - $new_amount = $amount / $xmr_live_price; - $rounded_amount = round($new_amount, 12); - - $wpdb->query("INSERT INTO $payment_id (rate) - VALUES ($live_for_storing)"); - } - - return $rounded_amount; - } - - // Submit payment and handle response - public function process_payment($order_id) - { - $order = wc_get_order($order_id); - $order->update_status('on-hold', __('Awaiting offline payment', 'monero_gateway')); - // Reduce stock levels - $order->reduce_order_stock(); - - // Remove cart - WC()->cart->empty_cart(); - - // Return thankyou redirect - return array( - 'result' => 'success', - 'redirect' => $this->get_return_url($order) - ); - - } - - - - // Validate fields - public function validate_fields() - { - if ($this->check_monero() != TRUE) { - echo "

Your Monero Address doesn't seem valid. Have you checked it?

"; - } - - } - - - public function check_monero() - { - $monero_address = $this->settings['monero_address']; - if (strlen($monero_address) == 95 && substr($monero_address, 1)) { - return true; - } - return false; - } - - private function set_paymentid_cookie() - { - if(!isset($_COOKIE['payment_id'])) - { - $payment_id = bin2hex(openssl_random_pseudo_bytes(8)); - setcookie('payment_id', $payment_id, time()+2700); - } - else - $payment_id = $_COOKIE['payment_id']; - return $payment_id; - } - public function instruction($order_id) - { - $order = wc_get_order($order_id); - $amount = floatval(preg_replace('#[^\d.]#', '', $order->get_total())); - $payment_id = $this->set_paymentid_cookie(); - $currency = $order->get_currency(); - $amount_xmr2 = $this->changeto($amount, $currency, $payment_id); - $address = $this->address; - if(!isset($address)){ - // If there isn't address (merchant missed that field!), $address will be the Monero address for donating :) - $address = "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A"; - } - $uri = "monero:$address?amount=$amount?payment_id=$payment_id"; - $array_integrated_address = $this->monero_daemon->make_integrated_address($payment_id); - if(!isset($array_integrated_address)){ - $this->log->add('Monero_Gateway', '[ERROR] Unable to getting integrated address'); - // Seems that we can't connect with daemon, then set array_integrated_address, little hack - $array_integrated_address["integrated_address"] = $address; - } - $message = $this->verify_payment($payment_id, $amount_xmr2, $order); - if($this->confirmed){ - $color = "006400"; - } - else{ - $color = "DC143C"; - } - echo "

".$message."

"; - echo ""; - - echo "
- -
-
-
-
-
-

Monero Payment Box

-
-
- -
-
- Send " . $amount_xmr2 . " XMR to
- or scan QR Code with your mobile device

- If you need help with how to pay with Monero or want to learn more about it, please go to the Monerosite. -
-
- - -
-
-
- -
-
+ private $reloadTime = 30000; + private $discount; + private $confirmed = false; + private $monero_daemon; + + function __construct() + { + $this->id = "monero_gateway"; + $this->method_title = __("Monero GateWay", 'monero_gateway'); + $this->method_description = __("Monero Payment Gateway Plug-in for WooCommerce. You can find more information about this payment gateway on our website. You'll need a daemon online for your address.", 'monero_gateway'); + $this->title = __("Monero Gateway", 'monero_gateway'); + $this->version = "0.21"; + // + $this->icon = apply_filters('woocommerce_offline_icon', ''); + $this->has_fields = false; + + $this->log = new WC_Logger(); + + $this->init_form_fields(); + $this->host = $this->get_option('daemon_host'); + $this->port = $this->get_option('daemon_port'); + $this->address = $this->get_option('monero_address'); + $this->username = $this->get_option('username'); + $this->password = $this->get_option('password'); + $this->discount = $this->get_option('discount'); + + // After init_settings() is called, you can get the settings and load them into variables, e.g: + // $this->title = $this->get_option('title' ); + $this->init_settings(); + + // Turn these settings into variables we can use + foreach ($this->settings as $setting_key => $value) { + $this->$setting_key = $value; + } + + add_action('admin_notices', array($this, 'do_ssl_check')); + add_action('admin_notices', array($this, 'validate_fields')); + add_action('woocommerce_thankyou_' . $this->id, array($this, 'instruction')); + if (is_admin()) { + /* Save Settings */ + add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options')); + add_filter('woocommerce_currencies', 'add_my_currency'); + add_filter('woocommerce_currency_symbol', 'add_my_currency_symbol', 10, 2); + add_action('woocommerce_email_before_order_table', array($this, 'email_instructions'), 10, 2); + } + $this->monero_daemon = new Monero_Library($this->host . ':' . $this->port . '/json_rpc', $this->username, $this->password); + } + + public function init_form_fields() + { + $this->form_fields = array( + 'enabled' => array( + 'title' => __('Enable / Disable', 'monero_gateway'), + 'label' => __('Enable this payment gateway', 'monero_gateway'), + 'type' => 'checkbox', + 'default' => 'no' + ), + + 'title' => array( + 'title' => __('Title', 'monero_gateway'), + 'type' => 'text', + 'desc_tip' => __('Payment title the customer will see during the checkout process.', 'monero_gateway'), + 'default' => __('Monero XMR Payment', 'monero_gateway') + ), + 'description' => array( + 'title' => __('Description', 'monero_gateway'), + 'type' => 'textarea', + 'desc_tip' => __('Payment description the customer will see during the checkout process.', 'monero_gateway'), + 'default' => __('Pay securely using XMR.', 'monero_gateway') + + ), + 'monero_address' => array( + 'title' => __('Monero Address', 'monero_gateway'), + 'label' => __('Useful for people that have not a daemon online'), + 'type' => 'text', + 'desc_tip' => __('Monero Wallet Address', 'monero_gateway') + ), + 'daemon_host' => array( + 'title' => __('Daemon Host/ IP', 'monero_gateway'), + 'type' => 'text', + 'desc_tip' => __('This is the Daemon Host/IP to authorize the payment with port', 'monero_gateway'), + 'default' => 'localhost', + ), + 'daemon_port' => array( + 'title' => __('Daemon PORT', 'monero_gateway'), + 'type' => 'text', + 'desc_tip' => __('This is the Daemon Host/IP to authorize the payment with port', 'monero_gateway'), + 'default' => '18080', + ), + 'username' => array( + 'title' => __('Daemon username', 'monero_gateway'), + 'desc_tip' => __('This is the username that you used with your monero wallet-rpc', 'monero_gateway'), + 'type' => __('text'), + 'default' => __('username', 'monero_gateway'), + + ), + 'password' => array( + 'title' => __('Daemon password', 'monero_gateway'), + 'desc_tip' => __('This is the password that you used with your monero wallet-rpc', 'monero_gateway'), + 'description' => __('you can leave these fields empty if you did not set', 'monero_gateway'), + 'type' => __('text'), + 'default' => '' + + ), + 'discount' => array( + 'title' => __('% discount for using XMR', 'monero_gateway'), + + 'desc_tip' => __('Provide a discount to your customers for making a private payment with XMR!', 'monero_gateway'), + 'description' => __('Do you want to spread the word about Monero? Offer a small discount! Leave this empty if you do not wish to provide a discount', 'monero_gateway'), + 'type' => __('text'), + 'default' => '5%' + + ), + 'environment' => array( + 'title' => __(' Test Mode', 'monero_gateway'), + 'label' => __('Enable Test Mode', 'monero_gateway'), + 'type' => 'checkbox', + 'description' => __('Check this box if you are using testnet', 'monero_gateway'), + 'default' => 'no' + ), + 'onion_service' => array( + 'title' => __(' Onion Service', 'monero_gateway'), + 'label' => __('Enable Onion Service', 'monero_gateway'), + 'type' => 'checkbox', + 'description' => __('Check this box if you are running on an Onion Service (Suppress SSL errors)', 'monero_gateway'), + 'default' => 'no' + ), + ); + } + + public function add_my_currency($currencies) + { + $currencies['XMR'] = __('Monero', 'woocommerce'); + return $currencies; + } + + function add_my_currency_symbol($currency_symbol, $currency) + { + switch ($currency) { + case 'XMR': + $currency_symbol = 'XMR'; + break; + } + return $currency_symbol; + } + + public function admin_options() + { + $this->log->add('Monero_gateway', '[SUCCESS] Monero Settings OK'); + + echo "

Monero Payment Gateway

"; + + echo "

Welcome to Monero Extension for WooCommerce. Getting started: Make a connection with daemon Contact Me"; + echo "

"; + $this->getamountinfo(); + echo "
"; + echo ""; + $this->generate_settings_html(); + echo "
"; + echo "

Learn more about using a password with the monero wallet-rpc here

"; + } + + public function getamountinfo() + { + $wallet_amount = $this->monero_daemon->getbalance(); + if (!isset($wallet_amount)) { + $this->log->add('Monero_gateway', '[ERROR] No connection with daemon'); + $wallet_amount['balance'] = "0"; + $wallet_amount['unlocked_balance'] = "0"; + } + $real_wallet_amount = $wallet_amount['balance'] / 1000000000000; + $real_amount_rounded = round($real_wallet_amount, 6); + + $unlocked_wallet_amount = $wallet_amount['unlocked_balance'] / 1000000000000; + $unlocked_amount_rounded = round($unlocked_wallet_amount, 6); + + echo "Your balance is: " . $real_amount_rounded . " XMR
"; + echo "Unlocked balance: " . $unlocked_amount_rounded . " XMR
"; + } + + public function process_payment($order_id) + { + $order = wc_get_order($order_id); + $order->update_status('on-hold', __('Awaiting offline payment', 'monero_gateway')); + // Reduce stock levels + $order->reduce_order_stock(); + + // Remove cart + WC()->cart->empty_cart(); + + // Return thank you redirect + return array( + 'result' => 'success', + 'redirect' => $this->get_return_url($order) + ); + + } + + // Submit payment and handle response + + public function validate_fields() + { + if ($this->check_monero() != TRUE) { + echo "

Your Monero Address doesn't seem valid. Have you checked it?

"; + } + + } + + + // Validate fields + + public function check_monero() + { + $monero_address = $this->settings['monero_address']; + if (strlen($monero_address) == 95 && substr($monero_address, 1)) { + return true; + } + return false; + } + + public function instruction($order_id) + { + $order = wc_get_order($order_id); + $amount = floatval(preg_replace('#[^\d.]#', '', $order->get_total())); + $payment_id = $this->set_paymentid_cookie(); + $currency = $order->get_currency(); + $amount_xmr2 = $this->changeto($amount, $currency, $payment_id); + $address = $this->address; + if (!isset($address)) { + // If there isn't address (merchant missed that field!), $address will be the Monero address for donating :) + $address = "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A"; + } + $uri = "monero:$address?amount=$amount?payment_id=$payment_id"; + $array_integrated_address = $this->monero_daemon->make_integrated_address($payment_id); + if (!isset($array_integrated_address)) { + $this->log->add('Monero_Gateway', '[ERROR] Unable to getting integrated address'); + // Seems that we can't connect with daemon, then set array_integrated_address, little hack + $array_integrated_address["integrated_address"] = $address; + } + $message = $this->verify_payment($payment_id, $amount_xmr2, $order); + if ($this->confirmed) { + $color = "006400"; + } else { + $color = "DC143C"; + } + echo "

" . $message . "

"; + echo ""; + + echo "
+
+
+
+
+
+

Monero Payment Box

+
+
+ +
+
+ Send " . $amount_xmr2 . " XMR to
+ or scan QR Code with your mobile device

+ If you need help with how to pay with Monero or want to learn more about it, please go to the Monerosite. +
+
+
+
+
+
- - "; - } - - - // Check if we are forcing SSL on checkout pages - // Custom function not required by the Gateway - public function do_ssl_check() - { - if ($this->enabled == "yes") { - if (get_option('woocommerce_force_ssl_checkout') == "no") { - echo "

" . sprintf(__("%s is enabled and WooCommerce is not forcing the SSL certificate on your checkout page. Please ensure that you have a valid SSL certificate and that you are forcing the checkout pages to be secured."), $this->method_title, admin_url('admin.php?page=wc-settings&tab=checkout')) . "

"; - } - } - } - - public function connect_daemon(){ - $host = $this->settings['daemon_host']; - $port = $this->settings['daemon_port']; - $monero_library = new Monero($host, $port); - if( $monero_library->works() == true){ - echo "

Everything works! Congratulations and welcome to Monero.

+ "; + } + + private function set_paymentid_cookie() + { + if (!isset($_COOKIE['payment_id'])) { + $payment_id = bin2hex(openssl_random_pseudo_bytes(8)); + setcookie('payment_id', $payment_id, time() + 2700); + } else + $payment_id = $_COOKIE['payment_id']; + return $payment_id; + } + + public function changeto($amount, $currency, $payment_id) + { + global $wpdb; + // This will create a table named whatever the payment id is inside the database "WordPress" + $create_table = "CREATE TABLE IF NOT EXISTS $payment_id ( + rate INT + )"; + $wpdb->query($create_table); + $rows_num = $wpdb->get_results("SELECT count(*) as count FROM $payment_id"); + if ($rows_num[0]->count > 0) // Checks if the row has already been created or not + { + $stored_rate = $wpdb->get_results("SELECT rate FROM $payment_id"); + + $stored_rate_transformed = $stored_rate[0]->rate / 100; //this will turn the stored rate back into a decimaled number + + if (isset($this->discount)) { + $discount_decimal = $this->discount / 100; + $new_amount = $amount / $stored_rate_transformed; + $discount = $new_amount * $discount_decimal; + $final_amount = $new_amount - $discount; + $rounded_amount = round($final_amount, 12); + } else { + $new_amount = $amount / $stored_rate_transformed; + $rounded_amount = round($new_amount, 12); //the moneo wallet can't handle decimals smaller than 0.000000000001 + } + } else // If the row has not been created then the live exchange rate will be grabbed and stored + { + $xmr_live_price = $this->retriveprice($currency); + $live_for_storing = $xmr_live_price * 100; //This will remove the decimal so that it can easily be stored as an integer + $new_amount = $amount / $xmr_live_price; + $rounded_amount = round($new_amount, 12); + + $wpdb->query("INSERT INTO $payment_id (rate) + VALUES ($live_for_storing)"); + } + + return $rounded_amount; + } + + + // Check if we are forcing SSL on checkout pages + // Custom function not required by the Gateway + + public function retriveprice($currency) + { + $xmr_price = file_get_contents('https://min-api.cryptocompare.com/data/price?fsym=XMR&tsyms=BTC,USD,EUR,CAD,INR,GBP&extraParams=monero_woocommerce'); + $price = json_decode($xmr_price, TRUE); + if (!isset($price)) { + $this->log->add('Monero_Gateway', '[ERROR] Unable to get the price of Monero'); + } + switch ($currency) { + case 'USD': + return $price['USD']; + case 'EUR': + return $price['EUR']; + case 'CAD': + return $price['CAD']; + case 'GBP': + return $price['GBP']; + case 'INR': + return $price['INR']; + case 'XMR': + $price = '1'; + return $price; + } + } + + public function verify_payment($payment_id, $amount, $order_id) + { + /* + * function for verifying payments + * Check if a payment has been made with this payment id then notify the merchant + */ + $message = "We are waiting for your payment to be confirmed"; + $amount_atomic_units = $amount * 1000000000000; + $get_payments_method = $this->monero_daemon->get_payments($payment_id); + if (isset($get_payments_method["payments"][0]["amount"])) { + if ($get_payments_method["payments"][0]["amount"] >= $amount_atomic_units) { + $message = "Payment has been received and confirmed. Thanks!"; + $this->log->add('Monero_gateway', '[SUCCESS] Payment has been recorded. Congratulations!'); + $this->confirmed = true; + $order = wc_get_order($order_id); + $order->update_status('completed', __('Payment has been received', 'monero_gateway')); + global $wpdb; + $wpdb->query("DROP TABLE $payment_id"); // Drop the table from database after payment has been confirmed as it is no longer needed + + $this->reloadTime = 3000000000000; // Greatly increase the reload time as it is no longer needed + } + } + return $message; + } + + public function do_ssl_check() + { + if ($this->enabled == "yes" && !$this->settings['onion_service']) { + if (get_option('woocommerce_force_ssl_checkout') == "no") { + echo "

" . sprintf(__("%s is enabled and WooCommerce is not forcing the SSL certificate on your checkout page. Please ensure that you have a valid SSL certificate and that you are forcing the checkout pages to be secured."), $this->method_title, admin_url('admin.php?page=wc-settings&tab=checkout')) . "

"; + } + } + } + + public function connect_daemon() + { + $host = $this->settings['daemon_host']; + $port = $this->settings['daemon_port']; + $monero_library = new Monero($host, $port); + if ($monero_library->works() == true) { + echo "

Everything works! Congratulations and welcome to Monero.

"; - - } - else{ - $this->log->add('Monero_gateway','[ERROR] Plugin can not reach wallet rpc.'); - echo "

Error with connection of daemon, see documentation!

"; - } } - - - - public function verify_payment($payment_id, $amount, $order_id){ - /* - * function for verifying payments - * Check if a payment has been made with this payment id then notify the merchant - */ - - $amount_atomic_units = $amount * 1000000000000; - $get_payments_method = $this->monero_daemon->get_payments($payment_id); - if(isset($get_payments_method["payments"][0]["amount"])) - { - if($get_payments_method["payments"][0]["amount"] >= $amount_atomic_units) - { - $message = "Payment has been received and confirmed. Thanks!"; - $this->log->add('Monero_gateway','[SUCCESS] Payment has been recorded. Congratulations!'); - $this->confirmed = true; - $order = wc_get_order($order_id); - $order->update_status('completed', __('Payment has been received', 'monero_gateway')); - global $wpdb; - $wpdb->query("DROP TABLE $payment_id"); // Drop the table from database after payment has been confirmed as it is no longer needed - - $this->reloadTime = 3000000000000; // Greatly increase the reload time as it is no longer needed - } - } - else - { - $message = "We are waiting for your payment to be confirmed"; - } - return $message; - } - public function getamountinfo(){ - $wallet_amount = $this->monero_daemon->getbalance(); - if(!isset($wallet_amount)){ - $this->log->add('Monero_gateway','[ERROR] No connection with daemon'); - $wallet_amount['balance'] = "0"; - $wallet_amount['unlocked_balance'] = "0"; - } - $real_wallet_amount = $wallet_amount['balance'] / 1000000000000; - $real_amount_rounded = round($real_wallet_amount, 6); - - $unlocked_wallet_amount = $wallet_amount['unlocked_balance'] / 1000000000000; - $unlocked_amount_rounded = round($unlocked_wallet_amount, 6); - - echo "Your balance is: ".$real_amount_rounded. " XMR
"; - echo "Unlocked balance: ".$unlocked_amount_rounded." XMR
"; - } + + } else { + $this->log->add('Monero_gateway', '[ERROR] Plugin can not reach wallet rpc.'); + echo "

Error with connection of daemon, see documentation!

"; + } + } } diff --git a/monero/library.php b/monero/library.php index 2aafb7d..a6a11e3 100644 --- a/monero/library.php +++ b/monero/library.php @@ -1,4 +1,5 @@ 8, CURLOPT_TIMEOUT => 8 ); - - + private $username; + private $password; private $httpErrors = array( 400 => '400 Bad Request', 401 => '401 Unauthorized', @@ -32,62 +31,79 @@ class Monero_Library 502 => '502 Bad Gateway', 503 => '503 Service Unavailable' ); - + public function __construct($pUrl, $pUser, $pPass) { $this->validate(false === extension_loaded('curl'), 'The curl extension must be loaded to use this class!'); $this->validate(false === extension_loaded('json'), 'The json extension must be loaded to use this class!'); - + $this->url = $pUrl; - $this->username = $pUser; - $this->password = $pPass; + $this->username = $pUser; + $this->password = $pPass; } - - private function getHttpErrorMessage($pErrorNumber) + + public function validate($pFailed, $pErrMsg) { - return isset($this->httpErrors[$pErrorNumber]) ? $this->httpErrors[$pErrorNumber] : null; + if ($pFailed) { + echo $pErrMsg; + } } - + public function setDebug($pIsDebug) { $this->is_debug = !empty($pIsDebug); return $this; } - - /* public function setParametersStructure($pParametersStructure) - { - if (in_array($pParametersStructure, array('array', 'object'))) - { - $this->parameters_structure = $pParametersStructure; - } - else - { - throw new UnexpectedValueException('Invalid parameters structure type.'); - } - return $this; - } */ - + + /* public function setParametersStructure($pParametersStructure) + { + if (in_array($pParametersStructure, array('array', 'object'))) + { + $this->parameters_structure = $pParametersStructure; + } + else + { + throw new UnexpectedValueException('Invalid parameters structure type.'); + } + return $this; + } */ + public function setCurlOptions($pOptionsArray) { - if (is_array($pOptionsArray)) - { + if (is_array($pOptionsArray)) { $this->curl_options = $pOptionsArray + $this->curl_options; - } - else - { + } else { echo 'Invalid options type.'; } return $this; } - - private function request($pMethod, $pParams) + + public function _print($json) + { + $json_encoded = json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + echo $json_encoded; + } + + public function address() + { + $address = $this->_run('getaddress'); + return $address; + } + + public function _run($method, $params = null) + { + $result = $this->request($method, $params); + return $result; //the result is returned as an array + } + + private function request($pMethod, $pParams) { static $requestId = 0; // generating uniuqe id per process $requestId++; // check if given params are correct $this->validate(false === is_scalar($pMethod), 'Method name has no scalar value'); - // $this->validate(false === is_array($pParams), 'Params must be given as array'); + // $this->validate(false === is_array($pParams), 'Params must be given as array'); // send params as an object or an array //$pParams = ($this->parameters_structure == 'object') ? $pParams[0] : array_values($pParams); // Request (method invocation) @@ -102,242 +118,206 @@ class Monero_Library $responseDecoded = json_decode($responseMessage, true); // check if decoding json generated any errors $jsonErrorMsg = $this->getJsonLastErrorMsg(); - $this->validate( !is_null($jsonErrorMsg), $jsonErrorMsg . ': ' . $responseMessage); + $this->validate(!is_null($jsonErrorMsg), $jsonErrorMsg . ': ' . $responseMessage); // check if response is correct $this->validate(empty($responseDecoded['id']), 'Invalid response data structure: ' . $responseMessage); $this->validate($responseDecoded['id'] != $requestId, 'Request id: ' . $requestId . ' is different from Response id: ' . $responseDecoded['id']); - if (isset($responseDecoded['error'])) - { + if (isset($responseDecoded['error'])) { $errorMessage = 'Request have return error: ' . $responseDecoded['error']['message'] . '; ' . "\n" . 'Request: ' . $request . '; '; - if (isset($responseDecoded['error']['data'])) - { + if (isset($responseDecoded['error']['data'])) { $errorMessage .= "\n" . 'Error data: ' . $responseDecoded['error']['data']; } - $this->validate( !is_null($responseDecoded['error']), $errorMessage); + $this->validate(!is_null($responseDecoded['error']), $errorMessage); } return $responseDecoded['result']; } - protected function & getResponse(&$pRequest) - { - // do the actual connection - $ch = curl_init(); - if ( !$ch) - { - throw new RuntimeException('Could\'t initialize a cURL session'); - } - curl_setopt($ch, CURLOPT_URL, $this->url); - curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); - curl_setopt($ch, CURLOPT_USERPWD, $this->username . ":" . $this->password); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $pRequest); - curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); - curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - if ( !curl_setopt_array($ch, $this->curl_options)) - { - throw new RuntimeException('Error while setting curl options'); - } - // send the request - $response = curl_exec($ch); - // check http status code - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if (isset($this->httpErrors[$httpCode])) - { - echo 'Response Http Error - ' . $this->httpErrors[$httpCode]; - } - // check for curl error - if (0 < curl_errno($ch)) - { - echo 'Unable to connect to '.$this->url . ' Error: ' . curl_error($ch); - } - // close the connection - curl_close($ch); - return $response; - } - - public function validate($pFailed, $pErrMsg) - { - if ($pFailed) - { - echo $pErrMsg; - } - } - + protected function debug($pAdd, $pShow = false) { static $debug, $startTime; // is_debug off return - if (false === $this->is_debug) - { + if (false === $this->is_debug) { return; } // add $debug .= $pAdd; // get starttime $startTime = empty($startTime) ? array_sum(explode(' ', microtime())) : $startTime; - if (true === $pShow and !empty($debug)) - { + if (true === $pShow and !empty($debug)) { // get endtime $endTime = array_sum(explode(' ', microtime())); // performance summary $debug .= 'Request time: ' . round($endTime - $startTime, 3) . ' s Memory usage: ' . round(memory_get_usage() / 1024) . " kb\r\n"; echo nl2br($debug); - // send output imidiately + // send output immediately flush(); // clean static $debug = $startTime = null; } } - + + protected function & getResponse(&$pRequest) + { + // do the actual connection + $ch = curl_init(); + if (!$ch) { + throw new RuntimeException('Could\'t initialize a cURL session'); + } + curl_setopt($ch, CURLOPT_URL, $this->url); + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); + curl_setopt($ch, CURLOPT_USERPWD, $this->username . ":" . $this->password); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $pRequest); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); + curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + if (!curl_setopt_array($ch, $this->curl_options)) { + throw new RuntimeException('Error while setting curl options'); + } + // send the request + $response = curl_exec($ch); + // check http status code + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if (isset($this->httpErrors[$httpCode])) { + echo 'Response Http Error - ' . $this->httpErrors[$httpCode]; + } + // check for curl error + if (0 < curl_errno($ch)) { + echo 'Unable to connect to ' . $this->url . ' Error: ' . curl_error($ch); + } + // close the connection + curl_close($ch); + return $response; + } + + //prints result as json + function getJsonLastErrorMsg() { - if (!function_exists('json_last_error_msg')) - { + if (!function_exists('json_last_error_msg')) { function json_last_error_msg() { static $errors = array( - JSON_ERROR_NONE => 'No error', - JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', + JSON_ERROR_NONE => 'No error', + JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', - JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', - JSON_ERROR_SYNTAX => 'Syntax error', - JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded' + JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', + JSON_ERROR_SYNTAX => 'Syntax error', + JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded' ); $error = json_last_error(); return array_key_exists($error, $errors) ? $errors[$error] : 'Unknown error (' . $error . ')'; } } - + // Fix PHP 5.2 error caused by missing json_last_error function - if (function_exists('json_last_error')) - { + if (function_exists('json_last_error')) { return json_last_error() ? json_last_error_msg() : null; - } - else - { + } else { return null; } } - - public function _run($method,$params = null) - { - $result = $this->request($method, $params); - return $result; //the result is returned as an array - } - - //prints result as json - public function _print($json) - { - $json_encoded = json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); - echo $json_encoded; - } - + /* * The following functions can all be called to interact with the monero rpc wallet * They will majority of them will return the result as an array * Example: $daemon->address(); where $daemon is an instance of this class, will return the wallet address as string within an array */ - - public function address() - { - $address = $this->_run('getaddress'); - return $address; - } - + public function getbalance() { - $balance = $this->_run('getbalance'); - return $balance; + $balance = $this->_run('getbalance'); + return $balance; } - + public function getheight() { - $height = $this->_run('getheight'); - return $height; + $height = $this->_run('getheight'); + return $height; } - + public function incoming_transfer($type) { $incoming_parameters = array('transfer_type' => $type); $incoming_transfers = $this->_run('incoming_transfers', $incoming_parameters); return $incoming_transfers; } - - public function get_transfers($input_type, $input_value) - { + + public function get_transfers($input_type, $input_value) + { $get_parameters = array($input_type => $input_value); $get_transfers = $this->_run('get_transfers', $get_parameters); return $get_transfers; } - + public function view_key() { $query_key = array('key_type' => 'view_key'); $query_key_method = $this->_run('query_key', $query_key); return $query_key_method; - } - - /* A payment id can be passed as a string - A random payment id will be generatd if one is not given */ + } + public function make_integrated_address($payment_id) { $integrate_address_parameters = array('payment_id' => $payment_id); $integrate_address_method = $this->_run('make_integrated_address', $integrate_address_parameters); return $integrate_address_method; } - + + /* A payment id can be passed as a string + A random payment id will be generatd if one is not given */ + public function split_integrated_address($integrated_address) { - if(!isset($integrated_address)){ + if (!isset($integrated_address)) { echo "Error: Integrated_Address mustn't be null"; - } - else{ - $split_params = array('integrated_address' => $integrated_address); - $split_methods = $this->_run('split_integrated_address', $split_params); - return $split_methods; + } else { + $split_params = array('integrated_address' => $integrated_address); + $split_methods = $this->_run('split_integrated_address', $split_params); + return $split_methods; } } - + public function make_uri($address, $amount, $recipient_name = null, $description = null) { - // If I pass 1, it will be 0.0000001 xmr. Then + // If I pass 1, it will be 0.0000001 xmr. Then $new_amount = $amount * 100000000; - + $uri_params = array('address' => $address, 'amount' => $new_amount, 'payment_id' => '', 'recipient_name' => $recipient_name, 'tx_description' => $description); $uri = $this->_run('make_uri', $uri_params); return $uri; } - + public function parse_uri($uri) { $uri_parameters = array('uri' => $uri); $parsed_uri = $this->_run('parse_uri', $uri_parameters); return $parsed_uri; } - + public function transfer($amount, $address, $mixin = 4) { - $new_amount = $amount * 1000000000000; + $new_amount = $amount * 1000000000000; $destinations = array('amount' => $new_amount, 'address' => $address); $transfer_parameters = array('destinations' => array($destinations), 'mixin' => $mixin, 'get_tx_key' => true, 'unlock_time' => 0, 'payment_id' => ''); $transfer_method = $this->_run('transfer', $transfer_parameters); return $transfer_method; } - + public function get_payments($payment_id) { - $get_payments_parameters = array('payment_id' => $payment_id); - $get_payments = $this->_run('get_payments', $get_payments_parameters); - return $get_payments; - } - - public function get_bulk_payments($payment_id, $min_block_height) - { - $get_bulk_payments_parameters = array('payment_id' => $payment_id, 'min_block_height' => $min_block_height); - $get_bulk_payments = $this->_run('get_bulk_payments', $get_bulk_payments_parameters); - return $get_bulk_payments; - } -} + $get_payments_parameters = array('payment_id' => $payment_id); + $get_payments = $this->_run('get_payments', $get_payments_parameters); + return $get_payments; + } + + public function get_bulk_payments($payment_id, $min_block_height) + { + $get_bulk_payments_parameters = array('payment_id' => $payment_id, 'min_block_height' => $min_block_height); + $get_bulk_payments = $this->_run('get_bulk_payments', $get_bulk_payments_parameters); + return $get_bulk_payments; + } +} diff --git a/monero/monero_gateway.php b/monero/monero_gateway.php index 82d03b8..c0c5917 100644 --- a/monero/monero_gateway.php +++ b/monero/monero_gateway.php @@ -7,54 +7,56 @@ Version: 1.0 Author: SerHack Author URI: http://monerointegrations.com */ -if ( ! defined( 'ABSPATH' ) ) { - exit; // Exit if accessed directly +if (!defined('ABSPATH')) { + exit; // Exit if accessed directly } // Include our Gateway Class and register Payment Gateway with WooCommerce -add_action( 'plugins_loaded', 'monero_init', 0 ); -function monero_init() { - /* If the class doesn't exist (== WooCommerce isn't installed), return NULL */ - if ( ! class_exists( 'WC_Payment_Gateway' ) ) return; - - - /* If we made it this far, then include our Gateway Class */ - include_once( 'include/monero_payments.php' ); - require_once( 'library.php'); +add_action('plugins_loaded', 'monero_init', 0); +function monero_init() +{ + /* If the class doesn't exist (== WooCommerce isn't installed), return NULL */ + if (!class_exists('WC_Payment_Gateway')) return; - // Lets add it too WooCommerce - add_filter( 'woocommerce_payment_gateways', 'monero_gateway' ); - function monero_gateway( $methods ) { - $methods[] = 'Monero_Gateway'; - return $methods; - } - - + /* If we made it this far, then include our Gateway Class */ + include_once('include/monero_payments.php'); + require_once('library.php'); + + // Lets add it too WooCommerce + add_filter('woocommerce_payment_gateways', 'monero_gateway'); + function monero_gateway($methods) + { + $methods[] = 'Monero_Gateway'; + return $methods; + } } /* * Add custom link * The url will be http://yourworpress/wp-admin/admin.php?=wc-settings&tab=checkout */ -add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'monero_payment' ); -function monero_payment( $links ) { - $plugin_links = array( - '' . __( 'Settings', 'monero_payment' ) . '', - ); +add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'monero_payment'); +function monero_payment($links) +{ + $plugin_links = array( + '' . __('Settings', 'monero_payment') . '', + ); - return array_merge( $plugin_links, $links ); + return array_merge($plugin_links, $links); } -add_action( 'admin_menu', 'monero_create_menu' ); - function monero_create_menu(){ - add_menu_page( - __( 'Monero', 'textdomain' ), + +add_action('admin_menu', 'monero_create_menu'); +function monero_create_menu() +{ + add_menu_page( + __('Monero', 'textdomain'), 'Monero', 'manage_options', 'admin.php?page=wc-settings&tab=checkout§ion=monero_gateway', '', - plugins_url( 'monero/assets/icon.png' ), + plugins_url('monero/assets/icon.png'), 56 // Position on menu, woocommerce has 55.5, products has 55.6 - + ); }