[#1310] Booking error: Client email value is wrong

Migrated from Redmine #1310 | Author: Ilya Radu
Status: New | Priority: Normal | Created: 2024-11-22


When I try to create a booking through the SimplyBook API, there is an error related to the client’s email value.
and gives the following error: Client email value is wrong.


// server.js

const express = require("express");
const axios = require("axios");
const dotenv = require("dotenv");
const cors = require("cors");

dotenv.config();

const app = express();
app.use(express.json());
app.use(cors());

const API_KEY = process.env.SIMPLYBOOK_API_KEY;
const COMPANY_LOGIN = process.env.COMPANY_LOGIN;
const LOGIN_URL = "https://user-api.simplybook.me/login";
const API_URL = "https://user-api.simplybook.me";

const getAuthToken = async () => {
  try {
    const response = await axios.post(
      LOGIN_URL,
      {
        method: "getToken",
        params: {
          companyLogin: COMPANY_LOGIN,
          apiKey: API_KEY,
        },
        id: 1,
      },
      {
        headers: {
          "Content-Type": "application/json",
        },
      },
    );

    if (response.data && response.data.result) {
      const token = response.data.result;
      return token;
    } else {
      throw new Error("Failed to obtain authorization token from API response");
    }
  } catch (error) {
    throw error;
  }
};

app.get("/api/services", async (req, res) => {
  try {
    const token = await getAuthToken();

    const response = await axios.post(
      API_URL,
      {
        method: "getEventList",
        params: {},
        id: 1,
      },
      {
        headers: {
          "Content-Type": "application/json",
          "X-Company-Login": COMPANY_LOGIN,
          "X-Token": token,
        },
      },
    );

    if (response.data.error) {
      return res.status(500).json({ message: "Error fetching services" });
    }

    res.status(200).json(response.data.result);
  } catch (error) {
    res.status(500).json({ message: "Error fetching services" });
  }
});

app.get("/api/performers", async (req, res) => {
  try {
    const token = await getAuthToken();

    const response = await axios.post(
      API_URL,
      {
        method: "getUnitList",
        params: {},
        id: 1,
      },
      {
        headers: {
          "Content-Type": "application/json",
          "X-Company-Login": COMPANY_LOGIN,
          "X-Token": token,
        },
      },
    );

    if (response.data.error) {
      return res.status(500).json({ message: "Error fetching performers" });
    }

    res.status(200).json(response.data.result);
  } catch (error) {
    res.status(500).json({ message: "Error fetching performers" });
  }
});

app.get("/api/available-dates", async (req, res) => {
  const { performerId } = req.query;

  try {
    const token = await getAuthToken();

    const response = await axios.post(
      API_URL,
      {
        method: "getFirstWorkingDay",
        params: [performerId || null],
        id: 1,
      },
      {
        headers: {
          "Content-Type": "application/json",
          "X-Company-Login": COMPANY_LOGIN,
          "X-Token": token,
        },
      },
    );

    if (response.data.error) {
      return res.status(500).json({ message: "Error fetching available dates" });
    }

    res.status(200).json({ firstAvailableDate: response.data.result });
  } catch (error) {
    res.status(500).json({ message: "Error fetching available dates" });
  }
});

app.get("/api/available-times", async (req, res) => {
  const { date, serviceId, performerId } = req.query;

  if (!date || !serviceId) {
    return res.status(400).json({ message: "Parameters date and serviceId are required" });
  }

  try {
    const token = await getAuthToken();

    const response = await axios.post(
      API_URL,
      {
        method: "getStartTimeMatrix",
        params: [date, date, serviceId, performerId || null, 1],
        id: 1,
      },
      {
        headers: {
          "Content-Type": "application/json",
          "X-Company-Login": COMPANY_LOGIN,
          "X-Token": token,
        },
      },
    );

    if (response.data.error) {
      return res.status(500).json({ message: "Error fetching available times" });
    }

    const times = response.data.result[date] || [];

    res.status(200).json({ availableTimes: times });
  } catch (error) {
    res.status(500).json({ message: "Error fetching available times" });
  }
};

const addClient = async (client, clientData) => {
  const response = await client.post("/", {
    method: "addClient",
    params: clientData,
    id: 1,
  });

  if (response.data.error) {
    throw new Error(response.data.error.message);
  }

  return response.data.result;
};

app.post("/api/booking", async (req, res) => {
  const { name, email, phone, serviceId, performerId, date, time, additionalFields } = req.body;

  if (!name || !email || !phone || !serviceId || !date || !time) {
    return res.status(400).json({ message: "Invalid data" });
  }

  let additionalFieldValues = additionalFields || {};

  try {
    const token = await getAuthToken();

    const client = axios.create({
      baseURL: API_URL,
      headers: {
        "Content-Type": "application/json",
        "X-Company-Login": COMPANY_LOGIN,
        "X-Token": token,
      },
    });

    const clientResult = await addClient(client, { name, email, phone });
    const clientId = clientResult.id;

    const bookingRequest = {
      method: "book",
      params: [
        serviceId,
        performerId || null,
        `${date} ${time}`,
        clientId,
        additionalFieldValues,
        1,
      ],
      id: 1,
    };

    const bookingResponse = await client.post("/", bookingRequest);

    if (bookingResponse.data.error) {
      return res.status(500).json({
        message: "Error during booking",
        error: bookingResponse.data.error,
      });
    }

    res.status(200).json({
      message: "Booking successfully completed",
      data: bookingResponse.data.result,
    });
  } catch (error) {
    res.status(500).json({ message: "Error during booking", error: error.message });
  }
});

const PORT = process.env.PORT || 5000;

app.listen(PORT, () => {});

Redmine Admin wrote:

please provide raw http request and response you got

Ilya Radu wrote:

Redmine Admin wrote:

please provide raw http request and response you got

=== Incoming HTTP Request ===
POST /api/booking
Headers: {
host: ‘localhost:5000’,
connection: ‘keep-alive’,
‘content-length’: ‘165’,
‘sec-ch-ua’: ‘“Chromium”;v=“128”, “Not;A=Brand”;v=“24”, “Opera GX”;v=“114”’,
accept: ‘application/json, text/plain, /’,
‘sec-ch-ua-platform’: ‘“Windows”’,
‘sec-ch-ua-mobile’: ‘?0’,
‘user-agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0’,
‘content-type’: ‘application/json’,
origin: ‘http://localhost:3000’,
‘sec-fetch-site’: ‘same-site’,
‘sec-fetch-mode’: ‘cors’,
‘sec-fetch-dest’: ‘empty’,
referer: ‘http://localhost:3000/’,
‘accept-encoding’: ‘gzip, deflate, br, zstd’,
‘accept-language’: ‘ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7’
}
Body: {“name”:“Ilya Radu",“email”:"radui2004@gmail.com”,“phone”:“0635956911”,“serviceId”:“2”,“performerId”:“2”,“date”:“2024-11-27”,“time”:“16:30:00”,“additionalFields”:{}}
Raw HTTP Request:
{“name”:“Ilya Radu",“email”:"radui2004@gmail.com”,“phone”:“0635956911”,“serviceId”:“2”,“performerId”:“2”,“date”:“2024-11-27”,“time”:“16:30:00”,“additionalFields”:{}}
Reservation request received (raw data):
{
“name”: “Ilya Radu”,
“email”: “radui2004@gmail.com”,
“phone”: “0635956911”,
“serviceId”: “2”,
“performerId”: “2”,
“date”: “2024-11-27”,
“time”: “16:30:00”,
“additionalFields”: {}
}
Response from the API when a token is received: {
result: ‘d91cb55def34e7807b68dc9be3133a6caab0d5be13a2e5c2f8e6921055565eae’,
id: ‘1’
}
Authorization token received: d91cb55def34e7807b68dc9be3133a6caab0d5be13a2e5c2f8e6921055565eae
Booking error: Client email value is wrong
=== Outgoing HTTP Response ===
Status: 500
Headers: [Object: null prototype] {
‘x-powered-by’: ‘Express’,
‘access-control-allow-origin’: ‘*’,
‘content-type’: ‘application/json; charset=utf-8’
}
Body: {“message”:“Booking error:”,“error”:“Client email value is wrong”}