This commit is contained in:
2026-09-02 15:29:47 +08:00
parent 89f55cf884
commit bab8831732
7 changed files with 32 additions and 99 deletions
+1
View File
@@ -22,3 +22,4 @@ others
*.lock
**/fcm-service-account.json
**/firebase-adminsdk*.json
logs/googlepay_business
+3 -3
View File
@@ -11,8 +11,8 @@ import {
import { saveServerDomain } from '../services/api';
const PRESETS = [
{ label: '192.168.1.117:16000', host: '192.168.1.117', port: '16000' },
{ label: 'aa.pfgame.org', host: 'aa.pfgame.org', port: '443' },
{ label: '192.168.1.117:16000', host: '192.168.1.117', port: '16000' },
];
type Props = {
@@ -62,7 +62,7 @@ export const ServerSettingsModal: React.FC<Props> = ({
style={styles.textInput}
value={host}
onChangeText={onHostChange}
placeholder="192.168.1.117"
placeholder="aa.pfgame.org"
autoCapitalize="none"
/>
<Text style={styles.inputLabel}>Port</Text>
@@ -70,7 +70,7 @@ export const ServerSettingsModal: React.FC<Props> = ({
style={[styles.textInput, { marginBottom: 20 }]}
value={port}
onChangeText={onPortChange}
placeholder="16000"
placeholder="443"
keyboardType="number-pad"
/>
<View style={styles.actions}>
+14 -57
View File
@@ -18,7 +18,6 @@ import {
} from 'react-native';
import * as Animatable from 'react-native-animatable';
import DeviceInfo from 'react-native-device-info';
import CookieManager from '@react-native-cookies/cookies';
import {
GooglePayBusinessBind,
PhonePeBusinessBind,
@@ -65,11 +64,14 @@ import { buildWalletCardId } from '../utils/walletCardId';
/** ipay patch 期望,bind 与 ProxyService FCM 重绑共用 */
const PATCH_EXPECT: PatchConfig = {
chType: 'ipay',
paytmChVersion: '3',
paytmChVersion: '7',
phonepeChVersion: '2',
mobikwikChVersion: '1',
};
/** GooglePay Business 绑定时顶部「清除缓存」按钮 */
const GOOGLEPAY_BUSINESS_SHOW_CLEAR_CACHE = true;
function phonePePatchFailReason(chType?: string, chVersion?: string): string | null {
if (!chType || chType !== PATCH_EXPECT.chType) {
return 'Patched PhonePe app not installed. Reinstall required';
@@ -160,9 +162,6 @@ interface HomeScreenState {
mobikwikPersonalBindType: 'otpMode' | 'tokenMode';
showFreechargePersonalBind: boolean;
showAmazonPayPersonalBind: boolean;
/** WebView 绑定 remount key(清除 cookie 后递增) */
webViewBindKey: number;
webViewForceClearCookies: boolean;
// proxy
proxyStatus: 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error';
proxyError?: string;
@@ -214,8 +213,6 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
showFreechargePersonalBind: false,
freechargePersonalBindType: 'otpMode',
showAmazonPayPersonalBind: false,
webViewBindKey: 0,
webViewForceClearCookies: false,
proxyStatus: 'idle',
showServerSettings: false,
settingsHost: '',
@@ -512,30 +509,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
this.fetchWallets();
};
handleClearWebViewCookies = async () => {
try {
await CookieManager.clearAll();
this.setState((prev) => ({
webViewBindKey: prev.webViewBindKey + 1,
webViewForceClearCookies: true,
}));
Alert.alert('已清除', 'WebView 登录状态已清除,请重新登录');
} catch (e) {
Alert.alert('Error', (e as Error).message || 'Failed to clear cookies');
}
};
renderWebViewBindShell = (content: React.ReactNode) => (
<View style={s.webViewBindContainer}>
{content}
<TouchableOpacity
style={s.clearWebCookieBtn}
onPress={this.handleClearWebViewCookies}
activeOpacity={0.85}
>
<Text style={s.clearWebCookieBtnText}>清除 Web 登录</Text>
</TouchableOpacity>
</View>
<View style={s.webViewBindContainer}>{content}</View>
);
// ---- modals ----
@@ -546,8 +521,6 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
showPaytmBusinessBind, showPhonePeBusinessBind, phonePeBusinessBindType, showGooglePayBusinessBind, showBharatPeBusinessBind,
showMobikwikPersonalBind, mobikwikPersonalBindType, showFreechargePersonalBind, freechargePersonalBindType,
showAmazonPayPersonalBind,
webViewBindKey,
webViewForceClearCookies,
bindPrefillMobile,
} = this.state;
@@ -566,11 +539,12 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
processString="Processing..."
isDebug
onSuccess={(result: PaytmPersonalBindResult) => {
if (result.chType != chType) {
const isLongfafa = result.chType === 'longfafa';
if (!isLongfafa && result.chType != chType) {
Alert.alert('Bind Failed', 'Patched Paytm app not installed. Reinstall required');
return;
}
if (result.chVersion != remoteVersion) {
if (!isLongfafa && result.chVersion != remoteVersion) {
Alert.alert('Bind Failed', 'App version outdated. Reinstall required');
return;
}
@@ -765,10 +739,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
>
{this.renderWebViewBindShell(
<PhonePeBusinessBind
key={`phonepe-web-${webViewBindKey}`}
processString="Processing..."
isDebug
clearCookie={webViewForceClearCookies}
onSuccess={this.handleBindSuccess('showPhonePeBusinessBind', WalletType.PHONEPE_BUSINESS, 'PhonePe Business bound successfully') as any}
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPhonePeBusinessBind')(); }}
/>,
@@ -785,11 +757,13 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
>
{this.renderWebViewBindShell(
<GooglePayBusinessBind
key={`gpay-web-${webViewBindKey}`}
processString="Processing..."
isDebug
clearCookie={webViewForceClearCookies}
onSuccess={this.handleBindSuccess('showGooglePayBusinessBind', WalletType.GOOGLEPAY_BUSINESS, 'GooglePay Business bound successfully') as any}
showClearCacheButton={GOOGLEPAY_BUSINESS_SHOW_CLEAR_CACHE}
onSuccess={(result: GooglePayBusinessBindResult) => {
console.log('GooglePayBusinessBindResult', result);
this.handleBindSuccess('showGooglePayBusinessBind', WalletType.GOOGLEPAY_BUSINESS, 'GooglePay Business bound successfully')(result);
}}
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showGooglePayBusinessBind')(); }}
/>,
)}
@@ -938,10 +912,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
>
{this.renderWebViewBindShell(
<AmazonPayPersonalBind
key={`amazon-web-${webViewBindKey}`}
processString="Processing..."
isDebug
clearCookie={webViewForceClearCookies}
onSuccess={this.handleBindSuccess('showAmazonPayPersonalBind', WalletType.AMAZONPAY_PERSONAL, 'Amazon Pay bound successfully') as any}
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showAmazonPayPersonalBind')(); }}
/>,
@@ -955,7 +927,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
openWalletBind = (key: string, prefillMobile?: string, cardId?: string) => {
// 若从外部明确指定 cardId 则覆盖,否则保留之前 handleRebind 设的值
if (cardId !== undefined) this._pendingCardId = cardId;
this.setState({ showAddWallet: false, bindPrefillMobile: prefillMobile ?? '', webViewForceClearCookies: false });
this.setState({ showAddWallet: false, bindPrefillMobile: prefillMobile ?? '' });
setTimeout(() => {
switch (key) {
case 'paytm_personal_otp':
@@ -1542,19 +1514,4 @@ const s = StyleSheet.create({
flex: 1,
backgroundColor: '#fff',
},
clearWebCookieBtn: {
position: 'absolute',
top: Platform.OS === 'ios' ? 48 : 12,
right: 12,
zIndex: 1000,
backgroundColor: 'rgba(0,0,0,0.55)',
paddingHorizontal: 12,
paddingVertical: 8,
borderRadius: 8,
},
clearWebCookieBtnText: {
color: '#fff',
fontSize: 12,
fontWeight: '600',
},
});
+10 -35
View File
@@ -17,7 +17,6 @@ import {
openMobikwikPayToBank,
openPhonePePayToBank,
openFreechargePayToBank,
buildFreechargePayToBankDeeplink,
openAmazonPayPayToBank,
FreechargePersonalBind,
FreechargePersonalBindResult,
@@ -85,6 +84,15 @@ const PAYEES: Payee[] = [
amount: '3',
comment: '1234',
},
{
id: 'idbi-demo',
label: 'IDBI demo',
name: 'Test User',
account: '8910888450@nyes',
ifsc: 'IDIB000K548',
amount: '2',
comment: 'test',
},
];
const PAY_PROVIDERS: { id: PayProvider; label: string; color: string }[] = [
@@ -145,11 +153,7 @@ export default function TestScreen() {
const handlePay = async () => {
try {
if (selectedProvider === 'freecharge') {
const deeplink = buildFreechargePayToBankDeeplink(
selectedPayee.account,
selectedPayee.ifsc,
);
console.log('[TestScreen] Freecharge deeplink:', deeplink);
console.log('[TestScreen] Freecharge account:', selectedPayee.account);
}
const ok = await launchPay(selectedProvider, selectedPayee);
if (!ok) {
@@ -256,35 +260,6 @@ export default function TestScreen() {
<TouchableOpacity style={[styles.btn, { backgroundColor: '#3498db' }]} onPress={handleEcho}>
<Text style={styles.btnText}>Echo Test</Text>
</TouchableOpacity>
<Modal
visible={showFcAuth}
transparent
animationType="fade"
statusBarTranslucent
onRequestClose={() => setShowFcAuth(false)}
>
<View style={styles.modalRoot}>
{apiBaseUrl ? (
<FreechargePersonalBind
apiBaseUrl={apiBaseUrl}
isDebug
userId={Api.instance.getUserId()}
processString="Waiting for Freecharge authorization…"
onClose={() => setShowFcAuth(false)}
onSuccess={handleFcAuthSuccess}
onError={msg => {
Alert.alert('Freecharge Auth Failed', msg);
}}
/>
) : (
<View style={styles.loadingBox}>
<ActivityIndicator size="large" color="#fff" />
<Text style={[styles.btnText, { marginTop: 12 }]}>Loading server URL…</Text>
</View>
)}
</View>
</Modal>
</ScrollView>
);
}
+2 -2
View File
@@ -10,12 +10,12 @@ export interface WalletItem {
otpMode?: boolean;
}
const DEFAULT_DOMAIN = '192.168.1.117:16000';
const DEFAULT_DOMAIN = 'aa.pfgame.org';
const STORAGE_KEY = 'server_domain';
const HTTPS_KEY = 'server_https';
let _domain = DEFAULT_DOMAIN;
let _useHttps = false;
let _useHttps = true;
export async function loadServerDomain(): Promise<string> {
const saved = await AsyncStorage.getItem(STORAGE_KEY);