Hi there,
There's always going to be a payment form involved where the customer enters their card or other payment details securely into a Stripe-hosted or -provided component.
In the integration guide I linked, while it doesn't explicitly do this in that specific way, there's the ability to have two pages, the first page where a form is presented that collects the customer's details(in a PCI-compliant manner that does not involve your own code touching the raw card details of course!) and a second page that allows for details to be reviewed. It's certainly possible to build this in such a way that when you create the ConfirmationToken(in the first page), you then POST a form to your backend with the ID of the ConfirmationToken; and then your backend PHP can run logic to retrieve details of the token and your cart and render the next, 'review' page.
The existing guide does things as more of a single-page-application where after the payment form is completed the details/review is rendered in the same page with an AJAX/fetch/XHR request, but you can divide this into two pages. For example you can submit the ConfirmationToken as hidden field in a form action to the PHP script (exactly the same way the code you presented in your initial message does), that then runs the logic and renders the review page. Here's some pointers to get you started:
Adapting Step 4 from the guide:
form.addEventListener('submit', async (event) => {
// ... (re-use existing code in the guide)
// ...
const {error, confirmationToken} = await stripe.createConfirmationToken({
elements,
params: {
payment_method_data: {
billing_details: {
name: 'Jenny Rosen',
}
}
}
});
// ... (re-use existing code in the guide)
// Now that you have a ConfirmationToken, you can use it in the following steps to render a confirmation page or run additional validations on the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', confirmationToken.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
In the backend PHP script that is your <form> action:
$confirmationTokenId = $_POST['stripeToken'];
$confirmationToken = $stripe->confirmationTokens->retrieve($confirmationTokenId, []);
if($confirmationToken->payment_method_preview->type === 'card') {
$card_brand = $confirmationToken->payment_method_preview->card->brand;
$card_last4 = $confirmationToken->payment_method_preview->card->last4;
// etc — you can use get other details and then render these variables into the 'review' page
// along with your own cart info.
// ...
}
> 2ndly, nothing about php at all in the url sent
Most of our docs have PHP samples for all backend code, but for some reason this specific guide doesn't have a PHP example for step 5 unfortunately, I'll report it internally.
> I am not trying to run a payment, in trying to create a new customer profile and then attach the card to it
This exact same flow works for saving a card, with only small changes:
- you'd pass `mode:"setup"` instead of `mode:"payment"` when initialising Elements in step 3
I think overall if you build this flow(even it just initially to accept a one-time payment as a learning exercise) it will become clearer how this can be integrated into your flows and how the different parts fit together, and then how straightforward it is to then adapt to a SetupIntent-based flow for saving a card instead of charging it immediately.
> and that would help install some confidence.
> So we were so far off, it's almost dishearteni
I would ask you to please show a bit more respect as I am trying to help you, developer-to-developer.
If you're facing difficulty building this integration you can definitely open a support ticket at
https://support.stripe.com/?contact=true or reply to any existing support tickets you have open, with the code you're working on, and we can help and offer advice!
All the best,
Kyle