فوری آغاز
کم از کم ادائیگی انٹیگریشن: API کے ذریعے انوائس بنانا اور ادائیگی کی اطلاع کو ہینڈل کرنا۔ آخری سیکشن آرڈر کی تکمیل کے بارے میں ہے۔ مثالیں اپنے آپ میں مکمل ہیں؛ ان میں کوئی SDK استعمال نہیں ہوتا۔
AI ایجنٹ کے ساتھ کام کر رہے ہیں؟ اسے اس صفحے کا markdown ورژن دیں۔ اس میں آپ کی سائٹ یا اسٹور کے لیے انٹیگریشن بنانے کی کافی تفصیل موجود ہے۔
پیشگی ضروریات
| قدر | کہاں سے حاصل کریں |
|---|---|
| API کلید | انٹیگریشنز (Integrations) سیکشن |
| پروجیکٹ ID | پروجیکٹس (Projects) سیکشن |
| Webhook کی خفیہ کلید | پروجیکٹ کی سیٹنگز |
اسی پروجیکٹ کی سیٹنگز میں Webhook URL درج کریں — آپ کے سرور پر اطلاعات کے ہینڈلر کا ایڈریس۔ صرف HTTPS؛ سروس ری ڈائریکٹس کو فالو نہیں کرتی۔
مثالیں ٹیسٹ قدریں استعمال کرتی ہیں — انہیں اپنی قدروں سے بدل دیں۔
انوائس بنانا
POST https://api.bitsby.app/invoices/create، جبکہ API کلید Authorization ہیڈر میں جاتی ہے۔
| پیرامیٹر | لازمی | قدر |
|---|---|---|
projectId | ہاں | پروجیکٹ ID، UUID |
amountFiat | ہاں | انوائس کی رقم |
currencyFiat | ہاں | کرنسی: USD، EUR، RUB |
timeToPay | ہاں | ادائیگی کی مہلت گھنٹوں میں: 0.5، 1، 3، 6، 12 |
description | نہیں | تفصیل، گاہک کو ادائیگی کے صفحے پر نظر آتی ہے |
serviceData | نہیں | سروس ڈیٹا، گاہک کو نظر نہیں آتا۔ ہم آرڈر نمبر بھیجنے کی تجویز دیتے ہیں: یہ ادائیگی کی اطلاع میں واپس آتا ہے |
- cURL
- PHP
- TypeScript
- JavaScript
- Python
curl -X POST https://api.bitsby.app/invoices/create \
-H "Authorization: Token MSvL2ltaDZdWVjmZURURMVWhqSJLT2NURjhL2Fla1Z1T1IxQTltKs1T3Ay" \
-F "projectId=9deea1e2-0c08-41a3-bdc2-a34eada3892d" \
-F "amountFiat=49.90" \
-F "currencyFiat=USD" \
-F "timeToPay=1" \
-F "description=Order 4172" \
-F "serviceData=order-4172"
<?php
$apiKey = 'MSvL2ltaDZdWVjmZURURMVWhqSJLT2NURjhL2Fla1Z1T1IxQTltKs1T3Ay';
$projectId = '9deea1e2-0c08-41a3-bdc2-a34eada3892d';
$ch = curl_init('https://api.bitsby.app/invoices/create');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ['Authorization: Token '.$apiKey],
CURLOPT_POSTFIELDS => http_build_query([
'projectId' => $projectId,
'amountFiat' => 49.90,
'currencyFiat' => 'USD',
'timeToPay' => 1,
'description' => 'Order 4172',
'serviceData' => 'order-4172', // your order id
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($response['result'] !== 'success') {
exit('API error: '.$response['data']);
}
$invoice = $response['data'];
// $invoice['id'] — invoice id, store it with the order
// $invoice['url'] — payment page for the customer
const API_KEY = 'MSvL2ltaDZdWVjmZURURMVWhqSJLT2NURjhL2Fla1Z1T1IxQTltKs1T3Ay';
const PROJECT_ID = '9deea1e2-0c08-41a3-bdc2-a34eada3892d';
interface Invoice {
id: string;
uid: string;
url: string;
timeToPayDatetime: string;
}
const response = await fetch('https://api.bitsby.app/invoices/create', {
method: 'POST',
headers: { Authorization: `Token ${API_KEY}` },
body: new URLSearchParams({
projectId: PROJECT_ID,
amountFiat: '49.90',
currencyFiat: 'USD',
timeToPay: '1',
description: 'Order 4172',
serviceData: 'order-4172', // your order id
}),
signal: AbortSignal.timeout(10_000),
});
const result: { result: string; data: Invoice | string } = await response.json();
if (result.result !== 'success') {
throw new Error(`API error: ${result.data}`);
}
const invoice = result.data as Invoice;
// invoice.id — invoice id, store it with the order
// invoice.url — payment page for the customer
const API_KEY = 'MSvL2ltaDZdWVjmZURURMVWhqSJLT2NURjhL2Fla1Z1T1IxQTltKs1T3Ay';
const PROJECT_ID = '9deea1e2-0c08-41a3-bdc2-a34eada3892d';
const response = await fetch('https://api.bitsby.app/invoices/create', {
method: 'POST',
headers: { Authorization: `Token ${API_KEY}` },
body: new URLSearchParams({
projectId: PROJECT_ID,
amountFiat: '49.90',
currencyFiat: 'USD',
timeToPay: '1',
description: 'Order 4172',
serviceData: 'order-4172', // your order id
}),
signal: AbortSignal.timeout(10_000),
});
const result = await response.json();
if (result.result !== 'success') {
throw new Error(`API error: ${result.data}`);
}
const invoice = result.data;
// invoice.id — invoice id, store it with the order
// invoice.url — payment page for the customer
import requests
API_KEY = 'MSvL2ltaDZdWVjmZURURMVWhqSJLT2NURjhL2Fla1Z1T1IxQTltKs1T3Ay'
PROJECT_ID = '9deea1e2-0c08-41a3-bdc2-a34eada3892d'
response = requests.post(
'https://api.bitsby.app/invoices/create',
headers={'Authorization': f'Token {API_KEY}'},
data={
'projectId': PROJECT_ID,
'amountFiat': '49.90',
'currencyFiat': 'USD',
'timeToPay': '1',
'description': 'Order 4172',
'serviceData': 'order-4172', # your order id
},
timeout=10,
)
result = response.json()
if result['result'] != 'success':
raise RuntimeError(f"API error: {result['data']}")
invoice = result['data']
# invoice['id'] — invoice id, store it with the order
# invoice['url'] — payment page for the customer
جواب:
{
"result": "success",
"data": {
"id": "ade9550d-3dc7-4fd3-b94e-3b4c12aaaa0c",
"uid": "MXNj4m8HhcM4",
"createDatetime": "2026-09-14 10:12:03",
"timeToPayDatetime": "2026-09-14 11:12:03",
"commissionFiatUSD": 0.5,
"amountFiatUSD": 49.9,
"url": "https://dash.bitsby.app/invoices/pay/MXNj4m8HhcM4"
}
}
data.id کو آرڈر کے ساتھ محفوظ کریں اور گاہک کو data.url پر بھیجیں — ادائیگی کا صفحہ۔ لنک کسی بھی طریقے سے پہنچائیں: ری ڈائریکٹ، ای میل، بوٹ کا پیغام۔ انوائس timeToPayDatetime (UTC) تک درست رہتی ہے۔
اطلاع کو ہینڈل کرنا
جب انوائس کا اسٹیٹس ادا شدہ (Paid) ہو جاتا ہے، تو سروس پروجیکٹ کے Webhook URL پر POST درخواست بھیجتی ہے۔ باڈی JSON میں ہوتی ہے؛ دستخط ہیڈرز میں ہوتا ہے:
| ہیڈر | قدر |
|---|---|
X-Timestamp | بھیجنے کا وقت، سیکنڈز میں unix time |
X-Signature | sha256= + اسٹرنگ <timestamp>.<request body> کا hex HMAC-SHA256 |
دستخط کی کلید Webhook کی خفیہ کلید ہے۔ دستخط کا حساب درخواست کی خام باڈی پر ہوتا ہے، اس لیے JSON پارس کرنے سے پہلے اسے جانچیں۔
- PHP
- TypeScript
- JavaScript
- Python
<?php
$secret = 'k7QwR2mZ9tXbN4vL8sJpH3dF6yA1cE0u';
$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
// Reject replayed requests: allow up to 5 minutes of clock drift
if (abs(time() - (int)$timestamp) > 300) {
http_response_code(400);
exit;
}
$expected = 'sha256='.hash_hmac('sha256', $timestamp.'.'.$body, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(403);
exit;
}
$invoice = json_decode($body, true)['invoice'];
if ($invoice['status'] === 'paid') {
// $invoice['serviceData'] — the order id passed at creation: 'order-4172'
// $invoice['amountFiat'] — the original invoice amount: 49.9
// Issue the order here, see the next section
}
http_response_code(200);
import { createHmac, timingSafeEqual } from 'node:crypto';
import express, { type Request, type Response } from 'express';
const SECRET = 'k7QwR2mZ9tXbN4vL8sJpH3dF6yA1cE0u';
const app = express();
// express.raw: the signature is computed over the raw request body
app.post('/webhook', express.raw({ type: 'application/json' }), (req: Request, res: Response) => {
const timestamp = req.get('X-Timestamp') ?? '';
const signature = req.get('X-Signature') ?? '';
const body = (req.body as Buffer).toString('utf8');
// Reject replayed requests: allow up to 5 minutes of clock drift
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.sendStatus(400);
}
const expected = 'sha256=' + createHmac('sha256', SECRET)
.update(`${timestamp}.${body}`, 'utf8')
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(signature);
if (a.length !== b.length || !timingSafeEqual(a, b)) {
return res.sendStatus(403);
}
const { invoice } = JSON.parse(body);
if (invoice.status === 'paid') {
// invoice.serviceData — the order id passed at creation: 'order-4172'
// invoice.amountFiat — the original invoice amount: 49.9
// Issue the order here, see the next section
}
res.sendStatus(200);
});
app.listen(8080);
import { createHmac, timingSafeEqual } from 'node:crypto';
import express from 'express';
const SECRET = 'k7QwR2mZ9tXbN4vL8sJpH3dF6yA1cE0u';
const app = express();
// express.raw: the signature is computed over the raw request body
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const timestamp = req.get('X-Timestamp') ?? '';
const signature = req.get('X-Signature') ?? '';
const body = req.body.toString('utf8');
// Reject replayed requests: allow up to 5 minutes of clock drift
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.sendStatus(400);
}
const expected = 'sha256=' + createHmac('sha256', SECRET)
.update(`${timestamp}.${body}`, 'utf8')
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(signature);
if (a.length !== b.length || !timingSafeEqual(a, b)) {
return res.sendStatus(403);
}
const { invoice } = JSON.parse(body);
if (invoice.status === 'paid') {
// invoice.serviceData — the order id passed at creation: 'order-4172'
// invoice.amountFiat — the original invoice amount: 49.9
// Issue the order here, see the next section
}
res.sendStatus(200);
});
app.listen(8080);
import hashlib
import hmac
import time
from flask import Flask, request
SECRET = 'k7QwR2mZ9tXbN4vL8sJpH3dF6yA1cE0u'
app = Flask(__name__)
@app.post('/webhook')
def webhook():
timestamp = request.headers.get('X-Timestamp', '')
signature = request.headers.get('X-Signature', '')
# The signature is computed over the raw request body
body = request.get_data(as_text=True)
# Reject replayed requests: allow up to 5 minutes of clock drift
if abs(time.time() - int(timestamp or 0)) > 300:
return '', 400
expected = 'sha256=' + hmac.new(
SECRET.encode(),
f'{timestamp}.{body}'.encode(),
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, signature):
return '', 403
invoice = request.get_json()['invoice']
if invoice['status'] == 'paid':
# invoice['serviceData'] — the order id passed at creation: 'order-4172'
# invoice['amountFiat'] — the original invoice amount: 49.9
# Issue the order here, see the next section
pass
return '', 200
10 سیکنڈ کے اندر 2xx کوڈ کے ساتھ جواب دیں۔ کوئی اور کوڈ، ری ڈائریکٹ یا ٹائم آؤٹ ناکام ڈیلیوری شمار ہوتا ہے: سروس 5 منٹ سے 24 گھنٹے تک بڑھتے ہوئے وقفوں سے دوبارہ کوشش کرتی ہے، پھر رک جاتی ہے۔ طویل پروسیسنگ کو قطار میں منتقل کریں: پہلے 200 کے ساتھ جواب دیں، پھر آرڈر پر کام کریں۔
اطلاع کا مکمل فارمیٹ اور فیلڈز کی تفصیل Webhook URL سیکشن میں ہے۔
آرڈر کی تکمیل
paid اسٹیٹس والی جانچ شدہ اطلاع ادائیگی کی تصدیق کرتی ہے۔ تکمیل کے مراحل:
- آرڈر تلاش کریں
invoice.serviceDataکے ذریعے — وہ قدر جو آپ نے انوائس بناتے وقت بھیجی تھی (order-4172)۔ invoice.idکے ذریعے جانچیں کہ آیا اس انوائس کا آرڈر پہلے ہی مکمل ہو چکا ہے۔ ایک ہیinvoice.idوالی اطلاع ایک سے زیادہ بار آ سکتی ہے — آرڈر صرف ایک بار مکمل کریں اور پروسیس ہو جانے کا نشان محفوظ کریں۔- رقم اور کرنسی جانچیں
invoice.amountFiatاورinvoice.currencyFiatسے ملا کر — یہ انوائس کی اصل قدریں ہیں اور کبھی نہیں بدلتیں۔ سروسamountFiatUSDکو اصل میں موصول ہونے والی رقم سے بدل دیتی ہے۔ رقموں کا موازنہ نمبرز کے طور پر کریں، اسٹرنگز کے طور پر نہیں: آخر کے صفر ختم ہو جاتے ہیں، اس لیے49.90بطور49.9آتا ہے۔ اگر قدریں آرڈر سے مطابقت نہ رکھیں، تو تکمیل کے بجائے انوائس کو دستی جائزے کے لیے بھیجیں — ایسے معاملات کی تفصیل ادائیگیوں کو منسلک کرنا اور رقم کا فرق میں ہے۔ - آرڈر مکمل کریں اور اسے پروسیس شدہ کے طور پر نشان زد کریں۔
تکمیل کے وقت ادائیگی کی مہلت نہ جانچیں: ادائیگی کی آن چین تصدیق timeToPayDatetime کے بعد ہو سکتی ہے، اور تاجر ادائیگی کو دستی طور پر انوائس سے منسلک کر سکتا ہے۔ اطلاع بذات خود ادائیگی کی تصدیق کرتی ہے۔
آگے کیا ہے
- API ریفرنس — انوائسز کی فہرستیں، منسوخی، اعداد و شمار، بیلنس
- Webhook کے دستخط کی جانچ — دستخط کا طریقہ کار تفصیل سے
- ادائیگیوں کو منسلک کرنا اور رقم کا فرق — کم ادائیگی، زائد ادائیگی، غیر منسلک ادائیگیاں
- HTML فارمز — API کے بغیر ادائیگیاں وصول کرنا