bharatpe business 改为 otp 模式 ,去除 web 的抓取

This commit is contained in:
2026-03-11 12:09:01 +08:00
parent ef35ef3364
commit 8a104b3e7f
3 changed files with 157 additions and 12 deletions

140
App.tsx
View File

@@ -1,11 +1,10 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Alert, AppState, AppStateStatus, Modal, Text, TouchableOpacity, View } from "react-native"; import { Alert, AppState, AppStateStatus, Modal, Text, TextInput, TouchableOpacity, View } from "react-native";
import DeviceInfo from 'react-native-device-info'; import DeviceInfo from 'react-native-device-info';
import { import {
PaytmBusinessBind, PaytmBusinessBind,
PhonePeBusinessBind, PhonePeBusinessBind,
GooglePayBusinessBind, GooglePayBusinessBind,
BharatPeBusinessBind,
WalletType, WalletType,
PaytmBusinessBindResult, PaytmBusinessBindResult,
PhonePeBusinessBindResult, PhonePeBusinessBindResult,
@@ -32,12 +31,14 @@ import {
FreeChargeBind, FreeChargeBind,
MobikwikOTPBind, MobikwikOTPBind,
PayTmPersonalOTPBind, PayTmPersonalOTPBind,
PhonePePersonalOTPBind PhonePePersonalOTPBind,
BharatPeBusinessOTPBind,
} from './components/WalletBindComponents'; } from './components/WalletBindComponents';
import Api from './services/api'; import Api from './services/api';
import { AppProps, WalletmanAppState } from './types'; import { AppProps, WalletmanAppState } from './types';
import { styles } from './styles'; import { styles } from './styles';
import WebView from "react-native-webview";
export default class App extends Component<AppProps, WalletmanAppState> { export default class App extends Component<AppProps, WalletmanAppState> {
private deviceId: string; private deviceId: string;
@@ -45,6 +46,8 @@ export default class App extends Component<AppProps, WalletmanAppState> {
private clientId: string = ''; private clientId: string = '';
private appStateSubscription?: any; private appStateSubscription?: any;
private webViewRef: WebView | null = null;
constructor(props: AppProps) { constructor(props: AppProps) {
super(props); super(props);
this.state = { this.state = {
@@ -234,11 +237,9 @@ export default class App extends Component<AppProps, WalletmanAppState> {
// BharatPe Business // BharatPe Business
handleUploadBharatPeBusiness = async (result: BharatPeBusinessBindResult) => { handleUploadBharatPeBusiness = async (result: BharatPeBusinessBindResult) => {
try { try {
console.log(result); console.log(JSON.stringify(result));
const response = await Api.instance.register(WalletType.BHARATPE_BUSINESS, result);
console.log(response);
this.setState({ showBharatPeBusinessBind: false }); this.setState({ showBharatPeBusinessBind: false });
Alert.alert('绑定成功', 'BharatPe Business 绑定成功');
} catch (error) { } catch (error) {
Alert.alert('绑定失败', (error as Error).message); Alert.alert('绑定失败', (error as Error).message);
this.setState({ showBharatPeBusinessBind: false }); this.setState({ showBharatPeBusinessBind: false });
@@ -423,9 +424,24 @@ export default class App extends Component<AppProps, WalletmanAppState> {
renderBharatPeBusinessBind = () => { renderBharatPeBusinessBind = () => {
return ( return (
<Modal visible transparent onRequestClose={() => this.setState({ showBharatPeBusinessBind: false })}> <Modal visible transparent onRequestClose={() => this.setState({ showBharatPeBusinessBind: false })}>
<BharatPeBusinessBind <BharatPeBusinessOTPBind
processString="Processing..."
isDebug={true} isDebug={true}
onRequestOTP={async (walletType, params) => {
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} onSuccess={this.handleUploadBharatPeBusiness}
onError={(error: string) => { onError={(error: string) => {
Alert.alert('绑定失败', error); Alert.alert('绑定失败', error);
@@ -560,7 +576,113 @@ export default class App extends Component<AppProps, WalletmanAppState> {
return null; return null;
} }
renderWebDemo() {
const handleMessage = (event: any) => {
try {
const data = JSON.parse(event.nativeEvent.data);
if (data.type === 'iframe_message') {
console.log('[Demo] iframe message:', data.data);
}
} catch (e) {
console.error('[Demo] Parse error:', e);
}
};
const syncToIframe = (fieldId: string, value: string) => {
const js = `
window.postMessage({
type: 'set_field',
fieldId: '${fieldId}',
value: '${value.replace(/'/g, "\\'")}'
}, '*');
`;
this.webViewRef?.injectJavaScript(js);
};
const clickLogin = () => {
const js = `window.postMessage({type: 'click_login'}, '*');`;
this.webViewRef?.injectJavaScript(js);
};
const injectedJS = `
window.addEventListener('message', function(event) {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'iframe_message',
data: event.data
}));
});
true;
`;
return (
<View style={{flex: 1}}>
<WebView
ref={(ref) => { this.webViewRef = ref; }}
source={{ uri: 'https://dashboard.paytm.com' }}
javaScriptEnabled={true}
domStorageEnabled={true}
thirdPartyCookiesEnabled={true}
sharedCookiesEnabled={true}
onMessage={handleMessage}
injectedJavaScript={injectedJS}
interceptUrlPattern="accounts.paytm.com/oauth-js-sdk/"
interceptInjectedScript={`
if (!window.__paytmMessageHandler) {
window.__paytmMessageHandler = function(event) {
if (event.data.type === 'set_field') {
const el = document.getElementById(event.data.fieldId);
if (el) {
el.click();
el.focus();
el.value = event.data.value;
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
el.dispatchEvent(new Event('blur', { bubbles: true }));
}
}
if (event.data.type === 'click_login') {
const btn = document.getElementById('login_button');
if (btn) btn.click();
}
};
window.addEventListener('message', window.__paytmMessageHandler);
window.parent.postMessage({type: 'iframe_ready'}, '*');
}
`}
/>
<View style={{padding: 20, backgroundColor: '#f5f5f5', borderTopWidth: 1, borderTopColor: '#ddd'}}>
<Text style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Test Controls</Text>
<Text style={{marginTop: 5}}>Mobile:</Text>
<TextInput
style={{borderWidth: 1, borderColor: '#ccc', padding: 10, borderRadius: 5, backgroundColor: '#fff', marginTop: 5}}
onChangeText={(text) => syncToIframe('email_mobile_login', text)}
placeholder="Enter mobile number"
keyboardType="phone-pad"
/>
<Text style={{marginTop: 10}}>Password:</Text>
<TextInput
style={{borderWidth: 1, borderColor: '#ccc', padding: 10, borderRadius: 5, backgroundColor: '#fff', marginTop: 5}}
onChangeText={(text) => syncToIframe('password_login', text)}
placeholder="Enter password"
secureTextEntry
/>
<TouchableOpacity
style={{marginTop: 15, backgroundColor: '#00BAF2', padding: 15, borderRadius: 5, alignItems: 'center'}}
onPress={clickLogin}
>
<Text style={{color: '#fff', fontSize: 16, fontWeight: 'bold'}}>Login</Text>
</TouchableOpacity>
</View>
</View>
);
}
render() { render() {
// return this.renderWebDemo();
return ( return (
<View style={styles.container}> <View style={styles.container}>
{(() => { {(() => {

View File

@@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { WalletType, FreechargePersonalBindResult, MobikwikPersonalBindResult, PaytmPersonalBindResult, PhonePePersonalBindResult } from 'rnwalletman'; import { WalletType, FreechargePersonalBindResult, MobikwikPersonalBindResult, PaytmPersonalBindResult, PhonePePersonalBindResult, BharatPeBusinessBindResult } from 'rnwalletman';
import { OTPBindUI } from './OTPBindUI'; import { OTPBindUI } from './OTPBindUI';
export class FreeChargeBind extends Component<{ export class FreeChargeBind extends Component<{
@@ -77,6 +77,29 @@ export class PayTmPersonalOTPBind extends Component<{
} }
} }
export class BharatPeBusinessOTPBind extends Component<{
onRequestOTP: (walletType: WalletType, params: any) => Promise<any>;
onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>;
onSuccess: (result: BharatPeBusinessBindResult) => void;
onError: (error: string) => void;
isDebug: boolean;
}> {
render() {
return (
<OTPBindUI
walletType={WalletType.BHARATPE_BUSINESS}
title="BharatPe 绑定"
otpLength={4}
onRequestOTP={this.props.onRequestOTP}
onVerifyOTP={this.props.onVerifyOTP}
onSuccess={this.props.onSuccess}
onError={this.props.onError}
isDebug={this.props.isDebug}
/>
);
}
}
export class PhonePePersonalOTPBind extends Component<{ export class PhonePePersonalOTPBind extends Component<{
onRequestOTP: (walletType: WalletType, params: any) => Promise<any>; onRequestOTP: (walletType: WalletType, params: any) => Promise<any>;
onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>; onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>;