iko1133

Flitt test

Sep 1st, 2025
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { NativeStackScreenProps } from "@react-navigation/native-stack";
  2. import React, { useRef, useState } from "react";
  3. import { Linking, StyleSheet, View } from "react-native";
  4. import { Text } from "react-native-paper";
  5. import WebView from "react-native-webview";
  6. import i18n from "src/config/language";
  7. import { Store, useStore } from "src/store/store";
  8. import Screen from "../atoms/Screen";
  9.  
  10. interface PaymentWebViewParams {
  11.   paymentUrl?: string;
  12.   amount?: number;
  13.   onPaymentSuccess?: () => void;
  14.   onPaymentError?: () => void;
  15. }
  16.  
  17. const Options = {
  18.   options: {
  19.     methods: ["card"],
  20.     methods_disabled: [],
  21.     card_icons: ["mastercard", "visa"],
  22.     fields: false,
  23.     full_screen: false,
  24.     button: true,
  25.     hide_title: true,
  26.     hide_link: true,
  27.     email: false,
  28.     theme: {
  29.       type: "light",
  30.       preset: "reset",
  31.     },
  32.   },
  33.   params: {
  34.     merchant_id: 1549901,
  35.     required_rectoken: "y",
  36.     currency: "GEL",
  37.     amount: 500,
  38.   },
  39.   css_variable: {
  40.     main: "#7d8ff8",
  41.     card_bg: "#353535",
  42.     card_shadow: "#9ADBE8",
  43.   },
  44. };
  45.  
  46. const html = `
  47. <!DOCTYPE html>
  48. <html>
  49. <head>
  50.   <meta charset="utf-8">
  51.   <meta name="viewport" content="width=device-width, initial-scale=1.0">
  52.   <title>Payment</title>
  53.   <link rel="stylesheet" href="https://pay.fondy.eu/latest/checkout-vue/checkout.css">
  54.   <style>
  55.     html, body {
  56.       height: 100%;
  57.       margin: 0;
  58.       padding: 0;
  59.       font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  60.     }
  61.    
  62.     #checkout-container {
  63.       width: 100%;
  64.       height: 100%;
  65.       display: flex;
  66.       justify-content: center;
  67.       align-items: center;
  68.       padding: 16px;
  69.       box-sizing: border-box;
  70.     }
  71.   </style>
  72. </head>
  73. <body>
  74.   <div id="checkout-container"></div>
  75.  
  76.   <script src="https://pay.flitt.com/latest/checkout-vue/checkout.js"></script>
  77.   <script>
  78.     // Payment configuration
  79.  
  80.     const Options = ${JSON.stringify(Options)};
  81.  
  82.     // Initialize checkout when DOM is ready
  83.     document.addEventListener('DOMContentLoaded', function() {
  84.       if (typeof checkout === 'function') {
  85.         checkout("#checkout-container", Options);
  86.       } else {
  87.         console.error('Checkout function not available');
  88.       }
  89.     });
  90.  
  91.     // Handle payment success/error callbacks
  92.     window.addEventListener('message', function(event) {
  93.       if (event.data.type === 'payment_success') {
  94.         window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({
  95.           type: 'payment_success',
  96.           data: event.data
  97.         }));
  98.       } else if (event.data.type === 'payment_error') {
  99.         window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({
  100.           type: 'payment_error',
  101.           data: event.data
  102.         }));
  103.       }
  104.     });
  105.   </script>
  106. </body>
  107. </html>
  108. `;
  109.  
  110. export default function PaymentWebView({
  111.   navigation,
  112.   route,
  113. }: NativeStackScreenProps<any, "PaymentWebView">) {
  114.   const { amount, onPaymentSuccess, onPaymentError } =
  115.     route.params as PaymentWebViewParams & { amount?: number };
  116.   const { setError, setMessage } = useStore((state: Store) => state);
  117.   const webViewRef = useRef(null);
  118.   const [loading, setLoading] = useState(true);
  119.  
  120.   // Generate dynamic HTML with the payment amount
  121.   const generateHTML = () => {
  122.     return html.replace("amount: 500", `amount: ${amount || 500}`);
  123.   };
  124.  
  125.   const handleLoadStart = () => {
  126.     setLoading(true);
  127.   };
  128.  
  129.   const handleLoadEnd = () => {
  130.     setLoading(false);
  131.   };
  132.  
  133.   const handleError = (syntheticEvent: any) => {
  134.     const { nativeEvent } = syntheticEvent;
  135.     console.warn("WebView error: ", nativeEvent);
  136.     setError(i18n.t("purchaseError"));
  137.     navigation.goBack();
  138.   };
  139.  
  140.   return (
  141.     <Screen style={styles.container}>
  142.       <View style={styles.webviewContainer}>
  143.         <WebView
  144.           ref={webViewRef}
  145.           // source={{ uri: "https://codepen.io/flitt/pen/BaggpVw" }}
  146.           source={{ html: generateHTML(), baseUrl: "https://google.com" }}
  147.           style={styles.webview}
  148.           onLoadStart={handleLoadStart}
  149.           onLoadEnd={handleLoadEnd}
  150.           onError={handleError}
  151.           // onMessage={handleMessage}
  152.           javaScriptEnabled={true}
  153.           domStorageEnabled={true}
  154.           startInLoadingState={true}
  155.           scalesPageToFit={true}
  156.           sharedCookiesEnabled
  157.           thirdPartyCookiesEnabled
  158.           allowsBackForwardNavigationGestures={true}
  159.           injectedJavaScript={`(function() {
  160.             const open = window.open;
  161.             window.open = function(url) {
  162.               window.ReactNativeWebView.postMessage(JSON.stringify({ t:'OPEN', url }));
  163.               return null;
  164.             };
  165.             document.addEventListener('click', function(e){
  166.               const a = e.target.closest('a[target="_blank"]');
  167.               if (a && a.href) { e.preventDefault();
  168.                 window.ReactNativeWebView.postMessage(JSON.stringify({ t:'OPEN', url:a.href }));
  169.               }
  170.             }, true);
  171.           })();
  172.           true;`}
  173.           setSupportMultipleWindows
  174.           onCreateWindow={(e) => {
  175.             Linking.openURL(e.nativeEvent.targetUrl);
  176.             return false;
  177.           }}
  178.           onMessage={(e) => {
  179.             try {
  180.               const m = JSON.parse(e.nativeEvent.data);
  181.               if (m.t === "OPEN" && m.url) Linking.openURL(m.url);
  182.             } catch {}
  183.           }}
  184.         />
  185.       </View>
  186.  
  187.       {loading && (
  188.         <View style={styles.loadingContainer}>
  189.           <Text style={styles.loadingText}>{i18n.t("loading")}</Text>
  190.         </View>
  191.       )}
  192.     </Screen>
  193.   );
  194. }
  195.  
  196. const styles = StyleSheet.create({
  197.   container: {
  198.     flex: 1,
  199.   },
  200.   header: {
  201.     padding: 16,
  202.     borderBottomWidth: 1,
  203.     borderBottomColor: "#E5E5E5",
  204.     backgroundColor: "#FFFFFF",
  205.   },
  206.   headerText: {
  207.     fontSize: 18,
  208.     fontWeight: "600",
  209.     color: "#20232B",
  210.     textAlign: "center",
  211.   },
  212.   webviewContainer: {
  213.     flex: 1,
  214.   },
  215.   webview: {
  216.     flex: 1,
  217.   },
  218.   loadingContainer: {
  219.     position: "absolute",
  220.     top: 0,
  221.     left: 0,
  222.     right: 0,
  223.     bottom: 0,
  224.     justifyContent: "center",
  225.     alignItems: "center",
  226.     backgroundColor: "rgba(255, 255, 255, 0.8)",
  227.   },
  228.   loadingText: {
  229.     fontSize: 16,
  230.     color: "#636B74",
  231.   },
  232. });
  233.  
Advertisement
Add Comment
Please, Sign In to add comment