پوش (push)

ارتباط میان دستگاه‌های سرویس گیرنده با سرورهای پشتیبانی کننده آنها، در اکثر مواقع از سمت سرویس گیرنده آغاز می‌شود. ولیکن در مواقعی نیاز است سرور آغاز کننده ارتباط با دستگاه‌های سرویس گیرنده باشد. این نوع ارتباط به دلیل ارسال داده از سمت سرور به سرویس گیرنده، PUSH نامیده می‌شود. امروزه از این نوع ارتباط به طور معمول به منظور آگاه ساختن یا به روز کردن سرویس گیرنده‌ها نسبت به رویدادی خاص یا ارسال اطلاعات استفاده می‌شود. برای مطالعه بیشتر در این مورد اینجا کلیک کنید.

مکانیزمی که در اکثر پوش سیستم‌ها استفاده می‌شود به این شکل است که ابتدا client ارتباطی پایدار (persistent) را با سرور پوش برقرار کرده و سپس پیام‌های ارسالی از سمت سرور را دریافت می‌کند. همانطور که در بخش واژگان شرح داده شده است به ارتباط اولیه که توسط client برقرار می‌شود subscribe گفته شده و به انتشار پیام که بر روی ارتباط برقرار شده از سمت سرور پوش انجام می‌شود publish گفته می‌شود. در شکل زیر، تفاوت ارتباطات‌ یکبار مصرف که اکثر درخواست‌های وب از این نوع هستند و ارتباطات پایدار را می‌توانید مشاهده کنید.

Persistent connection

همانگونه که در تصویر مشاهده می‌کنید در ارتباطات یکبار مصرف (سمت چپ) پس از ایجاد ارتباط از سمت کلاینت، سرور پاسخ لازم را ارسال کرده و سپس کلاینت به ارتباط ایجاد شده پایان می‌دهد. در صورتی که در سمت دیگر، کلاینت پس از ایجاد ارتباط،‌ به انتطار دریافت پیام‌(های) بعدی از سمت سرور می‌نشیند.


واژگان

پیش از شروع استفاده از بفرست، نیاز است با واژگانی که در فناوری PUSH و بفرست به کار رفته است آشنا شوید. از واژگانی که شرح داده شده، در ادامه به دفعات استفاده خواهد شد. لذا مطالعه دقیق این واژگان به درک چگونگی استفاده از سرویس بفرست کمک خواهد کرد.

subscribe درخواست برقراری ارتباط با درگاه بفرست است که از سمت اپلیکیشن موبایل یا هر نوع رسانه سمت کاربر صورت می‌گیرد. در نتیجه subscribe کردن، ارتباطی میان دستگاه کاربر (موبایل/تبلت/کامپیوتر شخصی یا ...) و درگاه بفرست برقرار می‌شود که کاربر می‌تواند پیام‌های ارسالی سرور را بر روی این ارتباط دریافت کند.

publish درخواستی است از سمت کاربر به درگاه بفرست برای ارسال پیامی به یکی از کاربران اپلیکیشن خود.

uid شناسه‌ای است که بفرست به حساب کاربری شما نسبت می‌دهد.در بفرست از این شناسه در تشخیص کاربر استفاده می‌شود و همانطور که در بخش endpoints مطالعه خواهید کرد لازم است در تمام درخواست‌ها uid، به منظور تشخیص کاربر گنجانده شود.

chid شناسه‌ای است که معرف هر یک از کاربران شما در بفرست است. برای مثال بیایید فرض کنیم شما اپلیکیشن موبایلی دارید که کاربری با نام‌ X دارد. برای استفاده از سرویس بفرست و ارسال پوش نوتیفیکیشن به کاربر X، می‌بایست این کاربر به بفرست معرفی شود. این کار با انتخاب هر مقدار دل‌خواهی برای پارامتر chid از سمت شما انجام می‌شود. می‌توانید از یک رشته Alpha-numeric یا رشته عددی به عنوان مقدار chid در درخواست‌های خود برای ارسال پیام به کاربر X استفاده کنید. لطفا به این نکته دقت داشته باشید که chid هر کاربر اپلیکیشن شما می‌بایست یکتا بوده و تنها متعلق به آن کاربر باشد.

