پرش به مطلب اصلی

توسعه اپلیکیشن‌های بازارچه CDN

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

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

در این راهنما به بررسی ساختار و شیوه‌ی توسعه‌ی اپلیکیشن‌‌های CDN برای بازارچه‌ی ابری آروان می‌پردازیم.

برای ثبت یک برنامه‌ی جدید باید یک فایل به اسم install.json ساخته شود که شامل محتوای js و css برنامه (resources)، پارامترهای قابل دریافت از کاربر هنگام نصب (options) و وب هوک‌های تعیین‌شده جهت صدا زدن api تعریف‌شده توسط توسعه‌دهنده‌ی برنامه هنگام رخ دادن ایونت های خاص باشد.

در ادامه، یک نمونه از فایل install.json (بدون هوک) را مشاهده می‌کنید.

{
"resources": {
"head": [
{
"type": "style",
"content": "#unique-app-prefix-style{background-color:#C1272D;text-align:center}"
},
{
"type": "script",
"content": "!function(){console.log('The application source code lies here, within an IIFE to prevent scope collision with other applications, also the app can access user defined options like this :' + INSTALL_OPTIONS.full_name)}();"
}
],
"body": [
{
"type": "script",
"content": "!function(){console.log('The application source code lies here, within an IIFE to prevent scope collision with other applications, also the app can access user defined options like this :' + INSTALL_OPTIONS.age)}();"
}
]
},
"options": {
"properties": {
"fullname": {
"title": "Full Name",
"description": "Enter Your FullName here, this is a string input",
"type": "string"
},
"age": {
"title": "age",
"description": "Enter Your age, this is a number input",
"type": "number"
},
"agreement": {
"title": "agreement",
"description": "Do you agree with our terms? this is a boolean input",
"type": "boolean"
}
},
"required": [
"fullname",
"age"
]
}
}

Resources

شامل سه آیتم head،body و options_translations هستند:

  • head

    به انتهای تگ <head> و قبل از بسته شدن آن در وب‌سایت استفاده کننده به ترتیب تعریف شده در این فایل اضافه می‌شوند.

  • body

    به انتهای تگ <body> و قبل از بسته شدن آن در وب‌سایت استفاده کننده به ترتیب تعریف شده در این فایل اضافه می‌شوند.

  • options_translations

    برای عملیات ترجمه (پشتیبانی از زبان‌های متفاوت) استفاده می‌شود.

  • type

    می‌تواند یکی از دو مقدار "style" یا "script" باشد.

  • content

    متناظر با type تعریف‌شده، می‌تواند حاوی کد js یا css باشد. باید در نظر داشت کد حتما باید minify شده و تا حد امکان کوچک باشد. در ضمیمه‌ی شماره‌ی ۱ به جزییات و راهنمای ساخت هر کدام می پردازیم.

  • Options

آپشن قابلیت شخصی‌سازی اپلیکیشن برای هر کاربر را فراهم می‌کند. آپشن از استاندارد JSON-Schema برای تعریف و اعتبار سنجی مقادیر استفاده می‌کند.

{
"options": {
"properties": {
"<option name>": {
"title": "shown to user during app installation",
"Description": "shown to user during app installation",
"default": "default value",
"type": "string" }
},
"required": [ //if the option is required include it in this array
"<option name>"
]
}
}

ضمیمه شماره یک

راهنمای تبدیل اسکریپت برنامه

  • همان‌طور که در مثال اشاره شده است، اسکریپت برنامه باید داخل یک فانکشن IIFE یا Immediately Invoked Function Expression قرار بگیرد تا اسکوپ برنامه از بقیه‌ی برنامه ها جدا باشد.
  • تمامی optionsها در هنگام اجرای script داخل آبجکتی به نام INSTALL_OPTIONS قابل دسترسی هستند. برای مثال اگر آپشنی به اسم token تعریف شده باشد مقدار آن را می توان به این شکل بازیابی کرد:
