重构 demo
This commit is contained in:
185
components/OTPBindUI.tsx
Normal file
185
components/OTPBindUI.tsx
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { View, TextInput, TouchableOpacity, Text, StyleSheet, ActivityIndicator } from 'react-native';
|
||||||
|
import { WalletType } from 'rnwalletman';
|
||||||
|
import { useOTPBind } from '../hooks/useOTPBind';
|
||||||
|
|
||||||
|
interface OTPBindUIProps {
|
||||||
|
walletType: WalletType;
|
||||||
|
title: string;
|
||||||
|
otpLength?: number;
|
||||||
|
mobileLength?: number;
|
||||||
|
onRequestOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onSuccess: (result: any) => void;
|
||||||
|
onError: (error: string) => void;
|
||||||
|
isDebug: boolean;
|
||||||
|
additionalParams?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OTPBindUI: React.FC<OTPBindUIProps> = ({
|
||||||
|
walletType,
|
||||||
|
title,
|
||||||
|
otpLength = 6,
|
||||||
|
mobileLength = 10,
|
||||||
|
onRequestOTP,
|
||||||
|
onVerifyOTP,
|
||||||
|
onSuccess,
|
||||||
|
onError,
|
||||||
|
isDebug,
|
||||||
|
additionalParams = {},
|
||||||
|
}) => {
|
||||||
|
const [state, actions] = useOTPBind(
|
||||||
|
walletType,
|
||||||
|
{
|
||||||
|
onRequestOTP,
|
||||||
|
onVerifyOTP,
|
||||||
|
onSuccess,
|
||||||
|
onError,
|
||||||
|
isDebug,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
otpLength,
|
||||||
|
mobileLength,
|
||||||
|
additionalParams,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (state.step === 'processing') {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<ActivityIndicator size="large" color="#fff" />
|
||||||
|
<Text style={styles.processingText}>处理中...</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={styles.form}>
|
||||||
|
<Text style={styles.title}>{title}</Text>
|
||||||
|
|
||||||
|
{state.step === 'mobile' && (
|
||||||
|
<>
|
||||||
|
<TextInput
|
||||||
|
style={styles.input}
|
||||||
|
placeholder="请输入手机号"
|
||||||
|
placeholderTextColor="#999"
|
||||||
|
keyboardType="phone-pad"
|
||||||
|
maxLength={mobileLength}
|
||||||
|
value={state.mobile}
|
||||||
|
onChangeText={actions.setMobile}
|
||||||
|
editable={!state.loading}
|
||||||
|
/>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.button, state.loading && styles.buttonDisabled]}
|
||||||
|
onPress={actions.requestOTP}
|
||||||
|
disabled={state.loading}
|
||||||
|
>
|
||||||
|
{state.loading ? (
|
||||||
|
<ActivityIndicator color="#fff" />
|
||||||
|
) : (
|
||||||
|
<Text style={styles.buttonText}>获取验证码</Text>
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{state.step === 'otp' && (
|
||||||
|
<>
|
||||||
|
<Text style={styles.hint}>验证码已发送至 {state.mobile}</Text>
|
||||||
|
<TextInput
|
||||||
|
style={styles.input}
|
||||||
|
placeholder={`请输入 ${otpLength} 位验证码`}
|
||||||
|
placeholderTextColor="#999"
|
||||||
|
keyboardType="number-pad"
|
||||||
|
maxLength={otpLength}
|
||||||
|
value={state.otp}
|
||||||
|
onChangeText={actions.setOtp}
|
||||||
|
editable={!state.loading}
|
||||||
|
/>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.button, state.loading && styles.buttonDisabled]}
|
||||||
|
onPress={actions.verifyOTP}
|
||||||
|
disabled={state.loading}
|
||||||
|
>
|
||||||
|
{state.loading ? (
|
||||||
|
<ActivityIndicator color="#fff" />
|
||||||
|
) : (
|
||||||
|
<Text style={styles.buttonText}>验证并绑定</Text>
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.linkButton}
|
||||||
|
onPress={actions.resetToMobile}
|
||||||
|
disabled={state.loading}
|
||||||
|
>
|
||||||
|
<Text style={styles.linkText}>重新输入手机号</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.8)',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
width: '80%',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderRadius: 10,
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#ddd',
|
||||||
|
borderRadius: 5,
|
||||||
|
padding: 12,
|
||||||
|
fontSize: 16,
|
||||||
|
marginBottom: 15,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
backgroundColor: '#007AFF',
|
||||||
|
borderRadius: 5,
|
||||||
|
padding: 15,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
buttonDisabled: {
|
||||||
|
backgroundColor: '#ccc',
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
linkButton: {
|
||||||
|
marginTop: 10,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
linkText: {
|
||||||
|
color: '#007AFF',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
hint: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#666',
|
||||||
|
marginBottom: 10,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
processingText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16,
|
||||||
|
marginTop: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
101
components/WalletBindComponents.tsx
Normal file
101
components/WalletBindComponents.tsx
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { WalletType, FreechargePersonalBindResult, MobikwikPersonalBindResult, PaytmPersonalBindResult, PhonePePersonalBindResult } from 'rnwalletman';
|
||||||
|
import { OTPBindUI } from './OTPBindUI';
|
||||||
|
|
||||||
|
export class FreeChargeBind extends Component<{
|
||||||
|
onRequestOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onSuccess: (result: FreechargePersonalBindResult) => void;
|
||||||
|
onError: (error: string) => void;
|
||||||
|
isDebug: boolean;
|
||||||
|
}> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<OTPBindUI
|
||||||
|
walletType={WalletType.FREECHARGE_PERSONAL}
|
||||||
|
title="Freecharge 绑定"
|
||||||
|
otpLength={4}
|
||||||
|
onRequestOTP={this.props.onRequestOTP}
|
||||||
|
onVerifyOTP={this.props.onVerifyOTP}
|
||||||
|
onSuccess={this.props.onSuccess}
|
||||||
|
onError={this.props.onError}
|
||||||
|
isDebug={this.props.isDebug}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MobikwikOTPBind extends Component<{
|
||||||
|
onRequestOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onSuccess: (result: MobikwikPersonalBindResult) => void;
|
||||||
|
onError: (error: string) => void;
|
||||||
|
isDebug: boolean;
|
||||||
|
deviceId: string;
|
||||||
|
tuneUserId: string;
|
||||||
|
}> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<OTPBindUI
|
||||||
|
walletType={WalletType.MOBIKWIK_PERSONAL}
|
||||||
|
title="Mobikwik 绑定"
|
||||||
|
otpLength={6}
|
||||||
|
onRequestOTP={this.props.onRequestOTP}
|
||||||
|
onVerifyOTP={this.props.onVerifyOTP}
|
||||||
|
onSuccess={this.props.onSuccess}
|
||||||
|
onError={this.props.onError}
|
||||||
|
isDebug={this.props.isDebug}
|
||||||
|
additionalParams={{
|
||||||
|
deviceId: this.props.deviceId,
|
||||||
|
tuneUserId: this.props.tuneUserId,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PayTmPersonalOTPBind extends Component<{
|
||||||
|
onRequestOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onSuccess: (result: PaytmPersonalBindResult) => void;
|
||||||
|
onError: (error: string) => void;
|
||||||
|
isDebug: boolean;
|
||||||
|
}> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<OTPBindUI
|
||||||
|
walletType={WalletType.PAYTM_PERSONAL}
|
||||||
|
title="Paytm 绑定"
|
||||||
|
otpLength={8}
|
||||||
|
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<{
|
||||||
|
onRequestOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onSuccess: (result: PhonePePersonalBindResult) => void;
|
||||||
|
onError: (error: string) => void;
|
||||||
|
isDebug: boolean;
|
||||||
|
}> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<OTPBindUI
|
||||||
|
walletType={WalletType.PHONEPE_PERSONAL}
|
||||||
|
title="PhonePe 绑定"
|
||||||
|
otpLength={8}
|
||||||
|
onRequestOTP={this.props.onRequestOTP}
|
||||||
|
onVerifyOTP={this.props.onVerifyOTP}
|
||||||
|
onSuccess={this.props.onSuccess}
|
||||||
|
onError={this.props.onError}
|
||||||
|
isDebug={this.props.isDebug}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
129
hooks/useOTPBind.ts
Normal file
129
hooks/useOTPBind.ts
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { WalletType } from 'rnwalletman';
|
||||||
|
|
||||||
|
export interface OTPBindCallbacks {
|
||||||
|
onRequestOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onVerifyOTP: (walletType: WalletType, params: any) => Promise<any>;
|
||||||
|
onSuccess: (result: any) => void;
|
||||||
|
onError: (error: string) => void;
|
||||||
|
isDebug?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OTPBindState {
|
||||||
|
mobile: string;
|
||||||
|
otp: string;
|
||||||
|
step: 'mobile' | 'otp' | 'processing';
|
||||||
|
loading: boolean;
|
||||||
|
otpData: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OTPBindActions {
|
||||||
|
setMobile: (mobile: string) => void;
|
||||||
|
setOtp: (otp: string) => void;
|
||||||
|
requestOTP: () => Promise<void>;
|
||||||
|
verifyOTP: () => Promise<void>;
|
||||||
|
resetToMobile: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useOTPBind(
|
||||||
|
walletType: WalletType,
|
||||||
|
callbacks: OTPBindCallbacks,
|
||||||
|
config?: {
|
||||||
|
otpLength?: number;
|
||||||
|
mobileLength?: number;
|
||||||
|
additionalParams?: any;
|
||||||
|
}
|
||||||
|
): [OTPBindState, OTPBindActions] {
|
||||||
|
const [mobile, setMobile] = useState('');
|
||||||
|
const [otp, setOtp] = useState('');
|
||||||
|
const [step, setStep] = useState<'mobile' | 'otp' | 'processing'>('mobile');
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [otpData, setOtpData] = useState<any>(null);
|
||||||
|
|
||||||
|
const { onRequestOTP, onVerifyOTP, onSuccess, onError, isDebug = false } = callbacks;
|
||||||
|
const { otpLength = 6, mobileLength = 10, additionalParams = {} } = config || {};
|
||||||
|
|
||||||
|
const log = (...args: any[]) => {
|
||||||
|
if (isDebug) console.log(`[${walletType}]`, ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = (...args: any[]) => {
|
||||||
|
if (isDebug) console.error(`[${walletType}]`, ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const requestOTP = async () => {
|
||||||
|
if (!mobile || mobile.length !== mobileLength) {
|
||||||
|
onError('Invalid mobile number');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
log('Requesting OTP for:', mobile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await onRequestOTP(walletType, {
|
||||||
|
mobile,
|
||||||
|
...additionalParams,
|
||||||
|
});
|
||||||
|
log('OTP response:', response);
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setOtpData(response.data);
|
||||||
|
setStep('otp');
|
||||||
|
} else {
|
||||||
|
error('OTP request failed:', response.message);
|
||||||
|
onError(response.message || 'Failed to request OTP');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
error('Request OTP error:', e);
|
||||||
|
onError(e instanceof Error ? e.message : 'Failed to request OTP');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const verifyOTP = async () => {
|
||||||
|
if (!otp || otp.length !== otpLength) {
|
||||||
|
onError(`Invalid OTP (expected ${otpLength} digits)`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
setStep('processing');
|
||||||
|
log('Verifying OTP:', otp);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await onVerifyOTP(walletType, {
|
||||||
|
mobile,
|
||||||
|
otp,
|
||||||
|
...additionalParams,
|
||||||
|
...(otpData || {}),
|
||||||
|
});
|
||||||
|
log('Verify response:', response);
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
onSuccess(response.data);
|
||||||
|
} else {
|
||||||
|
error('Verify failed:', response.message);
|
||||||
|
setStep('otp');
|
||||||
|
onError(response.message || 'Failed to verify OTP');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
error('Verify OTP error:', e);
|
||||||
|
setStep('otp');
|
||||||
|
onError(e instanceof Error ? e.message : 'Failed to verify OTP');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetToMobile = () => {
|
||||||
|
setStep('mobile');
|
||||||
|
setOtp('');
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
{ mobile, otp, step, loading, otpData },
|
||||||
|
{ setMobile, setOtp, requestOTP, verifyOTP, resetToMobile },
|
||||||
|
];
|
||||||
|
}
|
||||||
Submodule libs/rnwalletman updated: ad66622161...51280d4a12
Submodule servers/walletman updated: aa50a6588d...ef6bc8907c
77
services/api.ts
Normal file
77
services/api.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import { WalletType } from 'rnwalletman';
|
||||||
|
|
||||||
|
class Api {
|
||||||
|
public static readonly BASE_URL = 'http://192.168.1.117:16000';
|
||||||
|
private static _instance: Api | null = null;
|
||||||
|
private userId: number = 0;
|
||||||
|
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
public setUserId(userId: number) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getUserId(): number {
|
||||||
|
return this.userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static get instance() {
|
||||||
|
if (Api._instance === null) {
|
||||||
|
Api._instance = new Api();
|
||||||
|
}
|
||||||
|
return Api._instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private headers(): Record<string, string> {
|
||||||
|
const h: Record<string, string> = { 'Content-Type': 'application/json' };
|
||||||
|
if (this.userId) h['X-User-ID'] = String(this.userId);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async login(username: string, password: string): Promise<number> {
|
||||||
|
const res = await fetch(`${Api.BASE_URL}/login`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ username, password }),
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (!data.success) throw new Error(data.message);
|
||||||
|
this.userId = data.data.userId;
|
||||||
|
return this.userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async register(walletType: WalletType, params: any) {
|
||||||
|
const res = await fetch(`${Api.BASE_URL}/register`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: this.headers(),
|
||||||
|
body: JSON.stringify({ walletType, params }),
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (!data.success) throw new Error(data.message);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async requestOTP(walletType: WalletType, mobile: string, params: any = {}) {
|
||||||
|
const res = await fetch(`${Api.BASE_URL}/request-otp`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: this.headers(),
|
||||||
|
body: JSON.stringify({ walletType, mobile, ...params }),
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (!data.success) throw new Error(data.message);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async verifyOTP(walletType: WalletType, mobile: string, otp: string, params: any = {}) {
|
||||||
|
const res = await fetch(`${Api.BASE_URL}/verify-otp`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: this.headers(),
|
||||||
|
body: JSON.stringify({ walletType, mobile, otp, params }),
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (!data.success) throw new Error(data.message);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Api;
|
||||||
46
styles/index.ts
Normal file
46
styles/index.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
export const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: "lightblue",
|
||||||
|
borderRadius: 5,
|
||||||
|
width: 200,
|
||||||
|
height: 55,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
modal: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
modalContent: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
bindButton: {
|
||||||
|
padding: 10,
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
backgroundColor: "#007AFF",
|
||||||
|
borderRadius: 5,
|
||||||
|
width: "90%",
|
||||||
|
height: 55,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
bindButtonText: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
});
|
||||||
25
types/index.ts
Normal file
25
types/index.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
export interface AppProps {}
|
||||||
|
|
||||||
|
export interface WalletmanAppState {
|
||||||
|
/* Paytm Personal */
|
||||||
|
showPaytmPersonalBind: boolean;
|
||||||
|
paytmPersonalBindType: 'otpMode' | 'tokenMode';
|
||||||
|
showPaytmBusinessBind: boolean;
|
||||||
|
|
||||||
|
/* PhonePe Personal */
|
||||||
|
showPhonePePersonalBind: boolean;
|
||||||
|
phonePePersonalBindType: 'otpMode' | 'tokenMode';
|
||||||
|
showPhonePeBusinessBind: boolean;
|
||||||
|
|
||||||
|
/* GooglePay Business */
|
||||||
|
showGooglePayBusinessBind: boolean;
|
||||||
|
|
||||||
|
/* BharatPe Business */
|
||||||
|
showBharatPeBusinessBind: boolean;
|
||||||
|
|
||||||
|
/* Mobikwik Personal */
|
||||||
|
showMobikwikPersonalBind: boolean;
|
||||||
|
|
||||||
|
/* Freecharge Personal */
|
||||||
|
showFreechargePersonalBind: boolean;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user