Skip to content

Commit

Permalink
Merge pull request #64 from lnbits/atm_withdraw_boltcard
Browse files Browse the repository at this point in the history
allow withdraw with boltcard
  • Loading branch information
arcbtc authored Feb 8, 2024
2 parents 1314d54 + 7dcffb3 commit f981e7e
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 5 deletions.
50 changes: 47 additions & 3 deletions templates/tpos/tpos.html
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,9 @@ <h5 class="q-mt-none q-mb-sm">
// if searchTerm entered, filter out items that don't match
if (this.searchTerm) {
items = items.filter(item => {
return item.title.toLowerCase().includes(this.searchTerm.toLowerCase())
return item.title
.toLowerCase()
.includes(this.searchTerm.toLowerCase())
})
}
// if categoryFilter entered, filter out items that don't match
Expand Down Expand Up @@ -920,6 +922,7 @@ <h5 class="q-mt-none q-mb-sm">
lnurl = res.data.lnurl
dialog.data = {payment_request: lnurl}
dialog.show = true
self.readNfcTag()
dialog.dismissMsg = self.$q.notify({
timeout: 0,
message: 'Withdraw...'
Expand Down Expand Up @@ -949,6 +952,7 @@ <h5 class="q-mt-none q-mb-sm">
self.atmToken = ''
self.complete.show = true
self.atmMode = false
this.connectionWithdraw.close()
}
}
this.getRates()
Expand Down Expand Up @@ -1108,7 +1112,9 @@ <h5 class="q-mt-none q-mb-sm">

this.nfcTagReading = true
this.$q.notify({
message: 'Tap your NFC tag to pay this invoice with LNURLw.'
message: this.atmMode
? 'Tap your NFC tag to withdraw with LNURLp.'
: 'Tap your NFC tag to pay this invoice with LNURLw.'
})

return ndef.scan({signal: readerAbortController.signal}).then(() => {
Expand Down Expand Up @@ -1136,7 +1142,15 @@ <h5 class="q-mt-none q-mb-sm">

//User feedback, show loader icon
self.nfcTagReading = false
self.payInvoice(lnurl, readerAbortController)
if (self.atmMode) {
LNbits.api
.request('GET', `${lnurl.replace('lnurlw://', 'https://')}`)
.then(res => {
self.makeWithdraw(res.data.payLink)
})
} else {
self.payInvoice(lnurl, readerAbortController)
}

this.$q.notify({
type: 'positive',
Expand All @@ -1154,6 +1168,36 @@ <h5 class="q-mt-none q-mb-sm">
})
}
},
makeWithdraw(payLink, readerAbortController) {
if (!payLink) {
this.$q.notify({
type: 'negative',
message: 'LNURL not found in NFC tag.'
})
return
}
LNbits.api
.request(
'GET',
`/tpos/api/v1/atm/withdraw/${this.atmToken}/${this.sat}/pay?payLink=${payLink}`
)
.then(res => {
if (!res.data.success) {
this.$q.notify({
type: 'negative',
message: res.data.detail
})
} else {
this.stack = []
this.total = 0.0
this.$q.notify({
type: 'positive',
message: 'Topup successful!'
})
}
readerAbortController.abort()
})
},
payInvoice: function (lnurl, readerAbortController) {
const self = this

Expand Down
61 changes: 59 additions & 2 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
from lnbits.core.views.api import api_payment
from lnbits.decorators import (
WalletTypeInfo,
check_admin,
get_key_type,
require_admin_key,
require_invoice_key,
)
from lnbits.utils.exchange_rates import get_fiat_rate_satoshis

Expand Down Expand Up @@ -245,6 +243,65 @@ async def api_tpos_atm_pin_check(tpos_id: str, atmpin: int):
return token


@tpos_ext.get("/api/v1/atm/withdraw/{k1}/{amount}/pay", status_code=HTTPStatus.OK)
async def api_tpos_atm_pay(
request: Request, k1: str, amount: int, payLink: str = Query(...)
):
try:
# get the payment_request from the lnurl
payLink = payLink.replace("lnurlp://", "https://")
logger.debug(payLink)
async with httpx.AsyncClient() as client:
headers = {"user-agent": f"lnbits/tpos"}
r = await client.get(payLink, follow_redirects=True, headers=headers)
if r.is_error:
return {"success": False, "detail": "Error loading"}
resp = r.json()

amount = amount * 1000 # convert to msats

if resp["tag"] != "payRequest":
return {"success": False, "detail": "Wrong tag type"}

if amount < resp["minSendable"]:
return {"success": False, "detail": "Amount too low"}

if amount > resp["maxSendable"]:
return {"success": False, "detail": "Amount too high"}

cb_res = await client.get(
resp["callback"],
follow_redirects=True,
headers=headers,
params={"amount": amount},
)
cb_resp = cb_res.json()
if cb_res.is_error:
return {"success": False, "detail": "Error loading callback"}

# pay the invoice
lnurl_cb_url = str(request.url_for("tpos.tposlnurlcharge.callback"))
pay_invoice = await client.get(
lnurl_cb_url,
params={"pr": cb_resp["pr"], "k1": k1},
)
if pay_invoice.status_code != 200:
return {"success": False, "detail": "Error paying invoice"}
return {"success": True, "detail": "Payment successful"}

except AssertionError as ex:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=str(ex),
)
except Exception as ex:
logger.warning(ex)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail="Cannot process atm withdraw",
)


@tpos_ext.get(
"/api/v1/atm/withdraw/{withdraw_token}/{amount}", status_code=HTTPStatus.CREATED
)
Expand Down

0 comments on commit f981e7e

Please sign in to comment.