Payments
Other payment methods
Przelewy24
Accept a payment

Przelewy24 payments

Learn how to accept Przelewy24 (P24), the most popular payment method in Poland.

Przelewy24 is a single use payment method where customers are required to authenticate their payment. Customers pay with Przelewy24 by redirecting from your website, authorizing the payment, then returning to your website where you get immediate notification on whether the payment succeeded or failed.

1 Set up Stripe Server-side

First, you need a Stripe account. Register now.

Use our official libraries for access to the Stripe API from your application:

# Available as a gem gem install stripe
# If you use bundler, you can add this line to your Gemfile gem 'stripe'
# Install through pip pip install --upgrade stripe
# Or find the Stripe package on http://pypi.python.org/pypi/stripe/
# Find the version you want to pin: # https://github.com/stripe/stripe-python/blob/master/CHANGELOG.md # Specify that version in your requirements.txt file stripe>=2.48.0,<3.0
# Install the PHP library via Composer composer require stripe/stripe-php
# Or download the source directly: https://github.com/stripe/stripe-php/releases
/* For Gradle, add the following dependency to your build.gradle and replace {VERSION} with the version number you want to use from - https://mvnrepository.com/artifact/com.stripe/stripe-java or - https://github.com/stripe/stripe-java/releases/latest */ implementation "com.stripe:stripe-java:{VERSION}"
<!-- For Maven, add the following dependency to your POM and replace {VERSION} with the version number you want to use from - https://mvnrepository.com/artifact/com.stripe/stripe-java or - https://github.com/stripe/stripe-java/releases/latest --> <dependency> <groupId>com.stripe</groupId> <artifactId>stripe-java</artifactId> <version>{VERSION}</version> </dependency>
# For other environments, manually install the following JARs: # - The Stripe JAR from https://github.com/stripe/stripe-java/releases/latest # - Google Gson from https://github.com/google/gson
# Install via npm npm install --save stripe
# Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v71
// Then import the package import ( "github.com/stripe/stripe-go/v71" )
# Install via dotnet dotnet add package Stripe.net dotnet restore
# Or install via NuGet PM> Install-Package Stripe.net

2 Create a PaymentIntent Server-side

Stripe uses an object, called a PaymentIntent, to represent your intent to collect payment from a customer, tracking the lifecycle of the payment process through each stage.

First, create a PaymentIntent on your server and specify the amount to collect, and eur or pln as the currency. If you already have an integration using the Payment Intents API, add p24 to the list of payment method types for your PaymentIntent.

curl https://api.stripe.com/v1/payment_intents \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d amount=1099 \ -d currency=pln \ -d "payment_method_types[]"=p24
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' intent = Stripe::PaymentIntent.create({ amount: 1099, currency: 'pln', payment_method_types: ['p24'], })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.PaymentIntent.create( amount=1099, currency='pln', payment_method_types=['p24'], )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\PaymentIntent::create([ 'amount' => 1099, 'currency' => 'pln', 'payment_method_types' => ['p24'], ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; PaymentIntentCreateParams params = PaymentIntentCreateParams.builder() .setAmount(1099L) .setCurrency("pln") .setCustomer(customer.getId()) .addPaymentMethodType("p24") .build(); PaymentIntent paymentIntent = PaymentIntent.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const paymentIntent = await stripe.paymentIntents.create({ amount: 1099, currency: 'pln', payment_method_types: ['p24'], });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1099), Currency: stripe.String(string(Stripe.CurrencyPLN)), PaymentMethodTypes: stripe.StringSlice([]string{ "p24", }), } pi, _ := paymentintent.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new PaymentIntentCreateOptions { Amount = 1099, Currency = "pln", PaymentMethodTypes = new List<string> { "p24", }, }; var service = new PaymentIntentService(); var intent = service.Create(options);

Included in the returned PaymentIntent is a client secret, which you’ll use to securely complete the payment process instead of passing the entire PaymentIntent object. Send the client secret back to the client so you can use it in later steps.

Statement descriptors with Przelewy24

Przelewy24 lets you provide a custom statement descriptor before confirming the PaymentIntent and redirecting your customer to their bank’s website. This can be provided by setting the value for statement_descriptor.

