All Skills

Implement web service integrations in B2C Commerce using LocalServiceRegistry. Use when calling external APIs, configuring service credentials in services.xml, handling HTTP requests/responses, or implementing circuit breakers. Covers HTTP, SOAP, FTP, and SFTP services.

S
$npx skills add SalesforceCommerceCloud/b2c-developer-tooling --skill b2c-webservices

Web Services Skill

This skill guides you through implementing web service integrations in B2C Commerce using the Service Framework.

Overview

The Service Framework provides a structured way to call external services with:

FeatureDescription
ConfigurationService settings managed in Business Manager
Rate LimitingAutomatic throttling to protect external systems
Circuit BreakerAutomatic failure handling to prevent cascade failures
LoggingCommunication logging with sensitive data filtering
MockingTest services without external calls

Service Types

TypeUse CaseProtocol
HTTPREST APIs, webhooksHTTP/HTTPS
HTTPFormForm submissionsHTTP/HTTPS with form encoding
FTPFile transfers (deprecated)FTP
SFTPSecure file transfersSFTP
SOAPSOAP web servicesHTTP/HTTPS with SOAP
GENERICCustom protocolsAny

Service Framework Components

Business Manager Configuration

Services are configured in Administration > Operations > Services:

  1. Service Configuration - General settings (enabled, logging, callbacks)
  2. Service Profile - Rate limiting and circuit breaker settings
  3. Service Credential - URL and authentication credentials

Script Components

ComponentPurpose
LocalServiceRegistryCreates service instances
ServiceCallbackDefines request/response handling
ServiceBase service with common methods
ResultResponse object with status and data

Basic Pattern

'use strict';

var LocalServiceRegistry = require('dw/svc/LocalServiceRegistry');

