Stripe.js 和 hcaptcha,其中 hcaptcha 绑定到按钮

如何解决Stripe.js 和 hcaptcha,其中 hcaptcha 绑定到按钮

代码:

<!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 工作正常,因为其他表单网页中不涉及 Stripe。

其他想法:

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

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

解决方法

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

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-