[料理佳餚] 用 LineBot 實現簡易的 IM 客服功能

看了董大偉老師的文章「關於LineBot (1) - 用c#建立一個LineBot」之後,我也來跟風一下,可是只有簡單的機器人回應有一點單調,憑藉著我以前在 CTI 領域的經驗,來實作一個簡易型的 IM 客服進線功能。

客服進線的流程大概是像下面這個樣子,有時候還會有滿意度調查,但是我們不必搞那麼複雜簡單做就好,所以省略這個部分。

-> 客戶 Call-In
-> 播放歡迎語音
-> 客戶依指示輸入資訊
-> 客服人員接起
-> 客服人員服務客戶
-> 掛斷

註冊 Line BOT API Trial Account

我就用 LineBot 來實作上面這樣子的一個進線流程的簡易版,首先要去註冊一個帳號,我們就去 BOT API Trial Account 這個地方註冊,順著註冊流程註冊完之後,我們就到 Line Business Center 就可以看到我們註冊成功的帳號。

點擊「使用」按鈕,我們就來到了 Line developers 平台,可以看到我們建好的 Channel,中間那個 QR Code 就是拿來加好友用的。

接收訊息

我們要接收訊息必須提供一個 Callback URL 讓 Line 來轉發訊息,我們可以從 API reference for BOT API 文件中 Receiving messages 這個區塊,來查看 Line 轉發過來的訊息 JSON 格式,知道會收到什麼樣的訊息之後,我們就寫一個 Web Api 來接收訊息。

[HttpPost]
public ActionResult Receive()
{
    string rawData = string.Empty;

    Request.InputStream.Seek(0, SeekOrigin.Begin);
    using (StreamReader sr = new StreamReader(Request.InputStream))
    {
        rawData = sr.ReadToEnd();
    }

    var results = JSON.DeserializeDynamic(rawData).result;

    return new HttpStatusCodeResult(HttpStatusCode.OK);
}

設定 Callback URL

在 Line developers 平台,點擊下面的 EDIT 按鈕就可以修改帳號資訊,我們就把做好的 Callback URL 填進去,而 Callback URL 一定要是 https://,接著按下 SAVE 就可以了,順便一提,Azure App Service 真是方便,預設就有 https:// 可以用。

傳送訊息

客服人員透過 Web 來傳送訊息到 Line 給客戶,我們撰寫一個 SendMessage 方法來將訊息傳送到 Line。

private void SendMessage(string message, string customerId)
{
    XDocument xml = XDocument.Load(Server.MapPath("~/App_Data/confidential.xml"));

    RestClient restClient = new RestClient(@"https://trialbot-api.line.me/v1/events");
    RestRequest restRequest = new RestRequest(Method.POST);

    restRequest.AddHeader("Content-Type", "application/json; charser=UTF-8");
    restRequest.AddHeader("X-Line-ChannelID", xml.Root.Element("ChannelID").Value);
    restRequest.AddHeader("X-Line-ChannelSecret", xml.Root.Element("ChannelSecret").Value);
    restRequest.AddHeader("X-Line-Trusted-User-With-ACL", xml.Root.Element("ChannelMID").Value);

    restRequest.AddJsonBody(new
    {
        to = new[] { customerId },
        toChannel = 1383378250,
        eventType = "138311608800106203",
        content = new
        {
            contentType = 1,
            toType = 1,
            text = message
        }
    });

    var restResponse = restClient.Execute(restRequest);
}

實作客服進線流程的商業邏輯

既然是簡易的 IM 客服我就簡單寫,看到一堆 if...else... 請勿見怪。

if (customer == null)
{
    // 客戶不存在就建立客戶資料
    customer = this.CreateCustomer(customerId, xml);

    this.SendMessage("客人您好,請問該怎麼稱呼您呢?", customer.Attribute("Id").Value);
}
else if (customer.Attribute("FlowId").Value.Equals("0"))
{
    // 儲存客戶稱呼
    customer.Attribute("Name").Value = results[0].content.text;
    customer.Attribute("FlowId").Value = "1";

    this.SaveCustomers(xml);

    this.SendMessage(
        $"{customer.Attribute("Name").Value},您好!請問您住哪裡?",
        customer.Attribute("Id").Value);
}
else if (customer.Attribute("FlowId").Value.Equals("1"))
{
    // 儲存客戶居住地
    customer.Attribute("Place").Value = results[0].content.text;
    customer.Attribute("FlowId").Value = "2";

    this.SaveCustomers(xml);

    this.SendMessage(
        $"{customer.Attribute("Place").Value}的{customer.Attribute("Name").Value},您好!請問有什麼可以為您服務的嗎?",
        customer.Attribute("Id").Value);

    // 客服人員接起
    var customerServiceHub = GlobalHost.ConnectionManager.GetHubContext<CustomerServiceHub>();

    customerServiceHub.Clients.All.inbound(
        $"{customer.Attribute("Place").Value}的{customer.Attribute("Name").Value}來了,正在線上。",
        customer.Attribute("Id").Value);
}
else if (customer.Attribute("FlowId").Value.Equals("2"))
{
    var customerServiceHub = GlobalHost.ConnectionManager.GetHubContext<CustomerServiceHub>();

    if (text.StartsWith("再見", StringComparison.Ordinal))
    {
        // 客戶道再見
        customer.Attribute("FlowId").Value = "0";

        this.SaveCustomers(xml);

        customerServiceHub.Clients.All.chat(
            "客戶離開!",
            customer.Attribute("Id").Value,
            customer.Attribute("Place").Value,
            customer.Attribute("Name").Value);
    }
    else
    {
        // 客服人員與客戶溝通
        customerServiceHub.Clients.All.chat(
            text,
            customer.Attribute("Id").Value,
            customer.Attribute("Place").Value,
            customer.Attribute("Name").Value);
    }
}

實際來訂一個便當

參考資料

 < Source Code >

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學