var myService = LocalServiceRegistry.createService('my.service.id', {
    /**
     * Configure the request before it is sent
     * @param {dw.svc.HTTPService} svc - The service instance
     * @param {Object} params - Parameters passed to service.call()
     * @returns {string} Request body
     */
    createRequest: function (svc, params) {
        svc.setRequestMethod('POST');
        svc.addHeader('Content-Type', 'application/json');
        return JSON.stringify(params);
    },

    /**
     * Parse the response after a successful call
     * @param {dw.svc.HTTPService} svc - The service instance
     * @param {dw.net.HTTPClient} client - The HTTP client with response
     * @returns {Object} Parsed response
     */
    parseResponse: function (svc, client) {
        return JSON.parse(client.text);
    },

    /**
     * Filter sensitive data from logs (required for production)
     * @param {string} msg - The message to filter
     * @returns {string} Filtered message
     */
    filterLogMessage: function (msg) {
        return msg.replace(/("api_key"\s*:\s*")[^"]+"/g, '$1***"');
    }
});

// Call the service
var result = myService.call({ key: 'value' });

if (result.ok) {
    var data = result.object;
} else {
    var error = result.errorMessage;
}

Service Callbacks

CallbackRequiredDescription
createRequestYes*Configure request, return body
parseResponseYes*Parse response, return result object
executeNoCustom execution logic (replaces default)
initServiceClientNoCreate/configure underlying client
mockCallNoReturn mock response (execute phase only)
mockFullNoReturn mock response (entire call)
filterLogMessageRecommendedFilter sensitive data from logs
getRequestLogMessageNoCustom request log message
getResponseLogMessageNoCustom response log message

*Required unless execute is implemented

Result Object

The call() method returns a dw.svc.Result:

PropertyTypeDescription
okBooleanTrue if successful
statusString"OK", "ERROR", or "SERVICE_UNAVAILABLE"
objectObjectResponse from parseResponse
errorNumberError code (e.g., HTTP status)
errorMessageStringError description
unavailableReasonStringWhy service is unavailable
mockResultBooleanTrue if from mock callback

Unavailable Reasons

ReasonDescription
TIMEOUTCall timed out
RATE_LIMITEDRate limit exceeded
CIRCUIT_BROKENCircuit breaker open
DISABLEDService disabled
CONFIG_PROBLEMConfiguration error

Error Handling

var result = myService.call(params);

if (result.ok) {
    return result.object;
}

// Handle different error types
switch (result.status) {
    case 'SERVICE_UNAVAILABLE':
        switch (result.unavailableReason) {
            case 'RATE_LIMITED':
                // Retry later
                break;
            case 'CIRCUIT_BROKEN':
                // Service is down, use fallback
                break;
            case 'TIMEOUT':
                // Request timed out
                break;
        }
        break;
    case 'ERROR':
        // Check HTTP status code
        if (result.error === 401) {
            // Authentication error
        } else if (result.error === 404) {
            // Resource not found
        }
        break;
}

throw new Error('Service error: ' + result.errorMessage);

Log Filtering

Production environments require log filtering to prevent sensitive data exposure:

var myService = LocalServiceRegistry.createService('my.service', {
    createRequest: function (svc, params) {
        // ... configure request
    },

    parseResponse: function (svc, client) {
        return JSON.parse(client.text);
    },

    /**
     * Filter sensitive data from all log messages
     */
    filterLogMessage: function (msg) {
        // Filter API keys
        msg = msg.replace(/api_key=[^&]+/g, 'api_key=***');
        // Filter authorization headers
        msg = msg.replace(/Authorization:\s*[^\r\n]+/gi, 'Authorization: ***');
        // Filter passwords in JSON
        msg = msg.replace(/("password"\s*:\s*")[^"]+"/g, '$1***"');
        return msg;
    },

    /**
     * Custom request log message (optional)
     */
    getRequestLogMessage: function (request) {
        // Return custom message or null for default
        return 'Request: ' + request.substring(0, 100) + '...';
    },

    /**
     * Custom response log message (optional)
     */
    getResponseLogMessage: function (response) {
        // Return custom message or null for default
        return 'Response received';
    }
});

Mocking Services

Use mock callbacks for testing without external calls:

var myService = LocalServiceRegistry.createService('my.service', {
    createRequest: function (svc, params) {
        svc.setRequestMethod('GET');
        svc.addParam('id', params.id);
        return null;
    },

    parseResponse: function (svc, client) {
        return JSON.parse(client.text);
    },

    /**
     * Mock the execute phase only (createRequest and parseResponse still run)
     */
    mockCall: function (svc, request) {
        return {
            statusCode: 200,
            text: JSON.stringify({ id: 1, name: 'Mock Data' })
        };
    },

    /**
     * Or mock the entire call (replaces all phases)
     */
    mockFull: function (svc, params) {
        return { id: params.id, name: 'Full Mock Data' };
    }
});

// Force mock mode
myService.setMock();
var result = myService.call({ id: 123 });

Service Configuration in Business Manager

Creating a Service

  1. Go to Administration > Operations > Services
  2. Click New under Service Configurations
  3. Fill in:
    • Service ID: Unique identifier (e.g., my.api.service)
    • Service Type: HTTP, FTP, SOAP, etc.
    • Enabled: Check to enable
    • Profile: Select or create a profile
    • Credential: Select or create credentials
    • Communication Log: Enable for debugging

Service Profile Settings

SettingDescription
TimeoutMaximum wait time in milliseconds
Rate LimitMaximum calls per time unit
Circuit Breaker EnabledEnable automatic failure handling
Max Circuit Breaker CallsCalls before circuit opens
Circuit Breaker IntervalTime window for tracking failures

Service Credential Settings

SettingDescription
IDCredential identifier
URLBase URL for the service
UserUsername for authentication
PasswordPassword for authentication

Detailed References

Script API Classes

ClassDescription
dw.svc.LocalServiceRegistryCreate service instances
dw.svc.ServiceBase service class
dw.svc.HTTPServiceHTTP service methods
dw.svc.FTPServiceFTP/SFTP service methods
dw.svc.SOAPServiceSOAP service methods
dw.svc.ResultService call result
dw.svc.ServiceConfigService configuration
dw.svc.ServiceProfileRate limit/circuit breaker config
dw.svc.ServiceCredentialAuthentication credentials
dw.net.HTTPClientUnderlying HTTP client
dw.net.FTPClientUnderlying FTP client
dw.net.SFTPClientUnderlying SFTP client