mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
combine use of websocket and callback
This commit is contained in:
parent
5a5e0960c3
commit
3cbe451878
@ -52,48 +52,6 @@ class Blockonomics implements MethodInterface
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doCurlCall($url, $post_content = '')
|
|
||||||
{
|
|
||||||
$ch = curl_init();
|
|
||||||
curl_setopt($ch, CURLOPT_URL, $url);
|
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
||||||
if ($post_content) {
|
|
||||||
curl_setopt($ch, CURLOPT_POST, 1);
|
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_content);
|
|
||||||
}
|
|
||||||
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
|
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
||||||
'Authorization: Bearer ' . $this->blockonomics->api_key,
|
|
||||||
'Content-type: application/x-www-form-urlencoded',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$contents = curl_exec($ch);
|
|
||||||
if (curl_errno($ch)) {
|
|
||||||
echo "Error:" . curl_error($ch);
|
|
||||||
}
|
|
||||||
$responseObj = json_decode($contents);
|
|
||||||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
||||||
curl_close ($ch);
|
|
||||||
|
|
||||||
if ($status != 200) {
|
|
||||||
echo "ERROR: " . $status . ' ' . $responseObj->message;
|
|
||||||
}
|
|
||||||
return $responseObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCallbackUrl()
|
|
||||||
{
|
|
||||||
$GET_CALLBACKS_URL = 'https://www.blockonomics.co/api/address?&no_balance=true&only_xpub=true&get_callback=true';
|
|
||||||
$SET_CALLBACK_URL = 'https://www.blockonomics.co/api/update_callback';
|
|
||||||
$get_callback_response = $this->doCurlCall($GET_CALLBACKS_URL);
|
|
||||||
|
|
||||||
$callback_url = $this->blockonomics->callback_url;
|
|
||||||
$xpub = $get_callback_response[0]->address;
|
|
||||||
$post_content = '{"callback": "' . $callback_url . '", "xpub": "' . $xpub . '"}';
|
|
||||||
|
|
||||||
$responseObj = $this->doCurlCall($SET_CALLBACK_URL, $post_content);
|
|
||||||
return $responseObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBTCAddress()
|
public function getBTCAddress()
|
||||||
{
|
{
|
||||||
@ -160,7 +118,6 @@ class Blockonomics implements MethodInterface
|
|||||||
$data['invoice_id'] = $_invoice->invoice_id;
|
$data['invoice_id'] = $_invoice->invoice_id;
|
||||||
$data['invoice_number'] = $_invoice->invoice_number;
|
$data['invoice_number'] = $_invoice->invoice_number;
|
||||||
$data['end_time'] = $this->getTenMinutesCountDownEndTime();
|
$data['end_time'] = $this->getTenMinutesCountDownEndTime();
|
||||||
$data['callback_url'] = $this->setCallbackUrl();
|
|
||||||
$data['invoice_redirect_url'] = "/client/invoices/{$_invoice->invoice_id}";
|
$data['invoice_redirect_url'] = "/client/invoices/{$_invoice->invoice_id}";
|
||||||
|
|
||||||
$data['websocket_url'] = 'wss://www.blockonomics.co/payment/' . $btc_address;
|
$data['websocket_url'] = 'wss://www.blockonomics.co/payment/' . $btc_address;
|
||||||
@ -169,12 +126,11 @@ class Blockonomics implements MethodInterface
|
|||||||
|
|
||||||
public function paymentResponse(PaymentResponseRequest $request)
|
public function paymentResponse(PaymentResponseRequest $request)
|
||||||
{
|
{
|
||||||
|
echo "Payment response received";
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'payment_hash' => ['required'],
|
'payment_hash' => ['required'],
|
||||||
'amount' => ['required'],
|
'amount' => ['required'],
|
||||||
'currency' => ['required'],
|
'currency' => ['required'],
|
||||||
'payment_method_id' => ['required'],
|
|
||||||
'txid' => ['required'],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -54,51 +54,73 @@ class BlockonomicsPaymentDriver extends BaseDriver
|
|||||||
$this->api_key = $this->company_gateway->getConfigField('apiKey');
|
$this->api_key = $this->company_gateway->getConfigField('apiKey');
|
||||||
$this->callback_secret = $this->company_gateway->getConfigField('callbackSecret');
|
$this->callback_secret = $this->company_gateway->getConfigField('callbackSecret');
|
||||||
$this->callback_url = $this->company_gateway->getConfigField('callbackUrl');
|
$this->callback_url = $this->company_gateway->getConfigField('callbackUrl');
|
||||||
|
// $this->setCallbackUrl();
|
||||||
return $this; /* This is where you boot the gateway with your auth credentials*/
|
return $this; /* This is where you boot the gateway with your auth credentials*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get($url, $apiKey = null)
|
public function doCurlCall($url, $post_content = '')
|
||||||
{
|
{
|
||||||
// Initialize cURL session
|
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
|
|
||||||
// Set cURL options
|
|
||||||
curl_setopt($ch, CURLOPT_URL, $url);
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
if ($post_content) {
|
||||||
// Set HTTP headers
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
$headers = ['Content-Type: application/json'];
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_content);
|
||||||
if ($apiKey) {
|
|
||||||
$headers[] = 'Authorization: Bearer ' . $apiKey;
|
|
||||||
}
|
}
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
'Authorization: Bearer ' . $this->api_key,
|
||||||
|
'Content-type: application/x-www-form-urlencoded',
|
||||||
|
]);
|
||||||
|
|
||||||
// Execute cURL session and get the response
|
$contents = curl_exec($ch);
|
||||||
$response = curl_exec($ch);
|
|
||||||
|
|
||||||
// Check for errors
|
|
||||||
if (curl_errno($ch)) {
|
if (curl_errno($ch)) {
|
||||||
throw new Exception(curl_error($ch));
|
echo "Error:" . curl_error($ch);
|
||||||
|
}
|
||||||
|
$responseObj = json_decode($contents);
|
||||||
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
curl_close ($ch);
|
||||||
|
|
||||||
|
if ($status != 200) {
|
||||||
|
echo "ERROR: " . $status . ' ' . $responseObj->message;
|
||||||
|
}
|
||||||
|
return $responseObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close cURL session
|
public function setCallbackUrl()
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
// Return the response
|
|
||||||
return json_decode($response, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_callbacks($api_key)
|
|
||||||
{
|
{
|
||||||
$GET_CALLBACKS_URL = 'https://www.blockonomics.co/api/address?&no_balance=true&only_xpub=true&get_callback=true';
|
$GET_CALLBACKS_URL = 'https://www.blockonomics.co/api/address?&no_balance=true&only_xpub=true&get_callback=true';
|
||||||
$response = $this->get($GET_CALLBACKS_URL, $api_key);
|
$SET_CALLBACK_URL = 'https://www.blockonomics.co/api/update_callback';
|
||||||
return $response;
|
$get_callback_response = $this->doCurlCall($GET_CALLBACKS_URL);
|
||||||
|
|
||||||
|
$callback_url = $this->callback_url;
|
||||||
|
$xpub = $get_callback_response[0]->address;
|
||||||
|
$post_content = '{"callback": "' . $callback_url . '", "xpub": "' . $xpub . '"}';
|
||||||
|
|
||||||
|
$responseObj = $this->doCurlCall($SET_CALLBACK_URL, $post_content);
|
||||||
|
return $responseObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public function get_callbackSecret()
|
public function findPaymentByTxid($txid)
|
||||||
// {
|
{
|
||||||
// return md5(uniqid(rand(), true));
|
return Payment::whereRaw('BINARY `transaction_reference` LIKE ? AND BINARY `transaction_reference` LIKE ?', [
|
||||||
// }
|
"%payment hash:%",
|
||||||
|
"%txid: " . $txid . "%"
|
||||||
|
])->firstOrFail();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findPaymentHashInTransactionReference($transaction_reference)
|
||||||
|
{
|
||||||
|
$pattern = '/payment hash:\s*([a-zA-Z0-9]+)/';
|
||||||
|
// Perform the regex match
|
||||||
|
if (preg_match($pattern, $transaction_reference, $matches)) {
|
||||||
|
// Return the matched payment hash
|
||||||
|
return $matches[1];
|
||||||
|
} else {
|
||||||
|
// Return null if no match is found
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Returns an array of gateway types for the payment gateway */
|
/* Returns an array of gateway types for the payment gateway */
|
||||||
@ -130,70 +152,43 @@ class BlockonomicsPaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
public function processWebhookRequest()
|
public function processWebhookRequest()
|
||||||
{
|
{
|
||||||
// Get the callback parameters
|
// TODO: Figure out why init does not work
|
||||||
|
// $this->init();
|
||||||
|
// $secret = $this->company_gateway->getConfigField('callbackSecret');
|
||||||
|
// //Match secret for security
|
||||||
|
// if ($_GET['secret'] != $secret) {
|
||||||
|
// echo "Invalid Secret";
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
$txid = $_GET['txid'];
|
$txid = $_GET['txid'];
|
||||||
$value = $_GET['value'];
|
$value = $_GET['value'];
|
||||||
$status = $_GET['status'];
|
$status = $_GET['status'];
|
||||||
$addr = $_GET['addr'];
|
$addr = $_GET['addr'];
|
||||||
$receivedSecret = $_GET['secret'];
|
|
||||||
|
|
||||||
// Initialize the Webhook client (assuming it can be used for validation)
|
|
||||||
$webhookClient = new Webhook($this->blockonomics_url, $this->api_key);
|
|
||||||
|
|
||||||
// Validate the webhook request
|
|
||||||
if (!$webhookClient->isValidRequest($_GET, $receivedSecret)) {
|
|
||||||
throw new PaymentFailed('Invalid webhook request');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only accept confirmed transactions
|
// Only accept confirmed transactions
|
||||||
if ($status != 2) {
|
if ($status != 2) {
|
||||||
throw new PaymentFailed('Transaction not confirmed');
|
throw new PaymentFailed('Transaction not confirmed');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to the database
|
$payment = $this->findPaymentByTxid($txid);
|
||||||
$db = new SQLite3('payments_db.sqlite', SQLITE3_OPEN_READWRITE);
|
$payment_hash = $this->findPaymentHashInTransactionReference($payment->transaction_reference);
|
||||||
|
|
||||||
// Find the payment hash in the database
|
|
||||||
$this->payment_hash = PaymentHash::whereRaw('BINARY `hash`= ?', [$addr])->firstOrFail();
|
|
||||||
|
|
||||||
// Set the payment method to cryptocurrency
|
|
||||||
$this->setPaymentMethod(GatewayType::CRYPTO);
|
|
||||||
|
|
||||||
// Determine the payment status
|
|
||||||
$StatusId = Payment::STATUS_PENDING;
|
|
||||||
if ($this->payment_hash->payment_id == null) {
|
|
||||||
$_invoice = Invoice::with('client')->withTrashed()->find($this->payment_hash->fee_invoice_id);
|
|
||||||
$this->client = $_invoice->client;
|
|
||||||
|
|
||||||
$dataPayment = [
|
|
||||||
'payment_method' => $this->payment_method,
|
|
||||||
'payment_type' => PaymentType::CRYPTO,
|
|
||||||
'amount' => $_invoice->amount,
|
|
||||||
'gateway_type_id' => GatewayType::CRYPTO,
|
|
||||||
'transaction_reference' => $txid
|
|
||||||
];
|
|
||||||
$payment = $this->createPayment($dataPayment, $StatusId);
|
|
||||||
} else {
|
|
||||||
$payment = Payment::withTrashed()->find($this->payment_hash->payment_id);
|
|
||||||
$StatusId = $payment->status_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the payment status based on the transaction status
|
|
||||||
switch ($status) {
|
switch ($status) {
|
||||||
case 0:
|
case 0:
|
||||||
$StatusId = Payment::STATUS_PENDING;
|
$statusId = Payment::STATUS_PENDING;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
$StatusId = Payment::STATUS_PENDING;
|
$statusId = Payment::STATUS_PENDING;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
$StatusId = Payment::STATUS_COMPLETED;
|
$statusId = Payment::STATUS_COMPLETED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the updated payment status
|
// Save the updated payment status
|
||||||
if ($payment->status_id != $StatusId) {
|
if ($payment->status_id != $statusId) {
|
||||||
$payment->status_id = $StatusId;
|
$payment->status_id = $statusId;
|
||||||
$payment->save();
|
$payment->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,15 +103,10 @@
|
|||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
console.log('Payment status:', data.status);
|
console.log('Payment status:', data.status);
|
||||||
const isPaymentUnconfirmed = data.status === 0;
|
const isPaymentUnconfirmed = data.status === 0;
|
||||||
|
const isPaymentPartiallyConfirmed = data.status === 1;
|
||||||
const isPaymentConfirmed = data.status === 2;
|
const isPaymentConfirmed = data.status === 2;
|
||||||
if (isPaymentUnconfirmed) {
|
const shouldSubmitForm = isPaymentUnconfirmed || isPaymentConfirmed || isPaymentPartiallyConfirmed;
|
||||||
// Hide all existing content
|
if (shouldSubmitForm) {
|
||||||
document.querySelector('.initial-state').style.display = 'none';
|
|
||||||
document.querySelector('.progress-message').style.display = 'block';
|
|
||||||
document.getElementById('txid').innerText = data.txid || '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isPaymentConfirmed) {
|
|
||||||
document.querySelector('input[name="txid"]').value = data.txid || '';
|
document.querySelector('input[name="txid"]').value = data.txid || '';
|
||||||
document.getElementById('server-response').submit();
|
document.getElementById('server-response').submit();
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ use App\Http\Controllers\Bank\YodleeController;
|
|||||||
use App\Http\Controllers\CompanyUserController;
|
use App\Http\Controllers\CompanyUserController;
|
||||||
use App\Http\Controllers\PaymentTermController;
|
use App\Http\Controllers\PaymentTermController;
|
||||||
use App\PaymentDrivers\PayPalPPCPPaymentDriver;
|
use App\PaymentDrivers\PayPalPPCPPaymentDriver;
|
||||||
|
use App\PaymentDrivers\BlockonomicsPaymentDriver;
|
||||||
use App\Http\Controllers\EmailHistoryController;
|
use App\Http\Controllers\EmailHistoryController;
|
||||||
use App\Http\Controllers\GroupSettingController;
|
use App\Http\Controllers\GroupSettingController;
|
||||||
use App\Http\Controllers\OneTimeTokenController;
|
use App\Http\Controllers\OneTimeTokenController;
|
||||||
@ -458,5 +459,6 @@ Route::post('api/v1/yodlee/balance', [YodleeController::class, 'balanceWebhook']
|
|||||||
|
|
||||||
Route::get('api/v1/protected_download/{hash}', [ProtectedDownloadController::class, 'index'])->name('protected_download')->middleware('throttle:300,1');
|
Route::get('api/v1/protected_download/{hash}', [ProtectedDownloadController::class, 'index'])->name('protected_download')->middleware('throttle:300,1');
|
||||||
Route::post('api/v1/ppcp/webhook', [PayPalPPCPPaymentDriver::class, 'processWebhookRequest'])->middleware('throttle:1000,1');
|
Route::post('api/v1/ppcp/webhook', [PayPalPPCPPaymentDriver::class, 'processWebhookRequest'])->middleware('throttle:1000,1');
|
||||||
|
Route::get('api/v1/blockonomics/callback', [BlockonomicsPaymentDriver::class, 'processWebhookRequest'])->middleware('throttle:1000,1');
|
||||||
|
|
||||||
Route::fallback([BaseController::class, 'notFound'])->middleware('throttle:404');
|
Route::fallback([BaseController::class, 'notFound'])->middleware('throttle:404');
|
||||||
|
@ -5622,5 +5622,14 @@
|
|||||||
"GET",
|
"GET",
|
||||||
"HEAD"
|
"HEAD"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"generated::aB3xYz9KlmN7Pq8R": {
|
||||||
|
"name": "generated::aB3xYz9KlmN7Pq8R",
|
||||||
|
"domain": null,
|
||||||
|
"action": "App\\Http\\Controllers\\BlockonomicsPaymentDriver@processWebhookRequest",
|
||||||
|
"uri": "api/v1/blockonomics/callback",
|
||||||
|
"method": [
|
||||||
|
"GET"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user