137 lines
3.6 KiB
TypeScript
137 lines
3.6 KiB
TypeScript
// services/socketService.ts
|
|
import { PAYMENT_SOCKET_BASE_URL, STORAGE_KEYS } from "@/constants/config";
|
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
import io, { Socket } from "socket.io-client";
|
|
|
|
class SocketService {
|
|
private socket: Socket | null = null;
|
|
private static instance: SocketService;
|
|
|
|
private constructor() {}
|
|
|
|
public static getInstance(): SocketService {
|
|
if (!SocketService.instance) {
|
|
SocketService.instance = new SocketService();
|
|
}
|
|
return SocketService.instance;
|
|
}
|
|
|
|
public async connect(): Promise<Socket> {
|
|
try {
|
|
const token = await AsyncStorage.getItem(STORAGE_KEYS.AUTH_TOKEN);
|
|
|
|
if (!token) {
|
|
throw new Error("No auth token found");
|
|
}
|
|
|
|
this.socket = io(PAYMENT_SOCKET_BASE_URL, {
|
|
transports: ["websocket"],
|
|
autoConnect: true,
|
|
reconnection: true,
|
|
reconnectionDelay: 1000,
|
|
reconnectionAttempts: 5,
|
|
timeout: 20000,
|
|
extraHeaders: {
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
});
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this.socket!.on("connect", () => {
|
|
console.log("Socket connected:", this.socket?.id);
|
|
resolve(this.socket!);
|
|
});
|
|
|
|
this.socket!.on("connect_error", (error) => {
|
|
console.error("Socket connection error:", error);
|
|
reject(error);
|
|
});
|
|
|
|
this.socket!.on("disconnect", (reason) => {
|
|
console.log("Socket disconnected:", reason);
|
|
});
|
|
});
|
|
} catch (error) {
|
|
console.error("Failed to connect socket:", error);
|
|
return Promise.reject(error);
|
|
}
|
|
}
|
|
|
|
public registerTransaction(transactionId: string): Promise<void> {
|
|
return new Promise((resolve, reject) => {
|
|
const socket = this.socket; // Save reference to socket here
|
|
|
|
if (!socket || !socket.connected) {
|
|
reject(new Error("Socket not connected"));
|
|
return;
|
|
}
|
|
|
|
const timeoutMs = 5000;
|
|
|
|
const timeoutId = setTimeout(() => {
|
|
socket.off("registration-ack", onRegistrationAck);
|
|
reject(new Error("Timeout: No registration-ack received"));
|
|
}, timeoutMs);
|
|
|
|
const onRegistrationAck = (data: any) => {
|
|
console.log("inside onRegisterAck");
|
|
if (data.transactionId === transactionId) {
|
|
clearTimeout(timeoutId);
|
|
// socket.off("registration-ack", onRegistrationAck);
|
|
|
|
if (data.success) {
|
|
resolve();
|
|
} else {
|
|
reject(new Error("Registration failed"));
|
|
}
|
|
}
|
|
};
|
|
|
|
socket.on("registration-ack", onRegistrationAck);
|
|
|
|
socket.on("register-transaction", this.onPaymentConfirm);
|
|
socket.onAny((eventName, ...args) => {
|
|
console.log(eventName, "eventname", JSON.stringify(args), "✅✅✅✅✅");
|
|
});
|
|
|
|
socket.emit("register-transaction", { transactionId });
|
|
});
|
|
}
|
|
|
|
private onPaymentConfirm(eventname: string, ...args: any[]): void {
|
|
console.log(eventname, "eventName", JSON.stringify(args));
|
|
}
|
|
|
|
public onPaymentConfirmation(callback: (data: any) => void): void {
|
|
if (!this.socket) {
|
|
console.error("Socket not connected");
|
|
return;
|
|
}
|
|
|
|
this.socket.on("register-transaction", callback);
|
|
}
|
|
|
|
public offPaymentConfirmation(): void {
|
|
if (this.socket) {
|
|
this.socket.off("payment-confirmation");
|
|
}
|
|
}
|
|
|
|
public disconnect(): void {
|
|
if (this.socket) {
|
|
this.socket.disconnect();
|
|
this.socket = null;
|
|
}
|
|
}
|
|
|
|
public isConnected(): boolean {
|
|
return this.socket?.connected || false;
|
|
}
|
|
|
|
public getSocket(): Socket | null {
|
|
return this.socket;
|
|
}
|
|
}
|
|
|
|
export default SocketService.getInstance();
|