1. หน้าแรก
  2. นักพัฒนา
นักพัฒนา

เชื่อมต่อการรับชำระเงินด้วยคริปโตได้ในไม่กี่นาที

REST API ที่เข้ากันได้กับ NOWPayments v1: ใช้เอนด์พอยต์ ฟิลด์ ค่าสถานะ และรหัสสกุลเงินเดียวกัน ยืนยันตัวตนด้วย x-api-key และรับการอัปเดตสถานะผ่าน IPN ที่มีลายเซ็นกำกับ

URL หลักของ APIhttps://omniwallet.ewin888.com/api/v1/
สภาพแวดล้อมทดสอบhttps://omniwallet-dev.ewin888.com/api/v1/

เริ่มต้นอย่างรวดเร็ว

  1. 01

    รับคีย์ API

    สมัครและเข้าสู่ระบบหลังบ้าน สร้างคีย์ที่เมนู “นักพัฒนา → คีย์ API” จากนั้นตั้งค่ารหัสลับ IPN ที่เมนู “IPN” เราแนะนำให้เชื่อมต่อระบบในสภาพแวดล้อมทดสอบก่อน

  2. 02

    สร้างรายการชำระเงิน

    เรียก POST /v1/payment พร้อมระบุยอดเงิน สกุลเงินที่ใช้ตั้งราคา และเหรียญที่ต้องการรับ ในข้อมูลที่ตอบกลับ pay_address คือที่อยู่เฉพาะของรายการนี้ และ pay_amount คือยอดที่ต้องชำระ

    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"
      }'
    การตอบกลับJSON
    {
      "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

    พาลูกค้าไปชำระเงิน

    แสดงที่อยู่และยอดเงิน (หรือ QR) ให้ลูกค้า หรือจะใช้ POST /v1/invoice สร้างหน้าใบแจ้งหนี้สำเร็จรูป แล้วพาลูกค้าไปยัง invoice_url ที่ได้จากการตอบกลับก็ได้

    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"
      }'
    การตอบกลับJSON
    {
      "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

    รับ IPN

    ทุกครั้งที่สถานะการชำระเงินเปลี่ยน เราจะส่งคำขอ POST ไปยัง ipn_callback_url ของคุณ โปรดตรวจสอบลายเซ็นก่อน แล้วจึงอัปเดตคำสั่งซื้อตาม payment_status

    ตรวจสอบ IPN
  5. 05

    สลับไปใช้สภาพแวดล้อมจริง

    เมื่อผ่านการยืนยันตัวตนธุรกิจแล้ว ให้สร้างคีย์ API และรหัสลับ IPN ใหม่ในสภาพแวดล้อมจริง แล้วเปลี่ยน URL หลักเป็นของสภาพแวดล้อมจริง

ตรวจสอบลายเซ็น IPN

เราใช้รหัสลับ IPN ของคุณคำนวณ HMAC-SHA512 จาก “JSON ที่เรียงคีย์ตามลำดับตัวอักษร” แล้วใส่ค่าเป็นสตริงเลขฐานสิบหกในเฮดเดอร์ x-omni-sig เนื้อหาคำขอที่เราส่งไปคือ JSON ที่เรียงลำดับแล้วนี้ คุณจึงตรวจสอบกับเนื้อหาดิบที่ได้รับได้โดยตรง

  • เปรียบเทียบลายเซ็นด้วยวิธีที่ใช้เวลาคงที่
  • IPN อาจถูกส่งซ้ำหรือมาถึงไม่ตามลำดับ: ให้ตัดรายการซ้ำโดยใช้ payment_id และสถานะ และเรียก GET /v1/payment/{id} เพื่อดูสถานะล่าสุดเมื่อจำเป็น
  • การตอบกลับด้วยรหัส 2xx ใด ๆ ถือว่าได้รับ IPN แล้ว ส่วนการตอบกลับอื่นหรือกรณีหมดเวลาจะมีการส่งใหม่โดยอัตโนมัติ
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
ตัวอย่างเนื้อหา 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"
}

สถานะการชำระเงิน

ค่าสถานะเหมือนกับ NOWPayments

สถานะความหมาย
waiting
รอชำระเงิน
รอลูกค้าชำระเงิน
confirming
กำลังยืนยัน
ตรวจพบธุรกรรมแล้ว กำลังรอการยืนยันบล็อก
confirmed
ยืนยันแล้ว
ยืนยันยอดเงินเข้าแล้ว
sending
กำลังชำระบัญชี
กำลังโอนเข้าวอลเล็ตของคุณ
partially_paid
ชำระบางส่วน
ชำระไม่ครบ ลูกค้าสามารถชำระส่วนที่ขาดได้ก่อนหมดอายุ
finished
เสร็จสมบูรณ์
ชำระเงินเสร็จสมบูรณ์
failed
ไม่สำเร็จ
ชำระเงินไม่สำเร็จ เช่น ตรงกับรายชื่อผู้ถูกคว่ำบาตร
refunded
คืนเงินแล้ว
คืนเงินให้ผู้ชำระแล้ว
expired
หมดอายุ
ไม่ได้ชำระภายในเวลาที่กำหนด

ย้ายระบบจาก NOWPayments

