goletter / hyperf-card
Hyperf 多平台发卡 SDK(Airwallex / Slash / Lampay / Photonpay / Wasabi),含 Factory、Bundle 与可选统一适配层
Requires
- php: >=8.1
- ext-json: *
- ext-openssl: *
- guzzlehttp/guzzle: ^7.0
Requires (Dev)
None
Suggests
- hyperf/framework: Required to use ConfigProvider in Hyperf applications.
Provides
None
Conflicts
None
Replaces
- goletter/card: v1.0.0
README
多平台卡片 API SDK,支持 Airwallex、Slash、Lampay、Photonpay、Wasabi。
安装
composer require goletter/hyperf-card
依赖要求
- PHP >= 8.1
- ext-openssl / ext-json
- GuzzleHttp >= 7.0
架构说明
本包分两层(请按场景选用):
| 层级 | 入口 | 命名空间 | 行为 |
|---|---|---|---|
| SDK 层 | $bundle->card() / api() |
Platforms\{Vendor}\Api\CardApi |
官方路径 + 原始 JSON;失败抛 *ApiException |
| 适配层 | $bundle->adapter() |
Platforms\{Vendor}\Adapter\CardAdapter |
{code,msg,data} + 字段/状态映射(Lampay 无适配层,adapter() 为 null) |
推荐:CardFactory → CardPlatformBundle → 按需 card() 或 adapter()。
工厂模式(推荐,以 Slash 为例)
统一入口是 CardFactory,返回 CardPlatformBundle:
CardFactory::slash($config)
│
▼
CardPlatformBundle
├─ name = 'slash'
├─ platform = Slash 实例
├─ client = Slash\Client
├─ card()/api() → Slash\Api\CardApi (薄 SDK)
└─ adapter() → Slash\Adapter\CardAdapter (Result 适配层)
1. 静态创建(任意 PHP 项目)
三种写法等价,任选其一:
use Goletter\Card\CardFactory; use Goletter\Card\Platforms\Slash\Exceptions\SlashApiException; $config = [ 'base_url' => 'https://api.slash.com', // 也可用 baseUrl 'api_key' => 'your-api-key', // 也可用 apiKey 'timeout' => 60, // 可选:敏感信息解密 // 'rsa_public_key' => '...', // 'private_key' => file_get_contents('/secure/slash-private.pem'), // 'vault_base_url' => 'https://vault.slash.com', // 可选:更新限额时的商户白名单 // 'merchant_allowlist' => ['merchant_v2_xxx'], ]; // ① 命名方法(IDE 提示最好) $bundle = CardFactory::slash($config); // ② 字符串平台名 $bundle = CardFactory::make('slash', $config); // ③ 数字别名(与 publish/card.php 中 platforms 映射一致,默认 1 = slash) $bundle = CardFactory::make(1, $config);
2. 通过 Bundle 调用 Slash
适配层(业务统一字段,推荐现有业务继续用)
$adapter = $bundle->adapter(); // Slash\Adapter\CardAdapter try { // 返回 {code, msg, data} $page = $adapter->cardList([ 'cursor' => '', // 首页传空;下一页用上一页 data.cursor ]); if ($page['code'] !== 1) { throw new \RuntimeException($page['msg'] ?? 'list failed'); } foreach ($page['data']['data'] ?? [] as $card) { // ... } $info = $adapter->cardInfo(['card_id' => 'card_xxx']); $adapter->cardFreeze(['card_id' => 'card_xxx']); $adapter->cardUnfreeze(['card_id' => 'card_xxx']); $adapter->cardCancel(['card_id' => 'card_xxx']); } catch (SlashApiException $e) { echo $e->getMessage(); print_r($e->getResponse()); }
分页拉取全部卡片:
$adapter = $bundle->adapter(); $allCards = []; $cursor = ''; do { $page = $adapter->listCardsPaginated($cursor === '' ? null : $cursor); if ($page['code'] !== 1) { break; } $allCards = array_merge($allCards, $page['data']['data'] ?? []); $cursor = (string) ($page['data']['cursor'] ?? ''); } while ($cursor !== '');
SDK 层(官方原始响应)
$api = $bundle->card(); // 等同 $bundle->api() // 原始 Slash JSON;失败直接抛 SlashApiException $raw = $api->listCards(['cursor' => '', 'sort' => 'createdAt', 'sortDirection' => 'DESC']); $detail = $api->getCard('card_xxx', ['include_pan' => 'true', 'include_cvv' => 'true']); $api->patchCard('card_xxx', ['status' => 'paused']);
3. Hyperf 中使用(配置 + DI)
发布配置:
php bin/hyperf.php vendor:publish goletter/hyperf-card
编辑 config/autoload/card.php 中的 slash 段(可用环境变量):
'slash' => [ 'base_url' => env('SLASH_BASE_URL', 'https://api.slash.com'), 'api_key' => env('SLASH_API_KEY', ''), 'timeout' => 60, // 'rsa_public_key' => env('SLASH_RSA_PUBLIC_KEY', ''), // 'private_key' => env('SLASH_PRIVATE_KEY', ''), // 'vault_base_url' => env('SLASH_VAULT_URL', ''), // 'merchant_allowlist' => [], ],
注入工厂后,配置文件会自动合并,调用时只需传覆盖项:
use Goletter\Card\CardFactory; use Hyperf\Di\Annotation\Inject; class CardService { #[Inject] protected CardFactory $cardFactory; public function listSlashCards(?string $cursor = null): array { // 读取 config/autoload/card.php 的 slash 配置 $bundle = $this->cardFactory->create('slash'); // 临时覆盖(例如切换账号 api_key) // $bundle = $this->cardFactory->create('slash', ['api_key' => $otherKey]); // 业务统一字段 → adapter();官方原始 JSON → card()/api() return $bundle->adapter()->cardList([ 'cursor' => $cursor ?? '', ]); } }
未注入时也可手动把配置灌进共享工厂:
$factory = new CardFactory(require BASE_PATH . '/config/autoload/card.php'); CardFactory::setShared($factory); $bundle = CardFactory::slash(); // 使用配置文件中的 slash 段
4. 其它平台(同一套工厂)
| 写法 | 平台 |
|---|---|
CardFactory::airwallex($config) / make(0, …) |
Airwallex |
CardFactory::slash($config) / make(1, …) |
Slash |
CardFactory::lampay($config) / make(2, …) |
Lampay |
CardFactory::photonpay($config) / make(3, …) |
Photonpay |
CardFactory::wasabi($config) / make(4, …) |
Wasabi |
Airwallex Token 持久化示例:
use Goletter\Card\Contract\TokenPersisterInterface; $bundle = CardFactory::airwallex([ 'api_key' => '...', 'client_id' => '...', 'card_accounts_id' => 1, 'token_persister' => $container->get(TokenPersisterInterface::class), // 或:'token_persister' => fn ($accountId, array $token) => { ... }, ]);
Airwallex API
配置
use Goletter\Card\Platforms\Airwallex\Airwallex; $airwallex = new Airwallex([ 'baseUrl' => 'https://api-demo.airwallex.com', // API 基础地址 'apiKey' => 'your-api-key', // API Key 'clientId' => 'your-client-id', // Client ID 'timeout' => 60, // 请求超时时间(秒) 'requestSource' => 4, // 请求来源标识 ]);
配置参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| baseUrl | string | 否 | https://api-demo.airwallex.com |
API 基础地址 |
| apiKey | string | 是 | - | API Key |
| clientId | string | 是 | - | Client ID |
| timeout | int | 否 | 60 | 请求超时时间(秒) |
| requestSource | int | 否 | 4 | 请求来源标识 |
认证 API
登录获取 Token
// 自动获取并管理 token $result = $airwallex->authentication()->login(); // 返回结果包含 token // $result['token']
注意: SDK 会自动管理 token 的获取和刷新,无需手动处理。当 token 过期时,会自动重新获取。
卡片 API
获取卡片列表
$cards = $airwallex->card()->listCards([ 'page_num' => 0, // 页码,从 0 开始 'page_size' => 10, // 每页数量 ]); // 返回卡片列表数据
获取卡片详情
$cardId = 'd467705b-6ef1-42b0-8b67-aa74caaa6b06'; $cardDetails = $airwallex->card()->getCardDetails($cardId);
获取卡片限额
$cardId = 'd467705b-6ef1-42b0-8b67-aa74caaa6b06'; $limits = $airwallex->card()->getCardLimits($cardId);
创建卡片
$newCard = $airwallex->card()->createCard([ // 卡片创建所需的数据 // 具体字段请参考 Airwallex API 文档 ]);
更新卡片
$cardId = 'd467705b-6ef1-42b0-8b67-aa74caaa6b06'; $updatedCard = $airwallex->card()->updateCard($cardId, [ // 需要更新的字段 ]);
冻结卡片
$cardId = 'd467705b-6ef1-42b0-8b67-aa74caaa6b06'; $result = $airwallex->card()->freezeCard($cardId, [ // 可选:冻结原因等数据 ]);
解冻卡片
$cardId = 'd467705b-6ef1-42b0-8b67-aa74caaa6b06'; $result = $airwallex->card()->unfreezeCard($cardId, [ // 可选:解冻原因等数据 ]);
取消卡片
$cardId = 'd467705b-6ef1-42b0-8b67-aa74caaa6b06'; $result = $airwallex->card()->cancelCard($cardId, [ // 可选:取消原因等数据 ]);
手动设置 Token
如果已有有效的 token,可以手动设置,避免重复登录:
$airwallex->setAccessToken('your-token', $expiresAt); // $expiresAt 为可选的过期时间戳
异常处理
SDK 提供了两种异常类型:
- AirwallexApiException - 通用 API 异常
- AirwallexTokenExpiredException - Token 过期异常(继承自 AirwallexApiException)
use Goletter\Card\Platforms\Airwallex\Exceptions\AirwallexApiException; use Goletter\Card\Platforms\Airwallex\Exceptions\AirwallexTokenExpiredException; try { $cards = $airwallex->card()->listCards(); } catch (AirwallexTokenExpiredException $e) { // Token 过期,SDK 会自动重新获取,但也可以手动处理 echo "Token expired: " . $e->getMessage(); } catch (AirwallexApiException $e) { // 其他 API 错误 echo "API Error: " . $e->getMessage(); $response = $e->getResponse(); // 获取错误响应数据 }
完整使用示例
<?php use Goletter\Card\Platforms\Airwallex\Airwallex; use Goletter\Card\Platforms\Airwallex\Exceptions\AirwallexApiException; // 初始化 $airwallex = new Airwallex([ 'baseUrl' => 'https://api-demo.airwallex.com', 'apiKey' => 'your-api-key', 'clientId' => 'your-client-id', ]); try { // 登录(可选,SDK 会在需要时自动登录) $airwallex->authentication()->login(); // 获取卡片列表 $cards = $airwallex->card()->listCards([ 'page_num' => 0, 'page_size' => 10, ]); // 获取第一张卡片的详情 if (!empty($cards['items'])) { $firstCardId = $cards['items'][0]['id']; $cardDetails = $airwallex->card()->getCardDetails($firstCardId); $cardLimits = $airwallex->card()->getCardLimits($firstCardId); } } catch (AirwallexApiException $e) { echo "Error: " . $e->getMessage() . "\n"; print_r($e->getResponse()); }
Slash API
推荐使用 工厂模式 创建:
CardFactory::slash($config)。
配置
use Goletter\Card\CardFactory; // 推荐 $bundle = CardFactory::slash([ 'base_url' => 'https://api.slash.com', 'api_key' => 'your-api-key', 'timeout' => 60, ]); // 也可直接 new(不经过工厂) use Goletter\Card\Platforms\Slash\Slash; $slash = new Slash([ 'base_url' => 'https://api.slash.com', 'api_key' => 'your-api-key', 'timeout' => 60, ]);
配置参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| base_url / baseUrl | string | 否 | https://api.slash.com |
API 基础地址 |
| api_key / apiKey | string | 是 | - | API Key(X-API-Key) |
| timeout | int | 否 | 60 | 请求超时(秒) |
| rsa_public_key | string | 否 | - | 请求敏感字段时的 RSA 公钥 |
| private_key | string | 否 | - | 解密 PAN/CVV 的私钥 PEM |
| vault_base_url | string | 否 | 自动推导 | 敏感读卡 vault 地址 |
| merchant_allowlist | array | 否 | [] |
updateCard 商户白名单 |
卡片 API
以下示例基于工厂适配层:$adapter = CardFactory::slash($config)->adapter();
获取卡片列表
Slash 仅支持 cursor 分页(不支持 limit / offset)。适配层返回 Result 信封:
$adapter = CardFactory::slash($config)->adapter(); $result = $adapter->cardList(['cursor' => '']); // $result['code'] === 1 // $result['data']['data'] / $result['data']['cursor'] $allCards = []; $cursor = ''; do { $result = $adapter->listCardsPaginated($cursor === '' ? null : $cursor); $allCards = array_merge($allCards, $result['data']['data'] ?? []); $cursor = (string) ($result['data']['cursor'] ?? ''); } while ($cursor !== '');
获取卡片详情
$detail = $adapter->cardInfo(['card_id' => 'card-id']); // $detail['data']['cardNo'] / cvv / cardStatus ...
SDK 层(原始 Slash API)
$api = CardFactory::slash($config)->card(); $raw = $api->listCards(['cursor' => '']); $card = $api->getCard('card-id', ['include_pan' => 'true', 'include_cvv' => 'true']);
创建虚拟卡片
$newCard = $slash->card()->createCard([ 'card_type' => 'virtual', 'name' => 'Card Name', 'account_id' => 'account-id', // 其他创建所需的数据 // 具体字段请参考 Slash API 文档 ]);
创建实体卡片
$newCard = $slash->card()->createPhysicalCard([ 'name' => 'Card Name', 'account_id' => 'account-id', // 其他创建所需的数据 ]);
更新卡片
$cardId = 'card-id'; $updatedCard = $slash->card()->updateCard($cardId, [ // 需要更新的字段 ]);
部分更新卡片
$cardId = 'card-id'; $updatedCard = $slash->card()->patchCard($cardId, [ // 需要更新的字段(部分更新) ]);
冻结卡片
$cardId = 'card-id'; $result = $slash->card()->freezeCard($cardId, [ // 可选:冻结原因等数据 ]);
解冻卡片
$cardId = 'card-id'; $result = $slash->card()->unfreezeCard($cardId, [ // 可选:解冻原因等数据 ]);
取消卡片
$cardId = 'card-id'; $result = $slash->card()->cancelCard($cardId, [ // 可选:取消原因等数据 ]);
删除卡片
$cardId = 'card-id'; $result = $slash->card()->deleteCard($cardId);
设置消费限制
$cardId = 'card-id'; $result = $slash->card()->setSpendingConstraints($cardId, [ // 消费限制规则 // 例如:商户类别、交易金额等限制 ]);
获取消费限制
$cardId = 'card-id'; $constraints = $slash->card()->getSpendingConstraints($cardId);
异常处理
SDK 提供了两种异常类型:
- SlashApiException - 通用 API 异常
- SlashTokenExpiredException - API Key 无效或过期异常(继承自 SlashApiException)
use Goletter\Card\Platforms\Slash\Exceptions\SlashApiException; use Goletter\Card\Platforms\Slash\Exceptions\SlashTokenExpiredException; try { $cards = $slash->card()->listCards(); } catch (SlashTokenExpiredException $e) { // API Key 无效或过期 echo "API Key invalid: " . $e->getMessage(); } catch (SlashApiException $e) { // 其他 API 错误 echo "API Error: " . $e->getMessage(); $response = $e->getResponse(); // 获取错误响应数据 }
完整使用示例
<?php use Goletter\Card\Platforms\Slash\Slash; use Goletter\Card\Platforms\Slash\Exceptions\SlashApiException; // 初始化 $slash = new Slash([ 'baseUrl' => 'https://api.slash.com', 'apiKey' => 'your-api-key', ]); try { // 方式一:循环获取所有卡片数据 $allCards = []; $cursor = null; do { $response = $slash->card()->listCardsPaginated($cursor); // 合并当前页数据 if (isset($response['data']) && is_array($response['data'])) { $allCards = array_merge($allCards, $response['data']); } // 获取下一页游标 $cursor = $response['metadata']['nextCursor'] ?? null; } while ($cursor !== null); // 方式二:逐页处理(适合大数据量,避免内存占用过大) $cursor = null; do { $response = $slash->card()->listCardsPaginated($cursor); // 处理当前页的卡片 foreach ($response['data'] ?? [] as $card) { // 处理每张卡片,例如保存到数据库 // processCard($card); } // 获取下一页游标 $cursor = $response['metadata']['nextCursor'] ?? null; } while ($cursor !== null); // 获取第一张卡片的详情 if (!empty($cards['data'])) { $firstCardId = $cards['data'][0]['id']; $cardDetails = $slash->card()->getCard($firstCardId); $constraints = $slash->card()->getSpendingConstraints($firstCardId); } // 创建虚拟卡片 $newCard = $slash->card()->createCard([ 'card_type' => 'virtual', 'name' => 'My Virtual Card', 'account_id' => 'account-id', ]); } catch (SlashApiException $e) { echo "Error: " . $e->getMessage() . "\n"; print_r($e->getResponse()); }
Lampay API
基于 Lampay Consumer API(Base URL: https://api.lampay.app)。
认证使用 API Key + RSA-SHA256 请求签名 / 响应验签,发卡等敏感接口使用 RSA-OAEP-AES-256-GCM 加密信封。
配置
use Goletter\Card\Platforms\Lampay\Lampay; $lampay = new Lampay([ 'base_url' => 'https://api.lampay.app', 'api_key' => 'your-api-key', // 客户端鉴权私钥(签名) 'private_key' => file_get_contents('/secure/client-auth-private.pem'), // 平台鉴权公钥(验签) 'public_key' => file_get_contents('/secure/platform-auth-public.pem'), // 可选:加解密(发卡 / 敏感信息 / Webhook) 'merchant_enc_private_key' => file_get_contents('/secure/client-enc-private.pem'), 'platform_enc_public_key' => file_get_contents('/secure/platform-enc-public.pem'), 'webhook_receiver_key_id' => 'receiver-api-key-biz-id', 'provider_type' => '10010105', 'api_version' => '1', 'timeout' => 60, ]);
配置参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| base_url / baseUrl | string | 否 | https://api.lampay.app |
API 基础地址 |
| api_key / apiKey | string | 是 | - | API Key 调用凭证 |
| private_key / merchantAuthPrivateKeyPem | string | 是 | - | 客户端鉴权私钥 PEM |
| public_key / platformAuthPublicKeyPem | string | 是 | - | 平台鉴权公钥 PEM(响应/Webhook 验签) |
| merchant_enc_private_key | string | 否 | - | 客户端加密私钥(解密敏感响应/Webhook) |
| platform_enc_public_key | string | 否 | - | 平台加密公钥(加密发卡请求) |
| webhook_receiver_key_id | string | 否 | - | Webhook 接收方 API Key 业务 ID |
| provider_type | string | 否 | 10010105 |
部分卡片路径中的提供商类型 |
| api_version | string | 否 | 1 |
X-API-VERSION |
| timeout | int | 否 | 60 | 请求超时(秒) |
卡片 API
// 产品组列表(首次只读联调) $groups = $lampay->card()->listProductGroups(['page' => 0, 'size' => 20]); // 卡片列表(分页,page 从 0 开始) $cards = $lampay->card()->listCards(['page' => 0, 'size' => 20]); // 卡片详情 $detail = $lampay->card()->getCard('VC_xxx'); // 敏感信息(需配置加密私钥;自动解密) $reveal = $lampay->card()->revealSensitive('VC_xxx'); // $reveal['sensitive'] => pan / cvv / expiryMonth / expiryYear // 发卡预检 + 加密发卡(需配置平台加密公钥) $lampay->card()->createCardPrecheck($payload); $result = $lampay->card()->createCard($payload, $idempotencyKey); // 更新消费规则 / 别名 $lampay->card()->updateSpendingControls(['cardInfoBizId' => 'VC_xxx', 'spendingRule' => [...]]); $lampay->card()->updateRemark('VC_xxx', 'Ops Card'); // 冻结 / 解冻 / 注销 $lampay->card()->freezeCard('VC_xxx'); $lampay->card()->unfreezeCard('VC_xxx'); $lampay->card()->cancelCard('VC_xxx'); // 交易列表 $txs = $lampay->card()->listTransactions(['cardInfoBizId' => 'VC_xxx', 'page' => 0, 'size' => 20]);
Webhook
$handled = $lampay->webhook()->handle(getallheaders(), file_get_contents('php://input')); // $handled['event'] / delivery_biz_id / event_type
异常处理
use Goletter\Card\Platforms\Lampay\Exceptions\LampayApiException; try { $cards = $lampay->card()->listCards(['page' => 0, 'size' => 20]); } catch (LampayApiException $e) { echo $e->getMessage(); print_r($e->getResponse()); }
Photonpay API
配置
use Goletter\Card\Platforms\Photonpay\Photonpay; $photonpay = new Photonpay([ 'base_url' => 'https://x-api.photonpay.com', 'api_key' => 'your-api-key', 'api_secret' => 'your-api-secret', 'private_key' => 'your-rsa-private-key', // 请求签名 'token' => 'optional-existing-token', 'timeout' => 60, ]);
配置参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| base_url / baseUrl | string | 否 | https://x-api.photonpay.com |
API 基础地址 |
| api_key / apiKey | string | 是 | - | API Key |
| api_secret / apiSecret | string | 是* | - | API Secret(无 token 时用于登录) |
| private_key | string | 否 | - | RSA 私钥(X-PD-SIGN) |
| token | string | 否 | - | 已有 access token |
| verify_ssl | bool | 否 | true |
TLS 证书校验 |
| timeout | int | 否 | 60 | 请求超时时间(秒) |
认证 API
$result = $photonpay->authentication()->login(); // $result['token'] / $result['access_token']
未传入 token 或临近过期时,SDK 会自动调用 /api/v1/auth/token 刷新。
卡片 API
use Goletter\Card\CardFactory; $bundle = CardFactory::photonpay($config); // 适配层 → {code, msg, data} $adapter = $bundle->adapter(); $cards = $adapter->cardList([ 'page_index' => 1, 'page_size' => 10, 'from_created_at' => '2024-01-01 00:00:00', 'to_created_at' => '2024-12-31 23:59:59', ]); $detail = $adapter->cardInfo(['card_id' => 'card-id']); $adapter->cardFreeze(['card_id' => 'card-id']); // SDK 层 → 官方原始 JSON $api = $bundle->card(); $raw = $api->pagingVccCard(['pageIndex' => 1, 'pageSize' => 10]); $newCard = $api->openCard([/* 见 Photonpay 文档 */]);
异常处理
use Goletter\Card\Platforms\Photonpay\Exceptions\PhotonpayApiException; use Goletter\Card\Platforms\Photonpay\Exceptions\PhotonpayTokenExpiredException; try { $cards = CardFactory::photonpay($config)->adapter()->cardList([ 'page_index' => 1, 'page_size' => 10, ]); } catch (PhotonpayTokenExpiredException $e) { echo "Token expired: " . $e->getMessage(); } catch (PhotonpayApiException $e) { echo "API Error: " . $e->getMessage(); print_r($e->getResponse()); }
Wasabi API
use Goletter\Card\CardFactory; $bundle = CardFactory::wasabi([ 'base_url' => 'https://sandbox-api-merchant.wasabicard.com', 'api_key' => 'your-api-key', 'private_key' => file_get_contents('/secure/wasabi-private.pem'), 'wsb_public_key' => file_get_contents('/secure/wasabi-public.pem'), 'timeout' => 60, ]); // 适配层 $cards = $bundle->adapter()->cardList(['page_index' => 1, 'page_size' => 20]); $detail = $bundle->adapter()->cardInfo(['card_id' => 'xxx']); // SDK 层 $raw = $bundle->card()->listCards(['pageNum' => 1, 'pageSize' => 20]);
注意事项
Airwallex
-
Token 管理:SDK 会自动管理 token 的获取和刷新。Token 会在过期前 60 秒自动刷新。
-
环境配置:
- 测试环境:
https://api-demo.airwallex.com - 生产环境:
https://api.airwallex.com
- 测试环境:
-
请求来源:
requestSource参数默认为 4,如有特殊要求请根据实际情况调整。
Slash
-
API Key 认证:Slash 使用 API Key 进行认证,通过
X-API-Keyheader 传递。 -
环境配置:
- 生产环境:
https://api.slash.com - 请根据实际情况配置正确的 API 地址
- 生产环境:
-
消费限制:Slash 支持设置消费限制规则,可以基于商户类别、交易金额等进行控制。
Lampay
-
认证方式:
X-Api-Key+ RSA-SHA256 请求签名(X-Signature),响应使用平台鉴权公钥验签。 -
加密:发卡请求使用 RSA-OAEP-AES-256-GCM 信封;敏感信息与 Webhook 需客户端加密私钥解密。
-
环境配置:
- 生产环境:
https://api.lampay.app - 详见 https://docs.lampay.app/
- 生产环境:
-
卡片管理:列表/详情、加密发卡、消费规则、冻结/解冻/注销、交易查询与 Webhook。
Photonpay
-
Token 管理:未传入
token或临近过期时,会调用/api/v1/auth/token(可用token_url覆盖)。请配置api_key+api_secret。 -
环境配置:
- 默认:
https://x-api.photonpay.com - TLS 校验默认开启,可通过
verify_ssl => false关闭(仅建议本地调试)
- 默认:
-
卡片功能:当前适配
/vcc/openApi/v4/*与账户查询接口(cardList/cardInfo/ 冻结解冻 / 交易等)。
Wasabi
-
认证:
X-WSB-API-KEY+ RSA 请求签名;响应用平台公钥验签,敏感数据用商户私钥解密。 -
环境配置:沙箱默认
https://sandbox-api-merchant.wasabicard.com,生产请换成正式域名。
通用
-
请求超时:默认超时时间为 60 秒,可根据实际情况调整。
-
错误处理:建议在生产环境中对异常进行适当的处理和日志记录。
-
API 文档:具体 API 字段和参数请参考各平台的官方 API 文档。
许可证
MIT