diff --git a/helpers.py b/helpers.py index fdc8f96..02c0b68 100644 --- a/helpers.py +++ b/helpers.py @@ -18,29 +18,32 @@ async def register_atm_payment( """ # create a new lnurlpayment record data = base64.urlsafe_b64decode(payload) + payload = payload.replace("=", "") decrypted = xor_decrypt(device.key.encode(), data) - price_msat = ( - await fiat_amount_as_satoshis(float(decrypted[1]) / 100, device.currency) * 1000 - if device.currency != "sat" - else decrypted[1] * 1000 - ) - price_msat = int(price_msat - ((price_msat / 100) * device.profit)) lnurldevicepayment = await get_recent_lnurldevicepayment(payload) # If the payment is already registered and been paid, return None if lnurldevicepayment and lnurldevicepayment.payload == lnurldevicepayment.payhash: - return None, price_msat + return None, lnurldevicepayment.sats * 1000 # If the payment is already registered and not been paid, return lnurlpayment record if lnurldevicepayment and lnurldevicepayment.payload != lnurldevicepayment.payhash: - return lnurldevicepayment, price_msat + return lnurldevicepayment, lnurldevicepayment.sats * 1000 + price_msat = ( + await fiat_amount_as_satoshis(float(decrypted[1]) / 100, device.currency) * 1000 + if device.currency != "sat" + else decrypted[1] * 1000 + ) + price_msat = int(price_msat - ((price_msat / 100) * device.profit)) + sats = int(price_msat / 1000) lnurldevicepayment = await create_lnurldevicepayment( deviceid=device.id, payload=payload, - sats=int(price_msat / 1000), + sats=sats, pin=decrypted[0], payhash="payment_hash", ) + price_msat = sats * 1000 return lnurldevicepayment, price_msat diff --git a/views.py b/views.py index 7eff4bb..e68b304 100644 --- a/views.py +++ b/views.py @@ -17,8 +17,8 @@ from lnurl import encode as lnurl_encode from loguru import logger -from .crud import get_lnurldevice, get_lnurldevicepayment, get_recent_lnurldevicepayment -from .helpers import xor_decrypt +from .crud import get_lnurldevice, get_lnurldevicepayment +from .helpers import register_atm_payment, xor_decrypt lnurldevice_generic_router = APIRouter() @@ -97,7 +97,7 @@ async def atmpage(request: Request, lightning: str): logger.debug(access) # Attempt to get recent payment information - recent_pay_attempt = await get_recent_lnurldevicepayment(p) + lnurldevicepayment, price_msat = await register_atm_payment(device, p) # Render the response template return lnurldevice_renderer().TemplateResponse( @@ -105,15 +105,15 @@ async def atmpage(request: Request, lightning: str): { "request": request, "lnurl": lightning, - "amount": int(((int(price_msat) / 100) * device.profit) + int(price_msat)), + "amount": lnurldevicepayment.sats, "device_id": device.id, "boltz": True if access else False, "p": p, - "recentpay": recent_pay_attempt.id if recent_pay_attempt else False, + "recentpay": lnurldevicepayment.id if lnurldevicepayment else False, "used": ( True - if recent_pay_attempt - and recent_pay_attempt.payload == recent_pay_attempt.payhash + if lnurldevicepayment + and lnurldevicepayment.payload == lnurldevicepayment.payhash else False ), }, diff --git a/views_lnurl.py b/views_lnurl.py index 0be4f0d..2d882b2 100644 --- a/views_lnurl.py +++ b/views_lnurl.py @@ -7,6 +7,7 @@ from lnbits.core.services import create_invoice from lnbits.core.views.api import pay_invoice from lnbits.utils.exchange_rates import fiat_amount_as_satoshis +from starlette.exceptions import HTTPException from .crud import ( create_lnurldevicepayment, @@ -153,7 +154,7 @@ async def lnurl_params( if atm: lnurldevicepayment, price_msat = await register_atm_payment(device, p) if not lnurldevicepayment: - return {"status": "ERROR", "reason": "Could not create ATM payment."} + return {"status": "ERROR", "reason": "Payment already claimed."} return { "tag": "withdrawRequest", "callback": str( @@ -161,7 +162,7 @@ async def lnurl_params( "lnurldevice.lnurl_callback", paymentid=lnurldevicepayment.id ) ), - "k1": p, + "k1": lnurldevicepayment.payload, "minWithdrawable": price_msat, "maxWithdrawable": price_msat, "defaultDescription": f"{device.title} ID: {lnurldevicepayment.id}", @@ -213,8 +214,12 @@ async def lnurl_callback( return {"status": "ERROR", "reason": "lnurldevice not found."} if device.device == "atm": if lnurldevicepayment.payload == lnurldevicepayment.payhash: - await delete_atm_payment_link(paymentid) - return {"status": "ERROR", "reason": "Payment already claimed"} + return {"status": "ERROR", "reason": "Payment already claimed."} + if lnurldevicepayment.payhash == "pending": + return { + "status": "ERROR", + "reason": "Pending. If you are unable to withdraw contact vendor", + } if not pr: await delete_atm_payment_link(paymentid) return {"status": "ERROR", "reason": "No payment request."} @@ -234,10 +239,9 @@ async def lnurl_callback( await delete_atm_payment_link(paymentid) return {"status": "ERROR", "reason": "Bad K1"} if lnurldevicepayment.payhash != "payment_hash": - await delete_atm_payment_link(paymentid) return {"status": "ERROR", "reason": "Payment already claimed"} try: - lnurldevicepayment.payhash = lnurldevicepayment.payload + lnurldevicepayment.payhash = "pending" lnurldevicepayment_updated = await update_lnurldevicepayment( lnurldevicepayment ) @@ -245,17 +249,25 @@ async def lnurl_callback( await pay_invoice( wallet_id=device.wallet, payment_request=pr, - max_sat=int(lnurldevicepayment_updated.sats / 1000), + max_sat=int(lnurldevicepayment_updated.sats) + 100, extra={"tag": "lnurldevice_withdraw"}, ) - except Exception: + lnurldevicepayment.payhash = lnurldevicepayment.payload + lnurldevicepayment_updated = await update_lnurldevicepayment( + lnurldevicepayment + ) + assert lnurldevicepayment_updated + return {"status": "OK"} + except HTTPException as e: + return {"status": "ERROR", "reason": str(e)} + except Exception as e: lnurldevicepayment.payhash = "payment_hash" lnurldevicepayment_updated = await update_lnurldevicepayment( lnurldevicepayment ) assert lnurldevicepayment_updated - return {"status": "ERROR", "reason": "Failed to make payment."} - return {"status": "OK"} + return {"status": "ERROR", "reason": str(e)} + if device.device == "switch": if not amount: return {"status": "ERROR", "reason": "No amount"}