Merge pull request #40 from cryptochangements34/master
Allow Transaction Verification Without Monero-Wallet-RPC
This commit is contained in:
commit
6326652a19
@ -12,6 +12,7 @@ class Monero_Gateway extends WC_Payment_Gateway
|
||||
private $discount;
|
||||
private $confirmed = false;
|
||||
private $monero_daemon;
|
||||
private $non_rpc = false;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
@ -30,8 +31,21 @@ class Monero_Gateway extends WC_Payment_Gateway
|
||||
$this->host = $this->get_option('daemon_host');
|
||||
$this->port = $this->get_option('daemon_port');
|
||||
$this->address = $this->get_option('monero_address');
|
||||
$this->viewKey = $this->get_option('viewKey');
|
||||
$this->discount = $this->get_option('discount');
|
||||
|
||||
$this->use_viewKey = $this->get_option('use_viewKey');
|
||||
$this->use_rpc = $this->get_option('use_rpc');
|
||||
|
||||
if($this->use_viewKey == 'yes')
|
||||
{
|
||||
$this->non_rpc = true;
|
||||
}
|
||||
if($this->use_rpc == 'yes')
|
||||
{
|
||||
$this->non_rpc = false;
|
||||
}
|
||||
|
||||
// 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();
|
||||
@ -77,12 +91,32 @@ class Monero_Gateway extends WC_Payment_Gateway
|
||||
'default' => __('Pay securely using XMR.', 'monero_gateway')
|
||||
|
||||
),
|
||||
'use_viewKey' => array(
|
||||
'title' => __('Use ViewKey', 'monero_gateway'),
|
||||
'label' => __(' Verify Transaction with ViewKey ', 'monero_gateway'),
|
||||
'type' => 'checkbox',
|
||||
'description' => __('Fill in the Address and ViewKey fields to verify transactions with your ViewKey', 'monero_gateway'),
|
||||
'default' => 'no'
|
||||
),
|
||||
'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')
|
||||
),
|
||||
'viewKey' => array(
|
||||
'title' => __('Secret ViewKey', 'monero_gateway'),
|
||||
'label' => __('Secret ViewKey'),
|
||||
'type' => 'text',
|
||||
'desc_tip' => __('Your secret ViewKey', 'monero_gateway')
|
||||
),
|
||||
'use_rpc' => array(
|
||||
'title' => __('Use monero-wallet-rpc', 'monero_gateway'),
|
||||
'label' => __(' Verify transactions with the monero-wallet-rpc ', 'monero_gateway'),
|
||||
'type' => 'checkbox',
|
||||
'description' => __('This must be setup seperatly', 'monero_gateway'),
|
||||
'default' => 'no'
|
||||
),
|
||||
'daemon_host' => array(
|
||||
'title' => __('Monero wallet rpc Host/ IP', 'monero_gateway'),
|
||||
'type' => 'text',
|
||||
@ -100,8 +134,8 @@ class Monero_Gateway extends WC_Payment_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%'
|
||||
'type' => __('number'),
|
||||
'default' => '5'
|
||||
|
||||
),
|
||||
'environment' => array(
|
||||
@ -140,17 +174,19 @@ class Monero_Gateway extends WC_Payment_Gateway
|
||||
public function admin_options()
|
||||
{
|
||||
$this->log->add('Monero_gateway', '[SUCCESS] Monero Settings OK');
|
||||
|
||||
echo "<h1>Monero Payment Gateway</h1>";
|
||||
|
||||
echo "<p>Welcome to Monero Extension for WooCommerce. Getting started: Make a connection with daemon <a href='https://reddit.com/u/serhack'>Contact Me</a>";
|
||||
echo "<div style='border:1px solid #DDD;padding:5px 10px;font-weight:bold;color:#223079;background-color:#9ddff3;'>";
|
||||
$this->getamountinfo();
|
||||
|
||||
if(!$this->non_rpc) // only try to get balance data if using wallet-rpc
|
||||
$this->getamountinfo();
|
||||
|
||||
echo "</div>";
|
||||
echo "<table class='form-table'>";
|
||||
$this->generate_settings_html();
|
||||
echo "</table>";
|
||||
echo "<h4>Learn more about using monero-wallet-rpc <a href=\"https://github.com/monero-integrations/monerowp/blob/master/README.md\">here</a></h4>";
|
||||
echo "<h4>Learn more about using monero-wallet-rpc <a href=\"https://github.com/monero-integrations/monerowp/blob/master/README.md\">here</a> and viewkeys <a href=\"https://getmonero.org/resources/moneropedia/viewkey.html\">here</a> </h4>";
|
||||
}
|
||||
|
||||
public function getamountinfo()
|
||||
@ -197,7 +233,15 @@ class Monero_Gateway extends WC_Payment_Gateway
|
||||
public function validate_fields()
|
||||
{
|
||||
if ($this->check_monero() != TRUE) {
|
||||
echo "<div class=\"error\"><p>Your Monero Address doesn't seem valid. Have you checked it?</p></div>";
|
||||
echo "<div class=\"error\"><p>Your Monero Address doesn't look valid. Have you checked it?</p></div>";
|
||||
}
|
||||
if(!$this->check_viewKey())
|
||||
{
|
||||
echo "<div class=\"error\"><p>Your ViewKey doesn't look valid. Have you checked it?</p></div>";
|
||||
}
|
||||
if($this->check_checkedBoxes())
|
||||
{
|
||||
echo "<div class=\"error\"><p>You must choose to either use monero-wallet-rpc or a ViewKey, not both</p></div>";
|
||||
}
|
||||
|
||||
}
|
||||
@ -213,6 +257,29 @@ class Monero_Gateway extends WC_Payment_Gateway
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public function check_viewKey()
|
||||
{
|
||||
if($this->use_viewKey == 'yes')
|
||||
{
|
||||
if (strlen($this->viewKey) == 64) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public function check_checkedBoxes()
|
||||
{
|
||||
if($this->use_viewKey == 'yes')
|
||||
{
|
||||
if($this->use_rpc == 'yes')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public function is_virtual_in_cart($order_id)
|
||||
{
|
||||
@ -231,93 +298,164 @@ class Monero_Gateway extends WC_Payment_Gateway
|
||||
|
||||
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 get integrated address');
|
||||
// Seems that we can't connect with daemon, then set array_integrated_address, little hack
|
||||
$array_integrated_address["integrated_address"] = $address;
|
||||
}
|
||||
if($this->is_virtual_in_cart($order_id) == true){
|
||||
echo "test";
|
||||
}
|
||||
$message = $this->verify_payment($payment_id, $amount_xmr2, $order);
|
||||
if ($this->confirmed) {
|
||||
$color = "006400";
|
||||
} else {
|
||||
$color = "DC143C";
|
||||
}
|
||||
echo "<h4><font color=$color>" . $message . "</font></h4>";
|
||||
if($this->non_rpc)
|
||||
{
|
||||
$order = wc_get_order($order_id);
|
||||
$amount = floatval(preg_replace('#[^\d.]#', '', $order->get_total()));
|
||||
$payment_id = $this->set_paymentid_cookie(32);
|
||||
$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";
|
||||
|
||||
echo "
|
||||
<head>
|
||||
<!--Import Google Icon Font-->
|
||||
<link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'>
|
||||
<link href='https://fonts.googleapis.com/css?family=Montserrat:400,800' rel='stylesheet'>
|
||||
<link href='http://cdn.monerointegrations.com/style.css' rel='stylesheet'>
|
||||
<!--Let browser know website is optimized for mobile-->
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0'/>
|
||||
</head>
|
||||
<body>
|
||||
<!-- page container -->
|
||||
<div class='page-container'>
|
||||
<!-- monero container payment box -->
|
||||
<div class='container-xmr-payment'>
|
||||
<!-- header -->
|
||||
<div class='header-xmr-payment'>
|
||||
<span class='logo-xmr'><img src='http://cdn.monerointegrations.com/logomonero.png' /></span>
|
||||
<span class='xmr-payment-text-header'><h2>MONERO PAYMENT</h2></span>
|
||||
</div>
|
||||
<!-- end header -->
|
||||
<!-- xmr content box -->
|
||||
<div class='content-xmr-payment'>
|
||||
<div class='xmr-amount-send'>
|
||||
<span class='xmr-label'>Send:</span>
|
||||
<div class='xmr-amount-box'>".$amount_xmr2."</div><div class='xmr-box'>XMR</div>
|
||||
</div>
|
||||
<div class='xmr-address'>
|
||||
<span class='xmr-label'>To this address:</span>
|
||||
<div class='xmr-address-box'>".$array_integrated_address['integrated_address']."</div>
|
||||
</div>
|
||||
<div class='xmr-qr-code'>
|
||||
<span class='xmr-label'>Or scan QR:</span>
|
||||
<div class='xmr-qr-code-box'><img src='https://api.qrserver.com/v1/create-qr-code/? size=200x200&data=".$uri."' /></div>
|
||||
</div>
|
||||
<div class='clear'></div>
|
||||
</div>
|
||||
<!-- end content box -->
|
||||
<!-- footer xmr payment -->
|
||||
<div class='footer-xmr-payment'>
|
||||
<a href='https://getmonero.org' target='_blank'>Help</a> | <a href='https://getmonero.org' target='_blank'>About Monero</a>
|
||||
</div>
|
||||
<!-- end footer xmr payment -->
|
||||
</div>
|
||||
<!-- end monero container payment box -->
|
||||
</div>
|
||||
<!-- end page container -->
|
||||
</body>
|
||||
";
|
||||
if($this->verify_non_rpc($payment_id, $amount_xmr2, $order_id) == false);
|
||||
{
|
||||
echo "<h4> We are waiting for your transaction to be confirmed </h4>";
|
||||
}
|
||||
|
||||
echo "
|
||||
<head>
|
||||
<!--Import Google Icon Font-->
|
||||
<link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'>
|
||||
<link href='https://fonts.googleapis.com/css?family=Montserrat:400,800' rel='stylesheet'>
|
||||
<link href='http://cdn.monerointegrations.com/style.css' rel='stylesheet'>
|
||||
<!--Let browser know website is optimized for mobile-->
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0'/>
|
||||
</head>
|
||||
<body>
|
||||
<!-- page container -->
|
||||
<div class='page-container'>
|
||||
<!-- monero container payment box -->
|
||||
<div class='container-xmr-payment'>
|
||||
<!-- header -->
|
||||
<div class='header-xmr-payment'>
|
||||
<span class='logo-xmr'><img src='http://cdn.monerointegrations.com/logomonero.png' /></span>
|
||||
<span class='xmr-payment-text-header'><h2>MONERO PAYMENT</h2></span>
|
||||
</div>
|
||||
<!-- end header -->
|
||||
<!-- xmr content box -->
|
||||
<div class='content-xmr-payment'>
|
||||
<div class='xmr-amount-send'>
|
||||
<span class='xmr-label'>Send:</span>
|
||||
<div class='xmr-amount-box'>".$amount_xmr2."</div>
|
||||
<span class='xmr-label'>Payment ID:</span>
|
||||
<div class='xmr-integrated-address-box'>".$payment_id."</div>
|
||||
</div>
|
||||
<div class='xmr-address'>
|
||||
<span class='xmr-label'>To this address:</span>
|
||||
<div class='xmr-address-box'>".$address."</div>
|
||||
</div>
|
||||
<div class='xmr-qr-code'>
|
||||
<span class='xmr-label'>Or scan QR:</span>
|
||||
<div class='xmr-qr-code-box'><img src='https://api.qrserver.com/v1/create-qr-code/? size=200x200&data=".$uri."' /></div>
|
||||
</div>
|
||||
<div class='clear'></div>
|
||||
</div>
|
||||
<!-- end content box -->
|
||||
<!-- footer xmr payment -->
|
||||
<div class='footer-xmr-payment'>
|
||||
<a href='https://getmonero.org' target='_blank'>Help</a> | <a href='https://getmonero.org' target='_blank'>About Monero</a>
|
||||
</div>
|
||||
<!-- end footer xmr payment -->
|
||||
</div>
|
||||
<!-- end monero container payment box -->
|
||||
</div>
|
||||
<!-- end page container -->
|
||||
</body>
|
||||
";
|
||||
|
||||
echo "
|
||||
<script type='text/javascript'>setTimeout(function () { location.reload(true); }, $this->reloadTime);</script>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$order = wc_get_order($order_id);
|
||||
$amount = floatval(preg_replace('#[^\d.]#', '', $order->get_total()));
|
||||
$payment_id = $this->set_paymentid_cookie(8);
|
||||
$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 get 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 "<h4><font color=$color>" . $message . "</font></h4>";
|
||||
|
||||
echo "
|
||||
<script type='text/javascript'>setTimeout(function () { location.reload(true); }, $this->reloadTime);</script>";
|
||||
echo "
|
||||
<head>
|
||||
<!--Import Google Icon Font-->
|
||||
<link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'>
|
||||
<link href='https://fonts.googleapis.com/css?family=Montserrat:400,800' rel='stylesheet'>
|
||||
<link href='http://127.0.0.1:8888/style.css' rel='stylesheet'>
|
||||
<!--Let browser know website is optimized for mobile-->
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0'/>
|
||||
</head>
|
||||
<body>
|
||||
<!-- page container -->
|
||||
<div class='page-container'>
|
||||
<!-- monero container payment box -->
|
||||
<div class='container-xmr-payment'>
|
||||
<!-- header -->
|
||||
<div class='header-xmr-payment'>
|
||||
<span class='logo-xmr'><img src='http://cdn.monerointegrations.com/logomonero.png' /></span>
|
||||
<span class='xmr-payment-text-header'><h2>MONERO PAYMENT</h2></span>
|
||||
</div>
|
||||
<!-- end header -->
|
||||
<!-- xmr content box -->
|
||||
<div class='content-xmr-payment'>
|
||||
<div class='xmr-amount-send'>
|
||||
<span class='xmr-label'>Send:</span>
|
||||
<div class='xmr-amount-box'>".$amount_xmr2."</div>
|
||||
</div>
|
||||
<div class='xmr-address'>
|
||||
<span class='xmr-label'>To this address:</span>
|
||||
<div class='xmr-address-box'>".$array_integrated_address['integrated_address']."</div>
|
||||
</div>
|
||||
<div class='xmr-qr-code'>
|
||||
<span class='xmr-label'>Or scan QR:</span>
|
||||
<div class='xmr-qr-code-box'><img src='https://api.qrserver.com/v1/create-qr-code/? size=200x200&data=".$uri."' /></div>
|
||||
</div>
|
||||
<div class='clear'></div>
|
||||
</div>
|
||||
<!-- end content box -->
|
||||
<!-- footer xmr payment -->
|
||||
<div class='footer-xmr-payment'>
|
||||
<a href='https://getmonero.org' target='_blank'>Help</a> | <a href='https://getmonero.org' target='_blank'>About Monero</a>
|
||||
</div>
|
||||
<!-- end footer xmr payment -->
|
||||
</div>
|
||||
<!-- end monero container payment box -->
|
||||
</div>
|
||||
<!-- end page container -->
|
||||
</body>
|
||||
";
|
||||
|
||||
echo "
|
||||
<script type='text/javascript'>setTimeout(function () { location.reload(true); }, $this->reloadTime);</script>";
|
||||
}
|
||||
}
|
||||
|
||||
private function set_paymentid_cookie()
|
||||
private function set_paymentid_cookie($size)
|
||||
{
|
||||
if (!isset($_COOKIE['payment_id'])) {
|
||||
$payment_id = bin2hex(openssl_random_pseudo_bytes(8));
|
||||
$payment_id = bin2hex(openssl_random_pseudo_bytes($size));
|
||||
setcookie('payment_id', $payment_id, time() + 2700);
|
||||
}
|
||||
else{
|
||||
@ -457,6 +595,41 @@ class Monero_Gateway extends WC_Payment_Gateway
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function verify_non_rpc($payment_id, $amount, $order_id)
|
||||
{
|
||||
$tools = new NodeTools();
|
||||
$bc_height = $tools->get_last_block_height();
|
||||
$txs_from_block = $tools->get_txs_from_block($bc_height);
|
||||
$tx_count = count($txs_from_block) - 1; // The tx at index 0 is a coinbase tx so it can be ignored
|
||||
|
||||
$i = 1;
|
||||
$output_found;
|
||||
$block_index;
|
||||
while($i <= $tx_count)
|
||||
{
|
||||
$tx_hash = $txs_from_block[$i]['tx_hash'];
|
||||
$result = $tools->check_tx($tx_hash, $this->address, $this->viewKey);
|
||||
if($result)
|
||||
{
|
||||
$output_found = $result;
|
||||
$block_index = $i;
|
||||
$i = $tx_count; // finish loop
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
if(isset($output_found))
|
||||
{
|
||||
$amount_atomic_units = $amount * 1000000000000;
|
||||
if($txs_from_block[$block_index]['payment_id'] == $payment_id && $output_found >= $amount)
|
||||
{
|
||||
$this->on_verified($payment_id, $amount_atomic_units, $order_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function do_ssl_check()
|
||||
{
|
||||
if ($this->enabled == "yes" && !$this->get_option('onion_service')) {
|
||||
|
@ -319,3 +319,62 @@ class Monero_Library
|
||||
return $get_bulk_payments;
|
||||
}
|
||||
}
|
||||
|
||||
class NodeTools
|
||||
{
|
||||
public function get_last_block_height()
|
||||
{
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_RETURNTRANSFER => 1,
|
||||
CURLOPT_URL => 'https://xmrchain.net/api/networkinfo',
|
||||
));
|
||||
$resp = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
|
||||
$array = json_decode($resp, true);
|
||||
return $array['data']['height'] - 1;
|
||||
}
|
||||
|
||||
public function get_txs_from_block($height)
|
||||
{
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_RETURNTRANSFER => 1,
|
||||
CURLOPT_URL => 'https://xmrchain.net/api/search/' . $height,
|
||||
));
|
||||
$resp = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
|
||||
$array = json_decode($resp, true);
|
||||
|
||||
return $array['data']['txs'];
|
||||
}
|
||||
|
||||
public function check_tx($tx_hash, $address, $viewKey)
|
||||
{
|
||||
$curl = curl_init();
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_RETURNTRANSFER => 1,
|
||||
CURLOPT_URL => 'https://xmrchain.net/api/outputs?txhash=' .$tx_hash . '&address='. $address . '&viewkey='. $viewKey .'&txprove=0',
|
||||
));
|
||||
$resp = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
$array = json_decode($resp, true);
|
||||
$output_count = count($array['data']['outputs']);
|
||||
$i = 0;
|
||||
while($i < $output_count)
|
||||
{
|
||||
if($array['data']['outputs'][$i]['match'])
|
||||
{
|
||||
return $array['data']['outputs'][$i];
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user