Compare commits
8 Commits
bb215fd492
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c42d89d585 | |||
| cc6a4443ee | |||
| 9477c1fed0 | |||
| a113805b51 | |||
| 2f4241951d | |||
| 57928cd97d | |||
| 0db8a9254a | |||
| d0f60b5ece |
91
App.tsx
91
App.tsx
@@ -29,10 +29,8 @@ import {
|
|||||||
PhonePePersonalBind,
|
PhonePePersonalBind,
|
||||||
SmsMessage,
|
SmsMessage,
|
||||||
NotificationMessage,
|
NotificationMessage,
|
||||||
proxyManager,
|
proxyBackgroundService,
|
||||||
} from "rnwalletman";
|
} from "rnwalletman";
|
||||||
import BarcodeScanning from '@react-native-ml-kit/barcode-scanning';
|
|
||||||
import RNFS from 'react-native-fs';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FreeChargeBind,
|
FreeChargeBind,
|
||||||
@@ -71,18 +69,21 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
// 先登录获取 userId
|
|
||||||
try {
|
|
||||||
const userId = await Api.instance.login('test123', '123456');
|
|
||||||
console.log('[登录成功] userId:', userId);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[登录失败]', error);
|
|
||||||
Alert.alert('登录失败', String(error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.setupPermissions();
|
await this.setupPermissions();
|
||||||
await this.initProxyClient();
|
|
||||||
|
// Login with auto-retry every 3s until success (setTimeout, non-blocking)
|
||||||
|
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);
|
this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,11 +95,9 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
|||||||
|
|
||||||
handleAppStateChange = (nextAppState: AppStateStatus) => {
|
handleAppStateChange = (nextAppState: AppStateStatus) => {
|
||||||
if (nextAppState === 'background' || nextAppState === 'inactive') {
|
if (nextAppState === 'background' || nextAppState === 'inactive') {
|
||||||
console.log('[AppState] 应用进入后台,关闭代理');
|
console.log('[AppState] 应用进入后台,代理服务继续运行');
|
||||||
this.stopProxyClient();
|
|
||||||
} else if (nextAppState === 'active') {
|
} else if (nextAppState === 'active') {
|
||||||
console.log('[AppState] 应用回到前台,重连代理');
|
console.log('[AppState] 应用回到前台');
|
||||||
this.initProxyClient();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,32 +120,30 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async initProxyClient() {
|
async startProxyClient() {
|
||||||
try {
|
try {
|
||||||
this.clientId = DeviceInfo.getUniqueIdSync();
|
this.clientId = DeviceInfo.getUniqueIdSync();
|
||||||
const userId = Api.instance.getUserId();
|
const userId = Api.instance.getUserId();
|
||||||
console.log('[Proxy] 初始化客户端:', this.clientId, 'userId:', userId);
|
const { clientId } = this;
|
||||||
|
console.log('[Proxy] 初始化后台服务:', clientId, 'userId:', userId);
|
||||||
|
|
||||||
await proxyManager.start({
|
await proxyBackgroundService.start({
|
||||||
wsUrl: 'ws://192.168.1.117:16001/ws',
|
wsUrl: Api.WS_URL,
|
||||||
clientId: this.clientId || '',
|
clientId: this.clientId || '',
|
||||||
userId: userId,
|
userId: userId,
|
||||||
debug: true,
|
// debug: true,
|
||||||
heartbeatInterval: 10000,
|
heartbeatInterval: 10000,
|
||||||
reconnectInterval: 5000,
|
reconnectInterval: 5000,
|
||||||
reconnectMaxAttempts: 3,
|
reconnectMaxAttempts: Infinity,
|
||||||
onConnected: () => {
|
onConnected: () => {
|
||||||
console.log('[Proxy] 客户端已连接');
|
console.log('[Proxy] 后台服务已连接');
|
||||||
},
|
},
|
||||||
onDisconnected: () => {
|
onDisconnected: () => {
|
||||||
console.log('[Proxy] 客户端已断开');
|
console.log('[Proxy] 后台服务已断开');
|
||||||
},
|
},
|
||||||
onError: (error: string) => {
|
onError: (error: string) => {
|
||||||
console.warn('[Proxy] 错误:', error);
|
console.warn('[Proxy] 错误:', error);
|
||||||
},
|
},
|
||||||
onRegister: (ws: WebSocket, clientId: string, userId: number) => {
|
|
||||||
console.log('[Proxy] 客户端已注册:', clientId, userId);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Proxy] 初始化失败:', error);
|
console.error('[Proxy] 初始化失败:', error);
|
||||||
@@ -155,32 +152,19 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
|||||||
|
|
||||||
stopProxyClient() {
|
stopProxyClient() {
|
||||||
try {
|
try {
|
||||||
proxyManager.stop();
|
proxyBackgroundService.stop();
|
||||||
console.log('[Proxy] 客户端已断开');
|
console.log('[Proxy] 后台服务已停止');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Proxy] 断开失败:', error);
|
console.error('[Proxy] 停止失败:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
decodeQRFromUrl = async (url: string) => {
|
|
||||||
const localPath = `${RNFS.CachesDirectoryPath}/temp_qr_${Date.now()}.jpg`;
|
|
||||||
try {
|
|
||||||
await RNFS.downloadFile({ fromUrl: url, toFile: localPath }).promise;
|
|
||||||
const barcodes = await BarcodeScanning.scan(`file://${localPath}`);
|
|
||||||
if (barcodes.length > 0) return barcodes[0].value;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Paytm Personal
|
// Paytm Personal
|
||||||
handleUploadPaytmPersonalToken = async (result: PaytmPersonalBindResult) => {
|
handleUploadPaytmPersonalToken = async (result: PaytmPersonalBindResult) => {
|
||||||
try {
|
try {
|
||||||
console.log(result);
|
console.log(result);
|
||||||
await Api.instance.register(WalletType.PAYTM_PERSONAL, result);
|
await Api.instance.register(WalletType.PAYTM_PERSONAL, result);
|
||||||
this.setState({ showPaytmPersonalBind: false });
|
this.setState({ showPaytmPersonalBind: false });
|
||||||
console.log('绑定成功', 'Paytm Personal Token 绑定成功');
|
|
||||||
Alert.alert('绑定成功', 'Paytm Personal Token 绑定成功');
|
Alert.alert('绑定成功', 'Paytm Personal Token 绑定成功');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Alert.alert('绑定失败', (error as Error).message);
|
Alert.alert('绑定失败', (error as Error).message);
|
||||||
@@ -189,11 +173,12 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PhonePe Personal
|
// PhonePe Personal
|
||||||
handleUploadPhonePePersonal = async (result: PhonePePersonalBindResult) => {
|
handleUploadPhonePePersonalToken = async (result: PhonePePersonalBindResult) => {
|
||||||
try {
|
try {
|
||||||
console.log(result);
|
console.log('PhonePe Personal Token Data:', result);
|
||||||
await Api.instance.register(WalletType.PHONEPE_PERSONAL, result);
|
await Api.instance.register(WalletType.PHONEPE_PERSONAL, result);
|
||||||
this.setState({ showPhonePePersonalBind: false });
|
this.setState({ showPhonePePersonalBind: false });
|
||||||
|
Alert.alert('绑定成功', 'PhonePe Personal Token 绑定成功');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Alert.alert('绑定失败', (error as Error).message);
|
Alert.alert('绑定失败', (error as Error).message);
|
||||||
this.setState({ showPhonePePersonalBind: false });
|
this.setState({ showPhonePePersonalBind: false });
|
||||||
@@ -240,8 +225,10 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
|||||||
handleUploadBharatPeBusiness = async (result: BharatPeBusinessBindResult) => {
|
handleUploadBharatPeBusiness = async (result: BharatPeBusinessBindResult) => {
|
||||||
try {
|
try {
|
||||||
console.log(result);
|
console.log(result);
|
||||||
await Api.instance.register(WalletType.BHARATPE_BUSINESS, result);
|
const response = await Api.instance.register(WalletType.BHARATPE_BUSINESS, result);
|
||||||
|
console.log(response);
|
||||||
this.setState({ showBharatPeBusinessBind: false });
|
this.setState({ showBharatPeBusinessBind: false });
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Alert.alert('绑定失败', (error as Error).message);
|
Alert.alert('绑定失败', (error as Error).message);
|
||||||
this.setState({ showBharatPeBusinessBind: false });
|
this.setState({ showBharatPeBusinessBind: false });
|
||||||
@@ -330,7 +317,7 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
|||||||
<PhonePePersonalBind
|
<PhonePePersonalBind
|
||||||
processString="Processing..."
|
processString="Processing..."
|
||||||
isDebug={true}
|
isDebug={true}
|
||||||
onSuccess={this.handleUploadPhonePePersonal}
|
onSuccess={this.handleUploadPhonePePersonalToken}
|
||||||
onError={(error: string) => {
|
onError={(error: string) => {
|
||||||
Alert.alert('绑定失败', error);
|
Alert.alert('绑定失败', error);
|
||||||
this.setState({ showPhonePePersonalBind: false });
|
this.setState({ showPhonePePersonalBind: false });
|
||||||
@@ -361,7 +348,11 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
|||||||
return { success: false, message: (error as Error).message };
|
return { success: false, message: (error as Error).message };
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onSuccess={this.handleUploadPhonePePersonal}
|
onSuccess={(result: PhonePePersonalBindResult) => {
|
||||||
|
console.log('[PhonePePersonal] OTP 绑定成功:', result);
|
||||||
|
Alert.alert('绑定成功', 'PhonePe Personal OTP 绑定成功');
|
||||||
|
this.setState({ showPhonePePersonalBind: false });
|
||||||
|
}}
|
||||||
onError={(error: string) => {
|
onError={(error: string) => {
|
||||||
Alert.alert('绑定失败', error);
|
Alert.alert('绑定失败', error);
|
||||||
this.setState({ showPhonePePersonalBind: false });
|
this.setState({ showPhonePePersonalBind: false });
|
||||||
|
|||||||
1
android/.idea/vcs.xml
generated
1
android/.idea/vcs.xml
generated
@@ -7,6 +7,7 @@
|
|||||||
<mapping directory="$PROJECT_DIR$/../libs/rnwalletman" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/../libs/rnwalletman" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/../node_modules/rnauto" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/../node_modules/rnauto" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/../node_modules/rnwalletman" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/../node_modules/rnwalletman" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/../servers/usdtman" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/../servers/walletman" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/../servers/walletman" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MainApplication"
|
android:name=".MainApplication"
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export class PhonePePersonalOTPBind extends Component<{
|
|||||||
<OTPBindUI
|
<OTPBindUI
|
||||||
walletType={WalletType.PHONEPE_PERSONAL}
|
walletType={WalletType.PHONEPE_PERSONAL}
|
||||||
title="PhonePe 绑定"
|
title="PhonePe 绑定"
|
||||||
otpLength={8}
|
otpLength={5}
|
||||||
onRequestOTP={this.props.onRequestOTP}
|
onRequestOTP={this.props.onRequestOTP}
|
||||||
onVerifyOTP={this.props.onVerifyOTP}
|
onVerifyOTP={this.props.onVerifyOTP}
|
||||||
onSuccess={this.props.onSuccess}
|
onSuccess={this.props.onSuccess}
|
||||||
|
|||||||
Submodule libs/rnwalletman updated: 0179dfbc68...9e984f0edd
@@ -7,7 +7,8 @@
|
|||||||
"ios": "react-native run-ios",
|
"ios": "react-native run-ios",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"start": "react-native start",
|
"start": "react-native start",
|
||||||
"test": "jest"
|
"test": "jest",
|
||||||
|
"postinstall": "patch-package"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-native-cookies/cookies": "^6.2.1",
|
"@react-native-cookies/cookies": "^6.2.1",
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-native": "0.72.10",
|
"react-native": "0.72.10",
|
||||||
|
"react-native-background-actions": "^4.0.1",
|
||||||
"react-native-device-info": "14.0.4",
|
"react-native-device-info": "14.0.4",
|
||||||
"react-native-fs": "^2.20.0",
|
"react-native-fs": "^2.20.0",
|
||||||
"react-native-tcp-socket": "^6.4.1",
|
"react-native-tcp-socket": "^6.4.1",
|
||||||
@@ -35,6 +37,7 @@
|
|||||||
"eslint": "^8.19.0",
|
"eslint": "^8.19.0",
|
||||||
"jest": "^29.2.1",
|
"jest": "^29.2.1",
|
||||||
"metro-react-native-babel-preset": "0.76.8",
|
"metro-react-native-babel-preset": "0.76.8",
|
||||||
|
"patch-package": "^8.0.1",
|
||||||
"prettier": "^2.4.1",
|
"prettier": "^2.4.1",
|
||||||
"react-test-renderer": "18.2.0",
|
"react-test-renderer": "18.2.0",
|
||||||
"typescript": "4.8.4"
|
"typescript": "4.8.4"
|
||||||
|
|||||||
15
patches/react-native-background-actions+4.0.1.patch
Normal file
15
patches/react-native-background-actions+4.0.1.patch
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
diff --git a/node_modules/react-native-background-actions/android/src/main/java/com/asterinet/react/bgactions/RNBackgroundActionsTask.java b/node_modules/react-native-background-actions/android/src/main/java/com/asterinet/react/bgactions/RNBackgroundActionsTask.java
|
||||||
|
index 9900fc0..d810b1c 100644
|
||||||
|
--- a/node_modules/react-native-background-actions/android/src/main/java/com/asterinet/react/bgactions/RNBackgroundActionsTask.java
|
||||||
|
+++ b/node_modules/react-native-background-actions/android/src/main/java/com/asterinet/react/bgactions/RNBackgroundActionsTask.java
|
||||||
|
@@ -41,8 +41,8 @@ final public class RNBackgroundActionsTask extends HeadlessJsTaskService {
|
||||||
|
notificationIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
|
||||||
|
}
|
||||||
|
final PendingIntent contentIntent;
|
||||||
|
- if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||||
|
- contentIntent = PendingIntent.getActivity(context,0, notificationIntent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT);
|
||||||
|
+ if (Build.VERSION.SDK_INT >= 34) { // Android 14 (UPSIDE_DOWN_CAKE)
|
||||||
|
+ contentIntent = PendingIntent.getActivity(context,0, notificationIntent, PendingIntent.FLAG_MUTABLE | 0x01000000); // FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_MUTABLE);
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
Submodule servers/walletman updated: ef6bc8907c...d85e65d275
@@ -1,7 +1,12 @@
|
|||||||
import { WalletType } from 'rnwalletman';
|
import { WalletType } from 'rnwalletman';
|
||||||
|
|
||||||
|
const DOMAIN = '192.168.0.101:16000';
|
||||||
|
const BASE_URL = `http://${DOMAIN}`;
|
||||||
|
const WS_URL = `ws://${DOMAIN}/ws`;
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
public static readonly BASE_URL = 'http://192.168.1.117:16000';
|
public static readonly BASE_URL = BASE_URL;
|
||||||
|
public static readonly WS_URL = WS_URL;
|
||||||
private static _instance: Api | null = null;
|
private static _instance: Api | null = null;
|
||||||
private userId: number = 0;
|
private userId: number = 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user