Skip to main content
Glama

Payware MCP Server

Official
by payware
products-api.jsโ€ข21.7 kB
import axios from 'axios'; import FormData from 'form-data'; import { createJWTToken } from '../../core/auth/jwt-token.js'; import { createJWTForPartner } from '../../core/auth/jwt-factory.js'; import { createMinimizedJSON } from '../../core/utils/json-serializer.js'; import { getSandboxUrl, getProductionUrl } from '../../config/env.js'; /** * Product types */ export const PRODUCT_TYPES = { ITEM: 'ITEM', SERVICE: 'SERVICE' }; /** * Price correction types for schedules */ export const PRICE_CORRECTION_TYPES = { DISCOUNT: 'DISCOUNT', INCREMENT: 'INCREMENT' }; /** * Correction methods for schedules */ export const CORRECTION_TYPES = { PERCENTAGE: 'PERCENTAGE', VALUE: 'VALUE' }; /** * Overlap priority options */ export const OVERLAP_PRIORITY = { LOWEST: 'LOWEST', HIGHEST: 'HIGHEST' }; /** * QR code error correction levels */ export const QR_ERROR_CORRECTION = { LOW: 'LOW', MEDIUM: 'MEDIUM', QUARTILE: 'QUARTILE', HIGH: 'HIGH' }; /** * Image formats */ export const IMAGE_FORMATS = { PNG: 'PNG', SVG: 'SVG', JPG: 'JPG' }; /** * Image types */ export const IMAGE_TYPES = { QR: 'QR', BARCODE: 'BARCODE' }; /** * Barcode human readable locations */ export const BARCODE_LOCATIONS = { NONE: 'NONE', BOTTOM: 'BOTTOM', TOP: 'TOP' }; /** * Create authentication headers based on partner type * @param {string} partnerType - merchant, isv, or payment_institution * @param {Object} authParams - Authentication parameters * @returns {Object} Headers for API request */ async function createAuthHeaders(partnerType, authParams) { const baseHeaders = { 'Content-Type': 'application/json', 'Api-Version': '1' }; let tokenData; switch (partnerType) { case 'merchant': case 'payment_institution': // Standard JWT authentication tokenData = createJWTToken( authParams.partnerId, authParams.privateKey, authParams.requestBody ); break; case 'isv': // ISV JWT with OAuth2 tokenData = await createJWTForPartner({ partnerId: authParams.isvPartnerId, privateKey: authParams.privateKey, merchantId: authParams.merchantPartnerId, oauth2Token: authParams.oauth2Token, requestBody: authParams.requestBody }); break; default: throw new Error(`Unknown partner type: ${partnerType}`); } return { ...baseHeaders, 'Authorization': `Bearer ${tokenData.token}` }; } /** * Create authentication headers for multipart/form-data requests */ async function createMultipartAuthHeaders(partnerType, authParams) { const headers = await createAuthHeaders(partnerType, authParams); // Remove Content-Type to let axios set it with boundary for multipart delete headers['Content-Type']; return headers; } // ==================== // PRODUCT MANAGEMENT // ==================== /** * Create a new product */ export async function createProduct({ name, shortDescription, longDescription, sku, upc, shippable = 'FALSE', active = 'FALSE', shop, prData = {}, prOptions = {}, partnerType, useSandbox = false, ...authParams }) { if (!name) { throw new Error('Product name is required'); } const requestBody = { name, shippable, active }; // Optional fields if (shop) requestBody.shop = shop; if (shortDescription) requestBody.shortDescription = shortDescription; if (longDescription) requestBody.longDescription = longDescription; if (sku) requestBody.sku = sku; if (upc) requestBody.upc = upc; if (Object.keys(prData).length > 0) requestBody.prData = prData; if (Object.keys(prOptions).length > 0) requestBody.prOptions = prOptions; const minimizedBody = createMinimizedJSON(requestBody); const headers = await createAuthHeaders(partnerType, { ...authParams, requestBody: minimizedBody }); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.post( `${baseUrl}/products`, minimizedBody, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products`, method: 'POST', requestBody: minimizedBody, statusCode: response.status } }; } catch (error) { throw new Error(`Failed to create product: ${error.response?.data?.message || error.message}`); } } /** * Get list of products */ export async function getProducts({ partnerType, useSandbox = false, ...authParams }) { const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.get( `${baseUrl}/products`, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products`, method: 'GET', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to get products: ${error.response?.data?.message || error.message}`); } } /** * Get product information by ID */ export async function getProduct({ productId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.get( `${baseUrl}/products/${productId}`, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}`, method: 'GET', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to get product: ${error.response?.data?.message || error.message}`); } } /** * Update product */ export async function updateProduct({ productId, name, shortDescription, longDescription, sku, upc, shippable, active, shop, prData = {}, prOptions = {}, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } const requestBody = {}; // Only include fields that are provided if (name !== undefined) requestBody.name = name; if (shop !== undefined) requestBody.shop = shop; if (shortDescription !== undefined) requestBody.shortDescription = shortDescription; if (longDescription !== undefined) requestBody.longDescription = longDescription; if (sku !== undefined) requestBody.sku = sku; if (upc !== undefined) requestBody.upc = upc; if (shippable !== undefined) requestBody.shippable = shippable; if (active !== undefined) requestBody.active = active; if (Object.keys(prData).length > 0) requestBody.prData = prData; if (Object.keys(prOptions).length > 0) requestBody.prOptions = prOptions; const minimizedBody = createMinimizedJSON(requestBody); const headers = await createAuthHeaders(partnerType, { ...authParams, requestBody: minimizedBody }); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.patch( `${baseUrl}/products/${productId}`, minimizedBody, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}`, method: 'PATCH', requestBody: minimizedBody, statusCode: response.status } }; } catch (error) { throw new Error(`Failed to update product: ${error.response?.data?.message || error.message}`); } } /** * Delete product */ export async function deleteProduct({ productId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.delete( `${baseUrl}/products/${productId}`, { headers } ); return { success: true, requestInfo: { url: `${baseUrl}/products/${productId}`, method: 'DELETE', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to delete product: ${error.response?.data?.message || error.message}`); } } /** * Generate product image (QR code or barcode) */ export async function getProductImage({ productId, type = IMAGE_TYPES.QR, qrOptions = {}, barOptions = {}, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } const requestBody = { type }; if (type === IMAGE_TYPES.QR && Object.keys(qrOptions).length > 0) { requestBody.qrOptions = qrOptions; } if (type === IMAGE_TYPES.BARCODE && Object.keys(barOptions).length > 0) { requestBody.barOptions = barOptions; } const minimizedBody = createMinimizedJSON(requestBody); const headers = await createAuthHeaders(partnerType, { ...authParams, requestBody: minimizedBody }); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.post( `${baseUrl}/products/${productId}/image`, minimizedBody, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/image`, method: 'POST', requestBody: minimizedBody, statusCode: response.status } }; } catch (error) { throw new Error(`Failed to get product image: ${error.response?.data?.message || error.message}`); } } // ==================== // PRICE SCHEDULES // ==================== /** * Create price schedule for a product */ export async function createPriceSchedule({ productId, description, priceCorrection = PRICE_CORRECTION_TYPES.DISCOUNT, correctionType = CORRECTION_TYPES.PERCENTAGE, correctionValue = '0.00', dateFrom, dateTo, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } const requestBody = { priceCorrection, correctionType, correctionValue }; if (description) requestBody.description = description; if (dateFrom) requestBody.dateFrom = dateFrom; if (dateTo) requestBody.dateTo = dateTo; const minimizedBody = createMinimizedJSON(requestBody); const headers = await createAuthHeaders(partnerType, { ...authParams, requestBody: minimizedBody }); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.post( `${baseUrl}/products/${productId}/schedules`, minimizedBody, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/schedules`, method: 'POST', requestBody: minimizedBody, statusCode: response.status } }; } catch (error) { throw new Error(`Failed to create price schedule: ${error.response?.data?.message || error.message}`); } } /** * Get product schedules */ export async function getProductSchedules({ productId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.get( `${baseUrl}/products/${productId}/schedules`, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/schedules`, method: 'GET', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to get product schedules: ${error.response?.data?.message || error.message}`); } } /** * Get schedule information */ export async function getSchedule({ productId, scheduleId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } if (!scheduleId) { throw new Error('scheduleId is required'); } const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.get( `${baseUrl}/products/${productId}/schedules/${scheduleId}`, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/schedules/${scheduleId}`, method: 'GET', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to get schedule: ${error.response?.data?.message || error.message}`); } } /** * Update price schedule */ export async function updatePriceSchedule({ productId, scheduleId, description, priceCorrection, correctionType, correctionValue, dateFrom, dateTo, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } if (!scheduleId) { throw new Error('scheduleId is required'); } const requestBody = {}; if (description !== undefined) requestBody.description = description; if (priceCorrection !== undefined) requestBody.priceCorrection = priceCorrection; if (correctionType !== undefined) requestBody.correctionType = correctionType; if (correctionValue !== undefined) requestBody.correctionValue = correctionValue; if (dateFrom !== undefined) requestBody.dateFrom = dateFrom; if (dateTo !== undefined) requestBody.dateTo = dateTo; const minimizedBody = createMinimizedJSON(requestBody); const headers = await createAuthHeaders(partnerType, { ...authParams, requestBody: minimizedBody }); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.patch( `${baseUrl}/products/${productId}/schedules/${scheduleId}`, minimizedBody, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/schedules/${scheduleId}`, method: 'PATCH', requestBody: minimizedBody, statusCode: response.status } }; } catch (error) { throw new Error(`Failed to update schedule: ${error.response?.data?.message || error.message}`); } } /** * Delete price schedule */ export async function deletePriceSchedule({ productId, scheduleId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } if (!scheduleId) { throw new Error('scheduleId is required'); } const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.delete( `${baseUrl}/products/${productId}/schedules/${scheduleId}`, { headers } ); return { success: true, requestInfo: { url: `${baseUrl}/products/${productId}/schedules/${scheduleId}`, method: 'DELETE', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to delete schedule: ${error.response?.data?.message || error.message}`); } } // ==================== // AUDIO/SOUNDBITE MANAGEMENT // ==================== /** * Register audio file for a product */ export async function registerAudio({ productId, audioFile, audioPath, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } if (!audioFile && !audioPath) { throw new Error('Either audioFile buffer or audioPath is required'); } const formData = new FormData(); if (audioFile) { formData.append('file', audioFile); } else if (audioPath) { const fs = await import('fs'); formData.append('file', fs.createReadStream(audioPath)); } const headers = await createMultipartAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.post( `${baseUrl}/products/${productId}/audios/upload`, formData, { headers: { ...headers, ...formData.getHeaders() } } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/audios/upload`, method: 'POST', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to register audio: ${error.response?.data?.message || error.message}`); } } /** * Get product audios */ export async function getProductAudios({ productId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.get( `${baseUrl}/products/${productId}/audios`, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/audios`, method: 'GET', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to get product audios: ${error.response?.data?.message || error.message}`); } } /** * Get audio information */ export async function getAudio({ productId, audioId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } if (!audioId) { throw new Error('audioId is required'); } const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.get( `${baseUrl}/products/${productId}/audios/${audioId}`, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/audios/${audioId}`, method: 'GET', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to get audio: ${error.response?.data?.message || error.message}`); } } /** * Update audio information */ export async function updateAudio({ productId, audioId, title, newProductId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } if (!audioId) { throw new Error('audioId is required'); } const requestBody = {}; if (title !== undefined) requestBody.title = title; if (newProductId !== undefined) requestBody.productId = newProductId; const minimizedBody = createMinimizedJSON(requestBody); const headers = await createAuthHeaders(partnerType, { ...authParams, requestBody: minimizedBody }); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.patch( `${baseUrl}/products/${productId}/audios/${audioId}`, minimizedBody, { headers } ); return { success: true, data: response.data, requestInfo: { url: `${baseUrl}/products/${productId}/audios/${audioId}`, method: 'PATCH', requestBody: minimizedBody, statusCode: response.status } }; } catch (error) { throw new Error(`Failed to update audio: ${error.response?.data?.message || error.message}`); } } /** * Delete audio */ export async function deleteAudio({ productId, audioId, partnerType, useSandbox = false, ...authParams }) { if (!productId) { throw new Error('productId is required'); } if (!audioId) { throw new Error('audioId is required'); } const headers = await createAuthHeaders(partnerType, authParams); const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl(); try { const response = await axios.delete( `${baseUrl}/products/${productId}/audios/${audioId}`, { headers } ); return { success: true, requestInfo: { url: `${baseUrl}/products/${productId}/audios/${audioId}`, method: 'DELETE', statusCode: response.status } }; } catch (error) { throw new Error(`Failed to delete audio: ${error.response?.data?.message || error.message}`); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/payware/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server