关于 integrate-payroc-cloud
Payroc Cloud 集成技能面向开发者,指导通过 REST API 为实体支付设备提交和查询支付指令。涵盖销售、退款、撤销、签名及闭环读取;不涉及设备配置或配对。
主要功能
- 01获取 bearer token
- 02提交并轮询异步指令
- 03检索支付、退款和签名结果
- 04取消进行中的指令
- 05读取闭环数据及查询设备
适用场景
- 01将 POS 应用接入 Payroc Cloud 支付
- 02实现销售、预授权或退款流程
- 03处理签名捕获和撤销操作
- 04通过 API 查询设备序列号
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ payroc/ skills --skill integrate-payroc-cloud安装后在 Claude Code 中输入/integrate-payroc-cloud确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/_sources.mdapi-schema.mderror-response-format.mdidentity-call.mdnarrative-extend.mdnarrative-run-a-sale.md详细介绍
集成 Payroc Cloud
范围:通过 Payroc Cloud 进行面对面银行卡支付——半集成产品中的 API 部分。
提交、轮询和获取驱动物理支付设备的云端指令:
销售、预授权、退款(关联和非关联)、撤销、签名采集和闭环读取,以及只读设备查询。不在范围内的是物理设备配置/配对——本技能从你已有设备的 serialNumber 开始。
版本检查(先运行)
在发布任何消息或开始流程之前,请确认本技能是最新版本:
- 从上方 frontmatter 的
metadata.version字段读取本技能的版本。 - 获取已发布的副本并读取其
metadata.version:https://raw.githubusercontent.com/payroc/skills/main/plugins/payroc/transaction/skills/integrate-payroc-cloud/SKILL.md - 将两个版本作为语义化版本进行比较:
-
此版本 >= 已发布版本 → 静默继续,不发送消息。(开发者运行尚未发布的较新版本是预期情况,也没有问题。)
-
此版本 < 已发布版本 → 告知开发者:
⚠️ 此技能已有新版本(v<published>)发布——你正在运行 v<current>。建议升级以获得最佳效果。
然后询问对方是要继续使用当前版本,还是先停止并升级,并按其选择执行。
-
无法获取(离线、网络错误、404)→ 简要说明无法验证版本,然后继续。
-
Payroc Cloud 的工作方式
在半集成模式中,POS 永远不会直接与支付设备通信。POS 通过 HTTPS 向 Payroc 网关发送指令;网关将其转发至设备;设备执行银行卡交互(轻触/插入/PIN/签名);结果经由网关返回,供 POS 获取。
POS / POS app --HTTPS--> Payroc gateway --> payment device (Payroc App)
^ | |
+-------- poll status <----+<--- result ------------+
由于所有操作都经由网关路由,你的集成是纯 REST——无需嵌入设备 SDK,服务器也不会接触银行卡数据。本技能涵盖这一 REST 接口。
范围内与范围外的内容:
- **范围内(纯 API):**构建并提交指令(支付/退款/签名);轮询指令;获取生成的支付/退款/签名;取消正在进行的指令;读取闭环负载;关联/非关联退款和撤销;使用
GET /devices查找serialNumber。 - **范围外(硬件):**配置或配对物理设备(Android / Ingenico / ID TECH 设置)、轻触/插入/刷卡/PIN/屏幕签名交互,以及将真实序列号绑定到终端。如果开发者需要这些内容,请明确说明——这属于设备设置,而非 API 工作。
本技能将设备和 serialNumber 视为已提供的输入。如果开发者没有 serialNumber,可通过 GET /devices 查找(只读,不涉及硬件);Payroc Cloud Simulator(cloud.uat.payroc.com)则会为每个浏览器标签页生成一个模拟序列号,供无硬件测试使用。
参考资料 — 请阅读这些资料,不要凭记忆输出
此技能从下方本地的 references/ 文件中提取内容,而不是实时查找或凭记忆生成。
这里有两种互补的来源,分别解答不同类型的问题;用错来源是已知的常见错误:
references/api-schema.md— 线上传输的内容。 字段名称、类型、必填标记、枚举值、请求/响应结构、端点清单和错误封装。每当需要知道字段叫什么或接受哪些值时,都要阅读此文件。所有枚举值和字段名称都必须从此文件中提取,不要凭记忆输出——看似合理、实际却不在枚举中的值(例如状态"approved"、entryMethod值"chip")是最常见的错误来源。references/narrative-run-a-sale.md和references/narrative-extend.md— 调用顺序。 哪个调用应先执行、轮询后跟随链接的流程如何衔接,以及后续流程(签名、带引用/不带引用的退款、撤销)如何基于核心模式构建。references/error-response-format.md— 错误封装(RFC 7807)+ Payroc errors[] + 规范错误类型目录。 服务端 API 调用的封装结构和规范错误type目录;api-schema.md包含各状态码对应的表格。
来源 URL 和最后同步日期见 references/_sources.md。
如实说明限制。 这些参考资料根据 Payroc 发布的文档整理,未通过启用 Cloud 的账号或硬件进行验证。契约(路径、字段、枚举、指令生命周期)直接来自文档,具有可靠性;Cloud 的错误响应结构是假设与跨技能标准一致,尚未针对 Cloud 确认。若开发者正在构建严格的错误处理逻辑,请告知此限制。
核心原则
- 先检查,再提问。 先阅读开发者的代码库——编程语言、HTTP 客户端、配置和机密的处理方式,以及现有的 Payroc 或 POS 集成——并根据其实际情况提问,而不是询问可以从代码中推断出的内容。
- 先阅读,再输出,逐项核对。 输出任何枚举值或字段名称(
currency、entryMethod、指令status、mitAgreement、tip.type、退款responseCode、支付查询中的type等)之前,都要从references/api-schema.md中读取。技能中的内联示例只是帮助你识别结构,并不能替代你在构建每个请求体时阅读参考资料。 - 只需掌握一种模式。 销售、退款和签名都是相同的异步指令流程:提交(202)→ 轮询 → 跟随链接 → 检索。掌握一次即可,其余只是变化。
- 指令 ID 不等于资源 ID。 轮询会返回
paymentInstructionId;已完成指令的link.href指向另一个 ID——paymentId。请跟随该链接;切勿根据指令 ID 拼接资源 URL。 - 202 ≠ 已批准。
202表示网关已接受指令,并将其转发给设备。销售的实际结果(银行批准/拒绝)在检索到的支付记录中,而非指令中。 - 切勿硬编码凭据。 API 密钥以及任何终端/序列号值都应来自环境变量或机密管理器,绝不能写入源代码。
快速参考
Base URL (test): https://api.uat.payroc.com/v1 Identity (test): https://identity.uat.payroc.com/authorize
Base URL (prod): https://api.payroc.com/v1 Identity (prod): https://identity.payroc.com/authorize
# Instruction submit (runs on the device) — Idempotency-Key required
POST /devices/{serialNumber}/payment-instructions -> 202
POST /devices/{serialNumber}/refund-instructions -> 202 (unreferenced refund)
POST /devices/{serialNumber}/signature-instructions -> 202
# Poll an instruction (gateway long-holds ~60s) / cancel it
GET /payment-instructions/{id} -> 200
DELETE /payment-instructions/{id} -> 204 (only while inProgress, else 409)
# ...same GET/DELETE shape for refund-instructions and signature-instructions
# Retrieve the resulting resource (follow link.href from the completed instruction)
GET /payments/{paymentId} GET /refunds/{refundId} GET /signatures/{signatureId}
GET /closed-loop-reads/{closedLoopReadId}
# Referenced refund & reversal (standard payments API, NOT device instructions) — Idempotency-Key required
POST /payments/{paymentId}/refunds -> 201
POST /payments/{paymentId}/reverse -> 200
GET /payments GET /payments/{paymentId} # find / retrieve a payment
GET /devices # find a serialNumber
Headers: Authorization: Bearer <token> Content-Type: application/json Idempotency-Key: <uuid-v4>
步骤 1 — 获取 Bearer 令牌
输出任何身份验证代码之前,请先阅读
references/identity-call.md。不要猜测端点 URL、标头名称或响应结构——仅使用参考资料中记录的内容。
令牌约 1 小时后过期(expires_in: 3600)。每次会话前都要交换 API 密钥,并在令牌过期前主动刷新。
# Test / sandbox (production: identity.payroc.com)
curl -X POST https://identity.uat.payroc.com/authorize \
-H "x-api-key: $PAYROC_API_KEY"
响应包含 access_token、expires_in、token_type: "Bearer"。后续每个请求都要发送
Authorization: Bearer <access_token>。
第 2 步 — 指令模式(提交 → 轮询 → 跟随链接 → 检索)
阅读 references/narrative-run-a-sale.md。这是 Payroc Cloud 的核心;每项操作都使用此模式。
- 提交指令到设备,并附上一个全新的
Idempotency-Key。你会收到202 Accepted和{ status: "inProgress", <x>InstructionId, link }。保存指令 ID。 - 轮询
GET /<x>-instructions/{id}。网关会将响应保持等待状态,最长约 60 秒 以等待状态变化,因此不要编写紧密循环或自行休眠。发出 GET 请求,等待其返回,只有在状态仍为inProgress时才重新发出请求。状态包括inProgress、completed、failure、canceled——请从references/api-schema.md中读取,不要凭记忆。 - 状态为
completed时,响应中的link.href指向真实资源。跟随该链接:GET /payments/{paymentId}(或/refunds/{id}、/signatures/{id})。不要用指令 ID 拼出此 URL——两者的 ID 不同。检索到的 payment 会在transactionResult中包含银行处理结果——应根据transactionResult.status分支判断,并从references/api-schema.md中读取完整的批准状态集合(例如,ready= 已授权且已排队等待捕获,也属于批准),不要只依赖某个记住的值(如complete)。 - 状态为
failure时,读取errorMessage。状态为canceled时,表示指令已先行取消。
取消。 DELETE /<x>-instructions/{id} 会返回 204,但仅当指令处于 inProgress 状态时才有效。一旦指令已完成、失败或取消,DELETE 就会返回 409 Conflict。如果不确定当前状态,请先 GET 指令并读取 status,再进行取消。
检查点
提交会返回 202、指令 ID 和 self 链接;轮询最终会得到 completed(或带有 errorMessage 的 failure);跟随完成状态的链接即可检索资源。
第 3 步 — 构建销售指令
构建请求正文时,请阅读 references/api-schema.md 中的 paymentInstructionRequest 部分。
必填项:processingTerminalId 和 order(orderId、amount、currency)。
POST /v1/devices/{serialNumber}/payment-instructions
{
"processingTerminalId": "1234001",
"order": {
"orderId": "OrderRef6543",
"amount": 4999,
"currency": "USD",
"breakdown": {
"subtotal": 4500,
"tip": { "type": "fixedAmount", "mode": "prompted", "amount": 499 },
"taxes": [ { "rate": 0.08, "name": "Sales Tax" } ]
}
},
"customizationOptions": { "entryMethod": "deviceRead" },
"autoCapture": true
}
关键选项(请从参考文档中读取枚举和字段的详细信息):
amount是以订单货币计价的整数分(ISO 4217)。4999= $49.99。不要发送小数。- 销售 vs 预授权 vs 结算:
autoCapture: true(默认值)= 销售;autoCapture: false= 预授权(稍后捕获);processAsSale: true会立即结算并忽略autoCapture。请谨慎选择。 entryMethod默认值为deviceRead;其他值请参阅参考文档,不要自行编造。- **在销售时进行令牌化:**设置
credentialOnFile.tokenize: true(对于商户发起的后续交易,还需设置mitAgreement)。
第 4 步 — 扩展(签名、退款、撤销)
阅读 references/narrative-extend.md 了解调用顺序,阅读 references/api-schema.md 了解数据结构。
- 采集签名 — 独立操作,不关联付款。提交
{ "processingTerminalId": "…" }至/signature-instructions,轮询,然后跟随signature链接调用GET /signatures/{id},并解码 Base64 编码的signature(其contentType,例如image/png)。 - 无关联退款 — 设备指令:
POST /devices/{serialNumber}/refund-instructions。 注意,退款订单中的order.description必填。轮询 → 跟随链接 → 调用GET /refunds/{id}。 - 有关联退款 — 不是设备指令;它使用标准 payments API,并且需要原始
paymentId。通过GET /payments/{paymentId}获取,或使用GET /payments搜索(last4、cardholderName、orderId、dateFrom/dateTo,……),然后提交POST /payments/{paymentId}/refunds,并提供{ amount, currency }。 - 撤销付款 — 同样使用 payments API,适用于仍在未结批次中的付款:
POST /payments/{paymentId}/reverse(全额撤销时省略amount,部分撤销时提供该字段)。不会发生资金转移。 - 撤销与退款:付款仍在未结批次中、资金尚未扣除 → 撤销;付款已结算 → 退款。 请注意,对未结批次中的付款进行有关联退款,会自动撤销该付款,而不是创建退款 — 请谨慎确认你的操作意图。
- 闭环读取 — 如果你已发出闭环指令(例如读取 MiFare 卡),请通过
GET /closed-loop-reads/{id}获取负载。其data对象没有固定结构(结构因卡而异);不要假设它遵循固定架构。参见references/api-schema.md。
幂等性
每个指令 POST(以及每个退款/撤销 POST)都需要 Idempotency-Key 标头 — 每次新提交都使用全新的 UUID v4。若要重试可能未成功提交的请求(网络短暂中断、超时),请使用相同密钥重新发送逐字节完全相同的请求正文:网关会返回原始结果,而不会再次向设备提交指令。使用同一密钥但更改请求正文会返回 409。轮询(GET)和取消(DELETE)不需要幂等密钥。
处理错误
错误采用 RFC 7807 问题详情封装格式(type、title、status、detail、instance),并扩展了 Payroc 的 errors[] 数组。封装格式见 references/error-response-format.md,规范错误 type 目录亦见该文档;读取 errors[].parameter,将每项失败映射到请求正文中的字段。各状态码对应的表格见 references/api-schema.md。
尚未验证 Cloud 错误格式。 我们假设 Cloud 格式一致,并采用了标准 Payroc 封装格式(已在入驻端点上确认),但无法通过有效的 Cloud 账户进行确认。遇到
failure指令时读取errorMessage,遇到 4xx 时读取errors[],但不要对 Cloud 特有的错误文本作硬编码假设。
| 状态 | 场景 | 操作 |
|---|---|---|
| 400 | 提交时发生验证错误 | 将每个 errors[].parameter 映射到对应字段;修正后重新提交(若重试内容相同,则复用同一幂等密钥)。 |
| 401 | 令牌已过期/无效 | 重新进行身份验证以获取新的 bearer token。 |
| 403 | 权限不足 | 检查 API 密钥的作用域。 |
| 404 | 未找到指令或资源 | 验证 ID,并确认没有混淆指令 ID 与资源 ID。 |
| 409 | 冲突 — 指令状态不再是 inProgress,但仍尝试取消;或复用幂等密钥但请求正文已更改 | 先通过 GET 获取指令当前的 status;不要盲目重试。 |
| 500 | 服务器错误 | 采用退避策略重试;如果存在 errors,则显示该信息。 |
此外,还包括指令级结果:轮询到 status: "failure" → 读取 errorMessage;status: "canceled" → 指令在完成前已取消。
常见陷阱
- 根据指令 ID 推导资源 URL。 已完成的指令会提供一个指向不同 ID 的
link.href。请跟随链接;不要拼接/payments/{paymentInstructionId}。 - 把
202(或轮询时的200)当作成功。202= 已接受并等待转发;轮询可能返回200,但status: "failure"。销售结果以检索到的付款为准。 - 紧密循环轮询/手动休眠。 网关已经会让轮询长时间保持连接,约 60 秒。只需等待 GET 请求完成;仅当状态仍为
inProgress时才重新发起请求。 - 取消得太晚。 只有状态为
inProgress时,DELETE才有效;否则会返回409。请先检查status。 - 金额使用小数。
amount始终是整数分。 - 臆造枚举值。
entryMethod、指令status、currency、mitAgreement、tip.type、退款responseCode、付款搜索的status/type都是枚举值——请从references/api-schema.md中读取。 - 退款指令中遗漏
order.description——此字段在退款指令中是必填项(付款指令中则不是)。 - 对未结批次的付款使用退款而非撤销。 对未结批次中的付款进行引用式退款会自动撤销该笔付款。如果要取消尚未结算的付款,请使用
POST /payments/{paymentId}/reverse。 - 重复使用或省略幂等键。 每次新提交都使用新的 UUID;只有重试完全相同的请求体时才使用相同的键;GET/DELETE 请求不使用幂等键。
- 尝试“设置”设备。 配对/配置属于硬件范畴,不在范围内。此技能从已知的
serialNumber开始(使用GET /devices查找)。
完整字段参考
请阅读 references/api-schema.md,了解:端点清单;指令对象及其 status 枚举;paymentInstructionRequest/refundInstructionRequest/signatureInstructionRequest 模式(含 order、breakdown、credentialOnFile、customizationOptions);签名和闭环检索;引用式退款和撤销端点;GET /payments 和 GET /devices 搜索;以及错误封装。