shared key کلیدی است که از آن در ساختن رشته auth که در ادامه شرح داده شده استفاده می‌شود. این کلید توسط کاربر تعیین می‌شود و می‌تواند شامل حداقل ۳۲ و حداکثر ۴۸ کاراکتر Alpha-numeric باشد.

api key کلیدی است که از آن در ساختن رشته auth که در ادامه شرح داده شده استفاده می‌شود. این کلید توسط بفرست تولید می‌شود و در اختیار کاربر قرار می‌گیرد.

api version : سرویس‌های بفرست در قالب نسخه‌های متفاوتی ارائه می‌شود. در هر نسخه ممکن است قابلیت جدیدی افزوده شده و دیگر سرویس‌ها بهبود یافته باشند. با ارائه هر نسخه، بفرست تغییرات ایجاد شده در آن نسخه را با جزئیات، برای استفاده کاربران شرح خواهد داد. همچنین ممکن است با گذشت زمان نسخه‌های قدیمی‌تر با اطلاع رسانی پیشین دیگر پشتیبانی نشوند.

auth رشته‌ای است که به منظور تشخیص هویت کاربر در درخواست‌هایی که به درگاه‌های بفرست ارسال می‌کند استفاده می‌شود. رشته auth وابسته به api key و shared key و آدرس درگاهی است که قصد فراخوانی آن را دارید. مراحل ایجاد رشته auth در ادامه شرح داده شده است.

ابتدا آدرس درگاهی که قصد فراخوانی آن را دارید به دو بخش (پروتکل +‌ دامنه +‌ پورت) و آدرس پس از دامنه تقسیم کنید. برای مثال در آدرس https://gw.bef.rest:8443/xapi/1/publish/UID/CHID بخش اول https://gw.bef.rest:8443 و بخش دوم /xapi/1/publish/UID/CHID خواهد بود. بخش دوم آدرس را addr بنامید.

  1. رشته‌ای با فرمت apikey,addr شکل دهید. دقت داشته باشید که apikey و addr با استفاده از کاراکتر comma از یکدیگر جدا شده‌اند و هیچ کاراکتر دیگری میان آنها وجود ندارد.
  2. رشته بدست آمده از مرحله قبل را با الگوریتم MD5 رمز نگاری کنید.
  3. آرایه بایت یا رشته باینری بدست آمده از مرحله قبل را با استفاده از الگوریتم BASE64 رمز نگاری کرده و آن را payload بنامید و سپس جایگزینی‌های زیر را انجام دهید.
    • کاراکترهای + را در payload با کاراکتر - جایگزین کنید
    • کاراکترهای = را در payload حذف کنید
    • کاراکترهای / را در payload با کاراکتر ـ (underscore) جایگزین کنید
  4. رشته‌ای با فرمت sharedkey,payload شکل دهید و آن را با استفاده از الگوریتم MD5 رمز نگاری کنید. مانند مرحله نخست دقت داشته باشید که هر یک از پارامتر‌ها با استفاده از کاراکتر comma از یکدیگر جدا شده‌اند و هیچ کاراکتر دیگری میان آنها وجود ندارد.
  5. آرایه بایت یا رشته باینری بدست آمده از مرحله قبل را با استفاده از الگوریتم BASE64 رمز نگاری کنید. سپس جایگزینی‌های مرحله ۳ را دوباره بر روی رشته بدست آمده انجام دهید
  6. رشته بدست آمده auth نام دارد!

channel id شناسه‌ای است یکتا برای هر subscriber متصل شده به بفرست که از ترکیب UID و CHID آن subscriber به شکل UID-CHID تولید می‌شود. فرض کنید شناسه کاربری شما (UID) در بفرست 1 باشد. حال کاربری که شما CHID با مقدار 100 به او اختصاص داده‌اید برای دریافت پوش نوتیفیکیشن‌های شما به بفرست متصل می‌شود. channel id این کاربر 1-100 خواهد بود.

