Skip to main content

Create Order

Create payment orders that generate unique payment links for your customers.

Overview

Payment orders define the payment amount, currency, and blockchain network. Each order generates a unique payment link that customers can use to complete their payment.

Quick Start

import { HashNutClient, HashNutService, CreatePayOrderRequest } from '@hashnut/sdk';

const client = new HashNutClient(secretKey, true);
const service = new HashNutService(client);

const request = new CreatePayOrderRequest.Builder()
.withAccessKeyId(accessKeyId)
.withMerchantOrderId(`order-${Date.now()}`)
.withChainCode('erc20')
.withCoinCode('usdt')
.withAmount('0.01')
.build();

const response = await service.createPayOrder(request);
console.log('Payment URL:', response.data.paymentUrl);

Order Creation Flow

Required Parameters

ParameterTypeDescriptionExample
merchantOrderIdstringUnique order ID in your system"order-123"
chainCodestringBlockchain network code"erc20", "polygon-erc20"
coinCodestringCurrency code (case-sensitive)"usdt", "usdc"
amountdecimalPayment amount (minimum 0.01)0.01, 1.5

Optional Parameters

ParameterTypeDescriptionWhen to Use
callBackUrlstringWebhook URL for payment notificationsAlways recommended
frontendCallbackUrlstringRedirect URL after paymentFor customer redirect
receiptAddressstringCustom receiving addressIf not using default
splitterAddressstringCustom smart contract addressAdvanced use cases

Step-by-Step Guide

Step 1: Choose Chain and Currency

First, query available options:

// Get supported chains
import { QueryChainsRequest } from '@hashnut/sdk';
const chainsRequest = new QueryChainsRequest.Builder().build();
const chainsResponse = await service.queryAllChainInfo(chainsRequest);

// Get supported tokens for a chain
import { QuerySupportCoinRequest } from '@hashnut/sdk';
const coinsRequest = new QuerySupportCoinRequest.Builder()
.withChainCode('erc20')
.build();
const coinsResponse = await service.querySupportCoin(coinsRequest);

Common Combinations:

  • Ethereum + USDT: chainCode: "erc20", coinCode: "usdt"
  • Polygon + USDC: chainCode: "polygon-erc20", coinCode: "usdc"
  • TRON + USDT: chainCode: "tron-trc20", coinCode: "usdt"

Step 2: Set Payment Amount

Important:

  • Minimum: 0.01
  • Format: Base unit (e.g., 0.01 for 0.01 USDT, not 10000)
  • Precision: Round to 2 decimal places
// ✅ Correct
amount: 0.01 // 0.01 USDT

// ❌ Wrong
amount: 10000 // This would be 10,000 USDT!

Step 3: Generate Merchant Order ID

Requirements:

  • Must be unique per merchant
  • Max 255 characters
  • Use descriptive format

Good Examples:

`order-${Date.now()}`
`payment-${userId}-${timestamp}`
`${productId}-${orderNumber}`

Bad Examples:

`order-1`  // Not unique
`test` // Not descriptive

Step 4: Configure Callbacks

Backend Webhook (callBackUrl):

  • Receives payment status updates
  • Must be HTTPS
  • Should verify signatures

Frontend Redirect (frontendCallbackUrl):

  • Customer redirected here after payment
  • Can include order parameters
  • Should show success/failure page

Step 5: Create the Order

try {
const request = new CreatePayOrderRequest.Builder()
.withAccessKeyId(accessKeyId)
.withMerchantOrderId(`order-${Date.now()}`)
.withChainCode('erc20')
.withCoinCode('usdt')
.withAmount('0.01')
.build();

const response = await service.createPayOrder(request);
const order = response.data;

// Store order.payOrderId in your database
// Redirect customer to order.paymentUrl
window.location.href = order.paymentUrl;
} catch (error) {
console.error('Order creation failed:', error);
}

Order Response

Response Fields

{
"code": 0,
"msg": "success",
"data": {
"payOrderId": "01KBZ292SK2GKFK97916F5EC3B",
"accessSign": "D3DE7E4002057C0EAED1BE2268DA53CC9058DCFC9DCAF50D999AF270A7B033C5",
"merchantOrderId": "order-123"
}
}

Payment URL Construction

Construct the payment URL:

https://testnet.hashnut.io/pay?accessSign={accessSign}&merchantOrderId={merchantOrderId}&payOrderId={payOrderId}&chainCode={chainCode}

SDK Method:

const paymentUrl = order.paymentUrl; // SDK handles construction

Order Types

DeFi Orders

Smart Contract Mode:

  • Uses address pool from smart contract
  • Funds held in contract until withdrawal
  • Supports multi-party fee splitting

Use When:

  • You need maximum security
  • You want address pool management
  • You need on-chain verification

CeFi Orders

Direct Wallet Mode:

  • Uses your direct wallet address
  • Funds sent directly to wallet
  • Simplified fund management

Use When:

  • You want immediate fund access
  • You prefer simpler operations
  • You don't need address pools

Best Practices

Order ID Management

  1. Use UUIDs or Timestamps: Ensure uniqueness
  2. Store in Database: Save payOrderId and merchantOrderId mapping
  3. Idempotency: Check for existing orders before creating
  4. Format: Use consistent naming convention

Amount Handling

  1. Validate Minimum: Ensure amount >= 0.01
  2. Round to 2 Decimals: Avoid floating point issues
  3. Currency Precision: Consider token decimals (USDT = 6, ETH = 18)
  4. Display Format: Show user-friendly amounts

Error Handling

try {
const request = new CreatePayOrderRequest.Builder()
.withAccessKeyId(accessKeyId)
.withMerchantOrderId(`order-${Date.now()}`)
.withChainCode('erc20')
.withCoinCode('usdt')
.withAmount('0.01')
.build();

const response = await service.createPayOrder(request);
} catch (error) {
if (error.errorCode === -2) {
// Authentication or parameter error
console.error('Invalid request:', error.message);
} else {
// Other errors
console.error('Order creation failed:', error);
}
}

Common Use Cases

E-Commerce Checkout

// In checkout flow
const request = new CreatePayOrderRequest.Builder()
.withAccessKeyId(accessKeyId)
.withMerchantOrderId(`checkout-${cartId}-${Date.now()}`)
.withChainCode('erc20')
.withCoinCode('usdt')
.withAmount(cartTotal.toString())
.build();

const response = await service.createPayOrder(request);
// Redirect to payment
router.redirect(response.data.paymentUrl);

Subscription Payment

// Recurring payment
const request = new CreatePayOrderRequest.Builder()
.withAccessKeyId(accessKeyId)
.withMerchantOrderId(`subscription-${userId}-${subscriptionId}-${billingCycle}`)
.withChainCode('polygon-erc20')
.withCoinCode('usdc')
.withAmount(subscriptionAmount.toString())
.build();

const response = await service.createPayOrder(request);

Donation/One-Time Payment

// Simple donation
const request = new CreatePayOrderRequest.Builder()
.withAccessKeyId(accessKeyId)
.withMerchantOrderId(`donation-${Date.now()}`)
.withChainCode('erc20')
.withCoinCode('usdt')
.withAmount(donationAmount.toString())
.build();

const response = await service.createPayOrder(request);

Order Expiration

Orders may expire after a certain time period. Check order status regularly if payment is delayed.

Next Steps


Order created? Learn about Order Management →