payment notification webhook
This commit is contained in:
parent
30e0537270
commit
632d35682d
6 changed files with 53 additions and 6 deletions
|
|
@ -27,9 +27,10 @@ async def create_card(data: CreateCardData, wallet_id: str) -> Card:
|
|||
k0,
|
||||
k1,
|
||||
k2,
|
||||
otp
|
||||
otp,
|
||||
webhook_url
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
card_id,
|
||||
|
|
@ -45,6 +46,7 @@ async def create_card(data: CreateCardData, wallet_id: str) -> Card:
|
|||
data.k1,
|
||||
data.k2,
|
||||
secrets.token_hex(16),
|
||||
data.webhook_url,
|
||||
),
|
||||
)
|
||||
card = await get_card(card_id)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ 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
|
||||
|
|
@ -119,12 +120,32 @@ async def lnurl_callback(
|
|||
invoice = bolt11.decode(pr)
|
||||
hit = await spend_hit(id=hit.id, amount=int(invoice.amount_msat / 1000))
|
||||
try:
|
||||
await pay_invoice(
|
||||
payment_hash = await pay_invoice(
|
||||
wallet_id=card.wallet,
|
||||
payment_request=pr,
|
||||
max_sat=card.tx_limit,
|
||||
extra={"tag": "boltcard", "tag": hit.id},
|
||||
)
|
||||
|
||||
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"}
|
||||
|
|
|
|||
|
|
@ -58,3 +58,11 @@ async def m001_initial(db):
|
|||
);
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
async def m002_add_webhook(db):
|
||||
await db.execute(
|
||||
"""
|
||||
ALTER TABLE boltcards.cards ADD COLUMN webhook_url TEXT NOT NULL DEFAULT '';
|
||||
"""
|
||||
)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class Card(BaseModel):
|
|||
prev_k1: str
|
||||
prev_k2: str
|
||||
otp: str
|
||||
webhook_url: str
|
||||
time: int
|
||||
|
||||
def from_row(cls, row: Row) -> "Card":
|
||||
|
|
@ -56,6 +57,7 @@ class CreateCardData(BaseModel):
|
|||
prev_k0: str = Query(ZERO_KEY)
|
||||
prev_k1: str = Query(ZERO_KEY)
|
||||
prev_k2: str = Query(ZERO_KEY)
|
||||
webhook_url: str = Query(...)
|
||||
|
||||
|
||||
class Hit(BaseModel):
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ new Vue({
|
|||
cardDialog: {
|
||||
show: false,
|
||||
data: {
|
||||
webhook_url: '',
|
||||
counter: 1,
|
||||
k0: '',
|
||||
k1: '',
|
||||
|
|
@ -270,7 +271,8 @@ new Vue({
|
|||
k1: card.k1,
|
||||
k2: card.k2,
|
||||
k3: card.k1,
|
||||
k4: card.k2
|
||||
k4: card.k2,
|
||||
webhook_url: card.webhook_url
|
||||
}
|
||||
this.qrCodeDialog.show = true
|
||||
},
|
||||
|
|
@ -398,7 +400,9 @@ new Vue({
|
|||
let cards = _.findWhere(this.cards, {id: cardId})
|
||||
|
||||
LNbits.utils
|
||||
.confirmDialog('Are you sure you want to delete this card? Without access to the card keys you won\'t be able to reset them in the future!')
|
||||
.confirmDialog(
|
||||
"Are you sure you want to delete this card? Without access to the card keys you won't be able to reset them in the future!"
|
||||
)
|
||||
.onOk(function () {
|
||||
LNbits.api
|
||||
.request(
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@
|
|||
v-model="toggleAdvanced"
|
||||
label="Show advanced options"
|
||||
></q-toggle>
|
||||
<div v-show="toggleAdvanced">
|
||||
<div v-show="toggleAdvanced" class="q-gutter-y-md">
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
|
|
@ -322,6 +322,14 @@
|
|||
>Zero if you don't know.</q-tooltip
|
||||
>
|
||||
</q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.number="cardDialog.data.webhook_url"
|
||||
type="text"
|
||||
label="Notification webhook"
|
||||
>
|
||||
</q-input>
|
||||
<q-btn
|
||||
unelevated
|
||||
color="primary"
|
||||
|
|
@ -380,6 +388,8 @@
|
|||
<strong>Lock key:</strong> {{ qrCodeDialog.data.k0 }}<br />
|
||||
<strong>Meta key:</strong> {{ qrCodeDialog.data.k1 }}<br />
|
||||
<strong>File key:</strong> {{ qrCodeDialog.data.k2 }}<br />
|
||||
<strong>Notification webhook:</strong> {{ qrCodeDialog.data.webhook_url
|
||||
}}<br />
|
||||
</p>
|
||||
<br />
|
||||
<q-btn
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue