bharatpe business 改为 otp 模式 ,去除 web 的抓取
This commit is contained in:
142
App.tsx
142
App.tsx
@@ -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,19 +31,23 @@ 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;
|
||||||
private tuneUserId: string;
|
private tuneUserId: string;
|
||||||
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}>
|
||||||
{(() => {
|
{(() => {
|
||||||
|
|||||||
@@ -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>;
|
||||||
|
|||||||
Submodule servers/walletman updated: 0eaa98c661...ae94e22e38
Reference in New Issue
Block a user