diff --git a/.gitignore b/.gitignore index c84cba0..9fceb0a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ protected/qrcodes/* protected/uploads/* *.log *.db + +version.txt diff --git a/README.md b/README.md index f087897..f899887 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -# Napay POS - Point of sale +# Fidelity POS +This is a fork of Napay POS + +A POS (Point of sale) is all you need to start earning bitcoins. [![Screenshot of NaPay PWA app](css/images/screenshot.png)](https://napay.napoliblockchain.it) -A POS (Point of sale) is all you need to start earning bitcoins. ## Authors @@ -10,14 +12,14 @@ Made with ❤️ by [Sergio Casizzone](https://sergiocasizzone.altervista.org) **Features** - - [x] Mobile & Desktop Layout - - [x] Bitcoin Transactions list & details - - [x] Token (TTS) Transactions list & details - - [x] Bitcoin (Lightning) & Token receive - - [x] Print receipts +- [x] Mobile & Desktop Layout +- [x] Bitcoin Transactions list & details +- [x] Token (TTS) Transactions list & details +- [x] Bitcoin (Lightning) & Token receive +- [x] Print receipts **PWA** - - [x] Service Worker - - [x] indexedDB - - [x] static precache & dynamic cache +- [x] Service Worker +- [x] indexedDB +- [x] static precache & dynamic cache diff --git a/css/favicon.ico b/css/favicon.ico index 6f279a0..17c16d7 100644 Binary files a/css/favicon.ico and b/css/favicon.ico differ diff --git a/css/images/BG.svg b/css/images/BG.svg deleted file mode 100644 index 82209a3..0000000 --- a/css/images/BG.svg +++ /dev/null @@ -1,1023 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/css/images/anb-chiaro.png b/css/images/anb-chiaro.png deleted file mode 100644 index 6bedbd9..0000000 Binary files a/css/images/anb-chiaro.png and /dev/null differ diff --git a/css/images/anb-dark.png b/css/images/anb-dark.png deleted file mode 100644 index cbe2013..0000000 Binary files a/css/images/anb-dark.png and /dev/null differ diff --git a/css/images/anb-trasparente-single.png b/css/images/anb-trasparente-single.png deleted file mode 100644 index d71c93a..0000000 Binary files a/css/images/anb-trasparente-single.png and /dev/null differ diff --git a/css/images/anb-trasparente-single2.png b/css/images/anb-trasparente-single2.png deleted file mode 100644 index cb4457c..0000000 Binary files a/css/images/anb-trasparente-single2.png and /dev/null differ diff --git a/css/images/anb-trasparente.png b/css/images/anb-trasparente.png deleted file mode 100644 index 4a5f163..0000000 Binary files a/css/images/anb-trasparente.png and /dev/null differ diff --git a/css/images/anb-trasparente.xcf b/css/images/anb-trasparente.xcf deleted file mode 100644 index 7ef54d1..0000000 Binary files a/css/images/anb-trasparente.xcf and /dev/null differ diff --git a/css/images/anb-trasparente1.png b/css/images/anb-trasparente1.png deleted file mode 100644 index a23a28c..0000000 Binary files a/css/images/anb-trasparente1.png and /dev/null differ diff --git a/css/images/anb-trasparente2.png b/css/images/anb-trasparente2.png deleted file mode 100644 index b05cf65..0000000 Binary files a/css/images/anb-trasparente2.png and /dev/null differ diff --git a/css/images/bitcoin_e_comune.png b/css/images/bitcoin_e_comune.png deleted file mode 100644 index 91061cf..0000000 Binary files a/css/images/bitcoin_e_comune.png and /dev/null differ diff --git a/css/images/bitcoin_e_comune.svg b/css/images/bitcoin_e_comune.svg deleted file mode 100644 index f47a978..0000000 --- a/css/images/bitcoin_e_comune.svg +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bitcoin - - - bitcoin - - - - - ACCEPTED HERE - - - ACCEPTED HERE - - - - diff --git a/css/images/favicon.ico b/css/images/favicon.ico index 6f279a0..17c16d7 100644 Binary files a/css/images/favicon.ico and b/css/images/favicon.ico differ diff --git a/css/images/favicon.png b/css/images/favicon.png deleted file mode 100644 index d255a9d..0000000 Binary files a/css/images/favicon.png and /dev/null differ diff --git a/css/images/logo.png b/css/images/logo.png new file mode 100644 index 0000000..6dbb089 Binary files /dev/null and b/css/images/logo.png differ diff --git a/css/images/logo_comune_trasparente.png b/css/images/logo_comune_trasparente.png deleted file mode 100644 index ba63352..0000000 Binary files a/css/images/logo_comune_trasparente.png and /dev/null differ diff --git a/css/images/logo_napoli_comune.png b/css/images/logo_napoli_comune.png deleted file mode 100644 index 133715a..0000000 Binary files a/css/images/logo_napoli_comune.png and /dev/null differ diff --git a/css/images/logocomune.png b/css/images/logocomune.png deleted file mode 100644 index 30b721b..0000000 Binary files a/css/images/logocomune.png and /dev/null differ diff --git a/css/images/logonapay.png b/css/images/logonapay.png deleted file mode 100644 index 7d472ee..0000000 Binary files a/css/images/logonapay.png and /dev/null differ diff --git a/css/images/napay-bianco.png b/css/images/napay-bianco.png deleted file mode 100644 index 794a7d6..0000000 Binary files a/css/images/napay-bianco.png and /dev/null differ diff --git a/css/images/napay-yellow.png b/css/images/napay-yellow.png deleted file mode 100644 index 4a8d9d1..0000000 Binary files a/css/images/napay-yellow.png and /dev/null differ diff --git a/css/images/npay-anb-trasparente.png b/css/images/npay-anb-trasparente.png deleted file mode 100644 index 2b8a9f6..0000000 Binary files a/css/images/npay-anb-trasparente.png and /dev/null differ diff --git a/css/images/npay-anb-trasparente0.png b/css/images/npay-anb-trasparente0.png deleted file mode 100644 index 2b8a9f6..0000000 Binary files a/css/images/npay-anb-trasparente0.png and /dev/null differ diff --git a/css/images/npay-anb.png b/css/images/npay-anb.png deleted file mode 100644 index 3e4bfbf..0000000 Binary files a/css/images/npay-anb.png and /dev/null differ diff --git a/css/images/npay-anb.xcf b/css/images/npay-anb.xcf deleted file mode 100644 index 0b1b22f..0000000 Binary files a/css/images/npay-anb.xcf and /dev/null differ diff --git a/css/images/npay-chiaro.png b/css/images/npay-chiaro.png deleted file mode 100644 index ca5ad21..0000000 Binary files a/css/images/npay-chiaro.png and /dev/null differ diff --git a/css/images/npay-chiaro.xcf b/css/images/npay-chiaro.xcf deleted file mode 100644 index 2a465b4..0000000 Binary files a/css/images/npay-chiaro.xcf and /dev/null differ diff --git a/css/images/npay-trasparente.png b/css/images/npay-trasparente.png deleted file mode 100644 index 78bd630..0000000 Binary files a/css/images/npay-trasparente.png and /dev/null differ diff --git a/css/images/parthenope.png b/css/images/parthenope.png deleted file mode 100644 index 31233c3..0000000 Binary files a/css/images/parthenope.png and /dev/null differ diff --git a/css/images/vesuvio.jpg b/css/images/vesuvio.jpg deleted file mode 100644 index 646858b..0000000 Binary files a/css/images/vesuvio.jpg and /dev/null differ diff --git a/index.php b/index.php index fdcf65d..f662d51 100644 --- a/index.php +++ b/index.php @@ -1,7 +1,9 @@ { - show_easy_numpad(); - // }); -}); - -function show_easy_numpad() { - var easy_numpad = ` -
-
-
- -

0

- -

0

-
- -
- - - - - - - - - - - - - - - - - - - - - - -
789
456
123
0.C
-
- - - -
-
-
-
- `; - $('.card-body').append(easy_numpad); -} - -function easy_numpad_close() { - $('#easy-numpad-frame').remove(); -} - -function update_bitcoin(){ - var quote = $('#ebc_price').text(); - if (isNaN(quote)) - return true; - - var base = $('#easy-numpad-output').text(); - - var result = ebc_arrotonda( base / quote , 8); - $('#easy-numpad-output-bitcoin').text( result ); - -} - -function easynum(num) { - event.stopPropagation(); - - navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate; - if (navigator.vibrate) { - navigator.vibrate(60); - } - - var easy_num_text = $('#easy-numpad-output').text(); - - if (isNaN(num)){ - if(!easy_num_text.includes('.')) - //$('#easy-numpad-output').text(easy_num_text+num); - $('#easy-numpad-output').append(num); - }else{ - if (eval(easy_num_text) == 0){ - if (easy_num_text.includes('.')) - $('#easy-numpad-output').append(num); - else if (num != 0) - $('#easy-numpad-output').text(num); - } - else - $('#easy-numpad-output').append(num); - } - - - update_bitcoin(); - -} -function easy_numpad_del() { - event.preventDefault(); - var easy_numpad_output_val = $('#easy-numpad-output').text(); - var easy_numpad_output_val_deleted = easy_numpad_output_val.slice(0, -1); - if (easy_numpad_output_val_deleted == '') - easy_numpad_output_val_deleted = 0; - $('#easy-numpad-output').text(easy_numpad_output_val_deleted); - $('#bitpay-pairing__message').text(''); - update_bitcoin(); -} -// function easy_numpad_clear() { -// event.preventDefault(); -// $('#easy-numpad-output').text(""); -// update_bitcoin(); -// } -//function easy_numpad_cancel() { -// event.preventDefault(); -// $('#easy-numpad-frame').remove(); -//} -function ebc_arrotonda(numero,x) { - var number = Math.round(numero*Math.pow(10,x))/Math.pow(10,x); - return Number(number.toString().substring(0,11)); -} diff --git a/jquery/___numpad/easy-numpad.min.js b/jquery/___numpad/easy-numpad.min.js deleted file mode 100644 index e69de29..0000000 diff --git a/manifest.json b/manifest.json index c1f67d8..50bb15b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { - "name": "Napay POS - Point of sale", - "short_name": "Napay POS", + "name": "Fidelity POS", + "short_name": "Fidelity POS", "icons": [ { "src": "src/images/icons/app-icon-48x48.png", @@ -44,7 +44,7 @@ "orientation": "portrait-primary", "background_color": "#fff", "theme_color": "#3f51b5", - "description": "A web application using Bitcoin & Naples Payment Token, implementing a lot of PWA love.", + "description": "A web application using ERC20 Token, implementing a lot of PWA love.", "dir": "ltr", "lang": "it-IT" } diff --git a/protected/commands/ReceiveCommand.php b/protected/commands/ReceiveCommand.php index 833e905..b832039 100644 --- a/protected/commands/ReceiveCommand.php +++ b/protected/commands/ReceiveCommand.php @@ -1,4 +1,15 @@ logfilehandle; } + //scrive a video e nel file log le informazioni richieste private function log($text){ $save = new Save; - $save->WriteLog('pos','commands','receive',$text); + $save->WriteLog('pos','commands','receive', $text); + echo "\r\n" .date('Y/m/d h:i:s a - ', time()) .$text; } public function actionIndex($id){ @@ -71,15 +84,6 @@ public function actionIndex($id){ $seconds = 1; $events = true; - // preparo il log file - $nomeLogFile = Yii::app()->basePath."/log/pos-receive.log"; - // if (!is_writable($nomeLogFile)){ - // chmod($nomeLogFile, 0755); // octal; correct value of mode - // } - - //non c'è output, pertanto salvo gli errori nel log file - $myfile = fopen($nomeLogFile, "a"); - $this->setLogFile($myfile); $this->log("Start Check invoice #: $id"); //carico l'invoice @@ -92,21 +96,20 @@ public function actionIndex($id){ while(true){ $ipnflag = false; - if ($invoice->status == 'new'){ //se il valore è new proseguo + if ($invoice->status == 'new' || $invoice->status == 'expired'){ //se il valore è new proseguo // cerco le transazioni su bolt_tokens in pending $criteria=new CDbCriteria; - $criteria->compare('type','token',true); + $criteria->compare('type','token'); //$criteria->compare('status','new',true); - $criteria->compare('item_desc','wallet',true); - $criteria->compare('to_address',$invoice->to_address,true); + $criteria->compare('item_desc','wallet'); + $criteria->compare('to_address',$invoice->to_address); $criteria->addCondition("invoice_timestamp > " .$invoice->invoice_timestamp); $criteria->addCondition("blocknumber > " .$invoice->blocknumber); + $criteria->compare('token_price',$invoice->token_price,true); // false -> valore identico $transactions = Tokens::model()->findAll($criteria); - - // echo '
'.print_r($transactions,true).'
'; - $this->log("Ricerca Transazioni: ".'
'.print_r($transactions,true).'
'); + //echo '
'.print_r($transactions,true).'
'; //exit; if (!empty($transactions)) @@ -117,6 +120,7 @@ public function actionIndex($id){ $this->log("Transazione n. $transaction->id_token"); if ($transaction->status <> 'new'){ $this->log("Transazione n. $transaction->id_token COMPLETATA."); + $this->log('
'.print_r($transaction->attributes,true).'
'); $invoice->status = $transaction->status; $invoice->token_ricevuti = $transaction->token_price; $invoice->from_address = $transaction->from_address; @@ -144,7 +148,7 @@ public function actionIndex($id){ } }//foreach loop } - if ($expiring_seconds < 0){//invoice expired + if ($ipnflag === false && $expiring_seconds < 0){//invoice expired $invoice->status = 'expired'; $ipnflag = true; } @@ -156,7 +160,9 @@ public function actionIndex($id){ #fwrite($this->getLogFile(), date('Y/m/d h:i:s a', time()) . " :
".print_r($tokens->attributes,true)."
\n"); //echo '
'.print_r($invoice->attributes,true).'
'; if ($invoice->save()){ - $this->log("End : invoice #: $id, Status: $invoice->status, Received: $invoice->token_ricevuti"); + $this->log("Invoice n. $invoice->id_token SALVATA."); + $this->log('
'.print_r($invoice->attributes,true).'
'); + //$this->log("End : invoice #: $id, Status: $invoice->status, Received: $invoice->token_ricevuti"); $this->sendIpn($invoice->attributes); }else{ $this->log("Error : Cannot save invoice #. $id, Status: $invoice->status."); @@ -166,19 +172,15 @@ public function actionIndex($id){ } //conto alla rovescia fino alla scadenza dell'invoice - #fwrite($this->getLogFile(), date('Y/m/d h:i:s a', time()) . " : '.$ReceivingType.' Status: ".$tokens->status.", Seconds: ".$expiring_seconds."\n"); + $this->log("Invoice: $id, Status: ".$invoice->status.", Seconds: ".$expiring_seconds."\n"); //echo chr(32).$expiring_seconds; - $this->log("remaining seconds... $expiring_seconds"); + // $this->log("remaining seconds... $expiring_seconds"); $expiring_seconds --; sleep(1); } } private function sendIpn($ipn){ - $nomeLogFile = Yii::app()->basePath."/log/pos-ipn.log"; - $myfile = fopen($nomeLogFile, "a"); - $this->setLogFile($myfile); - // $tokens = (object) $ipn; if (true === empty($tokens)) { @@ -205,7 +207,7 @@ private function sendIpn($ipn){ Push::Send($save->Notification($notification,true),'dashboard'); //ADESSO POSSO USCIRE CON UN MESSAGGIO POSITIVO ;^) - $this->log("IPN received for Invoice #: ".crypt::Encrypt($tokens->id_token).", Status=" .$tokens->status.", Price=". $tokens->token_price); + $this->log("IPN received for Invoice #: ".crypt::Encrypt($tokens->id_token).", Status=" .$tokens->status.", Price=". $tokens->token_price.", Received: ".$tokens->token_ricevuti); } } ?> diff --git a/protected/components/POSIdentity.php b/protected/components/POSIdentity.php index b9e27be..e8d8d07 100644 --- a/protected/components/POSIdentity.php +++ b/protected/components/POSIdentity.php @@ -8,7 +8,6 @@ class POSIdentity extends CUserIdentity { const ERROR_USERNAME_NOT_MEMBER = 4; - const ERROR_USERNAME_NOT_PAYER = 6; private $_id; /** @@ -50,39 +49,6 @@ public function authenticatePOS() $merchants=Merchants::model()->findByPk($pos->id_merchant); $users=Users::model()->findByPk($merchants->id_user); - //$NomePOS .= chr(32).$stores->denomination; - //$NomePOS .= chr(32).$merchants->denomination; - - /* - * VERIFICA SE IL SOCIO HA PAGATO LA QUOTA D'ISCRIZIONE - */ - $timestamp = time(); - $criteria = new CDbCriteria(); - $criteria->compare('id_user',$merchants->id_user, false); - - $provider = Pagamenti::model()->Paid()->OrderByIDDesc()->findAll($criteria); - if ($provider === null){ - //$expiration_membership = $timestamp; - $this->errorCode=self::ERROR_USERNAME_NOT_PAYER; - $save->WriteLog('pos','useridentity','authenticate','User not payer: '.$this->username); - return !$this->errorCode; - }else{ - $provider = (array) $provider; - if (count($provider) == 0) - $expiration_membership = 1; - else - $expiration_membership = strtotime($provider[0]->data_scadenza); - } - // scadenza entro il 31 gennaio per provvedere all'iscrizione (se la data_scadenza - // è al 31 dicembre) - // temporaneamente posticipato al 28 febbraio - $expiration_membership += (31+28) *24*60*60; - if ($expiration_membership <= $timestamp){ - $this->errorCode=self::ERROR_USERNAME_NOT_MEMBER; - $save->WriteLog('pos','useridentity','authenticate','User not member: '.$this->username); - return !$this->errorCode; - } - $save->WriteLog('pos','useridentity','authenticate','User '.$this->username. ' logged in.'); $this->setState('objUser', array( diff --git a/protected/config/.gitignore b/protected/config/.gitignore index 7e9a3bc..5cc18ed 100644 --- a/protected/config/.gitignore +++ b/protected/config/.gitignore @@ -1,2 +1,3 @@ main.php database.php +console.php diff --git a/protected/config/console.php b/protected/config/console.php index 8bbe312..bc50355 100644 --- a/protected/config/console.php +++ b/protected/config/console.php @@ -1,9 +1,10 @@ dirname(__FILE__).DIRECTORY_SEPARATOR.'..', 'name'=>'My Console Application', @@ -31,20 +32,6 @@ ), ), ), - // MIE CLASSI - 'webRequest'=>require($libsPath.'/webRequest/webRequest.php'), - 'crypt'=>require($libsPath.'/crypt/crypt.php'), - 'NAPay'=>require($libsPath.'/NAPay/Autoloader.php'), - 'Utils'=>require($libsPath.'/Utils/Utils.php'), - 'eth'=>require($libsPath.'/ethereum/eth.php'), - - //'Settings'=>require($libsPath.'/NAPay/Settings.php'), - // 'Notifi'=>require(dirname(__FILE__).'../../extensions/web-app/Notifi.php'), - // 'Push'=>require(dirname(__FILE__).'../../extensions/web-app/Push.php'), - // 'SaveModels'=>require(dirname(__FILE__).'../../extensions/web-app/SaveModels.php'), - // 'Save'=>require(dirname(__FILE__).'../../extensions/web-app/Save.php'), - // 'eth'=>require(dirname(__FILE__).'../../extensions/web-app/eth.php'), - ), 'params'=>array( 'libsPath'=>$libsPath, diff --git a/protected/config/console.php.example b/protected/config/console.php.example new file mode 100644 index 0000000..bc50355 --- /dev/null +++ b/protected/config/console.php.example @@ -0,0 +1,39 @@ +dirname(__FILE__).DIRECTORY_SEPARATOR.'..', + 'name'=>'My Console Application', + + // preloading 'log' component + 'preload'=>array('log'), + // autoloading model and component classes + 'import'=>array( + 'application.models.*', + 'application.components.*', + ), + + // application components + 'components'=>array( + + // database settings are configured in database.php + 'db'=>require(dirname(__FILE__).'/database.php'), + + 'log'=>array( + 'class'=>'CLogRouter', + 'routes'=>array( + array( + 'class'=>'CFileLogRoute', + 'levels'=>'error, warning', + ), + ), + ), + ), + 'params'=>array( + 'libsPath'=>$libsPath, + ), +); diff --git a/protected/config/database.php.example b/protected/config/database.php.example index 731e871..d222359 100644 --- a/protected/config/database.php.example +++ b/protected/config/database.php.example @@ -4,6 +4,6 @@ return array( 'emulatePrepare' => true, 'charset' => 'utf8', 'username' => 'root', - 'connectionString' => 'mysql:host=127.0.0.1;port=3306;dbname=', + 'connectionString' => 'mysql:host=localhost;port=3306;dbname=', 'password' => '' ); diff --git a/protected/config/main.php.example b/protected/config/main.php.example index 2a249a5..34b1c2f 100644 --- a/protected/config/main.php.example +++ b/protected/config/main.php.example @@ -1,18 +1,18 @@ $timeOutSeconds, 'shortName'=>$shortName, 'blockchainCheck'=>$blockchainCheck, - 'blockchainEthereum'=>$blockchainEthereum, 'TokenImage'=>$TokenImage, 'TokenNameComplete'=>$TokenNameComplete, diff --git a/protected/controllers/InvoicesController.php b/protected/controllers/InvoicesController.php index 380e45d..9c05b8b 100644 --- a/protected/controllers/InvoicesController.php +++ b/protected/controllers/InvoicesController.php @@ -1,4 +1,14 @@ params['libsPath'] . '/ethereum/web3/vendor/autoload.php'; use Web3\Web3; @@ -39,9 +49,6 @@ public function accessRules() return array( array('allow', // allow authenticated user to perform 'create' and 'update' actions 'actions'=>array( - 'Btcpayserver', - 'Bitpay', - 'Coingate', 'token' ), 'users'=>array('@'), @@ -63,19 +70,6 @@ public function accessRules() */ public function actionToken() { - // TEST SCRIPT - // $cmd = Yii::app()->basePath.DIRECTORY_SEPARATOR.'yiic receive --id='.crypt::Encrypt(658); - // Utils::execInBackground($cmd); - // //finalmente ritorno all'app e restituisco l'url con il qr-code della transazione da pagare!!! - // $send_json = array( - // 'success'=> 1, - // 'url' => Yii::app()->createUrl('qrcode/index',array( - // 'id'=>crypt::Encrypt(658), - // 'id_pos'=>crypt::Encrypt(20), // serve per recuperare le info del POS, visto che ormai il wallet è scollegato dal merchant id - // )), - // ); - // echo CJSON::encode($send_json); - // exit; if (true === isset($_POST['amount']) && trim($_POST['amount']) <> 0) { $amount = (float)trim($_POST['amount']); @@ -110,17 +104,6 @@ public function actionToken() exit; } - //Carico i parametri - // $settings=Settings::load(); //$settings=SettingsNapos::model()->findByPk(1); // la PK è 1 per i settings dell'applicazione Napos - // if ($settings === null){//} || empty($settings->poa_port)){ - // echo CJSON::encode(array("error"=>'Errore: I parametri di configurazione Token non sono stati trovati')); - // exit; - // } - - // se la connessione al nodo poa è attiva proseguo - //if( webRequest::url_test( $settings->poa_url ) ) { - // $web3 = new Web3($settings->poa_url); - // $web3 = new Web3(WebApp::getPoaNode()); $poaNode = WebApp::getPoaNode(); if (!$poaNode){ $save = new Save; @@ -130,7 +113,7 @@ public function actionToken() "error"=>'Error: All Nodes are down.', ); }else{ - $web3 = new Web3($poaNode); + $web3 = new Web3($poaNode); // blocco in cui presumibilmente avviene la transazione $block = null; @@ -148,9 +131,10 @@ public function actionToken() $invoice_timestamp = $timestamp; //calcolo expiration time - $storeSettings = Settings::loadStore($pos->id_store); - - $totalseconds = $storeSettings->invoice_expiration * 60; //invoice_expiration è in minuti, * 60 lo trasforma in secondi + // $storeSettings = Settings::loadStore($pos->id_store); + // $totalseconds = $storeSettings->invoice_expiration * 60; //invoice_expiration è in minuti, * 60 lo trasforma in secondi + $storeSettings = Settings::load(); + $totalseconds = $storeSettings->poa_expiration * 60; //invoice_expiration è in minuti, * 60 lo trasforma in secondi $expiration_timestamp = $timestamp + $totalseconds; //DEFAULT = 15 MINUTES // TODO: al momento il token è peggato 1/1 sull'euro @@ -182,7 +166,7 @@ public function actionToken() $save = new Save; $invoice = $save->PosInvoices($attributes); - // echo '
'.print_r($tokens,true).'
'; + // echo '
'.print_r($invoice,true).'
'; // exit; $memo = 'Pagamento a '.$pos->denomination; @@ -209,6 +193,8 @@ public function actionToken() 'price' => $rate * $amount, 'deleted' => 0, ); + + // echo '
'.print_r($notification,true).'
'; $save = new Save; Push::Send($save->Notification($notification,true),'dashboard'); @@ -225,631 +211,6 @@ public function actionToken() )), ); } - // }else{ - // $send_json = array( - // 'success'=> 0, - // "error"=>'Errore: La connessione alla POA sembra non funzionare.', - // ); - // } echo CJSON::encode($send_json); } - - - - /** - * action BTCPAY SERVER Transaction - * @param _POST['amount'] the amount to be send - * @param _POST['id_pos'] the pos creating invoice - * @return URL con la pagina per visualizzare il qrcode - */ - public function actionBtcpayserver() - { - $save = new Save; - - if (true === isset($_POST['amount']) && trim($_POST['amount']) != 0) { - $amount = trim($_POST['amount']); - } else { - echo CJSON::encode(array("error"=>"Amount invalid!")); - exit; - } - //echo $url; - //exit; - - $pos = new Pos; - $pos=Pos::model()->findByPk($_POST['id_pos']); - if($pos===null){ - echo CJSON::encode(array("error"=>"The requested ID Pos does not exist!")); - exit; - } - $pairings = Pairings::model()->findByAttributes(array('id_pos'=>$pos->id_pos)); - - // carico l'estensione - require_once Yii::app()->params['libsPath'] . '/BTCPay/BTCPay.php'; - - // Effettuo il login senza dati - $BTCPay = new BTCPay(null,null); - // imposto l'url che è associato a ciascun merchant - $merchants = Merchants::model()->findByPk($pos->id_merchant); - $BTCPay->setBTCPayUrl(Settings::loadUser($merchants->id_user)->blockchainAddress); - - // Carico l'URL del Server BTC direttamente dalla CLASSE - $BPSUrl = $BTCPay->getBTCPayUrl(); - - /** - * AUTOLOADER GATEWAYS - */ - $btcpayserver = Yii::app()->params['libsPath'] . '/gateways/btcpayserver/Btcpay/Autoloader.php'; - if (true === file_exists($btcpayserver) && true === is_readable($btcpayserver)){ - require_once $btcpayserver; - \Btcpay\Autoloader::register(); - } else { - throw new Exception('BtcPay Server Library could not be loaded'); - exit; - } - - /** - * To load up keys that you have previously saved, you need to use the same - * storage engine. You also need to tell it the location of the key you want - * to load. - */ - - $folder = str_replace("htdocs\pos","htdocs\\napay",Yii::app()->basePath . '/privatekeys/'); - $folder = str_replace("var/www/pos","var/www/napay",$folder); - - - //verifico esistenza coppia chiavi public/private - if (!file_exists($folder.$pairings->sin.".pub") ){ - $save->WriteLog('pos','invoice','Btcpayserver','The requested Public Key does not exist on this Server.',true); - } - - //verifico esistenza coppia chiavi public/private - if (!file_exists($folder.$pairings->sin.".pri") ){ - $save->WriteLog('pos','invoice','Btcpayserver','The requested Private Key does not exist on this Server.',true); - } - - //CREO UNA NUOVA TRANSAZIONE SU DB PER PERMETTERNE IL RECUPERO PER LA STAMPA ricevuta - $timestamp = time(); - $attributes = array( - 'id_pos' => $_POST['id_pos'], - 'id_merchant' => $pos->id_merchant, - 'status' => 'new', //è sicuramente new - 'btc_price' => 0, - 'price' => $_POST['amount'], - 'currency' => 'EUR', - 'item_desc' => '', - 'item_code' => '', - 'id_invoice_bps' => '', - 'invoice_timestamp' => $timestamp, - 'expiration_timestamp' => $timestamp, - 'current_tempo' => $timestamp, - 'btc_paid' => 0, - 'rate' => 0, - 'bitcoin_address' => '', - 'token' => '', - 'btc_due' => 0, - 'satoshis_perbyte' => 0, - 'total_fee' => 0, - ); - $transaction = $save->Transaction($attributes,'new'); //viene restituito un oggetto non un array - - $storageEngine = new \Btcpay\Storage\EncryptedFilesystemStorage('mc156MdhshuUYTF5365'); - $privateKey = $storageEngine->load($folder.$pairings->sin.'.pri'); - $publicKey = $storageEngine->load($folder.$pairings->sin.'.pub'); - - $client = new \Btcpay\Client\Client(); - $adapter = new \Btcpay\Client\Adapter\CurlAdapter(); - - $client->setPrivateKey($privateKey); - $client->setPublicKey($publicKey); - $client->setUri($BPSUrl); - $client->setAdapter($adapter); - // --------------------------- - - /** - * The last object that must be injected is the token object. - */ - $token = new \Btcpay\Token(); - $token->setToken(crypt::Decrypt($pairings->token)); // UPDATE THIS VALUE - $token->setFacade('merchant'); // BTCPAYSERVER :::SERGIO CASIZZONE - - /** - * Token object is injected into the client - */ - $client->setToken($token); - - /** - * This is where we will start to create an Invoice(for bitcpay and transaction for Napos) object, make sure to check - * the InvoiceInterface for methods that you can use. - */ - $invoice = new \Btcpay\Invoice(); - - $buyer = new \Btcpay\Buyer(); - // $buyer - // ->setEmail($_POST['email']); - - // Add the buyers info to invoice - $invoice->setBuyer($buyer); - $invoice->setFullNotifications(true); //serve per l'ipn - $invoice->setExtendedNotifications(true); //serve per l'ipn - - /** - * Item is used to keep track of a few things - */ - //PRODUCT INFORMATIONS - //item code - //item description - - $item = new \Btcpay\Item(); - $item - ->setCode($_POST['id_pos']) - ->setDescription(substr($pairings->label,0,20)) - ->setPrice($_POST['amount']); - - $invoice->setItem($item); - - /** - * BitPay supports multiple different currencies. Most shopping cart applications - * and applications in general have defined set of currencies that can be used. - * Setting this to one of the supported currencies will create an invoice using - * the exchange rate for that currency. - * - * @see https://test.bitpay.com/bitcoin-exchange-rates for supported currencies - */ - $invoice->setCurrency(new \Btcpay\Currency('EUR')); - - // Configure the rest of the invoice - //come order ID salvo l'id della transazione in locale - $redirectUrl = 'https://'.$_SERVER['HTTP_HOST'].Yii::app()->createUrl('keypad/index',array('id'=>crypt::Encrypt($transaction->id_transaction),'action'=>'btcpay')); - #echo $redirectUrl; - - // per distinguere test da produzione... - if (gethostname() == 'blockchain1'){ - $URLIpn = 'https://napay.napoliblockchain.tk'.Yii::app()->createUrl('ipn/btcpayserver'); - }elseif (gethostname()=='CGF6135T' || gethostname()=='NUNZIA'){ // SERVE PER LE PROVE IN UFFICIO - $URLIpn = 'https://'.$_SERVER['HTTP_HOST'].Yii::app()->createUrl('ipn/btcpayserver'); - }else{ - $URLIpn = 'https://napay.napoliblockchain.it'.Yii::app()->createUrl('ipn/btcpayserver'); - } - // echo "
".print_r($URLIpn,true)."
"; - // exit; - $invoice - ->setOrderId(crypt::Encrypt($transaction->id_transaction)) - //->setNotificationEmail('') - // You will receive IPN's at this URL, should be HTTPS for security purposes! - ->setNotificationUrl($URLIpn) - //->setRedirectUrl($_POST['redirectUrl']) - ->setRedirectUrl($redirectUrl); - - /** - * Updates invoice with new information such as the invoice id and the URL where - * a customer can view the invoice. - */ - - // echo "
".print_r($invoice,true)."
"; - // exit; - - - try { - $client->createInvoice($invoice); - } catch (\Exception $e) { - $body = $this->getJsonBody($client->getResponse()); - echo CJSON::encode($body); - exit(1); // We do not want to continue if something went wrong - } - - $body = $this->getJsonBody($client->getResponse()); - $result = $body['data']; - - // aggiorno la transactions_info - $cryptoInfoRestApi = null; - $save = new Save; - $cryptoInfo = $save->CryptoInfo($transaction->id_transaction, $invoice->getCryptoInfo()); - // echo '
'.print_r($cryptoInfo,true).'
'; - // exit; - if (!empty($cryptoInfo)){ - foreach ($cryptoInfo as $index => $restItem){ - $cryptoInfoRestApi[$index]['cryptoCode'] = $restItem->cryptoCode; - $cryptoInfoRestApi[$index]['paymentType'] = $restItem->paymentType; - $cryptoInfoRestApi[$index]['rate'] = $restItem->rate; - $cryptoInfoRestApi[$index]['paid'] = $restItem->paid; - $cryptoInfoRestApi[$index]['price'] = $restItem->price; - $cryptoInfoRestApi[$index]['due'] = $restItem->due; - $cryptoInfoRestApi[$index]['txId'] = $restItem->txId; - $cryptoInfoRestApi[$index]['receivedDate'] = $restItem->received; - $cryptoInfoRestApi[$index]['value'] = $restItem->value; - $cryptoInfoRestApi[$index]['address'] = $restItem->destination; - } - } - - $return = (object) [ - 'url' => $result['url'], - 'status' => $result['status'], - 'btcPrice' => $result['btcPrice'], - 'rate' => $result['rate'], - 'id' => $result['id'], - 'invoiceTime' => $result['invoiceTime'], - 'expirationTime' => $result['expirationTime'], - 'cryptoInfo' => $cryptoInfoRestApi, - ]; - - - //AGGIORNA ADESSO la transazione su DB CON I DATI RICEVUTI DA _BTCSERVER_ - $attributes = array( - 'id_transaction' => $transaction->id_transaction, - //'id_pos' => $_POST['id_pos'], - //'id_merchant' => $_POST['id_merchant'], - 'status' => $invoice->getStatus(), - 'btc_price' => $invoice->getBtcPrice(), - //'price' => $_POST['amount'], - //'currency' => 'EUR', - 'item_desc' => $invoice->getItemDesc(), - 'item_code' => $invoice->getItemCode(), - 'id_invoice_bps' => $invoice->getId(), - 'invoice_timestamp' => substr($invoice->getInvoiceTime(),0,-3), - 'expiration_timestamp' => substr($invoice->getExpirationTime(),0,-3), - 'current_tempo' => substr($invoice->getCurrentTime(),0,-3), - 'btc_paid' => $invoice->getBtcPaid(), - 'rate' => $invoice->getRate(), - 'bitcoin_address' => $result['bitcoinAddress'], - 'token' => (string) $invoice->getToken(), - 'btc_due' => $result['btcDue'], - 'satoshis_perbyte' => $result['minerFees']['BTC']['satoshisPerByte'], - 'total_fee' => $result['minerFees']['BTC']['totalFee'], - ); - - $transaction = $save->Transaction($attributes,'update'); //viene restituito un oggetto non un array - - $notification = array( - 'type_notification' => 'invoice', - 'id_user' => Merchants::model()->findByPk($transaction->id_merchant)->id_user, - 'id_tocheck' => $transaction->id_transaction, - 'status' => 'new', - 'description' => 'You generated a new invoice.', - // La URL non deve comprendere l'hostname in quanto deve essere raggiungibile da più applicazioni - 'url' => 'index.php?r=transactions/view&id='.crypt::Encrypt($transaction->id_transaction), - 'timestamp' => $timestamp, - 'price' => $_POST['amount'], - 'deleted' => 0, - ); - - Push::Send($save->Notification($notification,true),'dashboard'); - - //finalmente ritorno all'app e restituisco l'url con il qr-code della transazione da pagare!!! - $send_json = array( - 'url' => $invoice->getUrl(), - ); - echo CJSON::encode($send_json); - } - - //recupera lo streaming json dal contenuto txt del body - private function getJsonBody($response) - { - $start = strpos($response,'{',0); - $substr = substr($response,$start); - return json_decode($substr, true); - } - - /** - * action BITPAY Transaction - */ - // public function actionBitpay() - // { - // if (true === isset($_POST['amount']) && trim($_POST['amount']) != 0) { - // $amount = trim($_POST['amount']); - // } else { - // echo CJSON::encode(array("error"=>"Amount invalid!")); - // exit; - // } - // - // $pos = new Pos; - // $pos=Pos::model()->findByPk($_POST['id_pos']); - // if($pos===null){ - // echo CJSON::encode(array("error"=>"The requested ID Pos does not exist!")); - // exit; - // } - // $pairings = Pairings::model()->findByAttributes(array('id_pos'=>$pos->id_pos)); - // - // /** - // * AUTOLOADER GATEWAYS - // */ - // $bitpay = Yii::app()->basePath . '/extensions/gateways/bitpay/Bitpay/Autoloader.php'; - // if (true === file_exists($bitpay) && - // true === is_readable($bitpay)) - // { - // require_once $bitpay; - // \Bitpay\Autoloader::register(); - // } else { - // throw new Exception('Bitpay Server Library could not be loaded'); - // exit; - // } - // //Yii::app()->user->setState("agenzia_entrate", Yii::app()->params['agenziaentrate']); - // - // /** - // * To load up keys that you have previously saved, you need to use the same - // * storage engine. You also need to tell it the location of the key you want - // * to load. - // */ - // //$folder = Yii::app()->basePath . '/privatekeys/bitpay-'; - // //$folder = $_SERVER["DOCUMENT_ROOT"].'/../npay/protected/privatekeys/bitpay-'; - // - // /** NON AGISCO PIù SU PATH WWW, MA SULLE CARTELLE - // * Visto che paolo ha modificato il nome delle cartelle da npay a napay su .tk come faccio ad accedervi? - // */ - // if (gethostname()=='blockchain1'){ - // $folder = $_SERVER["DOCUMENT_ROOT"].'/../napay/protected/privatekeys/bitpay-'; - // }elseif (gethostname()=='CGF6135T'){ // SERVE PER LE PROVE IN UFFICIO - // $folder = $_SERVER["DOCUMENT_ROOT"].'npay/protected/privatekeys/bitpay-'; - // }else{ - // $folder = $_SERVER["DOCUMENT_ROOT"].'/../npay/protected/privatekeys/bitpay-'; - // } - // - // - // $storageEngine = new \Bitpay\Storage\EncryptedFilesystemStorage('mnewhdo3yy4yFDASc156MdhshuUYTF5365'); - // $privateKey = $storageEngine->load($folder.$_POST['id_pos'].'.pri'); - // $publicKey = $storageEngine->load($folder.$_POST['id_pos'].'.pub'); - // - // // Get a BitPay Client to prepare for invoice creation - // $client = new \Bitpay\Client\Client(); - // //$network = new \Bitpay\Network\Testnet(); - // $network = new \Bitpay\Network\Livenet(); - // $adapter = new \Bitpay\Client\Adapter\CurlAdapter(); - // - // $client->setPrivateKey($privateKey); - // $client->setPublicKey($publicKey); - // $client->setNetwork($network); - // $client->setAdapter($adapter); - // /** - // * The last object that must be injected is the token object. - // */ - // $token = new \Bitpay\Token(); - // $token - // ->setToken(Utility::decryptURL($pairings->token)); - // /** - // * Token object is injected into the client - // */ - // $client->setToken($token); - // /** - // * This is where we will start to create an Invoice(for bitcpay and transaction for Napos) object, make sure to check - // * the InvoiceInterface for methods that you can use. - // */ - // $invoice = new \Bitpay\Invoice(); - // - // //woocomerce - // //$invoice->setOrderId((string)$order_number); - // //$invoice->setCurrency('EUR'); - // $invoice->setFullNotifications(true); - // $invoice->setExtendedNotifications(true); - // - // - // // Add the buyers info to invoice - // $buyer = new \Bitpay\Buyer(); - // $buyer->setEmail($_POST['email']); - // $invoice->setBuyer($buyer); - // - // /** - // * Item is used to keep track of a few things - // */ - // //PRODUCT INFORMATIONS - // //item code - // //item description - // - // $item = new \Bitpay\Item(); - // $item - // ->setCode($_POST['id_pos']) - // ->setDescription(substr($pairings->label,0,20)) - // ->setPrice($_POST['amount']); - // - // $invoice->setItem($item); - // - // /** - // * BitPay supports multiple different currencies. Most shopping cart applications - // * and applications in general have defined set of currencies that can be used. - // * Setting this to one of the supported currencies will create an invoice using - // * the exchange rate for that currency. - // * - // * @see https://test.bitpay.com/bitcoin-exchange-rates for supported currencies - // */ - // $invoice->setCurrency(new \Bitpay\Currency('EUR')); - // - // // Configure the rest of the invoice - // //non c'è nessun order id in quanto non viene generato prima un carrello ed un ordine, ma passa subito - // //all'acquisto! - // $invoice->setOrderId($pos->denomination); - // // You will receive IPN's at this URL, should be HTTPS for security purposes! - // $invoice->setRedirectUrl($_POST['redirectUrl']); - // $invoice->setNotificationUrl($_POST['ipnUrl']); - // //$invoice->setTransactionSpeed($this->transaction_speed); - // - // /** - // * Updates invoice with new information such as the invoice id and the URL where - // * a customer can view the invoice. - // */ - // try { - // $client->createInvoice($invoice); - // } catch (\Exception $e) { - // $request = $client->getRequest(); - // $response = $client->getResponse(); - // //echo (string) $request.PHP_EOL.PHP_EOL.PHP_EOL; - // //echo (string) $response.PHP_EOL.PHP_EOL; - // //$send_json = array ('error'=>(string) $response); - // // echo "
".print_r($send_json,true)."
"; - // // exit; - // - // $string = (string) $response; - // $start = strpos($string,'{',0); - // $substr = substr($string,$start); - // $send_json = array ('error'=>$substr); - // echo CJSON::encode($send_json); - // exit; - // // exit(1); // We do not want to continue if something went wrong - // } - // //TRASFORMA OBJECT $client IN ARRAY - // $response = $client->getResponse(); - // $start = strpos($response,'{',0); - // $substr = substr($response,$start); - // $body = json_decode($substr, true); - // $array = $body['data']; - // // - // #echo "
".print_r($array,true)."
"; - // #exit; - // - // $btc_due = $array['paymentTotals']['BTC']/100000000; - // $satoshis_perbyte = $array['minerFees']['BTC']['satoshisPerByte']; - // $total_fee = $array['minerFees']['BTC']['totalFee']/100000000; - // $bitcoin_address = $array['url']; //$array['bitcoinAddress']; - // - // $invoice_timestamp = substr($array['invoiceTime'],0,-3); - // $expiration_timestamp = substr($array['expirationTime'],0,-3); - // $current_tempo = substr($array['currentTime'],0,-3); - // - // #echo "
".print_r($array,true)."
"; - // #exit; - // - // //salva la transazione BitPay - // $timestamp = time(); - // $attributes = array( - // 'id_pos' => $_POST['id_pos'], - // 'id_merchant' => $_POST['id_merchant'], - // 'status' => $invoice->getStatus(), - // 'btc_price' => $array['paymentSubtotals']['BTC']/100000000, - // 'price' => $_POST['amount'], - // 'currency' => 'EUR', - // 'item_desc' => $invoice->getItemDesc(), - // 'item_code' => $array['orderId'], - // 'id_invoice_bps' => $array['id'], - // 'invoice_timestamp' => $invoice_timestamp, - // 'expiration_timestamp' => $expiration_timestamp, - // 'current_tempo' => $current_tempo, - // 'btc_paid' => $array['amountPaid'], - // 'rate' => $array['exchangeRates']['BTC']['EUR'], - // 'bitcoin_address' => $bitcoin_address, - // 'token' => (string) $invoice->getToken(), - // 'btc_due' => $btc_due, - // 'satoshis_perbyte' => $satoshis_perbyte, - // 'total_fee' => $total_fee, - // ); - // $transaction = $this->save_transaction($attributes); - // //salva la notifica BitPay - // $notification = array( - // 'type_notification' => 'new', - // 'id_merchant' => $transaction['id_merchant'], - // 'id_tocheck' => $transaction['id_transaction'], - // 'status' => $transaction['status'], - // 'description' => ' da '. $pairings->label, - // 'url' => "index.php?r=transactions/view&id=".Utility::encryptURL($transaction['id_transaction']), - // 'timestamp' => $timestamp, - // 'price' => $_POST['amount'], - // 'deleted' => 0, - // ); - // NaPay::save_notification($notification); - // - // //finalmente ritorno all'app e restituisco l'url con il qr-code della transazione da pagare!!! - // $send_json = array( - // 'url' => $invoice->getUrl(), - // ); - // echo CJSON::encode($send_json); - // } - - /** - * action BITPAY Transaction - */ - // public function actionCoingateInvoice() - // { - // if (true === isset($_POST['amount']) && trim($_POST['amount']) != 0) { - // $amount = trim($_POST['amount']); - // } else { - // echo CJSON::encode(array("error"=>"Amount invalid!")); - // exit; - // } - // - // //$pos = new Pos; - // $pos=Pos::model()->findByPk($_POST['id_pos']); - // if($pos===null){ - // echo CJSON::encode(array("error"=>"The requested ID Pos does not exist!")); - // exit; - // } - // //$merchants = new Merchants; - // $merchants=Merchants::model()->findByPk($pos->id_merchant); - // if($merchants===null){ - // echo CJSON::encode(array("error"=>"The requested Merchant does not exist!")); - // exit; - // } - // $pairings = Pairings::model()->findByAttributes(array('id_pos'=>$pos->id_pos)); - // if($pairings===null){ - // echo CJSON::encode(array("error"=>"The requested Token does not exist!")); - // exit; - // } - // - // //init CoinGate - // NaPay::init_coingate(Utility::decryptURL($pairings->token)); - // - // // init array order - // $array = array( - // 'order_id' => $pos->id_pos, - // 'price_amount' => number_format($_POST['amount'], 8, '.', ''), - // 'price_currency' => 'EUR',//get_woocommerce_currency(), - // 'receive_currency' => 'BTC', //$this->receive_currency, - // 'cancel_url' => $_POST['redirectUrl'],//$order->get_cancel_order_url(), - // 'callback_url' => $_POST['ipnUrl'], - // 'success_url' => $_POST['redirectUrl'], - // 'title' => ' ' . $merchants->denomination, - // 'description' => ' ' . $pos->denomination, - // 'token' => Utility::decryptURL($pairings->token) - // ); - // $invoice = \CoinGate\Merchant\Order::create($array); - // if ($invoice && $invoice->payment_url) { - // $send_json = array( - // 'url' => $invoice->payment_url, - // ); - // } else { - // echo CJSON::encode(array("error"=>"Failed!")); - // exit; - // } - // - // #echo "
".print_r($invoice,true)."
"; - // #exit; - // //salva la transazione CoinGate - // $timestamp = time(); - // $attributes = array( - // 'id_pos' => $_POST['id_pos'], - // 'id_merchant' => $_POST['id_merchant'], - // 'status' => $invoice->status, - // 'btc_price' => 0, - // 'price' => $_POST['amount'], - // 'currency' => $invoice->receive_currency, - // 'item_desc' => $pos->denomination, - // 'item_code' => $_POST['id_pos'], - // 'id_invoice_bps' => $invoice->id, - // 'invoice_timestamp' => $timestamp, - // 'expiration_timestamp' => $timestamp + (60 * 15), //15 minuti di scadenza - // 'current_tempo' => $timestamp, - // 'btc_paid' => 0, - // 'rate' => $_POST['rate'], - // 'bitcoin_address' => $invoice->payment_url, - // 'token' => Utility::encryptURL($invoice->token), - // 'btc_due' => 0, - // 'satoshis_perbyte' => 0, - // 'total_fee' => 0 - // ); - // $transaction = $this->save_transaction($attributes); - // #echo '
'.print_r($transaction,true).'
'; - // #exit; - // //salva la notifica CoinGate - // $notification = array( - // 'type_notification' => 'new', - // 'id_merchant' => $transaction['id_merchant'], - // 'id_tocheck' => $transaction['id_transaction'], - // 'status' => $transaction['status'], - // 'description' => ' da '. $pairings->label, - // 'url' => "index.php?r=transactions/view&id=".Utility::encryptURL($transaction['id_transaction']), - // 'timestamp' => $timestamp, - // 'price' => $_POST['amount'], - // 'deleted' => 0, - // ); - // NaPay::save_notification($notification); - // - // //finalmente ritorno all'app e restituisco l'url con il qr-code della transazione da pagare!!! - // echo CJSON::encode($send_json); - // } - } diff --git a/protected/controllers/KeypadController.php b/protected/controllers/KeypadController.php index 2406be4..eab50f4 100644 --- a/protected/controllers/KeypadController.php +++ b/protected/controllers/KeypadController.php @@ -118,40 +118,10 @@ public function actionIndex() // verifico se è in scadenza $warningmessage = null; - $deadline = WebApp::StatoPagamenti(Yii::app()->user->objUser['id_user'],true); - if ($deadline >= -31-28){ - $warningmessage[] = $this->writeMessage('deadline', 28+31 - $deadline); - } - // if (!(WebApp::isMobileDevice())){ - // $this->layout='//layouts/keypad-desktop'; - // - // $pos = Pos::model()->findByPk(Yii::app()->user->objUser['id_pos']); - // //cerco tutti gli shop - // $criteria=new CDbCriteria(); - // $criteria->compare('id_store',$pos->id_store,false); - // $criteria->compare('deleted',0,false); - // $shops = Shops::model()->findAll($criteria); - // - // $bps_shopid = array(); - // foreach ($shops as $x => $item) - // $bps_shopid[] = ['denomination'=>$item->denomination,'bps_shopid'=>$item->bps_shopid]; - // - // echo "
".print_r($bps_shopid,true)."
"; - // exit; - // - // - // - // $this->render('keypad-desktop',array( - // //$this->render('keypad-mobile',array( - // 'invoiceIsPaid'=>$invoiceIsPaid, - // 'invoiceId' => $id, - // 'invoiceAction'=> $action, - // 'warningmessage'=>$warningmessage, // messaggio di scadenza - // 'bps_shopid' => $bps_shopid, - // )); - // }else{ + + if (isset($_GET['tag'])){ $shop = Shops::model()->findByPk(crypt::Decrypt($_GET['tag'])); $this->render('keypad-desktop',array( diff --git a/protected/controllers/MessagesController.php b/protected/controllers/MessagesController.php index 48b3105..7e4b6b7 100644 --- a/protected/controllers/MessagesController.php +++ b/protected/controllers/MessagesController.php @@ -1,4 +1,11 @@ params['libsPath'] . '/ethereum/web3/vendor/autoload.php'; use Web3\Web3; use Web3\Contract; @@ -76,12 +87,136 @@ protected function performAjaxValidation($model) } } + //scrive a video e nel file log le informazioni richieste + private function log($text){ + $save = new Save; + $save->WriteLog('pos','qrcode','getInvoiceStatus', $text); + } /** * @param POST integer id_token the ID of the model to be searched */ public function actionGetInvoiceStatus(){ - $model = $this->loadModel(crypt::Decrypt($_POST['id_token'])); - echo CJSON::encode(array("status"=>$model->status)); + // $model = $this->loadModel(crypt::Decrypt($_POST['id_token'])); + // echo CJSON::encode(array("status"=>$model->status)); + // } + // public function a2GetInvoiceStatus(){ + $id = $_POST['id_token']; + // $this->log("Start Check invoice #: $id"); + + //carico l'invoice + $invoice = $this->loadModel(crypt::Decrypt($id)); + // $this->log("Invoice $id loaded. Status is $invoice->status"); + + $expiring_seconds = $invoice->expiration_timestamp +1 - time(); + $transactionValue = $invoice->token_ricevuti; + + $ipnflag = false; + if ($invoice->status == 'new' || $invoice->status == 'expired'){ //se il valore è new proseguo + // cerco le transazioni su bolt_tokens in pending + $criteria=new CDbCriteria; + + $criteria->compare('type','token'); + //$criteria->compare('status','new',true); + $criteria->compare('item_desc','wallet'); + $criteria->compare('to_address',$invoice->to_address); + $criteria->addCondition("invoice_timestamp > " .$invoice->invoice_timestamp); + $criteria->addCondition("blocknumber > " .$invoice->blocknumber); + $criteria->compare('token_price',$invoice->token_price,true); // false -> valore identico + + $transactions = Tokens::model()->findAll($criteria); + + if (!empty($transactions)) + { + $this->log("Transazioni trovate."); + foreach ($transactions as $transaction) + { + $this->log("Transazione n. $transaction->id_token"); + if ($transaction->status <> 'new'){ + $this->log("Transazione n. $transaction->id_token COMPLETATA."); + $this->log('
'.print_r($transaction->attributes,true).'
'); + $invoice->status = $transaction->status; + $invoice->token_ricevuti = $transaction->token_price; + $invoice->from_address = $transaction->from_address; + $invoice->blocknumber = $transaction->blocknumber; + $invoice->txhash = $transaction->txhash; + + // carico il memo di tokens e lo aggiorno con quello del pos + $memoToken = TokensMemo::model()->findByAttributes(['id_token'=>$transaction->id_token]); + if (null === $memoToken) + $memoToken = new TokensMemo; + + $this->log("TokensMemo: ($transaction->id_token)".'
'.print_r(crypt::Decrypt($memoToken->memo),true).'
'); + $invoiceMemo = PosInvoicesMemo::model()->findByAttributes(['id_token'=>$invoice->id_token]); + if (null === $invoiceMemo) + $invoiceMemo = new PosInvoicesMemo; + + $this->log("PosInvoicesMemo: ($invoice->id_token)".'
'.print_r(crypt::Decrypt($invoiceMemo->memo),true).'
'); + $memoToken->memo = $invoiceMemo->memo; + $memoToken->id_token = $transaction->id_token; + + // aggiorno il messaggio + $memoToken->save(); + + + $invoice->save(); + + $ipnflag = true; + }else{ + $this->log("Transazione n. $transaction->id_token ancora in new..."); + } + }//foreach loop + } + if ($ipnflag === false && $expiring_seconds < 0){//invoice expired + $invoice->status = 'expired'; + $ipnflag = true; + } + } + if ($expiring_seconds < 0){//invoice expired + $ipnflag = true; + } + if ($ipnflag){ //send ipn in case flag is true: può venire + // aggiorno l'invoice e invio il messaggio push + if ($invoice->save()){ + //$this->log("End : invoice #: $id, Status: $invoice->status, Received: $invoice->token_ricevuti"); + $this->sendIpn($invoice->attributes); + }else{ + $this->log("Error : Cannot save invoice #. $id, Status: $invoice->status."); + } + } + //conto alla rovescia fino alla scadenza dell'invoice + $this->log("Invoice: $id, Status: ".$invoice->status.", Seconds: ".$expiring_seconds."\n"); + // ritorno lo stato + echo CJSON::encode(array("status"=>$invoice->status)); + } + + private function sendIpn($ipn){ + $tokens = (object) $ipn; + + if (true === empty($tokens)) { + $this->log("Error. Could not decode the JSON payload from Token Server."); + throw new \Exception('Could not decode the JSON payload from Token Server.'); + }else{ + #fwrite($myfile, $date . " : 2. Json ok.\n"); + } + + //QUINDI INVIO UN MESSAGGIO DI NOTIFICA + $notification = array( + 'type_notification' => 'invoice', + 'id_user' => $tokens->id_user, + 'id_tocheck' => $tokens->id_token, + 'status' => $tokens->status, + // 'description' => ' da '. $tokens->item_desc, + 'description' => Notifi::description($tokens->status,'token'), + 'url' => "index.php?r=tokens/view&id=".crypt::Encrypt($tokens->id_token), + 'timestamp' => time(), + 'price' => $tokens->token_price, + 'deleted' => 0, + ); + $save = new Save; + Push::Send($save->Notification($notification,true),'dashboard'); + + //ADESSO POSSO USCIRE CON UN MESSAGGIO POSITIVO ;^) + $this->log("IPN received for Invoice #: ".crypt::Encrypt($tokens->id_token).", Status=" .$tokens->status.", Price=". $tokens->token_price.", Received: ".$tokens->token_ricevuti); } /** @@ -104,139 +239,5 @@ public function actionIndex($id,$id_pos) )); } - /** - * action Create Token Invoice - */ - // public function actionInvoice() - // { - // if (true === isset($_POST['amount']) && trim($_POST['amount']) != 0) { - // $amount = (float)trim($_POST['amount']); - // } else { - // echo CJSON::encode(array("error"=>"Amount invalid!")); - // exit; - // } - // - // $pos = new Pos; - // $pos=Pos::model()->findByPk($_POST['id_pos']); - // if($pos===null){ - // echo CJSON::encode(array("error"=>"The requested ID Pos does not exist!")); - // exit; - // } - // - // $wallets = Wallets::model()->findByAttributes(array('wallet_address'=>$_POST['wallet_address'])); - // if($wallets===null){ - // echo CJSON::encode(array("error"=>"The requested Wallet address does not exist!")); - // exit; - // } - // - // //Carico i parametri - // $settings=Settings::load(); //$settings=SettingsNapos::model()->findByPk(1); // la PK è 1 per i settings dell'applicazione Napos - // if ($settings === null || empty($settings->poa_url)){//} || empty($settings->poa_port)){ - // echo CJSON::encode(array("error"=>'Errore: I parametri di configurazione Token non sono stati trovati')); - // exit; - // } - // - // // mi connetto al nodo poa - // $web3 = new Web3($settings->poa_url); - // $contract = new Contract($web3->provider, $settings->poa_abi); - // $eth = $web3->eth; - // $utils = $web3->utils; - // $balance = 0; - // - // // utilizzo questo campo per salvare il numero di blocco in cui avviene la transazione - // $response = null; - // $eth->getBlockByNumber('latest',false, function ($err, $block) use (&$response){ - // if ($err !== null) { - // throw new CHttpException(404,'Errore: '.$err->getMessage()); - // } - // $response = $block; - // }); - // - // //salva la transazione del token - // $timestamp = time(); - // $invoice_timestamp = $timestamp; - // - // //calcolo expiration time - // //$settings=SettingsNapos::model()->findByPk(1); // la PK è 1 per i settings dell'applicazione Napos - // $totalseconds = $settings->poa_expiration * 60; //poa_expiration è in minuti, * 60 lo trasforma in secondi - // $expiration_timestamp = $timestamp + $totalseconds; //DEFAULT = 15 MINUTES - // - // $rate = NaPay::getFiatRate('token'); // - // //echo '
'.print_r(strlen($amount),true).'
'; - // //exit; - // - // $attributes = array( - // 'id_pos' => $_POST['id_pos'], - // 'id_merchant' => $_POST['id_merchant'], - // 'status' => 'new', - // 'type' => 'token', - // 'token_price' => $rate * $amount, - // 'token_ricevuti' => 0, - // 'fiat_price' => $amount, - // 'currency' => 'EUR', - // 'item_desc' => $pos->denomination, - // 'item_code' => $pos->id_pos, - // 'invoice_timestamp' => $invoice_timestamp, - // 'expiration_timestamp' => $expiration_timestamp, - // 'rate' => $rate, - // 'wallet_address' => $wallets->wallet_address, - // 'balance' => hexdec($response->number), // numero del blocco in base 10 - // 'txhash' => '', - // 'poa_url' => '',//$wallets->poa_url, //inserisco poa_url e poa_port così ogni token è legato alla propria poa e nn può funzionare su un'altra - // 'poa_port' => '',//$wallets->poa_port, - // 'id_bill' => 0 - // ); - // //restituisce un object - // $tokens = $this->save_tokenTransaction($attributes); - // - // //salva la notifica - // $notification = array( - // 'type_notification' => $tokens->type, - // 'id_merchant' => $tokens->id_merchant, - // 'id_tocheck' => $tokens->id_token, - // 'status' => $tokens->status, - // 'description' => ' '.ucfirst($tokens->type).' da '. $tokens->item_desc, - // 'url' => "index.php?r=tokens/view&id=".Utility::encryptURL($tokens->id_token), - // 'timestamp' => $timestamp, - // 'price' => $_POST['amount'], - // 'deleted' => 0, - // ); - // NaPay::save_notification($notification); - // - // //eseguo lo script che si occuperà in background di verificare lo stato dell'invoice appena creata... - // $cmd = Yii::app()->basePath.DIRECTORY_SEPARATOR.'yiic receive --id='.Utility::encryptURL($tokens->id_token); - // NaPay::execInBackground($cmd); - // - // //finalmente ritorno all'app e restituisco l'url con il qr-code della transazione da pagare!!! - // $send_json = array( - // 'url' => Yii::app()->createUrl('webtoken/qrcode',array('id'=>Utility::encryptURL($tokens->id_token))), - // ); - // echo CJSON::encode($send_json); - // } - - // private function setBalance($balance){ - // $value = (string) $balance * 1; - // $this->balance = $value / 1000000000000000000;; - // } - // private function setBalance($balance){ - // $value = (string) $balance * 1; - // $this->balance = $value; - // } - // private function getBalance(){ - // return $this->balance; - // } - // private function save_tokenTransaction($array){ - // $tokens = new Tokens; - // $tokens->attributes = $array; - // #echo '
'.print_r($array,true).'
'; - // #exit; - // if (!$tokens->save()){ - // echo CJSON::encode(array("error"=>'Error: Cannot save transaction.')); - // exit; - // } - // #echo '
'.print_r($tokens->attributes,true).'
'; - // #exit; - // return (object) $tokens->attributes; - // } } diff --git a/protected/controllers/SettingsController.php b/protected/controllers/SettingsController.php index 944ddc5..ba335c8 100644 --- a/protected/controllers/SettingsController.php +++ b/protected/controllers/SettingsController.php @@ -1,4 +1,9 @@ user->objUser) && Yii::app()->user->objUser['facade'] != 'dashboard'){ - // Yii::app()->user->logout(); - // $this->redirect(Yii::app()->homeUrl); - // } - } - /** - * @var string the default layout for the views. Defaults to '//layouts/column2', meaning - * using two-column layout. See 'protected/views/layouts/column2.php'. - */ - // public $layout='//layouts/main_keypad'; -public $layout='//layouts/column1'; - /** - * @return array action filters - */ - public function filters() - { - return array( - 'accessControl', // perform access control for CRUD operations - // 'postOnly + delete', // we only allow deletion via POST request - ); - } - - /** - * Specifies the access control rules. - * This method is used by the 'accessControl' filter. - * @return array access control rules - */ - public function accessRules() - { - return array( - array('allow', // allow authenticated user to perform 'create' and 'update' actions - 'actions'=>array('index','view','delete'), - 'users'=>array('@'), - ), - array('deny', // deny all users - 'users'=>array('*'), - ), - ); - } - - /** - * Deletes a particular model. - * If deletion is successful, the browser will be redirected to the 'admin' page. - * @param integer $id the ID of the model to be deleted - */ - public function actionDelete($id) - { - $save = new Save; - $this->loadModel(crypt::Decrypt($id))->delete(); - $save->WriteLog('pos','transactions','delete','Transaction ['.crypt::Decrypt($id).'] deleted by '.Yii::app()->user->objUser['email'],false); - $this->redirect(array('index')); - } - - /** - * Displays a particular model. - * @param integer $id the ID of the model to be displayed - */ - public function actionView($id) - { - $this->render('view',array( - 'model'=>$this->loadModel(crypt::Decrypt($id)), - )); - } - - - /** - * Lists all models. - */ - public function actionIndex() - { - $modelc=new Transactions('search'); - $modelc->unsetAttributes(); - - if(isset($_GET['Transactions'])) - $modelc->attributes=$_GET['Transactions']; - - $this->render('index',array( - 'modelc'=>$modelc, - )); - } - - - /** - * Returns the data model based on the primary key given in the GET variable. - * If the data model is not found, an HTTP exception will be raised. - * @param integer $id the ID of the model to be loaded - * @return Transactions the loaded model - * @throws CHttpException - */ - public function loadModel($id) - { - $model=Transactions::model()->findByPk($id); - if($model===null) - throw new CHttpException(404,'The requested page does not exist.'); - return $model; - } - - - - -} diff --git a/protected/models/LoginPosForm.php b/protected/models/LoginPosForm.php index cd15559..585ab98 100644 --- a/protected/models/LoginPosForm.php +++ b/protected/models/LoginPosForm.php @@ -77,10 +77,6 @@ public function authenticatePOS($attribute,$params) $errorCode = $this->_identity->errorCode; switch ($errorCode){ - case POSIdentity::ERROR_USERNAME_NOT_PAYER: - $this->addError('username',"Nessun pagamento trovato."); - break; - case POSIdentity::ERROR_USERNAME_NOT_MEMBER: $this->addError('username',"L'iscrizione è scaduta. Provvedere al pagamento della quota associativa per il rinnovo."); break; diff --git a/protected/models/Transactions.php b/protected/models/Transactions.php deleted file mode 100644 index 9927b56..0000000 --- a/protected/models/Transactions.php +++ /dev/null @@ -1,151 +0,0 @@ -true), - array('status', 'length', 'max'=>250), - array('currency', 'length', 'max'=>10), - array('token', 'length', 'max'=>5000), - array('item_code, id_invoice_bps, bitcoin_address ', 'length', 'max'=>60), - array('item_desc ', 'length', 'max'=>5000), - - // The following rule is used by search(). - // @todo Please remove those attributes that should not be searched. - array('status, btc_price, price, id_invoice_bps, id_pos, expiration_timestamp', 'safe', 'on'=>'search'), - ); - } - - /** - * @return array relational rules. - */ - public function relations() - { - // NOTE: you may need to adjust the relation name and the related - // class name for the relations automatically generated below. - return array( - - ); - } - - /** - * @return array customized attribute labels (name=>label) - */ - public function attributeLabels() - { - return array( - 'id_transaction' => '#', - 'id_pos' => 'Pos', - 'id_merchant' => 'Id Merchant', - 'status' => 'Stato', - 'btc_price' => 'Importo Crypto', - 'btc_due' => 'Btc Dovuto', - 'price' => 'Importo', - 'currency' => 'Valuta', - 'item_desc' => 'Descrizione Oggetto', - 'item_code' => 'Codice Ordine', - //'guid' => 'guid', - 'id_invoice_bps' => 'Codice Transazione', - 'invoice_timestamp' => 'Data', - 'expiration_timestamp' => 'Scadenza', - 'current_tempo' => 'Orario Corrente', - 'btc_paid' => 'Btc Ricevuti', - 'rate' => 'Tasso', - 'bitcoin_address' => 'Indirizzo', - 'token' => 'Token', - 'satoshis_perbyte' => 'Satoshis per byte', - 'total_fee' => 'Tassa Miner', - 'id_bill' => 'id fattura', - ); - } - - /** - * Retrieves a list of models based on the current search/filter conditions. - * - * Typical usecase: - * - Initialize the model fields with values from filter form. - * - Execute this method to get CActiveDataProvider instance which will filter - * models according to data in model fields. - * - Pass data provider to CGridView, CListView or any similar widget. - * - * @return CActiveDataProvider the data provider that can return the models - * based on the search/filter conditions. - */ - public function search() - { - // @todo Please modify the following code to remove attributes that should not be searched. - // echo Yii::app()->user->objUser['privilegi']; - // exit; - - $criteria=new CDbCriteria; - if (Yii::app()->user->objUser['privilegi'] == 10){ - $merchants=Merchants::model()->findByAttributes(array( - 'id_user'=>Yii::app()->user->objUser['id_user'], - 'deleted'=>'0', - )); - $criteria->compare('id_merchant',$merchants->id_merchant,false); - } - - $criteria->compare('id_pos',$this->id_pos,true); - - $criteria->compare('btc_price',$this->btc_price,true); - $criteria->compare('price',$this->price,true); - $criteria->compare('id_invoice_bps',$this->id_invoice_bps,true); - $criteria->compare('DATE_FORMAT(invoice_timestamp,"%d/%m/%y")',$this->invoice_timestamp,true); - $criteria->compare('rate',$this->rate,true); - - $criteria->compare('status',$this->status,false); - - if (!isset($_GET['typelist'])){ - $criteria->addCondition("status = 'complete'"); - }else if ($_GET['typelist'] == 0){ - $criteria->addCondition("status = 'complete'"); - }else if ($_GET['typelist'] == 1){ - $criteria->addCondition("(status = 'paid' OR status = 'confirmed')"); - }else if ($_GET['typelist'] == 2){ - $criteria->addCondition("status = 'new'"); - } - - return new CActiveDataProvider($this, array( - 'criteria'=>$criteria, - 'sort'=>array( - 'defaultOrder'=>array( - 'id_transaction'=>true, - ) - ), - )); - } - - /** - * Returns the static model of the specified AR class. - * Please note that you should have this exact method in all your CActiveRecord descendants! - * @param string $className active record class name. - * @return Stores the static model class - */ - public static function model($className=__CLASS__) - { - return parent::model($className); - } -} diff --git a/protected/models/TransactionsData.php b/protected/models/TransactionsData.php deleted file mode 100644 index 1dd7fe5..0000000 --- a/protected/models/TransactionsData.php +++ /dev/null @@ -1,116 +0,0 @@ -true), - array('customAmount, discountPercentage, subTotal, discountAmount, tip, total', 'numerical'), - // The following rule is used by search(). - // @todo Please remove those attributes that should not be searched. - array('id_pos_data, id_transaction, cart, customAmount, discountPercentage, subTotal, discountAmount, tip, total', 'safe', 'on'=>'search'), - ); - } - - /** - * @return array relational rules. - */ - public function relations() - { - // NOTE: you may need to adjust the relation name and the related - // class name for the relations automatically generated below. - return array( - ); - } - - /** - * @return array customized attribute labels (name=>label) - */ - public function attributeLabels() - { - return array( - 'id_pos_data' => 'Id Pos Data', - 'id_transaction' => 'Id Transaction', - 'cart' => 'Cart', - 'customAmount' => 'Custom Amount', - 'discountPercentage' => 'Discount Percentage', - 'subTotal' => 'Sub Total', - 'discountAmount' => 'Discount Amount', - 'tip' => 'Tip', - 'total' => 'Total', - ); - } - - /** - * Retrieves a list of models based on the current search/filter conditions. - * - * Typical usecase: - * - Initialize the model fields with values from filter form. - * - Execute this method to get CActiveDataProvider instance which will filter - * models according to data in model fields. - * - Pass data provider to CGridView, CListView or any similar widget. - * - * @return CActiveDataProvider the data provider that can return the models - * based on the search/filter conditions. - */ - public function search() - { - // @todo Please modify the following code to remove attributes that should not be searched. - - $criteria=new CDbCriteria; - - $criteria->compare('id_pos_data',$this->id_pos_data); - $criteria->compare('id_transaction',$this->id_transaction); - $criteria->compare('cart',$this->cart,true); - $criteria->compare('customAmount',$this->customAmount); - $criteria->compare('discountPercentage',$this->discountPercentage); - $criteria->compare('subTotal',$this->subTotal); - $criteria->compare('discountAmount',$this->discountAmount); - $criteria->compare('tip',$this->tip); - $criteria->compare('total',$this->total); - - return new CActiveDataProvider($this, array( - 'criteria'=>$criteria, - )); - } - - /** - * Returns the static model of the specified AR class. - * Please note that you should have this exact method in all your CActiveRecord descendants! - * @param string $className active record class name. - * @return TransactionsData the static model class - */ - public static function model($className=__CLASS__) - { - return parent::model($className); - } -} diff --git a/protected/models/TransactionsInfo.php b/protected/models/TransactionsInfo.php deleted file mode 100644 index e75d320..0000000 --- a/protected/models/TransactionsInfo.php +++ /dev/null @@ -1,134 +0,0 @@ -true), - array('rate, paid, price, due, value', 'numerical'), - array('cryptoCode', 'length', 'max'=>10), - array('paymentType', 'length', 'max'=>50), - array('address, txId, destination', 'length', 'max'=>500), - // The following rule is used by search(). - // @todo Please remove those attributes that should not be searched. - array('id_transaction_info, id_transaction, cryptoCode, paymentType, rate, paid, price, due, address, txCount, txId, received, value, destination', 'safe', 'on'=>'search'), - ); - } - - /** - * @return array relational rules. - */ - public function relations() - { - // NOTE: you may need to adjust the relation name and the related - // class name for the relations automatically generated below. - return array( - ); - } - - /** - * @return array customized attribute labels (name=>label) - */ - public function attributeLabels() - { - return array( - 'id_transaction_info' => 'Id Transaction Info', - 'id_transaction' => 'Id Transaction', - 'cryptoCode' => 'Asset', - 'paymentType' => 'Tipo di Pagamento', - 'rate' => 'Tasso', - 'paid' => 'Pagato', - 'price' => 'Prezzo', - 'due' => 'Dovuto', - 'address' => 'Indirizzo', - 'txCount' => 'Tx Count', - 'txId' => 'Transazione', - 'received' => 'Data di Ricezione', - 'value' => 'Valore', - 'destination' => 'Indirizzo di destinazione', - ); - } - - /** - * Retrieves a list of models based on the current search/filter conditions. - * - * Typical usecase: - * - Initialize the model fields with values from filter form. - * - Execute this method to get CActiveDataProvider instance which will filter - * models according to data in model fields. - * - Pass data provider to CGridView, CListView or any similar widget. - * - * @return CActiveDataProvider the data provider that can return the models - * based on the search/filter conditions. - */ - public function search() - { - // @todo Please modify the following code to remove attributes that should not be searched. - - $criteria=new CDbCriteria; - - $criteria->compare('id_transaction_info',$this->id_transaction_info); - $criteria->compare('id_transaction',$this->id_transaction); - $criteria->compare('cryptoCode',$this->cryptoCode,true); - $criteria->compare('paymentType',$this->paymentType,true); - $criteria->compare('rate',$this->rate); - $criteria->compare('paid',$this->paid); - $criteria->compare('price',$this->price); - $criteria->compare('due',$this->due); - $criteria->compare('address',$this->address,true); - $criteria->compare('txCount',$this->txCount); - $criteria->compare('txId',$this->txId,true); - $criteria->compare('received',$this->received); - $criteria->compare('value',$this->value); - $criteria->compare('destination',$this->destination,true); - - return new CActiveDataProvider($this, array( - 'criteria'=>$criteria, - )); - } - - /** - * Returns the static model of the specified AR class. - * Please note that you should have this exact method in all your CActiveRecord descendants! - * @param string $className active record class name. - * @return TransactionsInfo the static model class - */ - public static function model($className=__CLASS__) - { - return parent::model($className); - } -} diff --git a/protected/views/keypad/js_main.php b/protected/views/keypad/js_main.php index 41d027b..bb9f9dd 100644 --- a/protected/views/keypad/js_main.php +++ b/protected/views/keypad/js_main.php @@ -12,10 +12,8 @@ //RICERCA GATEWAY PER INVIARE COMANDI PERSONALIZZATI $merchants=Merchants::model()->findByPk($pos->id_merchant); $settings=Settings::loadUser($merchants->id_user); -$gateways=Gateways::model()->findByPk($settings->id_gateway); // url creazione invoices -$urlController = Yii::app()->createUrl('invoices/'.$gateways->action_controller); // controller che crea la transazione $urlTokenController = Yii::app()->createUrl('invoices/token'); // controller che crea la transazione per il token // CERCO L'INDIRIZZO DEL TOKEN. SE PRESENTE AUTORIZZO LA CREAZIONE DELL'INVOICE, ALTRIMENTI NISBA... @@ -36,7 +34,6 @@ var ajax_loader_url = 'css/images/loading.gif'; var tokenAuth = '{$tokenAuth}'; - var bitcoinInvoice = document.querySelector('#done'); var tokenInvoice = document.querySelector('#token'); var countDecimals = function(value) { @@ -100,57 +97,6 @@ }); }); - bitcoinInvoice.addEventListener('click', function(){ - event.preventDefault(); - var amount_val = $('#easy-numpad-output').text(); - if (amount_val == 0 || amount_val == '') - return false; - - if (countDecimals(amount_val) > 2){ - $('.error-header').addClass("bg-danger").show(); - $('.error-message').text('Errore. Utilizzare massimo 2 cifre decimali'); - return false; - } - - $.ajax({ - url:'{$urlController}', - type: "POST", - beforeSend: function() { - $('#waiting_span-btc').hide(); - $('#waiting_span-btc').after('
'); - }, - data:{ - 'id_pos' : '{$BtcPayServerIDPOS}', - 'amount' : amount_val, - }, - dataType: "json", - success:function(data){ - $('.waiting_span').remove(); - $('#waiting_span-btc').show(); - console.log(data); - - if (data.error){ - $('.error-header').addClass("bg-danger").show(); - $('.error-message').text(data.error); - return false; - }else{ - if ('{$gateways->action_controller}' != 'Bitpay') - window.location.href = data.url; - else - top.location = data.url; - } - }, - error: function(j){ - var json = jQuery.parseJSON(j.responseText); - $('#waiting_span-btc').show(); - $('.waiting_span').remove(); - $('.error-header').addClass("bg-danger").show(); - $('.error-message').text(json.error); - } - }); - }); - - JS; Yii::app()->clientScript->registerScript('myPos', $myPos, CClientScript::POS_END); diff --git a/protected/views/layouts/header_mobile.php b/protected/views/layouts/header_mobile.php index d41bec2..039ae23 100644 --- a/protected/views/layouts/header_mobile.php +++ b/protected/views/layouts/header_mobile.php @@ -30,46 +30,9 @@ Keypad - findByPk(Yii::app()->user->objUser['id_pos']); - //cerco tutti gli shop - $criteria=new CDbCriteria(); - $criteria->compare('id_store',$pos->id_store,false); - $criteria->compare('deleted',0,false); - $shops = Shops::model()->findAll($criteria); - - $bps_shopid = array(); - foreach ($shops as $x => $item) - $bps_shopid[] = ['denomination'=>$item->denomination,'bps_shopid'=>crypt::Encrypt($item->id_shop)]; - - // var_dump($bps_shopid); - // exit; - if (!empty($bps_shopid)){ - ?> -
  • - - Self POS - -
  • - - -
  • - - Transazioni -
  • - Token + Transazioni
  • diff --git a/protected/views/layouts/menu_aside.php b/protected/views/layouts/menu_aside.php index 23cb191..4040797 100644 --- a/protected/views/layouts/menu_aside.php +++ b/protected/views/layouts/menu_aside.php @@ -25,57 +25,15 @@ Keypad - findByPk(Yii::app()->user->objUser['id_pos']); - //cerco tutti gli shop - $criteria=new CDbCriteria(); - $criteria->compare('id_store',$pos->id_store,false); - $criteria->compare('deleted',0,false); - $shops = Shops::model()->findAll($criteria); - - $bps_shopid = array(); - foreach ($shops as $x => $item) - $bps_shopid[] = ['denomination'=>$item->denomination,'bps_shopid'=>crypt::Encrypt($item->id_shop)]; - - // var_dump($bps_shopid); - // exit; - if (!empty($bps_shopid)){ - ?> -
  • - - Self POS - -
  • - - - -
  • - - Transazioni -
  • - Token + Transazioni
  • - -
  • - - diff --git a/protected/views/qrcode/index.php b/protected/views/qrcode/index.php index 8e87f33..442f1b1 100644 --- a/protected/views/qrcode/index.php +++ b/protected/views/qrcode/index.php @@ -130,7 +130,7 @@ function getTimeOffset() {
    widget('application.extensions.qrcode.QRCodeGenerator',array( - 'data' => $model->to_address, //.'?amount='.$model->token_price, + 'data' => $model->to_address.'?amount='.$model->token_price, 'filename' => $merchants->id_merchant . '.png', 'filePath' => Yii::app()->basePath . '/qrcodes/', 'subfolderVar' => false, diff --git a/protected/views/qrcode/js_qrcode.php b/protected/views/qrcode/js_qrcode.php index 3cb0bd5..e295ca2 100644 --- a/protected/views/qrcode/js_qrcode.php +++ b/protected/views/qrcode/js_qrcode.php @@ -66,7 +66,7 @@ function checkPayment(perc){ break; case 'paid': - case 'complete': + case 'complete': $('.return-button').show(); $( ".bp-view" ).removeClass( "active" ); $( "#paid" ).addClass( "active" ); @@ -99,10 +99,12 @@ function checkPayment(perc){ var minutes = {$minutes} var ss = {$ss} + // tempo di scadenza var ts = new Date(yyyy,mm,dd,hh,minutes,ss); + // controllo se il time di adesso è > del time di scadenza if((new Date()) > ts){ - checkPayment(100);//fattura scaduta + checkPayment(100); //fattura scaduta } $('#countdown').countdown({ timestamp : ts, diff --git a/protected/views/site/_login.php b/protected/views/site/_login.php index 45b246f..4e99caa 100644 --- a/protected/views/site/_login.php +++ b/protected/views/site/_login.php @@ -63,14 +63,7 @@
    -
    -
    - -
    -
    - -
    -
    + diff --git a/protected/views/tokens/view.php b/protected/views/tokens/view.php index aaf5f1a..9b24a7e 100644 --- a/protected/views/tokens/view.php +++ b/protected/views/tokens/view.php @@ -46,7 +46,7 @@ 'type'=>'raw', 'name'=>Yii::t('model','status'), //'value'=>WebApp::walletStatus($model->status), - 'value' => ( $model->status == "new" ) ? + 'value' => ( $model->status == "new" || $model->status == 'expired' ) ? ( CHtml::ajaxLink( WebApp::walletStatus($model->status), // the link body (it will NOT be HTML-encoded.) diff --git a/protected/views/transactions/_index.php b/protected/views/transactions/_index.php deleted file mode 100644 index a436106..0000000 --- a/protected/views/transactions/_index.php +++ /dev/null @@ -1,65 +0,0 @@ - - -
    -
    -
    -
    -

    Lista transazioni

    -
    - - widget('zii.widgets.grid.CGridView', array( - //'htmlOptions' => array('class' => 'table table-borderless table-striped table-data2'), - 'htmlOptions' => array('class' => 'table table-data4'), - 'dataProvider'=>$dataProvider, - 'columns' => array( - - array( - 'type'=>'raw', - 'name'=>'invoice_timestamp', - 'value' => 'CHtml::link(CHtml::encode(date("d/m/Y H:i:s",$data->invoice_timestamp)), Yii::app()->createUrl("transactions/view")."&id=".CHtml::encode(Utility::encryptURL($data->id_transaction)))', - ), - - array( - 'name'=>'status', - //'value'=>'$data->status', - 'type' => 'raw', - //'value'=>'WebApp::walletStatus($data->status)', - 'value'=>'CHtml::link(WebApp::walletStatus($data->status), Yii::app()->createUrl("transactions/view")."&id=".CHtml::encode(Utility::encryptURL($data->id_transaction)))', - 'cssClassExpression' => '( $data->status == "complete" ) ? "process" : (( $data->status == "expired" ) ? "denied" : "desc incorso")', - ), - array( - 'name'=>'price', - 'type' => 'raw', - 'value'=>'"€ ". $data->price', - ), - - - array( - 'name'=>'bitcoin_address', - 'type' => 'raw', - 'value' => 'CHtml::encode(substr($data->bitcoin_address,0,7))."…"', - //'value' => 'CHtml::link(CHtml::encode($data->bitcoin_address), WebApp::isBtcAddress($data->bitcoin_address), array("target"=>"_blank"))', - - ), - - ) - )); - ?> -
    -
    -
    - - -
    -
    diff --git a/protected/views/transactions/_view.php b/protected/views/transactions/_view.php deleted file mode 100644 index f48b4a9..0000000 --- a/protected/views/transactions/_view.php +++ /dev/null @@ -1,72 +0,0 @@ -BTCPayServerAddress; - -?> -
    -
    -
    -
    -

    Dettaglio transazione #id_transaction; ?>

    -
    - widget('zii.widgets.CDetailView', array( - 'htmlOptions' => array('class' => 'table table-borderless table-striped '), - 'data'=>$model, - 'attributes'=>array( - //'id_invoice_bps', - array( - 'type'=>'raw', - 'name'=>'id_invoice_bps', - 'value' => CHtml::link(CHtml::encode($model->id_invoice_bps), $btcpayInvoiceAddress.'/invoice?id='.$model->id_invoice_bps, array("target"=>"_blank")), - ), - array( - 'type'=>'raw', - 'name'=>'status', - 'value'=>WebApp::walletStatus($model->status), - ), - array( - 'label'=>'Data', - 'value'=>date("d/m/Y H:i:s",$model->invoice_timestamp), - ), - array( - 'label'=>'Importo', - 'value'=>'€ '.$model->price, - ), - array( - 'label'=>'Rate', - 'value'=>$model->rate, - ), - 'btc_price', - 'btc_due', - 'btc_paid', - array( - 'label'=>'POS Utilizzato', - 'value'=>$model->item_desc, - ), - array( - 'label'=>'Satoshis/byte', - 'value'=>$model->satoshis_perbyte, - ), - - //'currency', - array( - 'label'=>'Tassa Miner', - 'value'=>$model->total_fee, - ), - array( - 'label'=>'Indirizzo', - 'type'=>'raw', - 'value' => CHtml::link(CHtml::encode($model->bitcoin_address), WebApp::isBtcAddress($model->bitcoin_address), array("target"=>"_blank")), - ), - - ), - )); ?> -
    -
    -
    - -
    -
    diff --git a/protected/views/transactions/index.php b/protected/views/transactions/index.php deleted file mode 100644 index dcf4bc5..0000000 --- a/protected/views/transactions/index.php +++ /dev/null @@ -1,173 +0,0 @@ -user->objUser['privilegi'] == 10){ - $merchants=Merchants::model()->findByAttributes(array( - 'id_user'=>Yii::app()->user->objUser['id_user'], - 'deleted'=>'0', - )); - $criteria->compare('id_merchant',$merchants->id_merchant,false); -} -// if (Yii::app()->user->objUser['privilegi'] == 15){ -// $associations=Associations::model()->findByAttributes(array( -// 'id_user'=>Yii::app()->user->objUser['id_user'], -// 'deleted'=>'0', -// )); -// $merchants=Merchants::model()->findByAttributes(array( -// 'id_association'=>$associations->id_association, -// 'deleted'=>'0', -// )); -// $criteria->compare('id_merchant',$merchants->id_merchant,false); -// } -if (Yii::app()->user->objUser['privilegi'] == 20){ - $criteria->compare('deleted',0,false); -} - -$url = Yii::app()->createUrl('transactions/index'); -$myList = << -
    -
    -
    - - -
    -
    - - - - - - -
    - widget('zii.widgets.grid.CGridView', array( - //'htmlOptions' => array('class' => 'table table-borderless table-striped table-earning'), - //'htmlOptions' => array('class' => 'table table table-borderless table-data3'), - //'htmlOptions' => array('class' => 'table table-borderless table-data3'), - //'htmlOptions' => array('class' => 'table table-borderless table-data3 table-earning '), - //'dataProvider'=>$dataProvider, - //'htmlOptions' => array('class' => 'table table-borderless table-data2 table-earning table-wallet text-dark'), - // 'htmlOptions' => array('class' => 'table table-borderless text-dark table-data4 table-wallet'), - // 'htmlOptions' => array('class' => 'table table-striped text-dark table-data4 table-wallet'), - //'htmlOptions' => array('class' => 'table table-wallet'), - 'dataProvider'=>$modelc->search(), - 'filter'=>$modelc, - 'enablePagination' => true, - - 'columns' => array( - //'value'=>'id_transaction', - array( - 'name'=>'invoice_timestamp', - 'type' => 'raw', - 'value' => 'CHtml::link(WebApp::dateLN($data->invoice_timestamp), Yii::app()->createUrl("transactions/view",["id"=>crypt::Encrypt($data->id_transaction)]) )', - 'filter'=>"", - - ), - array( - 'name'=>'status', - 'type' => 'raw', - 'value'=>'CHtml::link(WebApp::walletStatus($data->status), Yii::app()->createUrl("transactions/view")."&id=".CHtml::encode(crypt::Encrypt($data->id_transaction)))', - 'class'=>'DataColumn', - 'evaluateHtmlOptions'=>true, - 'htmlOptions'=>array('id'=>'"transactionstatus_{$data->id_transaction}"'), - 'filter'=>WebApp::statusList('transaction'), - ), - array( - 'name'=>'price', - 'type' => 'raw', - 'value'=>'"€ ". $data->price', - ), - array( - 'name'=>'rate', - 'type' => 'raw', - 'value'=>'"€ ". $data->rate', - ), - array( - 'name'=>'btc_price', - 'value'=>'$data->btc_price', - ), - // array( - // 'name'=>'id_pos', - // 'value'=> 'Pos::model()->findByAttributes(array("id_pos"=> "$data->id_pos" ))->denomination', - // ), - array( - 'name'=>'id_pos', - 'header'=>'Pos', - 'value'=>'($data->id_pos >0) ? Pos::model()->findByPk($data->id_pos)->denomination : Shops::model()->findByPk($data->item_code*1)->denomination', - 'filter'=>CHtml::listData(Pos::model()->findAll($criteria), 'id_pos', 'denomination'), - ), - array( - 'name'=>'id_invoice_bps', - 'type' => 'raw', - 'value' => 'CHtml::link(CHtml::encode($data->id_invoice_bps), Yii::app()->createUrl("transactions/view")."&id=".CHtml::encode(crypt::Encrypt($data->id_transaction)))', - ), - - // array( - // 'name'=>'bitcoin_address', - // 'type' => 'raw', - // //'value'=>'$data->bitcoin_address', - // 'value' => 'CHtml::link(CHtml::encode($data->bitcoin_address), WebApp::isBtcAddress($data->bitcoin_address), array("target"=>"_blank"))', - // ), - - ) - )); - ?> -
    -
    - -
    -
    - - - - - diff --git a/protected/views/transactions/view.php b/protected/views/transactions/view.php deleted file mode 100644 index cbcf9e8..0000000 --- a/protected/views/transactions/view.php +++ /dev/null @@ -1,129 +0,0 @@ -blockchainAddress; - -$merchants = Merchants::model()->findByPk($model->id_merchant); -$btcpayInvoiceAddress = Settings::loadUser($merchants->id_user)->blockchainAddress; - -?> -
    -
    -
    -
    -
    -
    - - Dettaglio transazione id_invoice_bps), $btcpayInvoiceAddress.'/invoice?id='.$model->id_invoice_bps, array("target"=>"_blank")); ?> -
    -
    -
    - widget('zii.widgets.CDetailView', array( - //'htmlOptions' => array('class' => 'table table-borderless table-striped '), - 'data'=>$model, - 'attributes'=>array( - //'id_invoice_bps', - // array( - // 'type'=>'raw', - // 'name'=>'id_invoice_bps', - // 'value' => CHtml::link(CHtml::encode($model->id_invoice_bps), $btcpayInvoiceAddress.'/invoice?id='.$model->id_invoice_bps, array("target"=>"_blank")), - // ), - array( - 'type'=>'raw', - 'name'=>'status', - //'value'=>WebApp::walletStatus($model->status), - 'value' => ( $model->status <> "complete" ) ? - ( - CHtml::ajaxLink( - WebApp::walletStatus($model->status), // the link body (it will NOT be HTML-encoded.) - array('backend/checkSingleInvoice'."&id=".CHtml::encode(crypt::Encrypt($model->id_transaction))), // the URL for the AJAX request. If empty, it is assumed to be the current URL. - array( - 'update'=>'.btn-outline-dark', - 'beforeSend' => 'function() { - $(".btn").text("Checking..."); - $(".btn").addClass("alert-warning text-light"); - }', - - 'complete' => 'function(data) { - $(".btn").removeClass("btn-secondary"); - //console.log(data); - var obj = JSON.parse(data.responseText) - console.log(obj); - $(".btn").text(obj.message); - var time = 1; - - if (obj.success == 1){ - function waitUntil(time){ - time -= 1; - $(".btn").text(obj.message+ " (- "+time+")"); - - if (time >0) - setTimeout(function(){ waitUntil(time) }, 1000); - else - location.reload(); - } - setTimeout(function(){ waitUntil(time) }, 1000); - }else{ - $(".btn").addClass("btn-warning"); - $(".btn").text("Transazione non trovata. Se vuoi cancellarla clicca sul pulsante \'ELIMINA\' sottostante"); - $("#btn-delete-transaction").text("ELIMINA"); - $(".delete-transaction").show(); - } - }', - ) - ) - ) : WebApp::walletStatus($model->status), - ), - array( - 'label'=>'Data', - 'value'=>date("d/m/Y H:i:s",$model->invoice_timestamp), - ), - array( - 'label'=>'Importo', - 'type'=>'raw', - 'value'=>'
    € '.$model->price.'
    ', - ), - array( - 'label'=>'POS Utilizzato', - 'value'=>($model->id_pos >0) ? Pos::model()->findByPk($model->id_pos)->denomination : Shops::model()->findByPk($model->item_code)->denomination, - ), - [ - 'label' => 'Sommario', - 'type'=>'raw', - 'value' => WebApp::showCryptoInfo($model->id_transaction), - ], - [ - 'label' => 'Vendita Pos', - 'type'=>'raw', - 'value' => WebApp::showPosData($model->id_transaction), - 'visible' => WebApp::issetPosData($model->id_transaction), - ], - - ), - )); ?> -
    -
    -
    -
    -
    - - -
    -
    diff --git a/protected/yiic b/protected/yiic old mode 100644 new mode 100755 diff --git a/protected/yiic.bat b/protected/yiic.bat index 5d2eceb..645f7f6 100644 --- a/protected/yiic.bat +++ b/protected/yiic.bat @@ -9,8 +9,8 @@ rem ------------------------------------------------------------- set BIN_PATH=%~dp0 -if "%PHP_COMMAND%" == "" set PHP_COMMAND=e:\xampp\php\php.exe +if "%PHP_COMMAND%" == "" set PHP_COMMAND=\xampp\php\php.exe "%PHP_COMMAND%" "%BIN_PATH%yiic.php" %* -@endlocal +@endlocal \ No newline at end of file diff --git a/protected/yiic.php b/protected/yiic.php index 82c1628..26dedef 100644 --- a/protected/yiic.php +++ b/protected/yiic.php @@ -1,7 +1,8 @@ { - //show_easy_numpad(); - // }); -//}); - function show_easy_numpad() { var easy_numpad = `
    @@ -40,11 +34,9 @@ function show_easy_numpad() {
    - - - +
    diff --git a/src/js/utility.js b/src/js/utility.js index 1813ee0..4c50fec 100644 --- a/src/js/utility.js +++ b/src/js/utility.js @@ -1,4 +1,4 @@ -var dbPromise = idb.open('napay-pos', 1, function(db) { +var dbPromise = idb.open('fidelize-pos', 1, function(db) { if (!db.objectStoreNames.contains('sin')) { db.createObjectStore('sin', {keyPath: 'id'}); } diff --git a/themes/cool/css/theme.css b/themes/cool/css/theme.css index 23ae62a..5667871 100644 --- a/themes/cool/css/theme.css +++ b/themes/cool/css/theme.css @@ -14680,7 +14680,7 @@ section { padding-left: 30px; } -#page-vesuvio{ +#p age-vesuvio{ width: 100%; height: 100%; top: 0; left: 0; background: url(../../../css/images/BG.svg) no-repeat center top; position: fixed; z-index: -1; -webkit-background-size: cover; diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..cca4e2c --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +49556ee3edfc71245102d4fb00b531ab558e3df1