[#1317] Error: Client email value is wrong

Migrated from Redmine #1317 | Author: Ilya Radu
Status: New | Priority: Immediate, there is BUG! | Created: 2024-11-27


Hello earlier when sending a booking request I got the error “Client email value is wrong” I thought it was related to adding a client and so I decided to do it differently, specifically not to add a new client but to get through the api a list of clients that already exist and by their id to make a booking request, but for some reason I still get the error “Client email value is wrong” even when I take an existing client.

this my backend file:


// server.js

const express = require("express");
const axios = require("axios");
const dotenv = require("dotenv");
const cors = require("cors");
const bodyParser = require("body-parser");

// Load environment variables from .env file
dotenv.config();

const app = express();

// Middleware to capture raw request body
const rawBodySaver = (req, res, buf, encoding) => {
  if (buf && buf.length) {
    req.rawBody = buf.toString(encoding || "utf8");
  }
};

// Configure express.json with rawBodySaver
app.use(express.json({ verify: rawBodySaver }));
app.use(cors());

// Middleware to capture response body
const captureResponseBody = (req, res, next) => {
  let oldWrite = res.write;
  let oldEnd = res.end;

  const chunks = [];

  res.write = function (chunk, ...args) {
    chunks.push(Buffer.from(chunk));
    oldWrite.apply(res, [chunk, ...args]);
  };

  res.end = function (chunk, ...args) {
    if (chunk) {
      chunks.push(Buffer.from(chunk));
    }
    const body = Buffer.concat(chunks).toString("utf8");
    res.locals.body = body;
    oldEnd.apply(res, [chunk, ...args]);
  };

  next();
};

app.use(captureResponseBody);

// Middleware for logging incoming HTTP requests
app.use((req, res, next) => {
  console.log("=== Incoming HTTP Request ===");
  console.log(`${req.method} ${req.originalUrl}`);
  console.log("Headers:", req.headers);
  console.log("Body:", req.rawBody);

  // Override res.send method to log the response
  const originalSend = res.send;
  res.send = function (body) {
    console.log("=== Outgoing HTTP Response ===");
    console.log(`Status: ${res.statusCode}`);
    console.log("Headers:", res.getHeaders());
    console.log("Body:", body);
    originalSend.apply(res, arguments);
  };

  next();
});

// Load environment variables
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";

// Function to get authorization token
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",
        },
      },
    );

    console.log("API response when obtaining token:", response.data);

    if (response.data && response.data.result) {
      const token = response.data.result;
      console.log("Authorization token obtained:", token);
      return token;
    } else {
      throw new Error("Failed to obtain authorization token from API response");
    }
  } catch (error) {
    console.error(
      "Error obtaining authorization token:",
      error.response ? error.response.data : error.message,
    );
    throw error;
  }
};

const getUserAuthToken = async () => {
  try {
    const response = await axios.post(
      LOGIN_URL,
      {
        method: "getUserToken",
        params: {
          companyLogin: COMPANY_LOGIN,
          userLogin: "ilya@1-tn.com",
          userPassword: "pk7m7ohocq46fs",
        },
        id: 1,
      },
      {
        headers: {
          "Content-Type": "application/json",
        },
      },
    );

    if (response.data && response.data.result) {
      const userToken = response.data.result;
      console.log("User token obtained:", userToken);
      return userToken;
    } else {
      throw new Error("Failed to obtain user token from API response");
    }
  } catch (error) {
    console.error(
      "Error obtaining user token:",
      error.response ? error.response.data : error.message,
    );
    throw error;
  }
};

// Route to get the list of services
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) {
      console.error("Error fetching services list:", response.data.error);
      return res.status(500).json({ message: "Error fetching services" });
    }

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

// Route to get the list of performers
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) {
      console.error("Error fetching performers list:", response.data.error);
      return res.status(500).json({ message: "Error fetching performers" });
    }

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