INSTAL_OPTIONS.token
  • تمامی double quoteها باید escape شوند.

  • برای اسکیپ دابل کوت و مینیفای کردن می‌توانید از سایت CyberChef-Minify کمک بگیرید.

  • اکنون می‌توانید خروجی را که یک رشته استرینگ است داخل فایل install.json در content قرار دهید.

مثال: ساخت فایل install.json برای برنامه رای‌چت

اسکریپت سایت رای چت برای قرار گرفتن در لیست اپ‌های بازارچه:

<script type="text/javascript">
!function () { // the script is already inside in IIFE
function t() {
var t = document.createElement("script");
t.type = "text/javascript", t.async = !0, localStorage.getItem("rayToken") ? t.src = "https://app.raychat.io/scripts/js/" + r + "?rid=" + localStorage.getItem("rayToken") + "&href=" + window.location.href : t.src = "https://app.raychat.io/scripts/js/" + r;
var e = document.getElementsByTagName("script")[0];
e.parentNode.insertBefore(t, e);
}
var e = document, a = window, r = "xxxxxx-xxxx-xxxx-xxxx";
"complete" == e.readyState ? t() : a.attachEvent ? a.attachEvent("onload", t) : a.addEventListener("load", t, !1);
}();
</script>

اولین قدم این است که مقدار "xxxxxx-xxxx-xxxx-xxxx" که محل قرار گیری توکن کاربر است را تغییر دهیم تا آن را از INSTALL_OPTIONS بخواند:

var e = document, a = window, r = INSTAL_OPTIONS.token;

سپس اسکریپت باید داخل یک IIFE قرار بگیرد. در این مثال، رای‌چت به‌ شکل پیش‌فرض این ویژگی را داشت.

اکنون، کافی است تگ <script> را حذف کنیم و محتوای داخل آن را در وب‌سایت CyberChef که بالاتر اشاره شد قرار دهیم تا خروجی زیر تولید شود:

