Skip to content

申請虛擬卡

非同步開卡介面。請求成功只代表"已入隊",開卡完成結果透過 card.opened / card.open_failed webhook 推送,或透過 card/info 輪詢。

端點

MethodPOST
Path/api/v1/openapi/card/apply
鑑權HMAC
冪等鍵必填 Idempotency-Key

請求欄位

不要傳 card_type

本介面不需要card_type。伺服器從 header_id 自動推導,並校驗是否在虛擬卡範圍內。

欄位型別必填說明
header_idstringhdr_<id> 格式(列卡頭
package_idstringpkg_<id> 格式(列卡配置
first_namestring⚠️持卡人名(看 header.require_phone/email)
last_namestring⚠️持卡人姓
phone_codestring⚠️國家區號(如 86 / 1
phonestring⚠️手機號(不含區號)
emailstring⚠️郵箱
use_bound_emailbool預設 false,使用請求中傳的 email。傳 true 時回退到賬號繫結的郵箱。
use_bound_phonebool預設 false,使用請求中傳的 phone + phone_code。傳 true 時回退到賬號繫結的手機號。
first_deposit_amountstring自定義首充總額,非負整數(支付/充值資產單位,如 USDT)。空 = 用配置底額。必須 ≥ 套餐的 min_first_deposit列卡配置);該最低值高於 base 時本欄位必填(留空會被 first_recharge_below_min 拒絕)。超出 base 的部分按充值口徑收手續費,並與開卡費一併凍結。可用首充預覽精確試算。

持卡人欄位是否必填

  • header.require_phone == true 時需要 phone_code + phone(或顯式傳 use_bound_phone == true 讓服務端讀賬號繫結的手機號)
  • header.require_email == true 時需要 email(或顯式傳 use_bound_email == true 讓服務端讀賬號繫結的郵箱)
  • first_name / last_name 多數情況下需要(virtual_g / virtual_a 始終必填,見下文)
  • OpenAPI 與 H5 使用者端的預設值相反:本介面的 use_bound_phone / use_bound_email 預設為 false —— 服務端使用你傳的值。商戶的終端使用者一般沒有在我們這邊繫結過手機號/郵箱,回退到"繫結值"會失敗。只有當你確實需要使用賬號繫結值時才顯式傳 true

自定義首充

預設按配置底額開卡。如需加充,傳 first_deposit_amount(非負整數,且 ≥ base)。底額按 1:1 免費進卡;超出底額的超額按充值口徑收手續費,扣費後按 1:1 進卡(USDT/USD,不走匯率),發給提供方的首充取整為整數。開卡費 + 完整計算出的凍結額在開卡時一併從錢包凍結。

套餐還可能設定高於底額的首充最低金額列卡配置min_first_deposit,預覽裡的 min_first_deposit_amount)。此時 first_deposit_amount 必填且須 ≥ 該最低值,仍然只有底額部分免手續費(例:底額 10、最低 500 → 至少首充 50010 免費、490 收費)。

開卡前先預覽

校驗邏輯(格式 / >= base / 最大充值 / 充值限額 / 餘額)與首充預覽共用。先調預覽即可向客戶展示精確的 total_freeze / first_recharge_card——數值與本介面 1:1 一致。非法金額在本介面同樣被拒,錯誤 key 與預覽的 invalid_reason 相同(見典型錯誤)。

G 卡(virtual_g)特殊約束

申請 virtual_g 時,服務端會在 header 配置之外強制以下約束:

約束規則失敗 message_key
郵箱始終必填(服務端強制覆蓋 header 設定)bank_card_email_required
手機號phone_code + phone 始終必填(服務端強制覆蓋 header 設定)bank_card_phone_required
持卡人姓名first_name + last_name 拼接後必須匹配 ^[A-Za-z]+(?: [A-Za-z]+)*$,總長度 ≤ 40 字元(僅 ASCII 字母 + 單個空格分隔;不含數字、符號、非 ASCII 字元)virtual_g_name_invalid
生日與賬單地址不要傳 —— 服務端自動生成virtual_g_required_fields_missing(僅當服務端自動填充失敗時返回)

申請前先校驗姓名

真實世界的持卡人姓名常帶變音符號、連字元或撇號——這些字元會被提供方拒絕。請在前端引導終端使用者輸入只含 ASCII 字母 + 單空格分隔的姓名。

A 卡(virtual_a)特殊約束

virtual_a(A 卡)與 V / R / G 同一提供方體系,遵循提供方自己的開卡協議。無論 header.require_* 配置如何,服務端都會強制以下規則 —— 列卡頭返回的已是生效值(A 卡卡頭恆為 require_email=truerequire_phone=false):

約束規則失敗 message_key
郵箱始終必填 —— 傳 email(賬號已繫結郵箱時也可 use_bound_email=truebank_card_email_required
手機號不收集 —— phone_code / phone / use_bound_phone 會被忽略,提供方協議沒有手機號欄位
持卡人姓名first_namelast_name 均必填且不能為空白(純空格會被拒絕);在凍結任何資金之前校驗virtual_a_required_fields_missing
生日與賬單地址不要傳 —— 服務端自動生成virtual_a_required_fields_missing(僅當服務端自動填充失敗時返回)

其餘能力(自定義首充、冪等、card.opened / card.open_failed 非同步結果、充值、凍結 / 解凍、銷卡、交易明細、敏感卡資訊)與其他虛擬卡型別完全一致。

請求示例

json
{
  "header_id": "hdr_5",
  "package_id": "pkg_12",
  "first_name": "John",
  "last_name": "Doe"
}

請求頭必須含:

http
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

響應欄位

欄位型別說明
card_idstringcard_<id> 格式(用於後續查詢)
statusint1=pending 2=active 3=failed 4=closing 5=closed 6=frozen
status_descstring英文描述
created_atstringRFC3339 時間

響應示例(成功入隊)

json
{
  "code": 200,
  "message": "成功",
  "data": {
    "card_id": "card_12345",
    "status": 1,
    "status_desc": "pending",
    "created_at": "2026-04-29T11:00:12Z"
  }
}

status=1 不代表卡已可用

返回 status=1 (pending) 只是"已入隊"。等 card.opened webhook 到達,或輪詢 card/info 看到 status=2 (active) 才能用。

後續流程

diagram

典型錯誤

HTTPmessage_key說明
400insufficient_balance餘額不足(開卡費 + 首充)
400invalid_first_deposit_amountfirst_deposit_amount 不是純非負整數(小數 / 符號 / 科學計數法 / 位數過多)
400first_recharge_below_basefirst_deposit_amount 低於配置底額
400first_recharge_below_minfirst_deposit_amount(或留空的預設底額)低於套餐首充最低金額 min_first_deposit
400first_recharge_exceeds_max超額超過 max_recharge_amount
400first_recharge_limit_exceeded超額超過賬號充值限額
400first_recharge_asset_mismatch開卡費資產 ≠ 充值資產;該配置不支援自定義超額
400first_recharge_excess_too_small扣費 + 取整後到卡為 0,請加大金額
400kyc_required請先完成實名認證
400kyc_not_approved賬號 KYC 未透過
400bank_card_email_required卡型別需要郵箱;請傳 email 或顯式設 use_bound_email=true(僅當賬號已繫結時)
400bank_card_phone_required卡型別需要手機號;請傳 phone_code+phone 或顯式設 use_bound_phone=true(僅當賬號已繫結時)
400openapi_card_type_not_supportedheader 對應的卡型別不在虛擬卡範圍
400account_manager_bind_required客戶經理管控卡頭,而賬號未繫結客戶經理 —— header_id 只能用 /card_headers/list 返回的值
400account_manager_unavailable賬號繫結的客戶經理已失效;請聯絡平臺客服
400account_manager_open_disabled客戶經理未對該賬號放開此卡頭 / 套餐;請只使用列表介面返回的卡頭與套餐(列表已不含未放開 / 被關閉的)
400virtual_g_name_invalid(G 卡)持卡人姓名不滿足 ASCII 字母 / 單空格 / ≤40 字元規則
400virtual_g_required_fields_missing(G 卡)服務端無法組裝完整的開卡請求(罕見,通常是配置或地址池缺失)
400virtual_a_required_fields_missing(A 卡)first_name / last_name 缺失或為空白,或服務端無法組裝完整的開卡請求(卡頭 / 地址池問題)
400openapi_invalid_header_idheader_id 缺字首或不存在
400openapi_invalid_package_idpackage_id 缺字首 / 不屬於該 header
400openapi_idempotency_key_required缺冪等鍵
400openapi_idempotency_key_too_long冪等鍵超 128 字元
400openapi_idempotency_key_invalid_chars冪等鍵含非法字元
401openapi_invalid_credentials鑑權失敗
409openapi_idempotency_key_conflict同 key 不同 body
500openapi_apply_card_failed服務端異常

注意事項

  • 開卡費 + 首充會在請求時一併扣款 / 凍結。傳自定義 first_deposit_amount 時,超額手續費也會一併凍結(見自定義首充)。失敗的開卡會自動退還
  • 非同步任務最長可能跑幾分鐘。不要因為客戶端 30 秒內沒收到 webhook 就重試 apply(重試需帶相同 Idempotency-Key
  • card_id 一旦返回就永久指向這次請求的卡(即使最終失敗)

採用 MIT 等價條款釋出