-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
50ea2d0
commit 8443ff5
Showing
3 changed files
with
135 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
src/addons/BS/BtcPayProvider/Payment/Concerns/Webhook.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
<?php | ||
|
||
namespace BS\BtcPayProvider\Payment\Concerns; | ||
|
||
use BTCPayServer\Client\Invoice; | ||
use XF\Payment\CallbackState; | ||
|
||
use function BS\BtcPayProvider\Helpers\data_get; | ||
|
||
trait Webhook | ||
{ | ||
protected function getWebhookPaymentResult(CallbackState $state): ?int | ||
{ | ||
$payload = $state->payload ?? []; | ||
|
||
switch ($state->hookType) { | ||
case 'InvoiceSettled': | ||
if ($payload['overPaid'] ?? false) { | ||
$state->logType = 'info'; | ||
$state->logMessage = 'Invoice payment settled but was overpaid.'; | ||
} | ||
|
||
return CallbackState::PAYMENT_RECEIVED; | ||
|
||
case 'InvoicePaymentSettled': | ||
if (! data_get($state->purchaseRequest->extra_data, 'invoiceExpired')) { | ||
$state->logType = 'info'; | ||
$state->logMessage = 'Invoice (partial) payment settled.'; | ||
return null; | ||
} | ||
|
||
// here invoice expired | ||
$state->logType = 'info'; | ||
if ($this->invoiceIsFullyPaid($state->paymentProfile->options, $state->transactionId)) { | ||
$state->logMessage = 'Invoice fully settled after invoice was already expired. Needs manual checking.'; | ||
} else { | ||
$state->logMessage = '(Partial) payment settled but invoice not settled yet (could be more transactions incoming). Needs manual checking.'; | ||
} | ||
return null; | ||
|
||
case 'InvoiceReceivedPayment': | ||
$state->logType = 'info'; | ||
if (data_get($payload, 'afterExpiration')) { | ||
$state->logMessage = 'Invoice (partial) payment incoming (unconfirmed) after invoice was already expired.'; | ||
} else { | ||
$state->logMessage = 'Invoice (partial) payment incoming (unconfirmed). Waiting for settlement.'; | ||
} | ||
return null; | ||
|
||
case 'InvoiceProcessing': | ||
$state->logType = 'info'; | ||
if (data_get($payload, 'overPaid')) { | ||
$state->logMessage = 'Invoice payment received fully with overpayment, waiting for settlement.'; | ||
} else { | ||
$state->logMessage = 'Invoice payment received fully, waiting for settlement.'; | ||
} | ||
return null; | ||
|
||
case 'InvoiceExpired': | ||
$state->logType = 'info'; | ||
if (data_get($payload, 'partiallyPaid')) { | ||
$state->logMessage = 'Invoice expired but was paid partially, please check.'; | ||
} else { | ||
$state->logMessage = 'Invoice expired. No action to take.'; | ||
} | ||
$this->updateStatePurchaseRequestExtraData($state, 'invoiceExpired', true); | ||
return null; | ||
|
||
case 'InvoiceInvalid': | ||
$state->logType = 'info'; | ||
if (data_get($payload, 'manuallyMarked')) { | ||
$state->logMessage = 'Invoice manually marked invalid.'; | ||
} else { | ||
$state->logMessage = 'Invoice became invalid.'; | ||
} | ||
return null; | ||
|
||
default: | ||
return null; | ||
} | ||
} | ||
|
||
protected function updateStatePurchaseRequestExtraData( | ||
CallbackState $state, | ||
array|string $key, | ||
mixed $value = null | ||
): void { | ||
$request = $state->purchaseRequest; | ||
$extraData = $request->extra_data; | ||
|
||
if (is_array($key)) { | ||
$extraData = array_merge($extraData, $key); | ||
} else { | ||
$extraData[$key] = $value; | ||
} | ||
|
||
$request->extra_data = $extraData; | ||
$request->save(); | ||
} | ||
|
||
protected function invoiceIsFullyPaid(array $options, string $invoiceId): bool | ||
{ | ||
$client = new Invoice($options['host'], $options['api_key']); | ||
|
||
try { | ||
return $client->getInvoice($options['store_id'], $invoiceId) | ||
->isSettled(); | ||
} catch (\Throwable $e) { | ||
\XF::logException($e, false, 'BTCPay Server invoice retrieval failed: '); | ||
} | ||
|
||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php | ||
|
||
namespace BS\BtcPayProvider\Helpers; | ||
|
||
function data_get(array $arr, mixed $key, mixed $default = null): mixed | ||
{ | ||
return $arr[$key] ?? $default; | ||
} |