From ca7a3257a8614e697bac5e8b311ad2fff7d19231 Mon Sep 17 00:00:00 2001 From: "Jose M. Valera Reales" Date: Sun, 25 May 2025 12:06:40 +0200 Subject: [PATCH 1/3] feat: allow customizing invoice messages --- README.md | 11 ++++++++++ lightning-config.dist.php | 2 ++ src/Config/LightningConfig.php | 20 +++++++++++++++++++ src/Invoice/Application/CallbackUrl.php | 4 +++- src/Invoice/Application/InvoiceGenerator.php | 12 +++++------ src/Invoice/InvoiceConfig.php | 10 ++++++++++ src/Invoice/InvoiceFactory.php | 3 +++ tests/Feature/InvoiceFacadeTest.php | 2 +- tests/Unit/Config/LightningConfigTest.php | 12 +++++++++++ .../Domain/CallbackUrl/CallbackUrlTest.php | 1 + .../Domain/LnAddress/InvoiceGeneratorTest.php | 6 ++++++ 11 files changed, 74 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7cc6171..82b003a 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,17 @@ cp lightning-config.dist.php lightning-config.php cp nostr.dist.json nostr.json ``` +You can customize the invoice description and the success message by editing +`lightning-config.php`: + +```php +use PhpLightning\Config\LightningConfig; + +return (new LightningConfig()) + ->setDescriptionTemplate('Pay to %s on mynode') + ->setSuccessMessage('Thanks for the payment!'); +``` + Run a local PHP server listening `public/index.php` ```bash diff --git a/lightning-config.dist.php b/lightning-config.dist.php index e802cad..31cd26e 100644 --- a/lightning-config.dist.php +++ b/lightning-config.dist.php @@ -7,6 +7,8 @@ return (new LightningConfig()) ->setDomain('localhost') ->setReceiver('default-receiver') + ->setDescriptionTemplate('Pay to %s') + ->setSuccessMessage('Payment received!') ->setSendableRange(min: 100_000, max: 10_000_000_000) ->setCallbackUrl('localhost:8000/callback') ->addBackendsFile(getcwd() . DIRECTORY_SEPARATOR . 'nostr.json'); diff --git a/src/Config/LightningConfig.php b/src/Config/LightningConfig.php index da30a58..47de68f 100644 --- a/src/Config/LightningConfig.php +++ b/src/Config/LightningConfig.php @@ -16,6 +16,8 @@ final class LightningConfig implements JsonSerializable private ?string $receiver = null; private ?SendableRange $sendableRange = null; private ?string $callbackUrl = null; + private ?string $descriptionTemplate = null; + private ?string $successMessage = null; public function setDomain(string $domain): self { @@ -42,6 +44,18 @@ public function setCallbackUrl(string $callbackUrl): self return $this; } + public function setDescriptionTemplate(string $template): self + { + $this->descriptionTemplate = $template; + return $this; + } + + public function setSuccessMessage(string $message): self + { + $this->successMessage = $message; + return $this; + } + public function addBackendsFile(string $path): self { $this->backends ??= new BackendsConfig(); @@ -92,6 +106,12 @@ public function jsonSerialize(): array if ($this->callbackUrl !== null) { $result['callback-url'] = $this->callbackUrl; } + if ($this->descriptionTemplate !== null) { + $result['description-template'] = $this->descriptionTemplate; + } + if ($this->successMessage !== null) { + $result['success-message'] = $this->successMessage; + } return $result; } diff --git a/src/Invoice/Application/CallbackUrl.php b/src/Invoice/Application/CallbackUrl.php index a576c2c..cef9c12 100644 --- a/src/Invoice/Application/CallbackUrl.php +++ b/src/Invoice/Application/CallbackUrl.php @@ -7,6 +7,7 @@ use PhpLightning\Invoice\Domain\CallbackUrl\CallbackUrlInterface; use PhpLightning\Invoice\Domain\CallbackUrl\LnAddressGeneratorInterface; use PhpLightning\Shared\Value\SendableRange; +use function sprintf; final class CallbackUrl implements CallbackUrlInterface { @@ -16,6 +17,7 @@ public function __construct( private SendableRange $sendableRange, private LnAddressGeneratorInterface $lnAddressGenerator, private string $callback, + private string $descriptionTemplate, ) { } @@ -25,7 +27,7 @@ public function getCallbackUrl(string $username): array // Modify the description if you want to custom it // This will be the description on the wallet that pays your ln address // TODO: Make this customizable from some external configuration file - $description = 'Pay to ' . $lnAddress; + $description = sprintf($this->descriptionTemplate, $lnAddress); // TODO: images not implemented yet; `',["image/jpeg;base64","' . base64_encode($response) . '"]';` $imageMetadata = ''; diff --git a/src/Invoice/Application/InvoiceGenerator.php b/src/Invoice/Application/InvoiceGenerator.php index ce4dc0e..be94f85 100644 --- a/src/Invoice/Application/InvoiceGenerator.php +++ b/src/Invoice/Application/InvoiceGenerator.php @@ -7,15 +7,16 @@ use PhpLightning\Invoice\Domain\BackendInvoice\BackendInvoiceInterface; use PhpLightning\Shared\Transfer\BackendInvoiceResponse; use PhpLightning\Shared\Value\SendableRange; +use function sprintf; final class InvoiceGenerator { - public const MESSAGE_PAYMENT_RECEIVED = 'Payment received!'; - public function __construct( private BackendInvoiceInterface $backendInvoice, private SendableRange $sendableRange, private string $lnAddress, + private string $descriptionTemplate, + private string $successMessage, ) { } @@ -27,10 +28,7 @@ public function generateInvoice(int $milliSats): array 'reason' => 'Amount is not between minimum and maximum sendable amount', ]; } - // Modify the description if you want to custom it - // This will be the description on the wallet that pays your ln address - // TODO: Make this customizable from some external configuration file - $description = 'Pay to ' . $this->lnAddress; + $description = sprintf($this->descriptionTemplate, $this->lnAddress); // TODO: images not implemented yet $imageMetadata = ''; @@ -48,7 +46,7 @@ private function mapResponseAsArray(BackendInvoiceResponse $invoice): array 'status' => $invoice->getStatus(), 'successAction' => [ 'tag' => 'message', - 'message' => self::MESSAGE_PAYMENT_RECEIVED, + 'message' => $this->successMessage, ], 'routes' => [], 'disposable' => false, diff --git a/src/Invoice/InvoiceConfig.php b/src/Invoice/InvoiceConfig.php index 8318481..3342419 100644 --- a/src/Invoice/InvoiceConfig.php +++ b/src/Invoice/InvoiceConfig.php @@ -54,6 +54,16 @@ public function getSendableRange(): SendableRange return $this->get('sendable-range', SendableRange::default()); } + public function getDescriptionTemplate(): string + { + return (string)$this->get('description-template', 'Pay to %s'); + } + + public function getSuccessMessage(): string + { + return (string)$this->get('success-message', 'Payment received!'); + } + public function getDomain(): string { return (string)$this->get('domain', $_SERVER['HTTP_HOST'] ?? 'localhost'); diff --git a/src/Invoice/InvoiceFactory.php b/src/Invoice/InvoiceFactory.php index 2e825e0..8e84734 100644 --- a/src/Invoice/InvoiceFactory.php +++ b/src/Invoice/InvoiceFactory.php @@ -29,6 +29,7 @@ public function createCallbackUrl(string $username): CallbackUrlInterface $this->getConfig()->getSendableRange(), $this->createLnAddressGenerator(), $this->getConfig()->getCallback(), + $this->getConfig()->getDescriptionTemplate(), ); } @@ -38,6 +39,8 @@ public function createInvoiceGenerator(string $username): InvoiceGenerator $this->getBackendForUser($username), $this->getConfig()->getSendableRange(), $this->getConfig()->getDefaultLnAddress(), + $this->getConfig()->getDescriptionTemplate(), + $this->getConfig()->getSuccessMessage(), ); } diff --git a/tests/Feature/InvoiceFacadeTest.php b/tests/Feature/InvoiceFacadeTest.php index a3a2080..b5fb364 100644 --- a/tests/Feature/InvoiceFacadeTest.php +++ b/tests/Feature/InvoiceFacadeTest.php @@ -45,7 +45,7 @@ public function test_ln_bits_feature(): void $this->bootstrapGacela(); $this->mockLnPaymentRequest(); - $json = $this->facade->generateInvoice('alice', 2_000, 'lnbits'); + $json = $this->facade->generateInvoice('alice', 2_000); self::assertEquals([ 'pr' => 'lnbc10u1pjzh489...fake payment_request', diff --git a/tests/Unit/Config/LightningConfigTest.php b/tests/Unit/Config/LightningConfigTest.php index 81a254f..f3e8041 100644 --- a/tests/Unit/Config/LightningConfigTest.php +++ b/tests/Unit/Config/LightningConfigTest.php @@ -56,4 +56,16 @@ public function test_sendable_range(): void 'sendable-range' => SendableRange::withMinMax(1_000, 5_000), ], $config->jsonSerialize()); } + + public function test_description_and_success_message(): void + { + $config = (new LightningConfig()) + ->setDescriptionTemplate('Pay to %s on example') + ->setSuccessMessage('Thanks!'); + + self::assertSame([ + 'description-template' => 'Pay to %s on example', + 'success-message' => 'Thanks!', + ], $config->jsonSerialize()); + } } diff --git a/tests/Unit/Invoice/Domain/CallbackUrl/CallbackUrlTest.php b/tests/Unit/Invoice/Domain/CallbackUrl/CallbackUrlTest.php index 17548ac..21801a3 100644 --- a/tests/Unit/Invoice/Domain/CallbackUrl/CallbackUrlTest.php +++ b/tests/Unit/Invoice/Domain/CallbackUrl/CallbackUrlTest.php @@ -25,6 +25,7 @@ public function test_get_callback_url(): void SendableRange::withMinMax(1_000, 5_000), $lnAddressGenerator, 'https://domain/receiver', + 'Pay to %s', ); self::assertEquals([ diff --git a/tests/Unit/Invoice/Domain/LnAddress/InvoiceGeneratorTest.php b/tests/Unit/Invoice/Domain/LnAddress/InvoiceGeneratorTest.php index c04a69b..3fa6101 100644 --- a/tests/Unit/Invoice/Domain/LnAddress/InvoiceGeneratorTest.php +++ b/tests/Unit/Invoice/Domain/LnAddress/InvoiceGeneratorTest.php @@ -21,6 +21,8 @@ public function test_invalid_amount(): void $invoiceFacade, SendableRange::withMinMax(1_000, 3_000), 'ln@address', + 'Pay to %s', + 'Payment received!', ); $actual = $invoice->generateInvoice(100); @@ -42,6 +44,8 @@ public function test_unknown_backend(): void $invoiceFacade, SendableRange::withMinMax(1_000, 3_000), 'ln@address', + 'Pay to %s', + 'Payment received!', ); $actual = $invoice->generateInvoice(2_000); @@ -70,6 +74,8 @@ public function test_successful_payment_request_with_amount(): void $invoiceFacade, SendableRange::withMinMax(1_000, 3_000), 'ln@address', + 'Pay to %s', + 'Payment received!', ); $actual = $invoice->generateInvoice(2_000); From 60435bd92f7e055c07d127fa9fcc325e1e55c93d Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 25 May 2025 12:07:31 +0200 Subject: [PATCH 2/3] fix: lint --- src/Invoice/Application/CallbackUrl.php | 1 + src/Invoice/Application/InvoiceGenerator.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Invoice/Application/CallbackUrl.php b/src/Invoice/Application/CallbackUrl.php index cef9c12..271c6bd 100644 --- a/src/Invoice/Application/CallbackUrl.php +++ b/src/Invoice/Application/CallbackUrl.php @@ -7,6 +7,7 @@ use PhpLightning\Invoice\Domain\CallbackUrl\CallbackUrlInterface; use PhpLightning\Invoice\Domain\CallbackUrl\LnAddressGeneratorInterface; use PhpLightning\Shared\Value\SendableRange; + use function sprintf; final class CallbackUrl implements CallbackUrlInterface diff --git a/src/Invoice/Application/InvoiceGenerator.php b/src/Invoice/Application/InvoiceGenerator.php index be94f85..9322892 100644 --- a/src/Invoice/Application/InvoiceGenerator.php +++ b/src/Invoice/Application/InvoiceGenerator.php @@ -7,6 +7,7 @@ use PhpLightning\Invoice\Domain\BackendInvoice\BackendInvoiceInterface; use PhpLightning\Shared\Transfer\BackendInvoiceResponse; use PhpLightning\Shared\Value\SendableRange; + use function sprintf; final class InvoiceGenerator From 68282a51d689a825ba7094c0fd7c8ee486a48303 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sun, 25 May 2025 12:08:16 +0200 Subject: [PATCH 3/3] fix: ci actions --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d22284..f6060b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: name: Coding Guidelines runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: @@ -27,7 +27,7 @@ jobs: run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache dependencies - uses: actions/cache@v3.3.1 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -43,7 +43,7 @@ jobs: name: Type Checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: @@ -56,7 +56,7 @@ jobs: run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache dependencies - uses: actions/cache@v3.3.1 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -82,7 +82,7 @@ jobs: operating-system: - "ubuntu-latest" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: @@ -95,7 +95,7 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache dependencies - uses: actions/cache@v3.3.1 + uses: actions/cache@v4 with: path: ${{ steps.composercache.outputs.dir }} key: "php-${{ matrix.php-version }}-${{ matrix.dependencies }}-${{ hashFiles('**/composer.lock') }}"