craft-unit / craft-stripe-express-checkout
Adding the Stripe Express Checkout to Commerce-Stripe.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 3
Type:craft-plugin
Requires
- php: >=8.2
- craftcms/cms: ^5.0.0
- craftcms/commerce: ^5.0.0
- craftcms/commerce-stripe: ^5.0.0
Requires (Dev)
- codeception/codeception: ^5.1
- codeception/module-asserts: *
- codeception/module-phpbrowser: *
- codeception/module-yii2: ^1.1
- craftcms/ecs: dev-main
- craftcms/phpstan: dev-main
- vlucas/phpdotenv: ^5.6
This package is auto-updated.
Last update: 2025-09-29 08:47:24 UTC
README
Adding the Stripe Express Checkout Element to Commerce-Stripe.
Table of Contents
Features
- Adds the Stripe Express Checkout Element to your Craft Commerce site.
- Checkout products and carts with a single click.
- Supports Apple Pay, Google Pay, PayPal and much more.
- Supports shipping address and phone number requirements.
- Supports all the options from the Stripe Express Checkout Element.
- Intercept request through event hooks.
- Automatically adjusts costs based on configured shipping rules.
- Restrict deliveries to allowed countries in your Commerce settings.
Showcase
TODO: Add gif/webm of the express checkout; Maybe a YouTube Video showcasing the plugin would be neat
Requirements
Installation
You can install this plugin from the Plugin Store or with Composer.
From the Plugin Store
e Go to the Plugin Store in your project’s Control Panel and search for “Stripe Express Checkout”. Then press “Install”.
With Composer
Open your terminal and run the following commands:
# go to the project directory cd /path/to/my-project.test # tell Composer to load the plugin composer require craft-unit/craft-stripe-express-checkout # tell Craft to install the plugin ./craft plugin/install stripe-express-checkout
Setup
- Create a Stripe Account or use an existing one.
- Install Craft Commerce and the Stripe Gateway Plugin.
- Follow the setup instruction for the Stripe Gateway Plugin.
- Go to the plugin settings in the sidebar and select the gateway you just created.
- Render the buttons on your products and cart page.
- Be sure to handle the order complete event. You can use the
fetch
API to ask for the order and return it to the success page. See the Order complete section for more information.
Products page
products/_product.twig
{{ craft.expressCheckout.buttons({ itemsId: product.defaultVariant.id }) | raw }} {# or... #} {{ craft.expressCheckout.buttons({ items: [{ id: product.defaultVariant.id, qty: 1, }], }) | raw }}
Cart page
cart.twig
{{ craft.expressCheckout.buttons({ cart: craft.commerce.carts.cart, }) | raw }}
Order complete
After the order is completed, the user will be redirected to the success_url
you set in the options. At this point in
time your order might not be completed in Craft Commerce hence why you won't see the completed order. You can
use fetch
to
ask for the order and return it to the success page. Use the number
query parameter to get the order number.
// Get the order number from the query parameter const orderNumber = new URLSearchParams(window.location.search).get('number'); const order = await fetch(`/actions/commerce/stripe-express-checkout/get-order?number=${orderNumber}`);
Configuration
Configuration can be done globally in the plugin settings or locally by passing settings to
the craft.expressCheckout.buttons
function. Passing the settings to the function will override the global settings.
You can find all the options in the Stripe documentation.
Setting Name | Description |
---|---|
items |
List of item object with and id and qty . |
itemId |
ID of the variant to sell. |
gatewayId |
Select the gateway through which payments will be processed. |
shippingAddressRequired |
Checking this will prompt the user for their shipping address. |
phoneNumberRequired |
Checking this box will prompt the user for their phone number. |
restrictCountries |
Checking this will restrict the Stripe 'allowedCountries' to your country list in Commerce -> Store Settings -> Store -> Country List. |
successUrl |
The URL that Stripe redirects to after a successful transaction. The 'successUrl' gets a query parameter called 'number' that contains the order number. |
loaderTemplate |
The path to the loader template. |
buttonHeight |
The height of the buttons. |
applePayTheme |
The theme of the Apple Pay button. |
googlePayTheme |
The theme of the GooglePay button. |
paypalTheme |
The theme of the PayPal button. |
applePayType |
The type of the Apple Pay button. |
googlePayType |
The type of the GooglePay button. |
paypalType |
The type of the PayPal button. |
maxColumns |
The maximum number of columns. |
maxRows |
The maximum number of rows. |
overflow |
Choose how the overflow should be handled. |
paymentMethodOrder |
The order of the payment methods. |
showApplePay |
Show the Apple Pay button. |
showGooglePay |
Show the GooglePay button. |
phoneField |
Map the phone number to plain text on the order field layout. This will only take effect if you enable 'Phone Number Required'. |
Global Settings
Local settings
{% set settings = { name: product.slug ~ '-express-checkout', shippingAddressRequired: true, phoneNumberRequired: false, paymentMethodOrder: ['paypal', 'googlePay', 'link'], buttonTheme: { paypal: 'blue', }, buttonHeight: 55, buttonType: { paypal: 'pay', googlePay: 'order', }, wallets: { applePay: 'always', googlePay: 'always', } {# and more... #} } %}
Extending and Customizing
Event Hooks
Class | Event |
---|---|
StripeController | EVENT_BEFORE_UPDATE_SHIPPING_RATE |
StripeController | EVENT_AFTER_UPDATE_SHIPPING_RATE |
StripeController | EVENT_UPDATE_SHIPPING_ADDRESS_ORDER_BEFORE_SAVE |
StripeController | EVENT_UPDATE_SHIPPING_ADDRESS_ORDER_AFTER_SAVE |
ProcessStripeWebhook | EVENT_MODIFY_ORDER_DETAILS |
ProcessStripeWebhook | EVENT_BEFORE_SAVE_SHIPPING_ADDRESS |
ProcessStripeWebhook | EVENT_AFTER_SAVE_SHIPPING_ADDRESS |
ProcessStripeWebhook | EVENT_BEFORE_SAVE_BILLING_ADDRESS |
ProcessStripeWebhook | EVENT_AFTER_SAVE_BILLING_ADDRESS |
ProcessStripeWebhook | EVENT_BEFORE_SET_ORDER_CUSTOMER |
ProcessStripeWebhook | EVENT_WEBHOOK_FAILED |
ProcessStripeWebhook | EVENT_RECEIVED_WEBHOOK |
ProcessStripeWebhook | EVENT_BEFORE_UPDATE_ORDER_WITH_ORDER_DETAILS |
Frontend JS
Each button uses the StripeExpressCheckout
class. This class is responsible for creating the Stripe Element and
handling the payment intent.
The instance gets added to the window.stripeExpressCheckouts
object. You can give your express checkout buttons a
custom name by passing the name
option to the craft.expressCheckout.buttons
function.
You can then access the instance by calling window.stripeExpressCheckouts['your-custom-name']
or StripeExpressCheckout.getByName('your-custom-name')
.
Take a look at
the StripeExpressCheckout
class to see all the available events and methods.
Events
Event | Description |
---|---|
stripe-express-checkout:init | Called after instance was created and added to window object |
stripe-express-checkout:success | Called after successful onConfirm |
stripe-express-checkout:error | Called after failure in onConfirm |
All Events get dispatched on the window object. You can listen to them by adding an event listener to the window object.
window.addEventListener('stripe-express-checkout:init', event => { const {name, instance} = event.detail; console.log(name, instance); });
Public Methods
Method Name | Parameters | Description |
---|---|---|
setItemQty |
id: number, qty: number | Set the quantity of an item. |
Example
Below is a example showing how to manipulate the quantity of a product in the cart using the setItemQty
method.
<div class="quantity"> <input type="number" name="qty" value="1" min="1"> </div> {% set params = requiredParams | merge(optionalParams) %} {{ craft.expressCheckout.buttons({ name: 'foo', items: [{ id: variant.id, qty: 1, }] }) | raw }} <script> // Wait for the express checkout to initialize window.addEventListener('stripe-express-checkout:init', event => { // Get the instance by name const {name, instance} = event.detail; if (name !== 'product-express-checkout') return; const quantityInput = document.querySelector('.quantity input'); quantityInput.addEventListener('input', event => { const qty = parseInt(event.target.value, 10); // Set the quantity of the item instance.setItemQty({{ variant.id }}, qty); }); }); </script>