message id شناسه‌ای است که بفرست پس از دریافت درخواست ارسال پیام، به آن پیام اختصاص می‌دهد. کاربران می‌توانند از این شناسه برای بررسی وضعیت پیام ارسال شده استفاده کنند.

topic name رشته‌ای است که به منظور گروه‌بندی کاربران اپلیکیشن شما استفاده می‌شود و می‌توانید با استفاده از آن پیامی را به صورت جمعی برای کاربران خود ارسال کنید. مثالی در این مورد کمک خواهد کرد تا مفهوم topic و topic name را بهتر متوجه شوید. فرض کنید شما اپلیکیشنی خبری با یک میلیون کاربر دارید. هر یک از کاربران در زمینه‌های مختلفی همچون اخبار سیاسی، ورزشی یا اجتماعی، علاقه‌مندی خود را در اپلیکیشن ثبت می‌کنند و انتظار دارند پس از انتشار اخبار در زمینه مد نظر ایشان، بلافاصله از انتشار خبر جدید مطلع شوند. با استفاده از قابلیت ارسال پیام تاپیک می‌توانید با انتشار اخبار سیاسی، تنها با یک publish کردن همه کاربرانی را که در انتظار اخبار سیاسی هستند مطلع کنید. topic name می‌تواند تنها از ترکیب کاراکترهای Alpha-numeric تشکیل شود و به صورت دل‌خواه و انتخابی توسط کاربر بفرست ایجاد می‌شود.

topic message id که به اختصار MID در بفرست شناخته می‌شود، شناسه‌ای است که پس از انتشار پیام در تاپیک، به آن پیام اختصاص داده می‌شود. با استفاده از این شناسه می‌توانید وضعیت پیام ارسال شده در تاپیک را بررسی کنید.


درگاه‌های بفرست

در ادامه به تشریح درگاه‌های بفرست که پیش از این به برخی از آنها اشاره شد می‌پردازیم. در مطالعه مستندات درگاه‌ها لطفا به این نکات دقت کنید.

  • پیش از آدرس هریک از درگاه‌ها، Request method آن درگاه مشخص شده است.
  • UID و CHID در آدرس هر یک از درگاه‌ها می‌بایست با مقادیر معتبر جایگزین شوند.
  • درگاه‌های بفرست با توجه به قابلیت‌های ارائه شده، نسخه بندی شده‌اند. بفرست پس از ارائه نسخه‌ای جدید، نسخ پیشین را پشتیبانی خواهد کرد و با اطلاع قبلی آن نسخه‌ها را از فهرست درگاه‌های پشتیبانی شده خارج خواهد کرد. هم اکنون آخرین نسخه ارائه شده ‍1 است.
  • فیلد errorCode در پاسخ درگاه‌ها، نمایانگر نتیجه کلی درخواست است. مقدار 0 به معنای انجام موفقیت آمیز درخواست است. در صورت بروز خطا مقدار مرتبط با آن خطا در errorCode و پیامی در رابطه با آن خطا در فیلدی با نام message دریافت خواهید کرد.
post https://api.bef.rest/xapi/1/publish/UID/CHID

با فراخوانی این درگاه می‌توانید همانطور که در بخش شروع کنیم دیدید، به کاربر (CHID) پیامی را ارسال کنید.

Headers
X-BF-AUTH
رشته auth باید با استفاده از این هدر ارسال شود.
X-BF-TTL
این هدر برای مشخص کردن مدت زمانی که می خواهید پیام شما در صف فعال بماند به ثانیه است. حداکثر مقدار ممکن برای این هدر 1209600، معادل ۱۴ روز می‌باشد. به عنوان مثال اگر شما مقدار این پارامتر برای یک پیام را ۳۶۰۰ وارد کنید، درصورتی که کاربر مورد نظر آنلاین نباشد، این پیام تا یک ساعت در صف پیام‌های کاربر فعال باقی می‌ماند و در صورتی که کاربر بعد از گذشت یک ساعت برخط نشود، پیام به او نخواهد رسید.
Parameters

در ارسال درخواست به این درگاه، بدنه درخواست می‌بایست به صورت raw حاوی پیامی باشد که می‌خواهید به کاربر ارسال شود.

Response
  • فیلد messageId در entity شناسه‌ای است که بفرست به پیام ارسال شده نسبت داده است (در صورت نیاز بخش واژگان را مطالعه کنید)
  • فیلد channelId در entity نشانگر CHID ای است که پیام به وی ارسال شده است. (در صورت نیاز بخش واژگان را مطالعه کنید)
  • subscribers تعداد کاربران متصل با استفاده از CHID مشخص شده در درخواست است.
{
  "errorCode": 0,
  "entity": {
    "messageId": "xxx",
    "channelId": "zzz",
    "subscribers": 0
  }
}
get https://api.bef.rest/xapi/1/message-status/UID/MESSAGE-ID

با فراخوانی این درگاه می‌توانید از وضعیت پیامی که از پیش ارسال شده است اطلاع پیدا کنید.

Headers
X-BF-AUTH
رشته auth باید با استفاده از این هدر ارسال شود.
Response

مقدار فیلد status در entity نشانگر وضعیت پیام ارسال شده است. D به معنای دریافت شده، Q به معنای صف شده (کاربر در اولین اتصال، پیام را دریافت خواهد کرد) و E به معنای منقضی شدن پیام است (کاربر پس از ارسال پیام، آنلاین نشده است و پیام پس از گذشت زمان پیش فرض که ۱۰ روز است منقضی شده است).

{
  "errorCode": 0,
  "entity": {
    "status": "D/Q/E"
  }
}
post https://api.bef.rest/xapi/1/multi-publish/UID

با فراخوانی این درگاه می‌توانید پیامی را به چندین CHID ارسال کنید.

Headers
X-BF-AUTH
رشته auth باید با استفاده از این هدر ارسال شود.
X-BF-TTL
مقدار این هدر مشخص کننده مدت زمانی (ثانیه) است که پیام در صورت برخط نبودن کاربر در صف باقی خواهد ماند. حداکثر مقدار ممکن 1209600، معادل ۱۴ روز است. به عنوان مثال اگر از مقدار ۳۶۰۰ برای این هدر استفاده کنید، در صورتی که کاربر مورد نظر برخط نباشد، پیام ارسال شده تا یک ساعت در صف پیام‌های کاربر، فعال باقی خواهد ماند و در صورتی که کاربر بعد از گذشت یک ساعت برخط نشود، پیام از صف پیام‌های وی حذف خواهد شد.
X-BF-CH
با استفاده از این هدر، کانال‌های دریافت کننده را مشخص می‌کنید. شناسه کانال‌ها می‌بایست با استفاده از کاراکتر کاما (,) از یکدیگر جدا شوند. برای مثال اگر قصد دارید پیامی را به کانال‌هایی که با شناسه‌های 1، 2 و 3 ارسال کنید می‌بایست مقدار 1,2,3 در هدر X-BF-CH قرار داده شود.
نکته: رشته‌ای که در هدر X-BF-CH قرار داده می‌شود می‌تواند حداکثر ۶ کیلوبایت باشد. در صورتی که رشته‌ای بزرگتر از ۶ کیلوبایت در این هدر قرار گیرد پاسخی با کد 413 دریافت خواهید کرد.
Parameters

در ارسال درخواست به این درگاه، بدنه درخواست می‌بایست به صورت raw حاوی پیامی باشد که می‌خواهید به کانال‌های مشخص شده ارسال شود.

Response
  • مقدار 0 در فیلد errorCode نشانگر آن است که عملیات انتشار در تاپیک مشخص شده در درخواست با موفقیت انجام شده است. در صورت بروز خطا فیلد message به پاسخ افزوده خواهد شد که حاوی پیام خطای رخ داده است.
  • فیلد messageId در entity شناسه پیام ارسال شده را نشان می‌دهد.
{
  "errorCode": 0,
  "entity": {
    "messageId": "xyz"
  }
}
post https://api.bef.rest/xapi/1/t-publish/UID/TOPIC-NAME

با فراخوانی این درگاه می‌توانید پیامی را در یک تاپیک ارسال کنید.

Headers
X-BF-AUTH
رشته auth باید با استفاده از این هدر ارسال شود.
X-BF-TEXP
با استفاده از هدر X-BF-TEXP می‌توانید مدت زمان اعتبار پیام تاپیک را تعیین کنید. واحد مدت زمان اعتبار پیام، ثانیه است. برای مثال اگر می‌خواهید کاربران حداکثر تا ۲۴ ساعت آینده پیام جدید منتشر شده را دریافت کنند مقدار 86400 را به عنوان مقدار این هدر تنظیم کنید. در صورتی که می‌خواهید تنها کاربران برخط، پیام تاپیک را دریافت کنند از مقدار صفر استفاده کنید.
Parameters

در ارسال درخواست به این درگاه، بدنه درخواست می‌بایست به صورت raw حاوی پیامی باشد که می‌خواهید به کاربرانی که در تاپیک مشخص شده subscribe کرده‌اند ارسال شود.

Response

  • مقدار 0 در فیلد errorCode نشانگر آن است که عملیات انتشار در تاپیک مشخص شده در درخواست با موفقیت انجام شده است. در صورت بروز خطا فیلد message به پاسخ افزوده خواهد شد که حاوی پیام خطای رخ داده است.
  • فیلد subscribers در entity نشان دهنده تعداد کاربران آنلاینی است که بر روی تاپیک subscribe کرده‌اند.
  • فیلد messageId در entity شناسه پیام ارسال شده در این تاپیک را نشان می‌دهد.

{
  "errorCode": 0,
  "entity": {
    "subscribers": 10,
    "messageId": "1"
  }
}
get https://api.bef.rest/xapi/1/topic-status/UID/TOPIC-NAME

با فراخوانی این درگاه می‌توانید وضعیت هر یک از تاپیک‌های خود در بفرست را بررسی کنید.

Headers
X-BF-AUTH
رشته auth باید با استفاده از این هدر ارسال شود.
Response
  • مقدار 0 در فیلد errorCode نشانگر آن است که بررسی وضعیت تاپیک بدون مشکل انجام شده است و پاسخ دریافت شده قابل استفاده است.
  • فیلد messages در پاسخ، نشان دهنده تعداد کل پیام‌های منتشر شده در تاپیک است.
  • فیلد activeMessages در پاسخ، نشان دهنده تعداد پیام‌های فعال تاپیک است.
  • فیلد onlineChannels در پاسخ، نشان دهنده تعداد کاربران برخط است پیام‌های تاپیک را دریافت می‌کنند.
  • فیلد deliveries در پاسخ، نشان دهنده تعداد تجمیعی دریافت‌های پیام‌های تاپیک است.
{
  "errorCode": 0,
  "entity": {
    "name": "topic",
    "messages": 1,
    "activeMessages": 0,
    "onlineChannels": 79,
    "deliveries": 21
  }
}
get https://api.bef.rest/xapi/1/topic-msg-status/UID/TOPIC-NAME/MID

با فراخوانی این درگاه می‌توانید وضعیت هر یک از پیام‌های تاپیک‌های خود در بفرست را بررسی کنید.

Headers
X-BF-AUTH
رشته auth باید با استفاده از این هدر ارسال شود.
Response
  • مقدار 0 در فیلد errorCode نشانگر آن است که بررسی وضعیت پیام تاپیک بدون مشکل انجام شده است و پاسخ دریافت شده قابل استفاده است.
  • فیلد message در پاسخ، نشان دهنده متن پیام منتشر شده در تاپیک است.
  • فیلد created در پاسخ، نشان دهنده Unix timestamp ارسال پیام تاپیک است.
  • فیلد ttl در پاسخ، نشان دهنده مدت زمان اعتبار (ثانیه) پیام تاپیک است.
  • فیلد status در پاسخ، نشان دهنده وضعیت پیام است. مقدار ACTIVE گویای این مطلب است که کاربرانی که هنوز پیام تاپیک را دریافت نکرده‌اند، پس از اتصال، پیام را دریافت خواهند کرد. مقدار EXPIRED نیز نشان دهنده این است که مدت اعتبار پیام تاپیک به پایان رسیده است.
  • فیلد deliveries در پاسخ، نشان دهنده تعداد تجمیعی دریافت‌های پیام‌های تاپیک است.
{
  "errorCode": 0,
  "entity": {
    "message": "a sample message",
    "created": 1454409003,
    "ttl": 120,
    "status": "ACTIVE",
    "deliveries": 100
  }
}
get https://api.bef.rest/xapi/1/channel-status/UID/CHID

با فراخوانی این درگاه می‌توانید آماری در مورد یک کانال (کاربر) خود دریافت کنید.

Headers
X-BF-AUTH
رشته auth باید با استفاده از این هدر ارسال شود.
Response
  • فیلد storedMessages اشاره به تعداد پیام‌های صف شده کانال دارد.
  • فیلد subscribers نشان دهنده تعداد کاربران متصل به کانال مشخص شده است.
  • فیلد publishedMessages نشان دهنده تعداد پیام‌هایی است که تاکنون برای کاربر با CHID مشخص شده ارسال شده است.
{
  "errorCode": 0,
  "entity": {
    "storedMessages": 1,
    "subscribers": 2,
    "publishedMessages": 3
  }
}
get https://gw.bef.rest/xapi/1/subscribe/UID/CHID/SDK-VERSION

با فراخوانی این درگاه اتصالی از نوع persistent در اختیار خواهید داشت که می‌توانید پیام‌های ارسالی را بر روی آن دریافت کنید.

Headers

X-BF-AUTH
رشته auth باید با استفاده از این هدر ارسال شود.
X-BF-TOPICS
لیست تاپیک‌هایی که کاربر می‌خواهد پیام‌های آنها را دریافت کند. تاپیک‌ها می‌بایست با کاراکتر دش (-) از یکدیگر جدا شوند. همه کاربران حین subscription به صورت پیش‌فرض در تاپیکی به نام all سابیکرایب می‌شوند که در صورت نیاز به ارسال پیام به همه کاربران، می‌توان با publish کردن بر روی تاپیک all این کار را انجام داد.

Response

به دلیل از نوع persistent بودن اتصال درخواست subscription، پاسخی که دریافت می‌کنید از نوع Handshaking است. صرفا پیام‌های ارسالی در خروجی این اتصال دریافت خواهند شد.


نمونه کدها

در صورتی که SDK های بفرست پاسخ‌گوی نیاز‌های شما نیستند می‌توانید از نمونه کد‌های زیر استفاده کنید تا سریعتر بتوانید از سرویس بفرست استفاده کنید. دقت داشته باشید که نمونه کدهای زیر تنها برای آموزش و یادگیری آماده شده‌اند و برای استفاده در محیط واقعی سرویس‌دهی بهینه سازی نشده‌اند. در صورت نیاز می‌توانید با تیم پشتیبانی بفرست برای دریافت مشاوره و راهنمایی تماس حاصل کنید.

ایجاد رشته auth

در صورتی که هنوز تعریف رشته auth در بخش واژگان را مطالعه نکرده‌اید، لازم است با هدف و تعریف آن آشنا شوید. تولید رشته addr نکته کلیدی در ایجاد رشته auth به شکل صحیح است. در ادامه به مثال‌های تولید رشته addr دقت بفرمایید.

نمونه نخست (اتصال کانال به بفرست):
  1. آدرس درگاه را در نظر بگیرید
    https://gw.bef.rest/xapi/1/subscribe/UID/CHID/SDK-VERSION
  2. آدرس درگاه را با جایگزین کردن مقادیر UID، CHID و SDK-VERSION آماده کنید
    https://gw.bef.rest/xapi/1/subscribe/123456/987654321/2
  3. با حذف کردن "https://gw.bef.rest" از آدرس درگاه، addr به دست می‌آید.
    /xapi/1/subscribe/123456/987654321/2
نمونه دوم (ارسال پیام به کانال):
  1. آدرس درگاه را در نظر بگیرید
    https://api.bef.rest/xapi/1/publish/UID/CHID
  2. آدرس درگاه را با جایگزین کردن مقادیر UID و CHID آماده کنید
    https://gw.bef.rest/xapi/1/publish/123456/987654321
  3. با حذف کردن "https://gw.bef.rest" از آدرس درگاه، addr به دست می‌آید.
    /xapi/1/publish/123456/987654321

import org.apache.commons.codec.binary.Base64;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class BefrestAuth {

    private static final long UID = 1;
    private static final String API_KEY = "/* YOUR API KEY */";
    private static final String SHARED_KEY = "/* YOUR SHARED KEY */";

    public String generatePublishAuth(String chid) {
       return generateAuthToken(String.format("/xapi/1/publish/%d/%s", UID, chid));
    }

    public String generateSubscriptionAuth(String chid, int sdkVersion) {
        return generateAuthToken(String.format("/xapi/1/subscribe/%d/%s/%d", UID, chid, sdkVersion));
    }

    public String generateChannelStatusAuth(String chid) {
        return generateAuthToken(String.format("/xapi/1/channel-status/%d/%s", UID, chid));
    }

    /**
     * @param addr Please refer to https://bef.rest/documentation#generating-auth-string for instructions on
     *             how to build the addr parameter
     */
    private String generateAuthToken(String addr) {
        try {
            String initialPayload = String.format("%s,%s", API_KEY, addr);
            byte[] md5 = md5(initialPayload);
            String base64 = base64Encode(md5);

            String payload = String.format("%s,%s", SHARED_KEY, base64);
            md5 = md5(payload);
            return base64Encode(md5);
        } catch (Exception e) {
            // Log the occurred exception
            return null;
        }
    }

    private byte[] md5(String input) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.update(input.getBytes());
        return messageDigest.digest();
    }

    private String base64Encode(byte[] input) {
        return new String(Base64.encodeBase64(input))
                .replaceAll("\\+", "-")
                .replaceAll("=", "")
                .replaceAll("/", "_");
    }
}
class BefrestAuth
{
    private static $uid = /* REPLACE THIS COMMENT WITH YOUR UID */;
    private static $apiKey = '/* REPLACE THIS COMMENT WITH YOUR API KEY */';
    private static $sharedKey = '/* REPLACE THIS COMMENT WITH YOUR SHARED KEY */';

    public static function generateSubscriptionAuth($chid, $sdkVersion = 2) {
        return self::generateAuth(sprintf('/xapi/1/subscribe/%d/%s/%d', self::$uid, $chid, $sdkVersion));
    }

    public static function generatePublishAuth($chid) {
        return self::generateAuth(sprintf('/xapi/1/publish/%d/%s', self::$uid, $chid));
    }

    public static function generateChannelStatusAuth($chid) {
        return self::generateAuth(sprintf('/xapi/1/channel-status/%d/%s', self::$uid, $chid));
    }

    private static function generateAuth($addr = '') {
        $payload = self::base64Encode(hex2bin(md5(sprintf('%s,%s', self::$apiKey, $addr))));

        return self::base64Encode(
            hex2bin(md5(sprintf('%s,%s', self::$sharedKey, $payload))));
    }

    private static function base64Encode($input) {
        $payload = str_replace('+', '-', base64_encode($input));
        $payload = str_replace('=', '', $payload);
        return str_replace('/', '_', $payload);
    }
}
import hashlib
import base64

def generate_auth_token(api, shrd, addr):
    payload = '%s,%s' % (api, addr)
    crypt = base64.b64encode(md5(payload)).replace('+', '-').replace('=', '').replace('/', '_')
    payload = '%s,%s' % (shrd, crypt)
    auth = base64.b64encode(md5(payload)).replace('+', '-').replace('=', '').replace('/', '_')
    return auth

def md5(input):
    m = hashlib.md5()
    m.update(input)
    return m.digest()
using System;
using System.Security.Cryptography;
using System.Text;

public class BefrestAuth
{
    private static MD5 md5 = MD5.Create();
    private static long UID = /* REPLACE THIS COMMENT WITH YOUR UID */;
    private static String API_KEY = "/* REPLACE THIS COMMENT WITH YOUR API KEY */";
    private static String SHARED_KEY = "/* REPLACE THIS COMMENT WITH YOUR SHARED KEY */";

    public static String GeneratePublishAuth(String chid) {
        return GenerateAuthToken(String.Format("/xapi/1/publish/{0}/{1}", UID, chid));
    }

    public static String GenerateSubscriptionAuth(String chid, int sdkVersion) {
        return GenerateAuthToken(String.Format("/xapi/1/subscribe/{0}/{1}/{2}", UID, chid, sdkVersion));
    }

    public static String GenerateChannelStatusAuth(String chid) {
        return GenerateAuthToken(String.Format("/xapi/1/channel-status/{0}/{1}", UID, chid));
    }

    private static String ToCustomB64(byte[] input) {
        return Convert.ToBase64String(input)
        .Replace("+", "-")
        .Replace("=", "")
        .Replace("/", "_")
        .Replace("\n", "");
    }

    private static String GenerateAuthToken(String addr) {
        byte[] initialPayload = Encoding.UTF8.GetBytes(String.Format("{0},{1}", API_KEY, addr));
        byte[] hash = md5.ComputeHash(initialPayload);
        String base64 = ToCustomB64(hash);

        byte[] payload = Encoding.UTF8.GetBytes(String.Format("{0},{1}", SHARED_KEY, base64));
        hash = md5.ComputeHash(payload);
        return ToCustomB64(hash);
    }
}
انتشار پیام (publish)
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import java.io.InputStream;

public class Publisher {

    private static final String ENDPOINT = "https://api.bef.rest/xapi/1/publish/%d/%s";

    public String publish(long uid, String chid, String auth, String message) {
        HttpPost post = new HttpPost(String.format(ENDPOINT, uid, chid));
        post.setEntity(new StringEntity(message, "UTF8"));
        post.setHeader("X-BF-AUTH", auth);
        StringBuilder responseBuilder = new StringBuilder();

        try (CloseableHttpClient httpClient = HttpClients.custom().build()) {
            try (CloseableHttpResponse response = httpClient.execute(post)) {
                InputStream stream = response.getEntity().getContent();
                int content;
                int statusCode = response.getStatusLine().getStatusCode();

                if (statusCode == HttpStatus.SC_OK)
                    while ((content = stream.read()) != -1)
                        responseBuilder.append((char) content);

                return responseBuilder.toString();
            }
        } catch (Exception e) {
            // Handle the occurred exception
            return null;
        }
    }
}
class Publisher
{
    private static $ENDPOINT = 'https://api.bef.rest/xapi/1/publish/%d/%s';

    public static function publish($uid, $chid, $auth, $message) {
        $headers = array(
            sprintf('X-BF-AUTH: %s', $auth)
        );

        $curl = curl_init(sprintf(self::$ENDPOINT, $uid, $chid));
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $message);
        curl_exec($curl);
    }
}
import httplib

def publish(uid, chid, auth, message):
url = 'https://api.bef.rest/xapi/1/publish/%d/%s' % (uid, chid)
    headers = {'X-BF-AUTH': auth}
    conn = httplib.HTTPConnection(url)
    conn.request('POST', url, message, headers)
    resp = conn.getresponse()
    return resp.read()
curl -v -H 'X-BF-AUTH: place the auth string here' -X POST 'https://api.bef.rest/xapi/1/publish/<uid>/<chid>' \
    -d "message to be published"