Skip to content

示范商城 ​

HashNut 提供完整可运行的示范商户应用,演示完整的支付对接流程。可以作为你自己实现的参考。

组件语言仓库
Demo 后端 (Go)Go + Ginhashnut-demo-go
Demo 后端 (Java)Java + Spring Boothashnut-demo
Demo 前端React + TypeScripthashnut-demo-web

两个后端实现相同的 API 接口,前端通用。

TIP

想把它跑起来(克隆代码、起数据库、填 api key、启动前后端、跑通一笔支付), 见 2.5 验证 api key —— 那一页是按操作顺序写的完整步骤。

本页是参考资料:架构、数据库表结构、以及你自己实现时需要注意的关键细节。

架构 ​

浏览器 (localhost:5173)            Demo 后端 (localhost:1800)           HashNut API
        |                                   |                                |
        |  GET /api/products                |                                |
        |---------------------------------->|                                |
        |  GET /api/chains                  |                                |
        |---------------------------------->|  (从数据库读取)                |
        |                                   |                                |
        |  POST /api/orders                 |                                |
        |  {productId, blockChain, tokenSymbol} |                            |
        |---------------------------------->|  SDK.createOrder()             |
        |                                   |------------------------------->|
        |                                   |  payOrderId + receiptAddress   |
        |  payUrl (跳转到 HashNut 支付页)   |<-------------------------------|
        |<----------------------------------|                                |
        |                                   |                                |
        |  (用户在 HashNut 页面支付)        |                                |
        |                                   |  POST /api/notify (回调通知)   |
        |                                   |<-------------------------------|
        |                                   |  更新订单状态                   |
        |                                   |                                |
        |  跳转到 /payment-result           |                                |
        |  (前端显示支付成功)               |                                |

接口清单 ​

后端对前端暴露的接口,两个语言版本完全一致:

方法路径说明
GET/api/products获取商品列表
GET/api/chains获取支持的链+币种(从数据库读取)
POST/api/orders创建订单 {productId, blockChain, tokenSymbol}
GET/api/orders/:id查询订单状态
POST/api/orders/:id/confirm提交支付交易哈希 {payTxId}
POST/api/notifyHashNut 支付结果回调

数据库表结构 ​

Demo 使用 PostgreSQL,包含以下表:

表用途
t_coin_info支持的链和币种(决定前端能选哪些)
t_hashnut_api_key每条链的 splitter 地址 + API 密钥
products商品(只有价格,不绑定链/币种)
orders订单(记录用户选择的链+币种)

t_coin_info 决定支付页面上能选哪些链和币种,按你实际接入的链配置:

sql
INSERT INTO t_coin_info (block_chain, token_symbol, chain_label, coin_label, contract_address, decimals) VALUES
    ('ETH', 'usdt', 'Ethereum', 'USDT', '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6),
    ('TRON', 'usdt', 'Tron',     'USDT', 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',         6);

t_hashnut_api_key 一条链一行,值来自一键开户导出的信息 —— 具体怎么填见 2.5.4 把开户信息填进 migrate.sql。

关键实现细节 ​

照抄 demo 之前,这几点是你自己实现时最容易出问题的地方。

多链支持 ​

商品不绑定特定链。前端让用户选择支付链和币种,将 blockChain + tokenSymbol 传给后端。 后端从数据库查找对应的 splitter 和 API 密钥。

Webhook 处理 ​

/api/notify 端点接收 HashNut 的支付通知。你的处理逻辑需要:

  1. 解析 JSON(payOrderId、state、payTxId)
  2. 更新数据库中的订单状态
  3. 返回字符串 "success"(HTTP 200)确认收到

如果不返回 "success",HashNut 会重试通知。

完整的通知字段与验签方式见 支付通知。

支付页面跳转 ​

创建订单后,后端返回 payUrl 指向 HashNut 支付页面。前端跳转用户到该页面。 支付完成后,用户被跳转回你的 callbackUrl,带有 state 和 merchantOrderId 等查询参数。

notifyUrl 与 callbackUrl 的方向相反 ​

这是接入时最容易搞反的一对参数:

字段谁请求谁是否需要公网可达
notifyUrlHashNut 服务器 → 你的服务器需要
callbackUrl用户浏览器 → 你的站点不需要

Demo 里对应的路径分别是 /api/notify 和 /payment-result。本地开发时 notifyUrl 需要 内网穿透才能公网可达,做法见 附录:本地调试让 notifyUrl 公网可达。

相关 ​