跳到主要内容

商户接入文档

对接说明

两个功能:代收、代付。全部接口为 HTTPS + POST + JSON,接口地址 https://api.nickpay.net。你要写的只有签名、调接口、接通知三件事。

2026-09-18 起平台更名 NickPay、接口域名换为 api.nickpay.net; 原 api.hans-pay.cc.cd 继续可用,接口与签名规则不变,请尽快切到新域名。

版本 v2.1 更新于 2026-09-18

通用约定

凭据与白名单

运营提供 merchant_no(商户号)与 api_secret(签名密钥,只展示一次), 并登记你的出口 IP。平台不登记默认回调地址:代收与代付的通知通常打到不同接收端,请每笔请求自带 notify_url

请求头

Content-Type: application/json,并设置自定义 User-Agent(如 MyShop/1.0)。

金额

一律字符串。请求传整数 VND("50000"),响应固定 2 位小数("50000.00")。

时间

expire_atpaid_at 为越南时间 UTC+7,格式 YYYY-MM-DD HH:mm:sstimestamp 为 Unix 秒,与服务器相差超过 5 分钟拒绝。

响应外壳

{"code":"0000","msg":"success","data":{…},"sign":"…"},HTTP 恒为 200,看 code

幂等

同一 merchant_order_no 参数一致的重复请求返回同一笔单;参数不一致返回 1005。 请求超时请用同一单号重发或查单,不要换单号。

签名

HMAC-SHA256,请求、响应、通知三个方向用同一个算法。

  1. 1

    取字段

    请求 JSON 第一层全部字段(不含 sign),去掉值为空字符串的。

  2. 2

    拼接

    按字段名 ASCII 升序拼成 k1=v1&k2=v2&…

  3. 3

    HMAC

    sign = hex(HMAC_SHA256(拼接串, api_secret)),小写。

    响应验签:对 data 内的字段签。通知验签:对通知 JSON 去掉 sign 后的全部字段签。

sign.py
import hashlib, hmac

def sign(params: dict, secret: str) -> str:
    items = sorted(
        (k, v) for k, v in params.items()
        if k != "sign" and v != ""
    )
    raw = "&".join(f"{k}={v}" for k, v in items)
    return hmac.new(
        secret.encode(), raw.encode(), hashlib.sha256
    ).hexdigest()

# 通知验签
def verify_notify(body: dict, secret: str) -> bool:
    got  = body.get("sign", "")
    rest = {k: v for k, v in body.items() if k != "sign"}
    return hmac.compare_digest(got, sign(rest, secret))

# 响应验签:对 data 签,错误响应没有 sign
def verify_resp(resp: dict, secret: str) -> bool:
    return resp.get("code") == "0000" and \
        hmac.compare_digest(resp.get("sign", ""), sign(resp["data"], secret))

接口

代收三个,代付三个(加一个银行列表),余额一个。请求都带 merchant_notimestampsign

POST /api/v1/pay/create pay_method 由运营告知(当前 BANK_QR)。 付款人四项传真实值。订单 30 分钟有效。

pay_type=URL:引导用户打开 pay_payload(平台收银台,整段原样使用); pay_type=QRCODE:把 pay_payload 渲染成二维码。按字段判断,不要写死。

请求
{
  "merchant_no":        "M1001",
  "merchant_order_no":  "ORD20260820001",  // ≤ 64
  "amount":             "50000",           // 整数 VND
  "currency":           "VND",             // 选填
  "pay_method":         "BANK_QR",
  "payer_name":         "NGUYEN VAN A",
  "payer_email":        "a@example.com",
  "payer_phone":        "0912345678",
  "payer_account_no":   "0123456789",
  "payer_account_type": "BANK",            // 选填,或 PHONE
  "user_id":            "U10086",          // 选填
  "notify_url":         "https://your.domain/nickpay/notify",  // 请每笔都传:本笔通知地址;不传则不推送通知、只能查单
  "timestamp":          "1755657600",
  "sign":               "9f8e...c1"
}
响应 data
{
  "order_no":          "P2408201234",
  "merchant_order_no": "ORD20260820001",
  "amount":            "50000.00",
  "currency":          "VND",
  "pay_type":          "URL",
  "pay_payload":       "https://api.nickpay.net/pay/P24...?t=...",
  "expire_at":         "2026-08-20 15:30:00"
}

错误码

code0000 表示成功。HTTP 403 + 纯文本 error code: 1010 不是本接口错误,是安全防护拦了你的 User-Agent,换成自定义 UA 即可。

请求

1001 验签失败
1002 参数缺失或非法看 msg
1003 金额必须为整数 VND
1008 请求过期校准时钟
1009 IP 不在白名单联系运营登记

订单

1005 订单号重复且参数不一致换单号
1006 支付方式不支持联系运营
1007 订单不存在
1010 金额超出单笔限额msg 给出范围

商户与系统

1004 商户不存在或已停用
1012 代付:可用余额不足
1013 代付:未开通联系运营
2001 渠道暂不可用稍后重试
9999 系统错误先查单再联系运营

沙箱

代收下单请求多带 "sandbox": "1"(参与签名),其余不变:不产生真实支付, order_noT 开头,pay_payload 是模拟收银台, 页面上点「模拟支付成功 / 失败」即触发与生产完全一致的通知;查单同样带 "sandbox": "1"T 开头的单号绝不能发货。沙箱不支持代付。

还有问题?

联调阶段的疑问直接找运营对接人确认。