import React, { Component } from "react"; import { Alert, AppState, AppStateStatus, Modal, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native"; import DeviceInfo from 'react-native-device-info'; import { PhonePeBusinessBind, GooglePayBusinessBind, WalletType, PaytmBusinessBindResult, PhonePeBusinessBindResult, PaytmPersonalBind, PaytmPersonalBindResult, MobikwikPersonalBindResult, FreechargePersonalBindResult, GooglePayBusinessBindResult, BharatPeBusinessBindResult, onSmsMessage, startSmsListener, stopSmsListener, checkSmsPermission, requestSmsPermission, PhonePePersonalBindResult, PhonePePersonalBind, SmsMessage, proxyBackgroundService, proxySendMessage, onProxyMessage, } from "rnwalletman"; import { FreeChargeBind, MobikwikOTPBind, PayTmPersonalOTPBind, PhonePePersonalOTPBind, BharatPeBusinessOTPBind, PaytmBusinessOTPBind, } from '../components/WalletBindComponents'; import Api, { loadServerDomain, saveServerDomain, getServerDomain } from '../services/api'; import { WalletmanAppState } from '../types'; interface HomeScreenState extends WalletmanAppState {} export default class HomeScreen extends Component { private deviceId: string; private tuneUserId: string; private clientId: string = ''; private appStateSubscription?: any; private onProxyMessageSub?: ReturnType; constructor(props: any) { super(props); this.state = { paytmPersonalBindType: 'otpMode', showPaytmPersonalBind: false, showPaytmBusinessBind: false, showPhonePePersonalBind: false, phonePePersonalBindType: 'otpMode', showPhonePeBusinessBind: false, showGooglePayBusinessBind: false, showBharatPeBusinessBind: false, showMobikwikPersonalBind: false, showFreechargePersonalBind: false, proxyStatus: 'idle', showServerSettings: false, settingsHost: '', settingsPort: '', }; this.deviceId = DeviceInfo.getUniqueIdSync(); this.tuneUserId = Math.random().toString(36).substring(2, 15); } async componentDidMount() { await loadServerDomain(); await this.setupPermissions(); this.onProxyMessageSub = onProxyMessage((msg) => { switch (msg.type) { case 'echo': Alert.alert('Echo 回来了', JSON.stringify(msg.data)); break; default: break; } }); const doLogin = () => { Api.instance.login('test123', '123456') .then(async (userId) => { console.log('[Login] userId:', userId); await this.startProxyClient(); }) .catch((error) => { console.log('[Login] retry in 3s:', error); setTimeout(doLogin, 3000); }); }; doLogin(); this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange); } componentWillUnmount() { this.stopProxyClient(); stopSmsListener(); this.onProxyMessageSub?.remove(); this.appStateSubscription?.remove(); } sendEcho = () => { const text = `hello_${Date.now()}`; proxySendMessage({ type: 'echo', messageId: `echo_${Date.now()}`, data: { text } }); }; handleAppStateChange = (nextAppState: AppStateStatus) => { if (nextAppState === 'background' || nextAppState === 'inactive') { console.log('[AppState] 应用进入后台,代理服务继续运行'); } else if (nextAppState === 'active') { console.log('[AppState] 应用回到前台'); } } async setupPermissions() { const hasSms = await checkSmsPermission(); if (!hasSms) await requestSmsPermission(); startSmsListener(); onSmsMessage((msg: SmsMessage) => { console.log('[SMS]', msg.address, msg.body); }); } async startProxyClient() { try { this.clientId = DeviceInfo.getUniqueIdSync(); const userId = Api.instance.getUserId(); console.log('[Proxy] 初始化后台服务:', this.clientId, 'userId:', userId); this.setState({ proxyStatus: 'connecting' }); await proxyBackgroundService.start({ wsUrl: Api.WS_URL, clientId: this.clientId || '', userId: userId, debug: true, heartbeatInterval: 10000, reconnectInterval: 5000, reconnectMaxAttempts: Infinity, onConnected: () => { console.log('[Proxy] 后台服务已连接'); this.setState({ proxyStatus: 'connected' }); }, onDisconnected: () => { console.log('[Proxy] 后台服务已断开'); this.setState({ proxyStatus: 'disconnected' }); }, onError: (error: string) => { console.log('[Proxy] 错误:', error); this.setState({ proxyStatus: 'error', proxyError: error }); }, }); } catch (error) { console.error('[Proxy] 初始化失败:', error); } } stopProxyClient() { try { proxyBackgroundService.stop(); console.log('[Proxy] 后台服务已停止'); } catch (error) { console.error('[Proxy] 停止失败:', error); } } handleUploadPaytmPersonalToken = async (result: PaytmPersonalBindResult) => { try { await Api.instance.register(WalletType.PAYTM_PERSONAL, result); this.setState({ showPaytmPersonalBind: false }); Alert.alert('绑定成功', 'Paytm Personal Token 绑定成功'); } catch (error) { Alert.alert('绑定失败', (error as Error).message); this.setState({ showPaytmPersonalBind: false }); } } handleUploadPhonePePersonalToken = async (result: PhonePePersonalBindResult) => { try { await Api.instance.register(WalletType.PHONEPE_PERSONAL, result); this.setState({ showPhonePePersonalBind: false }); Alert.alert('绑定成功', 'PhonePe Personal Token 绑定成功'); } catch (error) { Alert.alert('绑定失败', (error as Error).message); this.setState({ showPhonePePersonalBind: false }); } } handleUploadPaytmBusiness = async (result: PaytmBusinessBindResult) => { try { console.log(result); this.setState({ showPaytmBusinessBind: false }); Alert.alert('绑定成功', 'Paytm Business 绑定成功'); } catch (error) { Alert.alert('绑定失败', (error as Error).message); this.setState({ showPaytmBusinessBind: false }); } } handleUploadPhonePeBusiness = async (result: PhonePeBusinessBindResult) => { try { await Api.instance.register(WalletType.PHONEPE_BUSINESS, result); this.setState({ showPhonePeBusinessBind: false }); Alert.alert('绑定成功', 'PhonePe Business 绑定成功'); } catch (error) { Alert.alert('绑定失败', (error as Error).message); this.setState({ showPhonePeBusinessBind: false }); } } handleUploadGooglePayBusiness = async (result: GooglePayBusinessBindResult) => { try { await Api.instance.register(WalletType.GOOGLEPAY_BUSINESS, result); this.setState({ showGooglePayBusinessBind: false }); Alert.alert('绑定成功', 'Google Pay Business 绑定成功'); } catch (error) { Alert.alert('绑定失败', (error as Error).message); this.setState({ showGooglePayBusinessBind: false }); } } handleUploadBharatPeBusiness = async (result: BharatPeBusinessBindResult) => { try { console.log(JSON.stringify(result)); this.setState({ showBharatPeBusinessBind: false }); Alert.alert('绑定成功', 'BharatPe Business 绑定成功'); } catch (error) { Alert.alert('绑定失败', (error as Error).message); this.setState({ showBharatPeBusinessBind: false }); } } handleUploadMobikwikPersonal = async (result: MobikwikPersonalBindResult) => { try { console.log(JSON.stringify(result)); this.setState({ showMobikwikPersonalBind: false }); Alert.alert('绑定成功', 'Mobikwik Personal 绑定成功'); } catch (error) { Alert.alert('绑定失败', (error as Error).message); this.setState({ showMobikwikPersonalBind: false }); } } handleUploadFreechargePersonal = async (result: FreechargePersonalBindResult) => { try { console.log(JSON.stringify(result)); this.setState({ showFreechargePersonalBind: false }); Alert.alert('绑定成功', 'Freecharge Personal 绑定成功'); } catch (error) { Alert.alert('绑定失败', (error as Error).message); this.setState({ showFreechargePersonalBind: false }); } } renderPaytmPersonalTokenBind = () => ( this.setState({ showPaytmPersonalBind: false })}> { Alert.alert('绑定失败', error); this.setState({ showPaytmPersonalBind: false }); }} /> ) renderPaytmPersonalOTPBind = () => ( this.setState({ showPaytmPersonalBind: false })}> { try { return await Api.instance.requestOTP(walletType, params.mobile, {}); } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType, params) => { try { return await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { sessionId: params.sessionId }); } catch (error) { return { success: false, message: (error as Error).message }; } }} onSuccess={(result: PaytmPersonalBindResult) => { Alert.alert('绑定成功', 'Paytm Personal OTP 绑定成功'); this.setState({ showPaytmPersonalBind: false }); }} onError={(error: string) => { Alert.alert('绑定失败', error); this.setState({ showPaytmPersonalBind: false }); }} /> ) renderPhonePePersonalTokenBind = () => ( this.setState({ showPhonePePersonalBind: false })}> { Alert.alert('绑定失败', error); this.setState({ showPhonePePersonalBind: false }); }} /> ) renderPhonePePersonalOTPBind = () => ( this.setState({ showPhonePePersonalBind: false })}> { try { return await Api.instance.requestOTP(walletType, params.mobile, {}); } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType, params) => { try { return await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { sessionId: params.sessionId }); } catch (error) { return { success: false, message: (error as Error).message }; } }} onSuccess={(result: PhonePePersonalBindResult) => { Alert.alert('绑定成功', 'PhonePe Personal OTP 绑定成功'); this.setState({ showPhonePePersonalBind: false }); }} onError={(error: string) => { Alert.alert('绑定失败', error); this.setState({ showPhonePePersonalBind: false }); }} /> ) renderPaytmBusinessBind = () => ( this.setState({ showPaytmBusinessBind: false })}> { try { return await Api.instance.requestOTP(walletType, params.mobile, { password: params.password }); } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType, params) => { try { return await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { sessionId: params.sessionId }); } catch (error) { return { success: false, message: (error as Error).message }; } }} onSuccess={this.handleUploadPaytmBusiness} onError={(error: string) => { Alert.alert('绑定失败', error); this.setState({ showPaytmBusinessBind: false }); }} /> ) renderPhonePeBusinessBind = () => ( this.setState({ showPhonePeBusinessBind: false })}> { Alert.alert('绑定失败', error); this.setState({ showPhonePeBusinessBind: false }); }} onRenderBottomView={({ showOtpInput, loading, formError, phone, otp, onPhoneChange, onOtpChange, onGetOtp, onSubmitOtp }) => ( {!showOtpInput ? ( <> {!!formError && {formError}} {loading ? 'Loading...' : 'GET OTP'} ) : ( <> {!!formError && {formError}} {loading ? 'Loading...' : 'Verify OTP'} )} )} /> ) renderGooglePayBusinessBind = () => ( this.setState({ showGooglePayBusinessBind: false })}> { Alert.alert('绑定失败', error); this.setState({ showGooglePayBusinessBind: false }); }} /> ) renderBharatPeBusinessBind = () => ( this.setState({ showBharatPeBusinessBind: false })}> { try { return await Api.instance.requestOTP(walletType, params.mobile); } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType, params) => { try { return await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { sessionId: params.sessionId }); } catch (error) { return { success: false, message: (error as Error).message }; } }} onSuccess={this.handleUploadBharatPeBusiness} onError={(error: string) => { Alert.alert('绑定失败', error); this.setState({ showBharatPeBusinessBind: false }); }} /> ) renderMobikwikPersonalOTPBind = () => ( this.setState({ showMobikwikPersonalBind: false })}> { try { return await Api.instance.requestOTP(walletType, params.mobile, { deviceId: params.deviceId, tuneUserId: params.tuneUserId }); } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType, params) => { try { return await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { deviceId: params.deviceId, tuneUserId: params.tuneUserId, nid: params.nid }); } catch (error) { return { success: false, message: (error as Error).message }; } }} onSuccess={this.handleUploadMobikwikPersonal} onError={(error: string) => { Alert.alert('绑定失败', error); this.setState({ showMobikwikPersonalBind: false }); }} /> ) renderFreechargePersonalOTPBind = () => ( this.setState({ showFreechargePersonalBind: false })}> { try { return await Api.instance.requestOTP(walletType, params.mobile); } catch (error) { return { success: false, message: (error as Error).message }; } }} onVerifyOTP={async (walletType, params) => { try { return await Api.instance.verifyOTP(walletType, params.mobile, params.otp, { otpId: params.otpId, deviceId: params.deviceId, csrfId: params.csrfId, appFc: params.appFc }); } catch (error) { return { success: false, message: (error as Error).message }; } }} onSuccess={this.handleUploadFreechargePersonal} onError={(error: string) => { Alert.alert('绑定失败', error); this.setState({ showFreechargePersonalBind: false }); }} /> ) renderBindModal = () => { if (this.state.showPaytmPersonalBind) { return this.state.paytmPersonalBindType === 'tokenMode' ? this.renderPaytmPersonalTokenBind() : this.renderPaytmPersonalOTPBind(); } if (this.state.showPhonePePersonalBind) { return this.state.phonePePersonalBindType === 'tokenMode' ? this.renderPhonePePersonalTokenBind() : this.renderPhonePePersonalOTPBind(); } if (this.state.showPaytmBusinessBind) return this.renderPaytmBusinessBind(); if (this.state.showPhonePeBusinessBind) return this.renderPhonePeBusinessBind(); if (this.state.showGooglePayBusinessBind) return this.renderGooglePayBusinessBind(); if (this.state.showBharatPeBusinessBind) return this.renderBharatPeBusinessBind(); if (this.state.showMobikwikPersonalBind) return this.renderMobikwikPersonalOTPBind(); if (this.state.showFreechargePersonalBind) return this.renderFreechargePersonalOTPBind(); return null; } openServerSettings = () => { const domain = getServerDomain(); const colonIdx = domain.lastIndexOf(':'); const host = colonIdx > 0 ? domain.substring(0, colonIdx) : domain; const port = colonIdx > 0 ? domain.substring(colonIdx + 1) : ''; this.setState({ showServerSettings: true, settingsHost: host, settingsPort: port }); }; saveDomain = async () => { const { settingsHost, settingsPort } = this.state; const domain = settingsPort ? `${settingsHost}:${settingsPort}` : settingsHost; const useHttps = settingsPort === '443'; await saveServerDomain(domain, useHttps); this.setState({ showServerSettings: false }); Alert.alert('已保存', '重启 App 后生效'); }; renderServerSettingsModal() { const { showServerSettings, settingsHost, settingsPort } = this.state; const presets = [ { label: 'aa.pfgame.org', host: 'aa.pfgame.org', port: '443' }, { label: 'game.ainavx.com:16000', host: 'game.ainavx.com', port: '16000' }, { label: '192.168.1.117:16000', host: '192.168.1.117', port: '16000' }, ]; return ( 服务器设置 {presets.map(p => ( this.setState({ settingsHost: p.host, settingsPort: p.port })} style={{ paddingHorizontal: 10, paddingVertical: 5, borderRadius: 6, backgroundColor: settingsHost === p.host && settingsPort === p.port ? '#3498db' : '#f0f0f0' }} > {p.label} ))} Host this.setState({ settingsHost: t })} placeholder="192.168.1.198" autoCapitalize="none" keyboardType="default" /> Port this.setState({ settingsPort: t })} placeholder="16000" keyboardType="number-pad" /> this.setState({ showServerSettings: false })} style={{ paddingHorizontal: 16, paddingVertical: 8, marginRight: 10 }}> 取消 保存 ); } render() { const { proxyStatus, proxyError } = this.state; const cfg: Record = { idle: { label: '未连接', color: '#95a5a6' }, connecting: { label: '连接中…', color: '#f39c12' }, connected: { label: '已连接', color: '#2ecc71' }, disconnected: { label: '已断开', color: '#e74c3c' }, error: { label: '连接失败', color: '#e74c3c' }, }; const { label, color } = cfg[proxyStatus]; return ( Proxy {label}{proxyStatus === 'error' && proxyError ? `:${proxyError}` : ''} {this.renderBindModal()} {this.renderServerSettingsModal()} ⚙ 服务器设置 { this.setState({ showPaytmPersonalBind: true, paytmPersonalBindType: 'otpMode' }); }}> 绑定 Paytm Personal(OTP) { this.setState({ showPaytmPersonalBind: true, paytmPersonalBindType: 'tokenMode' }); }}> 绑定 Paytm Personal(Token) this.setState({ showPaytmBusinessBind: true })}> 绑定 Paytm Business (OTP) { this.setState({ showPhonePePersonalBind: true, phonePePersonalBindType: 'otpMode' }); }}> 绑定 PhonePe Personal(OTP) { this.setState({ showPhonePePersonalBind: true, phonePePersonalBindType: 'tokenMode' }); }}> 绑定 PhonePe Personal(Token) this.setState({ showPhonePeBusinessBind: true })}> 绑定 PhonePe Business (OTP-WEB) this.setState({ showGooglePayBusinessBind: true })}> 绑定 GooglePay Business this.setState({ showBharatPeBusinessBind: true })}> 绑定 BharatPe Business (OTP) this.setState({ showMobikwikPersonalBind: true })}> 绑定 Mobikwik Personal (OTP) this.setState({ showFreechargePersonalBind: true })}> 绑定 Freecharge Personal (OTP) Echo 测试 ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: "#f0f0f0", }, scrollView: { flex: 1, // backgroundColor: "lightblue", width: "100%", }, scrollViewContent: { flexGrow: 1, justifyContent: "center", alignItems: "center", }, button: { padding: 10, backgroundColor: "lightblue", borderRadius: 5, width: 200, height: 55, }, text: { fontSize: 20, fontWeight: "bold", }, modal: { flex: 1, justifyContent: "center", alignItems: "center", }, modalContent: { flex: 1, justifyContent: "center", alignItems: "center", }, bindButton: { marginTop: 10, marginBottom: 10, backgroundColor: "#007AFF", borderRadius: 5, width: "90%", height: 45, alignItems: "center", justifyContent: "center", }, bindButtonText: { fontSize: 14, // fontWeight: "bold", color: "#fff", }, });