mcpField
S
snippe-integration

snippe-integration

github.com/neurotech-hq开发2139 次安装30 周前更新
代码仓库

关于 snippe-integration

snippe-integration 是面向开发者的技能,为应用接入坦桑尼亚支付处理商 Snippe 提供协议与实现指导,涵盖付款、出款和安全处理 Webhook。

主要功能

  1. 01创建付款、结账会话和出款
  2. 02验证 Webhook 签名与时间戳
  3. 03处理重复事件和重试
  4. 04排查 API 错误与验证问题

适用场景

  1. 01集成移动货币、银行卡或二维码收款
  2. 02实现 Snippe 托管结账页面
  3. 03安全接收支付状态 Webhook

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/neurotech-hq/skills --skill snippe-integration

安装后在 Claude Code 中输入/snippe-integration确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
disbursements.md
errors.md
payments.md
sessions.md
webhooks.md

详细介绍

Snippe 集成

Snippe 是一家面向坦桑尼亚的支付处理商。此技能可帮助你构建正确的集成:使用正确的身份验证发送 API 调用,按照正确的字段格式创建支付/会话/付款,安全验证 Webhook 签名,以及处理错误——包括那些容易出错的细微之处。

你正在编写与用户应用中的 Snippe 通信的代码。用户可能使用任何语言(Node.js、Python、PHP、Go、Ruby 等);此技能提供协议层面的知识,你需要根据用户当前使用的语言调整示例代码块。

API 基础知识

  • 基础 URL:https://api.snippe.sh
  • API 版本:2026-01-25(当前稳定版)
  • 货币:仅支持 TZS——其他货币会返回 400 validation_error。金额以最小货币单位的整数表示(不含小数)。
  • 身份验证:在 Authorization 标头中使用 Bearer 令牌。密钥格式为 snp_...,创建后仅显示一次,位于 Snippe Dashboard 的 Settings → API Keys 下。
Authorization: Bearer snp_your_api_key_here

API 密钥具有一组权限范围,商户在创建密钥时选择这些范围:

权限范围允许的操作
collection:read查看支付和余额
collection:create创建支付
disbursement:read查看付款
disbursement:create创建付款

如果你要构建仅用于收款的服务(例如结账服务),只需要 collection:*。除非应用确实会向外付款,否则不要申请 disbursement:*。

核心概念

Snippe 有四类资源。确定任务需要哪一类资源是首要决策:

资源用途端点前缀
支付向客户收款(移动支付、银行卡、二维码)/v1/payments
会话托管式结账页面——Snippe 呈现界面并处理支付方式选择/api/v1/sessions
付款向移动钱包或银行账户汇款/v1/payouts
Webhook向你的 URL 实时推送事件(你的服务)

支付与会话——这是最常见的分支选择问题:

  • 如果你需要完全控制界面并自行构建支付表单,请使用 Payments API。每次调用都会为一个渠道(移动支付/银行卡/二维码)创建一个支付意图。
  • 如果你想使用 Snippe 托管的移动端优化结账页面,请使用 Sessions——一个 URL 即可处理多种支付方式,非常适合通过 SMS/WhatsApp 分享,或嵌入简单应用。

快速开始:接受移动支付

从请求到结算的最简单端到端流程。

1. 创建支付
POST /v1/payments
Authorization: Bearer snp_your_api_key_here
Content-Type: application/json
Idempotency-Key: order-12345-attempt-1
{
  "payment_type": "mobile",
  "details": { "amount": 500, "currency": "TZS" },
  "phone_number": "255781000000",
  "customer": {
    "firstname": "FirstName",
    "lastname": "LastName",
    "email": "[email protected]"
  },
  "webhook_url": "https://yoursite.com/webhooks/snippe",
  "metadata": { "order_id": "ORD-12345" }
}
2. 响应
{
  "status": "success",
  "code": 201,
  "data": {
    "reference": "9015c155-9e29-4e8e-8fe6-d5d81553c8e6",
    "status": "pending",
    "payment_type": "mobile",
    "amount": { "currency": "TZS", "value": 500 },
    "expires_at": "2026-01-25T05:04:54Z"
  }
}

客户的手机会收到 USSD 推送。客户输入 PIN 后,Snippe 会向 webhook_url 发送 payment.completed(或 payment.failed)。如果支付未获授权,则会在 4 小时后过期。

3.(可选)轮询状态

如果你无法接收 Webhook,或者想要一种不依赖 Webhook 的确认方式,可以轮询:

