fix fix fix
This commit is contained in:
12
App.tsx
12
App.tsx
@@ -51,8 +51,8 @@ export default function App() {
|
|||||||
name="Home"
|
name="Home"
|
||||||
component={HomeScreen}
|
component={HomeScreen}
|
||||||
options={{
|
options={{
|
||||||
title: '钱包列表',
|
title: 'Wallets',
|
||||||
tabBarLabel: '钱包列表',
|
tabBarLabel: 'Wallets',
|
||||||
tabBarIcon: ({ color, size }) => <WalletIcon color={color} size={size} />,
|
tabBarIcon: ({ color, size }) => <WalletIcon color={color} size={size} />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -60,8 +60,8 @@ export default function App() {
|
|||||||
name="Test"
|
name="Test"
|
||||||
component={TestScreen}
|
component={TestScreen}
|
||||||
options={{
|
options={{
|
||||||
title: '测试',
|
title: 'Test',
|
||||||
tabBarLabel: '测试',
|
tabBarLabel: 'Test',
|
||||||
tabBarIcon: ({ color, size }) => <ToolIcon color={color} size={size} />,
|
tabBarIcon: ({ color, size }) => <ToolIcon color={color} size={size} />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -69,8 +69,8 @@ export default function App() {
|
|||||||
name="Message"
|
name="Message"
|
||||||
component={MessageScreen}
|
component={MessageScreen}
|
||||||
options={{
|
options={{
|
||||||
title: 'IM消息',
|
title: 'Messages',
|
||||||
tabBarLabel: 'IM消息',
|
tabBarLabel: 'Messages',
|
||||||
tabBarIcon: ({ color, size }) => <MessageIcon color={color} size={size} />,
|
tabBarIcon: ({ color, size }) => <MessageIcon color={color} size={size} />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
4
android/.idea/deploymentTargetSelector.xml
generated
4
android/.idea/deploymentTargetSelector.xml
generated
@@ -4,10 +4,10 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2026-01-23T07:17:48.908770Z">
|
<DropdownSelection timestamp="2026-03-24T13:16:14.737959Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=Y9Z5GMQC8LFE5LT4" />
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=10BFBM0Q5T005JE" />
|
||||||
</handle>
|
</handle>
|
||||||
</Target>
|
</Target>
|
||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
|
|||||||
13
android/.idea/deviceManager.xml
generated
Normal file
13
android/.idea/deviceManager.xml
generated
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DeviceTable">
|
||||||
|
<option name="columnSorters">
|
||||||
|
<list>
|
||||||
|
<ColumnSorterState>
|
||||||
|
<option name="column" value="Name" />
|
||||||
|
<option name="order" value="ASCENDING" />
|
||||||
|
</ColumnSorterState>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
1
android/.idea/gradle.xml
generated
1
android/.idea/gradle.xml
generated
@@ -32,6 +32,7 @@
|
|||||||
<option value="$PROJECT_DIR$/../node_modules/react-native-gesture-handler/android" />
|
<option value="$PROJECT_DIR$/../node_modules/react-native-gesture-handler/android" />
|
||||||
<option value="$PROJECT_DIR$/../node_modules/react-native-safe-area-context/android" />
|
<option value="$PROJECT_DIR$/../node_modules/react-native-safe-area-context/android" />
|
||||||
<option value="$PROJECT_DIR$/../node_modules/react-native-screens/android" />
|
<option value="$PROJECT_DIR$/../node_modules/react-native-screens/android" />
|
||||||
|
<option value="$PROJECT_DIR$/../node_modules/react-native-svg/android" />
|
||||||
<option value="$PROJECT_DIR$/../node_modules/react-native-tcp-socket/android" />
|
<option value="$PROJECT_DIR$/../node_modules/react-native-tcp-socket/android" />
|
||||||
<option value="$PROJECT_DIR$/../node_modules/react-native-webview/android" />
|
<option value="$PROJECT_DIR$/../node_modules/react-native-webview/android" />
|
||||||
<option value="$PROJECT_DIR$/../node_modules/rnauto/android" />
|
<option value="$PROJECT_DIR$/../node_modules/rnauto/android" />
|
||||||
|
|||||||
@@ -81,6 +81,15 @@ android {
|
|||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
splits {
|
||||||
|
abi {
|
||||||
|
enable true
|
||||||
|
reset()
|
||||||
|
include "arm64-v8a"
|
||||||
|
universalApk false
|
||||||
|
}
|
||||||
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
debug {
|
debug {
|
||||||
storeFile file('debug.keystore')
|
storeFile file('debug.keystore')
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import {
|
|||||||
|
|
||||||
import Api, { WalletItem, loadServerDomain, saveServerDomain, getServerDomain } from '../services/api';
|
import Api, { WalletItem, loadServerDomain, saveServerDomain, getServerDomain } from '../services/api';
|
||||||
|
|
||||||
// key 与服务端 WalletType 字符串一致(见 types.go)
|
// key matches server WalletType string (see types.go)
|
||||||
const WALLET_ICONS: Record<string, any> = {
|
const WALLET_ICONS: Record<string, any> = {
|
||||||
'paytm': require('../res/paytm.png'),
|
'paytm': require('../res/paytm.png'),
|
||||||
'paytm business': require('../res/paytm-business.png'),
|
'paytm business': require('../res/paytm-business.png'),
|
||||||
@@ -63,7 +63,7 @@ const WALLET_TYPE_COLORS: Record<string, string> = {
|
|||||||
'freecharge': '#ff5722',
|
'freecharge': '#ff5722',
|
||||||
};
|
};
|
||||||
|
|
||||||
// 钱包类型展示信息(walletType 与服务端一致)
|
// wallet type display info (walletType matches server)
|
||||||
const WALLET_TYPE_OPTIONS = [
|
const WALLET_TYPE_OPTIONS = [
|
||||||
{ key: 'paytm_personal_otp', walletType: 'paytm', label: 'Paytm Personal (OTP)', mode: 'otp' },
|
{ key: 'paytm_personal_otp', walletType: 'paytm', label: 'Paytm Personal (OTP)', mode: 'otp' },
|
||||||
{ key: 'paytm_personal_token', walletType: 'paytm', label: 'Paytm Personal (Token)', mode: 'token' },
|
{ key: 'paytm_personal_token', walletType: 'paytm', label: 'Paytm Personal (Token)', mode: 'token' },
|
||||||
@@ -201,7 +201,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
onError: (error: string) => this.setState({ proxyStatus: 'error', proxyError: error }),
|
onError: (error: string) => this.setState({ proxyStatus: 'error', proxyError: error }),
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Proxy] 初始化失败:', error);
|
console.error('[Proxy] init failed:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
wallets: s.wallets.map(w => w.id === walletId ? { ...w, upi: vpa } : w),
|
wallets: s.wallets.map(w => w.id === walletId ? { ...w, upi: vpa } : w),
|
||||||
}));
|
}));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Alert.alert('设置失败', (e as Error).message);
|
Alert.alert('Set Failed', (e as Error).message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -273,11 +273,11 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
const wt = typeMap[key as string];
|
const wt = typeMap[key as string];
|
||||||
if (wt) await Api.instance.register(wt as WalletType, result);
|
if (wt) await Api.instance.register(wt as WalletType, result);
|
||||||
this.setState({ [key]: false } as any);
|
this.setState({ [key]: false } as any);
|
||||||
Alert.alert('绑定成功', msg);
|
Alert.alert('Bind Success', msg);
|
||||||
this.fetchWallets();
|
this.fetchWallets();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.setState({ [key]: false } as any);
|
this.setState({ [key]: false } as any);
|
||||||
Alert.alert('绑定失败', (error as Error).message);
|
Alert.alert('Bind Failed', (error as Error).message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
|
|
||||||
if (showPaytmPersonalBind && paytmPersonalBindType === 'tokenMode') return (
|
if (showPaytmPersonalBind && paytmPersonalBindType === 'tokenMode') return (
|
||||||
<Modal visible transparent onRequestClose={close('showPaytmPersonalBind')}>
|
<Modal visible transparent onRequestClose={close('showPaytmPersonalBind')}>
|
||||||
<PaytmPersonalBind processString="Processing..." isDebug onSuccess={this.handleBindSuccess('showPaytmPersonalBind', 'Paytm Personal 绑定成功') as any} onError={(e: string) => { Alert.alert('绑定失败', e); close('showPaytmPersonalBind')(); }} />
|
<PaytmPersonalBind processString="Processing..." isDebug onSuccess={this.handleBindSuccess('showPaytmPersonalBind', 'Paytm Personal bound successfully') as any} onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPaytmPersonalBind')(); }} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
if (showPaytmPersonalBind) return (
|
if (showPaytmPersonalBind) return (
|
||||||
@@ -301,14 +301,14 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
<PayTmPersonalOTPBind isDebug
|
<PayTmPersonalOTPBind isDebug
|
||||||
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile, {}); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile, {}); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onSuccess={(r: PaytmPersonalBindResult) => { Alert.alert('绑定成功', 'Paytm Personal OTP'); this.setState({ showPaytmPersonalBind: false }); this.fetchWallets(); }}
|
onSuccess={(r: PaytmPersonalBindResult) => { Alert.alert('Bind Success', 'Paytm Personal OTP'); this.setState({ showPaytmPersonalBind: false }); this.fetchWallets(); }}
|
||||||
onError={(e: string) => { Alert.alert('绑定失败', e); close('showPaytmPersonalBind')(); }}
|
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPaytmPersonalBind')(); }}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
if (showPhonePePersonalBind && phonePePersonalBindType === 'tokenMode') return (
|
if (showPhonePePersonalBind && phonePePersonalBindType === 'tokenMode') return (
|
||||||
<Modal visible transparent onRequestClose={close('showPhonePePersonalBind')}>
|
<Modal visible transparent onRequestClose={close('showPhonePePersonalBind')}>
|
||||||
<PhonePePersonalBind processString="Processing..." isDebug onSuccess={this.handleBindSuccess('showPhonePePersonalBind', 'PhonePe Personal 绑定成功') as any} onError={(e: string) => { Alert.alert('绑定失败', e); close('showPhonePePersonalBind')(); }} />
|
<PhonePePersonalBind processString="Processing..." isDebug onSuccess={this.handleBindSuccess('showPhonePePersonalBind', 'PhonePe Personal bound successfully') as any} onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPhonePePersonalBind')(); }} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
if (showPhonePePersonalBind) return (
|
if (showPhonePePersonalBind) return (
|
||||||
@@ -316,8 +316,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
<PhonePePersonalOTPBind isDebug
|
<PhonePePersonalOTPBind isDebug
|
||||||
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile, {}); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile, {}); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onSuccess={(r: PhonePePersonalBindResult) => { Alert.alert('绑定成功', 'PhonePe Personal OTP'); this.setState({ showPhonePePersonalBind: false }); this.fetchWallets(); }}
|
onSuccess={(r: PhonePePersonalBindResult) => { Alert.alert('Bind Success', 'PhonePe Personal OTP'); this.setState({ showPhonePePersonalBind: false }); this.fetchWallets(); }}
|
||||||
onError={(e: string) => { Alert.alert('绑定失败', e); close('showPhonePePersonalBind')(); }}
|
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPhonePePersonalBind')(); }}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
@@ -326,16 +326,16 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
<PaytmBusinessOTPBind isDebug
|
<PaytmBusinessOTPBind isDebug
|
||||||
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile, { password: p.password }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile, { password: p.password }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onSuccess={this.handleBindSuccess('showPaytmBusinessBind', 'Paytm Business 绑定成功') as any}
|
onSuccess={this.handleBindSuccess('showPaytmBusinessBind', 'Paytm Business bound successfully') as any}
|
||||||
onError={(e: string) => { Alert.alert('绑定失败', e); close('showPaytmBusinessBind')(); }}
|
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPaytmBusinessBind')(); }}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
if (showPhonePeBusinessBind) return (
|
if (showPhonePeBusinessBind) return (
|
||||||
<Modal visible transparent onRequestClose={close('showPhonePeBusinessBind')}>
|
<Modal visible transparent onRequestClose={close('showPhonePeBusinessBind')}>
|
||||||
<PhonePeBusinessBind processString="Processing..." isDebug
|
<PhonePeBusinessBind processString="Processing..." isDebug
|
||||||
onSuccess={this.handleBindSuccess('showPhonePeBusinessBind', 'PhonePe Business 绑定成功') as any}
|
onSuccess={this.handleBindSuccess('showPhonePeBusinessBind', 'PhonePe Business bound successfully') as any}
|
||||||
onError={(e: string) => { Alert.alert('绑定失败', e); close('showPhonePeBusinessBind')(); }}
|
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPhonePeBusinessBind')(); }}
|
||||||
onRenderBottomView={({ showOtpInput, loading, formError, phone, otp, onPhoneChange, onOtpChange, onGetOtp, onSubmitOtp }) => (
|
onRenderBottomView={({ showOtpInput, loading, formError, phone, otp, onPhoneChange, onOtpChange, onGetOtp, onSubmitOtp }) => (
|
||||||
<View style={s.otpBar}>
|
<View style={s.otpBar}>
|
||||||
{!showOtpInput ? (<>
|
{!showOtpInput ? (<>
|
||||||
@@ -354,7 +354,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
);
|
);
|
||||||
if (showGooglePayBusinessBind) return (
|
if (showGooglePayBusinessBind) return (
|
||||||
<Modal visible transparent onRequestClose={close('showGooglePayBusinessBind')}>
|
<Modal visible transparent onRequestClose={close('showGooglePayBusinessBind')}>
|
||||||
<GooglePayBusinessBind processString="Processing..." isDebug onSuccess={this.handleBindSuccess('showGooglePayBusinessBind', 'GooglePay Business 绑定成功') as any} onError={(e: string) => { Alert.alert('绑定失败', e); close('showGooglePayBusinessBind')(); }} />
|
<GooglePayBusinessBind processString="Processing..." isDebug onSuccess={this.handleBindSuccess('showGooglePayBusinessBind', 'GooglePay Business bound successfully') as any} onError={(e: string) => { Alert.alert('Bind Failed', e); close('showGooglePayBusinessBind')(); }} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
if (showBharatPeBusinessBind) return (
|
if (showBharatPeBusinessBind) return (
|
||||||
@@ -362,8 +362,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
<BharatPeBusinessOTPBind isDebug
|
<BharatPeBusinessOTPBind isDebug
|
||||||
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onSuccess={this.handleBindSuccess('showBharatPeBusinessBind', 'BharatPe Business 绑定成功') as any}
|
onSuccess={this.handleBindSuccess('showBharatPeBusinessBind', 'BharatPe Business bound successfully') as any}
|
||||||
onError={(e: string) => { Alert.alert('绑定失败', e); close('showBharatPeBusinessBind')(); }}
|
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showBharatPeBusinessBind')(); }}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
@@ -372,8 +372,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
<MobikwikOTPBind isDebug deviceId={this.deviceId} tuneUserId={this.tuneUserId}
|
<MobikwikOTPBind isDebug deviceId={this.deviceId} tuneUserId={this.tuneUserId}
|
||||||
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile, { deviceId: p.deviceId, tuneUserId: p.tuneUserId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile, { deviceId: p.deviceId, tuneUserId: p.tuneUserId }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId, deviceId: p.deviceId, tuneUserId: p.tuneUserId, nid: p.nid }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId, deviceId: p.deviceId, tuneUserId: p.tuneUserId, nid: p.nid }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onSuccess={this.handleBindSuccess('showMobikwikPersonalBind', 'Mobikwik 绑定成功') as any}
|
onSuccess={this.handleBindSuccess('showMobikwikPersonalBind', 'Mobikwik bound successfully') as any}
|
||||||
onError={(e: string) => { Alert.alert('绑定失败', e); close('showMobikwikPersonalBind')(); }}
|
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showMobikwikPersonalBind')(); }}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
@@ -382,8 +382,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
<FreeChargeBind isDebug
|
<FreeChargeBind isDebug
|
||||||
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onRequestOTP={async (wt, p) => { try { return await Api.instance.requestOTP(wt, p.mobile); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { otpId: p.otpId, deviceId: p.deviceId, csrfId: p.csrfId, appFc: p.appFc }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
onVerifyOTP={async (wt, p) => { try { return await Api.instance.verifyOTP(wt, p.mobile, p.otp, { otpId: p.otpId, deviceId: p.deviceId, csrfId: p.csrfId, appFc: p.appFc }); } catch (e) { return { success: false, message: (e as Error).message }; } }}
|
||||||
onSuccess={this.handleBindSuccess('showFreechargePersonalBind', 'Freecharge 绑定成功') as any}
|
onSuccess={this.handleBindSuccess('showFreechargePersonalBind', 'Freecharge bound successfully') as any}
|
||||||
onError={(e: string) => { Alert.alert('绑定失败', e); close('showFreechargePersonalBind')(); }}
|
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showFreechargePersonalBind')(); }}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
@@ -420,7 +420,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
style={s.addModalBox}
|
style={s.addModalBox}
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
|
||||||
<Text style={s.addModalTitle}>选择钱包类型</Text>
|
<Text style={s.addModalTitle}>Select Wallet Type</Text>
|
||||||
<TouchableOpacity onPress={() => this.setState({ showAddWallet: false })}>
|
<TouchableOpacity onPress={() => this.setState({ showAddWallet: false })}>
|
||||||
<Text style={{ fontSize: 20, color: '#999' }}>✕</Text>
|
<Text style={{ fontSize: 20, color: '#999' }}>✕</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@@ -452,7 +452,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
<Modal visible={showServerSettings} transparent animationType="fade">
|
<Modal visible={showServerSettings} transparent animationType="fade">
|
||||||
<View style={s.modalOverlay}>
|
<View style={s.modalOverlay}>
|
||||||
<View style={s.settingsBox}>
|
<View style={s.settingsBox}>
|
||||||
<Text style={s.settingsTitle}>服务器设置</Text>
|
<Text style={s.settingsTitle}>Server Settings</Text>
|
||||||
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 6, marginBottom: 14 }}>
|
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 6, marginBottom: 14 }}>
|
||||||
{presets.map(p => (
|
{presets.map(p => (
|
||||||
<TouchableOpacity key={p.label} onPress={() => this.setState({ settingsHost: p.host, settingsPort: p.port })}
|
<TouchableOpacity key={p.label} onPress={() => this.setState({ settingsHost: p.host, settingsPort: p.port })}
|
||||||
@@ -467,16 +467,16 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
<TextInput style={[s.textInput, { marginBottom: 20 }]} value={settingsPort} onChangeText={t => this.setState({ settingsPort: t })} placeholder="16000" keyboardType="number-pad" />
|
<TextInput style={[s.textInput, { marginBottom: 20 }]} value={settingsPort} onChangeText={t => this.setState({ settingsPort: t })} placeholder="16000" keyboardType="number-pad" />
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'flex-end' }}>
|
<View style={{ flexDirection: 'row', justifyContent: 'flex-end' }}>
|
||||||
<TouchableOpacity onPress={() => this.setState({ showServerSettings: false })} style={{ paddingHorizontal: 16, paddingVertical: 8, marginRight: 10 }}>
|
<TouchableOpacity onPress={() => this.setState({ showServerSettings: false })} style={{ paddingHorizontal: 16, paddingVertical: 8, marginRight: 10 }}>
|
||||||
<Text style={{ color: '#666' }}>取消</Text>
|
<Text style={{ color: '#666' }}>Cancel</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={async () => {
|
<TouchableOpacity onPress={async () => {
|
||||||
const { settingsHost, settingsPort } = this.state;
|
const { settingsHost, settingsPort } = this.state;
|
||||||
const domain = settingsPort ? `${settingsHost}:${settingsPort}` : settingsHost;
|
const domain = settingsPort ? `${settingsHost}:${settingsPort}` : settingsHost;
|
||||||
await saveServerDomain(domain, settingsPort === '443');
|
await saveServerDomain(domain, settingsPort === '443');
|
||||||
this.setState({ showServerSettings: false });
|
this.setState({ showServerSettings: false });
|
||||||
Alert.alert('已保存', '重启 App 后生效');
|
Alert.alert('Saved', 'Restart app to take effect');
|
||||||
}} style={s.saveBtn}>
|
}} style={s.saveBtn}>
|
||||||
<Text style={{ color: '#fff', fontWeight: 'bold' }}>保存</Text>
|
<Text style={{ color: '#fff', fontWeight: 'bold' }}>Save</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@@ -522,14 +522,14 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
useNativeDriver
|
useNativeDriver
|
||||||
style={s.vpaModalBox}
|
style={s.vpaModalBox}
|
||||||
>
|
>
|
||||||
<Text style={s.vpaModalTitle}>选择 VPA</Text>
|
<Text style={s.vpaModalTitle}>Select VPA</Text>
|
||||||
<Text style={s.vpaModalSub}>{vpaModalWallet?.phone}</Text>
|
<Text style={s.vpaModalSub}>{vpaModalWallet?.phone}</Text>
|
||||||
|
|
||||||
<ScrollView style={s.vpaModalList} bounces={false}>
|
<ScrollView style={s.vpaModalList} bounces={false}>
|
||||||
{vpaModalLoading
|
{vpaModalLoading
|
||||||
? <ActivityIndicator size="large" color={color} style={{ marginVertical: 28 }} />
|
? <ActivityIndicator size="large" color={color} style={{ marginVertical: 28 }} />
|
||||||
: vpaModalVpas.length === 0
|
: vpaModalVpas.length === 0
|
||||||
? <Text style={{ color: '#aaa', textAlign: 'center', marginVertical: 28 }}>无 VPA 数据</Text>
|
? <Text style={{ color: '#aaa', textAlign: 'center', marginVertical: 28 }}>No VPA data</Text>
|
||||||
: vpaModalVpas.map(vpa => {
|
: vpaModalVpas.map(vpa => {
|
||||||
const selected = vpa === vpaModalSelected;
|
const selected = vpa === vpaModalSelected;
|
||||||
return (
|
return (
|
||||||
@@ -551,14 +551,14 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
|
|
||||||
<View style={s.vpaModalFooter}>
|
<View style={s.vpaModalFooter}>
|
||||||
<TouchableOpacity style={s.vpaModalCancelBtn} onPress={this.closeVpaModal}>
|
<TouchableOpacity style={s.vpaModalCancelBtn} onPress={this.closeVpaModal}>
|
||||||
<Text style={{ color: '#666', fontSize: 15 }}>取消</Text>
|
<Text style={{ color: '#666', fontSize: 15 }}>Cancel</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[s.vpaModalConfirmBtn, { backgroundColor: vpaModalSelected ? color : '#ccc' }]}
|
style={[s.vpaModalConfirmBtn, { backgroundColor: vpaModalSelected ? color : '#ccc' }]}
|
||||||
onPress={this.confirmVpa}
|
onPress={this.confirmVpa}
|
||||||
disabled={!vpaModalSelected}
|
disabled={!vpaModalSelected}
|
||||||
>
|
>
|
||||||
<Text style={{ color: '#fff', fontSize: 15, fontWeight: '600' }}>确认</Text>
|
<Text style={{ color: '#fff', fontSize: 15, fontWeight: '600' }}>Confirm</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</Animatable.View>
|
</Animatable.View>
|
||||||
@@ -570,22 +570,22 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
render() {
|
render() {
|
||||||
const { proxyStatus, proxyError, wallets, loadingWallets } = this.state;
|
const { proxyStatus, proxyError, wallets, loadingWallets } = this.state;
|
||||||
const proxyCfg: Record<string, { label: string; color: string }> = {
|
const proxyCfg: Record<string, { label: string; color: string }> = {
|
||||||
idle: { label: '未连接', color: '#95a5a6' },
|
idle: { label: 'Idle', color: '#95a5a6' },
|
||||||
connecting: { label: '连接中…', color: '#f39c12' },
|
connecting: { label: 'Connecting…', color: '#f39c12' },
|
||||||
connected: { label: '已连接', color: '#2ecc71' },
|
connected: { label: 'Connected', color: '#2ecc71' },
|
||||||
disconnected: { label: '已断开', color: '#e74c3c' },
|
disconnected: { label: 'Disconnected', color: '#e74c3c' },
|
||||||
error: { label: '连接失败', color: '#e74c3c' },
|
error: { label: 'Error', color: '#e74c3c' },
|
||||||
};
|
};
|
||||||
const { label, color } = proxyCfg[proxyStatus];
|
const { label, color } = proxyCfg[proxyStatus];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={s.container}>
|
<View style={s.container}>
|
||||||
{/* 顶栏 */}
|
{/* top bar */}
|
||||||
<View style={s.topBar}>
|
<View style={s.topBar}>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||||
<View style={{ width: 8, height: 8, borderRadius: 4, backgroundColor: color, marginRight: 6 }} />
|
<View style={{ width: 8, height: 8, borderRadius: 4, backgroundColor: color, marginRight: 6 }} />
|
||||||
<Text style={{ color, fontSize: 13 }}>
|
<Text style={{ color, fontSize: 13 }}>
|
||||||
Proxy {label}{proxyStatus === 'error' && proxyError ? `:${proxyError}` : ''}
|
Proxy {label}{proxyStatus === 'error' && proxyError ? `: ${proxyError}` : ''}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
|
||||||
@@ -608,11 +608,11 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 钱包列表 */}
|
{/* wallet list */}
|
||||||
<View style={s.listHeader}>
|
<View style={s.listHeader}>
|
||||||
<Text style={s.listHeaderText}>已绑定钱包</Text>
|
<Text style={s.listHeaderText}>Bound Wallets</Text>
|
||||||
<TouchableOpacity onPress={this.fetchWallets} disabled={loadingWallets}>
|
<TouchableOpacity onPress={this.fetchWallets} disabled={loadingWallets}>
|
||||||
<Text style={{ fontSize: 13, color: '#3498db' }}>{loadingWallets ? '刷新中…' : '刷新'}</Text>
|
<Text style={{ fontSize: 13, color: '#3498db' }}>{loadingWallets ? 'Refreshing…' : 'Refresh'}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -624,7 +624,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
|||||||
renderItem={this.renderWalletItem}
|
renderItem={this.renderWalletItem}
|
||||||
ListEmptyComponent={
|
ListEmptyComponent={
|
||||||
<View style={{ alignItems: 'center', marginTop: 60 }}>
|
<View style={{ alignItems: 'center', marginTop: 60 }}>
|
||||||
<Text style={{ color: '#aaa', fontSize: 14 }}>{loadingWallets ? '加载中…' : '暂无绑定钱包,点右上角 + Add 添加'}</Text>
|
<Text style={{ color: '#aaa', fontSize: 14 }}>{loadingWallets ? 'Loading…' : 'No wallets. Tap + Add to get started.'}</Text>
|
||||||
</View>
|
</View>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ interface Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MOCK_MESSAGES: Message[] = [
|
const MOCK_MESSAGES: Message[] = [
|
||||||
{ id: '1', title: '系统通知', content: '欢迎使用 RNPay,绑定钱包开始使用。', time: '10:00' },
|
{ id: '1', title: 'System Notification', content: 'Welcome to RNPay. Bind a wallet to get started.', time: '10:00' },
|
||||||
{ id: '2', title: '代理连接', content: '代理服务已成功连接到服务器。', time: '10:05' },
|
{ id: '2', title: 'Proxy Connected', content: 'Proxy service connected to server successfully.', time: '10:05' },
|
||||||
{ id: '3', title: '绑定提醒', content: '您有钱包待绑定,请前往首页操作。', time: '10:10' },
|
{ id: '3', title: 'Bind Reminder', content: 'You have wallets pending setup. Go to Home to bind them.', time: '10:10' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default class MessageScreen extends Component {
|
export default class MessageScreen extends Component {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default function TestScreen() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
subRef.current = onProxyMessage((msg) => {
|
subRef.current = onProxyMessage((msg) => {
|
||||||
if (msg.type === 'echo') {
|
if (msg.type === 'echo') {
|
||||||
Alert.alert('Echo 回来了', JSON.stringify(msg.data));
|
Alert.alert('Echo Response', JSON.stringify(msg.data));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return () => {
|
return () => {
|
||||||
@@ -20,7 +20,7 @@ export default function TestScreen() {
|
|||||||
const handlePaytmPay = () => {
|
const handlePaytmPay = () => {
|
||||||
paytmPay('100', 'Gurvir singh', '296001000405', 'ICIC0002960', 'ABCDEF')
|
paytmPay('100', 'Gurvir singh', '296001000405', 'ICIC0002960', 'ABCDEF')
|
||||||
.then(result => console.log(result))
|
.then(result => console.log(result))
|
||||||
.catch(error => Alert.alert('代付失败', String(error)));
|
.catch(error => Alert.alert('Transfer Failed', String(error)));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEcho = () => {
|
const handleEcho = () => {
|
||||||
@@ -29,30 +29,30 @@ export default function TestScreen() {
|
|||||||
|
|
||||||
const handlePaytmMagicPackage = () => {
|
const handlePaytmMagicPackage = () => {
|
||||||
isModifiedAppInstalled('iwpaytmgtk')
|
isModifiedAppInstalled('iwpaytmgtk')
|
||||||
.then(installed => Alert.alert('Paytm 魔改包', installed ? '已安装' : '未安装'))
|
.then(installed => Alert.alert('Paytm Modified App', installed ? 'Installed' : 'Not Installed'))
|
||||||
.catch(err => Alert.alert('检测失败', String(err)));
|
.catch(err => Alert.alert('Check Failed', String(err)));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePhonePeMagicPackage = () => {
|
const handlePhonePeMagicPackage = () => {
|
||||||
isModifiedAppInstalled('iwphonepegtk')
|
isModifiedAppInstalled('iwphonepegtk')
|
||||||
.then(installed => Alert.alert('PhonePe 魔改包', installed ? '已安装' : '未安装'))
|
.then(installed => Alert.alert('PhonePe Modified App', installed ? 'Installed' : 'Not Installed'))
|
||||||
.catch(err => Alert.alert('检测失败', String(err)));
|
.catch(err => Alert.alert('Check Failed', String(err)));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Text style={styles.sectionTitle}>测试工具</Text>
|
<Text style={styles.sectionTitle}>Test Tools</Text>
|
||||||
<TouchableOpacity style={[styles.btn, { backgroundColor: '#2ecc71' }]} onPress={handlePaytmPay}>
|
<TouchableOpacity style={[styles.btn, { backgroundColor: '#2ecc71' }]} onPress={handlePaytmPay}>
|
||||||
<Text style={styles.btnText}>Paytm Pay 代付测试</Text>
|
<Text style={styles.btnText}>Paytm Pay Transfer Test</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={[styles.btn, { backgroundColor: '#3498db' }]} onPress={handleEcho}>
|
<TouchableOpacity style={[styles.btn, { backgroundColor: '#3498db' }]} onPress={handleEcho}>
|
||||||
<Text style={styles.btnText}>Echo 测试</Text>
|
<Text style={styles.btnText}>Echo Test</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={[styles.btn, { backgroundColor: '#3498db' }]} onPress={handlePaytmMagicPackage}>
|
<TouchableOpacity style={[styles.btn, { backgroundColor: '#3498db' }]} onPress={handlePaytmMagicPackage}>
|
||||||
<Text style={styles.btnText}>Paytm 魔改包检测是否安装</Text>
|
<Text style={styles.btnText}>Check Paytm Modified App</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={[styles.btn, { backgroundColor: '#3498db' }]} onPress={handlePhonePeMagicPackage}>
|
<TouchableOpacity style={[styles.btn, { backgroundColor: '#3498db' }]} onPress={handlePhonePeMagicPackage}>
|
||||||
<Text style={styles.btnText}>PhonePe 魔改包检测是否安装</Text>
|
<Text style={styles.btnText}>Check PhonePe Modified App</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|||||||
Submodule servers/walletman updated: 82bbbe9a31...366576ca6e
4
types.ts
4
types.ts
@@ -23,11 +23,11 @@ export interface WalletmanAppState {
|
|||||||
/* Freecharge Personal */
|
/* Freecharge Personal */
|
||||||
showFreechargePersonalBind: boolean;
|
showFreechargePersonalBind: boolean;
|
||||||
|
|
||||||
/* Proxy 状态 */
|
/* Proxy status */
|
||||||
proxyStatus: 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error';
|
proxyStatus: 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error';
|
||||||
proxyError?: string;
|
proxyError?: string;
|
||||||
|
|
||||||
/* Server 设置 */
|
/* Server settings */
|
||||||
showServerSettings: boolean;
|
showServerSettings: boolean;
|
||||||
settingsHost: string;
|
settingsHost: string;
|
||||||
settingsPort: string;
|
settingsPort: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user