如何监听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 的输入事件,判断卡片是不是无效并禁用按钮?的主要内容,如果未能解决你的问题,请参考以下文章

我可以在不使用 Stripe Card Element 的情况下使用 Stripe api

如何创建带有发票的 Stripe 订单?

Stripe 取消 url 不会取消付款,因此 Stripe 不会发送取消付款意图

如何在 IOS 中使用 STRIPE API 创建 STRIPE 客户?

如何在 React 测试中加载 Stripe?

如何识别 Stripe webhooks 类型?