Enhance Blockonomics payment integration by adding required fields and improving transaction handling

This commit is contained in:
cnohall 2025-05-09 20:11:18 +09:00
parent dce8d798b3
commit d080f6db11
5 changed files with 65 additions and 31 deletions

View File

@ -124,6 +124,7 @@ class Blockonomics implements LivewireMethodInterface
return render('gateways.blockonomics.pay', $data);
}
public function paymentResponse(PaymentResponseRequest $request)
{
$request->validate([
@ -132,20 +133,49 @@ class Blockonomics implements LivewireMethodInterface
'currency' => ['required'],
'txid' => ['required'],
'payment_method_id' => ['required'],
'btc_address' => ['required'],
'btc_amount' => ['required'],
'btc_price' => ['required'],
// Setting status to required will break the payment process
// because sometimes the status is returned as 0 which is falsy
// and the validation will fail.
// 'status' => ['required'],
]);
try {
$data = [];
$fiat_amount = round(($request->btc_price * $request->btc_amount), 2);
$fiat_amount = round(($request->btc_price * $request->btc_amount), 2) / 100000000;
$data['amount'] = $fiat_amount;
$data['currency'] = $request->currency;
$data['payment_method_id'] = $request->payment_method_id;
$data['payment_type'] = PaymentType::CRYPTO;
$data['gateway_type_id'] = GatewayType::CRYPTO;
$data['transaction_reference'] = $request->txid;
// Randomize the transaction reference if the txid is a test payment
// to avoid duplicate transaction references in the database.
// Otherwise the payment hashed_id will not be unique.
if ($request->txid == 'WarningThisIsAGeneratedTestPaymentAndNotARealBitcoinTransaction') {
$data['transaction_reference'] = $request->txid . bin2hex(random_bytes(16));
} else {
$data['transaction_reference'] = $request->txid;
}
$statusId;
switch ($request->status) {
case 0:
$statusId = Payment::STATUS_PENDING;
break;
case 1:
$statusId = Payment::STATUS_PENDING;
break;
case 2:
$statusId = Payment::STATUS_COMPLETED;
break;
default:
$statusId = Payment::STATUS_PENDING;
}
$statusId = Payment::STATUS_PENDING;
$payment = $this->blockonomics->createPayment($data, $statusId);
$payment->custom_value1 = $request->btc_address;
$payment->save();
SystemLogger::dispatch(
['response' => $payment, 'data' => $data],

View File

@ -107,17 +107,15 @@ class BlockonomicsPaymentDriver extends BaseDriver
$addr = $request->addr;
$payment = Payment::query()
->where('company_id', $company->id)
->where('transaction_reference', $txid)
->firstOrFail();
->where('company_id', $company->id)
->where('transaction_reference', $txid)
->firstOrFail();
if (!$payment) {
// Already completed payment, no need to update status
if ($payment->status_id == Payment::STATUS_COMPLETED) {
return response()->json([], 200);
// TODO: Implement logic to create new payment in case user sends payment to the address after closing the payment page
}
$statusId = Payment::STATUS_PENDING;
switch ($status) {
case 0:
$statusId = Payment::STATUS_PENDING;
@ -128,16 +126,16 @@ class BlockonomicsPaymentDriver extends BaseDriver
case 2:
$statusId = Payment::STATUS_COMPLETED;
break;
default:
$statusId = Payment::STATUS_PENDING;
}
if ($payment->status_id == $statusId) {
return response()->json([], 200);
} else {
if ($payment->status_id !== $statusId) {
$payment->status_id = $statusId;
$payment->save();
return response()->json([], 200);
}
return response()->json([], 200);
}
@ -203,7 +201,7 @@ class BlockonomicsPaymentDriver extends BaseDriver
}
return 'ok';
}
return "Copy your Invoice Ninja Webhook URL and set it as your callback URL in Blockonomics";
return "No callback URL from your Blockonomics stores matches your Invoice Ninja webhook";
}
public function auth(): string

View File

@ -161,14 +161,18 @@ class Blockonomics {
ws.onmessage = function (event) {
const data = JSON.parse(event.data);
console.log('Payment status:', data.status);
const isPaymentUnconfirmed = data.status === 0;
const isPaymentPartiallyConfirmed = data.status === 1;
const isPaymentConfirmed = data.status === 2;
const { status, txid, value } = data || {};
console.log('Payment status:', status);
const isPaymentUnconfirmed = status === 0;
const isPaymentPartiallyConfirmed = status === 1;
const isPaymentConfirmed = status === 2;
// Confirmation status: 0 = unconfirmed, 1 = partially confirmed, 2 = confirmed
// If any of the statuses are true, submit the form and redirect
if (isPaymentUnconfirmed || isPaymentPartiallyConfirmed || isPaymentConfirmed) {
document.querySelector('input[name="txid"]').value = data.txid || '';
document.querySelector('input[name="txid"]').value = txid || '';
document.querySelector('input[name="status"]').value = status || '';
document.querySelector('input[name="btc_amount"]').value = value || '';
document.querySelector('input[name="btc_address"]').value = btcAddress || '';
document.getElementById('server-response').submit();
}
}

View File

@ -60,6 +60,7 @@
<input type="hidden" name="currency" value="{{ $currency }}">
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="txid" value="">
<input type="hidden" name="btc_address" value="{{ $btc_address }}" />
</form>
@ -102,19 +103,19 @@
margin-bottom: 20px;
display: flex;
justify-content: space-between;
}
}
.invoice-number {
width: 50%;
float: left;
text-align: left;
}
}
.invoice-amount {
width: 50%;
float: right;
text-align: right;
text-transform: uppercase;
margin-bottom: 20px;
}
}
.blockonomics-payment-wrapper {
display: flex;
justify-content: center;

View File

@ -1,5 +1,4 @@
<div class="rounded-lg border bg-card text-card-foreground shadow-sm overflow-hidden py-5 bg-white sm:gap-4" id="blockonomics-payment">
<meta name="amount" content="{{ $amount }}" />
<meta name="btc_amount" content="{{ $btc_amount }}" />
<meta name="btc_address" content="{{ $btc_address }}" />
@ -58,12 +57,14 @@
<input type="hidden" name="amount" value="{{ $amount }}">
<input type="hidden" name="btc_price" value="{{ $btc_price }}">
<input type="hidden" name="btc_amount" value="{{ $btc_amount }}">
<input type="hidden" name="btc_address" value="{{ $btc_address }}">
<input type="hidden" name="status" value="">
<input type="hidden" name="currency" value="{{ $currency }}">
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="txid" value="">
</form>
<style type="text/css">
.sections-wrapper {
display: flex;
@ -103,19 +104,19 @@
margin-bottom: 20px;
display: flex;
justify-content: space-between;
}
}
.invoice-number {
width: 50%;
float: left;
text-align: left;
}
}
.invoice-amount {
width: 50%;
float: right;
text-align: right;
text-transform: uppercase;
margin-bottom: 20px;
}
}
.blockonomics-payment-wrapper {
display: flex;
justify-content: center;
@ -188,4 +189,4 @@
@assets
@vite('resources/js/clients/payments/blockonomics.js')
@endassets
@endassets