GET /v1/payments/{reference}
Authorization: Bearer snp_your_api_key_here

实时状态优先使用 Webhook;仅在备用或对账时使用轮询。

关键规则(容易出错)

以下事项可能导致集成故障并引发支持工单。编写代码时,请逐项检查:

  • 仅支持 TZS 货币。 尝试发送 USD、EUR 或 KES 会返回 400 validation_error。金额以最小单位的整数表示——500 表示 500 TZS,而不是 5.00。
  • 最低金额:付款为 500 TZS,出款为 5,000 TZS。低于这些金额会返回验证错误。
  • 电话号码格式:255XXXXXXXXX(不带加号)或 +255XXXXXXXXX(带加号)。两种格式都有效;0781000000 这类本地格式无效。
  • Idempotency-Key 长度必须 ≤ 30 个字符。 这是导致难以理解的 PAY_001 错误的最常见原因。如果遇到 PAY_001,请先检查幂等键长度,再判断上游处理器是否宕机。相同键加不同请求正文会返回 422;相同键加相同请求正文会返回缓存响应(有效期为 24 小时)。始终在 POST /v1/payments 和 POST /v1/payouts/send 中包含幂等键。
  • Webhook 的 data.amount 是一个对象,不是整数。在 webhook 载荷中,你会收到 {"value": 50000, "currency": "TZS"}——请分别解析 .value 和 .currency。这与请求正文恰好相反,后者的 details.amount 是一个普通整数。这里解析不匹配是一个典型错误。
  • 根据原始请求正文验证 webhook 签名——按收到时的原样读取字节,不要先解析 JSON 再重新序列化。重新序列化会改变空白字符或键的顺序,从而导致 HMAC 验证失败。在 Express 中,使用 express.raw({ type: "application/json" });在 Flask 中,使用 request.get_data(as_text=True);在 Go 中,在任何 JSON 解码之前,使用 io.ReadAll 读取 req.Body。
  • 拒绝时间戳早于 5 分钟的 webhook,以防止重放攻击。在信任载荷之前,请将 X-Webhook-Timestamp 与当前时间进行比较。
  • 使用恒定时间比较(crypto.timingSafeEqual、hmac.compare_digest、hash_equals、hmac.Equal)检查 HMAC——绝不要对字符串使用 ==。计时攻击确实存在,而且很容易防范。
  • 按 id 对 webhook 事件去重——Snippe 可能会多次发送相同事件,你的处理程序必须具备幂等性。
  • 在 30 秒内向 webhook 返回 2xx,然后再异步处理。如果在处理过程中访问数据库或执行耗时操作,就会触发重试计划(3 → 6 → 12 → 24 分钟;尝试 5 次后放弃)。
  • 速率限制为每分钟 60 个请求。 请遵循 X-Ratelimit-Limit、X-Ratelimit-Remaining 和 X-Ratelimit-Reset 标头。收到 429 时,请等待到重置时间再继续。
  • Webhook 和重定向 URL 必须使用 HTTPS,且长度 ≤ 500 个字符。HTTP URL 会被拒绝。

选择合适的参考文件

仅加载当前任务所需的内容:

如果你正在处理……阅读
创建移动货币 / 卡 / QR 付款references/payments.md
托管结账页面、付款链接或分享 URLreferences/sessions.md
向外付款(工资、退款、供应商出款)references/disbursements.md
接收 webhook、验证签名、处理重试references/webhooks.md
诊断错误响应或验证失败references/errors.md

每个参考文件都自成一体,无需串联阅读。如果任务涉及多个方面(例如“创建付款并处理 webhook”),请加载两个相关文件。

出款前检查余额

创建出款之前,最好先确认余额充足:

GET /v1/payments/balance
Authorization: Bearer snp_your_api_key_here

返回以 TZS 计价的 available 和 balance 对象。出款手续费会加在金额之上,因此,若要出款 5,000 TZS,手续费为 1,500 TZS,则至少需要 6,500 TZS 的可用余额。请先使用 GET /v1/payouts/fee?amount=... 计算确切手续费——相关说明见 references/disbursements.md。

延伸阅读

如果这里没有涵盖某个问题,请参阅 https://snippe.sh/docs/2026-01-25 上的官方文档。也可以在任何文档 URL 后添加 .mdx,获取原始 Markdown(例如:https://snippe.sh/docs/2026-01-25/payments/mobile-money.mdx)。

评论

支持 Markdown