b2c-webservices
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWeb Services Skill
Web服务技能
This skill guides you through implementing web service integrations in B2C Commerce using the Service Framework.
本技能将指导你使用Service Framework在B2C Commerce中实现Web服务集成。
Overview
概述
The Service Framework provides a structured way to call external services with:
| Feature | Description |
|---|---|
| Configuration | Service settings managed in Business Manager |
| Rate Limiting | Automatic throttling to protect external systems |
| Circuit Breaker | Automatic failure handling to prevent cascade failures |
| Logging | Communication logging with sensitive data filtering |
| Mocking | Test services without external calls |
Service Framework提供了结构化的外部服务调用方式,具备以下特性:
| 功能 | 描述 |
|---|---|
| Configuration | 可在Business Manager中管理服务设置 |
| Rate Limiting | 自动限流以保护外部系统 |
| Circuit Breaker | 自动故障处理,防止级联故障 |
| Logging | 支持通信日志,可自动过滤敏感数据 |
| Mocking | 无需调用外部服务即可完成服务测试 |
Service Types
服务类型
| Type | Use Case | Protocol |
|---|---|---|
| REST APIs, webhooks | HTTP/HTTPS |
| Form submissions | HTTP/HTTPS with form encoding |
| File transfers (deprecated) | FTP |
| Secure file transfers | SFTP |
| SOAP web services | HTTP/HTTPS with SOAP |
| Custom protocols | Any |
| 类型 | 使用场景 | 协议 |
|---|---|---|
| REST API、webhook调用 | HTTP/HTTPS |
| 表单提交 | 带表单编码的HTTP/HTTPS |
| 文件传输(已废弃) | FTP |
| 安全文件传输 | SFTP |
| SOAP Web服务调用 | 带SOAP的HTTP/HTTPS |
| 自定义协议 | 任意协议 |
Service Framework Components
Service Framework 组件
Business Manager Configuration
Business Manager 配置
Services are configured in Administration > Operations > Services:
- Service Configuration - General settings (enabled, logging, callbacks)
- Service Profile - Rate limiting and circuit breaker settings
- Service Credential - URL and authentication credentials
服务在 Administration > Operations > Services 路径下配置:
- 服务配置 - 通用设置(启用状态、日志、回调)
- 服务配置文件 - 限流和circuit breaker设置
- 服务凭证 - URL和身份验证凭证
Script Components
脚本组件
| Component | Purpose |
|---|---|
| Creates service instances |
| Defines request/response handling |
| Base service with common methods |
| Response object with status and data |
| 组件 | 用途 |
|---|---|
| 创建服务实例 |
| 定义请求/响应处理逻辑 |
| 包含通用方法的基础服务类 |
| 包含状态和数据的响应对象 |
Basic Pattern
基础模式
javascript
'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;
}javascript
'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
服务回调
| Callback | Required | Description |
|---|---|---|
| Yes* | Configure request, return body |
| Yes* | Parse response, return result object |
| No | Custom execution logic (replaces default) |
| No | Create/configure underlying client |
| No | Return mock response (execute phase only) |
| No | Return mock response (entire call) |
| Recommended | Filter sensitive data from logs |
| No | Custom request log message |
| No | Custom response log message |
*Required unless is implemented
execute| 回调 | 是否必填 | 描述 |
|---|---|---|
| 是* | 配置请求,返回请求体 |
| 是* | 解析响应,返回结果对象 |
| 否 | 自定义执行逻辑(替代默认逻辑) |
| 否 | 创建/配置底层客户端 |
| 否 | 返回Mock响应(仅执行阶段生效) |
| 否 | 返回Mock响应(全调用流程生效) |
| 推荐实现 | 过滤日志中的敏感数据 |
| 否 | 自定义请求日志内容 |
| 否 | 自定义响应日志内容 |
*除非实现了,否则必填
executeResult Object
结果对象
The method returns a :
call()dw.svc.Result| Property | Type | Description |
|---|---|---|
| Boolean | True if successful |
| String | "OK", "ERROR", or "SERVICE_UNAVAILABLE" |
| Object | Response from |
| Number | Error code (e.g., HTTP status) |
| String | Error description |
| String | Why service is unavailable |
| Boolean | True if from mock callback |
call()dw.svc.Result| 属性 | 类型 | 描述 |
|---|---|---|
| 布尔值 | 调用成功则为true |
| 字符串 | 取值为"OK"、"ERROR"或"SERVICE_UNAVAILABLE" |
| 对象 | |
| 数字 | 错误码(例如HTTP状态码) |
| 字符串 | 错误描述 |
| 字符串 | 服务不可用的原因 |
| 布尔值 | 来自Mock回调则为true |
Unavailable Reasons
不可用原因
| Reason | Description |
|---|---|
| Call timed out |
| Rate limit exceeded |
| Circuit breaker open |
| Service disabled |
| Configuration error |
| 原因 | 描述 |
|---|---|
| 调用超时 |
| 超过限流阈值 |
| Circuit Breaker已打开 |
| 服务已禁用 |
| 配置错误 |
Error Handling
错误处理
javascript
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);javascript
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:
javascript
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';
}
});生产环境需要开启日志过滤,避免敏感数据泄露:
javascript
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
服务Mock
Use mock callbacks for testing without external calls:
javascript
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 });可使用Mock回调在不调用外部服务的情况下完成测试:
javascript
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
Business Manager中的服务配置
Creating a Service
创建服务
- Go to Administration > Operations > Services
- Click New under Service Configurations
- 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 ID: Unique identifier (e.g.,
- 进入 Administration > Operations > Services 路径
- 点击服务配置下的新建按钮
- 填写以下信息:
- Service ID:唯一标识符(例如)
my.api.service - Service Type:HTTP、FTP、SOAP等
- Enabled:勾选以启用服务
- Profile:选择或创建配置文件
- Credential:选择或创建凭证
- Communication Log:调试时可开启
- Service ID:唯一标识符(例如
Service Profile Settings
服务配置文件设置
| Setting | Description |
|---|---|
| Timeout | Maximum wait time in milliseconds |
| Rate Limit | Maximum calls per time unit |
| Circuit Breaker Enabled | Enable automatic failure handling |
| Max Circuit Breaker Calls | Calls before circuit opens |
| Circuit Breaker Interval | Time window for tracking failures |
| 设置项 | 描述 |
|---|---|
| Timeout | 最大等待时间(毫秒) |
| Rate Limit | 单位时间内最大调用次数 |
| Circuit Breaker Enabled | 开启自动故障处理 |
| Max Circuit Breaker Calls | Circuit Breaker打开前的最大失败调用次数 |
| Circuit Breaker Interval | 故障统计的时间窗口 |
Service Credential Settings
服务凭证设置
| Setting | Description |
|---|---|
| ID | Credential identifier |
| URL | Base URL for the service |
| User | Username for authentication |
| Password | Password for authentication |
| 设置项 | 描述 |
|---|---|
| ID | 凭证标识符 |
| URL | 服务的基础URL |
| User | 身份验证用户名 |
| Password | 身份验证密码 |
Detailed References
详细参考
- HTTP Services - REST API integrations
- FTP/SFTP Services - File transfer operations
- SOAP Services - SOAP web service integrations
- Services XML - Import/export service configurations
- HTTP Services - REST API集成
- FTP/SFTP Services - 文件传输操作
- SOAP Services - SOAP Web服务集成
- Services XML - 导入/导出服务配置
Script API Classes
脚本API类
| Class | Description |
|---|---|
| Create service instances |
| Base service class |
| HTTP service methods |
| FTP/SFTP service methods |
| SOAP service methods |
| Service call result |
| Service configuration |
| Rate limit/circuit breaker config |
| Authentication credentials |
| Underlying HTTP client |
| Underlying FTP client |
| Underlying SFTP client |
| 类 | 描述 |
|---|---|
| 创建服务实例 |
| 基础服务类 |
| HTTP服务方法 |
| FTP/SFTP服务方法 |
| SOAP服务方法 |
| 服务调用结果 |
| 服务配置 |
| 限流/Circuit Breaker配置 |
| 身份验证凭证 |
| 底层HTTP客户端 |
| 底层FTP客户端 |
| 底层SFTP客户端 |