// Route to get the nearest available date
app.get("/api/available-dates", async (req, res) => {
  const { performerId } = req.query; // Get performerId from the request

  try {
    const token = await getAuthToken();

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

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

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

// Route to get available time slots for a selected date
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) {
      console.error("Error fetching available times:", 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) {
    console.error("Error fetching available times:", error.message);
    res.status(500).json({ message: "Error fetching available times" });
  }
});

// Function to add a client
const addClient = async (client, clientData) => {
  const response = await client.post("/", {
    method: "addClient",
    params: {
      name: clientData.name,
      email: clientData.email,
      phone: clientData.phone,
      address1: clientData.address1 || "",
      address2: clientData.address2 || "",
      city: clientData.city || "",
      zip: clientData.zip || "",
      country_id: clientData.country_id || null,
    },
    id: 1,
  });

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

  return response.data.result;
};

// Update getClients function to return the list of clients
const getClients = async () => {
  try {
    const token = await getAuthToken();

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

    if (response.data.error) {
      console.error("Error fetching clients list:", response.data.error);
      return null; // Return null in case of error
    }

    const clients = response.data.result;
    console.log("Clients list:", clients);
    return clients; // Return the list of clients
  } catch (error) {
    console.error("Error fetching clients list:", error.message);
    return null;
  }
};

// Modify route for test client addition
app.post("/api/test-add-client", async (req, res) => {
  console.log("=== Test Client Addition ===");

  // Fixed client data for testing
  const fixedClientData = {
    name: "Test Client",
    email: "radui2004@gmail.com",
    phone: "+71234567890", // Changed: added '+' and country code
    address1: "Example Street, 1",
    address2: "Apt. 101",
    city: "Moscow",
    zip: "123456",
    country_id: 1,
  };

  console.log("Client data used:", fixedClientData);

  try {
    // Obtain authorization token
    const token = await getAuthToken();
    console.log("Authorization token obtained:", token);

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

    // Fetch and log existing clients
    console.log("Fetching existing clients...");
    const existingClients = await getClients(); // Fixed: removed parameter

    console.log("Existing clients:", existingClients);

    // Log the data being sent
    const addClientPayload = {
      method: "addClient",
      params: {
        name: fixedClientData.name,
        email: fixedClientData.email,
        phone: fixedClientData.phone,
        address1: fixedClientData.address1,
        address2: fixedClientData.address2,
        city: fixedClientData.city,
        zip: fixedClientData.zip,
        country_id: fixedClientData.country_id,
      },
      id: 1,
    };
    console.log("Data sent to addClient:", JSON.stringify(addClientPayload, null, 2));

    // Send request to add client
    const clientResult = await addClient(client, fixedClientData);
    console.log("Client successfully added:", clientResult);

    res.status(200).json({
      message: "Test client addition successful",
      data: clientResult,
    });
  } catch (error) {
    console.error(
      "Error during test client addition:",
      error.response ? error.response.data : error.message,
    );
    res.status(500).json({
      message: "Error during test client addition",
      error: error.message,
    });
  }
});

// Route to add a client with fixed data
app.post("/api/add-client", async (req, res) => {
  try {
    // Obtain user token
    const userToken = await getUserAuthToken();

    // Client data
    const clientData = {
      name: "Vasco",
      email: "radui2004@gmail.com",
      phone: "+351938901782",
      address1: "Example Street, 1",
      address2: "Apt. 101",
      city: "Moscow",
      zip: "123456",
      country_id: 1, // Country ID (e.g., 1 for Russia)
    };

    // Request to add client
    const response = await axios.post(
      `${API_URL}/admin/`,
      {
        method: "addClient",
        params: clientData,
        id: 1,
      },
      {
        headers: {
          "Content-Type": "application/json",
          "X-Company-Login": COMPANY_LOGIN,
          "X-User-Token": userToken,
        },
      },
    );

    if (response.data.error) {
      console.error("Error adding client:", response.data.error);
      return res.status(500).json({ message: "Error adding client" });
    }

    console.log("Client successfully added:", response.data.result);

    res.status(200).json({
      message: "Client successfully added",
      clientId: response.data.result,
    });
  } catch (error) {
    console.error("Error adding client:", error.message);
    res.status(500).json({ message: "Error adding client" });
  }
});

app.get("/api/clients", async (req, res) => {
  try {
    const userToken = await getUserAuthToken();

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

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

    console.log("Clients list:", response.data.result);

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

app.post("/api/book-with-client", async (req, res) => {
  const { clientId, serviceId, performerId, date, time } = req.body;

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

  try {
    const token = await getAuthToken();

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

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

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

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

// Start the server
const PORT = process.env.PORT || 5000;

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

this is my frontend file:


import React, { useState, useEffect } from "react";
import axios from "axios";
import {
  Container,
  TextField,
  Select,
  MenuItem,
  FormControl,
  InputLabel,
  Checkbox,
  FormControlLabel,
  FormGroup,
  Button,
  Typography,
  Grid,
  Box,
  Alert,
} from "@mui/material";

const BookingForm = () => {
  const [services, setServices] = useState({});
  const [performers, setPerformers] = useState({});
  const [selectedService, setSelectedService] = useState("");
  const [selectedPerformer, setSelectedPerformer] = useState("");
  const [selectedDate, setSelectedDate] = useState("");
  const [selectedTime, setSelectedTime] = useState("");
  const [availableTimes, setAvailableTimes] = useState([]);
  const [additionalFields, setAdditionalFields] = useState({});
  const [clients, setClients] = useState([]);
  const [selectedClientId, setSelectedClientId] = useState("");
  const [totalPrice, setTotalPrice] = useState(0);
  const [message, setMessage] = useState("");

  useEffect(() => {
    // Fetch the list of services
    const fetchServices = async () => {
      try {
        const response = await axios.get("http://localhost:5000/api/services");
        console.log("Services fetched:", response.data);
        setServices(response.data);
      } catch (error) {
        console.error("Error fetching services:", error);
      }
    };

    fetchServices();
  }, []);

  useEffect(() => {
    // Fetch the list of performers
    const fetchPerformers = async () => {
      try {
        const response = await axios.get("http://localhost:5000/api/performers");
        console.log("Performers fetched:", response.data);
        setPerformers(response.data);
      } catch (error) {
        console.error("Error fetching performers:", error);
      }
    };

    fetchPerformers();
  }, []);

  useEffect(() => {
    // Fetch the list of clients
    const fetchClients = async () => {
      try {
        const response = await axios.get("http://localhost:5000/api/clients");
        console.log("Clients fetched:", response.data);
        setClients(response.data);
        if (response.data.length > 0) {
          setSelectedClientId(response.data[0].id);
        }
      } catch (error) {
        console.error("Error fetching clients:", error);
      }
    };

    fetchClients();
  }, []);

  useEffect(() => {
    // Update available dates when a performer is selected
    if (selectedPerformer) {
      const fetchAvailableDate = async () => {
        try {
          const response = await axios.get("http://localhost:5000/api/available-dates", {
            params: {
              performerId: selectedPerformer,
            },
          });
          console.log("First available date:", response.data.firstAvailableDate);
          setSelectedDate(response.data.firstAvailableDate);
        } catch (error) {
          console.error("Error fetching available dates:", error);
        }
      };

      fetchAvailableDate();
    }
  }, [selectedPerformer]);

  useEffect(() => {
    // Fetch available times for the selected date
    if (selectedDate && selectedService) {
      const fetchAvailableTimes = async () => {
        try {
          const response = await axios.get("http://localhost:5000/api/available-times", {
            params: {
              date: selectedDate,
              serviceId: selectedService,
              performerId: selectedPerformer,
            },
          });
          console.log("Available times:", response.data.availableTimes);
          setAvailableTimes(response.data.availableTimes);
        } catch (error) {
          console.error("Error fetching available times:", error);
        }
      };

      fetchAvailableTimes();
    }
  }, [selectedDate, selectedService, selectedPerformer]);

  useEffect(() => {
    // Calculate the total price
    let basePrice = services[selectedService]?.price || 0;
    setTotalPrice(basePrice);
  }, [selectedService, services]);

  const handleSubmit = async (e) => {
    e.preventDefault();
    console.log("Submitting booking form with data:", {
      clientId: selectedClientId,
      serviceId: selectedService,
      performerId: selectedPerformer,
      date: selectedDate,
      time: selectedTime,
      additionalFields,
    });

    const bookingPayload = {
      clientId: selectedClientId,
      serviceId: selectedService,
      performerId: selectedPerformer,
      date: selectedDate,
      time: selectedTime,
      additionalFields: additionalFields,
    };

    try {
      const response = await axios.post(
        "http://localhost:5000/api/book-with-client",
        bookingPayload,
      );
      console.log("Booking successful:", response.data);
      setMessage(response.data.message);
    } catch (error) {
      console.error("Error during booking:", error.response?.data || error.message);
      setMessage(error.response?.data?.message || "An error occurred during booking.");
    }
  };

  const handleServiceChange = (e) => {
    setSelectedService(e.target.value);
    setSelectedDate("");
    setSelectedTime("");
    setAvailableTimes([]);
  };

  const handlePerformerChange = (e) => {
    setSelectedPerformer(e.target.value);
    setSelectedDate("");
    setSelectedTime("");
    setAvailableTimes([]);
  };

  return (
    
      
        
          Booking Form
        

        {message && (
          
            {message}
          
        )}

        
          
            {/* Client Selection */}
            {/* If you need to select a client from the list, you can add a dropdown */}
            {/* 
              
                Select Client
                
              
             */}

            {/* Service Selection */}
            
              
                Select Service
                
              
            

            {/* Performer Selection */}
            
              
                Select Performer
                
              
            

            {/* Date Selection */}
            
               {
                  setSelectedDate(e.target.value);
                  setSelectedTime("");
                }}
                required
              />
            

            {/* Time Selection */}
            
              
                Select Time
                
              
            

            {/* Display Total Price */}
            
              Total Price: {totalPrice} EUR
            

            {/* Submit Button */}
            
              
                Book
              
            
          
        
      
    
  );
};

export default BookingForm;

The http request and response I got:
=== Incoming HTTP Request ===
POST /api/book-with-client
Headers: {
host: ‘localhost:5000’,
connection: ‘keep-alive’,
‘content-length’: ‘110’,
‘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: {“clientId”:“2”,“serviceId”:“7”,“performerId”:“8”,“date”:“2024-11-28”,“time”:“13:20:00”,“additionalFields”:{}}
API response when obtaining token: {
result: ‘5ee6a030f6c852ab2b9a6053c9994efa624aa4d8cba722664c56516b7ccc0748’,
id: ‘1’
}
Authorization token obtained: 5ee6a030f6c852ab2b9a6053c9994efa624aa4d8cba722664c56516b7ccc0748
Error booking: {
code: -32061,
message: ‘Client name value is wrong’,
data: { field: ‘name’ }
}
=== 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”:“Error booking”}

Redmine Admin wrote:

please provide raw http request

Ilya Radu wrote:

Redmine Admin wrote:

please provide raw http request

=== Incoming HTTP Request ===
POST /api/book-with-client
Headers: {
host: ‘localhost:5000’,
connection: ‘keep-alive’,
‘content-length’: ‘110’,
‘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: {“clientId”:“2”,“serviceId”:“7”,“performerId”:“8”,“date”:“2024-11-28”,“time”:“13:20:00”,“additionalFields”:{}}
API response when obtaining token: {
result: ‘5ee6a030f6c852ab2b9a6053c9994efa624aa4d8cba722664c56516b7ccc0748’,
id: ‘1’
}
Authorization token obtained: 5ee6a030f6c852ab2b9a6053c9994efa624aa4d8cba722664c56516b7ccc0748
Error booking: {
code: -32061,
message: ‘Client name value is wrong’,
data: { field: ‘name’ }
} === 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”:“Error booking”}

Redmine Admin wrote:

this is not a call to our API, we do not have /api/book-with-client endpoint

Ilya Radu wrote:

Redmine Admin wrote:

this is not a call to our API, we do not have /api/book-with-client endpoint

this is not an call to API, using endpoint /api/book-with-client I send a request on my application from frontend to backend and this route sends a request to https://user-api.simplybook.me.


app.post("/api/book-with-client", async (req, res) => {
  const { clientId, serviceId, performerId, date, time } = req.body;

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

  try {
    const token = await getAuthToken();

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

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

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

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

Redmine Admin wrote:

we need a raw http request to our API

Ilya Radu wrote:

Redmine Admin wrote:

we need a raw http request to our API

=== Raw HTTP Request to Simply Book API ===
POST https://user-api.simplybook.me
Headers: Object [AxiosHeaders] {
Accept: ‘application/json, text/plain, /’,
‘Content-Type’: ‘application/json’,
‘X-Company-Login’: ‘studiofauve’,
‘X-Token’: ‘e037d627733f4b951c5db560a099fa9ec357715bf12e59b4719cc08622b869b5’
}
Request body: {
method: ‘book’,
params: [ ‘3’, ‘7’, ‘2024-11-28 16:25:00’, ‘2’, {}, 1 ],
id: 1
}
=== Raw HTTP Response from Simply Book API ===
Status: 200
Headers: Object [AxiosHeaders] {
server: ‘nginx’,
date: ‘Thu, 28 Nov 2024 13:57:09 GMT’,
‘content-type’: ‘application/json; charset=UTF-8’,
‘content-length’: ‘97’,
‘keep-alive’: ‘timeout=20’,
‘access-control-allow-origin’: ‘',
‘access-control-allow-methods’: ‘POST, GET, OPTIONS’,
‘access-control-allow-headers’: ‘content-type, x-company-login, x-application-token, x-user-token, x-token, x-requested-with, x-csrf-token’,
‘x-xss-protection’: ‘1; mode=block’,
‘x-iplb-request-id’: ‘1F25E754:E6CB_8E2C8CB0:01BB_674876B5_5FE6460:0A27’,
‘strict-transport-security’: ‘max-age=15768000’,
‘x-iplb-instance’: ‘59410’,
connection: ‘close’
}
Response Body: {
error: {
code: -32061,
message: ‘Client name value is wrong’,
data: { field: ‘name’ }
},
id: ‘1’
}
Error booking: {
code: -32061,
message: ‘Client name value is wrong’,
data: { field: ‘name’ }
}
=== 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”:“Error booking”}

Redmine Admin wrote:

i do not see any client data passed to API, do you?
method: ‘book’,
params: [ ‘3’, ‘7’, ‘2024-11-28 16:25:00’, ‘2’, {}, 1 ],

Ilya Radu wrote:

Redmine Admin wrote:

i do not see any client data passed to API, do you?
method: ‘book’,
params: [ ‘3’, ‘7’, ‘2024-11-28 16:25:00’, ‘2’, {}, 1 ],

As I described in the task I have already started to take clients that already exist through the api and in the request I pass their id values.
but I can make the code now to transfer my client’s values if necessary.

Redmine Admin wrote:

you need to use client login plugin and then pass id or always pass client email if no plugin is used

Ilya Radu wrote:

Redmine Admin wrote:

you need to use client login plugin and then pass id or always pass client email if no plugin is used

you mean this plugin?

Ilya Radu wrote:

Ilya Radu wrote:

Redmine Admin wrote:

you need to use client login plugin and then pass id or always pass client email if no plugin is used

you mean this plugin?

Ilya Radu wrote:

Ilya Radu wrote:

Ilya Radu wrote:

Redmine Admin wrote:

you need to use client login plugin and then pass id or always pass client email if no plugin is used

you mean this plugin?

Ilya Radu wrote:

Redmine Admin wrote:

you need to use client login plugin and then pass id or always pass client email if no plugin is used

one minute I’ll try to do it.

Ilya Radu wrote:

Redmine Admin wrote:

you need to use client login plugin and then pass id or always pass client email if no plugin is used

It worked for me, but now Client authorization is required
how can I fix this

Ilya Radu wrote:

Ilya Radu wrote:

Redmine Admin wrote:

you need to use client login plugin and then pass id or always pass client email if no plugin is used

It worked for me, but now Client authorization is required
how can I fix this

so if I get token like that:


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",
        },
      },
    );

    console.log("API response when obtaining token:", response.data);

    if (response.data && response.data.result) {
      const token = response.data.result;
      console.log("Authorization token obtained:", token);
      return token;
    } else {
      throw new Error("Failed to obtain authorization token from API response");
    }
  } catch (error) {
    console.error(
      "Error obtaining authorization token:",
      error.response ? error.response.data : error.message,
    );
    throw error;
  }
};

it gives an error: error: { code: -32068, message: ‘Client authorization required’, data: }

and if I get token like that:


const getUserAuthToken = async () => {
  try {
    const response = await axios.post(
      LOGIN_URL,
      {
        method: "getUserToken",
        params: {
          companyLogin: COMPANY_LOGIN,
          userLogin: "ilya@1-tn.com",
          userPassword: "pk7m7ohocq46fs",
        },
        id: 1,
      },
      {
        headers: {
          "Content-Type": "application/json",
        },
      },
    );

    if (response.data && response.data.result) {
      const userToken = response.data.result;
      console.log("User token obtained:", userToken);
      return userToken;
    } else {
      throw new Error("Failed to obtain user token from API response");
    }
  } catch (error) {
    console.error(
      "Error obtaining user token:",
      error.response ? error.response.data : error.message,
    );
    throw error;
  }
};

it gives an error: error: error: { code: -32600, message: ‘Access denied’, data: }