如何监听Stripe cardElement 的输入事件,判断卡片是不是无效并禁用按钮?

Posted

技术标签:

【中文标题】如何监听Stripe cardElement 的输入事件,判断卡片是不是无效并禁用按钮?【英文标题】:How to listen to the input event of the Stripe cardElement to determine if card is invalid and disable the button?如何监听Stripe cardElement 的输入事件,判断卡片是否无效并禁用按钮? 【发布时间】:2021-11-19 16:42:47 【问题描述】:

当我的用户使用订单信息和客户详细信息填写表单时,我禁用了提交按钮,直到我的验证得到满足。我使用的库是 express-validate。

我想要做的,是保持按钮禁用,首先,直到用户将信用卡信息输入到 Stripe 元素它实际上是一张有效的卡。 其次,在提交后,再次禁用该按钮,这样用户就无法继续点击该按钮。当成功或成功或错误通知返回时,我将重定向。

到目前为止,我还没有成功触发 cardElement.on() 方法,Stripe events。这就是我想要实现的目标,see client.js

这就是我目前所拥有的......

首页.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 方法

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
      );
      ...

编辑

在下面实现庞培的回答时,mounted() 中的监听器,这是 console.logs 的样子,直到信用卡输入完成...

【问题讨论】:

【参考方案1】:

需要注意的重要一点是,要启用触发createOrder 的按钮的change 处理程序位于createOrder 方法本身中。我会将处理程序代码移动到卡片元素安装在 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
  
);

从我上面的 sn-p 可以看出,event 参数有一个 complete 属性,当卡片元素的值为“格式良好且可能完整”时,该属性设置为 true[1]所以当它是真的你可以启用你的按钮。检查change 处理程序中的event.error 也是值得的,如果存在,则向用户显示event.error.message

同理,根据支付成功重定向客户或重新启用按钮,您可以使用then方法获取来自confirmCardPayment的响应,指示成功或失败[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
    
  );

[1]https://stripe.com/docs/js/element/events/on_change?type=cardElement#element_on_change-handler-complete

[2]https://stripe.com/docs/js/payment_intents/confirm_card_payment

【讨论】:

太棒了! Mounted() 实际上是监听 event.complete 属性的地方。我剩下的唯一问题是为什么在最初安装 DOM 节点按钮时必须附加侦听器?是不是因为在加载文档之前所有的监听器都需要在 window 对象上注册。

以上是关于如何监听Stripe cardElement 的输入事件,判断卡片是不是无效并禁用按钮?的主要内容,如果未能解决你的问题,请参考以下文章