יום שני, פברואר 01, 2010

קצת על חיובים

אמנם ההכרות שלי עם עולם הבילינג איננה גדולה (שנתיים בפיתוח) אבל יש שני מודלים שאני מכיר.
prepaid ו postpaid. כאשר יש עבודה עם שרתי VoIP (או למעשה כל פלטפורמה) ישנה בעייה מסויימת לעבודה עם prepaid(בגלל ששירותי radius לא ממש תומכים מהקופסה בפתרון כזה ). ישנן מספר גישות לכך:
לדוגמה שימוש בgatekeepr פתרון FOSSי מלא.
כתיבת מודל לfreeradius ומימוש אצל הלקוח.
שימוש call control בcdrtool

ישנם עוד פתרונות רבים לנושא אבל אותי מעניין הדרך המהירה ביותר (בשבילי).

ניקח לדוגמה את הדוגמה הבאה :
....
# define the profile
modparam("dialog", "profiles_with_value", "caller")
....

# Example route block:
# this example should be called before the t_relay() function of an outbound invite
#
########################################################################
# Request route 'callcontrol' with channel limit
########################################################################

route[39]
{
## have we done our checking on this call?
if(!isflagset(31))
{
# user has max channel limit set as preference
if(is_avp_set("$avp(s:channels)/n") && avp_check("$avp(s:channels)", "gt/i:0"))
{
# get current calls for uuid
get_profile_size("caller","$avp(s:caller_uuid)","$var(calls)");

# check within limit
if($avp(s:channels) > $var(calls))
{
xlog("L_INFO", "Call control: user '$avp(s:caller_uuid)' currently has
'$var(calls)' of '$avp(s:channels)' active calls before this one\n");
$var(setprofile) = 1;
}
else
{
xlog("L_INFO", "Call control: user channel limit exceeded [$var(calls)/$avp(s:channels)]\n");
send_reply("487", "Request Terminated: Channel limit exceeded\n");
exit;
}
}
else
{
$var(setprofile) = 0;
}

call_control();

switch ($retcode)
{
case 2:
# Call with no limit
case 1:
# Call with a limit under callcontrol management (either prepaid or postpaid)
break;
case -1:
# Not enough credit (prepaid call)
xlog("L_INFO", "Call control: not enough credit for prepaid call\n");
acc_rad_request("402");
sl_send_reply("402", "Not enough credit");
exit;
break;
case -2:
# Locked by call in progress (prepaid call)
xlog("L_INFO", "Call control: prepaid call locked by another call in progress\n");
acc_rad_request("403");
sl_send_reply("403", "Call locked by another call in progress");
exit;
break;
default:
# Internal error (message parsing, communication, ...)
xlog("L_INFO", "Call control: internal server error\n");
acc_rad_request("500");
sl_send_reply("500", "Internal server error");
exit;
}

if($var(setprofile) > 0)
{
create_dialog();
set_dlg_profile("caller","$avp(s:caller_uuid)");
}

## mark checking done
setflag(31);
}
}
אני מצטער על הדוגמה שלא ממחישה - אני עובד בתחום ואני לא רוצה אפילו בטעות לפגוע בזכויות של מישהוא.

הדוגמה מראה שימוש רגיל בcall control , עבור ביצוע עבודה לתשלום מראש. יש להוסיף את ביצוע החיוב להתחלת שיחה (אם קיים חוק בחיובים אצלכם לזה). חיוב זה צריך להתבצע או בזמן register יומי (כלומר פתחת את המכשיר ליום). או לאחר ה183 (אחרי early media). נקודה חשובה היא לשכוח להפסיק חיוב כאשר השיחה עברה למרכזיה:
אני מחייג למרכזיה ,
מחייג למישהוא אחר.
מנתק את השיחה.
שומע את ההודעות בתא קולי בתוך המרכזיה.
מחייג שוב לאדם אחר.

יש לשים לב שמצב כזה החיוב צריך להיות :
התחברות למרכזיה פעם אחת.
חיוג לאדם א' (וזמן שימוש)
חיוג לאדם ב' (וזמן שימוש)

צורה כזאת של חיוב קל לממש במודול חיצוני מאשר cdrtool (במידה והמרכזיה מחוץ לשליטה).

ביצוע חיוב להתחברות יכול להתבצע בשימוש בfreeradius.

נקודה מאוד חשובה -
החיוב צריך להתבצע בנקודה הראשונה (מפני שאם יש חיוב בפרוקסי זה לא חייב לעבור דרכו).
אמנם יש בעייה במימוש זה כאשר מדובר בעבודה על גבי LBים , אבל זה שווה את המאמץ (כמות השגיאות יורדת פלאים ).

אמנם זה נתן לנו מגבלת זמן עבור משתמש בודד (בהתאם לballance שלו). ישנם מספר גישות שאני מכיר לחיוב הballance של לקוח:
בתחילת ביצוע הפעולה (תשלום מראש עבור X שניות) - ואז להשאיר לcdrtool לבדוק אם השיחה יכולה להמשיך (לפני ניתוק בדיקה עם יש עוד יחדת מנייה אם לא ניתוק + זיכוי חלק יחסי).

אחרי ביצוע הפעולה.

חיוב על כל אירוע (CDR , רדיוס , MSG , זמן שימוש).

הנקודה החשובה ביותר שאני למדתי בפיתוח של מערכות בילינג היא קודם כל לא ! , אחרי זה לחייב , ואם שגויי להסיר חיוב.

במידה ולא מדובר במערכות חיצוניות (חיוב לא בזמן אמת - paypal), הבעיה פותרת כל מני מתחכמים (לבצע צילצול ניתוק בשביל להמנע מחיוב , לשלוח הודעה ולהתנתק לפני קבלת אישור). אני רוצה להאמין שדברים אלו הם באמת שגיאות משתמש.
אבל משום מה אני מתחיל לחשוד כשזה קורה יותר מדי פעמים.

למעשה גישה זו של חיוב ראשוני שוות ערך לעבודה באספנאות - קודם כל לא אחרי זה מה אתה רוצה. כלומר במצב שגיאה אתה קודם כל מפיל את הפעולה (או מחייב).

בפוסט הבא (שאני עובד עליו) אני אראה דוגמאות בילינג רגיל (לתשלום מראש).

אין תגובות:

הוסף רשומת תגובה