1. Trang chủ
  2. Nhà phát triển
Nhà phát triển

Tích hợp nhận thanh toán tiền mã hóa chỉ trong vài phút

REST API tương thích NOWPayments v1: cùng endpoint, trường dữ liệu, giá trị trạng thái và mã tiền tệ. Xác thực bằng x-api-key và nhận cập nhật trạng thái qua IPN có chữ ký.

URL cơ sở của APIhttps://omniwallet.ewin888.com/api/v1/
Môi trường thử nghiệmhttps://omniwallet-dev.ewin888.com/api/v1/

Bắt đầu nhanh

  1. 01

    Lấy khóa API

    Đăng ký và đăng nhập trang quản trị, tạo khóa tại “Nhà phát triển → Khóa API”, sau đó vào mục “IPN” để thiết lập khóa bí mật IPN. Chúng tôi khuyến nghị hoàn tất tích hợp trong môi trường thử nghiệm trước.

  2. 02

    Tạo khoản thanh toán

    Gọi POST /v1/payment với số tiền, đơn vị tiền tệ định giá và loại tiền thanh toán. Trong phản hồi, pay_address là địa chỉ riêng của khoản thanh toán này, còn pay_amount là số tiền cần thanh toán.

    POST /v1/paymentcurl
    curl -X POST "https://omniwallet.ewin888.com/api/v1/payment" \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: order-A-1024" \
      -d '{
        "price_amount": 120,
        "price_currency": "usd",
        "pay_currency": "usdttrc20",
        "order_id": "A-1024",
        "order_description": "Pro plan, 12 months",
        "ipn_callback_url": "https://example.com/ipn"
      }'
    Phản hồiJSON
    {
      "payment_id": 355446374401130,
      "payment_status": "waiting",
      "pay_address": "TJ8nq3M5yVfQ9C2dWkPz7aH4sLrE6uXbGt",
      "price_amount": 120,
      "price_currency": "usd",
      "pay_amount": 120.02,
      "pay_currency": "usdttrc20",
      "order_id": "A-1024",
      "network": "TRC20",
      "expiration_estimate_date": "2026-10-02T09:15:00.000Z",
      "omni_payment_url": "https://omniwallet.ewin888.com/payment/4fKq9ZtR2mXcL8vBnW1pYs"
    }
  3. 03

    Hướng dẫn khách hàng thanh toán

    Hiển thị địa chỉ và số tiền (hoặc mã QR) cho khách hàng; hoặc dùng POST /v1/invoice để tạo trang hóa đơn, rồi chuyển hướng khách hàng đến invoice_url trong phản hồi.

    POST /v1/invoicecurl
    curl -X POST "https://omniwallet.ewin888.com/api/v1/invoice" \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "price_amount": 49.9,
        "price_currency": "usd",
        "order_id": "A-1025",
        "order_description": "Starter plan",
        "ipn_callback_url": "https://example.com/ipn",
        "success_url": "https://example.com/thanks",
        "cancel_url": "https://example.com/cart"
      }'
    Phản hồiJSON
    {
      "id": "355447603200201",
      "order_id": "A-1025",
      "price_amount": "49.9",
      "price_currency": "usd",
      "pay_currency": null,
      "invoice_url": "https://omniwallet.ewin888.com/invoice/8hTz2QpLm4XwN7cVb1RkYe",
      "success_url": "https://example.com/thanks",
      "cancel_url": "https://example.com/cart",
      "created_at": "2026-10-01T09:20:00.000Z"
    }
  4. 04

    Nhận IPN

    Mỗi khi trạng thái thanh toán thay đổi, chúng tôi sẽ gửi yêu cầu POST đến ipn_callback_url của bạn. Hãy xác minh chữ ký trước, sau đó cập nhật đơn hàng theo payment_status.

    Xác minh IPN
  5. 05

    Chuyển sang môi trường chính thức

    Sau khi doanh nghiệp được xác minh, hãy tạo khóa API và khóa bí mật IPN mới trong môi trường chính thức, rồi đổi URL cơ sở sang môi trường chính thức.

Xác minh chữ ký IPN

