# Fully embedded Connect platform integration Provide Connect features to your connected accounts through your own website. Connect embedded components let you add Stripe-managed functionality to a custom interface that you provide to your connected accounts, such as those in SaaS platforms and marketplaces. They can perform payment-related activities there instead of through the Stripe Dashboard. In a fully embedded integration: - Connected accounts access Stripe-related data, forms, and notifications through embedded components in your platform’s application. They don’t have access to a Stripe Dashboard. - Stripe manages credit and fraud risk on your connected accounts. For any risk or compliance actions, we communicate directly with connected accounts and they respond by interacting with embedded components. - Stripe email notifications direct your connected accounts to embedded components on your website to review information or take required action. You must provide Stripe with the URLs for those components. ## View the demo site We’ve built a complete [demo site for our fictitious business, Furever](http://furever.dev). Furever is a platform providing software for pet-groomers that allows their users to collect payments. In this demo, you can interact with many embedded components, including account onboarding and account management. ## Before you begin Before you can build an embedded integration, complete the following prerequisites: 1. [Register your platform](https://dashboard.stripe.com/connect). 1. Add business details to [activate your account](https://dashboard.stripe.com/account/onboarding). 1. [Complete your platform profile](https://dashboard.stripe.com/connect/settings/profile). 1. [Customize your brand settings](https://dashboard.stripe.com/settings/connect/stripe-dashboard/branding). Add a business name, icon, and brand color. You must also decide whether your platform will own pricing, in which case Stripe collects payment fees from your platform and you bill your connected accounts. Otherwise, Stripe owns pricing and collects payment fees directly from your connected accounts. ## Create a connected account The following example creates a connected account where Stripe [manages risk](https://docs.stripe.com/connect/risk-management.md), controls pricing, and assumes responsibility for account onboarding requirements. Your platform uses embedded components and isn’t responsible for connected account negative balances. Your connected accounts don’t have access to Stripe-hosted Dashboards. > Because Stripe controls pricing in this example, you must integrate the [Documents embedded component](https://docs.stripe.com/connect/supported-embedded-components/documents.md). In addition, Stripe notifies connected accounts by email when their tax invoices or 1099s are ready for download. If you create accounts where your platform controls pricing, the Documents component isn’t required, and Stripe doesn’t send notifications to connected accounts about tax invoices or 1099s. You can request additional capabilities, such as specific payment methods, after the account onboards. Call [/v1/accounts](https://docs.stripe.com/api/accounts/create.md) with the following parameters: - `country` of the account - `controller.stripe_dashboard.type` = `none` - request the `card_payments` and `transfers` capabilities ```curl curl https://api.stripe.com/v1/accounts \ -u "<>:" \ -d country=US \ -d "controller[stripe_dashboard][type]=none" \ -d "capabilities[card_payments][requested]=true" \ -d "capabilities[transfers][requested]=true" ``` ```json { "id": ""{{CONNECTED_ACCOUNT_ID}}"", "object": "account", "controller": { "type": "application", "is_controller": true, "losses": {"payments": "stripe"}, "fees": {"payer": "account"}, "requirement_collection": "stripe", "stripe_dashboard": { "type": "none" } }, "type": "none", ... } ``` ## Set up embedded components Connected accounts access their accounts, as well as core payments functionality, directly in your platform and don’t have access to a Stripe-hosted Dashboard. You must provide access to certain features through your website. Your integration must include the following embedded components: - [Account onboarding](https://docs.stripe.com/connect/supported-embedded-components/account-onboarding.md) - [Account management](https://docs.stripe.com/connect/supported-embedded-components/account-management.md) - [Notification banner](https://docs.stripe.com/connect/supported-embedded-components/notification-banner.md) - [Documents](https://docs.stripe.com/connect/supported-embedded-components/documents.md) (when Stripe collects Stripe fees directly from connected accounts) Your integration must also provide a way to respond to disputes with evidence on individual payments. You can implement this [using our API](https://docs.stripe.com/disputes/api.md) or an embedded component ([Payments](https://docs.stripe.com/connect/supported-embedded-components/payments.md), [Payment details](https://docs.stripe.com/connect/supported-embedded-components/payment-details.md), or [Disputes for a payment](https://docs.stripe.com/connect/supported-embedded-components/disputes-for-a-payment.md)). We recommend that you provide a way to allow connected accounts to add money if needed to avoid a negative balance and prevent business disruptions. You can implement this using an embedded component ([Balances](https://docs.stripe.com/connect/supported-embedded-components/balances.md) or [Payouts](https://docs.stripe.com/connect/supported-embedded-components/payouts.md)). You can also add [additional embedded components](https://docs.stripe.com/connect/supported-embedded-components.md) or build your own UIs using our APIs. Make sure you [set up embedded components](https://docs.stripe.com/connect/get-started-connect-embedded-components.md) before onboarding connected accounts. ## Best practices To maximize the effectiveness of your integration, consider the following strategies: 1. **User focus**: Make sure that the onboarding process is intuitive by using the [account onboarding](https://docs.stripe.com/connect/supported-embedded-components/account-onboarding.md) component to guide users through account creation and management by breaking the process into simple steps and providing straightforward instructions. 1. **Prompt for compliance**: Use the [notification banner](https://docs.stripe.com/connect/supported-embedded-components/notification-banner.md) component to keep users updated on their compliance status and any outstanding requirements. Place the banner prominently in your application, such as on the homepage of your dashboard, to make sure that it’s visible and prompts timely action on necessary documentation or updates. 1. **Responsive design**: Make sure that the components you integrate are responsive across devices. Because connected accounts might access your platform from various devices, including mobile phones, make sure the onboarding and management interfaces function well on different screen sizes. 1. **User authentication and security**: Implement strong [authentication measures](https://docs.stripe.com/connect/get-started-connect-embedded-components.md?platform=web#user-authentication-in-connect-embedded-components) during the onboarding and account management processes. Although Stripe authentication protects sensitive account information and the ability to change payout details, other sensitive information relies solely on your product’s authentication and security. You can enhance overall security by using methods such as one-time SMS codes or two-factor authentication. 1. **Feedback mechanisms**: Integrate feedback options within your onboarding flow and management components. Enable users to report issues or suggest improvements, allowing you to continuously enhance the platform based on their input. 1. **Proactive engagement**: Encourage users to keep their accounts active by sending reminders or alerts about compliance obligations through email or platform notifications. This proactive approach can help prevent account suspensions and reduce frustration on the part of users. ## Onboard connected accounts Stripe uses an [AccountSession](https://docs.stripe.com/api/account_sessions.md) to express your intent to provide embedded component access to the connected account. Using an `AccountSession`, the embedded account onboarding component collects all required information based on your requested capabilities. ### Prefill the account You can streamline the onboarding flow for your connected accounts by prefilling `Account` properties with known information before you create an `AccountSession`. The onboarding component doesn’t request information that already exists on the `Account`. Prefill as much information as possible, including company, individual, and external account information, following these steps: 1. Use the [required verification information](https://docs.stripe.com/connect/required-verification-information.md) tool to learn about the requirements for your connected accounts, based on their location, business type, and requested capabilities. 1. Collect prefillable information matching the requirements. 1. Provide the collected information when you create the `Account` or add it prior to onboarding by updating the `Account`. After you create an `Account` and request its capabilities, you can check its specific requirements by looking at its [requirements](https://docs.stripe.com/api/accounts/object.md#account_object-requirements) property. Because your platform isn’t responsible for negative balances, your access to certain connected account information, such as payout accounts and legal entity information, is limited. After a connected account completes onboarding through the Account Onboarding embedded component, your platform can no longer update those properties. The connected account must make any updates to them. ### Onboard users through the embedded onboarding component Check out the [Furever demo site](https://furever.dev) for an example placement of the onboarding component. Connected accounts must go through onboarding and provide required information to enable charges and payouts. To onboard a connected account, host the [onboarding embedded component](https://docs.stripe.com/connect/supported-embedded-components/account-onboarding.md) on your site and direct new accounts there. ### Create an Account Session When [creating an Account Session](https://docs.stripe.com/api/account_sessions/create.md), enable account onboarding by specifying `account_onboarding` in the `components` parameter. ```curl curl https://api.stripe.com/v1/account_sessions \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ -d "components[account_onboarding][enabled]=true" ``` ### Render the Account onboarding component After creating the Account Session and [initializing ConnectJS](https://docs.stripe.com/connect/get-started-connect-embedded-components.md#account-sessions), you can render the Account onboarding component in the front end: #### JavaScript ```js // Include this element in your HTML const accountOnboarding = stripeConnectInstance.create('account-onboarding'); accountOnboarding.setOnExit(() => { console.log('User exited the onboarding flow'); }); container.appendChild(accountOnboarding); // Optional: make sure to follow our policy instructions above // accountOnboarding.setFullTermsOfServiceUrl('{{URL}}') // accountOnboarding.setRecipientTermsOfServiceUrl('{{URL}}') // accountOnboarding.setPrivacyPolicyUrl('{{URL}}') // accountOnboarding.setCollectionOptions({ // fields: 'eventually_due', // futureRequirements: 'include', // requirements: { // exclude: ['business_profile.product_description'] // } // }) // accountOnboarding.setOnStepChange((stepChange) => { // console.log(`User entered: ${stepChange.step}`); // }); ``` Present the onboarding flow to the account’s primary owner. The primary owner sets up authentication with Stripe, and is the user who can edit the account details and respond to risk interventions. The connected account has only a single set of authentication credentials with Stripe. The user with authentication credentials can authenticate using one-time SMS codes to perform more sensitive actions like updating bank accounts for payout destinations or providing updated legal entity information. ### Listen for onboarding events As the connected account proceeds through onboarding, [account.updated](https://docs.stripe.com/api/events/types.md#event_types-account.updated) events are also sent to your configured [Connect webhooks](https://docs.stripe.com/connect/webhooks.md). When the account finishes submitting their details, the `details_submitted` property on the `Account` changes to true. Check the status by looking for `details_submitted: true` in the `account.updated` event body in your webhook handler or by [retrieving the Account](https://docs.stripe.com/api/account/retrieve.md). If `details_submitted` is false, show the embedded onboarding component again. The component skips any information that’s already submitted and collects only the unsubmitted requirements. When a connected account submits their details and completes the onboarding flow, the embedded onboarding component calls the `onExit` handler that you [set when you render the component](https://docs.stripe.com/connect/supported-embedded-components/account-onboarding.md). Use the callback to direct the account to their next action. If you don’t set an exit handler, or take action inside of the handler, the account sees a completion message without a clear next step. ### Request additional capabilities (optional) Your platform can continue to [request additional capabilities](https://docs.stripe.com/connect/account-capabilities.md#creating) after onboarding a connected account. For example, you must request the capabilities for any payment methods you want to enable for an account. If any requested capabilities require additional information, the connected account receives a notification through the [embedded notification banner](https://docs.stripe.com/connect/build-full-embedded-integration.md#embed-the-notification-banner). ## Handle ongoing compliance and risk updates Because Stripe manages credit and fraud risk for your connected accounts, your accounts must be able to see and respond to alerts from Stripe. To facilitate that, your platform must integrate the notification banner and account management embedded components. For more information about how Stripe supports your connected accounts through these components, see [Embedded Connect support](https://docs.stripe.com/connect/embedded-support.md). ## Embed the notification banner Stripe uses the [notification banner embedded component](https://docs.stripe.com/connect/supported-embedded-components/notification-banner.md) to notify connected accounts of outstanding compliance requirements and other [risk-related requests](https://docs.stripe.com/connect/embedded-risk.md). Responding to these notifications allows an account to remain compliant so it can process payments and receive payouts. If there are no outstanding notifications, the embedded notification banner doesn’t render. Integrate the notification banner in a highly visible and easily accessible location on your website. For example, you can integrate it at the top of your payments page. ### Create an Account Session When [creating an Account Session](https://docs.stripe.com/api/account_sessions/create.md), enable notification banner by specifying `notification_banner` in the `components` parameter. ```curl curl https://api.stripe.com/v1/account_sessions \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ -d "components[notification_banner][enabled]=true" \ -d "components[notification_banner][features][external_account_collection]=true" ``` ### Render the notification banner component #### JavaScript ```js // Include this element in your HTML const notificationBanner = stripeConnectInstance.create('notification-banner'); container.appendChild(notificationBanner); // Optional: // notificationBanner.setCollectionOptions({ // fields: 'eventually_due', // futureRequirements: 'include', // }) ``` To respond to a banner notification, the account can click a button in the notification. You don’t need to redirect them to the account management embedded component. ## Embed account management Stripe requires the [account management embedded component](https://docs.stripe.com/connect/supported-embedded-components/account-management.md) when managing risk. Integrate the component in your website where an account updates their settings or profile. ### Create an Account Session When [creating an Account Session](https://docs.stripe.com/api/account_sessions/create.md), enable account management by specifying `account_management` in the `components` parameter. ```curl curl https://api.stripe.com/v1/account_sessions \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ -d "components[account_management][enabled]=true" \ -d "components[account_management][features][external_account_collection]=true" ``` ### Render the account management component #### JavaScript ```js // Include this element in your HTML const accountManagement = stripeConnectInstance.create('account-management'); container.appendChild(accountManagement); // Optional: // accountManagement.setCollectionOptions({ // fields: 'eventually_due', // futureRequirements: 'include', // }) ``` This component allows an account to update their account details, respond to compliance requirements that are due, and update their authentication credentials. ## Integrate payments Set up the payments integration after integrating required embedded components. You can add the payments and payout embedded components to your platform or build your own workflows. Configure [Connect webhooks](https://docs.stripe.com/connect/webhooks.md) and listen for the `account.updated` event. A connected account is ready to receive payments when its `charges_enabled` property is true. ## Integrate embedded payments and payouts Add the [payments](https://docs.stripe.com/connect/supported-embedded-components/payments.md) and [payouts](https://docs.stripe.com/connect/supported-embedded-components/payouts.md) embedded components to your platform *before* building your payments integration. That way, a connected account can easily access and manage their core payment workflows. The payments component shows a list of the connected account’s payments, and includes filtering and individual payment detail views. An account can issue refunds and respond to disputes with evidence on individual payments through this component. If you choose to build and maintain a completely API-driven custom payment list instead, you can still enable refunds and disputes using either the [Payment details](https://docs.stripe.com/connect/supported-embedded-components/payment-details.md) component, the [Disputes for a payment](https://docs.stripe.com/connect/supported-embedded-components/disputes-for-a-payment.md) component, or our [APIs](https://docs.stripe.com/disputes/api.md). ## Create an Account Session When you [create an Account Session](https://docs.stripe.com/api/account_sessions/create.md), enable the payments embedded component by specifying `payments` in the `components` parameter. You can turn on or off an individual feature of the payments component by specifying the `features` parameter under `payments`: ```curl curl https://api.stripe.com/v1/account_sessions \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ -d "components[payments][enabled]=true" \ -d "components[payments][features][refund_management]=true" \ -d "components[payments][features][dispute_management]=true" \ -d "components[payments][features][capture_payments]=true" \ -d "components[payments][features][destination_on_behalf_of_charge_management]=false" ``` Your connected accounts can view the complete set of information about direct charges. They can also manage refunds, manage disputes, and capture payments if you enable the corresponding features when creating an account session. ## Render the payments component After you create the account session and [initialize ConnectJS](https://docs.stripe.com/connect/get-started-connect-embedded-components.md#account-sessions), you can render the payments component in the front end: #### JavaScript ```js // Include this element in your HTML const payments = stripeConnectInstance.create('payments'); container.appendChild(payments); // Optional: specify filters to apply on load // payments.setDefaultFilters({ // amount: {greaterThan: 100}, // date: {before: new Date(2024, 0, 1)}, // status: ['partially_refunded', 'refund_pending', 'refunded'], // paymentMethod: 'card',}); ``` The payouts component shows the connected account’s recent payouts, current balance, and when funds will become available. When [creating an Account Session](https://docs.stripe.com/api/account_sessions/create.md), enable the payouts embedded component by specifying `payouts` in the `components` parameter. You can enable or disable individual features of the payouts component by specifying the `features` parameter under `payouts`: ```curl curl https://api.stripe.com/v1/account_sessions \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ -d "components[payouts][enabled]=true" \ -d "components[payouts][features][instant_payouts]=true" \ -d "components[payouts][features][standard_payouts]=true" \ -d "components[payouts][features][edit_payout_schedule]=true" \ -d "components[payouts][features][external_account_collection]=true" ``` After creating the account session and [initializing ConnectJS](https://docs.stripe.com/connect/get-started-connect-embedded-components.md#account-sessions), you can render the payouts component in the front end: #### JavaScript ```js // Include this element in your HTML const payouts = stripeConnectInstance.create('payouts'); container.appendChild(payouts); ``` For an immersive guide to implementing embedded components, follow the [Connect embedded components integration quickstart](https://docs.stripe.com/connect/connect-embedded-components/quickstart.md). ## Accept a payment If your connected accounts transact directly with customers, use [direct charges](https://docs.stripe.com/connect/direct-charges.md). Stripe assesses payment transaction fees to your platform when `controller.fees.payer` isn’t set to `account` for the [Account](https://docs.stripe.com/api/accounts/object.md). In turn, you’re responsible for charging payment processing fees on your connected accounts. You can specify a value for the [application fee](https://docs.stripe.com/connect/direct-charges.md#collect-fees) on each payment to automatically take fees from connected accounts without having to build it into your integration. (See full diagram at https://docs.stripe.com/connect/build-full-embedded-integration) We recommend using [Stripe Checkout](https://docs.stripe.com/payments/checkout.md), a prebuilt Stripe-hosted page, to accept payments. Checkout supports multiple payment methods and automatically shows the most relevant ones to your customer. You can also use the [Payment Element](https://docs.stripe.com/payments/payment-element.md), a prebuilt UI component you can embed to accept additional payment methods with a single integration. #### Checkout ### Create a Checkout Session (Sisi klien) (Sisi server) A Checkout Session controls what a customer sees in the Stripe-hosted payment page such as line items, the order amount and currency, and acceptable payment methods. When performing direct charges, Checkout uses the connected account’s branding settings. For more information, see [Customize branding](https://docs.stripe.com/connect/direct-charges.md?platform=web&ui=stripe-hosted#branding). Unlike destination charges or separate charges and transfers, connected accounts are responsible for handling disputes on direct charges—it’s not the responsibility of the platform. To create a Checkout Session, add a checkout button to your website that calls a server-side endpoint. ```html Checkout
``` On your server, make the following call to the Stripe API. After creating a Checkout Session, redirect your customer to the [URL](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-url) returned in the response. ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \ -d mode=payment \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d "payment_intent_data[application_fee_amount]=123" \ --data-urlencode "success_url=https://example.com/success" ``` - `line_items`—This parameter represents items that your customer is purchasing and that show up in the hosted user interface. - `success_url`—This argument redirects a customer after they complete a payment. - `Stripe-Account`—This header indicates a [direct charge](https://docs.stripe.com/connect/direct-charges.md) for your connected account. With direct charges, the connected account is responsible for Stripe fees, refunds, and chargebacks. Checkout uses the connected account’s branding, which allows their customers to feel like they’re interacting directly with the connected account instead of your platform. - (Optional) `payment_intent_data[application_fee_amount]`—This argument specifies the amount your platform plans to take from the transaction. After the payment is processed on the connected account, the `application_fee_amount` is transferred to the platform and the Stripe fee is deducted from the connected account’s balance. ### Handle post-payment events (Sisi server) Stripe sends a [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) event when the payment completes. [Use a webhook to receive these events](https://docs.stripe.com/webhooks/quickstart.md) and run actions, such as 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. Some payment methods also take 2-14 days for payment confirmation. Setting up your integration to listen for asynchronous events enables you to accept multiple [payment methods](https://stripe.com/payments/payment-methods-guide) with a single integration. In addition to handling the `checkout.session.completed` event, we recommend handling two other events when collecting payments with Checkout: | Kejadian | Keterangan | Langkah berikutnya | | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | | [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) | The customer has successfully authorized the payment by submitting the Checkout form. | Tunggu pembayaran berhasil atau gagal. | | [checkout.session.async_payment_succeeded](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_succeeded) | Pembayaran pelanggan berhasil. | Penuhi barang atau layanan yang dibeli. | | [checkout.session.async_payment_failed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_failed) | The payment was declined, or it failed for some other reason. | Contact the customer through email and request that they place a new order. | These events all include the [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md) object. After the payment succeeds, the underlying *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) status changes from `processing` to `succeeded`. #### Payment Element ### Create a PaymentIntent (Sisi server) Stripe uses a [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) object to represent your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process. ![An overview diagram of the entire payment flow](https://b.stripecdn.com/docs-statics-srv/assets/accept-a-payment-payment-element.5cf6795a02f864923f9953611493d735.svg) Metode pembayaran yang ditampikan kepada pelanggan selama proses checkout juga disertakan pada PaymentIntent. Anda dapat mengizinkan Stripe untuk secara otomatis menarik metode pembayaran dari pengaturan Dashboard atau Anda dapat mencantumkannya secara manual. Unless your integration requires a code-based option for offering payment methods, Stripe recommends the automated option. That’s because Stripe evaluates the currency, payment method restrictions, and other parameters to determine the list of supported payment methods. Payment methods that increase conversion and that are most relevant to the currency and customer’s location are prioritized. Lower priority payment methods are hidden in an overflow menu (⋯). #### Kelola metode pembayaran dari Dashboard Create a PaymentIntent on your server that specifies the amount and currency. In the latest version of the API, specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. You can manage payment methods from the [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe handles the return of eligible payment methods based on factors such as the transaction’s amount, currency, and payment flow. This makes sure that your PaymentIntent supports the payment methods that you configure in the Dashboard, as applicable. Always decide how much to charge on the server side (a trusted environment) as opposed to the client. This prevents malicious customers from being able to choose their own prices. ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \ -d amount=1099 \ -d currency=eur \ -d "automatic_payment_methods[enabled]=true" \ -d application_fee_amount=123 ``` #### Cantumkan metode pembayaran secara manual ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \ -d amount=1099 \ -d currency=eur \ -d "payment_method_types[]=bancontact" \ -d "payment_method_types[]=card" \ -d "payment_method_types[]=eps" \ -d "payment_method_types[]=ideal" \ -d "payment_method_types[]=p24" \ -d "payment_method_types[]=sepa_debit" \ -d "payment_method_types[]=sofort" \ -d application_fee_amount=123 ``` When creating a PaymentIntent, you need to specify certain parameters: - `amount` - Create a PaymentIntent on your server with a specified amount. Always determine how much to charge on the server side, as this is a trusted environment. This approach prevents malicious customers from choosing their own prices. - `currency` - The currency you include in the PaymentIntent filters the payment methods shown to the customer, so choose it based on the payment methods you want to offer. For example, if you pass `eur` and have OXXO enabled in the Dashboard, OXXO won’t appear to the customer because it doesn’t support `eur` payments. Some payment methods support multiple currencies and countries. This guide uses Bancontact, credit cards, EPS, iDEAL, Przelewy24, SEPA Direct Debit, and Sofort in the example code. - `"payment_method_types[]"` - Manually list all the payment methods you want to support. - (Optional) `payment_intent_data[application_fee_amount]` - This argument specifies the amount your platform plans to take from the transaction. If you’re using Stripe’s [Platform Pricing Tool](https://docs.stripe.com/connect/platform-pricing-tools.md) to manage application fee pricing from the [Dashboard](https://dashboard.stripe.com/test/settings/connect/platform_pricing/payments), don’t include this argument as it’ll override any pricing logic set by the tool. After processing the payment on the connected account, the `application_fee_amount` transfers to the platform, and the Stripe fee is deducted from the connected account’s balance. > Each payment method needs to support the currency passed in the PaymentIntent and your business needs to be based in one of the countries each payment method supports. See [Payment method integration options](https://docs.stripe.com/payments/payment-methods/integration-options.md) for more details about what’s supported. ### Ambil client secret PaymentIntent menyertakan *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) yang digunakan pada sisi client untuk menyelesaian proses pembayaran dengan aman. Anda dapat menggunakan pendekatan berbeda untuk meneruskan client secret ke sisi client. #### Aplikasi halaman tunggal Ambil client secret dari endpoint pada server Anda, menggunakan fungsi `fetch` browser. Pendekatan ini paling baik jika sisi client Anda adalah aplikasi satu halaman, terutama yang dibangun dengan kerangka kerja frontend modern seperti React. Buat endpoint server yang melayani client secret: #### Ruby ```ruby get '/secret' do intent = # ... Create or retrieve the PaymentIntent {client_secret: intent.client_secret}.to_json end ``` Kemudian ambil client secret dengan JavaScript pada sisi client: ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` #### Rendering sisi server Teruskan client secret ke client dari server Anda. Pendekatan ini berfungsi paling baik jika aplikasi menghasilkan konten statis pada server sebelum mengirimkannya ke browser. Tambahkan [client_secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) di formulir checkout Anda. Di kode sisi server Anda, ambil client secret dari PaymentIntent: #### Ruby ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the PaymentIntent erb :checkout end ``` ### Collect payment details (Sisi klien) Collect payment details on the client with the Payment Element. The Payment Element is a prebuilt UI component that simplifies collecting payment details for a variety of payment methods. Payment Element berisi iframe yang mengirimkan informasi pembayaran dengan aman ke Stripe melalui koneksi HTTPS. Hindari penempatan Payment Element dalam iframe lain karena sejumlah metode pembayaran memerlukan pengalihan ke halaman lain untuk konfirmasi pembayaran. The checkout page address must start with `https://` rather than `http://` for your integration to work. You can test your integration without using HTTPS, but remember to [enable it](https://docs.stripe.com/security/guide.md#tls) when you’re ready to accept live payments. #### Set up Stripe.js #### HTML+JS Payment Element tersedia secara otomatis sebagai fitur Stripe.js. Sertakan skrip Stripe.js di halaman checkout Anda dengan menambahkannya ke `head` file HTML Anda. Selalu muat Stripe.js langsung dari js.stripe.com agar tetap sesuai dengan PCI. Jangan sertakan skrip dalam bundel atau simpan sendiri salinannya. ```html Checkout ``` Create an instance of `Stripe` with the following JavaScript on your checkout page: ```javascript // Initialize Stripe.js with the same connected account ID used when creating // the PaymentIntent. const stripe = Stripe('<>', { stripeAccount: '{{CONNECTED_ACCOUNT_ID}}' }); ``` ### Add Stripe Elements and the Payment Element to your payment page Payment Element membutuhkan tempat tinggal di halaman pembayaran Anda. Buat simpul DOM kosong (wadah) dengan ID unik di formulir pembayaran Anda. ```html
``` When the form has loaded, create an instance of the Payment Element and mount it to the container DOM node along with the [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) from the previous step. Pass this value as an option when creating the [Elements](https://docs.stripe.com/js/elements_object/create) instance. The client secret must be handled carefully because it can complete the charge. Don’t log it, embed it in URLs, or expose it to anyone but the customer. ```javascript const options = { clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with the Appearance API appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form using the client secret const elements = stripe.elements(options); // Create and mount the Payment Element const paymentElement = elements.create("payment"); paymentElement.mount("#payment-element"); ``` The Payment Element renders a dynamic form that allows your customer to pick a payment method. The form automatically collects all necessary payments details for the payment method selected by the customer. You can [customize the appearance of the Payment Element](https://docs.stripe.com/elements/appearance-api.md) to match the design of your site when you set up the `Elements` object. #### React Instal pustaka Connect.js dan React Connect.js dari [register publik npm](https://www.npmjs.com/package/@stripe/react-connect-js). ```bash npm install --save @stripe/connect-js @stripe/react-connect-js ``` ### Add and configure the Elements provider to your payment page To use the Payment Element component, wrap your checkout page component in an [Elements provider](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider). Call `loadStripe` with your publishable key, and pass the returned `Promise` along with the [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) from the previous step as `options` in the `Elements` provider. ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import {Elements} from '@stripe/react-stripe-js'; import {loadStripe} from '@stripe/stripe-js'; import CheckoutForm from './CheckoutForm'; // Make sure to call `loadStripe` outside of a component’s render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe("<>", { stripeAccount: '{{CONNECTED_ACCOUNT_ID}}' }); function App() { const options = { // pass the client secret from the previous step clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with the Appearance API appearance: {/*...*/}, }; return ( ); }; ReactDOM.render(, document.getElementById('root')); ``` #### Add the PaymentElement component Gunakan komponen `PaymentElement` untuk membuat formulir Anda. ```jsx import React from 'react'; import {PaymentElement} from '@stripe/react-stripe-js'; const CheckoutForm = () => { return (
); }; export default CheckoutForm; ``` The Payment Element renders a dynamic form that allows your customer to pick a payment method type. The form automatically collects all necessary payments details for the payment method selected by the customer. You can [customize the appearance of the Payment Element](https://docs.stripe.com/elements/appearance-api.md) to match the design of your site when you configure the `Elements` provider. ### Submit the payment to Stripe (Sisi klien) Gunakan [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) untuk menyelesaikan pembayaran menggunakan detail dari Payment Element. Berikan [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) ke fungsi ini untuk menunjukkan ke mana Stripe harus mengalihkan pengguna setelah menyelesaikan pembayaran. Pengguna Anda mungkin pertama kali diarahkan ulang ke situs perantara, seperti halaman otorisasi bank, sebelum diarahkan ulang ke `return_url`. Pembayaran kartu segera dialihkan ke `return_url` bila pembayaran berhasil. Jika tidak ingin dialihkan untuk pembayaran kartu setelah pembayaran selesai, Anda dapat mengatur [pengalihan](https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_intent-options-redirect) ke `if_required`. Ini hanya mengalihkan pelanggan yang memproses pembayaran dengan metode pembayaran berbasis pengalihan. #### HTML + JS ```javascript const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://example.com/order/123/complete', }, }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } }); ``` #### React Untuk memanggil [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) dari komponen formulir pembayaran Anda, gunakan kait [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) dan [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook). Jika lebih suka komponen kelas tradisional daripada kait, Anda dapat menggunakan [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer) sebagai gantinya. ```jsx import React, {useState} from 'react'; import {useStripe, useElements, PaymentElement} from '@stripe/react-stripe-js'; const CheckoutForm = () => { const stripe = useStripe(); const elements = useElements(); const [errorMessage, setErrorMessage] = useState(null); const handleSubmit = async (event) => { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); if (!stripe || !elements) { // Stripe.js hasn't yet loaded. // Make sure to disable form submission until Stripe.js has loaded. return; } const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://example.com/order/123/complete', }, }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) setErrorMessage(error.message); } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } }; return (
{/* Show error message to your customers */} {errorMessage &&
{errorMessage}
} ); }; export default CheckoutForm; ``` Pastikan `return_url` sesuai dengan halaman pada situs web Anda yang menyediakan status pembayaran. Bila Stripe mengarahkan ulang pelanggan ke `return_url`, kami menyediakan parameter query URL berikut ini: | Parameter | Keterangan | | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | | `payment_intent` | Identifier unik untuk `PaymentIntent`. | | `payment_intent_client_secret` | [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) dari objek `PaymentIntent`. | > Jika memiliki alat yang melacak sesi browser pelanggan, Anda mungkin perlu menambah domain `stripe.com` ke daftar pengecualian perujuk. Pengarahan ulang menyebabkan sejumlah alat membuat sesi baru, yang mencegah Anda melacak sesi yang telah selesai. Gunakan salah satu parameter query untuk mengambil PaymentIntent. Periksa [status PaymentIntent](https://docs.stripe.com/payments/paymentintents/lifecycle.md) untuk memutuskan apa yang akan ditampilkan kepada pelanggan Anda. Anda juga dapat menambahkan parameter query Anda sendiri saat memberikan `return_url`, yang akan tetap ada selama proses pengalihan. #### HTML + JS ```javascript // Initialize Stripe.js using your publishable key const stripe = Stripe('<>'); // Retrieve the "payment_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'payment_intent_client_secret' ); // Retrieve the PaymentIntent stripe.retrievePaymentIntent(clientSecret).then(({paymentIntent}) => { const message = document.querySelector('#message') // Inspect the PaymentIntent `status` to indicate the status of the payment // to your customer. // // Some payment methods will [immediately succeed or fail][0] upon // confirmation, while others will first enter a `processing` state. // // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification switch (paymentIntent.status) { case 'succeeded': message.innerText = 'Success! Payment received.'; break; case 'processing': message.innerText = "Payment processing. We'll update you when payment is received."; break; case 'requires_payment_method': message.innerText = 'Payment failed. Please try another payment method.'; // Redirect your user back to your payment page to attempt collecting // payment again break; default: message.innerText = 'Something went wrong.'; break; } }); ``` #### React ```jsx import React, {useState, useEffect} from 'react'; import {useStripe} from '@stripe/react-stripe-js'; const PaymentStatus = () => { const stripe = useStripe(); const [message, setMessage] = useState(null); useEffect(() => { if (!stripe) { return; } // Retrieve the "payment_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'payment_intent_client_secret' ); // Retrieve the PaymentIntent stripe .retrievePaymentIntent(clientSecret) .then(({paymentIntent}) => { // Inspect the PaymentIntent `status` to indicate the status of the payment // to your customer. // // Some payment methods will [immediately succeed or fail][0] upon // confirmation, while others will first enter a `processing` state. // // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification switch (paymentIntent.status) { case 'succeeded': setMessage('Success! Payment received.'); break; case 'processing': setMessage("Payment processing. We'll update you when payment is received."); break; case 'requires_payment_method': // Redirect your user back to your payment page to attempt collecting // payment again setMessage('Payment failed. Please try another payment method.'); break; default: setMessage('Something went wrong.'); break; } }); }, [stripe]); return message; }; export default PaymentStatus; ``` ### Handle post-payment events (Sisi server) Stripe mengirim kejadian [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) ketika selesai pembayaran. Gunakan [alat webhook Dashboard](https://dashboard.stripe.com/webhooks) atau ikuti [panduan webhook](https://docs.stripe.com/webhooks/quickstart.md) untuk menerima kejadian ini dan menjalankan tindakan, seperti mengirim email konfirmasi pesanan kepada pelanggan Anda, mencatat penjualan di database, atau memulai alur kerja pengiriman. Dengarkan kejadian ini daripada menunggu callback dari client. Di client, pelanggan dapat menutup jendela browser atau keluar dari aplikasi sebelum callback mengeksekusi, dan klien jahat dapat memanipulasi respons. Penyiapan integrasi untuk mendengarkan kejadian asinkron memungkinkan Anda menyetujui [berbagai tipe metode pembayaran](https://stripe.com/payments/payment-methods-guide) dengan satu integrasi tunggal. Selain menangani kejadian `payment_intent.succeeded`, kami merekomendasikan penanganan kejadian ini yang lain ketika menagih pembayaran dengan Payment Element: | Kejadian | Keterangan | Tindakan | | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | Dikirim bila pelanggan berhasil menyelesaikan pembayaran. | Kirimi pelanggan konfirmasi pesanan dan *penuhi* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) pesanan mereka. | | [payment_intent. pemrosesan](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | Dikirim bila pelanggan berhasil memprakarsai pembayaran, tetapi pembayaran itu belum selesai. Kejadian ini paling umum dikirim saat pelanggan memprakarsai debit bank. Kejadian diikuti dengan kejadian `payment_intent.succeeded` atau `payment_intent.payment_failed` di masa mendatang. | Kirimi pelanggan konfirmasi pesanan yang menunjukkan bahwa pembayaran mereka menunggu penyelesaian. Untuk barang digital, Anda mungkin ingin memenuhi pesanan sebelum menunggu pembayaran selesai. | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | Dikirim bila pelanggan mencoba melakukan pembayaran, tetapi pembayaran itu gagal. | Jika transisi pembayaran dilakukan dari `processing` menjadi `payment_failed`, tawarkan upaya lain untuk membayar kepada pelanggan. | ## Set up email communications to connected accounts Stripe communicates with your connected accounts on your behalf to manage risk and ensure ongoing compliance. You can customize and brand these email communications with your own email domain and platform branding. We send the following emails to your connected accounts: - **Account emails** verify an account’s information, such as additions or changes to an email address, phone number, or bank account. - **Compliance emails** notify accounts to provide required information. Stripe often needs to collect further information to maintain compliance with our financial partners. - **Risk emails** notify accounts when they’re under a risk review. These emails often provide instructions on how to submit information to resolve a risk action; for example, to remove a pause on payouts. - **Tax emails** (only when Stripe collects Stripe fees directly from connected accounts) notify users when their tax invoices or 1099s are ready to download. If you want to send any other payments-related emails to your connected accounts, you must send them yourself. For example, to send emails for new disputes, [listen for](https://docs.stripe.com/webhooks.md) the `charge.dispute.created` event on a connected account. When that event occurs, use [the Disputes API](https://docs.stripe.com/api/disputes.md) to get the details and email them to the account. You must [update your Connect settings with the URLs](https://dashboard.stripe.com/settings/connect/site-links) of your payments and connected account workflows so Stripe’s email communications can direct your connected accounts to them. You must set these links before creating an `AccountSession` or an `AccountLink` in live mode. ## Handle redirects from email links Emails sent by Stripe that contain a call to action need to include a link to that action. For example, if we send an email directing action on a connected account, it must include a link to your Account management component. Before you can create a live mode Account Session, you must provide the URLs where you have integrated the embedded components into your website. Configure the sending email domain and embedded component URLs in the **Site links** section of [your platform’s Connect settings](https://dashboard.stripe.com/settings/connect/site-links). > Testing environments use the same URLs as live mode. For embedded components integrated in your site, select **Yes** and enter the URL of the page that hosts the component. For any actions not handled by an embedded component, select **No** and enter the URL of the page on your site where the account can perform the action. After entering the URLs, test them to verify that they open the right pages. You must set URLs for the following: - Notification banner - Account management - Payments - Payouts - Balances - Documents (when Stripe collects Stripe fees directly from connected accounts) When sending an email, Stripe automatically appends the connected account ID to the redirect URL as the `stripe_account_id` parameter. Use that parameter to identify the account and verify that they’re authenticated. Set up the route on your server to read the parameters and display the correct embedded component. For more information about configuring Stripe emails to your connected accounts, see [Email communications in embedded Connect integrations](https://docs.stripe.com/connect/embedded-comms.md) ## Configure email branding and settings Stripe can send emails reflecting your platform’s brand settings from your own email domain to your connected accounts. To configure Stripe emails to your connected accounts, visit [Emails](https://dashboard.stripe.com/settings/connect/emails) in your platform Dashboard. ## Go live At this point, you’ve configured your platform integration by doing the following: - Created connected accounts in the correct configuration - Integrated embedded components to allow connected accounts to onboard, manage their account, and respond to risk actions through your website - Set up payments using Direct charges with an application fee - Set up branded email communications to enable Stripe to communicate with your users for compliance, risk actions, and necessary documents ## Test your integration Test your account creation flow by using the embedded account onboarding integrated in your platform. Test the settings of your payment methods for your connected accounts by logging into one of your test accounts and navigating to the [Payment methods settings](https://dashboard.stripe.com/settings/payment_methods). Test your checkout flow with your test keys and a test account. You can use our [test cards](https://docs.stripe.com/testing.md) to test your payments flow and simulate various payment outcomes.