fix: direct fiat payments (#4116)

Co-authored-by: Arc <33088785+arcbtc@users.noreply.github.com>
This commit is contained in:
Vlad Stan 2026-07-31 16:22:55 +03:00 committed by GitHub
parent f981ee2bca
commit 51e585c78c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 72 additions and 0 deletions

View file

@ -275,6 +275,9 @@ class CreateInvoice(BaseModel):
labels: list[str] = []
external_id: str | None = Query(default=None, max_length=256)
def is_fiat_subscription(self) -> bool:
return (self.extra or {}).get("fiat_method") == "subscription"
@validator("payment_hash")
def check_hex(cls, v):
if v:

View file

@ -118,6 +118,8 @@ async def create_payment_request(
Create a lightning invoice or a fiat payment request.
"""
if invoice_data.fiat_provider:
if invoice_data.is_fiat_subscription():
raise ValueError("Cannot create direct fiat subscription payments.")
return await create_fiat_invoice(wallet_id, invoice_data)
return await create_wallet_invoice(wallet_id, invoice_data)

View file

@ -233,6 +233,40 @@ async def test_create_fiat_invoice(
assert invoice["extra"]["fiat_payment_request"] == fiat_payment_request
@pytest.mark.anyio
async def test_create_fiat_subscription_invoice_rejected(
client, inkey_headers_to, mocker: MockerFixture
):
fiat_mock = mocker.patch(
"lnbits.core.services.payments.create_fiat_invoice",
AsyncMock(),
)
response = await client.post(
"/api/v1/payments",
headers=inkey_headers_to,
json={
"unit": "USD",
"out": False,
"amount": 2100,
"fiat_provider": "stripe",
"extra": {
"fiat_method": "subscription",
"subscription": {
"checking_id": "fiat_stripe_cs_paid_session",
"payment_request": "",
},
},
},
)
assert response.status_code == 400
assert response.json()["detail"] == (
"Cannot create direct fiat subscription payments."
)
fiat_mock.assert_not_awaited()
@pytest.mark.anyio
@pytest.mark.parametrize("currency", ("msat", "RRR"))
async def test_create_invoice_validates_used_currency(

View file

@ -75,6 +75,39 @@ async def test_create_payment_request_routes_by_invoice_type(mocker: MockerFixtu
fiat_mock.assert_awaited_once()
@pytest.mark.anyio
@pytest.mark.parametrize("fiat_provider", ("stripe", "square", "paypal"))
async def test_create_payment_request_rejects_fiat_subscription(
fiat_provider: str, mocker: MockerFixture
):
fiat_mock = mocker.patch(
"lnbits.core.services.payments.create_fiat_invoice",
mocker.AsyncMock(),
)
with pytest.raises(
ValueError,
match="Cannot create direct fiat subscription payments.",
):
await create_payment_request(
"wallet-1",
CreateInvoice(
unit="USD",
amount=2100,
fiat_provider=fiat_provider,
extra={
"fiat_method": "subscription",
"subscription": {
"checking_id": "fiat_stripe_cs_paid_session",
"payment_request": "",
},
},
),
)
fiat_mock.assert_not_awaited()
@pytest.mark.anyio
async def test_update_pending_payment_and_bulk_pending_updates(mocker: MockerFixture):
wallet = await _create_wallet()