مستندات
با SMetaGateway بسازید.
هر آنچه برای ساخت فاکتور USDT TRC20 از سرور خود، هدایت خریداران به صفحه پرداخت و تأیید پرداختها با وبهوک امضاشده نیاز دارید.
نمای کلی
SMetaGateway یک لایه صدور فاکتور غیرامانی برای USDT روی شبکه ترون است. فروشندگان یک آدرس دریافت عمومی ثبت میکنند و خریداران مستقیماً به آن پرداخت میکنند. درگاه برای هر فاکتور یک مبلغ دقیق و یکتا تعیین میکند، وضعیت آن را پیگیری میکند، دادههای حسابداری را ثبت میکند و به سرور شما اطلاع میدهد.
همه اندپوینتها زیر مسیر /api/v1 روی همین دامنه قرار دارند. مبالغ همیشه رشتههای اعشاری با حداکثر شش رقم اعشار هستند — هرگز عدد اعشاری شناور (float) نیستند.
- سرور شما → SMetaGateway1POST /api/v1/invoices همراه با Idempotency-Key
- SMetaGateway → سرور شما2فاکتور با payable_amount و checkout_url
- سرور شما → خریدار3هدایت خریدار به checkout_url
- خریدار → SMetaGateway4خریدار صفحه پرداخت را باز کرده و کد QR را اسکن میکند
- خریدار → کیف پول ترون شما5خریدار مبلغ دقیق USDT را به آدرس شما میفرستد
- SMetaGateway6درگاه مبلغ دقیق را روی بلاکچین پیدا و فاکتور را تأیید میکند
- SMetaGateway → سرور شما7وبهوک امضاشده invoice.confirmed
- سرور شما → SMetaGateway8GET /api/v1/invoices/{id} برای اطمینان، سپس تحویل سفارش
مسیر دادهمسیر پول
شروع سریع
1. یک فضای کاری بسازید و یک آدرس دریافت ترون اضافه کنید. شناسه کیف پول را کپی کنید.
2. بخش توسعهدهندگان ← کلیدهای API را باز کنید و یک کلید با تاریخ انقضا بسازید. رمز با smg_ شروع میشود و فقط یک بار نمایش داده میشود؛ آن را در جای امن نگه دارید.
۳. با درخواست زیر از سرور خود یک فاکتور بسازید. شناسه فاکتور و مقدار دقیق payable_amount را ذخیره کنید.
۴. خریدار را به checkout_url هدایت کنید. سفارش را فقط پس از اعتبارسنجی وبهوک invoice.confirmed و استعلام فاکتور از سرور، پرداختشده بدانید.
curl -X POST "https://smg.sabco24.com/api/v1/invoices" \
-H "Authorization: Bearer $SMETA_API_KEY" \
-H "Idempotency-Key: order-1001" \
-H "Content-Type: application/json" \
-d '{"merchant_order_id":"1001","amount":"49.95","wallet_id":"WALLET_ID","description":"Example order","expires_in_minutes":20}'احراز هویت
یکپارچهسازیهای سمت سرور با کلید API از نوع bearer احراز هویت میشوند: Authorization: Bearer smg_…. کلیدها دامنههای invoices:read، invoices:write و ledger:read را دارند و میتوانند پس از ۳۰، ۹۰ یا ۳۶۵ روز منقضی شوند. کلید منقضیشده خطای 401 api_key_expired برمیگرداند؛ برای گرفتن رمز جدید آن را در داشبورد تعویض کنید. کلیدها را روی سرور نگه دارید و هرگز در مرورگر یا اپلیکیشن موبایل قرار ندهید.
داشبورد از یک کوکی نشست HttpOnly استفاده میکند. مدیریت حساب، ثبت کیف پول، کلیدهای API و وبهوکها به این نشست مالک نیاز دارند و با کلید API قابل انجام نیستند.
curl "https://smg.sabco24.com/api/v1/invoices/INVOICE_ID" \
-H "Authorization: Bearer $SMETA_API_KEY"مبالغ و شناسایی
قیمت پایه را بهصورت رشته اعشاری مانند "49.95" بفرستید. درگاه یک تعدیل شناسایی مثبت اضافه میکند — از 0.000001 تا 0.009999 USDT برای کمتر از ۱۰۰ USDT، یا از 0.000001 تا 0.999999 USDT برای ۱۰۰ USDT و بیشتر — و base_amount، adjustment و payable_amount را جداگانه برمیگرداند.
مبلغ نهایی دقیق به مدت ۹۰ روز برای همان شبکه، توکن و آدرس دریافت در میان همه فروشندگان رزرو میشود. مبالغ استفادهنشده در اولویتاند؛ مبلغ تکراری فاکتور را بهجای تأیید خودکار به وضعیت review میبرد.
به مدت ۹۰ روز برای هر شبکه، توکن و آدرس دریافت رزرو میشود
{
"base_amount": "49.950000",
"adjustment": "0.003821",
"payable_amount": "49.953821"
}فاکتورها و تکرارناپذیری
درخواست POST /api/v1/invoices به هدر Idempotency-Key نیاز دارد. تکرار همان درخواست با همان کلید، فاکتور اصلی را با idempotent_replay: true برمیگرداند؛ استفاده مجدد از کلید با داده متفاوت خطای 409 idempotency_conflict میدهد.
هر merchant_order_id فقط یک فاکتور دارد. شناسه فاکتور و payable_amount را همراه سفارش خود ذخیره کنید و هنگام رسیدن وبهوک مقایسه کنید.
POST /invoices + Idempotency-Key- کلید جدید201 — فاکتور جدید ساخته شد
- همان کلید، همان بدنهفاکتور اصلی، idempotent_replay: true
- همان کلید، بدنه متفاوت409 idempotency_conflict
{
"invoice": {
"id": "6f1c…",
"merchant_order_id": "1001",
"base_amount": "49.950000",
"adjustment": "0.003821",
"payable_amount": "49.953821",
"status": "pending",
"mode": "live",
"checkout_url": "https://smg.sabco24.com/checkout/…",
"expires_at": "2026-10-21T12:20:00.000Z",
"reserved_until": "2027-01-19T12:00:00.000Z"
},
"idempotent_replay": false
}صفحه پرداخت و وضعیت فاکتور
checkout_url یک لینک دسترسی است: هر کس آن را داشته باشد جزئیات ایمن پرداخت را میبیند، پس آن را محرمانه نگه دارید. صفحه پرداخت نام فروشنده، جزئیات مبلغ، آدرس دریافت، کد QR و زمان انقضا را نشان میدهد، بدون متادیتا یا شناسههای داخلی شما.
وضعیت فاکتور یکی از pending، confirmed، expired یا review است. صفحه پرداخت پس از expires_in_minutes (پیشفرض ۲۰، حداکثر ۱۴۴۰) منقضی میشود؛ رزرو مبلغ بهطور مستقل ۹۰ روز ادامه دارد.
pending- مبلغ دقیق دریافت شد
confirmed - زمان پرداخت تمام شد
expired - مبلغ تکراری یا نیازمند بررسی دستی
review
وبهوکهای امضاشده
یک اندپوینت HTTPS عمومی (پورت ۴۴۳) را از داشبورد ثبت کنید. رمز امضا فقط یک بار نمایش داده میشود. رویدادها: invoice.created، invoice.confirmed، invoice.expired، invoice.review و webhook.test. ارسال تا هشت بار تکرار میشود و بهصورت دستی نیز قابل تکرار است.
هر درخواست هدرهای X-SMeta-Event-Id، X-SMeta-Timestamp و X-SMeta-Signature را دارد. HMAC-SHA256 را روی timestamp + "." + بدنه خام محاسبه کنید، در زمان ثابت مقایسه کنید، مهرهای زمانی قدیمیتر از پنج دقیقه را رد کنید و سپس JSON را پردازش کنید. هر شناسه رویداد را فقط یک بار پردازش کنید.
- 1خواندن بدنه خام و هدرهای X-SMeta-*
- 2مهر زمانی کمتر از ۵ دقیقه است؟رد (4xx)
- 3HMAC-SHA256(timestamp + "." + body)
- 4مقایسه در زمان ثابت با X-SMeta-Signatureرد (4xx)
- 5این شناسه رویداد قبلاً پردازش شده؟پاسخ 2xx، رد شدن
- 6بهروزرسانی سفارش و پاسخ 2xx
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(rawBody: Buffer, headers: Record<string, string>, secret: string) {
const timestamp = headers['x-smeta-timestamp'];
const signature = headers['x-smeta-signature'] ?? '';
if (!/^\d+$/.test(timestamp) || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return null;
const expected = 'sha256=' + createHmac('sha256', secret)
.update(timestamp + '.').update(rawBody).digest('hex');
const a = Buffer.from(expected), b = Buffer.from(signature);
if (a.length !== b.length || !timingSafeEqual(a, b)) return null;
const event = JSON.parse(rawBody.toString('utf8'));
return event.id === headers['x-smeta-event-id'] ? event : null;
}خطاها و محدودیت نرخ
خطاها یک بدنه JSON با error.code و error.message برمیگردانند. وضعیتهای رایج: 400 اعتبارسنجی، 401 احراز هویت، 403 دسترسی یا مبدأ، 404 یافت نشد، 409 تعارض یا بازبینی، 429 محدودیت نرخ.
ساخت فاکتور به ۱۲۰ درخواست در دقیقه برای هر فروشنده محدود است. پاسخهای 429 و 5xx را با تأخیر افزایشی و همان Idempotency-Key دوباره امتحان کنید.
{
"error": {
"code": "idempotency_conflict",
"message": "This idempotency key was used with different invoice details."
},
"mode": "live"
}یکپارچهسازیها
داشبورد شامل ۳۲ دستورالعمل آماده برای Node.js، NestJS، PHP، Laravel، Python، Django، Go، Java، C#، Ruby، React، Next.js، Vue و پلتفرمهای فروشگاهی مانند WooCommerce، Magento و Shopware است. افزونه قابل دانلود ووکامرس نسخه پیشنمایش است و هنوز کلیدهای API عملیاتی را نمیپذیرد.
این دستورالعملها نمونه هستند، نه SDK منتشرشده. نمونههای فرانتاند سرور خود شما را که کلید API را نگه میدارد فراخوانی میکنند.
تأیید پرداخت
درگاه از طریق TronGrid شبکه اصلی ترون را برای انتقالهای تأییدشده USDT TRC20 به هر آدرس دریافتی که فاکتور باز دارد میخواند و هر انتقال را با رسید نهاییشده و موفق دوباره بررسی میکند. انتقال مبلغ دقیق payable_amount بین زمان ساخت و انقضای فاکتور، آن را تأیید میکند و هش تراکنش در tx_hash ذخیره میشود.
انتقالی که پس از انقضا برسد، با مبلغی که قبلاً استفاده شده یکی باشد، یا به فاکتوری در حال بررسی مربوط باشد، وضعیت را به review تغییر میدهد و هرگز خودکار تأیید نمیشود. شناسایی معمولاً چند دقیقه طول میکشد. کمیسیون صفر و ساختار غیرامانی بهتنهایی معافیت مالیاتی یا مجوز قانونی ایجاد نمیکنند.