mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-22 14:22:55 +01:00
118 lines
3.5 KiB
Python
118 lines
3.5 KiB
Python
import json
|
|
import hashlib
|
|
import math
|
|
from lnurl import LnurlPayResponse, LnurlPayActionResponse, LnurlErrorResponse # type: ignore
|
|
from lnurl.types import LnurlPayMetadata
|
|
from lnbits.core.services import create_invoice
|
|
from hashlib import md5
|
|
from fastapi import Request
|
|
from fastapi.param_functions import Query
|
|
from . import lnurlpos_ext
|
|
from fastapi.templating import Jinja2Templates
|
|
from starlette.exceptions import HTTPException
|
|
from starlette.responses import HTMLResponse
|
|
from http import HTTPStatus
|
|
from fastapi.params import Depends
|
|
from fastapi.param_functions import Query
|
|
from .crud import (
|
|
get_lnurlpos,
|
|
create_lnurlpospayment,
|
|
get_lnurlpospayment,
|
|
update_lnurlpospayment,
|
|
)
|
|
from lnbits.utils.exchange_rates import fiat_amount_as_satoshis
|
|
|
|
|
|
@lnurlpos_ext.get(
|
|
"/api/v1/lnurl/{nonce}/{payload}/{pos_id}",
|
|
status_code=HTTPStatus.OK,
|
|
name="lnurlpos.lnurl_response",
|
|
)
|
|
async def lnurl_response(
|
|
request: Request,
|
|
nonce: str = Query(None),
|
|
pos_id: str = Query(None),
|
|
payload: str = Query(None),
|
|
):
|
|
pos = await get_lnurlpos(pos_id)
|
|
if not pos:
|
|
raise HTTPException(
|
|
status_code=HTTPStatus.NOT_FOUND, detail="lnurlpos not found."
|
|
)
|
|
nonce1 = bytes.fromhex(nonce)
|
|
payload1 = bytes.fromhex(payload)
|
|
h = hashlib.sha256(nonce1)
|
|
h.update(pos.key.encode())
|
|
s = h.digest()
|
|
res = bytearray(payload1)
|
|
for i in range(len(res)):
|
|
res[i] = res[i] ^ s[i]
|
|
decryptedAmount = float(int.from_bytes(res[2:6], "little") / 100)
|
|
decryptedPin = int.from_bytes(res[:2], "little")
|
|
if type(decryptedAmount) != float:
|
|
raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not an amount.")
|
|
price_msat = (
|
|
await fiat_amount_as_satoshis(decryptedAmount, pos.currency)
|
|
if pos.currency != "sat"
|
|
else pos.currency
|
|
) * 1000
|
|
|
|
lnurlpospayment = await create_lnurlpospayment(
|
|
posid=pos.id,
|
|
payload=payload,
|
|
sats=price_msat,
|
|
pin=decryptedPin,
|
|
payhash="payment_hash",
|
|
)
|
|
|
|
if not lnurlpospayment:
|
|
raise HTTPException(
|
|
status_code=HTTPStatus.FORBIDDEN, detail="Could not create payment"
|
|
)
|
|
|
|
resp = LnurlPayResponse(
|
|
callback=request.url_for(
|
|
"lnurlpos.lnurl_callback", paymentid=lnurlpospayment.id
|
|
),
|
|
min_sendable=price_msat,
|
|
max_sendable=price_msat,
|
|
metadata=await pos.lnurlpay_metadata(),
|
|
)
|
|
|
|
return resp.dict()
|
|
|
|
|
|
@lnurlpos_ext.get(
|
|
"/api/v1/lnurl/cb/{paymentid}",
|
|
status_code=HTTPStatus.OK,
|
|
name="lnurlpos.lnurl_callback",
|
|
)
|
|
async def lnurl_callback(request: Request, paymentid: str = Query(None)):
|
|
print("lnurlpospayment")
|
|
lnurlpospayment = await get_lnurlpospayment(paymentid)
|
|
print(lnurlpospayment)
|
|
pos = await get_lnurlpos(lnurlpospayment.posid)
|
|
if not pos:
|
|
raise HTTPException(
|
|
status_code=HTTPStatus.FORBIDDEN, detail="lnurlpos not found."
|
|
)
|
|
payment_hash, payment_request = await create_invoice(
|
|
wallet_id=pos.wallet,
|
|
amount=int(lnurlpospayment.sats / 1000),
|
|
memo=pos.title,
|
|
description_hash=hashlib.sha256(
|
|
(await pos.lnurlpay_metadata()).encode("utf-8")
|
|
).digest(),
|
|
extra={"tag": "lnurlpos"},
|
|
)
|
|
lnurlpospayment = await update_lnurlpospayment(
|
|
lnurlpospayment_id=paymentid, payhash=payment_hash
|
|
)
|
|
|
|
resp = LnurlPayActionResponse(
|
|
pr=payment_request,
|
|
success_action=pos.success_action(paymentid, request),
|
|
routes=[],
|
|
)
|
|
|
|
return resp.dict()
|