重构 demo
This commit is contained in:
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 },
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user