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(); }