Chúng tôi dùng khóa bí mật IPN của bạn để tính HMAC-SHA512 trên “JSON đã sắp xếp tên trường theo thứ tự bảng chữ cái”, rồi đặt kết quả dưới dạng chuỗi thập lục phân vào header x-omni-sig. Nội dung yêu cầu chúng tôi gửi đi chính là đoạn JSON đã sắp xếp này, vì vậy bạn chỉ cần xác minh trực tiếp trên nội dung thô nhận được.

  • Đối chiếu chữ ký bằng phép so sánh thời gian hằng định (constant-time)
  • IPN có thể bị gửi trùng hoặc đến không theo thứ tự: hãy loại bỏ trùng lặp theo payment_id và trạng thái, khi cần thì gọi GET /v1/payment/{id} để lấy trạng thái mới nhất
  • Trả về bất kỳ mã 2xx nào nghĩa là đã nhận; với các phản hồi khác hoặc khi hết thời gian chờ, IPN sẽ được tự động gửi lại
ExpressNode.js
import crypto from 'node:crypto';
import express from 'express';

const app = express();
const IPN_SECRET = process.env.OMNI_IPN_SECRET;

// Keep the raw body: the signature covers the exact bytes we send.
app.post('/ipn', express.raw({ type: 'application/json' }), (req, res) => {
  const received = String(req.get('x-omni-sig') || '');
  const expected = crypto
    .createHmac('sha512', IPN_SECRET)
    .update(req.body)
    .digest('hex');

  const valid = received.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
  if (!valid) return res.status(401).send('invalid signature');

  const payment = JSON.parse(req.body.toString('utf8'));
  // Idempotent update: the same status can be delivered more than once.
  // await orders.applyStatus(payment.order_id, payment.payment_status);
  res.sendStatus(200);
});

app.listen(3000);
PHPPHP
<?php
$secret   = getenv('OMNI_IPN_SECRET');
$raw      = file_get_contents('php://input');
$received = $_SERVER['HTTP_X_OMNI_SIG'] ?? '';

// The signature covers the exact bytes we send.
$expected = hash_hmac('sha512', $raw, $secret);
if (!hash_equals($expected, $received)) {
    http_response_code(401);
    exit('invalid signature');
}

$payment = json_decode($raw, true);
// Idempotent update: the same status can be delivered more than once.
// apply_status($payment['order_id'], $payment['payment_status']);
http_response_code(200);
FlaskPython
import hashlib
import hmac
import json
import os

from flask import Flask, abort, request

app = Flask(__name__)
IPN_SECRET = os.environ["OMNI_IPN_SECRET"].encode()

@app.post("/ipn")
def ipn():
    raw = request.get_data()  # the exact bytes we signed
    expected = hmac.new(IPN_SECRET, raw, hashlib.sha512).hexdigest()
    received = request.headers.get("x-omni-sig", "")
    if not hmac.compare_digest(expected, received):
        abort(401)

    payment = json.loads(raw)
    # Idempotent update: the same status can be delivered more than once.
    # apply_status(payment["order_id"], payment["payment_status"])
    return "", 200
Ví dụ nội dung IPNJSON
{
  "actually_paid": 120.02,
  "actually_paid_at_fiat": 120,
  "invoice_id": null,
  "order_description": "Pro plan, 12 months",
  "order_id": "A-1024",
  "outcome_amount": 119.42,
  "outcome_currency": "usdttrc20",
  "parent_payment_id": null,
  "pay_address": "TJ8nq3M5yVfQ9C2dWkPz7aH4sLrE6uXbGt",
  "pay_amount": 120.02,
  "pay_currency": "usdttrc20",
  "payment_id": 355446374401130,
  "payment_status": "finished",
  "price_amount": 120,
  "price_currency": "usd",
  "purchase_id": null,
  "updated_at": "2026-10-01T09:17:42.000Z"
}

Trạng thái thanh toán

Giá trị trạng thái giống với NOWPayments.

Trạng tháiÝ nghĩa
waiting
Chờ thanh toán
Đang chờ khách hàng thanh toán
confirming
Đang xác nhận
Đã phát hiện giao dịch, đang chờ xác nhận khối
confirmed
Đã xác nhận
Đã xác nhận và ghi có
sending
Đang quyết toán
Đang quyết toán về ví của bạn
partially_paid
Thanh toán một phần
Thanh toán chưa đủ, khách hàng có thể bù phần còn thiếu trước khi hết hạn
finished
Hoàn tất
Thanh toán hoàn tất
failed
Thất bại
Thanh toán thất bại, ví dụ do trùng khớp danh sách trừng phạt
refunded
Đã hoàn tiền
Đã hoàn tiền cho người thanh toán
expired
Đã hết hạn
Quá hạn mà chưa thanh toán

Chuyển từ NOWPayments

