React集成Tyro支付网关时遇Tyro未定义问题求助
问题描述
我正尝试在React应用中集成Tyro支付网关,已经在public/index.html中添加了Tyro脚本标签,同时组件内也动态加载了该脚本,但运行应用时仍出现ESLint错误:
[Eslint] "Tyro is not defined (no-undef)"
目前已将paySecret设为固定字符串跳过API调用,需要按照文档步骤3的方式正确实例化Tyro()。
相关代码
public/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-app" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <title>React App</title> <script src="https://pay.connect.tyro.com/v1/tyro.js"></script> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> </body> </html>
TyroPayment组件代码
import React, { useEffect, useState } from 'react'; function TyroPayment() { const [tyroLibraryLoaded, setTyroLibraryLoaded] = useState(false); useEffect(() => { if (tyroLibraryLoaded === true) { init(); } }, [tyroLibraryLoaded]); useEffect(() => { const script = document.createElement('script'); script.src = 'https://pay.connect.tyro.com/v1/tyro.js'; script.corssOrigin = 'anonymous'; script.async = true; script.onload = () => setTyroLibraryLoaded(true); document.body.appendChild(script); }, []); let paySecret; // JavaScript sample code async function init() { const tyro = Tyro(); /* const response = await fetch('/create-order', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ apple: 55 }), }); paySecret = await response.json().paySecret; */ const paySecret = '$2a$10$KvfnNafAQguNViSHxLZsVuXv9ITJ56rCVFGIzDencnSB81TpvgAgm'; await tyro.init(paySecret); const payForm = tyro.createPayForm(); payForm.inject('#tyro-pay-form'); } return ( <div className='mainpage-container'> <form id='pay-form'> <div id='tyro-pay-form'></div> <button id='pay-form-submit'>Pay</button> </form> </div> ); } export default TyroPayment;
解决方案
1. 解决ESLint未定义错误
Tyro脚本加载后会挂载到全局window对象上,有两种方式处理这个错误:
- 方式一:直接从window调用
修改init函数中的实例化代码:const tyro = window.Tyro(); - 方式二:声明全局变量
在组件顶部添加注释,告诉ESLintTyro是合法全局变量:/* global Tyro */
2. 移除重复脚本加载
你同时在index.html和组件内加载了Tyro脚本,会导致重复请求,建议保留一种加载方式:
- 若保留
index.html的静态脚本,删除组件内动态加载的useEffect,改用判断window.Tyro是否存在来触发初始化:useEffect(() => { if (window.Tyro) init(); }, []); - 若保留动态加载,删除
index.html中的<script>标签,同时修正拼写错误:script.corssOrigin改为script.crossOrigin。
3. 修正组件冗余问题
- 删除外层冗余的
let paySecret;,因为init函数内已经重新声明了该变量; - 动态加载脚本时的
onload可直接绑定init函数,简化逻辑。
修改后的组件代码示例
/* global Tyro */ import React, { useEffect } from 'react'; function TyroPayment() { async function init() { const tyro = Tyro(); const paySecret = '$2a$10$KvfnNafAQguNViSHxLZsVuXv9ITJ56rCVFGIzDencnSB81TpvgAgm'; await tyro.init(paySecret); const payForm = tyro.createPayForm(); payForm.inject('#tyro-pay-form'); } useEffect(() => { // 优先使用index.html已加载的脚本,否则动态加载 if (window.Tyro) { init(); } else { const script = document.createElement('script'); script.src = 'https://pay.connect.tyro.com/v1/tyro.js'; script.crossOrigin = 'anonymous'; script.async = true; script.onload = init; document.body.appendChild(script); } }, []); return ( <div className='mainpage-container'> <form id='pay-form'> <div id='tyro-pay-form'></div> <button id='pay-form-submit'>Pay</button> </form> </div> ); } export default TyroPayment;
内容的提问来源于stack exchange,提问作者Lau Ricky
相关产品推荐
相关产品推荐

