【问题标题】:Stripe.js and hcaptcha where hcaptcha is tied to buttonStripe.js 和 hcaptcha,其中 hcaptcha 绑定到按钮
【发布时间】:2021-05-10 18:33:00
【问题描述】:

代码:

<!DOCTYPE html>

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>

  

<form id="payment-form" action="." method="post">
    <input type="hidden" name="csrfmiddlewaretoken" value="06dAlJhwvSjVK7u4CZcyAbsa9Ikn9EYsiFGxFpA8z3W2wsr0UMKb8KIxNmYbyFYg">
    <p><label for="email">Email:</label> <input type="email" name="payment_email" value="paus@prositeportal.ru" class="form-control" autocomplete="off" id="email" readonly="readonly" required></p>
<p><label for="phone">International Phone:</label> <input type="tel" name="payment_phone" class="form-control" autocomplete="off" id="phone" placeholder="International Phone" required></p>
<p><label for="cardholder-name">Full Name:</label> <input type="text" name="payment_name" class="form-control" autocomplete="off" id="cardholder-name" placeholder="Full Name" required></p>
<p><label for="line1">Address Line 1:</label> <input type="text" name="payment_address1" class="form-control" autocomplete="off" id="line1" placeholder="Address 1" required></p>
<p><label for="line2">Address Line 2:</label> <input type="text" name="payment_address2" class="form-control" autocomplete="off" id="line2" placeholder="Address 2"></p>
<p><label for="city">City:</label> <input type="text" name="payment_city" class="form-control" autocomplete="off" id="city" placeholder="City" required></p>
<p><label for="state">State or Province:</label> <input type="text" name="payment_state" class="form-control" autocomplete="off" id="state" placeholder="State or Province" required></p>
<p><label for="country">2 Letter Country Code (<a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements" target="_blank" rel="noopener noreferrer nofollow">Find Your Country Code</a>):</label> <input type="text" name="payment_country" class="form-control" autocomplete="off" id="country" maxlength="2" placeholder="Country Code" required></p>


      <script nonce="tKD42vLlpXoOTvs+kP4PUQ==" src="https://hcaptcha.com/1/api.js" async defer></script>

<script nonce="tKD42vLlpXoOTvs+kP4PUQ==">
  function onSubmit(token) {
      if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
      }
        var form = document.getElementById("payment-form");
        document.getElementById("card-button").disabled = true;
        form.submit();
        if (event.error) {
            document.getElementById("card-button").disabled = false;
        }
  }
</script>



            <label>
              Credit or Debit Card:
            </label>
            <div id="card-element" class="form-control stripe_card_padding">
            <!-- A Stripe Element will be inserted here. -->


        </div>
        <!-- Used to display form errors. -->
        <div id="card-errors" class="stripe_card_errors" role="alert" ></div>



        <!-- <div id="stripe-result-handler" class="is-hidden">
          Success! Got token: <span class="result"></span>
        </div> -->


        <button
          id="card-button"
          type="submit"
          class=" form-control payment_button h-captcha"
          data-sitekey="8b425911-fa93-429c-a98c-4c56b93b6662"
          data-callback="onSubmit"
        >
          Submit Payment
        </button>

      </form>



  <script nonce="tKD42vLlpXoOTvs+kP4PUQ==" src="https://js.stripe.com/v3/"></script>
  <script nonce="tKD42vLlpXoOTvs+kP4PUQ==">
  // Create a Stripe client.
    var stripe = Stripe("pk_test_tcuxCLB8Y8NN8H3OPcR6ALKh00UjP2WfYt");

    // Create an instance of Elements.
    var elements = stripe.elements();
    var cardButton = document.getElementById("card-button");
    var cardholderName = document.getElementById("cardholder-name");
//var cardElement = elements.create("card");
    //var cardElement = elements.create("card");
    //cardElement.mount("#card-element");
    var line1 = document.getElementById("line1");
    var line2 = document.getElementById("line2");
    var city = document.getElementById("city");
    var country = document.getElementById("country");

    var email = document.getElementById("email");
    var phone = document.getElementById("phone");
    var state = document.getElementById("state");


var style = {
  base: {
    color: 'black',
    iconColor: 'black',
    fontSize: '15px',
    fontFamily: '"Roboto", sans-serif',
    fontSmoothing: 'antialiased',
    '::placeholder': {
      color: 'black',
    },
  },
  invalid: {
    color: '',
    ':focus': {
      color: '',
    },
  },
};




