【问题标题】:react-native-webview how to inject javascript?react-native-webview 如何注入 javascript?
【发布时间】:2020-10-05 04:55:31
【问题描述】:

在 Android 上,我一直在使用 expo-stripe-checkout 在 Expo 托管应用上进行付款。在我更新到最新版本的 expo 和 react-native 之前,一切都运行良好。现在,没有一个回调,如 onClose 和 onPaymentSuccess 正在工作。似乎 WebView 已从 react-native 中删除,所以我直接从 react-native-webview 导入。

我没有使用expo-stripe-checkout,而是创建了自己的组件,以尝试解决正在发生的事情,似乎WebView 的injectedJavaScript 根本没有运行,因此window.postMessagewindow.ReactNativeWebView.postMessage 没有运行不工作。

package.json:

{
  "name": "example",
  "version": "0.0.6",
  "private": true,
  "devDependencies": {
    "jest-expo": "^37.0.0",
    "react-test-renderer": "16.0.0",
    "schedule": "^0.4.0"
  },
  "main": "./node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "eject": "expo eject",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "test": "node node_modules/jest/bin/jest.js --watch",
    "prettier": "./node_modules/prettier/bin-prettier.js --single-quote --trailing-comma es5 --print-width 100 --write 'app/**/*.js' -l"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "@ptomasroos/react-native-multi-slider": "^1.0.0",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-navigation/drawer": "^5.6.4",
    "@react-navigation/native": "^5.2.3",
    "@react-navigation/stack": "^5.2.18",
    "axios": "^0.17.1",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "emoji-utils": "^1.0.1",
    "expo": "^37.0.0",
    "expo-analytics": "^1.0.9",
    "expo-apple-authentication": "^2.1.1",
    "expo-av": "~8.1.0",
    "expo-blur": "~8.1.0",
    "expo-branch": "~2.1.0",
    "expo-constants": "~9.0.0",
    "expo-facebook": "~8.1.0",
    "expo-font": "~8.1.0",
    "expo-image-manipulator": "~8.1.0",
    "expo-image-picker": "~8.1.0",
    "expo-linear-gradient": "~8.1.0",
    "expo-permissions": "~8.1.0",
    "expo-stripe-checkout": "^1.0.1",
    "immutability-helper": "^2.8.1",
    "lottie-react-native": "~2.6.1",
    "moment": "^2.22.1",
    "prettier": "^1.12.1",
    "react": "16.9.0",
    "react-native": "0.61.4",
    "react-native-animate-number": "^0.1.2",
    "react-native-aws3": "0.0.9",
    "react-native-branch": "4.2.1",
    "react-native-calendars": "^1.20.0",
    "react-native-circular-action-menu": "^0.5.0",
    "react-native-circular-progress": "^1.0.1",
    "react-native-datepicker": "^1.7.2",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-gifted-chat": "0.13.0",
    "react-native-google-places-autocomplete": "^1.4.0",
    "react-native-invertible-scroll-view": "^1.1.1",
    "react-native-keyboard-aware-scroll-view": "0.9.1",
    "react-native-maps": "0.26.1",
    "react-native-modal": "^11.5.3",
    "react-native-modal-dropdown": "^0.6.2",
    "react-native-reanimated": "^1.8.0",
    "react-native-safe-area-context": "^0.7.3",
    "react-native-screens": "^2.7.0",
    "react-native-scroll-into-view": "^0.1.4",
    "react-native-snap-carousel": "^3.7.2",
    "react-native-status-bar-height": "^3.0.0-alpha.1",
    "react-native-svg": "11.0.1",
    "react-native-svg-icon": "^0.8.1",
    "react-native-swipe-gestures": "^1.0.5",
    "react-native-unimodules": "~0.8.1",
    "react-native-webview": "^10.3.1",
    "react-redux": "^5.0.7",
    "react-timer-mixin": "^0.13.4",
    "react-visibility-sensor": "^4.1.0",
    "redux": "^4.0.0",
    "redux-thunk": "^2.3.0",
    "sentry-expo": "~2.0.0",
    "socket.io-client": "^2.0.4"
  }
}

我尝试了网络上的几种不同建议,但没有任何效果:

StripeCheckout.js

import React, { Component } from 'react';
import { Platform, View, ViewPropTypes } from 'react-native';
import { PropTypes } from 'prop-types';
import { WebView } from 'react-native-webview'

