Issue
As my user fills out the form with order info and customer details, I have the submit button disabled until my validations are satisfied. The library I'm using is express-validate.
What I want to do also, is keep the button disabled, first until the user inputs the credit card info into the Stripe element and it is in fact a valid card. Secondly, upon submit, disable the button again so the user can't keep clicking the button. When the success or success or error notification comes back I'll redirect.
As of now I am not successful in getting the cardElement.on() method to trigger, Stripe events. And this was the example of what I am trying to achieve,see client.js
This is what I have so far...
Home.vue
<form
id="order-info"
class="form-container"
@submit.prevent="createOrder"
>
...
<div class="stripe-container">
<div id="stripe-element-card" ref="card">
<!-- Stripe.js injects the Card Element -->
</div>
</div>
<p id="card-error" role="alert" />
<p class="result-message hidden">
Payment succeeded
</p>
<button
v-if="toggleUserInfo"
id="submit"
class="stripe"
:disabled="$v.$invalid" // this is based on current form validations
type="submit"
// I want to disable also until card is valid and then disable again
// after user clicks to prevent additional clicking until success/error returns
>
<div
id="spinner"
class="spinner"
:class="{ hidden: !isLoading }"
></div>
<span id="button-text" :class="{ hidden: isLoading }">Pay now</span>
<script>
async mounted() {
stripe = await loadStripe(process.env.VUE_APP_STRIPE_PK);
elements = stripe.elements();
card = elements.create("card", { style: style });
card.mount("#stripe-element-card");
},
...
createOrder method
async createOrder(event) {
console.log(event.target);
this.loading(true);
this.$v.$touch();
if (!this.$v.$invalid) {
// gather order and user details, superfluous code
const cardElement = elements.getElement("card");
const billingDetails = {
name: user.name,
address: {
city: user.city,
line1: user.street,
state: "NY"
},
phone: user.phone
};
try {
cardElement.on("change", event => {
console.log("LOGGING THE CARD ELEMENT EVENT", event);
// NOT SEEING ANYTHING HERE
// disable button until valid card is inputted
});
...
EDIT
When implementing Pompey's answer below, the listener in mounted(), this is what the console.logs look like until the credit card input is complete...
Solution
One important thing to note is that your change handler that wants to enable the button that triggers createOrder is located in the createOrder method itself. I would move the handler code to just after the card element is mounted in Home.vue:
card.mount("#stripe-element-card");
cardElement.on("change", event => {
console.log("LOGGING THE CARD ELEMENT EVENT", event);
if (event.complete) {
// enable payment button
} else if (event.error) {
// show event.error.message to customer
}
});
And as you can see from my snippet above, the event parameter has a complete property that is set to true when the card element’s value is “well-formed and potentially complete”[1] so when it is true you can enable your button. It can also be worth checking the event.error in your change handler and if one is present, showing the user the event.error.message.
Similarly, to redirect the customer or re-enable the button based on the payment’s success, you can use the then method to get the response from confirmCardPayment indicating success or failure[2]:
stripe.confirmCardPayment('{PAYMENT_INTENT_CLIENT_SECRET}', {
...
})
.then(function(result) {
if(result.error)
{
// Display result.error.message and re-enable button to alllow for more attempts
}
else
{
// React to successful payment
}
});
[2]https://stripe.com/docs/js/payment_intents/confirm_card_payment
Answered By - Pompey

0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.