You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native WebView集成Paystack时取消支付按钮无响应问题

解决React Native WebView集成Paystack时取消按钮无响应的问题

问题根源分析

  1. 脚本注入时机错误:你在onNavigationStateChange中注入JS时,Paystack页面可能还未完全渲染,导致找不到目标按钮。
  2. 按钮选择器不可靠:依赖innerHTML.includes('Cancel Payment')判断按钮容易失效,Paystack的UI可能会更新文本或结构。
  3. HTMLCollection遍历问题:getElementsByTagName('button')返回的是HTMLCollection,不能直接用forEach,需要先转为数组。
  4. 未阻止原按钮默认行为:原按钮可能自带跳转逻辑,导致你的监听事件还未执行就触发了页面跳转。

可行解决方案

方案1:劫持原按钮事件并发送消息到RN

修改脚本注入时机和内容,确保页面加载完成后再执行,同时修复遍历和事件逻辑:

  1. 更新WebView配置:使用onLoadEnd事件注入脚本,确保页面完全渲染:
{isPaymentSuccess && paymentState && (
  <WebView 
    javaScriptEnabled={true}
    source={{ uri: paymentData }}
    style={{ marginTop: 50 }}
    onNavigationStateChange={handleNav}
    cacheEnabled={false}
    cacheMode={'LOAD_NO_CACHE'}
    ref={webView}
    onMessage={(e) => {
      const data = JSON.parse(e.nativeEvent.data);
      if (data.event === 'cancelled') {
        setPaymentState(false);
        // 这里可以添加取消后的逻辑
      }
    }}
    onLoadEnd={() => {
      webView.current?.injectJavaScript(handleCancel);
    }}
  />
)}
  1. 修正handleCancel脚本:
const handleCancel = `
// 将HTMLCollection转为数组遍历
const buttons = Array.from(document.getElementsByTagName('button'));
buttons.forEach(button => {
  // 改用更可靠的选择方式,比如检查按钮的类或属性(实际可通过浏览器调试查看)
  if (button.textContent.includes('Cancel Payment') || button.classList.contains('paystack-close-button')) {
    // 移除原有事件(可选,避免冲突)
    button.replaceWith(button.cloneNode(true));
    const newButton = document.querySelector('[textContent*="Cancel Payment"]');
    // 添加新的点击事件
    newButton.addEventListener('click', (e) => {
      e.preventDefault(); // 阻止默认跳转
      window.ReactNativeWebView.postMessage(JSON.stringify({event: 'cancelled'}));
      // 触发Paystack的关闭逻辑
      window.location.href = 'https://standard.paystack.co/close';
    });
  }
});
`;

方案2:隐藏原按钮,添加自定义取消按钮

如果劫持原按钮不稳定,可以直接隐藏原按钮,在WebView上方叠加RN的自定义按钮:

{isPaymentSuccess && paymentState && (
  <View style={{flex: 1}}>
    <WebView 
      // 原有WebView配置
    />
    {/* 自定义取消按钮,覆盖在WebView顶部 */}
    <TouchableOpacity 
      style={{position: 'absolute', top: 60, left: 20, padding: 10, backgroundColor: '#fff', borderRadius: 5}}
      onPress={() => {
        setPaymentState(false);
        // 如果需要触发Paystack的close逻辑,可以注入JS跳转
        webView.current?.injectJavaScript(`window.location.href = 'https://standard.paystack.co/close';`);
      }}
    >
      <Text>Cancel Payment</Text>
    </TouchableOpacity>
  </View>
)}

方案3:监听Paystack的close URL跳转

直接在onNavigationStateChange中检测是否跳转到https://standard.paystack.co/close,如果是则关闭WebView:

const handleNav = async (navState) => {
  const { url } = navState;
  if (url.includes('https://standard.paystack.co/close')) {
    setPaymentState(false);
    return;
  }
  // 原有回调URL验证逻辑
  const customUrl = url.split('?');
  const getCallBackURL = customUrl[0];
  const queryStr = customUrl[1];
  if (getCallBackURL === callback_url) {
    setPaymentState(false);
    try {
      const res = await axios.get(`${BASE_URL}/payverify/?${queryStr}`);
      if (res?.data?.status === 'success') {
        const payMentData = res?.data;
        navigation.navigate('ThankyouPage', {payMentData});
      }
    } catch (error) {
      // 处理错误
    }
  }
};

关键注意事项

  • 调试时可以用console.log在注入的JS中输出信息,通过Chrome调试WebView查看执行情况。
  • Paystack的UI结构可能会更新,建议通过浏览器开发者工具查看按钮的实际属性,调整选择器。
  • 确保window.ReactNativeWebView.postMessage能正常触发,RN端的onMessage能正确接收消息。

内容的提问来源于stack exchange,提问作者kingsJayson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 10:55:50