!function(){function t(){var t=document.createElement(\"script\");t.type=\"text/javascript\",t.async=!0,localStorage.getItem(\"rayToken\")?t.src=\"https://app.raychat.io/scripts/js/\"+r+\"?rid=\"+localStorage.getItem(\"rayToken\")+\"&href=\"+window.location.href:t.src=\"https://app.raychat.io/scripts/js/\"+r;var e=document.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(t,e)}var e=document,a=window,r=INSTAL_OPTIONS.token;\"complete\"==e.readyState?t():a.attachEvent?a.attachEvent(\"onload\",t):a.addEventListener(\"load\",t,!1)}();

در این مرحله اسکریپت کامل شده و باید فایل install.json را تولید کنیم.

{
"resources": {
"body": [
{
"type": "script",
"content": "!function(){function t(){var t=document.createElement(\"script\");t.type=\"text/javascript\",t.async=!0,localStorage.getItem(\"rayToken\")?t.src=\"https://app.raychat.io/scripts/js/\"+r+\"?rid=\"+localStorage.getItem(\"rayToken\")+\"&href=\"+window.location.href:t.src=\"https://app.raychat.io/scripts/js/\"+r;var e=document.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(t,e)}var e=document,a=window,r=INSTAL_OPTIONS.token;\"complete\"==e.readyState?t():a.attachEvent?a.attachEvent(\"onload\",t):a.addEventListener(\"load\",t,!1)}();"
}
]
},
"options": {
"properties": {
"token": {
"title": "توکن",
"description": "توکن وب‌سایت که از رایچت گرفته اید",
"type": "string"
}
},
"required": [
"token"
]
}
}

این فایل یک فایل آماده برای ساخت یک اپلیکیشن بازارچه است.

راهنمای تبدیل استایل برنامه

کافی است css مورد نظر را بدون در بر داشتن تگ‌های html مینیفای و escape کنید. در این مرحله هم می‌توانید از سایت CyberChef-CSS-Minify کمک بگیرید.

Hooks

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

یک مثال از برنامه نمونه زیر را در نظر بگیرید:

{
"resources": {
"body": [
{
"type": "script",
"content": "!function(){console.log('Your favorite color is :' + INSTALL_OPTIONS.color + 'also you are registered on our website with help of hooks, your token is :' INSTALL_OPTIONS.token )}();"
}
]
},
"options": {
"properties": {
"color": {
"title": "desired color",
"description": "tell us what's your favorite color",
"type": "string"
},
"token": {
"title": "token by hook",
"description": "The token will be automatically generated for you, we register you as our customer with your arvan's email address",
"type": "string"
}
},
"required": [
"color",
"token"
]
},
"hooks": [
{
"endpoint": "https://example-vendor.com/hook",
"events": [
"before-new-install"
]
}
]
}

این برنامه پس از نصب در کنسول مرورگر رنگ مورد علاقه‌ی صاحب وب‌سایت و توکنش را چاپ می‌کند.

هنگام نصب برنامه کاربر باید دو فیلد اجباری را پر کند. یکی رنگ و دیگری توکن. برای پر کردن رنگ مشکلی وجود ندارد اما برای دریافت توکن باید مراحلی طی شود. صاحب برنامه نیاز دارد برای راحتی کاربر در لحظه مراحل ثبت‌نام را انجام داده* و یک توکن به کاربر اختصاص دهد تا در فیلد مربوطه قرار بگیرد.

برای این کار در فایل install_json بخشی به نام hooks تعریف کرده، اندپوینتی که قرار است به هوک‌ها پاسخ دهد به همراه ایونت‌هایی که باید در آن‌ها این اندپوینت کال شوند ست می‌کند.

اکنون وقتی کاربر به نقطه‌ی "before-new-install" می‌رسد (وقتی دکمه‌‌ی نصب را می‌زند)، یک درخواست از سمت API آروان به "http://example-vendor.com/hook" با یک payload خاص که در ادامه بررسی می‌کنیم، فرستاده می‌شود. در این مرحله، سازنده‌ی برنامه می‌تواند payload را بررسی کند، ورودی‌های کاربر را مشاهده کند، ثبت نام را انجام دهد، ورودی‌ها را تغییر داده یا حتا خطا برگرداند و ادامه‌ی پروسه‌ی نصب را متوقف کند و خطا را به کاربر نمایش دهد.


*ثبت نام از این روش توصیه نمی‌شود و بهتر است که از طریق oauth انجام شود ولی تا زمان پیاده‌سازی می‌توان از این راه استفاده کرد.

Structure

ساده ترین ساختار هوک به‌شکل زیر است:

  "hooks": [
{
"endpoint": "https://example.com/my-endpoint",
"events": [
"before-new-install"
]
}
]
  • Endpoint

    آدرس HTTPS سروری که به هوک‎ها پاسخ می‌دهد.

  • Events

    آرایه‌ای از ایونت‌ها (بخش ایونتها را ببینید.)

    این امکان وجود دارد که چندین هوک مختلف را به یک ایونت متصل کرد. هم‌چنین امکان listen کردن چندین ایونت مختلف برای یک اندپوینت وجود دارد.

Events

  • Before-new-install

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

Request Payloads

نمونه درخواستی که آدرس وب‌هوک مشخص‌شده از آروان دریافت می‌کند :

{
"event": "before-new-install",
"user": {
"id": "003d7fb3-4108-43cd-b7c5-19a4c8cb2e51",
"email": "arvanuser@gmail.com"
},
"site": {
"id": "67bd92d3-cde1-45f5-91e2-32a021f7752c",
"name": "example.ir",
"owner_id": "393f1d23-80ee-4872-917c-1bca8a150d69"
},
"install": {
"options": {
"color": "filled-by-user",
"token": "webhook-server-will-fill-this"
},
"schema": {
"properties": {
"color": {
"title": "desired color",
"description": "tell us whats your favorite color",
"type": "string"
},
"token": {
"title": "token by hook",
"description": "The token will be automatically generated for you, we register you as our customer with your arvan's email address",
"type": "string"
}
},
"required": [
"color",
"token"
]
}
},
"app": { /* Your app */
"id": "21493101-cda6-4a48-8ef5-e1b5da6941df",
"name": "ref-hook",
"slug": "ref-hook"
}
}
  • event

    نام ایونتی که باعث صدا زدن وب‌هوک شده است.

  • user

    مشخصات کاربری که در حال نصب برنامه است.

  • site

    وب سایتی که برنامه روی آن نصب می‌شود.

  • install

    • options

      ورودی های کاربر تا به این‌جای کار را می‌توان در این فیلد مشاهده یا ویرایش کرد.

    • schema

      همان options در فایل install_json است که ساختار ورودی را مشخص می‌کند، این فیلد در حال حاضر فقط خواندنی است (تغییرات اثری نخواهند داشت) اما در نسخه های بعدی وب‌هوک می‌تواند با توجه به ورودی‌های کاربر schema را تغییر دهد تا برنامه‌های پیچیده‌تر با نصب راحت قابل پیاده‌سازی باشند.

  • app

    مشخصات ثبت‌شده در آروان برای اپلیکیشن در حال نصب

Hook Response Format

جواب وب هوک باید به فرمت زیر باشد:

{
proceed: Boolean /* Should we allow this action to proceed? */,
errors: [error] /* array of errors which occured while you attempted to handle this event. */,
install: Object { /* The newly updated install record incorporating your changes. */ }
}
  • proceed

    اگر false باشد فرآیند نصب متوقف خواهد شد و به کاربر خطا نمایش داده می‌شود.

  • errors

    آرایه‌ای از خطاهای رخ‌داده حین بررسی درخواست به فرمت زیر:

{
type: String /* A string representing a code for this error which will not change frequently. */,
message: String /* A human readable English-language explanation of the error to be displayed. */
}

مثال:

  "errors": [
{
"type": "error 422",
"message": "The value of color must in hexadecimal format"
}
]
  • install

    بخش install موجود در درخواست به همراه تغییرات اعمال شده از سمت هوک.

Hook Security

آروان هنگام فرستادن درخواست به سمت هوک سرور، تمام body درخواست (uncompressed) را با secret توسط الگوریتم SHA-256 HMAC هش می‌کند و داخل هدر x-signature-hmac-sha256-hex قرار می‌دهد. وب هوک هم موظف است این کار را انجام داده و با هدر مقایسه کند و اگر هدر اشتباه بود درخواست را رد کند.

مثال وریفای کردن در Laravel

      $hash = hash_hmac('sha256', $request->getContent(), 'my-app-secret');
if ($hash !== $request->header('x-signature-hmac-sha256-hex')) {
abort(401, "Hook signature does not match");
}
// proceed ...

طول secret برابر با 128 کاراکتر و طول hash برابر با 64 کاراکتر است. هر دوی آن‌ها در فرمت hexadecimal number ارایه می‌شوند.

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

برای ترجمه‌ی اطلاعات برنامه (نام، توضیح کوتاه و بلند) هنگام تعریف آن باید فیلدی با فرمت Json توسط ادمین به‌شکل زیر ارسال شود.

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

"info_translations": {
"en": {
"name": "english_name",
"short_description": "english_short_description",
"description": "english_description"
},
"fa": {
"name": "persian_name",
"short_description": "persian_short_description",
"description": "persian_description"
}
}

محدودیت‌های پیاده‌سازی

اگر با اپلیکیشن‌های CDN آشنایی دارید باید بدانید که نسخه‌ی کنونی cdn-app یا بازارچه ابری آروان شامل محدودیت های زیر است:

  • عدم وجود قابلیت تغییر فرم در حین نصب
  • قابل استفاده بودن فقط سه تایپ string ،integer ،boolean برای استفاده در فرم
  • عدم پشتیبانی از oauth
  • وجود نداشتن قابلیت استفاده از ریسورس در فایل های جداگانه و مشخص کردن مسیر (تمامی محتوای js و css باید داخل فایل install.json قرار بگیرند)
  • در حال حاضر فقط وب‌هوک before-new-install قابل استفاده است.