OK so here's how to go about it.
- On checkout, you'll need at minimum a form with the following elements:
<form method="post" id="card-info">
<input type="hidden" name="action" value="commerce/payments/pay">
<input type="hidden" name="paymentMethodId" value="[fill this via JS]">
<input type="hidden" name="orderEmail" value="[your customer email address]">
<input type="hidden" name="gatewayId" value="[your chosen gateway id - add js to have the user select one if you have multiple gateaways available]">
{{ redirectInput('/order?number='~cart.number) }}
{{ csrfInput() }}
<input name="firstName" type="text" placeholder="First Name">
<input name="lastName" type="text" placeholder="Last Name">
<div id="card-data" class="border border-grey-lighter rounded bg-grey-lighter text-grey-darker p-3"></div>
<button type="submit">Complete Purchase</button>
</form>
The real magic happens, of course, via JS.
First, include the stripe library:
<script src="https://js.stripe.com/v3/"></script>
Add this to your main JS file to display the stripe credit card input:
let stripe = Stripe(`your public sharing key`),
elements = stripe.elements(),
card = undefined;
let style = {
base: {
// Add your base input styles here. For example:
fontSize: '16px',
color: '#32325d',
// Attn: The number of usable styles is very limited. Refer to https://stripe.com/docs/stripe-js/reference#the-elements-object
}
}
card = elements.create('card', {style: style});
card.addEventListener('change', updateErrorMessage);
card.mount(document.querySelector('card-data'));
function updateErrorMessage (event) {
if (event.error) {
// Do something with event.error.message
}
}
Finally, you'll need to add code to make a request to the stripe API before the form is submitted, and fill in the value for the paymentMethodId hidden input. Refer to lines 66 to 94 here to get an idea how it's done: https://github.com/craftcms/commerce-stripe/blob/develop/src/web/assets/intentsform/js/paymentForm.js#L66
In addition, before you submit, make sure the cart has a valid value for "email". If you do a one page checkout like me, you may have to do an ajax post to /actions/commerce/cart/update-cart in order to save it first.
I implemented all of this in vuejs, so the above is untested simplified code. On request I can share my vuejs version but I thought to better keep it framework agnostic in this answer.