import React, { Component } from "react"; import { Alert, Modal, StyleSheet, Text, TouchableOpacity, View } from "react-native"; import { PaytmBusinessBind, PhonePeBusinessBind, GooglePayBusinessBind, BharatPeBusinessBind, WalletType, PaytmBusinessBindResult, PhonePeBusinessBindResult, PaytmPersonalBind, PaytmPersonalBindResult, MobikwikPersonalBind, MobikwikPersonalBindResult, FreechargePersonalBind, FreechargePersonalBindResult, GooglePayBusinessBindResult, BharatPeBusinessBindResult, paytmPay, onSmsMessage, onNotificationMessage, getAllSms, getAllNotifications, startSmsListener, startNotificationListener, stopSmsListener, stopNotificationListener, checkSmsPermission, checkNotificationPermission, openNotificationSettings, requestSmsPermission, PhonePePersonalBindResult, PhonePePersonalBind, SmsMessage, NotificationMessage, TcpProxy, } from "rnwalletman"; import BarcodeScanning from '@react-native-ml-kit/barcode-scanning'; import RNFS from 'react-native-fs'; interface AppProps { } interface AppState { showPaytmBusinessBind: boolean; showPaytmPersonalBind: boolean; showPhonePePersonalBind: boolean; showPhonePeBusinessBind: boolean; showGooglePayBusinessBind: boolean; showBharatPeBusinessBind: boolean; showMobikwikPersonalBind: boolean; showFreechargePersonalBind: boolean; } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", }, button: { padding: 10, backgroundColor: "lightblue", borderRadius: 5, width: 200, height: 50, }, text: { fontSize: 20, fontWeight: "bold", }, modal: { flex: 1, justifyContent: "center", alignItems: "center", }, modalContent: { flex: 1, justifyContent: "center", alignItems: "center", }, bindButton: { padding: 10, borderRadius: 5, width: 250, height: 40, justifyContent: "center", alignItems: "center", margin: 10, }, bindButtonText: { fontSize: 15, fontWeight: "bold", }, }); class Api { public static readonly BASE_URL = 'http://192.168.1.155:16000'; private static _instance: Api | null = null; private ws: WebSocket | null = null; private messageCallbacks = new Map void>(); private constructor() { } public static get instance() { if (Api._instance === null) { Api._instance = new Api(); } return Api._instance; } public setWebSocket(ws: WebSocket, serverUrl: string) { this.ws = ws; // 处理消息 ws.onmessage = (event) => { try { console.log('[WebSocket] 收到消息:', event.data); const msg = JSON.parse(event.data); // 处理响应消息 if (msg.type === 'response' && msg.messageId) { const callback = this.messageCallbacks.get(msg.messageId); if (callback) { callback(msg.data); this.messageCallbacks.delete(msg.messageId); } } // 处理代理请求 if (msg.type === 'proxyRequest') { console.log('[代理] 收到代理请求:', msg.data); const { host, port } = msg.data; // 创建TCP连接 TcpProxy.createProxy( msg.messageId, host, port, // onData: TCP收到数据 → 发送到服务器 (data: string) => { ws.send(JSON.stringify({ type: 'proxyData', messageId: msg.messageId, data: { data } })); }, // onClose: TCP关闭 → 通知服务器 () => { ws.send(JSON.stringify({ type: 'proxyClose', messageId: msg.messageId })); }, // onError: TCP错误 → 通知服务器 (error: string) => { console.error('[代理] TCP错误:', error); ws.send(JSON.stringify({ type: 'proxyClose', messageId: msg.messageId })); } ).then(success => { if (success) { // 回复就绪 ws.send(JSON.stringify({ type: 'proxyReady', messageId: msg.messageId })); console.log('[代理] TCP连接已建立'); } }).catch(err => { console.error('[代理] 创建失败:', err); }); } // 处理代理数据(服务器 → TCP) if (msg.type === 'proxyData' && msg.data?.data) { if (TcpProxy && typeof TcpProxy.writeProxy === 'function') { TcpProxy.writeProxy(msg.messageId, msg.data.data).then(success => { if (!success) { // 写入失败,通知服务器关闭 ws.send(JSON.stringify({ type: 'proxyClose', messageId: msg.messageId })); } }).catch(err => { console.error('[代理] 写入失败:', err); ws.send(JSON.stringify({ type: 'proxyClose', messageId: msg.messageId })); }); } } // 处理代理关闭 if (msg.type === 'proxyClose') { TcpProxy.closeProxy(msg.messageId) .catch(err => console.error('[代理] 关闭失败:', err)); } } catch (error) { console.error('[API] 解析消息失败:', error, event.data); } }; } private sendMessage(type: string, data: any): Promise { return new Promise((resolve, reject) => { if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { reject(new Error('WebSocket未连接')); return; } const messageId = `msg_${Date.now()}_${Math.random()}`; // 设置回调 this.messageCallbacks.set(messageId, (responseData) => { if (responseData.success) { resolve(responseData); } else { reject(new Error(responseData.message)); } }); // 发送消息 this.ws.send(JSON.stringify({ type, messageId, data })); // 超时处理 setTimeout(() => { if (this.messageCallbacks.has(messageId)) { this.messageCallbacks.delete(messageId); reject(new Error('请求超时')); } }, 30000); }); } public async register(walletType: WalletType, params: any) { return this.sendMessage('registerWallet', { walletType, params }); } public async requestOTP(walletType: WalletType, mobile: string, params: any = {}) { return this.sendMessage('requestOTP', { walletType, mobile, ...params }); } public async verifyOTP(walletType: WalletType, mobile: string, otp: string, params: any = {}) { return this.sendMessage('verifyOTP', { walletType, mobile, otp, ...params }); } } export default class App extends Component { private deviceId: string; private tuneUserId: string; private clientId: string; constructor(props: AppProps) { super(props); this.state = { showPaytmBusinessBind: false, showPaytmPersonalBind: false, showPhonePeBusinessBind: false, showPhonePePersonalBind: false, showGooglePayBusinessBind: false, showBharatPeBusinessBind: false, showMobikwikPersonalBind: false, showFreechargePersonalBind: false, }; // 临时使用测试成功的固定 ID this.deviceId = 'B6C1AB6DA4B659C287EA76AA96EC154B80E8D28D'; this.tuneUserId = 'b5bfa7df-e571-4ac8-bb51-90afc05d1d59'; this.clientId = `android_${Date.now()}`; } async componentDidMount() { /* 初始化代理客户端 */ await this.initProxyClient(); /* 权限申请 */ let smsPermission = await checkSmsPermission(); let notificationPermission = await checkNotificationPermission(); if (!smsPermission) { const granted = await requestSmsPermission(); smsPermission = await checkSmsPermission(); console.log('smsPermission:', smsPermission); if (!smsPermission) { Alert.alert('需要短信权限', '请在系统设置中授予短信权限'); } } if (!notificationPermission) { Alert.alert( '需要通知监听权限', '点击确定后将打开设置页面,请找到本应用并授予通知访问权限', [ { text: '确定', onPress: () => openNotificationSettings() }, { text: '取消' } ] ); return; } // 启动监听 startSmsListener(); startNotificationListener(); onSmsMessage((message: SmsMessage) => { console.log('[SMS]', message); }); onNotificationMessage((notification: NotificationMessage) => { console.log('[Notification]', notification); }); if (smsPermission) { getAllSms().then((sms: SmsMessage[]) => { console.log('[所有短信]', sms.length, '条'); }).catch(err => console.error('[获取短信失败]', err)); } if (notificationPermission) { getAllNotifications().then((notifications: NotificationMessage[]) => { console.log('[所有通知]', notifications.length, '条'); }).catch(err => console.error('[获取通知失败]', err)); } } private wsHeartbeatTimer?: NodeJS.Timeout; /** * 初始化代理客户端 */ async initProxyClient() { try { const serverUrl = `ws://${Api.BASE_URL.replace('http://', '')}/ws`; console.log(`[WebSocket] 连接服务器: ${serverUrl}, 客户端ID: ${this.clientId}`); // 创建WebSocket连接 const ws = new WebSocket(serverUrl); ws.onopen = () => { console.log('[WebSocket] ✅ 已连接'); // 注册客户端 ws.send(JSON.stringify({ type: 'register', clientId: this.clientId, messageId: 'register_' + Date.now() })); // 设置给API使用(传入serverUrl用于代理) Api.instance.setWebSocket(ws, serverUrl); // 启动心跳 this.startHeartbeat(ws); }; ws.onerror = (error) => { console.error('[WebSocket] 错误:', error); }; ws.onclose = () => { console.log('[WebSocket] 连接关闭'); this.stopHeartbeat(); // 3秒后重连 setTimeout(() => this.initProxyClient(), 3000); }; } catch (error) { console.error('[WebSocket] 连接失败:', error); } } /** * 启动心跳 */ startHeartbeat(ws: WebSocket) { this.stopHeartbeat(); this.wsHeartbeatTimer = setInterval(() => { if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: 'ping', messageId: 'ping_' + Date.now(), clientId: this.clientId })); } }, 20000); // 每20秒发送一次心跳 } /** * 停止心跳 */ stopHeartbeat() { if (this.wsHeartbeatTimer) { clearInterval(this.wsHeartbeatTimer); this.wsHeartbeatTimer = undefined; } } componentWillUnmount(): void { // 停止心跳 this.stopHeartbeat(); stopSmsListener(); stopNotificationListener(); } decodeQRFromUrl = async (url: string) => { const localPath = `${RNFS.CachesDirectoryPath}/temp_qr_${Date.now()}.jpg`; try { // 1. 下载图片 await RNFS.downloadFile({ fromUrl: url, toFile: localPath }).promise; // 2. 识别二维码 const barcodes = await BarcodeScanning.scan(`file://${localPath}`); if (barcodes.length > 0) { return barcodes[0].value; } } catch (e) { console.error(e); return null; } }; /* 绑定 Paytm Personal */ handlePaytmPersonalBind = () => { this.setState({ showPaytmPersonalBind: true }); } /* 上传 Paytm Personal 到服务器 */ handleUploadPaytmPersonal = async (result: PaytmPersonalBindResult) => { try { console.log(result); const response = await Api.instance.register(WalletType.PAYTM_PERSONAL, result); console.log(response); this.setState({ showPaytmPersonalBind: false }); } catch (error) { Alert.alert('Bind Paytm Personal Error', (error as Error).message || 'Unknown error'); this.setState({ showPaytmPersonalBind: false }); } } /* 绑定 Paytm Business */ handlePaytmBusinessBind = () => { this.setState({ showPaytmBusinessBind: true }); } /* 上传 Paytm Business 到服务器 */ handleUploadPaytmBusiness = async (result: PaytmBusinessBindResult) => { try { console.log(result); const response = await Api.instance.register(WalletType.PAYTM_BUSINESS, result); console.log(response); this.setState({ showPaytmBusinessBind: false }); } catch (error) { Alert.alert('Bind Paytm Business Error', (error as Error).message || 'Unknown error'); this.setState({ showPaytmBusinessBind: false }); } } /* 绑定 Mobikwik Personal */ handleMobikwikPersonalBind = () => { this.setState({ showMobikwikPersonalBind: true }); } /* 上传 Mobikwik Personal 到服务器 */ handleUploadMobikwikPersonal = async (result: MobikwikPersonalBindResult) => { try { console.log(JSON.stringify(result)); // 已在 verifyOTP 中完成注册 this.setState({ showMobikwikPersonalBind: false }); Alert.alert('绑定成功', 'Mobikwik Personal 绑定成功'); } catch (error) { Alert.alert('Bind Mobikwik Personal Error', (error as Error).message || 'Unknown error'); this.setState({ showMobikwikPersonalBind: false }); } } /* 绑定 Freecharge Personal */ handleFreechargePersonalBind = () => { this.setState({ showFreechargePersonalBind: true }); } /* 上传 Freecharge Personal 到服务器 */ handleUploadFreechargePersonal = async (result: FreechargePersonalBindResult) => { try { console.log(JSON.stringify(result)); // 已经在 FreechargePersonalBind 中完成注册 this.setState({ showFreechargePersonalBind: false }); Alert.alert('绑定成功', 'Freecharge Personal 绑定成功'); } catch (error) { Alert.alert('Bind Freecharge Personal Error', (error as Error).message || 'Unknown error'); this.setState({ showFreechargePersonalBind: false }); } } /* 绑定 PhonePe Personal */ handlePhonePePersonalBind = () => { this.setState({ showPhonePePersonalBind: true }); } /* 上传 PhonePe Personal 到服务器 */ handleUploadPhonePePersonal = async (result: PhonePePersonalBindResult) => { try { console.log(JSON.stringify(result)); Alert.alert('绑定成功', 'PhonePe Personal 绑定成功'); this.setState({ showPhonePePersonalBind: false }); } catch (error) { Alert.alert('Bind PhonePe Personal Error', (error as Error).message || 'Unknown error'); this.setState({ showPhonePePersonalBind: false }); } } /* 绑定 PhonePe Business */ handlePhonePeBusinessBind = () => { this.setState({ showPhonePeBusinessBind: true }); } /* 上传 PhonePe Business 到服务器 */ handleUploadPhonePeBusiness = async (result: PhonePeBusinessBindResult) => { try { console.log(JSON.stringify(result)); const response = await Api.instance.register(WalletType.PHONEPE_BUSINESS, result); console.log(response); this.setState({ showPhonePeBusinessBind: false }); } catch (error) { Alert.alert('Bind PhonePe Business Error', (error as Error).message || 'Unknown error'); this.setState({ showPhonePeBusinessBind: false }); } } /* 绑定 GooglePay Business */ handleGooglePayBusinessBind = () => { this.setState({ showGooglePayBusinessBind: true }); } /* 上传 GooglePay Business 到服务器 */ handleUploadGooglePayBusiness = async (result: GooglePayBusinessBindResult) => { try { console.log(JSON.stringify(result)); const response = await Api.instance.register(WalletType.GOOGLEPAY_BUSINESS, result); console.log(response); this.setState({ showGooglePayBusinessBind: false }); } catch (error) { Alert.alert('Bind GooglePay Business Error', (error as Error).message || 'Unknown error'); this.setState({ showGooglePayBusinessBind: false }); } } /* 绑定 BharatPe Business */ handleBharatPeBusinessBind = () => { this.setState({ showBharatPeBusinessBind: true }); } /* 上传 BharatPe Business 到服务器 */ handleUploadBharatPeBusiness = async (result: BharatPeBusinessBindResult) => { try { console.log(result); const qrCode = await this.decodeQRFromUrl(result.qrUrl || ''); console.log('qrCode:', qrCode); const response = await Api.instance.register(WalletType.BHARATPE_BUSINESS, { cookie: result.cookie, accessToken: result.accessToken, merchantId: result.merchantId, userName: result.userName, email: result.email, mobile: result.mobile, qrCode: qrCode, }); console.log(response); this.setState({ showBharatPeBusinessBind: false }); } catch (error) { Alert.alert('Bind BharatPe Business Error', (error as Error).message || 'Unknown error'); this.setState({ showBharatPeBusinessBind: false }); } } renderBindModal = () => { /* 绑定 PhonePe Personal */ if (this.state.showPhonePePersonalBind) { return ( this.setState({ showPhonePePersonalBind: false })}> { try { const response = await Api.instance.requestOTP(walletType, params.mobile, {}); return response; } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType: WalletType, params: any) => { try { const response = await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { sessionId: params.sessionId, // 只需要传 sessionId }); return response; } catch (error) { return { success: false, message: (error as Error).message }; } }} onSuccess={(result: PhonePePersonalBindResult) => { this.handleUploadPhonePePersonal(result); }} onError={(error: string) => { console.log(error); Alert.alert('绑定失败', error); this.setState({ showPhonePePersonalBind: false }); }} /> ); } /* 绑定 Paytm Business */ if (this.state.showPaytmBusinessBind) { return ( this.setState({ showPaytmBusinessBind: false })}> { this.handleUploadPaytmBusiness(result); }} onError={(error: string) => { console.log(error); this.setState({ showPaytmBusinessBind: false }); }} /> ); } /* 绑定 PhonePe Business */ if (this.state.showPhonePeBusinessBind) { return ( this.setState({ showPhonePeBusinessBind: false })}> { this.handleUploadPhonePeBusiness(result); }} onError={(error) => { console.log(error); this.setState({ showPhonePeBusinessBind: false }); }} /> ); } /* 绑定 GooglePay Business */ if (this.state.showGooglePayBusinessBind) { return ( this.setState({ showGooglePayBusinessBind: false })}> { this.handleUploadGooglePayBusiness(result); }} onError={(error: string) => { console.log(error); this.setState({ showGooglePayBusinessBind: false }); }} /> ); } /* 绑定 BharatPe Business */ if (this.state.showBharatPeBusinessBind) { return ( this.setState({ showBharatPeBusinessBind: false })}> { this.handleUploadBharatPeBusiness(result); }} onError={(error) => { console.log(error); this.setState({ showBharatPeBusinessBind: false }); }} /> ); } /* 绑定 Paytm Personal */ if (this.state.showPaytmPersonalBind) { return ( this.setState({ showPaytmPersonalBind: false })}> { this.handleUploadPaytmPersonal(result); }} onError={(error) => { console.log(error); this.setState({ showPaytmPersonalBind: false }); }} /> ); } /* 绑定 Mobikwik Personal */ if (this.state.showMobikwikPersonalBind) { return ( this.setState({ showMobikwikPersonalBind: false })}> { try { const response = await Api.instance.requestOTP(walletType, params.mobile, { deviceId: params.deviceId, tuneUserId: params.tuneUserId }); return response; } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType: WalletType, params: { mobile: string, otp: string, deviceId?: string, tuneUserId?: string, nid?: string }) => { try { const response = await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { deviceId: params.deviceId, tuneUserId: params.tuneUserId, nid: params.nid }); return response; } catch (error) { return { success: false, message: (error as Error).message }; } }} onSuccess={(result: MobikwikPersonalBindResult) => { this.handleUploadMobikwikPersonal(result); }} onError={(error) => { console.log(error); this.setState({ showMobikwikPersonalBind: false }); }} /> ); } /* 绑定 Freecharge Personal */ if (this.state.showFreechargePersonalBind) { return ( this.setState({ showFreechargePersonalBind: false })}> { try { const response = await Api.instance.requestOTP(walletType, params.mobile); return response; } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType: WalletType, params: { mobile: string, otp: string, otpId?: string, deviceId?: string, csrfId?: string, appFc?: string }) => { try { const response = await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { otpId: params.otpId, deviceId: params.deviceId, csrfId: params.csrfId, appFc: params.appFc }); return response; } catch (error) { return { success: false, message: (error as Error).message }; } }} processString="Processing Freecharge Personal..." // isDebug={true} onSuccess={(result: FreechargePersonalBindResult) => { this.handleUploadFreechargePersonal(result); }} onError={(error) => { console.log(error); this.setState({ showFreechargePersonalBind: false }); }} /> ); } return null; } render() { return ( {this.renderBindModal()} 绑定 Paytm Personal 绑定 Paytm Business 绑定 PhonePe Personal 绑定 PhonePe Business 绑定 GooglePay Business 绑定 BharatPe Business 绑定 Mobikwik Personal 绑定 Freecharge Personal ); } }