# Accept a stablecoin payment Start accepting stablecoins by integrating the Crypto payment method. You can accept stablecoin payments with *Checkout*, *Elements*, or can be directly integrated through the *Payment Intents API*. If you’re a Connect platform, see [Connect support](https://docs.stripe.com/crypto/stablecoin-payments.md#connect-support). When integrated, the option to pay with crypto appears in your checkout page, redirecting customers to a page hosted by *crypto.link.com* for payment completion. There, your customers can connect their wallet, and save and reuse their account using *Link*. You’re [immediately notified](https://docs.stripe.com/payments/payment-methods.md#payment-notification) if the payment succeeds or fails. Before you get started, see our [demo](https://buy.stripe.com/test_28o4ig0SY9Xq8co3cc). ![Let your users pay with crypto](images/crypto/accept-stablecoin-payments.png) Let your users pay with crypto # Stripe-hosted page > This is a Stripe-hosted page for when platform is web and payment-ui is stripe-hosted. View the original doc at https://docs.stripe.com/crypto/accept-stablecoin-payments?platform=web&payment-ui=stripe-hosted. Before you can enable crypto as a payment method within the prebuilt checkout page, go to your [payment methods settings](https://dashboard.stripe.com/settings/payment_methods) and request the **Crypto**. After we review your information and approve you as a user, the **Crypto** payment method appears as active in the Stripe Dashboard. When creating a new [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md), you need to: 1. Add `crypto` to the list of `payment_method_types`. 1. Make sure all `line_items` use `usd`. ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u <>: \ -d mode=payment \ -d "payment_method_types[0]"=crypto \ -d "line_items[0][price_data][currency]"=usd \ -d "line_items[0][price_data][product_data][name]"=T-shirt \ -d "line_items[0][price_data][unit_amount]"=2000 \ -d "line_items[0][quantity]"=1 \ --data-urlencode success_url="https://example.com/success" ``` ## Test your integration Test your Pay with Crypto integration with your test API keys by viewing the redirect page. You can test the successful payment case by authenticating the payment on the redirect page. The [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) transitions from `requires_action` to `succeeded`. 1. In *sandbox*, pay with testnet crypto assets on the payment page you’re redirected to. 1. Configure your wallet to the test network you intend to pay over. For example, if you want to pay with USDC on Ethereum, make sure your wallet is set to Ethereum’s Sepolia test network. You can use testnet “faucets” to top up your wallet. Here are a few: - [Circle USDC](https://faucet.circle.com/) - [Paxos USDP](https://faucet.paxos.com/) - [Devnet SOL](https://faucet.solana.com/) - [Sepolia ETH](https://faucets.chain.link/sepolia) - [Amoy POL](https://faucet.polygon.technology/) # Advanced integration > This is a Advanced integration for when platform is web and payment-ui is elements. View the original doc at https://docs.stripe.com/crypto/accept-stablecoin-payments?platform=web&payment-ui=elements. Embed a custom payment form in your website or application using the [Payment Element](https://docs.stripe.com/payments/payment-element.md). The Payment Element automatically supports crypto and other payment methods. Before you create a PaymentIntent, turn on **Crypto** in your [payment methods settings](https://dashboard.stripe.com/settings/payment_methods). For additional configuration and customization options, see [Accept a Payment](https://docs.stripe.com/payments/accept-a-payment.md?platform=web&ui=elements). ## Set up Stripe Use our official libraries to access the Stripe API from your application: ```bash \# Available as a gem sudo gem install stripe ``` ```ruby \# If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ```bash \# Install through pip pip3 install --upgrade stripe ``` ```bash \# Or find the Stripe package on http://pypi.python.org/pypi/stripe/ ``` ```python \# 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>=5.0.0 ``` ```bash \# Install the PHP library with Composer composer require stripe/stripe-php ``` ```bash \# Or download the source directly: https://github.com/stripe/stripe-php/releases ``` ```java /* For Gradle, add the following dependency to your build.gradle and replace 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:29.0.0" ``` ```xml com.stripe stripe-java 29.0.0 ``` ```bash \# 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 ``` ```bash \# Install with npm npm install stripe --save ``` ```bash \# Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v82 ``` ```go // Then import the package import ( "github.com/stripe/stripe-go/v82" ) ``` ```bash \# Install with dotnet dotnet add package Stripe.net dotnet restore ``` ```bash \# Or install with NuGet Install-Package Stripe.net ``` ## Create a PaymentIntent and retrieve the client secret The [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) object represents your intent to collect payment from a customer and tracks charge attempts and state changes throughout the payment process. ### Create the PaymentIntent 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. ### Retrieve the client secret The {{intentKind}} includes a *client secret* that the client side uses to securely complete the payment process. You can use different approaches to pass the client secret to the client side. Retrieve the client secret from an endpoint on your server, using the browser’s `fetch` function. This approach is best if your client side is a single-page application, particularly one built with a modern frontend framework like React. Create the server endpoint that serves the client secret: ```ruby get '/secret' do intent = # ... Create or retrieve the {{intentKind}} {client_secret: intent.client_secret}.to_json end ``` ```python from flask import Flask, jsonify app = Flask(__name__) @app.route('/secret') def secret(): intent = # ... Create or retrieve the {{intentKind}} return jsonify(client_secret=intent.client_secret) ``` ```php $intent->client_secret)); ?> ``` ```java import java.util.HashMap; import java.util.Map; import com.stripe.model.{{intentKind}}; import com.google.gson.Gson; import static spark.Spark.get; public class StripeJavaQuickStart { public static void main(String[] args) { Gson gson = new Gson(); get("/secret", (request, response) -> { {{intentKind}} intent = // ... Fetch or create the {{intentKind}} Map map = new HashMap(); map.put("client_secret", intent.getClientSecret()); return map; }, gson::toJson); } } ``` ```javascript const express = require('express'); const app = express(); app.get('/secret', async (req, res) => { const intent = // ... Fetch or create the {{intentKind}} res.json({client_secret: intent.client_secret}); }); app.listen(3000, () => { console.log('Running on port 3000'); }); ``` ```go package main import ( "encoding/json" "net/http" stripe "github.com/stripe/stripe-go/v{{golang.major_version}}" ) type CheckoutData struct { ClientSecret string `json:"client_secret"` } func main() { http.HandleFunc("/secret", func(w http.ResponseWriter, r *http.Request) { intent := // ... Fetch or create the {{intentKind}} data := CheckoutData{ ClientSecret: intent.ClientSecret, } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(data) }) http.ListenAndServe(":3000", nil) } ``` ```csharp using System; using Microsoft.AspNetCore.Mvc; using Stripe; namespace StripeExampleApi.Controllers { [Route("secret")] [ApiController] public class CheckoutApiController : Controller { [HttpGet] public ActionResult Get() { var intent = // ... Fetch or create the {{intentKind}} return Json(new {client_secret = intent.ClientSecret}); } } } ``` And then fetch the client secret with JavaScript on the client side: ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` Pass the client secret to the client from your server. This approach works best if your application generates static content on the server before sending it to the browser. ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the {{intentKind}} erb :checkout end ``` ```html
``` ```python @app.route('/checkout') def checkout(): intent = # ... Fetch or create the {{intentKind}} return render_template('checkout.html', client_secret=intent.client_secret) ``` ```php ...
... ``` ```html
``` ```java import java.util.HashMap; import java.util.Map; import com.stripe.model.{{intentKind}}; import spark.ModelAndView; import static spark.Spark.get; public class StripeJavaQuickStart { public static void main(String[] args) { get("/checkout", (request, response) -> { {{intentKind}} intent = // ... Fetch or create the {{intentKind}} Map map = new HashMap(); map.put("client_secret", intent.getClientSecret()); return new ModelAndView(map, "checkout.hbs"); }, new HandlebarsTemplateEngine()); } } ``` ```html
``` ```javascript const express = require('express'); const expressHandlebars = require('express-handlebars'); const app = express(); app.engine('.hbs', expressHandlebars({ extname: '.hbs' })); app.set('view engine', '.hbs'); app.set('views', './views'); app.get('/checkout', async (req, res) => { const intent = // ... Fetch or create the {{intentKind}} res.render('checkout', { client_secret: intent.client_secret }); }); app.listen(3000, () => { console.log('Running on port 3000'); }); ``` ```html
``` ```go package main import ( "html/template" "net/http" stripe "github.com/stripe/stripe-go/v{{golang.major_version}}" ) type CheckoutData struct { ClientSecret string } func main() { checkoutTmpl := template.Must(template.ParseFiles("views/checkout.html")) http.HandleFunc("/checkout", func(w http.ResponseWriter, r *http.Request) { intent := // ... Fetch or create the {{intentKind}} data := CheckoutData{ ClientSecret: intent.ClientSecret, } checkoutTmpl.Execute(w, data) }) http.ListenAndServe(":3000", nil) } ``` ```html
``` ```csharp using System; using Microsoft.AspNetCore.Mvc; using Stripe; namespace StripeExampleApi.Controllers { [Route("/[controller]")] public class CheckoutApiController : Controller { public IActionResult Index() { var intent = // ... Fetch or create the {{intentKind}} ViewData["ClientSecret"] = intent.ClientSecret; return View(); } } } ``` ## Collect payment details Collect payment details on the client with the [Payment Element](https://docs.stripe.com/payments/payment-element.md). The Payment Element is a prebuilt UI component that simplifies collecting payment details for a variety of payment methods. The Payment Element contains an iframe that securely sends payment information to Stripe over an HTTPS connection. Avoid placing the Payment Element within another iframe because some payment methods require redirecting to another page for payment confirmation. 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 The Payment Element is automatically available as a feature of Stripe.js. Include the Stripe.js script on your checkout page by adding it to the `head` of your HTML file. Always load Stripe.js directly from js.stripe.com to remain PCI compliant. Don’t include the script in a bundle or host a copy of it yourself. ```html Checkout ``` Create an instance of Stripe with the following JavaScript on your checkout page: ```javascript // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys ``` ### Add the Payment Element to your payment page The Payment Element needs a place to live on your payment page. Create an empty DOM node (container) with a unique ID in your payment form: ```html
``` When the previous form loads, create an instance of the Payment Element and mount it to the container DOM node. Pass the from the previous step into `options` when you create the [Elements](https://docs.stripe.com/js/elements_object/create) instance: ```javascript const options = { clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with appearance API. appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in a previous step const elements = stripe.elements(options); // Create and mount the Payment Element const paymentElementOptions = { layout: 'accordion'}; const paymentElement = elements.create('payment', paymentElementOptions); paymentElement.mount('#payment-element'); ``` ### Set up Stripe.js Install [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) and the [Stripe.js loader](https://www.npmjs.com/package/@stripe/stripe-js) from the npm public registry: ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-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` to the `Elements` provider. Also pass the [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) from the previous step as `options` to 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'; // Make sure to call `loadStripe` outside of a component’s render to avoid // recreating the `Stripe` object on every render. function App() { const options = { // passing the client secret obtained in step 3 clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with appearance API. appearance: {/*...*/}, }; return ( ); }; ReactDOM.render(, document.getElementById('root')); ``` ### Add the Payment Element component Use the `PaymentElement` component to build your form: ## Fetch updates from the server You might want to update attributes on the PaymentIntent after the Payment Element renders, such as the [amount](https://docs.stripe.com/api/payment_intents/update.md#update_payment_intent-amount) (for example, discount codes or shipping costs). You can [update the PaymentIntent](https://docs.stripe.com/api/payment_intents/update.md) on your server, then call [elements.fetchUpdates](https://docs.stripe.com/js/elements_object/fetch_updates) to see the new amount reflected in the Payment Element. This example shows you how to create the server endpoint that updates the amount on the PaymentIntent: ```ruby get '/update' do intent = Stripe::PaymentIntent.update( '{{PAYMENT_INTENT_ID}}', {amount: 1499}, ) {status: intent.status}.to_json end ``` ```python @app.route('/update') def secret(): intent = stripe.PaymentIntent.modify( "{{PAYMENT_INTENT_ID}}", amount=1499, ) return jsonify(status=intent.status) ``` ```php paymentIntents->update( '{{PAYMENT_INTENT_ID}}', ['amount' => 1499] ); echo json_encode(array('status' => $intent->status)); ?> ``` ```java import java.util.HashMap; import java.util.Map; import com.stripe.model.PaymentIntent; import com.google.gson.Gson; import static spark.Spark.get; public class StripeJavaQuickStart { public static void main(String[] args) { Gson gson = new Gson(); get("/update", (request, response) -> { PaymentIntent paymentIntent = PaymentIntent.retrieve( "{{PAYMENT_INTENT_ID}}" ); Map params = new HashMap<>(); params.put("amount", 1499); PaymentIntent updatedPaymentIntent = paymentIntent.update(params); Map response = new HashMap(); response.put("status", updatedPaymentIntent.getStatus()); return map; }, gson::toJson); } } ``` ```javascript app.get('/update', async (req, res) => { const intent = await stripe.paymentIntents.update( '{{PAYMENT_INTENT_ID}}', {amount: 1499} ); res.json({status: intent.status}); }); ``` ```go package main import ( "encoding/json" "net/http" stripe "github.com/stripe/stripe-go/v{{golang.major_version}}" ) type UpdateData struct { Status string `json:"status"` } func main() { http.HandleFunc("/update", func(w http.ResponseWriter, r *http.Request) { params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1499), } pi, _ := paymentintent.Update( "{{PAYMENT_INTENT_ID}}", params, ) data := UpdateData{ Status: pi.Status, } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(data) }) http.ListenAndServe(":3000", nil) } ``` ```csharp using System; using Microsoft.AspNetCore.Mvc; using Stripe; namespace StripeExampleApi.Controllers { [Route("update")] [ApiController] public class CheckoutApiController : Controller { [HttpPost] public ActionResult Post() { var options = new PaymentIntentUpdateOptions { Amount = 1499, }; var service = new PaymentIntentService(); var intent = service.Update( "{{PAYMENT_INTENT_ID}}", options); return Json(new {status = intent.Status}); } } } ``` This example demonstrates how to update the UI to reflect these changes on the client side: ```javascript (async () => { const response = await fetch('/update'); if (response.status === 'requires_payment_method') { const {error} = await elements.fetchUpdates(); } })(); ``` ## Submit the payment to Stripe Use [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) to complete the payment using details from the Payment Element. Provide a [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) to this function to indicate where Stripe should redirect the user after they complete the payment. Your user may be first redirected to an intermediate site, like a bank authorization page, before being redirected to the `return_url`. Card payments immediately redirect to the `return_url` when a payment is successful. ```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`. } }); ``` To call [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) from your payment form component, use the [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) and [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook) hooks. If you prefer traditional class components over hooks, you can instead use an [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer). ```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; ``` Make sure the `return_url` corresponds to a page on your website that provides the status of the payment. When Stripe redirects the customer to the `return_url`, we provide the following URL query parameters: | Parameter | Description | | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | | `payment_intent` | The unique identifier for the `PaymentIntent`. | | `payment_intent_client_secret` | The [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) of the `PaymentIntent` object. | If you have tooling that tracks the customer’s browser session, you might need to add the `stripe.com` domain to the referrer exclude list. Redirects cause some tools to create new sessions, which prevents you from tracking the complete session. Use one of the query parameters to retrieve the PaymentIntent. Inspect the [status of the PaymentIntent](https://docs.stripe.com/payments/paymentintents/lifecycle.md) to decide what to show your customers. You can also append your own query parameters when providing the `return_url`, which persist through the redirect process. ```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; } }); ``` ```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; ``` ## Redirect and authenticate transactions Customers can authenticate crypto transactions in the browser. After calling `confirmPayment`, we redirect customers to a page hosted by *crypto.link.com* to confirm their payment. When confirmation is complete, we redirect customers to the `return_url`. ## Test your integration Test your Pay with Crypto integration with your test API keys by viewing the redirect page. You can test the successful payment case by authenticating the payment on the redirect page. The [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) transitions from `requires_action` to `succeeded`. 1. In *sandbox*, pay with testnet crypto assets on the payment page you’re redirected to. 1. Configure your wallet to the test network you intend to pay over. For example, if you want to pay with USDC on Ethereum, make sure your wallet is set to Ethereum’s Sepolia test network. You can use testnet “faucets” to top up your wallet. Here are a few: - [Circle USDC](https://faucet.circle.com/) - [Paxos USDP](https://faucet.paxos.com/) - [Devnet SOL](https://faucet.solana.com/) - [Sepolia ETH](https://faucets.chain.link/sepolia) - [Amoy POL](https://faucet.polygon.technology/) # Direct API > This is a Direct API for when platform is web and payment-ui is direct-api. View the original doc at https://docs.stripe.com/crypto/accept-stablecoin-payments?platform=web&payment-ui=direct-api. Integrate Pay with Crypto directly through the *Payment Intents API*. Before you create a PaymentIntent, turn on **Crypto** in your [payment methods settings](https://dashboard.stripe.com/settings/payment_methods). ## Set up Stripe Use our official libraries to access the Stripe API from your application: ```bash \# Available as a gem sudo gem install stripe ``` ```ruby \# If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ```bash \# Install through pip pip3 install --upgrade stripe ``` ```bash \# Or find the Stripe package on http://pypi.python.org/pypi/stripe/ ``` ```python \# 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>=5.0.0 ``` ```bash \# Install the PHP library with Composer composer require stripe/stripe-php ``` ```bash \# Or download the source directly: https://github.com/stripe/stripe-php/releases ``` ```java /* For Gradle, add the following dependency to your build.gradle and replace 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:29.0.0" ``` ```xml com.stripe stripe-java 29.0.0 ``` ```bash \# 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 ``` ```bash \# Install with npm npm install stripe --save ``` ```bash \# Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v82 ``` ```go // Then import the package import ( "github.com/stripe/stripe-go/v82" ) ``` ```bash \# Install with dotnet dotnet add package Stripe.net dotnet restore ``` ```bash \# Or install with NuGet Install-Package Stripe.net ``` ## Create a PaymentIntent and retrieve the client secret The [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) object represents your intent to collect payment from your customer and tracks the lifecycle of the payment process. Create a PaymentIntent on your server and specify the amount to collect and a supported currency. If you have an existing Payment Intents integration, add `crypto` to the list of [payment_method_types](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_types). ```curl curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -d "payment_method_types[]"=crypto \ -d amount=1099 \ -d currency=usd ``` ### Retrieve the client secret The {{intentKind}} includes a *client secret* that the client side uses to securely complete the payment process. You can use different approaches to pass the client secret to the client side. Retrieve the client secret from an endpoint on your server, using the browser’s `fetch` function. This approach is best if your client side is a single-page application, particularly one built with a modern frontend framework like React. Create the server endpoint that serves the client secret: ```ruby get '/secret' do intent = # ... Create or retrieve the {{intentKind}} {client_secret: intent.client_secret}.to_json end ``` ```python from flask import Flask, jsonify app = Flask(__name__) @app.route('/secret') def secret(): intent = # ... Create or retrieve the {{intentKind}} return jsonify(client_secret=intent.client_secret) ``` ```php $intent->client_secret)); ?> ``` ```java import java.util.HashMap; import java.util.Map; import com.stripe.model.{{intentKind}}; import com.google.gson.Gson; import static spark.Spark.get; public class StripeJavaQuickStart { public static void main(String[] args) { Gson gson = new Gson(); get("/secret", (request, response) -> { {{intentKind}} intent = // ... Fetch or create the {{intentKind}} Map map = new HashMap(); map.put("client_secret", intent.getClientSecret()); return map; }, gson::toJson); } } ``` ```javascript const express = require('express'); const app = express(); app.get('/secret', async (req, res) => { const intent = // ... Fetch or create the {{intentKind}} res.json({client_secret: intent.client_secret}); }); app.listen(3000, () => { console.log('Running on port 3000'); }); ``` ```go package main import ( "encoding/json" "net/http" stripe "github.com/stripe/stripe-go/v{{golang.major_version}}" ) type CheckoutData struct { ClientSecret string `json:"client_secret"` } func main() { http.HandleFunc("/secret", func(w http.ResponseWriter, r *http.Request) { intent := // ... Fetch or create the {{intentKind}} data := CheckoutData{ ClientSecret: intent.ClientSecret, } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(data) }) http.ListenAndServe(":3000", nil) } ``` ```csharp using System; using Microsoft.AspNetCore.Mvc; using Stripe; namespace StripeExampleApi.Controllers { [Route("secret")] [ApiController] public class CheckoutApiController : Controller { [HttpGet] public ActionResult Get() { var intent = // ... Fetch or create the {{intentKind}} return Json(new {client_secret = intent.ClientSecret}); } } } ``` And then fetch the client secret with JavaScript on the client side: ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` Pass the client secret to the client from your server. This approach works best if your application generates static content on the server before sending it to the browser. ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the {{intentKind}} erb :checkout end ``` ```html
``` ```python @app.route('/checkout') def checkout(): intent = # ... Fetch or create the {{intentKind}} return render_template('checkout.html', client_secret=intent.client_secret) ``` ```php ...
... ``` ```html
``` ```java import java.util.HashMap; import java.util.Map; import com.stripe.model.{{intentKind}}; import spark.ModelAndView; import static spark.Spark.get; public class StripeJavaQuickStart { public static void main(String[] args) { get("/checkout", (request, response) -> { {{intentKind}} intent = // ... Fetch or create the {{intentKind}} Map map = new HashMap(); map.put("client_secret", intent.getClientSecret()); return new ModelAndView(map, "checkout.hbs"); }, new HandlebarsTemplateEngine()); } } ``` ```html
``` ```javascript const express = require('express'); const expressHandlebars = require('express-handlebars'); const app = express(); app.engine('.hbs', expressHandlebars({ extname: '.hbs' })); app.set('view engine', '.hbs'); app.set('views', './views'); app.get('/checkout', async (req, res) => { const intent = // ... Fetch or create the {{intentKind}} res.render('checkout', { client_secret: intent.client_secret }); }); app.listen(3000, () => { console.log('Running on port 3000'); }); ``` ```html
``` ```go package main import ( "html/template" "net/http" stripe "github.com/stripe/stripe-go/v{{golang.major_version}}" ) type CheckoutData struct { ClientSecret string } func main() { checkoutTmpl := template.Must(template.ParseFiles("views/checkout.html")) http.HandleFunc("/checkout", func(w http.ResponseWriter, r *http.Request) { intent := // ... Fetch or create the {{intentKind}} data := CheckoutData{ ClientSecret: intent.ClientSecret, } checkoutTmpl.Execute(w, data) }) http.ListenAndServe(":3000", nil) } ``` ```html
``` ```csharp using System; using Microsoft.AspNetCore.Mvc; using Stripe; namespace StripeExampleApi.Controllers { [Route("/[controller]")] public class CheckoutApiController : Controller { public IActionResult Index() { var intent = // ... Fetch or create the {{intentKind}} ViewData["ClientSecret"] = intent.ClientSecret; return View(); } } } ``` ## Redirect to the stablecoin payments page Use [Stripe.js](https://docs.stripe.com/js) to submit the payment to Stripe when a customer chooses **Crypto** as a payment method. Stripe.js is the foundational JavaScript library for building payment flows. It automatically handles complexities like the redirect described below, and lets you extend your integration to other payment methods. Include the Stripe.js script on your checkout page by adding it to the `` of your HTML file. ```html Checkout ``` Create an instance of Stripe.js with the following JavaScript on your checkout page: ```javascript // Set your publishable key. Remember to change this to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe('<>'); ``` Use the PaymentIntent [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) and call `stripe.confirmPayment` to handle the Pay with Crypto redirect. Add a `return_url` to determine where Stripe redirects the customer after they complete the payment: ```javascript const form = document.getElementById('payment-form'); form.addEventListener('submit', async function(event) { event.preventDefault(); // Set the clientSecret of the PaymentIntent const { error } = await stripe.confirmPayment({ clientSecret: clientSecret, confirmParams: { payment_method_data: { type: 'crypto', }, // Return URL where the customer should be redirected after the authorization return_url: `${window.location.href}`, }, }); if (error) { // Inform the customer that there was an error. const errorElement = document.getElementById('error-message'); errorElement.textContent = result.error.message; } }); ``` The `return_url` corresponds to a page on your website that displays the result of the payment. You can determine what to display by [verifying the status](https://docs.stripe.com/payments/payment-intents/verifying-status.md#checking-status) of the PaymentIntent. To verify the status, the Stripe redirect to the `return_url` includes the following URL query parameters. You can also append your own query parameters to the `return_url`. They persist throughout the redirect process. | | | | | `payment_intent` | The unique identifier for the `PaymentIntent`. | | `payment_intent_client_secret` | The [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) of the `PaymentIntent` object. | ## Handle post-payment events Stripe sends a [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) event when the payment completes. Use the Dashboard, a custom [webhook](https://docs.stripe.com/webhooks.md), 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 might close the browser window or quit the app before the callback executes, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events can also help you accept more payment methods in the future. To see the differences between all supported payment methods, see our [payment methods](https://stripe.com/payments/payment-methods-guide) guide. ### Receive events and run business actions There are a few options for receiving and running business actions: - **Manually:** Use the [Stripe Dashboard](https://dashboard.stripe.com/test/payments) to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments. - **Custom code:** [Build a webhook](https://docs.stripe.com/payments/handling-payment-events.md#build-your-own-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 [automation](https://stripe.partners/?f_category=automation) or [marketing and sales](https://stripe.partners/?f_category=marketing-and-sales), by integrating a partner application. ### Supported currencies You can create crypto payments in the currencies that map to your country. The default local currency for crypto is USD, with customers also seeing their purchase amount in this currency. ## Test your integration Test your Pay with Crypto integration with your test API keys by viewing the redirect page. You can test the successful payment case by authenticating the payment on the redirect page. The [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) transitions from `requires_action` to `succeeded`. 1. In *sandbox*, pay with testnet crypto assets on the payment page you’re redirected to. 1. Configure your wallet to the test network you intend to pay over. For example, if you want to pay with USDC on Ethereum, make sure your wallet is set to Ethereum’s Sepolia test network. You can use testnet “faucets” to top up your wallet. Here are a few: - [Circle USDC](https://faucet.circle.com/) - [Paxos USDP](https://faucet.paxos.com/) - [Devnet SOL](https://faucet.solana.com/) - [Sepolia ETH](https://faucets.chain.link/sepolia) - [Amoy POL](https://faucet.polygon.technology/) # iOS > This is a iOS for when platform is mobile and payment-ui is ios. View the original doc at https://docs.stripe.com/crypto/accept-stablecoin-payments?platform=mobile&payment-ui=ios. We recommend you use the [Mobile Payment Element](https://docs.stripe.com/payments/accept-a-payment.md?=ios), an embeddable payment form, to add Pay with Crypto and other payment methods to your integration with the least amount of effort. Pay with Crypto is a [single-use](https://docs.stripe.com/payments/payment-methods.md#usage) payment method where customers are required to [authenticate](https://docs.stripe.com/payments/payment-methods.md#customer-actions) their payment. Customers are redirected from your app, authorize the payment with Stripe Crypto, then return to your app. You’re [immediately notified](https://docs.stripe.com/payments/payment-methods.md#payment-notification) when the payment succeeds or fails. ## Set up Stripe ### Server-side This integration requires endpoints on your server that talk to the Stripe API. Use the official libraries for access to the Stripe API from your server: ```bash \# Available as a gem sudo gem install stripe ``` ```ruby \# If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ```bash \# Install through pip pip3 install --upgrade stripe ``` ```bash \# Or find the Stripe package on http://pypi.python.org/pypi/stripe/ ``` ```python \# 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>=5.0.0 ``` ```bash \# Install the PHP library with Composer composer require stripe/stripe-php ``` ```bash \# Or download the source directly: https://github.com/stripe/stripe-php/releases ``` ```java /* For Gradle, add the following dependency to your build.gradle and replace 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:29.0.0" ``` ```xml com.stripe stripe-java 29.0.0 ``` ```bash \# 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 ``` ```bash \# Install with npm npm install stripe --save ``` ```bash \# Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v82 ``` ```go // Then import the package import ( "github.com/stripe/stripe-go/v82" ) ``` ```bash \# Install with dotnet dotnet add package Stripe.net dotnet restore ``` ```bash \# Or install with NuGet Install-Package Stripe.net ``` ### Client-side Configure the SDK with your Stripe [publishable key](https://dashboard.stripe.com/test/apikeys) on app start. This enables your app to make requests to the Stripe API. Use your [test keys](https://docs.stripe.com/keys.md#obtain-api-keys) while you test and develop, and your [live mode](https://docs.stripe.com/keys.md#test-live-modes) keys when you publish your app. ## Create a PaymentIntent ### Server-side A [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) is an object that represents your intent to collect payment from a customer and tracks the lifecycle of the payment process through each stage. You can manage payment methods in 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. Create a PaymentIntent on your server with an amount and currency. Before creating the PaymentIntent, make sure to turn **Pay with Crypto** on in your [Payment methods settings](https://dashboard.stripe.com/settings/payment_methods). Always decide how much to charge on the server-side, a trusted environment, as opposed to the client. This prevents customers from being able to choose their own prices. If you don’t want to use the Dashboard or you want to manually specify payment methods, you can list them using the `payment_method_types` attribute. Create a PaymentIntent on your server with an amount, currency, and a list of payment methods. Always decide how much to charge on the server-side, a trusted environment, as opposed to the client. This prevents customers from being able to choose their own prices. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new PaymentIntentCreateOptions { Amount = 1099, Currency = "usd", PaymentMethodTypes = new List { "crypto" }, }; var service = new PaymentIntentService(); PaymentIntent paymentIntent = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1099), Currency: stripe.String(string(stripe.CurrencyUSD)), PaymentMethodTypes: []*string{stripe.String("crypto")}, }; result, err := paymentintent.New(params); ``` ```java Stripe.apiKey = "<>"; PaymentIntentCreateParams params = PaymentIntentCreateParams.builder() .setAmount(1099L) .setCurrency("usd") .addPaymentMethodType("crypto") .build(); PaymentIntent paymentIntent = PaymentIntent.create(params); ``` ```node const stripe = require('stripe')('<>'); const paymentIntent = await stripe.paymentIntents.create({ amount: 1099, currency: 'usd', payment_method_types: ['crypto'], }); ``` ```python import stripe stripe.api_key = "<>" payment_intent = stripe.PaymentIntent.create( amount=1099, currency="usd", payment_method_types=["crypto"], ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $paymentIntent = $stripe->paymentIntents->create([ 'amount' => 1099, 'currency' => 'usd', 'payment_method_types' => ['crypto'], ]); ``` ```ruby Stripe.api_key = '<>' payment_intent = Stripe::PaymentIntent.create({ amount: 1099, currency: 'usd', payment_method_types: ['crypto'], }) ``` ### Client-side On the client, request a PaymentIntent from your server and store its *client secret*. ```swift class CheckoutViewController: UIViewController { var paymentIntentClientSecret: String? // ...continued from previous step override func viewDidLoad() { // ...continued from previous step startCheckout() } func startCheckout() { // Request a PaymentIntent from your server and store its client secret // Click View full sample to see a complete implementation } } ``` ```objc @interface CheckoutViewController () // ...continued from previous step @property (strong) NSString *paymentIntentClientSecret; @end @implementation CheckoutViewController - (void)viewDidLoad { [super viewDidLoad]; // ...continued from previous step [self startCheckout]; } - (void)startCheckout { // Request a PaymentIntent from your server and store its client secret // Click View full sample to see a complete implementation } @end ``` ## Submit the payment to Stripe When a customer taps to pay with Pay with Crypto, confirm the `PaymentIntent` to complete the payment. Configure an `STPPaymentIntentParams` object with the `PaymentIntent` [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret). The client secret is different from your API keys that authenticate Stripe API requests. Handle it carefully because it can complete the charge. Don’t log it, embed it in URLs, or expose it to anyone but the customer. ### Set up a return URL The iOS SDK presents a webview in your app to complete the Pay with Crypto payment. When authentication is finished, the webview can automatically dismiss itself instead of having your customer close it. To enable this behavior, configure a custom URL scheme or universal link and set up your app delegate to forward the URL to the SDK. ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { let stripeHandled = StripeAPI.handleURLCallback(with: url) if (stripeHandled) { return true } else { // This was not a Stripe url – handle the URL normally as you would } return false } // This method handles opening universal link URLs (for example, "https://example.com/stripe_ios_callback") func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { if userActivity.activityType == NSUserActivityTypeBrowsingWeb { if let url = userActivity.webpageURL { let stripeHandled = StripeAPI.handleURLCallback(with: url) if (stripeHandled) { return true } else { // This was not a Stripe url – handle the URL normally as you would } } } return false } ``` ```objc // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { BOOL stripeHandled = [StripeAPI handleStripeURLCallbackWithURL:url]; if (stripeHandled) { return YES; } else { // This was not a Stripe url – handle the URL normally as you would } return NO; } // This method handles opening universal link URLs (for example, "https://example.com/stripe_ios_callback") - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> * _Nullable))restorationHandler { if (userActivity.activityType == NSUserActivityTypeBrowsingWeb) { if (userActivity.webpageURL) { BOOL stripeHandled = [StripeAPI handleStripeURLCallbackWithURL:userActivity.webpageURL]; if (stripeHandled) { return YES; } else { // This was not a Stripe url – handle the URL normally as you would } return NO; } } return NO; } ``` Pass the URL as the `return_url` when you confirm the PaymentIntent. After webview-based authentication finishes, Stripe redirects the user to the `return_url`. ### Confirm the Pay with Crypto payment Complete the payment by calling `STPPaymentHandler.confirmPayment`. This presents a webview where the customer can complete the payment with Pay with Crypto. After completion, Stripe calls the completion block with the result of the payment. ```swift let paymentIntentParams = STPPaymentIntentParams(clientSecret: paymentIntentClientSecret) // Pay with Crypto does not require additional parameters so we only need to pass the initialized // STPPaymentMethodCryptoParams instance to STPPaymentMethodParams let crypto = STPPaymentMethodCryptoParams() let paymentMethodParams = STPPaymentMethodParams(crypto: crypto, billingDetails: nil, metadata: nil) paymentIntentParams.paymentMethodParams = paymentMethodParams paymentIntentParams.returnURL = "payments-example://stripe-redirect" STPPaymentHandler.shared().confirmPayment(paymentIntentParams, with: self) { (handlerStatus, paymentIntent, error) in switch handlerStatus { case .succeeded: // Payment succeeded // ... case .canceled: // Payment canceled // ... case .failed: // Payment failed // ... @unknown default: fatalError() } } ``` ```objc STPPaymentIntentParams *paymentIntentParams = [[STPPaymentIntentParams alloc] initWithClientSecret:clientSecret]; STPPaymentMethodCryptoParams *crypto = [[STPPaymentMethodCryptoParams alloc] init]; // Pay with Crypto does not require additional parameters so we only need to pass the initialized // STPPaymentMethodCryptoParams instance to STPPaymentMethodParams paymentIntentParams.paymentMethodParams = [STPPaymentMethodParams paramsWithCrypto:crypto billingDetails:nil metadata:nil]; paymentIntentParams.returnURL = @"payments-example://stripe-redirect"; [[STPPaymentHandler sharedHandler] confirmPayment:paymentIntentParams withAuthenticationContext:self.delegate completion:^(STPPaymentHandlerActionStatus handlerStatus, STPPaymentIntent * handledIntent, NSError * _Nullable handlerError) { switch (handlerStatus) {     case STPPaymentHandlerActionStatusFailed:         // Payment failed             // ...             break;         case STPPaymentHandlerActionStatusCanceled:         // Payment canceled             // ...         break;         case STPPaymentHandlerActionStatusSucceeded:           // Payment succeeded             // ...             break; } }]; ``` ## Handle post-payment events Stripe sends a [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-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, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events also helps you accept more payment methods in the future. Learn about the [differences between all supported payment methods](https://stripe.com/payments/payment-methods-guide). ### Manually Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments. * [View your test payments in the Dashboard](https://dashboard.stripe.com/test/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. * [Build a custom webhook](https://docs.stripe.com/payments/handling-payment-events.md#build-your-own-webhook) ### Prebuilt apps Handle common business events, like [automation](https://stripe.partners/?f_category=automation) or [marketing and sales](https://stripe.partners/?f_category=marketing-and-sales), by integrating a partner application. # Android > This is a Android for when platform is mobile and payment-ui is android. View the original doc at https://docs.stripe.com/crypto/accept-stablecoin-payments?platform=mobile&payment-ui=android. We recommend you use the [Mobile Payment Element](https://docs.stripe.com/payments/accept-a-payment.md?platform=android), an embeddable payment form, to add Pay with Crypto and other payment methods to your integration with the least amount of effort. Pay with Crypto is a [single-use](https://docs.stripe.com/payments/payment-methods.md#usage) payment method where customers are required to [authenticate](https://docs.stripe.com/payments/payment-methods.md#customer-actions) their payment. Customers are redirected from your app, authorize the payment with Stripe, then return to your app. You’re [immediately notified](https://docs.stripe.com/payments/payment-methods.md#payment-notification) when the payment succeeds or fails. ## Set up Stripe ### Server-side This integration requires endpoints on your server that talk to the Stripe API. Use the official libraries for access to the Stripe API from your server: ```bash \# Available as a gem sudo gem install stripe ``` ```ruby \# If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ```bash \# Install through pip pip3 install --upgrade stripe ``` ```bash \# Or find the Stripe package on http://pypi.python.org/pypi/stripe/ ``` ```python \# 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>=5.0.0 ``` ```bash \# Install the PHP library with Composer composer require stripe/stripe-php ``` ```bash \# Or download the source directly: https://github.com/stripe/stripe-php/releases ``` ```java /* For Gradle, add the following dependency to your build.gradle and replace 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:29.0.0" ``` ```xml com.stripe stripe-java 29.0.0 ``` ```bash \# 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 ``` ```bash \# Install with npm npm install stripe --save ``` ```bash \# Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v82 ``` ```go // Then import the package import ( "github.com/stripe/stripe-go/v82" ) ``` ```bash \# Install with dotnet dotnet add package Stripe.net dotnet restore ``` ```bash \# Or install with NuGet Install-Package Stripe.net ``` ### Client-side ```kotlin plugins { id("com.android.application") } android { ... } dependencies { // ... } ``` ```groovy apply plugin: 'com.android.application' android { ... } dependencies { // ... } ``` For details on the latest SDK release and past versions, see the [Releases](https://github.com/stripe/stripe-android/releases) page on GitHub. To receive notifications when a new release is published, [watch releases for the repository](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository). Stripe samples also use [OkHttp](https://github.com/square/okhttp) and [GSON](https://github.com/google/gson) to make HTTP requests to a server. ## Create a PaymentIntent ### Server-side A [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) is an object that represents your intent to collect payment from a customer and tracks the lifecycle of the payment process through each stage. You can manage payment methods in 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. Create a PaymentIntent on your server with an amount and currency. Before creating the PaymentIntent, make sure to turn **Pay with Crypto** on in the [payment methods settings](https://dashboard.stripe.com/settings/payment_methods) page. Always decide how much to charge on the server-side, a trusted environment, as opposed to the client. This prevents customers from being able to choose their own prices. If you don’t want to use the Dashboard or you want to manually specify payment methods, you can list them using the `payment_method_types` attribute. Create a PaymentIntent on your server with an amount, currency, and a list of payment methods. Always decide how much to charge on the server-side, a trusted environment, as opposed to the client. This prevents customers from being able to choose their own prices. ```dotnet StripeConfiguration.ApiKey = "<>"; var options = new PaymentIntentCreateOptions { Amount = 1099, Currency = "usd", PaymentMethodTypes = new List { "crypto" }, }; var service = new PaymentIntentService(); PaymentIntent paymentIntent = service.Create(options); ``` ```go stripe.Key = "<>" params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1099), Currency: stripe.String(string(stripe.CurrencyUSD)), PaymentMethodTypes: []*string{stripe.String("crypto")}, }; result, err := paymentintent.New(params); ``` ```java Stripe.apiKey = "<>"; PaymentIntentCreateParams params = PaymentIntentCreateParams.builder() .setAmount(1099L) .setCurrency("usd") .addPaymentMethodType("crypto") .build(); PaymentIntent paymentIntent = PaymentIntent.create(params); ``` ```node const stripe = require('stripe')('<>'); const paymentIntent = await stripe.paymentIntents.create({ amount: 1099, currency: 'usd', payment_method_types: ['crypto'], }); ``` ```python import stripe stripe.api_key = "<>" payment_intent = stripe.PaymentIntent.create( amount=1099, currency="usd", payment_method_types=["crypto"], ) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $paymentIntent = $stripe->paymentIntents->create([ 'amount' => 1099, 'currency' => 'usd', 'payment_method_types' => ['crypto'], ]); ``` ```ruby Stripe.api_key = '<>' payment_intent = Stripe::PaymentIntent.create({ amount: 1099, currency: 'usd', payment_method_types: ['crypto'], }) ``` ### Client-side On the client, request a PaymentIntent from your server and store its *client secret*. ```kotlin class CheckoutActivity : AppCompatActivity() { private lateinit var paymentIntentClientSecret: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... startCheckout() } private fun startCheckout() { // Request a PaymentIntent from your server and store its client secret in paymentIntentClientSecret // Click View full sample to see a complete implementation } } ``` ```java public class CheckoutActivity extends AppCompatActivity { private String paymentIntentClientSecret; @Override public void onCreate(Bundle savedInstanceState) { // ... startCheckout(); } private void startCheckout() { // Request a PaymentIntent from your server and store its client secret in paymentIntentClientSecret // Click View full sample to see a complete implementation } } ``` ## Submit the payment to Stripe When a customer taps to pay with Pay with Crypto, confirm the `PaymentIntent` to complete the payment. Configure a `ConfirmPaymentIntentParams` object with the `PaymentIntent` [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret). The client secret is different from your API keys that authenticate Stripe API requests. Handle it carefully because it can complete the charge. Don’t log it, embed it in URLs, or expose it to anyone but the customer. ### Confirm Pay with Crypto payment Complete the payment by calling [PaymentLauncher confirm](https://stripe.dev/stripe-android/payments-core/com.stripe.android.payments.paymentlauncher/-payment-launcher/confirm.html). This redirects the customer to _https://crypto.link.com/pay_, where they can complete the payment with Pay with Crypto. After completion, Stripe calls the `PaymentResultCallback` you set with the result of the payment. ```kotlin class CheckoutActivity : AppCompatActivity() { // ... private val paymentLauncher: PaymentLauncher by lazy { val paymentConfiguration = PaymentConfiguration.getInstance(applicationContext) PaymentLauncher.create( activity = this, publishableKey = paymentConfiguration.publishableKey, stripeAccountId = paymentConfiguration.stripeAccountId, callback = ::onPaymentResult, ) } // … private fun startCheckout() { // ... val cryptoParams = PaymentMethodCreateParams.createCrypto() val confirmParams = ConfirmPaymentIntentParams .createWithPaymentMethodCreateParams( paymentMethodCreateParams = cryptoParams, clientSecret = paymentIntentClientSecret, ) paymentLauncher.confirm(confirmParams) } private fun onPaymentResult(paymentResult: PaymentResult) { // Handle the payment result… } } ``` ```java public class CheckoutActivity extends AppCompatActivity { // ... private PaymentLauncher paymentLauncher; @Override public void onCreate(@Nullable Bundle savedInstanceState) { // ... final PaymentConfiguration paymentConfiguration = PaymentConfiguration.getInstance(context); paymentLauncher = PaymentLauncher.create( this, paymentConfiguration.getPublishableKey(), paymentConfiguration.getStripeAccountId(), this::onPaymentResult ); } private void startCheckout() { // ... PaymentMethodCreateParams cryptoParams = PaymentMethodCreateParams.createCrypto(); ConfirmPaymentIntentParams createParams = ConfirmPaymentIntentParams .createWithPaymentMethodCreateParams( cryptoParams, paymentIntentClientSecret ); paymentLauncher.confirm(confirmParams); } // ... private void onPaymentResult(PaymentResult paymentResult) { // Handle the payment result… } } ``` ## Handle post-payment events Stripe sends a [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-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, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events also helps you accept more payment methods in the future. Learn about the [differences between all supported payment methods](https://stripe.com/payments/payment-methods-guide). ### Manually Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments. * [View your test payments in the Dashboard](https://dashboard.stripe.com/test/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. * [Build a custom webhook](https://docs.stripe.com/payments/handling-payment-events.md#build-your-own-webhook) ### Prebuilt apps Handle common business events, like [automation](https://stripe.partners/?f_category=automation) or [marketing and sales](https://stripe.partners/?f_category=marketing-and-sales), by integrating a partner application. ### Test your integration Test your Pay with Crypto integration with your test API keys by viewing the redirect page. You can test the successful payment case by authenticating the payment on the redirect page. The [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) transitions from `requires_action` to `succeeded`. 1. In *sandbox*, pay with testnet crypto assets on the payment page you’re redirected to. 1. Configure your wallet to the test network you intend to pay over. For example, if you want to pay with USDC on Ethereum, make sure your wallet is set to Ethereum’s Sepolia test network. You can use testnet “faucets” to top up your wallet. Here are a few: - [Circle USDC](https://faucet.circle.com/) - [Paxos USDP](https://faucet.paxos.com/) - [Devnet SOL](https://faucet.solana.com/) - [Sepolia ETH](https://faucets.chain.link/sepolia) - [Amoy POL](https://faucet.polygon.technology/)