- Trang chủ
- 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ý.
https://omniwallet.ewin888.com/api/v1/https://omniwallet-dev.ewin888.com/api/v1/Bắt đầu nhanh
- 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.
- 02
Tạo khoản thanh toán
Gọi
POST /v1/paymentvớ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_addresslà địa chỉ riêng của khoản thanh toán này, cònpay_amountlà số tiền cần thanh toán.POST /v1/paymentcurlcurl -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" } - 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 đếninvoice_urltrong phản hồi.POST /v1/invoicecurlcurl -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" } - 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
Xác minh IPNipn_callback_urlcủa bạn. Hãy xác minh chữ ký trước, sau đó cập nhật đơn hàng theopayment_status. - 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_idvà trạng thái, khi cần thì gọiGET /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
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);<?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);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{
"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 |
|---|---|
waitingChờ 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_paidThanh 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 |
finishedHoàn tất | Thanh toán hoàn tất |
failedThấ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.
- Đổi URL cơ sởThay
https://api.nowpayments.io/v1/bằng URL của OmniWallet bên dưới. - Dùng khóa API của OmniWalletTên header vẫn là
x-api-key. - 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íchx-nowpayments-sigtrong trang quản trị. - 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ằngGET /v1/merchant/coinshoặc trang tiền mã hóa được hỗ trợ. - 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.
- 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ạng | Testnet | Mã tiền tệ khả dụng |
|---|---|---|
| Ethereum | Ethereum Sepolia | eth usdc |
| BNB Smart Chain | BNB Smart Chain Testnet | bnbbsc usdtbsc |
| Polygon | Polygon Amoy | maticmainnet usdcmatic |
| Avalanche C-Chain | Avalanche Fuji | avax usdcavax |
| Arbitrum | Arbitrum Sepolia | etharb usdcarb |
| Base | Base Sepolia | ethbase usdcbase |
| Optimism | OP Sepolia | ethop usdcop |
| TRON | TRON Nile | trx usdttrc20 |
| Solana | Solana Devnet | sol usdcsol |
| Bitcoin | Bitcoin Testnet4 | btc |
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
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/jsonBắ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.