whalesky-labs / jd-sdk-php
京东开放平台 PHP SDK,支持京准通、POP、自营、V1 和 SP API
Requires
- php: >=7.4
- ext-curl: *
- ext-json: *
- ext-openssl: *
- guzzlehttp/guzzle: ^7.5
- monolog/monolog: ^1.24 || ^2.0 || ^3.0
- netresearch/jsonmapper: ^1.6
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.75
- phpunit/phpunit: ^9.6
Suggests
- ext-apcu: 京东安全 SDK 的本地密钥缓存
- ext-swoole: Swoole 协程支持(建议 >= 4.5)
- hyperf/guzzle: Hyperf/Swoole 环境下的协程 HTTP 与连接池支持
README
JD Open Platform SDK for PHP
京东开放平台 PHP SDK
京准通、POP 与自营 · V1 与 SP · Guzzle 7 · Swoole 协程连接池
由 WhaleSky Labs 维护
whalesky-labs/jd-sdk-php 是面向京东开放平台的 PHP Composer SDK,统一封装京准通、POP、自营三类官方下载包,并同时提供 V1 与 SP 两套接口的调用入口。
本项目不是京东官方发布的 Composer 包。京东官方下载包中的 Request、Domain、Api、Model 及安全 SDK 是接口定义的权威来源;本项目负责命名空间隔离、统一配置、Guzzle 传输、异常转换、重试和 Swoole 协程连接池。
当前三类官方 SDK 的生成版本如下。京东下载包未提供独立的语义化版本号,因此这里以压缩包文件名中的生成日期标识当前导入快照:
| SDK 类型 | V1 生成版本 | SP 生成版本 |
|---|---|---|
| 京准通 | 2026-08-10 | 2026-08-10 |
| POP | 2026-08-06 | 2026-08-06 |
| 自营 | 2026-08-09 | 2026-08-09 |
运行要求
- PHP 7.4 或更高版本
- cURL 扩展
- JSON 扩展
- OpenSSL 扩展
- Composer 2
主要运行时依赖为 Guzzle 7。使用安全 SDK 时,需要根据京东安全 SDK 的运行方式提供 APCu 或 Yac 缓存。Swoole/Hyperf 支持是可选能力,不影响 PHP-FPM 或普通 CLI 环境使用。
安装
项目尚未发布稳定版本到 Packagist。当前可将 GitHub 仓库注册为 Composer VCS 源后安装 dev-main:
composer config repositories.jd-sdk-php vcs https://github.com/whalesky-labs/jd-sdk-php.git composer require whalesky-labs/jd-sdk-php:dev-main
dev-main 是开发分支,不提供稳定版本兼容承诺。生产项目应提交自身的 composer.lock,并在升级前审查变更;需要严格复现时可在业务项目中锁定已审核的提交引用。
发布稳定版本到 Packagist 后,安装命令将简化为:
composer require whalesky-labs/jd-sdk-php
Swoole 或 Hyperf 项目建议额外安装:
composer require hyperf/guzzle
接口覆盖与选择
当前代码由以下官方下载快照导入:
| 接口类型 | 协议 | 调用入口 | 当前覆盖 | 官方代码文件 |
|---|---|---|---|---|
| 京准通 | V1 | $sdk->jzt()->v1() |
318 个 Request | 740 |
| 京准通 | SP | $sdk->jzt()->sp() |
3 个 operation | 35 |
| POP | V1 | $sdk->pop()->v1() |
564 个 Request | 961 |
| POP | SP | $sdk->pop()->sp() |
135 个 operation | 1,114 |
| 自营 | V1 | $sdk->selfOperated()->v1() |
577 个 Request | 961 |
| 自营 | SP | $sdk->selfOperated()->sp() |
135 个 operation | 1,235 |
此外导入 67 个安全 SDK 文件。来源压缩包名称、由本项目计算的 SHA-256 文件校验值、文件数量及兼容修复记录见 resources/sdk-manifest.json。
京准通、POP 与自营不是同一套接口。三类下载包的 Request、Api 和 Model 覆盖均不同,因此项目保持六套独立命名空间,不对官方接口做合并或推断。
命名空间映射如下:
| 接口集 | 根命名空间 |
|---|---|
| 京准通 V1 | JdSdk\Api\Jzt\V1 |
| 京准通 SP | JdSdk\Api\Jzt\Sp |
| POP V1 | JdSdk\Api\Pop\V1 |
| POP SP | JdSdk\Api\Pop\Sp |
| 自营 V1 | JdSdk\Api\SelfOperated\V1 |
| 自营 SP | JdSdk\Api\SelfOperated\Sp |
| 安全 SDK | ACES |
定位接口类
接口权限、字段定义和业务规则以京东开放平台文档为准。本项目不维护另一份接口目录,避免它与官方下载包产生版本漂移。
V1 可以按官方 API 方法名搜索 Request。例如定位 jingdong.pop.order.get:
rg -l 'jingdong\.pop\.order\.get' src/Api/Pop/V1/Request
SP 可以按官方 operation 名或资源路径搜索 Api。例如定位 listOrders:
rg -l 'function listOrders\(' src/Api/Pop/Sp
搜索前应先确定店铺类型和协议;不要因为 POP 与自营存在同名类,就假设其参数、响应或权限完全相同。
快速开始
<?php declare(strict_types=1); require __DIR__ . '/vendor/autoload.php'; use JdSdk\JdSdk; $sdk = new JdSdk( $appKey, $appSecret, ['access_token' => $accessToken] );
建议按京东开放平台应用维度复用 JdSdk 实例。凭证和 Access Token 应由业务系统、密钥管理服务或配置中心提供,不要写入仓库。
调用京准通 V1
use JdSdk\Api\Jzt\V1\Request\JztFindAllSubPinsRequest; $result = $sdk->jzt()->v1()->callApi( JztFindAllSubPinsRequest::class );
京准通通常使用独立应用凭证和授权 Token。不要使用同一个 JdSdk 实例同时承载京准通和其他应用的不同授权上下文。
调用京准通 SP
use JdSdk\Api\Jzt\Sp\sp\data\v0\api\ReportSchemasApi; use JdSdk\Api\Jzt\Sp\sp\data\v0\model\GetReportSchemasRequest; $request = $sdk->jzt()->sp()->model(GetReportSchemasRequest::class, [ 'subject_info' => $subjectInfo, ]); $response = $sdk->jzt()->sp()->callApi( ReportSchemasApi::class, 'getReportSchemas', [$reportSchemaId, $request] );
调用 POP V1
use JdSdk\Api\Pop\V1\Request\PopOrderGetRequest; $result = $sdk->pop()->v1()->callApi( PopOrderGetRequest::class, [ 'order_id' => '1234567890', 'optional_fields' => 'orderInfo,venderInfo', ] );
V1 调用返回数组。京东返回 error_response 时,SDK 抛出统一的 JdSdk\Core\Exception\ApiException。
调用 POP SP
use JdSdk\Api\Pop\Sp\sp\order\v0\api\OrdersApi; use JdSdk\Api\Pop\Sp\sp\order\v0\model\ListOrdersRequest; $request = $sdk->pop()->sp()->model(ListOrdersRequest::class, [ 'page' => 1, 'page_size' => 20, 'start_time' => strtotime('-1 day') * 1000, 'end_time' => time() * 1000, ]); $response = $sdk->pop()->sp()->callApi( OrdersApi::class, 'listOrders', [$request] );
SP 返回类型以官方生成方法为准;该示例返回官方响应 Model。使用 callApi() 时,官方 SP ApiException 会转换为本项目统一的 ApiException。
自营接口的调用方式相同,只需切换到 selfOperated() 并使用 JdSdk\Api\SelfOperated 命名空间下的官方类。
公共入口
本项目维护的封装层提供以下主要入口:
| 方法 | 返回值 | 用途 |
|---|---|---|
JdSdk::jzt() |
ShopClient |
选择京准通接口集 |
JdSdk::pop() |
ShopClient |
选择 POP 接口集 |
JdSdk::selfOperated() |
ShopClient |
选择自营接口集 |
ShopClient::v1() |
V1Client |
选择 V1 协议 |
ShopClient::sp() |
SpClient |
选择 SP 协议 |
JdSdk::config() |
JdConfig |
读取或调整 SDK 配置 |
JdSdk::security() |
ACES\TDEClient |
创建京东安全 SDK 客户端 |
JdSdk::poolStats() |
array |
获取当前进程的客户端与连接池统计 |
JdSdk::shutdown() |
void |
释放静态客户端和 SDK 连接池 |
V1 的主要调用方法是 callApi()、request()、domain() 和 execute();SP 的主要调用方法是 callApi()、model()、api() 和 configuration()。官方 Request、Domain、Api 和 Model 的公共方法不由本项目重新定义。
V1 API
参数映射
V1Client::callApi() 根据 Request setter 注入参数。以下两种形式都会匹配 setOrderId():
['orderId' => '1234567890'] ['order_id' => '1234567890']
无法匹配 setter 的参数会交给官方 Request 的 putOtherTextParam()。字段名称、必填条件和业务含义仍以京东开放平台文档为准。
构造官方 Request
需要调用官方 Request 的额外方法时,可以先创建对象再执行:
use JdSdk\Api\SelfOperated\V1\Request\AigcCopilotTestHelloRequest; $request = $sdk->selfOperated()->v1()->request( AigcCopilotTestHelloRequest::class, ['param1' => 'hello'] ); $request->setVersion('2.0'); $result = $sdk->selfOperated()->v1()->execute($request);
单次调用需要覆盖默认 Access Token 时,可传入 callApi() 的第三个参数:
$result = $sdk->pop()->v1()->callApi( PopOrderGetRequest::class, ['order_id' => '1234567890'], $requestAccessToken );
构造 Domain 对象
$caller = $sdk->pop()->v1()->domain( 'WareStockSkuFivestarSet\\CallerParam' ); $caller->setPin('example-pin');
V1 Request 和 Domain 必须属于当前选择的 POP 或自营命名空间;跨类型执行会抛出 InvalidApiException。
SP API
Model 与 Api
SP 保留 OpenAPI Generator 生成的 Model、Api、方法名和返回类型。model() 接受完整类名或相对于当前 SP 根命名空间的类名:
$request = $sdk->pop()->sp()->model( 'sp\\address\\v0\\model\\ListAreasRequest', ['level' => 2, 'parent_id' => 10] );
推荐通过 callApi() 调用,以获得统一异常转换。需要直接访问官方 Api 对象时,可以使用:
use JdSdk\Api\Pop\Sp\sp\address\v0\api\AreasApi; $api = $sdk->pop()->sp()->api(AreasApi::class); $response = $api->listAreas($request);
直接调用官方 Api 对象时,异常类型遵循该官方命名空间,而不是本项目统一异常类型。
异步与并发
官方 SP Api 提供异步方法。通过 callApi() 调用异步方法时,Promise 中的官方 SP ApiException 同样会被转换为本项目的统一 ApiException:
use GuzzleHttp\Promise\Utils; $promises = [ 'first' => $sdk->pop()->sp()->callApi( OrdersApi::class, 'listOrdersAsync', [$firstRequest] ), 'second' => $sdk->pop()->sp()->callApi( OrdersApi::class, 'listOrdersAsync', [$secondRequest] ), ]; $responses = Utils::unwrap($promises);
V1 官方协议只提供同步 execute()。V1 并发应由业务任务、进程或 Swoole 协程调度。
配置
$sdk = new JdSdk($appKey, $appSecret, [ 'access_token' => $accessToken, 'v1_server_url' => 'https://api.jd.com/routerjson', 'sp_server_url' => 'https://api-cn.jd.com/rest', 'timeout' => [ 'connect' => 5000, 'read' => 15000, ], 'retry' => [ 'enable' => true, 'max_times' => 2, 'interval' => 200, 'non_idempotent' => false, ], 'pool' => [ 'max_connections' => 50, 'max_idle_time' => 60, 'wait_timeout' => 3.0, ], 'debug' => false, 'user_agent' => 'MyApplication/1.0', ]);
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
access_token |
string |
'' |
默认 Access Token |
v1_server_url |
string |
https://api.jd.com/routerjson |
V1 网关地址 |
sp_server_url |
string |
https://api-cn.jd.com/rest |
SP 网关地址 |
timeout.connect |
int |
5000 |
连接超时,单位毫秒 |
timeout.read |
int |
15000 |
请求总超时,单位毫秒 |
retry.enable |
bool |
true |
是否启用重试中间件 |
retry.max_times |
int |
2 |
最大重试次数,不含首次请求 |
retry.interval |
int |
200 |
首次重试间隔,单位毫秒;后续指数退避 |
retry.non_idempotent |
bool |
false |
是否允许重试非幂等请求 |
pool.max_connections |
int |
50 |
单 Worker 最大连接数,范围 1–1000 |
pool.max_idle_time |
int |
60 |
空闲连接保留时间,单位秒;0 表示不按空闲时间淘汰 |
pool.wait_timeout |
float |
3.0 |
等待可用连接的超时,单位秒 |
debug |
bool |
false |
是否启用 Guzzle 调试输出 |
user_agent |
string |
JdSdk-PHP/1.0 |
HTTP User-Agent |
配置对象支持有限的链式调整:
$sdk->config() ->setAccessToken($newAccessToken) ->setTimeout(3000, 10000) ->setRetryConfig(true, 2, 200, false) ->setDebug(false);
应在首次调用 pop() 或 selfOperated() 前完成应用凭证、网关和 SP 配置。已经创建的官方 SP Configuration 对象不会因后续配置变更而自动重建。
异常处理
use JdSdk\Core\Exception\ApiException; use JdSdk\Core\Exception\ConfigurationException; use JdSdk\Core\Exception\HttpException; use JdSdk\Core\Exception\InvalidApiException; use JdSdk\Api\Pop\V1\Request\PopOrderGetRequest; try { $result = $sdk->pop()->v1()->callApi( PopOrderGetRequest::class, ['order_id' => '1234567890'] ); } catch (ApiException $exception) { $apiCode = $exception->getApiCode(); $responseData = $exception->getResponseData(); } catch (HttpException $exception) { $statusCode = $exception->getStatusCode(); $responseBody = $exception->getResponseBody(); } catch (InvalidApiException | ConfigurationException $exception) { $message = $exception->getMessage(); }
| 异常 | 含义 |
|---|---|
ApiException |
V1 error_response 或经 callApi() 转换后的 SP 官方 API 异常 |
HttpException |
V1 网络失败、非 2xx HTTP 响应或无法解析的响应 |
InvalidApiException |
类、方法或 POP/自营接口集不匹配 |
ConfigurationException |
凭证、URL、超时、重试或连接池配置无效 |
不要依赖异常消息解析错误码;应使用 getApiCode()、getResponseData()、getStatusCode() 和 getResponseBody()。
重试语义
默认仅在同时满足以下条件时重试:
- 请求方法为
GET、HEAD、OPTIONS或DELETE; - 发生连接异常,或响应状态为 HTTP 429 / 5xx;
- 尚未达到
retry.max_times。
V1 和多数写接口使用 POST,因此默认不会自动重试。只有在业务方确认接口及请求具备幂等性,并能接受重复提交风险时,才应设置:
['retry' => ['non_idempotent' => true]]
SDK 不生成业务幂等键,也不能替代订单、发货、退款等业务操作自身的幂等控制。
并发与 Swoole
HTTP 客户端在实际发送请求时检测运行环境,因此 SDK 实例可以在 Worker 启动阶段创建,在后续协程中复用。
| 运行环境 | 传输策略 |
|---|---|
Hyperf PoolHandler 可用 |
使用 Hyperf 原生连接池 |
| 协程 Handler 可用 | 使用 SDK Worker 级池包装协程 Guzzle Client |
| 原生 Swoole | 使用 SDK Worker 级池;非阻塞网络需要应用正确启用 runtime hook 或协程 Handler |
| PHP-FPM / 普通 CLI | 按传输配置复用进程级 Guzzle Client |
池化客户端会在同步或异步请求完成后归还客户端。连接池用于控制长生命周期 Worker 内的客户端数量并降低文件描述符耗尽风险,但池大小仍需根据并发量、上游限流和 Worker 数量进行容量规划。
查看运行环境和连接池状态:
$stats = JdSdk::poolStats();
返回值包含:
environment:fpm、swoole-sync或swoole-coroutinestandard_clients:当前进程内标准客户端数量native_pools:Hyperf 原生池客户端数量pools:SDK 连接池统计,包括活跃、空闲、等待和累计请求数
Worker 退出、长生命周期进程重载或测试隔离时,应释放静态客户端和连接池:
JdSdk::shutdown();
签名机制
V1 与 SP 均直接使用京东官方下载包中的签名逻辑。当前官方算法为:
- 按参数名排序;
- 拼接
appSecret + 参数名和值 + appSecret; - 计算 MD5;
- 将结果转为大写。
该签名不是 HMAC-SHA256。应用密钥不得写入日志、异常上下文或版本库。
安全 SDK
官方下载包中的安全 SDK 通过 ACES 命名空间提供敏感数据加解密能力:
$securityClient = $sdk->security();
也可以为安全 SDK 单独指定 Access Token:
$securityClient = $sdk->security($securityAccessToken);
安全 SDK 会按京东官方逻辑请求并缓存安全凭证,需要相应应用权限、网络访问和 APCu/Yac 缓存。它与 V1/SP 请求签名是两项不同能力。
更新官方 SDK
不要直接修改以下生成目录:
src/Api/Jztsrc/Api/Popsrc/Api/SelfOperatedsrc/Security
这些目录会在下次导入时整体替换。更新官方下载包后执行:
php scripts/import-official-sdk.php \
--jzt-dir=/path/to/jd-api-sdk-php-jzt \
--pop-dir=/path/to/jd-api-sdk-php-pop \
--self-operated-dir=/path/to/jd-api-sdk-php-self-operated
composer dump-autoload -o
composer test
导入器执行以下工作:
- 从三个下载目录发现 V1、SP 和安全 SDK 压缩包;
- 将京准通、POP、自营的 V1 与 SP 导入独立命名空间;
- 校验三份安全 SDK 压缩包哈希相同后只导入一份;
- 应用已知且形态受约束的生成器兼容修复;
- 原子替换生成目录并重建 manifest。
导入器不会修改官方下载目录,也不会把官方类转换为自定义 REST 定义。若压缩包结构、安全 SDK 哈希或已知缺陷形态发生变化,导入应失败并由维护者审查,而不是静默选择或宽泛改写。
所有兼容修复必须由导入器生成,并记录在 resources/sdk-manifest.json;不要在导入后手工修补生成文件。
项目结构
src/
├── Api/
│ ├── Jzt/{V1,Sp}/
│ ├── Pop/{V1,Sp}/
│ └── SelfOperated/{V1,Sp}/
├── Core/
│ ├── Client/
│ ├── Config/
│ ├── Exception/
│ ├── Http/
│ ├── Support/
│ └── Swoole/
├── Security/
└── JdSdk.php
src/Api、src/Security:由官方下载包生成,不作为手工维护区。src/Core、src/JdSdk.php:本项目维护的稳定封装层。scripts/import-official-sdk.php:可重复执行的官方 SDK 导入器。resources/sdk-manifest.json:来源和兼容修复审计记录。tests:封装层、官方调用主链和导入结果测试。
项目没有额外的 Official/ 目录。Api 和 Security 已清楚表达上游代码职责,再增加中间层不会改善更新边界。
版本与变更
稳定版本计划遵循 Semantic Versioning。每次发布的新增能力、行为变更、兼容性说明、修复和安全更新记录在 CHANGELOG.md;尚未发布的内容保留在 Unreleased 章节。
更新官方 SDK 时,除更新 Changelog 外,还必须提交重新生成的 resources/sdk-manifest.json,以便审计上游压缩包、文件数量和兼容修复。
CI 与发布
CI 在 main 分支推送、Pull Request 和手动触发时运行,使用 PHP 7.4–8.4 验证 Composer 元数据、依赖安装和 PHPUnit 测试。PHP 7.4 使用最低兼容依赖,其他版本分别解析其最高兼容依赖;代码风格在独立的 PHP 7.4 Job 中检查。
本项目维护的 PHP 代码使用 PHP CS Fixer 统一格式,并添加项目来源头注释。检查或修复代码风格:
composer cs-check composer cs-fix
格式化范围仅包括 .php-cs-fixer.php、src/Core、src/JdSdk.php、scripts 和 tests。官方下载生成的 src/Api 与 src/Security 不纳入格式化,避免修改上游代码和影响后续导入更新。
Release 仅通过 GitHub Actions 手动触发,提供以下参数:
| 参数 | 说明 |
|---|---|
mode |
auto 自动计算版本;manual 使用手动版本 |
version |
手动版本号,例如 5.0.0;仅 manual 模式必填 |
publish_release |
是否创建 vX.Y.Z Tag 并发布 GitHub Release |
source_branch |
发布来源分支,默认 main |
首次使用 auto 发布时版本为 1.0.0;后续基于最新 vX.Y.Z Tag 自动递增补丁版本。手动版本接受 5.0.0 或 v5.0.0,最终统一创建 v5.0.0 形式的 Tag。
发布工作流会校验 Unreleased、Composer 元数据并运行全部测试,GitHub Release 正文直接取自 Changelog 的 Unreleased 章节,版本号仅用于 Tag 和 Release 名称。publish_release=false 时仅执行发布预检,不创建 Tag 或 GitHub Release;Packagist 应通过 GitHub Webhook 或 Packagist GitHub Service 跟踪正式 Tag。
测试
安装开发依赖并执行默认单元测试:
composer install
composer test
所有测试统一位于 tests/:默认离线测试位于其功能子目录,真实接口测试位于 tests/Integration/。两类测试使用独立 PHPUnit 配置,默认测试会显式排除真实接口目录。
默认测试使用 Mock HTTP 响应,不读取真实应用凭证,也不会访问京东网关。真实接口验收只调用查询类接口:
cp .env.example .env
# 在 .env 中填写测试目标及对应应用凭证
composer test-integration
JD_INTEGRATION_TARGETS 支持以逗号分隔的 jzt-v1、jzt-sp、pop-v1、pop-sp、self-operated-v1 和 self-operated-sp。每个目标仅在显式选中时运行;选中京准通目标需填写 JD_JZT_APP_KEY、JD_JZT_APP_SECRET、JD_JZT_ACCESS_TOKEN,选中 POP 或自营目标需填写对应前缀的凭证。jzt-sp 还需提供报表 Schema ID 和主体信息。项目的 .env 仅供真实接口测试使用并已被 Git 忽略,凭证不得写入 .env.example 或提交到仓库;也可以直接注入同名进程环境变量,其优先级高于文件。
jzt-v1 调用 jingdong.jzt.findAllSubPins 查询当前授权京准通账号的子账号,jzt-sp 查询指定报表 Schema;pop-v1 调用 jingdong.seller.vender.info.get 获取当前授权店铺信息。V1 测试运行时会打印京东完整响应 JSON;输出不包含 App Secret、Access Token 或请求签名,但可能包含真实账号或店铺信息,请勿粘贴到公开环境。
集成测试不属于默认 composer test 或公开 CI,因为它依赖应用类型、接口授权、有效 Token 和京东网关可用性。未设置测试目标、目标名称无效、所选目标缺少凭证、鉴权失败或接口返回失败时,composer test-integration 都会失败;未选中的接口集显示为跳过,失败信息会脱敏已配置的应用凭证。
使用支持覆盖率的 PHP 运行时生成报告,例如:
phpdbg -qrr vendor/bin/phpunit --coverage-text
当前基线使用 PHP 8.1.31 和 PHPUnit 9.6.35:
- 47 项测试
- 150 个断言
src、scripts和tests下共 5,147 个 PHP 文件通过语法检查
当前 PHP CLI 未加载覆盖率驱动,因此本次没有沿用变更前的覆盖率百分比。生成覆盖率时只计算 src/Core 与 src/JdSdk.php;官方生成的 5,046 个 API 文件不计入覆盖率分母。测试使用代表性 V1/SP 接口验证签名、请求构造、同步/异步调用和异常转换。
贡献
提交 Pull Request 前请遵守以下边界:
- 不手工编辑
src/Api或src/Security;上游兼容变更应修改导入器并重建 manifest。 - 京准通、POP、自营及 V1、SP 必须保持独立,除非有官方下载包和测试证明可以安全合并。
- 新增或修改封装行为时补充对应测试。
- 不提交应用密钥、Access Token、业务数据、日志、缓存或官方下载压缩包。
- 提交前运行
composer validate --strict和composer test。
License
本项目维护的封装层在 Composer 元数据中声明为 MIT License。随官方下载包导入的生成代码、安全 SDK、证书及相关资产仍受京东官方适用条款约束;使用和再分发前请自行确认相应授权条件。
“京东”及相关标识归其权利人所有。本项目为社区维护项目,不代表京东官方背书、认证或支持。