API เข้ากันได้ โค้ดส่วนใหญ่จึงไม่ต้องแก้ไข

  1. เปลี่ยน URL หลักแทนที่ https://api.nowpayments.io/v1/ ด้วย URL ของ OmniWallet ด้านล่าง
  2. ใช้คีย์ API ของ OmniWalletชื่อเฮดเดอร์ยังคงเป็น x-api-key เหมือนเดิม
  3. อัปเดตการตรวจสอบ IPNเปลี่ยนไปใช้รหัสลับ IPN ของ OmniWallet และเฮดเดอร์ x-omni-sig หากต้องการให้โค้ดเดิมทำงานต่อได้โดยไม่ต้องแก้ไขเลย สามารถเปิดใช้เฮดเดอร์ x-nowpayments-sig เพื่อความเข้ากันได้ในระบบหลังบ้าน
  4. ตรวจสอบเหรียญที่รองรับรหัสสกุลเงินเหมือนเดิม (เช่น usdttrc20, usdcsol) แต่ใช้ได้เฉพาะเหรียญที่เรารองรับเท่านั้น โปรดตรวจสอบด้วย GET /v1/merchant/coins หรือที่หน้า เหรียญที่รองรับ
  5. ตรวจสอบการตั้งค่าการจ่ายเงินออกการจ่ายเงินออกยังคงใช้ JWT อายุ 5 นาทีที่ได้จาก POST /v1/auth เช่นเดิม นอกจากนี้ คีย์ API ที่มีสิทธิ์จ่ายเงินออกต้องตั้งค่าไวท์ลิสต์ IP และต้องเพิ่มที่อยู่ผู้รับเงินลงในไวท์ลิสต์ก่อน
URL หลักของ APIdiff
- https://api.nowpayments.io/v1/
+ https://omniwallet.ewin888.com/api/v1/

สิ่งที่เหมือนเดิม

  • พาธของเอนด์พอยต์และเมธอด HTTP
  • ชื่อฟิลด์ในคำขอและการตอบกลับ
  • ค่าสถานะของการชำระเงินและการจ่ายเงินออก
  • รหัสสกุลเงิน
  • อัลกอริทึมลายเซ็น IPN

ความแตกต่างที่ควรทราบ

  • เฮดเดอร์ลายเซ็น IPN คือ x-omni-sig (เลือกให้ส่ง x-nowpayments-sig มาพร้อมกันได้)
  • ฟิลด์ส่วนขยายของ OmniWallet ขึ้นต้นด้วย omni_
  • ไม่รองรับการจ่ายเงินออกเป็นสกุลเงินเฟียต (ตอบกลับด้วย HTTP 501)
  • การชำระบัญชีจะโอนเข้าวอลเล็ตที่ผูกไว้ในระบบหลังบ้านเสมอ
  • สภาพแวดล้อมทดสอบใช้เทสต์เน็ตจริงของบล็อกเชน

สภาพแวดล้อมทดสอบ (Sandbox)

สภาพแวดล้อมทดสอบเป็นระบบที่ติดตั้งแยกต่างหาก เชื่อมต่อกับเทสต์เน็ตของแต่ละเชน และมี API เหมือนกับสภาพแวดล้อมจริงทุกประการ

  • บัญชี คีย์ API และข้อมูลแยกจากสภาพแวดล้อมจริง จึงต้องสมัครแยกต่างหาก และการยืนยันตัวตนธุรกิจจะได้รับการอนุมัติโดยอัตโนมัติ
  • ชำระเงินด้วยเหรียญทดสอบของแต่ละเทสต์เน็ต และตรวจสอบธุรกรรมได้ในตัวสำรวจบล็อกของเทสต์เน็ตนั้น
  • เหรียญทดสอบไม่มีมูลค่าจริง โปรดอย่าโอนสินทรัพย์บนเมนเน็ตมายังที่อยู่ในสภาพแวดล้อมทดสอบ
เครือข่ายเทสต์เน็ตรหัสสกุลเงินที่ใช้ได้
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

การป้องกันรายการซ้ำและการลองใหม่

คำขอ POST ทุกรายการที่สร้างทรัพยากรสามารถแนบเฮดเดอร์ Idempotency-Key ได้ หากเครือข่ายหมดเวลา ให้ส่งซ้ำด้วยคีย์เดิม ระบบจะไม่สร้างรายการชำระเงินหรือรายการจ่ายเงินออกซ้ำ

  • คีย์เดียวกัน เนื้อหาเดียวกัน: ส่งคืนผลลัพธ์ของคำขอครั้งแรก
  • คีย์เดียวกัน แต่เนื้อหาต่างกัน: ตอบกลับด้วย 422 IDEMPOTENCY_KEY_REUSED
  • คำขอแรกยังประมวลผลอยู่: ตอบกลับด้วย 409 IDEMPOTENCY_IN_FLIGHT โปรดลองใหม่อีกครั้งในภายหลัง
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

เริ่มรับชำระเงินด้วยคริปโต

สมัครฟรี เชื่อมต่อระบบในสภาพแวดล้อมทดสอบให้เรียบร้อยก่อน เมื่อผ่านการยืนยันตัวตนธุรกิจแล้ว ก็สลับไปใช้สภาพแวดล้อมจริงได้