mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2024-11-20 18:51:05 +01:00
93 lines
2.8 KiB
Python
93 lines
2.8 KiB
Python
import hashlib
|
|
|
|
from fastapi.params import Query
|
|
from lnurl import ( # type: ignore
|
|
LnurlErrorResponse,
|
|
LnurlPayActionResponse,
|
|
LnurlPayResponse,
|
|
)
|
|
from starlette.requests import Request
|
|
|
|
from lnbits.core.services import create_invoice
|
|
from lnbits.extensions.offlineshop.models import Item
|
|
from lnbits.utils.exchange_rates import fiat_amount_as_satoshis
|
|
|
|
from . import offlineshop_ext
|
|
from .crud import get_item, get_shop
|
|
|
|
|
|
@offlineshop_ext.get("/lnurl/{item_id}", name="offlineshop.lnurl_response")
|
|
async def lnurl_response(req: Request, item_id: int = Query(...)):
|
|
item = await get_item(item_id) # type: Item
|
|
if not item:
|
|
return {"status": "ERROR", "reason": "Item not found."}
|
|
|
|
if not item.enabled:
|
|
return {"status": "ERROR", "reason": "Item disabled."}
|
|
|
|
price_msat = (
|
|
await fiat_amount_as_satoshis(item.price, item.unit)
|
|
if item.unit != "sat"
|
|
else item.price
|
|
) * 1000
|
|
|
|
resp = LnurlPayResponse(
|
|
callback=req.url_for("offlineshop.lnurl_callback", item_id=item.id),
|
|
min_sendable=price_msat,
|
|
max_sendable=price_msat,
|
|
metadata=await item.lnurlpay_metadata(),
|
|
)
|
|
|
|
return resp.dict()
|
|
|
|
|
|
@offlineshop_ext.get("/lnurl/cb/{item_id}", name="offlineshop.lnurl_callback")
|
|
async def lnurl_callback(request: Request, item_id: int):
|
|
item = await get_item(item_id) # type: Item
|
|
if not item:
|
|
return {"status": "ERROR", "reason": "Couldn't find item."}
|
|
|
|
if item.unit == "sat":
|
|
min = item.price * 1000
|
|
max = item.price * 1000
|
|
else:
|
|
price = await fiat_amount_as_satoshis(item.price, item.unit)
|
|
# allow some fluctuation (the fiat price may have changed between the calls)
|
|
min = price * 995
|
|
max = price * 1010
|
|
|
|
amount_received = int(request.query_params.get("amount") or 0)
|
|
if amount_received < min:
|
|
return LnurlErrorResponse(
|
|
reason=f"Amount {amount_received} is smaller than minimum {min}."
|
|
).dict()
|
|
elif amount_received > max:
|
|
return LnurlErrorResponse(
|
|
reason=f"Amount {amount_received} is greater than maximum {max}."
|
|
).dict()
|
|
|
|
shop = await get_shop(item.shop)
|
|
|
|
try:
|
|
payment_hash, payment_request = await create_invoice(
|
|
wallet_id=shop.wallet,
|
|
amount=int(amount_received / 1000),
|
|
memo=item.name,
|
|
description_hash=hashlib.sha256(
|
|
(await item.lnurlpay_metadata()).encode("utf-8")
|
|
).digest(),
|
|
extra={"tag": "offlineshop", "item": item.id},
|
|
)
|
|
except Exception as exc:
|
|
return LnurlErrorResponse(reason=exc.message).dict()
|
|
|
|
resp = LnurlPayActionResponse(
|
|
pr=payment_request,
|
|
success_action=item.success_action(shop, payment_hash, request)
|
|
if shop.method
|
|
else None,
|
|
routes=[],
|
|
)
|
|
|
|
return resp.dict()
|