Web端Stripe令牌创建正常,WebView偶现格式匹配错误求助
Stripe WebView环境下偶发"The string did not match the expected pattern"错误问题
问题描述
通过Stripe JS创建支付令牌后,将令牌关联到Connect账户的流程在Web端完全正常,但在**移动端WebView(非移动端浏览器响应式页面)**中操作时,偶尔会返回错误:The string did not match the expected pattern。
前端代码实现
var stripe = Stripe('pk_test_51ObgQ7AapkrJHjBL5v8QlnwtO6ARkY0cjR1PQHdol7DHzvwMnfHp7yJo44O1uMoAu17hotn4NOaI6FITTVH84auC00Cq4IfMCd'); var elements = stripe.elements(); var card = elements.create('card', { style: { base: { iconColor: '#666EE8', lineHeight: '40px', fontFamily: '-apple-system, BlinkMacSystemFont, sans-serif', fontSize: '15px', '::placeholder': { color: '#CFD7E0', }, }, } }); card.mount('#card-element'); function setOutcome(result) { var successElement = document.querySelector('.success'); var errorElement = document.querySelector('.error'); successElement.classList.remove('visible'); errorElement.classList.remove('visible'); if (result.token) { var token = result.token.id; fetch("/stripe/card/processing", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ token }), }).then((r) => { if (r.ok) { setLoading(false); var successElement = document.querySelector('.success'); successElement.textContent = "Success! Your Stripe card was successfully processed"; successElement.classList.add('visible'); } return r.json(); }).catch((error) => { setLoading(false); errorElement.textContent = error.message; errorElement.classList.add('visible'); }); } else if (result.error) { setLoading(false); errorElement.textContent = result.error.message; errorElement.classList.add('visible'); } } card.on('change', function (event) { setOutcome(event); }); document.querySelector('form').addEventListener('submit', async function (e) { setLoading(true); e.preventDefault(); var form = document.querySelector('form'); var extraDetails = { name: form.querySelector('input[name=cardholder-name]').value, currency: 'usd', }; stripe.createToken(card, extraDetails).then(setOutcome); }); function setLoading(isLoading) { if (isLoading) { document.querySelector("#submit").disabled = true; document.querySelector("#spinner").classList.remove("hidden"); document.querySelector("#button-text").classList.add("hidden"); } else { document.querySelector("#submit").disabled = false; document.querySelector("#spinner").classList.add("hidden"); document.querySelector("#button-text").classList.remove("hidden"); } }
后端处理函数截图

错误提示截图

问题排查与修复建议
可能的触发原因
- WebView输入自动格式化干扰:部分WebView会自动为卡号插入空格、连字符等分隔符,导致Stripe Elements获取的卡号格式不符合校验规则。
- Stripe JS与WebView内核兼容性:老旧WebView内核可能和当前Stripe JS版本存在适配问题,导致令牌生成异常。
- 令牌传递编码异常:WebView在发送JSON请求时,可能对令牌字符串做了错误编码,后端接收到的令牌格式不符合
tok_xxx的规范。 - WebView安全限制:WebView可能拦截了Stripe脚本加载或跨域请求,导致Elements初始化不完整,生成无效令牌。
针对性修复方案
- 清理输入内容:在获取持卡人姓名前,手动清理特殊字符,避免干扰Stripe校验:
document.querySelector('form').addEventListener('submit', async function (e) { setLoading(true); e.preventDefault(); var form = document.querySelector('form'); // 清理持卡人姓名中的特殊字符与多余空格 var cardholderName = form.querySelector('input[name=cardholder-name]').value.trim().replace(/[^\w\s]/g, ''); var extraDetails = { name: cardholderName, currency: 'usd', }; stripe.createToken(card, extraDetails).then(setOutcome); });
- 添加令牌格式校验:在发送请求前,先验证令牌格式是否符合Stripe规范:
if (result.token) { var token = result.token.id; // 校验令牌格式是否为Stripe标准格式 if (!/^tok_[a-zA-Z0-9]+$/.test(token)) { setLoading(false); errorElement.textContent = "无效的支付令牌"; errorElement.classList.add('visible'); return; } // 后续请求逻辑 }
- 升级Stripe JS版本:确保使用最新稳定版的Stripe脚本,提升兼容性:
<script src="https://js.stripe.com/v3/"></script>
- 调整WebView配置:
- 开启JavaScript执行权限
- 允许跨域资源共享(CORS)
- 禁用输入框自动格式化功能
- 将
js.stripe.com加入WebView的域名白名单
内容的提问来源于stack exchange,提问作者Hieu Dep Trai
相关产品推荐
相关产品推荐

