Email + OTP authentication flow for merchant access
Call sendMerchantOTP with merchant's email
Merchant receives 6-digit OTP via email and enters it in Rork app
Call verifyMerchantOTP with email + code
Session cookie is set, merchant can now access mobileAPI
// Step 1: Send OTP
async function sendOTP(email) {
try {
const response = await fetch('https://your-app.base44.com/functions/sendMerchantOTP', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email })
});
const data = await response.json();
if (data.success) {
console.log('✅ OTP sent to:', email);
// Show OTP input screen
return { success: true };
} else {
console.error('❌ Error:', data.error);
return { success: false, error: data.error };
}
} catch (error) {
console.error('❌ Request failed:', error);
return { success: false, error: error.message };
}
}
// Usage
await sendOTP('merchant@example.com');// Step 2: Verify OTP and Login
async function verifyOTPAndLogin(email, code) {
try {
// Verify OTP
const response = await fetch('https://your-app.base44.com/functions/verifyMerchantOTP', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, code })
});
const data = await response.json();
if (!data.success) {
console.error('❌ Verification failed:', data.error);
return { success: false, error: data.error };
}
// Extract magic link token
const { magicLinkToken, userId, email: verifiedEmail } = data;
console.log('✅ OTP verified!');
console.log('Magic Link Token:', magicLinkToken);
console.log('User ID:', userId);
// Authenticate with magic link
// IMPORTANT: This sets the authentication cookie
const loginUrl = `https://your-app.base44.com/auth/magic-link?token=${magicLinkToken}`;
const loginResponse = await fetch(loginUrl, {
method: 'GET',
credentials: 'include', // ✅ Store auth cookie
});
if (loginResponse.ok) {
console.log('✅ Logged in successfully!');
// Now you can call authenticated endpoints
return {
success: true,
userId,
email: verifiedEmail
};
} else {
console.error('❌ Login failed');
return { success: false, error: 'Login failed' };
}
} catch (error) {
console.error('❌ Request failed:', error);
return { success: false, error: error.message };
}
}
// Usage
const result = await verifyOTPAndLogin('merchant@example.com', '123456');
if (result.success) {
console.log('Ready to use mobileAPI!');
}After successful login, ALL mobileAPI calls with credentials: 'include' will be authenticated.
// After login, you can access merchant data
async function getMerchantProfile() {
const response = await fetch('https://your-app.base44.com/functions/mobileAPI', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include', // ✅ Send auth cookies
body: JSON.stringify({
action: 'merchantProfile'
})
});
const data = await response.json();
if (data.success) {
console.log('Merchant:', data.data);
return data.data;
} else {
console.error('Error:', data.error);
return null;
}
}
// Get merchant's orders (with multi-location support)
async function getMerchantOrders(storeId = null) {
const response = await fetch('https://your-app.base44.com/functions/mobileAPI', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include', // ✅ Send auth cookies
body: JSON.stringify({
action: 'merchantOrders',
params: {
store_id: storeId, // Optional: filter by specific location
status_filter: ['created', 'accepted', 'ready']
}
})
});
const data = await response.json();
if (data.success) {
console.log('Orders:', data.data);
return data.data;
}
}
// Get merchant's stores (with GPS auto-detect)
async function getMerchantStores(currentLat, currentLng) {
const response = await fetch('https://your-app.base44.com/functions/mobileAPI', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include', // ✅ Send auth cookies
body: JSON.stringify({
action: 'merchantGetStores',
params: {
current_lat: currentLat, // GPS location
current_lng: currentLng
}
})
});
const data = await response.json();
if (data.success) {
console.log('Stores:', data.data);
console.log('Nearest store:', data.nearest_store_id);
return data.data;
}
}// COMPLETE MERCHANT LOGIN FLOW FOR RORK
class MerchantAuth {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.isAuthenticated = false;
}
// Step 1: Send OTP to merchant email
async sendOTP(email) {
try {
const response = await fetch(`${this.baseUrl}/functions/sendMerchantOTP`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email })
});
const data = await response.json();
return data;
} catch (error) {
return { success: false, error: error.message };
}
}
// Step 2: Verify OTP and authenticate
async verifyAndLogin(email, code) {
try {
// Verify OTP
const verifyResponse = await fetch(`${this.baseUrl}/functions/verifyMerchantOTP`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, code })
});
const verifyData = await verifyResponse.json();
if (!verifyData.success) {
return verifyData;
}
// Authenticate with magic link
const loginUrl = `${this.baseUrl}/auth/magic-link?token=${verifyData.magicLinkToken}`;
const loginResponse = await fetch(loginUrl, {
method: 'GET',
credentials: 'include'
});
if (loginResponse.ok) {
this.isAuthenticated = true;
return {
success: true,
userId: verifyData.userId,
email: verifyData.email
};
}
return { success: false, error: 'Login failed' };
} catch (error) {
return { success: false, error: error.message };
}
}
// Step 3: Call authenticated API
async callAPI(action, params = {}) {
const response = await fetch(`${this.baseUrl}/functions/mobileAPI`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include', // ✅ Critical
body: JSON.stringify({ action, params })
});
return await response.json();
}
}
// USAGE EXAMPLE
const auth = new MerchantAuth('https://your-app.base44.com');
// Login flow
async function merchantLogin() {
// Step 1: Send OTP
const sendResult = await auth.sendOTP('merchant@example.com');
if (!sendResult.success) {
console.error('Failed to send OTP');
return;
}
console.log('✅ OTP sent to email');
// User enters code from email
const userEnteredCode = '123456'; // From user input
// Step 2: Verify and login
const loginResult = await auth.verifyAndLogin('merchant@example.com', userEnteredCode);
if (!loginResult.success) {
console.error('Login failed:', loginResult.error);
return;
}
console.log('✅ Logged in successfully!');
// Step 3: Access merchant data
const profile = await auth.callAPI('merchantProfile');
console.log('Merchant:', profile.data);
const orders = await auth.callAPI('merchantOrders', {
status_filter: ['created', 'accepted']
});
console.log('Orders:', orders.data);
const stores = await auth.callAPI('merchantGetStores', {
current_lat: 41.3083,
current_lng: -72.9279
});
console.log('Stores:', stores.data);
console.log('Nearest:', stores.nearest_store_id);
}
merchantLogin();