create new customer file, and add default payment method by card question

62 views
Skip to first unread message

Chris S

unread,
Jul 15, 2024, 4:46:56 AM7/15/24
to Stripe API Discussion
So as it where, the code below works perfectly to place a charge on a visa card, no problems, easy peasy.  However, the javascript is collecting the card details from an html form element.  I want to place this javascript on a "review" info page, that I have built, where I've collected all customer and card details into session variables, and I need to be able to form that into a card element, get the token out for the card, and be able to submit the card details thru the stripe api so it sets up a new customer.  With the service we are doing, the monthly rate will vary from month to month so we're requiring our customers to maintain an active payment method.  I have searched and searched online but I can't seem to manage to find what I need to to get it done.  If anyone could help at least point me in the right direction, would be snazzy.

Regards,
Chris

<script src="https://js.stripe.com/v3/"></script>
<script>
var stripe = Stripe('pk_test_51OubJME2udGRKRWHAkRnz3pNZ0OYWpDqwpGCDR0j20uLBZ7bFpkSa5nbuVafOd5TJC84rtuQumPzdRjJCsOlkGVF00TzNptNHl');
var elements = stripe.elements();

var card = elements.create('card');
card.mount('#card-element');

// Handle form submission
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();

stripe.createToken(card).then(function(result) {
if (result.error) {
// Show error to user
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server
stripeTokenHandler(result.token);
}
});
});

function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);

// Submit the form
form.submit();
}
</script>

Karl Reid

unread,
Jul 15, 2024, 4:53:48 AM7/15/24
to Stripe API Discussion, chris....@gmail.com
Hi there,

For that use case we'd suggest using this integration which was specifically designed for that flow.

Overall you would
- mount a PaymentElement on one page, and when the user completes the form, create a ConfirmationToken object.
- on a 'review' page, you can render details from the ConfirmationToken and your own concept of a 'cart' or so on.
- when the user confirms the order, you can call the Confirm PaymentIntent API on your backend server, passing the ConfirmationToken, to process the payment


Note that the approach from those docs will involve using the PaymentElement and thus automatically support many different payment methods than just card payments (the code you're showing is for a much older and card-only way of using Stripe that I wouldn't really suggest for a brand new integration to use).

I hope this helps but please do not hesitate to get back to me if you need more details.
All the best,
Karl

Chris S

unread,
Jul 15, 2024, 6:36:09 AM7/15/24
to api-d...@lists.stripe.com
Nope, wasn't helpful at all, 1, that page still shows the data in a form, so that's doesn't help at all. 2ndly, nothing about php at all in the url sent. So how about we at least get the llcorrect language, and that would help install some confidence. 

To unsubscribe from this topic, visit https://groups.google.com/a/lists.stripe.com/d/topic/api-discuss/bWCjBaPOreA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to api-discuss...@lists.stripe.com.

Karl Reid

unread,
Jul 15, 2024, 7:22:17 AM7/15/24
to Stripe API Discussion, chris....@gmail.com
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
- you'd create and confirm a SetupIntent in step 7(so using stripe.confirmSetup instead of confirmPayment, creating a SetupIntent instead of a PaymentIntent, etc).

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 
Reply all
Reply to author
Forward
0 new messages