Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@motorina0
Copy link
Collaborator

@motorina0 motorina0 commented May 30, 2025

Allow stripe payments

This PR allows the admin to configure stripe as a fiat payment provider.
This feature allows all (or a selected subset) of users to RECEIVE payments via stripe.

lnbits_stripe.mp4

User Flow

  • When the Fiat Provider is configured (Stripe in this case) the end user is allowed to select how it wants to receive the funds (lightning or stripe):

    • image
  • If the user selects Stripe then a Stripe Payment Request is generated instead of a LN bolt11.

  • The buyer/payer can scan the QR code or click on it and it will be redirected to a Stripe checkout page like this one:

    • image
  • After the Stripe payment is completed, Stripe will send a notification to the LNbits instance and the LNbits payment will be marked as successful.

    • image

For a user that only has fiat funds, but wants to PAY a bolt11 Lightning Invoice (received from someone) then all it has to do is:

  • create a payment request in his LNbits wallet for the desired amount with Stripe as Fiat Payment Provider
  • pay the Stripe payment request -> the LNbits wallet is toped-up with that amount
  • pay the external Lightning Invoice (his wallet now has the funds)

Admin Configs

Admins now have a Fiat Providers tab where they can configure multiple fiat providers (for now only Stripe is supported):
image

These configs should be self explanatory (they have hints and descriptions).

Todos:

  • check stripe callback signature

@codecov
Copy link

codecov bot commented May 30, 2025

Codecov Report

Attention: Patch coverage is 72.38267% with 153 lines in your changes missing coverage. Please review.

Project coverage is 61.02%. Comparing base (f4e7d0c) to head (188fb3a).
Report is 1 commits behind head on dev.

Files with missing lines Patch % Lines
lnbits/fiat/stripe.py 40.00% 57 Missing ⚠️
lnbits/core/services/payments.py 78.57% 30 Missing ⚠️
lnbits/fiat/base.py 75.30% 20 Missing ⚠️
lnbits/core/services/fiat_providers.py 61.70% 18 Missing ⚠️
lnbits/core/views/callback_api.py 46.66% 8 Missing ⚠️
lnbits/core/models/payments.py 80.64% 6 Missing ⚠️
lnbits/fiat/__init__.py 85.71% 4 Missing ⚠️
lnbits/core/views/fiat_api.py 88.88% 1 Missing ⚠️
lnbits/settings.py 96.66% 1 Missing ⚠️
lnbits/tasks.py 94.73% 1 Missing ⚠️
... and 7 more
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #3184      +/-   ##
==========================================
+ Coverage   60.51%   61.02%   +0.51%     
==========================================
  Files         105      111       +6     
  Lines       13817    14296     +479     
==========================================
+ Hits         8361     8724     +363     
- Misses       5456     5572     +116     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@motorina0 motorina0 force-pushed the add_stripe_payments branch from 6056fd4 to 0f73535 Compare June 2, 2025 08:18
@motorina0 motorina0 force-pushed the add_stripe_payments branch from 8ee77e6 to 18ed036 Compare June 12, 2025 09:18
@motorina0 motorina0 requested review from arcbtc, dni and talvasconcelos and removed request for arcbtc and dni June 20, 2025 12:17
@motorina0 motorina0 force-pushed the add_stripe_payments branch from f1f080a to 4e18812 Compare June 20, 2025 12:30
@motorina0 motorina0 marked this pull request as ready for review June 20, 2025 12:32
@motorina0 motorina0 force-pushed the add_stripe_payments branch 2 times, most recently from 2882a08 to d0d1dc5 Compare June 25, 2025 10:59
Comment on lines 78 to 87
class FiatPaymentSuccessStatus(FiatPaymentStatus):
paid = True


class FiatPaymentFailedStatus(FiatPaymentStatus):
paid = False


class FiatPaymentPendingStatus(FiatPaymentStatus):
paid = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum above would obsolete that

class FiatPaymentResponse(NamedTuple):
# when ok is None it means we don't know if this succeeded
ok: bool | None = None
checking_id: str | None = None # payment_hash, rcp_id
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this ever be none?

Comment on lines +730 to +731
from lnbits.tasks import create_task

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed here now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# tasks.py
from lnbits.core.services.payments import handle_fiat_payment_confirmation`

because now tasks.py imports from services (which is fine) and there is a circular dependecy

raise ValueError(
f"The amount exceeds the '{fiat_provider_name}'"
"faucet wallet balance.",
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

howe about creating a services/fiat_payments.py we already at 1k lines

Copy link
Collaborator Author

@motorina0 motorina0 Jun 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the fiat payment logic is coupled with the regular payment logic (created payments, etc)

def is_internal(self) -> bool:
return self.checking_id.startswith("internal_")
return self.checking_id.startswith("internal_") or self.checking_id.startswith(
"fiat_"
Copy link
Member

@dni dni Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does is_internal also check if its fiat?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fiat payments are always internal payments, but I wanted to have an explicit prefix for it

@motorina0 motorina0 force-pushed the add_stripe_payments branch from 2617c5f to 9a0899e Compare June 30, 2025 08:55
Copy link
Collaborator

@talvasconcelos talvasconcelos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested.

Settings are straightforward and simple. Works good, as expected

@motorina0 motorina0 merged commit aba6e4c into dev Jun 30, 2025
43 checks passed
@motorina0 motorina0 deleted the add_stripe_payments branch June 30, 2025 10:13
dni pushed a commit that referenced this pull request Jul 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants