باهمتا

پیشوندِ فراخوانیِ سرویس ها نشانی زیر است:

https://api.bahamta.com/v2/

برای نمونه، برای گرفتنِ فهرستِ قبض های یک صندوق، نشانیِ زیر باید به کار رود:

https://api.bahamta.com/v2/:number/funds/:fund_id/bills

که در آن، شماره ی مبایلِ کاربر و شناسه ی صندوق باید جایگزین شوند:

https://api.bahamta.com/v2/989123456789/funds/123/bills

روشِ پیاده سازیِ پیشنهادی

برای گرفتنِ توکنِ دسترسی می توانید به برنامه ی وب به نشانیِ dev.bahamta.com رفته و از قسمت منو، گزینه‌ی تنظیمات را انتخاب کرده و در بخش کلیدهای خارجی توکنِ دسترسی را دریافت کنید. همچنین برای مشخص کردنِ callback گزینه‌ی مسیرهای بازفراخوانی حساب‌های بانکی را انتخاب کنید تا بتوانید برای هر حساب بانکیِ خود، یک مسیر برای callback مشخص کنید.

توکنِ دسترسی باید روی سرورِ شما باشد. از آنجا که هر کس به این توکن دسترسی داشته باشد، می تواند به صندوق ها دسترسی داشته باشد، نباید روی برنامه های سمتِ کلاینت برود. برای نمونه هر زمان نیاز به ساختِ قبض بود، برنامه ی سمتِ کلاینتِ شما می تواند یک درخواست به سرورِ شما بدهد و سپس سرورِ شما، سرویسِ ساختِ قبض را فرا بخواند.

توکنِ دسترسی (access-token)، شناسه ی صندوق (fund_id) و شماره ی مبایل (number) باید در پیکربندیِ سرورِ شما قرار بگیرند.

برای صندوقِ خود یک callback مشخص کنید تا از تغییراتِ صندوقِ خود آگاه شوید. با هر تغییر، یک درخواست به نشانیِ مشخص شده فرستاده می شود.

قبض های ساخته شده، پرداخت شده و لغو شده همگی به callback فرستاده خواهند شد.

از آنجا که ممکن است به دلیل های گوناگون و پیش بینی نشده، گهگاه درخواست به callback نرسد، بهتر است سرویسِ فهرست قبض های صندوق (GET /:number/funds/:fund_id/bills) در بازه های زمانی (برای نمونه هر ۱۰ دقیقه یک بار) فراخوانی شود تا اگر هر تغییری به دستِ callback نرسیده است، بازیابی شود.

برای این کار، می توانید داده های برگشتی از این سرویس را upsert کنید تا اگر نیستند ساخته شوند و اگر هستند بروز رسانی شوند و روی داده های قبلی بنشینند.

سرویس ها

سرویس ها RESTful هستند و همه در بدنه JSON می گیرند و در پاسخ هم JSON بر می گردانند.

بیشترِ سرویس ها سرنویسی (Header) به نامِ access-token می گیرند که با آن دسترسیِ کاربرِ فراخواننده را بررسی می کنند. اگر توکنِ دسترسی در پایگاهِ داده نباشد یا برای شماره ی همراه کاربر ساخته نشده باشد، کدِ 401 بر می گردد.

در فراخوانیِ سرویس ها، number شماره ی همراهِ کاربرِ فراخواننده است. توکنِ دسترسیِ به کار رفته در سرنویس، باید برای این شماره ی همراه باشد وگرنه کدِ خطای 401 بر می گردد.

همچنین fund_id شناسه ی صندوق است که برای هر صندوق یکتا است.

در زمانِ به کار گیریِ این سرویس ها، خطا ها نیز باید کنترل شوند. بسیاری از خطا ها نباید در برنامه رخ دهند. برای نمونه، خطا های کدِ 400 که نشان دهنده ی داده ی نادرست هستند، باید پیش از فراخوانی سرویس بررسی شوند و از فرستادن داده ی نادرست جلوگیری شود؛ هر چند که اگر داده ی نادرستی فرستاده شود، در پیامِ خطا آن فیلدِ داده ای مشخص می شود.

کدِ خطای 401 برای نشان دادنِ نبودِ توکنِ دسترسی یا نادرست بودنِ آن است.

خطا های دیگر در هر سرویس آمده است و دلیل آن نیز مشخص شده است. بنا بر این برنامه می تواند در زمانِ گرفتنِ آن خطا، پیامِ درستی را به کاربر نشان دهد.

اگر خطای 500 باز گردد، نشان دهنده ی پیش آمدنِ خطایی در سرور است که پیش بینی نشده بوده است.

POST /:number/funds/:fund_id/bills

یک یا چند قبض می سازد.

درخواست:

[
  {
    "payer_number": "989001234567",
    "payer_name": "سهراب سپهری",
    "amount": "1500000",
    "note": "عضویتِ ماهانه ی دی ماهِ ۹۳"
  },
  {
    "payer_number": "989002345678",
    "payer_name": "پروین اعتصامی",
    "amount": "1500000",
    "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
    "silent": true
  }
]

در پاسخ کدِ 200 باز می گردد و قبض ها به همراهِ چند فیلدِ دیگر باز می گردند. برای نمایشِ قبض های ساخته شده به کاربر، باید داده های برگشتی را به کار برد:

[
  {
    "fund_id": 20,
    "bill_id": 1,
    "code": "123456",
    "url": "https://bahamta.com/20/1-123456",
    "state": "request",
    "amount": "1500000",
    "created": "2015-03-02T12:57:58.123Z",
    "modified": "2015-03-02T12:57:58.123Z",
    "display": "2015-03-02T12:57:58.123Z",
    "payer_number": "989001234567",
    "payer_name": "سهراب سپهری",
    "fund_name": "صندوقِ آزمایشی",
    "iban": "IR123456789012345678901234",
    "account_owner": "سهراب سپهری",
    "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
    "pay_wage": "0",
    "pay_trace": "",
    "pay_pan": "",
    "transfer_estimate": null,
    "transfer_trace": ""
  },
  {
    "fund_id": 20,
    "bill_id": 2,
    "code": "123456",
    "url": "https://bahamta.com/20/2-123456",
    "state": "request",
    "amount": "1500000",
    "created": "2015-03-02T12:57:58.123Z",
    "modified": "2015-03-02T12:57:58.123Z",
    "display": "2015-03-02T12:57:58.123Z",
    "payer_number": "989002345678",
    "payer_name": "پروین اعتصامی",
    "fund_name": "صندوقِ آزمایشی",
    "iban": "IR123456789012345678901234",
    "account_owner": "سهراب سپهری",
    "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
    "pay_wage": "0",
    "pay_trace": "",
    "pay_pan": "",
    "transfer_estimate": null,
    "transfer_trace": ""
  }
]

پارامترِ payer_number شماره ی همراهِ گیرنده ی قبض است و باید در این قالب باشد:

/^989[0-9]{9}$/

پارامترِ payer_name نامِ گیرنده ی قبض از دیدِ صادر کننده است و می تواند تا ۵۰ کاراکتر باشد.

پارامترِ amount مبلغ به ریال است و باید در این قالب باشد:

/^[1-9][0-9]{0,11}$/

اگر مبلغِ قبضی کمتر از اندازه ی مجاز باشد کدِ خطای 411 باز می گردد.

اگر مبلغِ قبضی بیش از اندازه ی مجاز باشد کدِ خطای 412 باز می گردد.

اگر تاریخِ قبض آینده باشد، در زمان سررسید، یک پیامک برای گیرنده ی قبض فرستاده می شود.

پارامترِ note می تواند تا ۱۰۰ کاراکتر داشته باشد و کاراکتر ها هر چیزی می توانند باشند ولی همه ی کاراکتر های فاصله، new line و ... با یک فاصله جایگزین خواهند شد.

پارامترِ silent اگر true باشد، از فرستادنِ پیامکِ قبض به گیرنده جلوگیری میکند.

اگر پارامتر ها نادرست باشند کدِ خطای 400 بر می گردد.

کاربر باید دسترسیِ owner یا editor داشته باشد وگرنه کدِ خطای 403 می گیرد.

اگر فیلدِ blocked برای همه ی کاربرانِ عضوِ صندوق خالی نباشد خطای 423 می گیرد.

در زمان درخواست، توکنِ دسترسی باید در سرنویسِ access-token فرستاده شود. اگر توکنِ درخواست درست نباشد یا برای این شماره ی همراه نباشد، کدِ خطای 401 بر می گردد.

GET /:number/funds/:fund_id/bills

تغییراتِ قبض های صندوق پس از یک زمانِ مشخص را بر می گرداند. اگر زمانی مشخص نشود، همه ی قبض ها از آغاز تا کنون را بر می گرداند.

پارامترِ درخواست:

since=2015-05-27T03:53:01.123Z

زمانِ فرستاده شده باید در قالبِ ISO 8601 باشد. اگر فرستاده نشود، برابر با epoch یا 1970-01-01T00:00:00+00:00 خواهد بود. برنامه ی فراخواننده، در فراخوانیِ نخست، این پارامتر را نمی فرستد (یا epoch را می فرستد) تا همه ی تغییرات از آغاز تا کنون را بگیرد. پس از آن باید همواره زمانِ آخرین تغییر که در پاسخ برگشته را بفرستد. برنامه ی فراخواننده نباید زمانِ دستگاه را بفرستد چون شاید زمان درست نباشد و مشکلاتِ فراوانی پیش آید. داده های برگشتی همواره بزرگتر از (و نه مساوی با) since خواهند بود.

اگر قالبِ زمانِ فرستاده شده درست نباشد کدِ خطای 400 باز می گردد.

اگر هیچ تغییری در قبض ها نباشد، در پاسخ کدِ 204 باز می گردد.

اگر تغییری در داده ها باشد، در پاسخ کدِ 200 باز می گردد:

{
  "bills": [
    {
      "fund_id": 20,
      "bill_id": 1,
      "code": "123456",
      "url": "https://bahamta.com/20/1-123456",
      "state": "pay",
      "amount": "1500000",
      "created": "2015-03-02T12:57:58.123Z",
      "modified": "2015-03-02T12:57:58.123Z",
      "display": "2015-03-02T12:57:58.123Z",
      "payer_number": "989001234567",
      "payer_name": "سهراب سپهری",
      "fund_name": "صندوقِ آزمایشی",
      "iban": "IR123456789012345678901234",
      "account_owner": "سهراب سپهری",
      "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
      "pay_wage": "5000",
      "pay_trace": "11111",
      "pay_pan": "123456******1234",
      "transfer_estimate": "2015-03-03T05:30:00Z",
      "transfer_trace": "1234567890"
    },
    {
      "fund_id": 20,
      "bill_id": 2,
      "code": "123456",
      "url": "https://bahamta.com/20/2-123456",
      "state": "request",
      "amount": "2000000",
      "created": "2015-03-02T12:57:58.123Z",
      "modified": "2015-03-02T12:57:58.123Z",
      "display": "2015-03-02T12:57:58.123Z",
      "payer_number": "989001234567",
      "payer_name": "سهراب سپهری",
      "fund_name": "صندوقِ آزمایشی",
      "iban": "IR123456789012345678901234",
      "account_owner": "سهراب سپهری",
      "note": "عضویتِ ماهانه ی بهمن ماهِ ۹۳",
      "pay_wage": "0",
      "pay_trace": "",
      "pay_pan": "",
      "transfer_estimate": null,
      "transfer_trace": ""
    },
    {
      "fund_id": 20,
      "bill_id": 3,
      "code": "123456",
      "url": "https://bahamta.com/20/3-123456",
      "state": "reject",
      "amount": "3000000",
      "created": "2015-03-02T12:57:58.123Z",
      "modified": "2015-03-02T12:57:58.123Z",
      "display": "2015-03-02T12:57:58.123Z",
      "payer_number": "989001234567",
      "payer_name": "سهراب سپهری",
      "fund_name": "صندوقِ آزمایشی",
      "iban": "IR123456789012345678901234",
      "account_owner": "سهراب سپهری",
      "note": "عضویتِ ماهانه ی اسفند ماهِ ۹۳",
      "pay_wage": "0",
      "pay_trace": "",
      "pay_pan": "",
      "transfer_estimate": null,
      "transfer_trace": ""
    }
  ],
  "until": "2015-03-02T12:57:58.123Z"
}

فیلدِ until برابر با بزرگترین فیلدِ modified در پاسخ است. برنامه ی فراخواننده باید پس از بروز رسانیِ پایگاهِ داده ی خود، این زمان را نیز ذخیره کند و در درخواست های آتی، این زمان را برای پارامترِ since بفرستد (تا زمانی که یک پاسخِ دیگر باز گردد که فیلدِ until را بروز کند). با این کار برنامه ی فراخواننده دیگر نیازی به گرفتنِ زمان از دستگاهِ کاربر نخواهد داشت.

