如何通过Ajax为Stripe Checkout设置有效的发布密钥?
问题原因分析
你猜的没错!Stripe的checkout.js脚本在加载完成的瞬间就会自动扫描页面中带有.stripe-button类的元素,读取data-key等属性来初始化付款按钮。而你的Ajax请求是异步执行的,这就导致脚本初始化按钮的时候,data-key还是空值——哪怕之后你用JS把data-key改成了正确的密钥,Stripe也不会重新初始化已经创建好的按钮,所以报错就不可避免了。
解决方案
这里有几种靠谱的解决方式,你可以根据自己的需求选择:
方案1:延迟加载checkout.js脚本
等Ajax获取到密钥后,再动态加载Stripe的checkout.js,这样脚本加载时data-key已经是正确值了:
<div id="button-stripe-vab"> <form action="stripeIPN.php" method="POST"> <script id="stripe-link" class="stripe-button" data-key="" data-amount="" data-name="" data-description="" data-image="image.png" data-locale="auto" data-label="Pay with card"> </script> </form> </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $.ajax({ type: "POST", url: "config.php", dataType:"json", success: function (result) { var pubkey = result; // 这里不需要重复JSON.parse,因为dataType已经指定为json $('#stripe-link').attr("data-key", pubkey); // 动态加载checkout.js脚本 var script = document.createElement('script'); script.src = 'https://checkout.stripe.com/checkout.js'; document.body.appendChild(script); } }); </script>
另外注意你的config.php有个关键问题:return $pubkey;在Web请求环境下不会输出任何内容,Ajax会拿到空响应,必须改成echo $pubkey;才能正确返回密钥!
方案2:手动初始化Stripe Checkout(更推荐)
放弃自动初始化的.stripe-button,改用纯JS手动创建按钮,完全控制初始化时机,还能自定义按钮样式:
<div id="button-stripe-vab"> <form action="stripeIPN.php" method="POST"> <input type="hidden" name="stripeToken" id="stripe-token"> <button id="custom-stripe-button" type="button">Pay with card</button> </form> </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://checkout.stripe.com/checkout.js"></script> <script> var stripeHandler; $.ajax({ type: "POST", url: "config.php", dataType:"json", success: function (result) { var pubkey = result; // 初始化Stripe Checkout handler stripeHandler = StripeCheckout.configure({ key: pubkey, image: 'image.png', locale: 'auto', token: function(token) { // 把token传入表单,然后提交 $('#stripe-token').val(token.id); $('#button-stripe-vab form').submit(); } }); // 绑定按钮点击事件 $('#custom-stripe-button').on('click', function(e) { stripeHandler.open({ name: '你的商家名称', description: '付款描述', amount: 100 // 注意是分单位,对应1欧元 }); e.preventDefault(); }); } }); // 页面关闭时清理handler,避免内存泄漏 window.addEventListener('popstate', function() { stripeHandler.close(); }); </script>
方案3:先隐藏容器,Ajax完成后动态渲染按钮
先把按钮容器隐藏,等获取到密钥后,再动态生成带有正确data-key的表单和脚本标签:
<div id="button-stripe-vab" style="display:none;"> </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $.ajax({ type: "POST", url: "config.php", dataType:"json", success: function (result) { var pubkey = result; // 动态生成完整的表单和Stripe按钮 var formHtml = ` <form action="stripeIPN.php" method="POST"> <script src="https://checkout.stripe.com/checkout.js" class="stripe-button" data-key="${pubkey}" data-amount="100" data-name="你的商家名称" data-description="付款描述" data-image="image.png" data-locale="auto" data-label="Pay with card"> </script> </form> `; $('#button-stripe-vab').html(formHtml).show(); } }); </script>
关键修复:config.php的输出问题
最后再强调一次,你的config.php必须把return $pubkey;改成echo $pubkey;,否则Ajax无法获取到密钥:
require_once "stripe-php-master/init.php"; $stripeDetails = array( "secretKey" => "sk_test_xxx", "publishableKey" => "pk_test_xxx" ); \Stripe\Stripe::setApiKey($stripeDetails['secretKey']); $pubkey = json_encode($stripeDetails['publishableKey']); echo $pubkey; // 替换原来的return
内容的提问来源于stack exchange,提问作者Borja
相关产品推荐
相关产品推荐