class StripeCheckout extends Component {

  render() {
    const {
      publicKey,
      amount,
      allowRememberMe,
      currency,
      description,
      imageUrl,
      storeName,
      prepopulatedEmail,
      style,
      onPaymentSuccess,
      onClose
    } = this.props;

    const jsCode = `(function() {
                    console.log('hello')
                    var originalPostMessage = window.ReactNativeWebView.postMessage;
                    var patchedPostMessage = function(message, targetOrigin, transfer) {
                      originalPostMessage(message, targetOrigin, transfer);
                    };
                    patchedPostMessage.toString = function() {
                      return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
                    };
                    window.ReactNativeWebView.postMessage = patchedPostMessage;
                  })();`;
    const runFirst = `
      console.log('firstRun')
      window.isNativeApp = true;
      true; // note: this is required, or you'll sometimes get silent failures
    `;

    return (
      <WebView
        ref={(ref) => { this.webview = ref; }}
        javaScriptEnabled={true}
        injectedJavaScriptForMainFrameOnly={false}
        scrollEnabled={false}
        bounces={false}
        messagingEnabled={true}
        onMessage={(event) => console.log(event)}
        onPaymentSuccess(event.nativeEvent.data)}
        injectedJavaScriptBeforeContentLoaded={runFirst}
        injectedJavaScript={jsCode}
        source={{ html: `<script src="https://checkout.stripe.com/checkout.js"></script>
            <script>
            var handler = StripeCheckout.configure({
              key: '${publicKey}',
              image: '${imageUrl}',
              locale: 'auto',
              token: function(token) {
                window.ReactNativeWebView.postMessage(token.id, token.id);
              },
            });
            window.onload = function() {
              console.log('onload')
              handler.open({
                image: '${imageUrl}',
                name: '${storeName}',
                description: '${description}',
                amount: ${amount},
                currency: '${currency}',
                allowRememberMe: ${allowRememberMe},
                email: '${prepopulatedEmail}',
                closed: function() {
                  window.ReactNativeWebView.postMessage("WINDOW_CLOSED", "*");
                }
              });
            };
            </script>`}}
        style={[{ flex: 1 }, style]}
        scalesPageToFit={Platform.OS === 'android'}
      />
    );
  }
}

StripeCheckout.propTypes = {
  publicKey: PropTypes.string.isRequired,
  amount: PropTypes.number.isRequired,
  imageUrl: PropTypes.string.isRequired,
  storeName: PropTypes.string.isRequired,
  description: PropTypes.string.isRequired,
  allowRememberMe: PropTypes.bool.isRequired,
  onPaymentSuccess: PropTypes.func.isRequired,
  onClose: PropTypes.func.isRequired,
  currency: PropTypes.string,
  prepopulatedEmail: PropTypes.string,
  style: ViewPropTypes.object
};

StripeCheckout.defaultProps = {
  prepopulatedEmail: '',
  currency: 'USD',
};

export default StripeCheckout;

没有控制台记录。条带集成弹出并成功返回一个令牌,但没有任何反应,并且组件没有接收到令牌(我可以看到它正在从条带日志中返回一个令牌)。

如果还有什么我应该发布的,请告诉我。谢谢!

【问题讨论】:

    标签: javascript android react-native react-native-webview


    【解决方案1】:

    我脑子里想的几件事:

    1. 在你的 package.json 中,react-native 版本应该是"react-native": "https://github.com/expo/react-native/archive/sdk-37.0.1.tar.gz",(Expo SDK 37 已经基于 0.61.4,但带有 Expo 特定的 mods)。在以前的版本中让 expo-stripe-checkout 像以前一样工作可能就这么简单。 The SDK 37 announcement blog post 提供有关 SDK 升级过程的更多信息,即:
      • 在你的项目目录下运行expo upgrade(需要最新版本的expo-cli,你可以用npm i -g expo-cli更新)。
      • 请务必查看更改日志以了解其他重大更改!
      • ...
    2. 如果这无助于让expo-checkout-stripe 再次工作(无论如何都要修复您的 React Native 版本,如果您不这样做,您肯定会遇到更多的 Expo 问题),请尝试以下一项或两项操作网页浏览:

    我希望这些建议之一至少能让你走上正确的道路。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-20
      • 2022-11-11
      • 1970-01-01
      • 2018-03-23
      • 1970-01-01
      相关资源
      最近更新 更多