اگر کاربر دسترسیِ owner یا editor یا viewer داشته باشد، می تواند همه ی قبض های صندوق را ببیند. اگر اینگونه نباشد، کدِ خطای 403 را می گیرد.

در زمان درخواست، توکنِ دسترسی باید در سرنویسِ access-token فرستاده شود. اگر توکنِ درخواست درست نباشد یا برای این شماره ی همراه نباشد، کدِ خطای 401 بر می گردد.

GET /:number/funds/:fund_id/bills/:bill_id

داده های یک قبض را بر می گرداند.

پاسخ (کدِ 200):

{
  "fund_id": 20,
  "bill_id": 1,
  "code": "123456",
  "url": "https://bahamta.com/20/1-123456",
  "state": "pay",
  "amount": "1500000",
  "created": "2015-03-02T12:57:58.123Z",
  "modified": "2015-03-02T12:57:58.123Z",
  "display": "2015-03-02T12:57:58.123Z",
  "payer_number": "989001234567",
  "payer_name": "سهراب سپهری",
  "fund_name": "صندوقِ آزمایشی",
  "iban": "IR123456789012345678901234",
  "account_owner": "سهراب سپهری",
  "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
  "pay_wage": "5000",
  "pay_trace": "11111",
  "pay_pan": "123456******1234",
  "transfer_estimate": "2015-03-03T05:30:00Z",
  "transfer_trace": "1234567890"
}

اگر چنین قبضی پیدا نشود، خطای 404 بر می گردد.

اگر کاربر دسترسیِ owner یا editor یا viewer داشته باشد، می تواند همه ی قبض های صندوق را ببیند. اگر اینگونه نباشد، کدِ خطای 403 را می گیرد.

در زمان درخواست، توکنِ دسترسی باید در سرنویسِ access-token فرستاده شود. اگر توکنِ درخواست درست نباشد یا برای این شماره ی همراه نباشد، کدِ خطای 401 بر می گردد.

DELETE /:number/funds/:fund_id/bills/:bill_id

قبض را لغو می کند.

در پاسخ کدِ 204 بر می گردد.

اگر وضعیتِ قبض request نباشد، کدِ خطای 400 بر می گردد.

کاربر باید دسترسیِ owner یا editor داشته باشد یا اینکه قبض برای او باشد وگرنه کدِ خطای 403 می گیرد.

در زمان درخواست، توکنِ دسترسی باید در سرنویسِ access-token فرستاده شود. اگر توکنِ درخواست درست نباشد یا برای این شماره ی همراه نباشد، کدِ خطای 401 بر می گردد.

نمونه داده های فرستاده شده به مسیرِ بازفراخوانی

در زمانِ ساخت، لغو یا پرداختِ قبض و همچنین ویرایشِ صندوق، داده ها به مسیر های بازفراخوانیِ صندوق فرستاده می شوند. این ویژگی کمک می کند تا برنامه ها بی درنگ از تغییر های مهمِ صندوق آگاه شوند و بتوانند به آن واکنش نشان دهند.

ساختِ قبض

در زمانِ ساختِ قبض یک درخواست به هر یک از مسیر های بازفراخوانی فرستاده می شود. نمونه درخواستِ فرستاده شده:

{
  "bills": [
    {
      "fund_id": 20,
      "bill_id": 1,
      "code": "123456",
      "url": "https://bahamta.com/20/1-123456",
      "state": "request",
      "amount": "1500000",
      "created": "2015-03-02T12:57:58.123Z",
      "modified": "2015-03-02T12:57:58.123Z",
      "display": "2015-03-02T12:57:58.123Z",
      "payer_number": "989001234567",
      "payer_name": "سهراب سپهری",
      "fund_name": "صندوقِ آزمایشی",
      "iban": "IR123456789012345678901234",
      "account_owner": "سهراب سپهری",
      "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
      "pay_wage": "0",
      "pay_trace": "",
      "pay_pan": "",
      "transfer_estimate": null,
      "transfer_trace": ""
    },
    {
      "fund_id": 20,
      "bill_id": 2,
      "code": "123456",
      "url": "https://bahamta.com/20/2-123456",
      "state": "request",
      "amount": "1500000",
      "created": "2015-03-02T12:57:58.123Z",
      "modified": "2015-03-02T12:57:58.123Z",
      "display": "2015-03-02T12:57:58.123Z",
      "payer_number": "989002345678",
      "payer_name": "پروین اعتصامی",
      "fund_name": "صندوقِ آزمایشی",
      "iban": "IR123456789012345678901234",
      "account_owner": "سهراب سپهری",
      "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
      "pay_wage": "0",
      "pay_trace": "",
      "pay_pan": "",
      "transfer_estimate": null,
      "transfer_trace": ""
    }
  ]
}

