diff --git a/config/services.php b/config/services.php index 12ee866..b5f1da3 100644 --- a/config/services.php +++ b/config/services.php @@ -40,4 +40,8 @@ return [ ], ], + 'btc_pay' => [ + 'api_key' => env('BTC_PAY_API_KEY'), + ] + ]; diff --git a/database/migrations/2024_10_24_132233_alter_payment_events_table.php b/database/migrations/2024_10_24_132233_alter_payment_events_table.php new file mode 100644 index 0000000..03c83bb --- /dev/null +++ b/database/migrations/2024_10_24_132233_alter_payment_events_table.php @@ -0,0 +1,28 @@ +dropColumn('zap_endpoint'); + $table->text('btc_pay_invoice')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('payment_events', function (Blueprint $table) { + // + }); + } +}; diff --git a/resources/views/pages/association/profile.blade.php b/resources/views/pages/association/profile.blade.php index 6b9fa85..bd13301 100644 --- a/resources/views/pages/association/profile.blade.php +++ b/resources/views/pages/association/profile.blade.php @@ -2,7 +2,6 @@ use Livewire\Volt\Component; -use SimpleSoftwareIO\QrCode\Facades\QrCode; use swentel\nostr\Filter\Filter; use swentel\nostr\Key\Key; use swentel\nostr\Message\EventMessage; @@ -13,6 +12,7 @@ use swentel\nostr\Request\Request; use swentel\nostr\Subscription\Subscription; use swentel\nostr\Event\Event as NostrEvent; use swentel\nostr\Sign\Sign; +use WireUi\Actions\Notification; use function Livewire\Volt\computed; use function Livewire\Volt\mount; @@ -27,8 +27,6 @@ name('association.profile'); state(['yearsPaid' => []]); state(['events' => []]); state(['payments' => []]); -state(['invoice' => null]); -state(['qrCode' => null]); state(['amountToPay' => config('app.env') === 'production' ? 21000 : 1]); state(['currentYearIsPaid' => false]); state(['currentPubkey' => null]); @@ -36,32 +34,6 @@ state(['currentPleb' => null]); form(\App\Livewire\Forms\ApplicationForm::class); -updated([ - 'invoice' => function () { - $this->qrCode = base64_encode( - QrCode::format('png') - ->size(300) - ->merge('/public/android-chrome-192x192.png', .3) - ->errorCorrection('H') - ->generate($this->invoice), - ); - }, -]); - -on([ - 'nostrLoggedOut' => function () { - $this->currentPubkey = null; - $this->currentPleb = null; - $this->yearsPaid = []; - $this->events = []; - $this->payments = []; - $this->invoice = null; - $this->qrCode = null; - $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; - $this->currentYearIsPaid = false; - }, -]); - on([ 'nostrLoggedIn' => function ($pubkey) { $this->currentPubkey = $pubkey; @@ -81,36 +53,84 @@ on([ $this->loadEvents(); $this->listenForPayment(); }, + 'nostrLoggedOut' => function () { + $this->currentPubkey = null; + $this->currentPleb = null; + $this->yearsPaid = []; + $this->events = []; + $this->payments = []; + $this->qrCode = null; + $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; + $this->currentYearIsPaid = false; + }, ]); +$pay = function ($comment) { + $paymentEvent = $this->currentPleb + ->paymentEvents() + ->where('year', date('Y')) + ->first(); + if ($paymentEvent->btc_pay_invoice) { + return redirect('https://pay.einundzwanzig.space/i/' . $paymentEvent->btc_pay_invoice); + } + try { + $response = Http::withHeaders([ + 'Authorization' => 'token ' . config('services.btc_pay.api_key'), + ])->post( + 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices', + [ + 'amount' => $this->amountToPay, + 'metadata' => [ + 'orderId' => $comment, + 'orderUrl' => url()->route('association.profile'), + 'itemDesc' => 'Mitgliedsbeitrag ' . date('Y') . ' von nostr:' . $this->currentPleb->npub, + 'posData' => [ + 'event' => $paymentEvent->event_id, + 'pubkey' => $this->currentPleb->pubkey, + 'npub' => $this->currentPleb->npub, + ], + ], + 'checkout' => [ + 'expirationMinutes' => 60 * 24 * 356, + 'redirectURL' => url()->route('association.profile'), + 'redirectAutomatically' => true, + 'defaultLanguage' => 'de', + ], + ], + )->throw(); + $paymentEvent->btc_pay_invoice = $response->json()['id']; + $paymentEvent->save(); + + return redirect($response->json()['checkoutLink']); + } catch (Exception $e) { + $notification = new Notification($this); + $notification->error( + 'Fehler beim Erstellen der Rechnung. Bitte versuche es später erneut: ' . $e->getMessage(), + ); + } +}; + $listenForPayment = function () { $paymentEvent = $this->currentPleb ->paymentEvents() ->where('year', date('Y')) ->first(); - if ($paymentEvent && !$paymentEvent->paid && $paymentEvent->zap_endpoint && !$this->currentYearIsPaid) { - $response = Http::get($paymentEvent->zap_endpoint); - - if (!isset($response->json()['tag'])) { - $paymentEvent->update(['paid' => true]); + if ($paymentEvent->btc_pay_invoice) { + $response = Http::withHeaders([ + 'Authorization' => 'token ' . config('services.btc_pay.api_key'), + ]) + ->get( + 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices/' . $paymentEvent->btc_pay_invoice, + ); + if ($response->json()['status'] === 'Settled') { + $paymentEvent->paid = true; + $paymentEvent->save(); + $this->payments = $this->currentPleb + ->paymentEvents() + ->get(); $this->currentYearIsPaid = true; } } - - if ($paymentEvent && $paymentEvent->paid && !$this->currentYearIsPaid) { - $this->payments = $paymentEvent = $this->currentPleb - ->paymentEvents() - ->get(); - $this->currentYearIsPaid = true; - } -}; - -$updateZapEndpoint = function ($zapEndpoint) { - $this->currentPleb - ->paymentEvents() - ->where('year', date('Y')) - ->first() - ->update(['zap_endpoint' => $zapEndpoint]); }; $save = function ($type) { @@ -127,7 +147,7 @@ $createPaymentEvent = function () { $note->setContent( 'Dieses Event dient der Zahlung des Mitgliedsbeitrags für das Jahr ' . date( 'Y', - ) . '. Bitte zappe den Betrag von ' . number_format($this->amountToPay, 0, ',', '.') . ' Satoshi.', + ) . '. Bitte bezahle den Betrag von ' . number_format($this->amountToPay, 0, ',', '.') . ' Satoshis.', ); $note->setTags([ ['d', $this->currentPleb->pubkey . ',' . date('Y')], @@ -188,7 +208,7 @@ $loadEvents = function () { @volt -
+
@@ -425,42 +445,29 @@ $loadEvents = function () { class="break-all">{{ $currentPleb->paymentEvents->first()->event_id }}

- @if(false && isset($events[0])) + @if(isset($events[0]))

{{ $events[0]['content'] }}

- @if(!$invoice && !$currentYearIsPaid) + @if(!$currentYearIsPaid)
@else - @if(!$currentYearIsPaid && $qrCode) -
- - qrcode - + @if($currentYearIsPaid) +
+
- @else - @if($currentYearIsPaid) -
- -
- @endif @endif @endif
@@ -494,6 +501,9 @@ $loadEvents = function () {
Event-ID
+ +
Quittung
+ @@ -517,6 +527,10 @@ $loadEvents = function () {
{{ $payment->event_id }}
+ + + @endforeach