The statement descriptor has a limit of 14 characters. It’s visible on your customer’s bank records in the format of P24-XXX-XXX-XXX {statement_descriptor}, where P24-XXX-XXX-XXX is a unique reference for this payment.

3 Collect payment method details Client-side

Create a payment form on your client to collect the required billing details from the customer:

Field Value
email The email address of the customer.
<form id="payment-form"> <div class="form-row"> <label for="email"> Email </label> <input id="email" name="email" required> </div> <!-- Used to display form errors. --> <div id="error-message" role="alert"></div> <button id="submit-button">Pay with P24</button> </form>

4 Submit the payment to Stripe Client-side

When a customer clicks to pay with P24, we recommend you use Stripe.js to submit the payment to Stripe. Stripe.js is our foundational JavaScript library for building payment flows. It will automatically handle complexities like the redirect described below, and enables you to easily extend your integration to other payment methods in the future.

Include the Stripe.js script on your checkout page by adding it to the head of your HTML file.

<head> <title>Checkout</title> <script src="https://js.stripe.com/v3/"></script> </head>

Create an instance of Stripe.js with the following JavaScript on your checkout page.

// Set your publishable key. Remember to change this to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
// Set your publishable key. Remember to change this to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');

To complete the payment on the client side, provide your client application with the client secret created in Step 2. This is different from your API keys that authenticate Stripe API requests.

The client secret should still be handled carefully because it can complete the charge. Do not log it, embed it in URLs, or expose it to anyone but the customer.

Confirm Przelewy24 payment

Use stripe.confirmP24Payment to handle the redirect away from your page and to complete the payment. Add a return_url to this function to indicate where Stripe should redirect the user to after they complete the payment on their bank’s website or mobile application. You must also provide the user’s email address in the billing_details hash.

var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx'); // Redirects away from the client stripe.confirmP24Payment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { billing_details: { email: "jenny.rosen@example.com" } }, return_url: 'https://your-website.com/checkout/complete', } ).then(function(result) { if (result.error) { // Inform the customer that there was an error. } });
var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx'); // Redirects away from the client const {error} = await stripe.confirmP24Payment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { billing_details: { email: "jenny.rosen@example.com" } }, return_url: 'https://your-website.com/checkout/complete', } ); if (error) { // Inform the customer that there was an error. }

Handling the redirect

The following URL query parameters are provided when Stripe redirects the customer to the return_url.

Parameter Description
payment_intent The unique identifier for the PaymentIntent.
payment_intent_client_secret The client secret of the PaymentIntent object.

You may also append your own query parameters when providing the return_url. They will persist through the redirect process.

The return_url should correspond to a page on your website that provides the status of the payment. You should verify the status of the PaymentIntent when rendering the return page. You can do so by using the retrievePaymentIntent function from Stripe.js and passing in the payment_intent_client_secret.