لغوِ قبض

در زمانِ لغوِ قبض یک درخواست به هر یک از مسیر های بازفراخوانی فرستاده می شود. نمونه درخواستِ فرستاده شده:

{
  "bills": [
    {
      "fund_id": 20,
      "bill_id": 1,
      "code": "123456",
      "url": "https://bahamta.com/20/1-123456",
      "state": "reject",
      "amount": "1500000",
      "created": "2015-03-02T12:57:58.123Z",
      "modified": "2015-04-02T12:57:58.123Z",
      "display": "2015-04-02T12:57:58.123Z",
      "payer_number": "989001234567",
      "payer_name": "سهراب سپهری",
      "fund_name": "صندوقِ آزمایشی",
      "iban": "IR123456789012345678901234",
      "account_owner": "سهراب سپهری",
      "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
      "pay_wage": "0",
      "pay_trace": "",
      "pay_pan": "",
      "transfer_estimate": null,
      "transfer_trace": ""
    }
  ]
}

پرداختِ قبض

در زمانِ پرداختِ قبض یک درخواست به هر یک از مسیر های بازفراخوانی فرستاده می شود. نمونه درخواستِ فرستاده شده:

{
  "bills": [
    {
      "fund_id": 20,
      "bill_id": 2,
      "code": "123456",
      "url": "https://bahamta.com/20/2-123456",
      "state": "pay",
      "amount": "1500000",
      "created": "2015-03-02T12:57:58.123Z",
      "modified": "2015-04-03T12:57:58.123Z",
      "display": "2015-04-03T12:57:58.123Z",
      "payer_number": "989002345678",
      "payer_name": "پروین اعتصامی",
      "fund_name": "صندوقِ آزمایشی",
      "iban": "IR123456789012345678901234",
      "account_owner": "سهراب سپهری",
      "note": "عضویتِ ماهانه ی دی ماهِ ۹۳",
      "pay_wage": "5000",
      "pay_trace": "11111",
      "pay_pan": "123456******1234",
      "transfer_estimate": "2015-04-04T05:30:00Z",
      "transfer_trace": "1234567890"
    }
  ]
}

ویرایشِ صندوق

در زمانِ ویرایشِ صندوق یک درخواست به هر یک از مسیر های بازفراخوانی فرستاده می شود. نمونه درخواستِ فرستاده شده:

{
  "funds": [
    {
      "fund_id": 20,
      "created": "2015-03-02T12:57:58.123Z",
      "modified": "2015-04-03T12:57:58.123Z",
      "type": "generic",
      "fund_name": "صندوقِ آزمایشی",
      "subtitle": "نامِ دوم",
      "iban": "IR123456789012345678901234",
      "account_owner": "سهراب سپهری"
    }
  ]
}

فیلد ها

فیلدِ code در bill

این کد برای جلوگیری از دیده شدنِ قبض ها با حدس زدنِ شناسه ی قبض و شناسه ی صندوق است.

فیلدِ url در bill

نشانیِ قبض است که کاربر با رفتن به آن می تواند قبض را پرداخت کند یا رسیدِ پرداخت را ببیند.

فیلدِ state در bill

وضعیت قبض است و یکی از این ها می تواند باشد: request برای قبض های پرداخت نشده، pay برای قبض های پرداخت شده، و reject برای قبض های لغو شده.

فیلدِ pay_wage در bill

اگر قبض پرداخت شده باشد، کارمزدِ پرداخت را نشان می دهد.

فیلدِ pay_trace در bill

اگر قبض پرداخت شده باشد، کدِ پیگیریِ پرداخت است.

فیلدِ pay_pan در bill

اگر قبض پرداخت شده باشد، شماره کارتِ پرداخت کننده است.

فیلدِ transfer_estimate در bill

اگر قبض پرداخت شده باشد، زمانِ تخمینیِ واریز به حساب را نشان می دهد.

فیلدِ transfer_trace در bill

اگر قبض پرداخت شده باشد و انتقال به حساب هم انجام شده باشد، کدِ پیگیریِ واریز به حساب است.