fix: webhook call on invoice pay (#3119)
This commit is contained in:
parent
56c8783d9a
commit
6c2b312c92
4 changed files with 25 additions and 14 deletions
|
|
@ -508,7 +508,7 @@ async def is_internal_status_success(
|
||||||
return payment.status == PaymentState.SUCCESS.value
|
return payment.status == PaymentState.SUCCESS.value
|
||||||
|
|
||||||
|
|
||||||
async def mark_webhook_sent(payment_hash: str, status: int) -> None:
|
async def mark_webhook_sent(payment_hash: str, status: str) -> None:
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""
|
"""
|
||||||
UPDATE apipayments SET webhook_status = :status
|
UPDATE apipayments SET webhook_status = :status
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ class Payment(BaseModel):
|
||||||
memo: str | None = None
|
memo: str | None = None
|
||||||
expiry: datetime | None = None
|
expiry: datetime | None = None
|
||||||
webhook: str | None = None
|
webhook: str | None = None
|
||||||
webhook_status: int | None = None
|
webhook_status: str | None = None
|
||||||
preimage: str | None = None
|
preimage: str | None = None
|
||||||
tag: str | None = None
|
tag: str | None = None
|
||||||
extension: str | None = None
|
extension: str | None = None
|
||||||
|
|
|
||||||
|
|
@ -205,24 +205,23 @@ async def dispatch_webhook(payment: Payment):
|
||||||
logger.debug("sending webhook", payment.webhook)
|
logger.debug("sending webhook", payment.webhook)
|
||||||
|
|
||||||
if not payment.webhook:
|
if not payment.webhook:
|
||||||
return await mark_webhook_sent(payment.payment_hash, -1)
|
return await mark_webhook_sent(payment.payment_hash, "-1")
|
||||||
|
|
||||||
headers = {"User-Agent": settings.user_agent}
|
headers = {"User-Agent": settings.user_agent}
|
||||||
async with httpx.AsyncClient(headers=headers) as client:
|
async with httpx.AsyncClient(headers=headers) as client:
|
||||||
data = payment.dict()
|
|
||||||
try:
|
try:
|
||||||
check_callback_url(payment.webhook)
|
check_callback_url(payment.webhook)
|
||||||
r = await client.post(payment.webhook, json=data, timeout=40)
|
r = await client.post(payment.webhook, json=payment.json(), timeout=40)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
await mark_webhook_sent(payment.payment_hash, r.status_code)
|
await mark_webhook_sent(payment.payment_hash, str(r.status_code))
|
||||||
except httpx.HTTPStatusError as exc:
|
except httpx.HTTPStatusError as exc:
|
||||||
await mark_webhook_sent(payment.payment_hash, exc.response.status_code)
|
await mark_webhook_sent(payment.payment_hash, str(exc.response.status_code))
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"webhook returned a bad status_code: {exc.response.status_code} "
|
f"webhook returned a bad status_code: {exc.response.status_code} "
|
||||||
f"while requesting {exc.request.url!r}."
|
f"while requesting {exc.request.url!r}."
|
||||||
)
|
)
|
||||||
except httpx.RequestError:
|
except httpx.RequestError:
|
||||||
await mark_webhook_sent(payment.payment_hash, -1)
|
await mark_webhook_sent(payment.payment_hash, "-1")
|
||||||
logger.warning(f"Could not send webhook to {payment.webhook}")
|
logger.warning(f"Could not send webhook to {payment.webhook}")
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -230,18 +229,21 @@ async def send_payment_notification(wallet: Wallet, payment: Payment):
|
||||||
try:
|
try:
|
||||||
await send_ws_payment_notification(wallet, payment)
|
await send_ws_payment_notification(wallet, payment)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error sending websocket payment notification", e)
|
logger.error(f"Error sending websocket payment notification {e!s}")
|
||||||
try:
|
try:
|
||||||
send_chat_payment_notification(wallet, payment)
|
send_chat_payment_notification(wallet, payment)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error sending chat payment notification", e)
|
logger.error(f"Error sending chat payment notification {e!s}")
|
||||||
try:
|
try:
|
||||||
await send_payment_push_notification(wallet, payment)
|
await send_payment_push_notification(wallet, payment)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error sending push payment notification", e)
|
logger.error(f"Error sending push payment notification {e!s}")
|
||||||
|
|
||||||
if payment.webhook and not payment.webhook_status:
|
try:
|
||||||
await dispatch_webhook(payment)
|
if payment.webhook and not payment.webhook_status:
|
||||||
|
await dispatch_webhook(payment)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error dispatching webhook: {e!s}")
|
||||||
|
|
||||||
|
|
||||||
async def send_ws_payment_notification(wallet: Wallet, payment: Payment):
|
async def send_ws_payment_notification(wallet: Wallet, payment: Payment):
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ from bolt11.types import MilliSatoshi
|
||||||
from pytest_mock.plugin import MockerFixture
|
from pytest_mock.plugin import MockerFixture
|
||||||
|
|
||||||
from lnbits.core.crud import get_standalone_payment, get_wallet
|
from lnbits.core.crud import get_standalone_payment, get_wallet
|
||||||
|
from lnbits.core.crud.payments import get_payment
|
||||||
from lnbits.core.models import Payment, PaymentState, Wallet
|
from lnbits.core.models import Payment, PaymentState, Wallet
|
||||||
from lnbits.core.services import create_invoice, pay_invoice
|
from lnbits.core.services import create_invoice, pay_invoice
|
||||||
from lnbits.exceptions import InvoiceError, PaymentError
|
from lnbits.exceptions import InvoiceError, PaymentError
|
||||||
|
|
@ -179,7 +180,12 @@ async def test_notification_for_internal_payment(to_wallet: Wallet):
|
||||||
invoice_queue: asyncio.Queue = asyncio.Queue()
|
invoice_queue: asyncio.Queue = asyncio.Queue()
|
||||||
register_invoice_listener(invoice_queue, test_name)
|
register_invoice_listener(invoice_queue, test_name)
|
||||||
|
|
||||||
payment = await create_invoice(wallet_id=to_wallet.id, amount=123, memo=test_name)
|
payment = await create_invoice(
|
||||||
|
wallet_id=to_wallet.id,
|
||||||
|
amount=123,
|
||||||
|
memo=test_name,
|
||||||
|
webhook="http://test.404.lnbits.com",
|
||||||
|
)
|
||||||
await pay_invoice(
|
await pay_invoice(
|
||||||
wallet_id=to_wallet.id, payment_request=payment.bolt11, extra={"tag": "lnurlp"}
|
wallet_id=to_wallet.id, payment_request=payment.bolt11, extra={"tag": "lnurlp"}
|
||||||
)
|
)
|
||||||
|
|
@ -192,6 +198,9 @@ async def test_notification_for_internal_payment(to_wallet: Wallet):
|
||||||
assert _payment.status == PaymentState.SUCCESS.value
|
assert _payment.status == PaymentState.SUCCESS.value
|
||||||
assert _payment.bolt11 == payment.bolt11
|
assert _payment.bolt11 == payment.bolt11
|
||||||
assert _payment.amount == 123_000
|
assert _payment.amount == 123_000
|
||||||
|
updated_payment = await get_payment(_payment.checking_id)
|
||||||
|
assert updated_payment.webhook_status == "404"
|
||||||
|
|
||||||
break # we found our payment, success
|
break # we found our payment, success
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue