关于 snippe-integration
snippe-integration 是面向开发者的技能,为应用接入坦桑尼亚支付处理商 Snippe 提供协议与实现指导,涵盖付款、出款和安全处理 Webhook。
主要功能
- 01创建付款、结账会话和出款
- 02验证 Webhook 签名与时间戳
- 03处理重复事件和重试
- 04排查 API 错误与验证问题
适用场景
- 01集成移动货币、银行卡或二维码收款
- 02实现 Snippe 托管结账页面
- 03安全接收支付状态 Webhook
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ neurotech-hq/ skills --skill snippe-integration安装后在 Claude Code 中输入/snippe-integration确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/disbursements.mderrors.mdpayments.mdsessions.mdwebhooks.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 |
| 托管结账页面、付款链接或分享 URL | references/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)。