var cardElement = elements.create('card', {style: style});
cardElement.mount('#card-element');



    // Add an instance of the card Element into the `card-element` <div>.
    // Handle real-time validation errors from the card Element.
    cardElement.addEventListener("change", function (event) {
      var displayError = document.getElementById("card-errors");
      if (event.error) {
        displayError.textContent = event.error.message;
      } else {
        displayError.textContent = "";
      }
    });
    // Handle form submission.
    //.value.trim() || null is needed to change the form input to required/optional for data collection. Was originally .value only.
    var form = document.getElementById("payment-form");
    form.addEventListener("submit", function (event) {
      event.preventDefault();
      document.getElementById("card-button").disabled = true;
      var billingInfo = {
      billing_details: {
        name: cardholderName.value.trim() || null,
        address: {
          line1: line1.value.trim() || null,
          line2: line2.value.trim() || null,
          city: city.value.trim() || null,
          state: state.value.trim() || null,
          country: country.value.trim() || null,
        },
        email: email.value,
        phone: phone.value.trim() || null,
      }
    };
      stripe.createPaymentMethod('card', cardElement, billingInfo).then(function (result) {
        if (result.error) {
          // Inform the user if there was an error.
          var errorElement = document.getElementById("card-errors");
          errorElement.textContent = result.error.message;
          document.getElementById("card-button").disabled = false;
        } else {
          // Send the token to your server.
          //setTimeout(stripeSourceHandler(result.paymentMethod.id), 3000);
          stripeSourceHandler(result.paymentMethod.id);
        }
      });
    });


    // Submit the form with the source ID.
    function stripeSourceHandler(payment_method_id) {
      var form = document.getElementById("payment-form");
      var hiddenInput = document.createElement("input");
      hiddenInput.setAttribute("type", "hidden");
      hiddenInput.setAttribute("name", "PaymentMethod");
      hiddenInput.setAttribute("value", payment_method_id);
      form.appendChild(hiddenInput);
      // Insert the source ID into the form so it gets submitted to the server
      // Submit the form
      form.submit();
    }


  </script>

https://jsfiddle.net/g5nkcL1u/

我正在尝试使用 hcaptcha 来做到这一点:

https://docs.hcaptcha.com/invisible#automatically-bind-the-challenge-to-a-button

我正在尝试将它与 stripe.js 结合起来。

我认为问题与按钮的数据回调有关。由于有 2 个单独的 form.submit();我的代码中的行,它不知道要运行哪一个。

我的问题是,如何将我的条带 javascript 与我的 hcaptcha javascript 结合起来让它们一起工作?

错误:

'No such PaymentMethod' -> 如果我使用 data-callback="stripeSourceHandler"

'无法识别的请求 URL (POST: /v1/payment_methods//attach)' -> 如果我使用 data-callback="onSubmit"

我认为这与我的服务器代码无关。如果我删除客户端上的所有 hcaptcha 代码,服务器端一切正常。如果我使用常规的 hcaptcha 复选框小部件而不是绑定到按钮,则一切正常,因为没有数据回调。但我想将 hcaptcha 绑定到一个按钮,因为与复选框小部件相比,它具有更好的用户体验。

我在我的其他表单网页中使用了 onSubmit 功能,并且 hcaptcha 工作正常,因为条纹不涉及其他表单网页。

其他想法:

onSubmit 不会调用创建 Stripe PaymentMethod 的代码部分。让创建发生在它自己的函数中,比如 callStripe(),然后在验证码部分之后调用 PaymentMethod 创建函数。

调用 hcaptcha.render() 显示验证码,然后创建 PaymentMethod 并提交表单

【问题讨论】:

    标签: javascript button stripe-payments captcha hcaptcha


    【解决方案1】:

    实际上是什么触发了验证码流? onSubmit 似乎没有任何明确的联系。否则,您应该能够将 3 个块的序列链接在一​​起:

    1. 允许 hcaptcha 绑定并调用onSubmit(或其他一些 函数),删除form.submit()调用
    2. 拆分表单事件 处理程序回调到一个独立的函数,并在之后调用它 验证码
    3. stripeSourceHandler 应该已经被称为 回调

    请注意,您还需要确保在服务器端验证 hcaptca 结果。

    另外,你没有递归的问题吗?您的表单提交侦听器 (form.addEventListener("submit", ...)) 最终会调用 stripeSourceHandler,而后者本身会调用 form.submit()

    【讨论】:

    • 点击提交按钮会触发验证码出现。请参阅上面的 hcaptcha 文档链接。 onSubmit 函数是我用来在我的网站上提交其他没有 stripe.js 的表单的函数。 onSubmit 将在 hcaptcha 解决后提交表单。我正在验证 hcaptcha 服务器端。你能通过代码向我展示你的建议吗?是的,所有提交似乎都存在某种类型的问题。但我需要 stripeSourceHandler 因为如果我删除 hcaptcha 行,它会导致一切正常。基本上每个代码都可以独立运行,但我需要将它们组合在一起。
    • 你基本上在最后重复了你原来的问题。您是否尝试按照我的建议将呼叫链接在一起?成功了吗?
    • 抱歉重复。我能回答你的问题吗?我不确定如何将它们链接在一起并按照您的建议执行 #2。你能告诉我吗?
    • 在 2/ 中,我的意思是在 form.addEventListener 的回调中取 function (event) {...} 并将其命名为 function doStripeStuff() { ... } ,然后在 onSubmit 中调用 doStripeStuff() (并删除对form.submit())。
    • 我通过这样做取得了一些进展。但是,如果 hcaptcha 无效,如何阻止表单在 javascript 中提交?如果 hcaptcha 有效并且表单在提交时有效,我还想禁用该按钮。如果有任何错误,请启用该按钮,以便用户重试。我没有尝试你所说的,因为我不确定该怎么做。 jsfiddle.net/0eLr8yx2
    猜你喜欢
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 2021-10-22
    • 2022-08-16
    • 2021-07-22
    • 1970-01-01
    相关资源
    最近更新 更多