From 8b3af03519c06437325e32e78a71febf9f91d3a1 Mon Sep 17 00:00:00 2001 From: Gene Takavic Date: Sun, 25 Sep 2022 17:01:22 +0200 Subject: [PATCH] webhook to pay_invoice --- lnbits/core/services.py | 31 ++++++++++++++++- lnbits/extensions/boltcards/lnurl.py | 42 ++++++++---------------- lnbits/extensions/boltcards/views_api.py | 5 --- lnbits/extensions/withdraw/lnurl.py | 30 +++++++---------- 4 files changed, 56 insertions(+), 52 deletions(-) diff --git a/lnbits/core/services.py b/lnbits/core/services.py index 10693f4b..aeb4f938 100644 --- a/lnbits/core/services.py +++ b/lnbits/core/services.py @@ -2,7 +2,7 @@ import asyncio import json from binascii import unhexlify from io import BytesIO -from typing import Dict, Optional, Tuple +from typing import Dict, Optional, Tuple, Union from urllib.parse import parse_qs, urlparse import httpx @@ -102,6 +102,7 @@ async def pay_invoice( extra: Optional[Dict] = None, description: str = "", conn: Optional[Connection] = None, + webhook: Optional[Union[str, tuple]] = None, ) -> str: """ Pay a Lightning invoice. @@ -231,6 +232,34 @@ async def pay_invoice( f"didn't receive checking_id from backend, payment may be stuck in database: {temp_id}" ) + if type(webhook) is str: + webhook_url = webhook + elif type(webhook) is tuple: + webhook_url = webhook[0] + additionals = webhook[1] + else: + webhook_url = None + + if webhook_url: + async with httpx.AsyncClient() as client: + try: + json = { + "payment_hash": invoice.payment_hash, + "payment_request": payment_request, + "amount": int(invoice.amount_msat / 1000), + } + if type(additionals) is dict: + json.update(additionals) + + r = await client.post( + webhook_url, + json=json, + timeout=40, + ) + except Exception as exc: + # webhook fails shouldn't cause the lnurlw to fail since invoice is already paid + logger.error("Caught exception when dispatching webhook url:", exc) + return invoice.payment_hash diff --git a/lnbits/extensions/boltcards/lnurl.py b/lnbits/extensions/boltcards/lnurl.py index be3e09d8..320b1666 100644 --- a/lnbits/extensions/boltcards/lnurl.py +++ b/lnbits/extensions/boltcards/lnurl.py @@ -1,19 +1,12 @@ -import base64 -import hashlib -import hmac import json import secrets from http import HTTPStatus -from io import BytesIO -from typing import Optional from urllib.parse import urlparse -import httpx from embit import bech32, compact from fastapi import Request from fastapi.param_functions import Query from fastapi.params import Depends, Query -from lnurl import Lnurl, LnurlWithdrawResponse from lnurl import encode as lnurl_encode # type: ignore from lnurl.types import LnurlPayMetadata # type: ignore from loguru import logger @@ -34,7 +27,6 @@ from .crud import ( get_hit, get_hits_today, spend_hit, - update_card, update_card_counter, update_card_otp, ) @@ -120,32 +112,26 @@ async def lnurl_callback( invoice = bolt11.decode(pr) hit = await spend_hit(id=hit.id, amount=int(invoice.amount_msat / 1000)) try: - payment_hash = await pay_invoice( + webhook = ( + ( + card.webhook_url, + { + "notification": "card_payment", + "card_external_id": card.external_id, + "card_name": card.card_name, + }, + ) + if card.webhook_url + else None + ) + await pay_invoice( wallet_id=card.wallet, payment_request=pr, max_sat=card.tx_limit, extra={"tag": "boltcard", "tag": hit.id}, + webhook=webhook, ) - if card.webhook_url: - async with httpx.AsyncClient() as client: - try: - r = await client.post( - card.webhook_url, - json={ - "notification": "card_payment", - "payment_hash": payment_hash, - "payment_request": pr, - "card_external_id": card.external_id, - "card_name": card.card_name, - "amount": int(invoice.amount_msat / 1000), - }, - timeout=40, - ) - except Exception as exc: - # webhook fails shouldn't cause the lnurlw to fail since invoice is already paid - logger.error("Caught exception when dispatching webhook url:", exc) - return {"status": "OK"} except: return {"status": "ERROR", "reason": f"Payment failed"} diff --git a/lnbits/extensions/boltcards/views_api.py b/lnbits/extensions/boltcards/views_api.py index 7b8357cf..2fc11dbc 100644 --- a/lnbits/extensions/boltcards/views_api.py +++ b/lnbits/extensions/boltcards/views_api.py @@ -12,21 +12,16 @@ from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key from . import boltcards_ext from .crud import ( create_card, - create_hit, delete_card, enable_disable_card, get_card, - get_card_by_otp, get_card_by_uid, get_cards, get_hits, get_refunds, update_card, - update_card_counter, - update_card_otp, ) from .models import CreateCardData -from .nxp424 import decryptSUN, getSunMAC @boltcards_ext.get("/api/v1/cards") diff --git a/lnbits/extensions/withdraw/lnurl.py b/lnbits/extensions/withdraw/lnurl.py index 18a99599..3379fd17 100644 --- a/lnbits/extensions/withdraw/lnurl.py +++ b/lnbits/extensions/withdraw/lnurl.py @@ -3,7 +3,6 @@ import traceback from datetime import datetime from http import HTTPStatus -import httpx import shortuuid # type: ignore from fastapi import HTTPException from fastapi.param_functions import Query @@ -115,29 +114,24 @@ async def api_lnurl_callback( payment_request = pr - payment_hash = await pay_invoice( + webhook = ( + ( + link.webhook_url, + { + "lnurlw": link.id, + }, + ) + if link.webhook_url + else None + ) + await pay_invoice( wallet_id=link.wallet, payment_request=payment_request, max_sat=link.max_withdrawable, extra={"tag": "withdraw"}, + webhook=webhook, ) - if link.webhook_url: - async with httpx.AsyncClient() as client: - try: - r = await client.post( - link.webhook_url, - json={ - "payment_hash": payment_hash, - "payment_request": payment_request, - "lnurlw": link.id, - }, - timeout=40, - ) - except Exception as exc: - # webhook fails shouldn't cause the lnurlw to fail since invoice is already paid - logger.error("Caught exception when dispatching webhook url:", exc) - return {"status": "OK"} except Exception as e: