# فوری آغاز

کم از کم ادائیگی انٹیگریشن: API کے ذریعے انوائس بنانا اور ادائیگی کی اطلاع کو ہینڈل کرنا۔ آخری سیکشن آرڈر کی تکمیل کے بارے میں ہے۔ مثالیں اپنے آپ میں مکمل ہیں؛ ان میں کوئی SDK استعمال نہیں ہوتا۔

:::tip
**AI ایجنٹ کے ساتھ کام کر رہے ہیں؟** اسے [اس صفحے کا markdown ورژن](/ur/quick-start.md) دیں۔ اس میں آپ کی سائٹ یا اسٹور کے لیے انٹیگریشن بنانے کی کافی تفصیل موجود ہے۔
:::

## پیشگی ضروریات

| قدر | کہاں سے حاصل کریں |
| --- | --- |
| API کلید | [انٹیگریشنز (Integrations)](https://dash.bitsby.app/integrations/list) سیکشن |
| پروجیکٹ ID | [پروجیکٹس (Projects)](https://dash.bitsby.app/projects/list) سیکشن |
| 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**

```bash showLineNumbers
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**

```php showLineNumbers
<?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
```

**TypeScript**

```typescript showLineNumbers
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
```

**JavaScript**

```js showLineNumbers
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
```

**Python**

```python showLineNumbers
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
```

جواب:

```json
{
  "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**

```php showLineNumbers
<?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);
```

**TypeScript**

```typescript showLineNumbers
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);
```

**JavaScript**

```js showLineNumbers
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);
```

**Python**

```python showLineNumbers
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](./webhook-url/index.md) سیکشن میں ہے۔

## آرڈر کی تکمیل

`paid` اسٹیٹس والی جانچ شدہ اطلاع ادائیگی کی تصدیق کرتی ہے۔ تکمیل کے مراحل:

1. **آرڈر تلاش کریں** `invoice.serviceData` کے ذریعے — وہ قدر جو آپ نے انوائس بناتے وقت بھیجی تھی (`order-4172`)۔
2. **`invoice.id` کے ذریعے جانچیں کہ آیا اس انوائس کا آرڈر پہلے ہی مکمل ہو چکا ہے۔** ایک ہی `invoice.id` والی اطلاع ایک سے زیادہ بار آ سکتی ہے — آرڈر صرف ایک بار مکمل کریں اور پروسیس ہو جانے کا نشان محفوظ کریں۔
3. **رقم اور کرنسی جانچیں** `invoice.amountFiat` اور `invoice.currencyFiat` سے ملا کر — یہ انوائس کی اصل قدریں ہیں اور کبھی نہیں بدلتیں۔ سروس `amountFiatUSD` کو اصل میں موصول ہونے والی رقم سے بدل دیتی ہے۔ رقموں کا موازنہ نمبرز کے طور پر کریں، اسٹرنگز کے طور پر نہیں: آخر کے صفر ختم ہو جاتے ہیں، اس لیے `49.90` بطور `49.9` آتا ہے۔ اگر قدریں آرڈر سے مطابقت نہ رکھیں، تو تکمیل کے بجائے انوائس کو دستی جائزے کے لیے بھیجیں — ایسے معاملات کی تفصیل [ادائیگیوں کو منسلک کرنا اور رقم کا فرق](./payment-matching.md) میں ہے۔
4. **آرڈر مکمل کریں اور اسے پروسیس شدہ کے طور پر نشان زد کریں۔**

تکمیل کے وقت ادائیگی کی مہلت نہ جانچیں: ادائیگی کی آن چین تصدیق `timeToPayDatetime` کے بعد ہو سکتی ہے، اور تاجر ادائیگی کو دستی طور پر انوائس سے منسلک کر سکتا ہے۔ اطلاع بذات خود ادائیگی کی تصدیق کرتی ہے۔

## آگے کیا ہے

- [API ریفرنس](./api/index.md) — انوائسز کی فہرستیں، منسوخی، اعداد و شمار، بیلنس
- [Webhook کے دستخط کی جانچ](./webhook-url/signature-verification.md) — دستخط کا طریقہ کار تفصیل سے
- [ادائیگیوں کو منسلک کرنا اور رقم کا فرق](./payment-matching.md) — کم ادائیگی، زائد ادائیگی، غیر منسلک ادائیگیاں
- [HTML فارمز](./creating-invoices/html-forms/index.md) — API کے بغیر ادائیگیاں وصول کرنا
