fix sms otp retriver
This commit is contained in:
69
utils/smsRetriever.ts
Normal file
69
utils/smsRetriever.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
type SmsRetrieverModule = {
|
||||
requestPhoneNumber: () => Promise<string>;
|
||||
startSmsRetriever: () => Promise<boolean>;
|
||||
addSmsListener: (callback: (event: { message?: string }) => void) => Promise<boolean>;
|
||||
removeSmsListener: () => void;
|
||||
};
|
||||
|
||||
function getModule(): SmsRetrieverModule | null {
|
||||
if (Platform.OS !== 'android') return null;
|
||||
return require('react-native-sms-retriever').default as SmsRetrieverModule;
|
||||
}
|
||||
|
||||
export function extractOtpFromMessage(message: string, length: number): string | null {
|
||||
const exact = new RegExp(`(?:^|[^\\d])(\\d{${length}})(?:[^\\d]|$)`);
|
||||
const m = message.match(exact);
|
||||
if (m) return m[1];
|
||||
const any = message.match(/(\d{4,8})/);
|
||||
if (!any) return null;
|
||||
const digits = any[1];
|
||||
if (digits.length >= length) return digits.slice(0, length);
|
||||
if (digits.length === length) return digits;
|
||||
return null;
|
||||
}
|
||||
|
||||
/** SMS Retriever:无需 READ_SMS,短信需含 app hash(见 Google 文档) */
|
||||
export async function startOtpSmsListener(
|
||||
otpLength: number,
|
||||
onOtp: (otp: string) => void,
|
||||
): Promise<() => void> {
|
||||
const mod = getModule();
|
||||
if (!mod) return () => {};
|
||||
|
||||
const stop = () => {
|
||||
try {
|
||||
mod.removeSmsListener();
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const registered = await mod.startSmsRetriever();
|
||||
if (!registered) return stop;
|
||||
await mod.addSmsListener((event) => {
|
||||
const msg = event.message ?? '';
|
||||
const otp = extractOtpFromMessage(msg, otpLength);
|
||||
if (otp) {
|
||||
onOtp(otp);
|
||||
stop();
|
||||
}
|
||||
});
|
||||
} catch {
|
||||
stop();
|
||||
}
|
||||
return stop;
|
||||
}
|
||||
|
||||
/** 系统号码选择器,一次性授权,无需 READ_SMS */
|
||||
export async function requestPhoneNumberHint(): Promise<string> {
|
||||
const mod = getModule();
|
||||
if (!mod) throw new Error('仅支持 Android');
|
||||
return mod.requestPhoneNumber();
|
||||
}
|
||||
|
||||
export function normalizeHintPhone(raw: string, mobileLength = 10): string {
|
||||
return raw.replace(/\D/g, '').slice(-mobileLength);
|
||||
}
|
||||
Reference in New Issue
Block a user