🔐 Merchant Login for Rork

Email + OTP authentication flow for merchant access

Login Flow Overview
1

Send OTP

Call sendMerchantOTP with merchant's email

2

User Enters Code

Merchant receives 6-digit OTP via email and enters it in Rork app

3

Verify OTP

Call verifyMerchantOTP with email + code

4

Authenticated!

Session cookie is set, merchant can now access mobileAPI

Step 1: Send OTP to Email
Rork Implementation
// 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 + Authenticate
Critical: Uses Magic Link Token
// 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!');
}
Step 3: Call Authenticated Merchant APIs

After successful login, ALL mobileAPI calls with credentials: 'include' will be authenticated.

After Login
// 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
Full Implementation
// 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();
Available Merchant API Actions

Profile & Settings

  • • merchantProfile
  • • updateMerchant
  • • merchantGetNotificationSettings
  • • merchantUpdateNotificationSettings

Orders

  • • merchantOrders (+ store_id filter)
  • • merchantAcceptOrder
  • • merchantRejectOrder
  • • merchantMarkReady

Menu Management

  • • merchantMenu
  • • merchantUpdateMenu
  • • merchantCreateMenuItem
  • • merchantUpdateMenuItem
  • • merchantToggleItemAvailability

Locations & Analytics

  • • merchantGetStores (+ GPS auto-detect)
  • • merchantUpdateStore
  • • merchantGetAnalytics (+ store_id filter)
  • • merchantGetPayouts