var url = new URL(window.location); var clientSecret = url.searchParams.get('payment_intent_client_secret'); stripe.retrievePaymentIntent(clientSecret).then(function(response) { if (response.error) { // Handle error here } else if (response.paymentIntent && response.paymentIntent.status === 'succeeded') { // Handle successful payment here } });
(async () => { const url = new URL(window.location); const clientSecret = url.searchParams.get('payment_intent_client_secret'); const {paymentIntent, error} = await stripe.retrievePaymentIntent(clientSecret); if (error) { // Handle error here } else if (paymentIntent && paymentIntent.status === 'succeeded') { // Handle successful payment here } })();

Przelewy24 reference

When a customer authorizes a payment, a unique reference will be stored on the resulting Charge under the payment_method_details property. You can also find your customer’s verified name, provided by Przelewy24.

You can choose to share this reference with your customer to help them locate payments in their records.

{ "charges": { "data": [ { "payment_method_details": { "p24": { "reference": "P24 123-456-789", "verified_name": "Jenny Rosen" }, "type": "p24" }, "id": "src_16xhynE8WzK49JbAs9M21jaR", "object": "source", "amount": 1099, "client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU",
See all 45 lines "created": 1445277809, "currency": "eur", "flow": "redirect", "livemode": true, "statement_descriptor": null, "status": "pending", "type": "p24", "usage": "single_use" } ], "object": "list", "has_more": false, "url": "/v1/charges?payment_intent=pi_1G1sgdKi6xqXeNtkldRRE6HT" }, "payment_method_options": { "p24": {} }, "payment_method_types": [ "p24" ], "id": "pi_1G1sgdKi6xqXeNtkldRRE6HT", "object": "payment_intent", "amount": 1099, "client_secret": "pi_1G1sgdKi6xqXeNtkldRRE6HT_secret_h9B56ObhTN72fQiBAuzcVPb2E", "confirmation_method": "automatic", "created": 1579259303, "currency": "eur", "livemode": true, "next_action": null }

Mobile applications

To integrate Przelewy24 within a mobile application, provide your application URI scheme as the return_url value. By doing so, your customers are returned to your app after completing authorization. Refer to our payments documentation for iOS or Android to learn more.

If you are integrating without using our mobile SDKs, the redirect URL must be opened using the device’s native browser. The use of in-app web views and containers can prevent your customer from completing authentication—resulting in a lower conversion rate.

Optional Handle post-payment events

Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard, a custom webhook, or a partner solution to receive these events and run actions, like sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow.

Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes. Setting up your integration to listen for asynchronous events also makes it easier to accept more payment methods in the future. Check out our guide to payment methods to see the differences between all supported payment methods.

Receive events and run business actions

Manually

Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments.

Custom code

Build a webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.

Prebuilt apps

Handle common business events, like shipping and inventory management, by integrating a partner application.

Przelewy24 is a single use payment method where customers are required to authenticate their payment. Customers pay with Przelewy24 by redirecting from your website, authorizing the payment, then returning to your website where you get immediate notification on whether the payment succeeded or failed.

1 Determine compatibility

A Checkout Session must satisfy all of the following conditions to support Przelewy24 payments:

  • Prices for all line items must be in the same currency. If you have line items in different currencies, create separate Checkout Sessions for each currency.
  • You can only use one-time line items (recurring subscription plans are not supported).

2 Accept a payment

This guide walks you through enabling Przelewy24 and shows the differences between accepting a card payment and using Przelewy24.

Enable Przelewy24 as a payment method

When creating a new Checkout Session, you need to:

  1. Add p24 to the list of payment_method_types.
  2. Make sure all your line_items use the same currency.
Stripe::Checkout::Session.create({ mode: 'payment', payment_method_types: ['card'], payment_method_types: ['p24'], # or you can take multiple payment methods with # payment_method_types: ['card', 'p24', ...] line_items: [{ price_data: { currency: 'usd', # To accept `p24`, all line items must have currency: `eur`, `pln` currency: 'eur', product_data: { name: 'T-shirt', }, unit_amount: 2000, }, quantity: 1, }], success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', })
stripe.checkout.Session.create( payment_method_types=['card'], payment_method_types=['p24'], # or you can take multiple payment methods with # payment_method_types=['card', 'p24', ...] line_items=[{ 'price_data': { currency: 'usd', # To accept `p24`, all line items must have currency: `eur`, `pln` currency: 'eur', 'product_data': { 'name': 'T-shirt', }, 'unit_amount': 2000, }, 'quantity': 1, }], mode='payment', success_url='https://example.com/success', cancel_url='https://example.com/cancel', )
$session = \Stripe\Checkout\Session::create([ 'payment_method_types' => ['card'], 'payment_method_types' => ['p24'], // or you can take multiple payment methods with // 'payment_method_types' => ['card', 'p24', ...] 'line_items' => [[ 'price_data' => [ 'currency' => 'usd', # To accept `p24`, all line items must have currency: `eur`, `pln` 'currency' => 'eur', 'product_data' => [ 'name' => 'T-shirt', ], 'unit_amount' => 2000, ], 'quantity' => 1, ]], 'mode' => 'payment', 'success_url' => 'https://example.com/success', 'cancel_url' => 'https://example.com/cancel', ]);
SessionCreateParams params = SessionCreateParams.builder() .addPaymentMethodType(SessionCreateParams.PaymentMethodType.CARD) .addPaymentMethodType(SessionCreateParams.PaymentMethodType.P24) .addLineItem( SessionCreateParams.LineItem.builder() .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setCurrency("usd") // To accept `p24`, all line items must have currency: `eur`, `pln` .setCurrency("eur") .setUnitAmount(2000L) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("T-shirt") .build()) .build()) .setQuantity(1L) .build()) .setMode(SessionCreateParams.Mode.PAYMENT) .setSuccessUrl("https://example.com/success") .setCancelUrl("https://example.com/cancel") .build(); Session session = Session.create(params);
const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], payment_method_types: ['p24'], // or you can take multiple payment methods with // payment_method_types: ['card', 'p24', ...] line_items: [{ price_data: { currency: 'usd', // To accept `p24`, all line items must have currency: `eur`, `pln` currency: 'eur', product_data: { name: 'T-shirt', }, unit_amount: 2000, }, quantity: 1, }], mode: 'payment', success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', });
params := &stripe.CheckoutSessionParams{ PaymentMethodTypes: stripe.StringSlice([]string{ "card", "p24", }), LineItems: []*stripe.CheckoutSessionLineItemParams{ &stripe.CheckoutSessionLineItemParams{ PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{ Currency: stripe.String("usd"), // To accept `p24`, all line items must have currency: `eur`, `pln` Currency: stripe.String("eur"), ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{ Name: stripe.String("T-shirt"), }, UnitAmount: stripe.Int64(2000), }, Quantity: stripe.Int64(1), }, }, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), SuccessURL: stripe.String("https://example.com/success"), CancelURL: stripe.String("https://example.com/cancel"), } s, _ := session.New(params)
var options = new SessionCreateOptions { PaymentMethodTypes = new List<string> { "card", "p24", }, LineItems = new List<SessionLineItemOptions> { new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { UnitAmount = 2000, Currency = "usd", // To accept `p24`, all line items must have currency: `eur`, `pln` Currency = "eur", ProductData = new SessionLineItemPriceDataProductDataOptions { Name = "T-shirt", }, }, Quantity = 1, }, }, Mode = "payment", SuccessUrl = "https://example.com/success", CancelUrl = "https://example.com/cancel", }; var service = new SessionService(); var session = service.Create(options);

Fulfill your orders

After accepting a payment, learn how to fulfill orders.

3 Test your integration

When testing your Checkout integration, select Przelewy24 as the payment method and click the Pay button.

4 Handle refunds and disputes

The refund period for Przelewy24 is up to 180 days after the original payment.

There is no dispute process—customers authenticate with their bank.

Accepting Przelewy24 in your app consists of displaying a webview to authenticate a payment. After authenticating, the customer returns to your app, and you can immediately confirm whether the payment succeeded or failed.

1 Set up Stripe Server-side Client-side

First, you need a Stripe account. Register now.

Server-side

This integration requires endpoints on your server that talk to the Stripe API. Use our official libraries for access to the Stripe API from your server:

# Available as a gem gem install stripe
# If you use bundler, you can add this line to your Gemfile gem 'stripe'
# Install through pip pip install --upgrade stripe
# Or find the Stripe package on http://pypi.python.org/pypi/stripe/
# Find the version you want to pin: # https://github.com/stripe/stripe-python/blob/master/CHANGELOG.md # Specify that version in your requirements.txt file stripe>=2.48.0,<3.0
# Install the PHP library via Composer composer require stripe/stripe-php
# Or download the source directly: https://github.com/stripe/stripe-php/releases
/* For Gradle, add the following dependency to your build.gradle and replace {VERSION} with the version number you want to use from - https://mvnrepository.com/artifact/com.stripe/stripe-java or - https://github.com/stripe/stripe-java/releases/latest */ implementation "com.stripe:stripe-java:{VERSION}"
<!-- For Maven, add the following dependency to your POM and replace {VERSION} with the version number you want to use from - https://mvnrepository.com/artifact/com.stripe/stripe-java or - https://github.com/stripe/stripe-java/releases/latest --> <dependency> <groupId>com.stripe</groupId> <artifactId>stripe-java</artifactId> <version>{VERSION}</version> </dependency>
# For other environments, manually install the following JARs: # - The Stripe JAR from https://github.com/stripe/stripe-java/releases/latest # - Google Gson from https://github.com/google/gson
# Install via npm npm install --save stripe
# Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v71
// Then import the package import ( "github.com/stripe/stripe-go/v71" )
# Install via dotnet dotnet add package Stripe.net dotnet restore
# Or install via NuGet PM> Install-Package Stripe.net

Client-side

The iOS SDK is open source, fully documented, and compatible with apps supporting iOS 11 or above.

  1. If you haven't already, install the latest version of CocoaPods.
  2. If you don't have an existing Podfile, run the following command to create one:
    pod init
  3. Add this line to your Podfile:
    pod 'Stripe'
  4. Run the following command:
    pod install
  5. Don't forget to use the .xcworkspace file to open your project in Xcode, instead of the .xcodeproj file, from here on out.
  6. In the future, to update to the latest version of the SDK, just run:
    pod update Stripe
  1. If you haven't already, install the latest version of Carthage.
  2. Add this line to your Cartfile:
    github "stripe/stripe-ios"
  3. Follow the Carthage installation instructions.
  4. In the future, to update to the latest version of the SDK, run the following command:
    carthage update stripe-ios --platform ios
  1. Head to our GitHub releases page and download and unzip Stripe.framework.zip.
  2. Drag Stripe.framework to the "Embedded Binaries" section of your Xcode project's "General" settings. Make sure to select "Copy items if needed".
  3. Head to the "Build Phases" section of your Xcode project settings, and create a new "Run Script Build Phase". Paste the following snippet into the text field:
    bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Stripe.framework/integrate-dynamic-framework.sh"
  4. In the future, to update to the latest version of our SDK, just repeat steps 1 and 2.

When your app starts, configure the SDK with your Stripe publishable key so that it can make requests to the Stripe API.

import UIKit import Stripe @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { Stripe.setDefaultPublishableKey("pk_test_TYooMQauvdEDq54NiTphI7jx") // do any other necessary launch configuration return true } }
#import "AppDelegate.h" #import <Stripe/Stripe.h> @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [Stripe setDefaultPublishableKey:@"pk_test_TYooMQauvdEDq54NiTphI7jx"]; // do any other necessary launch configuration return YES; } @end

2 Create a PaymentIntent Server-side Client-side

Stripe uses an object, called a PaymentIntent, to represent your intent to collect payment from a customer, tracking the lifecycle of the payment process through each stage.

Server-side

First, create a PaymentIntent on your server and specify the amount to collect, and eur or pln as the currency. If you already have an integration using the Payment Intents API, add p24 to the list of payment method types for your PaymentIntent.

curl https://api.stripe.com/v1/payment_intents \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d amount=1099 \ -d currency=pln \ -d "payment_method_types[]"=p24
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' intent = Stripe::PaymentIntent.create({ amount: 1099, currency: 'pln', payment_method_types: ['p24'], })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.PaymentIntent.create( amount=1099, currency='pln', payment_method_types=['p24'], )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\PaymentIntent::create([ 'amount' => 1099, 'currency' => 'pln', 'payment_method_types' => ['p24'], ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; PaymentIntentCreateParams params = PaymentIntentCreateParams.builder() .setAmount(1099L) .setCurrency("pln") .setCustomer(customer.getId()) .addPaymentMethodType("p24") .build(); PaymentIntent paymentIntent = PaymentIntent.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const paymentIntent = await stripe.paymentIntents.create({ amount: 1099, currency: 'pln', payment_method_types: ['p24'], });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1099), Currency: stripe.String(string(Stripe.CurrencyPLN)), PaymentMethodTypes: stripe.StringSlice([]string{ "p24", }), } pi, _ := paymentintent.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new PaymentIntentCreateOptions { Amount = 1099, Currency = "pln", PaymentMethodTypes = new List<string> { "p24", }, }; var service = new PaymentIntentService(); var intent = service.Create(options);

Included in the returned PaymentIntent is a client secret, which you’ll use to securely complete the payment process instead of passing the entire PaymentIntent object. Send the client secret back to the client so you can use it in later steps.

Client-side

On the client, request a PaymentIntent from your server and store its client secret.

class CheckoutViewController: UIViewController { var paymentIntentClientSecret: String? func startCheckout() { // Request a PaymentIntent from your server and store its client secret } }
@interface CheckoutViewController () @property (strong) NSString *paymentIntentClientSecret; @end @implementation CheckoutViewController - (void)startCheckout { // Request a PaymentIntent from your server and store its client secret } @end

Statement descriptors with Przelewy24

Przelewy24 lets you provide a custom statement descriptor before confirming the PaymentIntent and redirecting your customer to their bank’s website. This can be provided by setting the value for statement_descriptor.

The statement descriptor has a limit of 14 characters. It’s visible on your customer’s bank records in the format of P24-XXX-XXX-XXX {statement_descriptor}, where P24-XXX-XXX-XXX is a unique reference for this payment.

3 Collect payment method details Client-side

In your app, collect the required billing details (their email) from the customer. Create a STPPaymentIntentParams with the billing details.

let przelewy24Params = STPPaymentMethodPrzelewy24Params() let billingDetails = STPPaymentMethodBillingDetails() billingDetails.email = "email@email.com"
STPPaymentMethodPrzelewy24Params *przelewy24Params = [[STPPaymentMethodPrzelewy24Params alloc] init]; STPPaymentMethodBillingDetails *billingDetails = [[STPPaymentMethodBillingDetails alloc] init]; billingDetails.email = @"email@email.com";

4 Submit the payment to Stripe Client-side

Retrieve the client secret from the PaymentIntent you created in step 2 and call STPPaymentHandler confirmPayment. This presents a webview where the customer can complete the payment. Upon completion, the completion block is called with the result of the payment.

let paymentIntentParams = STPPaymentIntentParams(clientSecret: paymentIntentClientSecret) paymentIntentParams.paymentMethodParams = STPPaymentMethodParams( przelewy24: przelewy24Params, billingDetails: billingDetails, metadata: nil ) STPPaymentHandler.shared().confirmPayment(withParams: paymentIntentParams, authenticationContext: self) { (handlerStatus, paymentIntent, error) in switch handlerStatus { case .succeeded: // Payment succeeded case .canceled: // Payment was cancelled case .failed: // Payment failed @unknown default: fatalError() } }
STPPaymentIntentParams *paymentIntentParams = [[STPPaymentIntentParams alloc] initWithClientSecret:self.paymentIntentClientSecret]; paymentIntentParams.paymentMethodParams = [STPPaymentMethodParams paramsWithPrzelewy24:przelewy24Params billingDetails:billingDetails metadata:nil]; [[STPPaymentHandler sharedHandler] confirmPayment:paymentIntentParams withAuthenticationContext:self completion:^(STPPaymentHandlerActionStatus handlerStatus, STPPaymentIntent * handledIntent, NSError * _Nullable handlerError) { switch (handlerStatus) { case STPPaymentHandlerActionStatusFailed: // Payment failed break; case STPPaymentHandlerActionStatusCanceled: // Payment was cancelled break; case STPPaymentHandlerActionStatusSucceeded: // Payment succeeded break; } }];

Optional Handle post-payment events

Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard, a custom webhook, or a partner solution to receive these events and run actions, like sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow.

Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes. Setting up your integration to listen for asynchronous events also makes it easier to accept more payment methods in the future. Check out our guide to payment methods to see the differences between all supported payment methods.

Receive events and run business actions

Manually

Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments.

Custom code

Build a webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.

Prebuilt apps

Handle common business events, like shipping and inventory management, by integrating a partner application.

Accepting Przelewy24 in your app consists of displaying a webview to authenticate a payment. After authenticating, the customer returns to your app, and you can immediately confirm whether the payment succeeded or failed.

1 Set up Stripe Server-side Client-side

First, you need a Stripe account. Register now.

Server-side

This integration requires endpoints on your server that talk to the Stripe API. Use our official libraries for access to the Stripe API from your server:

# Available as a gem gem install stripe
# If you use bundler, you can add this line to your Gemfile gem 'stripe'
# Install through pip pip install --upgrade stripe
# Or find the Stripe package on http://pypi.python.org/pypi/stripe/
# Find the version you want to pin: # https://github.com/stripe/stripe-python/blob/master/CHANGELOG.md # Specify that version in your requirements.txt file stripe>=2.48.0,<3.0
# Install the PHP library via Composer composer require stripe/stripe-php
# Or download the source directly: https://github.com/stripe/stripe-php/releases
/* For Gradle, add the following dependency to your build.gradle and replace {VERSION} with the version number you want to use from - https://mvnrepository.com/artifact/com.stripe/stripe-java or - https://github.com/stripe/stripe-java/releases/latest */ implementation "com.stripe:stripe-java:{VERSION}"
<!-- For Maven, add the following dependency to your POM and replace {VERSION} with the version number you want to use from - https://mvnrepository.com/artifact/com.stripe/stripe-java or - https://github.com/stripe/stripe-java/releases/latest --> <dependency> <groupId>com.stripe</groupId> <artifactId>stripe-java</artifactId> <version>{VERSION}</version> </dependency>
# For other environments, manually install the following JARs: # - The Stripe JAR from https://github.com/stripe/stripe-java/releases/latest # - Google Gson from https://github.com/google/gson
# Install via npm npm install --save stripe
# Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v71
// Then import the package import ( "github.com/stripe/stripe-go/v71" )
# Install via dotnet dotnet add package Stripe.net dotnet restore
# Or install via NuGet PM> Install-Package Stripe.net

Client-side

The Android SDK is open source and fully documented.

To install the SDK, add stripe-android to the dependencies block of your app/build.gradle file:

apply plugin: 'com.android.application' android { ... } dependencies { // ... // Stripe Android SDK implementation 'com.stripe:stripe-android:16.0.1' }

Configure the SDK with your Stripe publishable key so that it can make requests to the Stripe API, such as in your Application subclass:

import com.stripe.android.PaymentConfiguration class MyApp : Application() { override fun onCreate() { super.onCreate() PaymentConfiguration.init( applicationContext, "pk_test_TYooMQauvdEDq54NiTphI7jx" ) } }
import com.stripe.android.PaymentConfiguration; public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); PaymentConfiguration.init( getApplicationContext(), "pk_test_TYooMQauvdEDq54NiTphI7jx" ); } }

Our code samples also use OkHttp and GSON to make HTTP requests to a server.

2 Create a PaymentIntent Server-side Client-side

Stripe uses an object, called a PaymentIntent, to represent your intent to collect payment from a customer, tracking the lifecycle of the payment process through each stage.

Server-side

First, create a PaymentIntent on your server and specify the amount to collect, and eur or pln as the currency. If you already have an integration using the Payment Intents API, add p24 to the list of payment method types for your PaymentIntent.

curl https://api.stripe.com/v1/payment_intents \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d amount=1099 \ -d currency=pln \ -d "payment_method_types[]"=p24
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' intent = Stripe::PaymentIntent.create({ amount: 1099, currency: 'pln', payment_method_types: ['p24'], })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.PaymentIntent.create( amount=1099, currency='pln', payment_method_types=['p24'], )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\PaymentIntent::create([ 'amount' => 1099, 'currency' => 'pln', 'payment_method_types' => ['p24'], ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; PaymentIntentCreateParams params = PaymentIntentCreateParams.builder() .setAmount(1099L) .setCurrency("pln") .setCustomer(customer.getId()) .addPaymentMethodType("p24") .build(); PaymentIntent paymentIntent = PaymentIntent.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const paymentIntent = await stripe.paymentIntents.create({ amount: 1099, currency: 'pln', payment_method_types: ['p24'], });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1099), Currency: stripe.String(string(Stripe.CurrencyPLN)), PaymentMethodTypes: stripe.StringSlice([]string{ "p24", }), } pi, _ := paymentintent.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new PaymentIntentCreateOptions { Amount = 1099, Currency = "pln", PaymentMethodTypes = new List<string> { "p24", }, }; var service = new PaymentIntentService(); var intent = service.Create(options);

Included in the returned PaymentIntent is a client secret, which you’ll use to securely complete the payment process instead of passing the entire PaymentIntent object. Send the client secret back to the client so you can use it in later steps.

Client-side

On the client, request a PaymentIntent from your server and store its client secret.

class P24PaymentActivity: AppCompatActivity() { private lateinit var paymentIntentClientSecret: String override fun onCreate(savedInstanceState: Bundle?) { // ... startCheckout() } private fun startCheckout() { // Request a PaymentIntent from your server and store its client secret } }
public class P24PaymentActivity extends AppCompatActivity { private String paymentIntentClientSecret; @Override public void onCreate(@Nullable Bundle savedInstanceState) { // ... startCheckout(); } private void startCheckout() { // Request a PaymentIntent from your server and store its client secret } }

Statement descriptors with Przelewy24

Przelewy24 lets you provide a custom statement descriptor before confirming the PaymentIntent and redirecting your customer to their bank’s website. This can be provided by setting the value for statement_descriptor.

The statement descriptor has a limit of 14 characters. It’s visible on your customer’s bank records in the format of P24-XXX-XXX-XXX {statement_descriptor}, where P24-XXX-XXX-XXX is a unique reference for this payment.

3 Collect payment method details Client-side

In your app, collect the required billing details (their email) from the customer. Create a PaymentMethodCreateParams with the billing details.

val billingDetails = PaymentMethod.BillingDetails(email = "email@email.com") val paymentMethodCreateParams = PaymentMethodCreateParams.createP24(billingDetails)
PaymentMethod.BillingDetails billingDetails = new PaymentMethod.BillingDetails.Builder() .setEmail("email@email.com") .build(); PaymentMethodCreateParams paymentMethodCreateParams = PaymentMethodCreateParams.createP24(billingDetails);

4 Submit the payment to Stripe Client-side

Retrieve the client secret from the PaymentIntent you created in step 2 and call the stripe confirmPayment method. This presents a webview where the customer can complete the payment. Upon completion, onActivityResult is called with the result of the payment.

class P24PaymentActivity : AppCompatActivity() { // ... private lateinit var paymentIntentClientSecret: String private val stripe: Stripe by lazy { Stripe( applicationContext, PaymentConfiguration.getInstance(applicationContext).publishableKey ) } private fun startCheckout() { // ... val confirmParams = ConfirmPaymentIntentParams .createWithPaymentMethodCreateParams( paymentMethodCreateParams = paymentMethodCreateParams, clientSecret = paymentIntentClientSecret ) stripe.confirmPayment(confirmParams) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) // Handle the result of stripe.confirmPayment stripe.onPaymentResult(requestCode, data, object : ApiResultCallback<PaymentIntentResult> { override fun onSuccess(result: PaymentIntentResult) { val paymentIntent = result.intent val status = paymentIntent.status when (status) { StripeIntent.Status.Succeeded -> { // Payment succeeded } else -> { // Payment failed/cancelled } } } override fun onError(e: Exception) { // Payment failed } }) } }
public class P24PaymentActivity extends AppCompatActivity { // ... private String paymentIntentClientSecret; private Stripe stripe; private void startCheckout() { // ... ConfirmPaymentIntentParams confirmParams = ConfirmPaymentIntentParams .createWithPaymentMethodCreateParams( paymentMethodCreateParams, paymentIntentClientSecret ); final Context context = getApplicationContext(); stripe = new Stripe( context, PaymentConfiguration.getInstance(context).getPublishableKey() ); stripe.confirmPayment(this, confirmParams); } // ... @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Handle the result of stripe.confirmPayment stripe.onPaymentResult(requestCode, data, new PaymentResultCallback()); } // ... private static final class PaymentResultCallback implements ApiResultCallback<PaymentIntentResult> { @Override public void onSuccess(@NonNull PaymentIntentResult result) { PaymentIntent paymentIntent = result.getIntent(); PaymentIntent.Status status = paymentIntent.getStatus(); if (status == PaymentIntent.Status.Succeeded) { // Payment succeeded } else { // Payment failed/cancelled } } @Override public void onError(@NonNull Exception e) { // Payment failed } } }

Optional Handle post-payment events

Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard, a custom webhook, or a partner solution to receive these events and run actions, like sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow.

Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes. Setting up your integration to listen for asynchronous events also makes it easier to accept more payment methods in the future. Check out our guide to payment methods to see the differences between all supported payment methods.

Receive events and run business actions

Manually

Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments.

Custom code

Build a webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.

Prebuilt apps

Handle common business events, like shipping and inventory management, by integrating a partner application.

Was this page helpful?
Questions? Contact us.
Developer tutorials on YouTube.