On this page
HMAC-SHA256 Signing ProcessStep 1: Generate Request MetadataStep 2: Build the Signing StringStep 3: Compute the SignatureStep 4: Set Request HeadersCode ExamplesAccess Sign (Body-Level Signing)Endpoint Authentication MethodsAuthentication
HashNut uses HMAC-SHA256 signatures to authenticate API requests. Some endpoints use header-based signing, while others use an accessSign field in the request body.
HMAC-SHA256 Signing Process
The signing process consists of four steps:
Step 1: Generate Request Metadata
Generate a UUID and a Unix timestamp (seconds) for each request.
Step 2: Build the Signing String
Concatenate the three components without any separator:
signString = uuid + timestamp + requestBodyWhere requestBody is the JSON string of the request body.
Step 3: Compute the Signature
Compute HMAC-SHA256 using your Secret Key, then Base64-encode the result:
signature = base64( hmac_sha256( secretKey, signString ) )Step 4: Set Request Headers
Include the following headers in your HTTP request:
| Header | Description |
|---|---|
hashnut-request-uuid | The UUID generated in Step 1 |
hashnut-request-timestamp | The Unix timestamp generated in Step 1 |
hashnut-request-sign | The Base64-encoded HMAC-SHA256 signature |
Content-Type | Must be application/json |
Code Examples
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.UUID;
public class HashNutSign {
public static String[] sign(String secretKey, String body) throws Exception {
String reqUUID = UUID.randomUUID().toString();
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String signString = reqUUID + timestamp + body;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));
String signature = Base64.getEncoder().encodeToString(
mac.doFinal(signString.getBytes()));
return new String[]{reqUUID, timestamp, signature};
}
}package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"time"
"github.com/google/uuid"
)
func sign(secretKey, body string) (reqUUID, timestamp, signature string) {
reqUUID = uuid.New().String()
timestamp = fmt.Sprintf("%d", time.Now().Unix())
signString := reqUUID + timestamp + body
mac := hmac.New(sha256.New, []byte(secretKey))
mac.Write([]byte(signString))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
return reqUUID, timestamp, signature
}const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
function sign(secretKey, body) {
const reqUUID = uuidv4();
const timestamp = Math.floor(Date.now() / 1000).toString();
const signString = reqUUID + timestamp + body;
const signature = crypto
.createHmac('sha256', secretKey)
.update(signString)
.digest('base64');
return { reqUUID, timestamp, signature };
}import hmac
import hashlib
import base64
import uuid
import time
def sign(secret_key: str, body: str):
req_uuid = str(uuid.uuid4())
timestamp = str(int(time.time()))
sign_string = req_uuid + timestamp + body
signature = base64.b64encode(
hmac.new(
secret_key.encode(),
sign_string.encode(),
hashlib.sha256
).digest()
).decode()
return req_uuid, timestamp, signatureAccess Sign (Body-Level Signing)
Some endpoints (such as Query Order and Confirm Paid) use a simplified signing method where the signature is included in the request body as the accessSign field instead of in headers.
The accessSign is computed as:
accessSign = base64( hmac_sha256( secretKey, requestBodyWithoutAccessSign ) )Where requestBodyWithoutAccessSign is the JSON string of the request body before the accessSign field is added.
Endpoint Authentication Methods
| Endpoint | Auth Method | Description |
|---|---|---|
POST /v4.0.0/pay/orders/api | Header signing | Create order |
POST /v4.0.0/pay/orders/cancel/api | Header signing | Cancel order |
POST /v4.0.0/pay/orders/query | Body accessSign | Query order |
POST /v4.0.0/pay/orders/confirm | Body accessSign | Confirm paid |
POST /v4.0.0/pay/orders/supplements | Body accessSign | Query supplements |
POST /v4.0.0/config/* | None | Public config endpoints |
TIP
If you use the Go SDK, signing is handled automatically. You only need to provide your Access Key ID and Secret Key when initializing the client.
