Skip to main content
Doss uses Stripe to process credit and debit card payments for wallet deposits. The integration uses the Stripe Payment Intents API (stripe/stripe-php ^10.7) and follows a two-step flow: create a payment intent, then confirm it with a tokenized card.

Prerequisites

  • A Stripe account
  • A publishable key and a secret key from your Stripe dashboard (test or live)
  • The Stripe payment method enabled for the target currency in the Doss admin panel
Never use your live secret key in a development or staging environment. Live keys process real charges immediately. Use test keys (sk_test_... / pk_test_...) until you are ready to go live.

Configuration

1

Open the payment method settings

In the Doss admin panel, navigate to Payment Methods and select Stripe.
2

Enter your API keys

Enter your Stripe Publishable Key and Secret Key. These are stored per currency in the currency_payment_methods table under the method_data JSON column as publishable_key and secret_key.
3

Activate Stripe for deposit

Enable the method for the deposit transaction type on each currency where you want to accept card payments. The activated_for field must include deposit.
4

Set fees and limits

Configure the minimum/maximum deposit limits and fee structure (percentage and fixed) for the Stripe payment method under Fees & Limits.

Payment flow

When a user selects Stripe as their deposit method, the application follows this sequence:
  1. Redirect to card formGET /deposit/stripe_payment loads the card entry page. The publishable key is passed to the view to initialize the Stripe client.
  2. Make paymentPOST /deposit/stripe-make-payment calls StripeRepository::makePayment(), which:
    • Creates a PaymentIntent (stripe->paymentIntents->create) for the total amount in the wallet currency (amount is multiplied by 100 to convert to the smallest currency unit).
    • Creates a PaymentMethod (stripe->paymentMethods->create) using the submitted card number, expiry month/year, and CVC.
    • Returns the paymentIntentId and paymentMethodId on success.
  3. Confirm paymentPOST /deposit/stripe-confirm-payment calls StripeRepository::paymentConfirm(), which calls stripe->paymentIntents->confirm with the intent ID and method ID.
    • If the intent status is succeeded, the deposit and transaction records are written to the database and the user’s wallet balance is updated.
    • If the status is requires_action, the request is rejected — 3DS cards are not supported.
  4. Success pageGET /deposit/stripe-payment/success displays the confirmed transaction details.

API routes

MethodRouteHandler
GET/deposit/stripe_paymentDepositController@stripePayment
POST/deposit/stripe-make-paymentDepositController@stripeMakePayment
POST/deposit/stripe-confirm-paymentDepositController@stripeConfirm
GET/deposit/stripe-payment/successDepositController@stripePaymentSuccess
The same flow is exposed for the mobile API under Api\DepositMoneyController@stripeMakePayment and Api\DepositMoneyController@stripeConfirm.

Test mode vs live mode

Stripe keys determine the environment automatically:
Key prefixEnvironment
sk_test_ / pk_test_Test — no real charges, use Stripe test cards
sk_live_ / pk_live_Live — real charges processed immediately
Swap keys in the admin panel to move between environments. No code changes are required.

Webhook setup

This integration does not use Stripe webhooks. Payment confirmation is handled synchronously via the /deposit/stripe-confirm-payment endpoint immediately after the user submits the card form. If you require asynchronous confirmation (for example, for delayed card networks), you would need to add a webhook endpoint and configure it in the Stripe dashboard.

Limitations

  • 3DS cards are not supported. If a card requires additional authentication (requires_action status), the payment is rejected with the message "3DS cards are not supported".
  • The card number, expiry, and CVC are submitted directly from the client to your server and then to Stripe. Ensure your server is PCI-compliant or use Stripe Elements to tokenize on the client side instead.

Build docs developers (and LLMs) love