feat: stripe api Intents needed for tap to pay (#3598)

Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
Co-authored-by: dni  <office@dnilabs.com>
This commit is contained in:
Arc 2025-12-06 16:50:53 +00:00 committed by GitHub
parent fcaeb0ac7a
commit 245569d0b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 34 additions and 8 deletions

View file

@ -48,6 +48,8 @@ async def handle_stripe_event(event: dict):
event_type = event.get("type")
if event_type == "checkout.session.completed":
await _handle_stripe_checkout_session_completed(event)
elif event_type == "payment_intent.succeeded":
await _handle_stripe_intent_session_completed(event)
elif event_type == "invoice.paid":
await _handle_stripe_subscription_invoice_paid(event)
else:
@ -56,18 +58,38 @@ async def handle_stripe_event(event: dict):
)
async def _handle_stripe_intent_session_completed(event: dict):
event_id = event.get("id")
event_object = event.get("data", {}).get("object", {})
object_type = event_object.get("object")
payment_hash = event_object.get("metadata", {}).get("payment_hash")
logger.debug(
f"Handling Stripe event: '{event_id}'. Type: '{object_type}'."
f" Payment hash: '{payment_hash}'."
)
if not payment_hash:
logger.warning("Stripe event does not contain a payment hash.")
return
payment = await get_standalone_payment(payment_hash)
if not payment:
logger.warning(f"No payment found for hash: '{payment_hash}'.")
return
await payment.check_fiat_status()
async def _handle_stripe_checkout_session_completed(event: dict):
event_id = event.get("id")
event_object = event.get("data", {}).get("object", {})
object_type = event_object.get("object")
payment_hash = event_object.get("metadata", {}).get("payment_hash")
lnbits_action = event_object.get("metadata", {}).get("lnbits_action")
alan_action = event_object.get("metadata", {}).get("alan_action")
logger.debug(
f"Handling Stripe event: '{event_id}'. Type: '{object_type}'."
f" Payment hash: '{payment_hash}'."
)
if lnbits_action != "invoice":
logger.warning(f"Stripe event is not an invoice: '{lnbits_action}'.")
if alan_action != "invoice":
logger.warning(f"Stripe event is not an invoice: '{alan_action}'.")
return
if not payment_hash:
@ -132,7 +154,7 @@ async def _get_stripe_subscription_payment_options(
metadata = parent.get("subscription_details", {}).get("metadata", {})
if metadata.get("lnbits_action") != "subscription":
if metadata.get("alan_action") != "subscription":
raise ValueError("Stripe invoice.paid metadata action is not 'subscription'.")
if "extra" in metadata:

View file

@ -170,7 +170,7 @@ class StripeWallet(FiatProvider):
("line_items[0][price]", subscription_id),
("line_items[0][quantity]", f"{quantity}"),
]
subscription_data = {**payment_options.dict(), "lnbits_action": "subscription"}
subscription_data = {**payment_options.dict(), "alan_action": "subscription"}
subscription_data["extra"] = json.dumps(subscription_data.get("extra") or {})
form_data += self._encode_metadata(
@ -315,7 +315,7 @@ class StripeWallet(FiatProvider):
("mode", "payment"),
("success_url", success_url),
("metadata[payment_hash]", payment_hash),
("metadata[lnbits_action]", "invoice"),
("metadata[alan_action]", "invoice"),
("line_items[0][price_data][currency]", currency.lower()),
("line_items[0][price_data][product_data][name]", line_item_name),
("line_items[0][price_data][unit_amount]", str(amount_cents)),

File diff suppressed because one or more lines are too long

View file

@ -428,6 +428,8 @@ window.localisation.en = {
look_and_feel: 'Look and Feel',
endpoint: 'Endpoint',
api: 'API',
api_stripe:
'API (warning: Stripe are twitchy about anything bitcoin, so avoid using word "bitcoin" in your memos!)',
api_token: 'API Token',
api_tokens: 'API Tokens',
access_control_list: 'Access Control List',

View file

@ -35,7 +35,7 @@
</template>
<q-card class="q-pb-xl">
<q-expansion-item :label="$t('api')" default-opened>
<q-expansion-item :label="$t('api_stripe')" default-opened>
<q-card-section class="q-pa-md">
<q-input
filled
@ -106,6 +106,8 @@
- the user completed the checkout process
<li><code>invoice.paid</code></li>
- the invoice was successfully paid (for subscriptions)
<li><code>payment_intent.succeeded</code></li>
- the intent was successfully paid (for tap-to-pay in TPoS)
</ul>
</q-card-section>
</q-expansion-item>