public function testInvoiceAddressCallback()
 {
     InvoiceAddress::saveInvoiceAddress(['address' => 'mrcpH23MHKweJmzNWNbPKMxtVKMJYVpKgr', 'destination_address' => null, 'invoice_amount' => 0, 'label' => 'invoice', 'callback_url' => 'http://dummy.url.com', 'forward' => 0, 'crypto_type_id' => 1, 'user_id' => 1]);
     $queryString = http_build_query(['cryptotype' => 1, 'secret' => 'testbtc123', 'txid' => '151f9b43343c5cd4f2064b5ac2a722f67cc53a845d05cdf9979379fa4ed19160', 'userid' => 1, 'time' => 'xxx']);
     $response = $this->call('GET', 'api/callback?' . $queryString);
     $result = $response->getContent();
     $this->assertEquals('*ok*', $result);
 }
 private function processInvoiceAddress(Transaction $transaction_model = null, InvoiceAddress $invoice_address_model, array $common_data, $satoshi_amount)
 {
     Log::info('Processing invoicing address ' . $common_data['address_to'] . ', destination address: ' . $invoice_address_model->destination_address . ', label: ' . $invoice_address_model->label . ', amount satoshi: ' . $invoice_address_model->received_amount . ', callback url: ' . $invoice_address_model->callback_url . ', forward: ' . $invoice_address_model->forward);
     $forward_tx_id = 0;
     // needed for callback. stays 0 when forwarding is not chosen
     DB::beginTransaction();
     if (!$transaction_model) {
         $initialUserBalance = Balance::getBalance($this->user->id, $this->crypto_type_id);
         // first callback, because no transaction initially found in db
         $common_data['transaction_type'] = TX_RECEIVE_INVOICING;
         // new API user balance
         $common_data['user_balance'] = bcadd($initialUserBalance->balance, $satoshi_amount);
         $common_data['balance'] = bcadd($invoice_address_model->balance, $satoshi_amount);
         // new address balance
         $common_data['previous_balance'] = $invoice_address_model->balance;
         // address balance before that transaction
         $common_data['bitcoind_balance'] = bcmul($this->bitcoin_core->getbalance(), SATOSHIS_FRACTION);
         // bitcoind balance on received! that means this transaction is not included, because it has 0 conf;
         $transaction_model = Transaction::insertNewTransaction($common_data);
         $total_received = bcadd($invoice_address_model->received_amount, $satoshi_amount);
         InvoiceAddress::updateReceived($invoice_address_model, $total_received);
         // update amount and mark as received
         /* update API user balance */
         $user_balance_updated = Balance::updateUserBalance($this->user, $satoshi_amount);
         // check if needs to be forwarded
         if ($invoice_address_model->forward == 1) {
             $bitcoin_amount = bcdiv($satoshi_amount, SATOSHIS_FRACTION, 8);
             // division
             Log::info('Starting to forward ' . $satoshi_amount . ' satoshis which is ' . $bitcoin_amount . ' bitcoins');
             try {
                 $forward_data = ['user_id' => $this->user->id, 'transaction_type' => TX_SEND, 'crypto_amount' => $satoshi_amount, 'crypto_type_id' => $this->crypto_type_id, 'address_to' => $common_data['address_to'], 'note' => 'invoice forwarding', 'balance' => bcsub($transaction_model->balance, $satoshi_amount)];
                 $forward_tx_id = $this->bitcoin_core->sendtoaddress($invoice_address_model->destination_address, (double) $bitcoin_amount);
                 if ($forward_tx_id) {
                     $forward_data['tx_id'] = $forward_tx_id;
                     $forward_data['previous_balance'] = $transaction_model->balance;
                     $forward_data['bitcoind_balance'] = bcmul($this->bitcoin_core->getbalance(), SATOSHIS_FRACTION);
                     Transaction::insertNewTransaction($forward_data);
                     Balance::updateUserBalance($this->user, $satoshi_amount);
                     Log::info('Forwarded ' . $bitcoin_amount . ' bitcoins to ' . $common_data['address_to']);
                 }
                 // TODO f****d when sendtoaddress throws exception, should send to server still the response.
             } catch (Exception $e) {
                 Log::error("#callback: send to address exception: " . $e->getMessage());
                 // add to transaction entry anyway, with failed forwarding and send warning out email !
                 $forward_data['note'] = 'failed invoice forwarding';
                 Transaction::insertNewTransaction($forward_data);
                 DB::commit();
                 MailHelper::sendEmailPlain(['email' => Config::get('mail.admin_email'), 'subject' => 'FAILED INVOICE FORWARDING!', 'text' => 'Failed to forward to ' . $common_data['address_to'] . ', ' . $satoshi_amount . ' satoshis, tx hash: ' . $common_data['tx_id']]);
             }
         }
         // add data that is specific to invoice address
         $common_data['transaction_hash'] = $forward_tx_id;
         $common_data['destination_address'] = $invoice_address_model->destination_address;
         $response = $this->sendUrl($common_data, $satoshi_amount, TX_INVOICE, $invoice_address_model->callback_url, Config::get('bitcoin.app_secret'));
         // if we get back an *ok* from the script then update the transactions status
         Transaction::updateTxOnAppResponse($transaction_model, $response['app_response'], $response['callback_url'], $response['callback_status'], $response['external_user_id']);
     } else {
         /* bitcoind sent 2nd callback for the transaction which is 1st confirmation
          * no need to shoot to the application, since application is updating first confirmation anyway on block-notify */
         Transaction::updateTxConfirmation($transaction_model, $common_data);
     }
     DB::commit();
 }