Платёжная система в 50 строк кода, реально?
- среда, 14 февраля 2018 г. в 03:15:49
pragma solidity ^0.4.18;
//version:4
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner public {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract PaymentSystem is Ownable {
struct order {
address payer;
uint256 value;
bool revert;
}
//база ордеров
mapping(uint256 => order) public orders;
//возврат денег при попытке отправить деньги на контракт
function () public payable {
revert();
}
event PaymentOrder(uint256 indexed id, address payer, uint256 value);
//оплата ордера
function paymentOrder(uint256 _id) public payable returns(bool) {
require(orders[_id].value==0 && msg.value>0);
orders[_id].payer=msg.sender;
orders[_id].value=msg.value;
orders[_id].revert=false;
//создать евент
PaymentOrder(_id, msg.sender, msg.value);
return true;
}
event RevertOrder(uint256 indexed id, address payer, uint256 value);
//возврат платежа администратором
function revertOrder(uint256 _id) public onlyOwner returns(bool) {
require(orders[_id].value>0 && orders[_id].revert==false);
orders[_id].revert=true;
orders[_id].payer.transfer(orders[_id].value);
RevertOrder(_id, orders[_id].payer, orders[_id].value);
return true;
}
//вывод денег администратором
function outputMoney(address _from, uint256 _value) public onlyOwner returns(bool) {
require(this.balance>=_value);
_from.transfer(_value);
return true;
}
}
<body>
<div class="main_section">
<h3 class="section_title">Pay</h3>
<div class="edit"><input type="text" class="myedit" id="edit_id" placeholder="id"></div>
<div class="edit"><input type="text" class="myedit" id="edit_value" placeholder="value (ETH)"></div>
<div id="button_pay" class="mybutton">pay</div>
<div id="message_pay" class="message"></div>
<script>
//оплата
//-----------------------------------------------------------------
var button_pay = document.querySelector('#button_pay');
button_pay.addEventListener('click', function() {
var pay_id = document.getElementById("edit_id").value;
var pay_value = web3.toWei(parseFloat(document.getElementById("edit_value").value), 'ether')
var user_adress = web3.eth.accounts[0];
if (!web3.isAddress(user_adress)) {
write_wessage("#message_pay", "error: MetaMask not open");
return;
}
if (pay_id.length==0) {
write_wessage("#message_pay", "error: not id");
return;
}
if (pay_value==0) {
write_wessage("#message_pay", "error: volume 0");
return;
}
contract.paymentOrder(
pay_id,
{from: user_adress, value: pay_value, gasPrice: 41000000000},
function (err, transaction_hash) {
if (err) {
write_wessage("#message_pay", "error");
console.log(err);
} else {
write_wessage("#message_pay", "transaction hash: "+transaction_hash);
}
});
});
</script>
</div>
</body>
<script>
function write_wessage(element, message) {
document.querySelector(element).innerHTML = message;
}
if (typeof web3 === 'undefined') {
document.getElementsByTagName("body")[0].innerHTML = 'You need to install MetaMask';
} else {
//инициализация контракта
var contract_adress='0x3b4a22858093B9942514eE42eD1B4BF177632ba3';
var abi=[ { "constant": true, "inputs": [], "name": "owner", "outputs": [ { "name": "", "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "uint256" } ], "name": "orders", "outputs": [ { "name": "payer", "type": "address" }, { "name": "value", "type": "uint256" }, { "name": "revert", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "previousOwner", "type": "address" }, { "indexed": true, "name": "newOwner", "type": "address" } ], "name": "OwnershipTransferred", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "id", "type": "uint256" }, { "indexed": false, "name": "payer", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "PaymentOrder", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "id", "type": "uint256" }, { "indexed": false, "name": "payer", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "RevertOrder", "type": "event" }, { "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "outputMoney", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_id", "type": "uint256" } ], "name": "paymentOrder", "outputs": [ { "name": "", "type": "bool" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_id", "type": "uint256" } ], "name": "revertOrder", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "payable": true, "stateMutability": "payable", "type": "fallback" } ];
var contract = web3.eth.contract(abi).at(contract_adress);
}
</script>
<body>
<div class="main_section">
<h3 class="section_title">Info</h3>
<div id="message_balance" class="message"></div>
<div id="message_owner" class="message"></div>
</div>
<div class="main_section">
<h3 class="section_title">Output money</h3>
<div class="edit"><input type="text" class="myedit" id="edit_adress" placeholder="adress"></div>
<div class="edit"><input type="text" class="myedit" id="edit_value" placeholder="value (ETH)"></div>
<div id="button_output" class="mybutton">output</div>
<div id="message_output" class="message"></div>
<script>
//вывод денег
//-----------------------------------------------------------------
var button_output = document.querySelector('#button_output');
button_output.addEventListener('click', function() {
var pay_value = web3.toWei(parseFloat(document.getElementById("edit_value").value), 'ether')
var to_adress = document.getElementById("edit_adress").value;
var user_adress = web3.eth.accounts[0];
if (!web3.isAddress(user_adress)) {
write_wessage("#message_output", "error: MetaMask not open");
return;
}
if (!web3.isAddress(to_adress)) {
write_wessage("#message_output", "error: adress not valid");
return;
}
if (pay_value==0) {
write_wessage("#message_output", "error: volume 0");
return;
}
contract.outputMoney(
to_adress,
pay_value,
{from: user_adress, gasPrice: 41000000000},
function (err, transaction_hash) {
if (err) {
write_wessage("#message_output", "error");
console.log(err);
} else {
write_wessage("#message_output", "transaction hash: "+transaction_hash);
}
});
});
</script>
</div>
<div class="main_section">
<h3 class="section_title">Revert order</h3>
<div class="edit"><input type="text" class="myedit" id="edit_id" placeholder="id"></div>
<div id="button_revert" class="mybutton">revert</div>
<div id="message_revert" class="message"></div>
<script>
//возврат денег
//-----------------------------------------------------------------
var button_revert = document.querySelector('#button_revert');
button_revert.addEventListener('click', function() {
var pay_id = document.getElementById("edit_id").value;
var user_adress = web3.eth.accounts[0];
if (!web3.isAddress(user_adress)) {
write_wessage("#message_revert", "error: MetaMask not open");
return;
}
if (pay_id.length==0) {
write_wessage("#message_revert", "error: not id");
return;
}
contract.revertOrder(
pay_id,
{from: user_adress, gasPrice: 41000000000},
function (err, transaction_hash) {
if (err) {
write_wessage("#message_revert", "error");
console.log(err);
} else {
write_wessage("#message_revert", "transaction hash: "+transaction_hash);
}
});
});
</script>
</div>
</body>
<script>
function write_wessage(element, message) {
document.querySelector(element).innerHTML = message;
}
if (typeof web3 === 'undefined') {
document.getElementsByTagName("body")[0].innerHTML = 'You need to install MetaMask';
} else {
//инициализация контракта
var contract_adress='0x3b4a22858093B9942514eE42eD1B4BF177632ba3';
var abi=[ { "constant": true, "inputs": [], "name": "owner", "outputs": [ { "name": "", "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "uint256" } ], "name": "orders", "outputs": [ { "name": "payer", "type": "address" }, { "name": "value", "type": "uint256" }, { "name": "revert", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "previousOwner", "type": "address" }, { "indexed": true, "name": "newOwner", "type": "address" } ], "name": "OwnershipTransferred", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "id", "type": "uint256" }, { "indexed": false, "name": "payer", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "PaymentOrder", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "id", "type": "uint256" }, { "indexed": false, "name": "payer", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "RevertOrder", "type": "event" }, { "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "outputMoney", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_id", "type": "uint256" } ], "name": "paymentOrder", "outputs": [ { "name": "", "type": "bool" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_id", "type": "uint256" } ], "name": "revertOrder", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "payable": true, "stateMutability": "payable", "type": "fallback" } ];
var contract = web3.eth.contract(abi).at(contract_adress);
//получаем баланс
web3.eth.getBalance(contract_adress.toString(), function (err, result) {
write_wessage("#message_balance", "contract balance: "+web3.fromWei(result, 'ether')+" ETH");
});
//получаем owner
contract.owner(function(err, data) {
if (err) {
write_wessage("#message_owner", "error");
} else {
write_wessage("#message_owner", "owner: "+data);
}
});
}
</script>
geth --rinkeby --datadir "D:/eth/blockchain_rinkeby" --rpc --rpcaddr "0.0.0.0" --rpcapi "admin,debug,miner,shh,txpool,personal,eth,net,web3" console
<?php
require 'ethereum-php-master/ethereum.php';
$rate=0.000000000000000001;
//создаём новое подключение
$ethereum = new Ethereum('192.168.56.1', 8545);
//создаём новый фильтр
$filter = new Ethereum_Filter('0x0', 'latest', '0x3b4a22858093B9942514eE42eD1B4BF177632ba3', []);
//отправляем фильтр в ноду
$result_filter=$ethereum->eth_newFilter($filter);
//получаем список events
$logs=$ethereum->eth_getFilterLogs($result_filter);
foreach ($logs as $key => $value) {
/*
сравниваем первый элемент масива topics, в нем хранится хэш имени события и списка типов переменных
строка: PaymentOrder(uint256,address,uint256) тип хэштрования: Keccak-256 (для получения хэша я воспользовался онлайн сервисом)
в остальнх элементах topics хранятся проиндексированные параметры события
*/
if (strcasecmp($value->{'topics'}[0], "0x"."c84883193d3a69d991d82f61928c06e179b647e413da4c20be80d8c0314c2e1b") == 0) {
echo "Payment order id:".hexdec($value->{'topics'}[1]);
/*
в элементе data хранятся остальные параметры события
склеенные по 32 байта
*/
$data=str_split(substr($value->{'data'}, 2),64);
echo " volume:".hexdec($data[1])*$rate." ETH";
echo "<br>";
}
}
?>