API tương thích nên phần lớn mã nguồn không cần sửa đổi.

  1. Đổi URL cơ sởThay https://api.nowpayments.io/v1/ bằng URL của OmniWallet bên dưới.
  2. Dùng khóa API của OmniWalletTên header vẫn là x-api-key.
  3. Cập nhật cách xác minh IPNChuyển sang dùng khóa bí mật IPN của OmniWallet và header x-omni-sig. Nếu muốn giữ nguyên hoàn toàn mã hiện có, bạn có thể bật header tương thích x-nowpayments-sig trong trang quản trị.
  4. Kiểm tra loại tiền được hỗ trợMã tiền tệ giống nhau (ví dụ usdttrc20, usdcsol), nhưng bạn chỉ có thể dùng những loại tiền chúng tôi hỗ trợ. Hãy kiểm tra bằng GET /v1/merchant/coins hoặc trang tiền mã hóa được hỗ trợ.
  5. Kiểm tra cài đặt chi trảChi trả vẫn dùng JWT có hiệu lực 5 phút lấy từ POST /v1/auth. Ngoài ra, khóa API có quyền chi trả phải thiết lập danh sách IP được phép, và địa chỉ nhận tiền cũng phải được thêm vào danh sách được phép trước.
URL cơ sở của APIdiff
- https://api.nowpayments.io/v1/
+ https://omniwallet.ewin888.com/api/v1/

Giữ nguyên

  • Đường dẫn endpoint và phương thức HTTP
  • Tên trường trong yêu cầu và phản hồi
  • Giá trị trạng thái của thanh toán và chi trả
  • Mã tiền tệ
  • Thuật toán chữ ký IPN

Những khác biệt cần lưu ý

  • Header chữ ký IPN là x-omni-sig (có thể chọn gửi kèm cả x-nowpayments-sig)
  • Các trường mở rộng của OmniWallet bắt đầu bằng omni_
  • Không hỗ trợ chi trả bằng tiền pháp định (phản hồi HTTP 501)
  • Tiền quyết toán luôn được chuyển về ví đã liên kết trong trang quản trị
  • Môi trường thử nghiệm dùng testnet thật của các blockchain

Môi trường thử nghiệm (Sandbox)

Môi trường thử nghiệm là một bản triển khai độc lập, kết nối với testnet của từng chuỗi, với API hoàn toàn giống môi trường chính thức.

  • Tài khoản, khóa API và dữ liệu đều tách biệt với môi trường chính thức nên bạn cần đăng ký riêng; việc xác minh doanh nghiệp sẽ được tự động phê duyệt
  • Thanh toán bằng tiền thử nghiệm của từng testnet; giao dịch có thể tra cứu trên trình khám phá khối của testnet đó
  • Tiền thử nghiệm không có giá trị thực; không chuyển tài sản trên mạng chính (mainnet) vào địa chỉ của môi trường thử nghiệm
MạngTestnetMã tiền tệ khả dụng
EthereumEthereum Sepoliaeth usdc
BNB Smart ChainBNB Smart Chain Testnetbnbbsc usdtbsc
PolygonPolygon Amoymaticmainnet usdcmatic
Avalanche C-ChainAvalanche Fujiavax usdcavax
ArbitrumArbitrum Sepoliaetharb usdcarb
BaseBase Sepoliaethbase usdcbase
OptimismOP Sepoliaethop usdcop
TRONTRON Niletrx usdttrc20
SolanaSolana Devnetsol usdcsol
BitcoinBitcoin Testnet4btc

Tính lũy đẳng và thử lại

Mọi yêu cầu POST tạo tài nguyên đều có thể kèm header Idempotency-Key. Khi gặp lỗi hết thời gian chờ do mạng, hãy gửi lại với cùng một khóa; khoản thanh toán hoặc chi trả sẽ không bị tạo trùng.

  • Cùng khóa, cùng nội dung: trả về kết quả của lần đầu tiên
  • Cùng khóa, khác nội dung: phản hồi 422 IDEMPOTENCY_KEY_REUSED
  • Yêu cầu đầu tiên vẫn đang được xử lý: phản hồi 409 IDEMPOTENCY_IN_FLIGHT, vui lòng thử lại sau
HTTPHTTP
POST /api/v1/payout HTTP/1.1
Host: omniwallet.ewin888.com
x-api-key: YOUR_API_KEY
Authorization: Bearer YOUR_JWT
Idempotency-Key: 6c0a8e6e-3f5b-4f7a-9a52-1f0c2d9b7e41
Content-Type: application/json

Bắt đầu nhận thanh toán bằng tiền mã hóa

Đăng ký miễn phí và hoàn tất tích hợp trong môi trường thử nghiệm; sau khi doanh nghiệp được xác minh, bạn có thể chuyển sang môi trường chính thức.