如何在 HTML 中建立圖片,以便建立動態複合式資訊卡

RCS Business Messaging 最強大且功能多元的其中一種,就是複合式資訊卡。透過複合式資訊卡,您可以在單一訊息中傳送許多相關資訊,包括圖片或影片、標題、說明,以及最多 4 項建議的回覆或動作。

獨立複合式資訊卡和複合式資訊卡輪轉介面是強大的功能,可為使用者打造引人入勝的體驗。只要分享的靜態圖片 (例如優待券或產品) 需要分享,圖片素材資源就可派上用場。不過,如果您根據使用者的相關資訊傳送動態內容 (例如登機證) 會怎麼樣?

在本文中,我將示範如何使用 HTML 即時建立圖片,並將這些圖片嵌入服務專員發送的複合式資訊卡。首先,讓我們來瞭解如何將 HTML 轉換為圖片。

從 HTML 到圖片

HTML 非常適合用來結合文字和媒體。開發人員如果想建立產品,以便傳送登機證、資料使用圖表或任何其他類型使用者專屬資訊,就必須使用動態產生的 HTML 程式碼。在 RCS Business Messaging 中,複合式資訊卡僅支援圖片和影片媒體類型,因此如要使用 HTML 的動態內容產生功能,HTML 必須先轉換為圖片。

幸運的是,大多數現代程式設計語言都支援程式庫,用於擷取能夠轉譯至少基本 HTML (例如 JEditorPane) 的網頁或元件,用來產生圖片。

你也可以使用 API 拍照。舉例來說,Google 的 Page Insights API 可根據網址自動產生螢幕截圖。

例子:

https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=https://www.google.com&screenshot=true

後續我們會使用 Node.js Express 應用程式,產生含有 HTML 的使用者專屬登機證,接著將圖片轉換為圖片、將其上傳至可公開存取的網址,然後在複合式資訊卡中附加該圖片,並傳送給使用者。

建立動態登機證

首先,我們需要的 HTML 產生登機證,如下圖所示。

登機證範例

有許多方法可以完成此操作,但我們會在名為 /getTicket?msisdn=+12223334444 的 Node.js 應用程式中定義網址端點,透過這個端點轉譯使用 EJS 檢視引擎所需的登機證。

假設有一個名為 getUserTicket 的函式,會擷取使用者的電話號碼,並傳回包含出發時間、座位、票券類型、起點等資訊等資訊的票券物件。

在 Express 應用程式的路由器中,我們會定義 getTicket 端點、呼叫 getUserTicket 函式,並將票證傳送至 EJS 範本。

router.get('/getTicket', function(req, res, next) {
    // Get the passed in phone number
    let msisdn = req.body.msisdn;

    // Get the ticket object for this user
    let ticket = getUserTicket(msisdn);

    // Render the ticket in HTML using an EJS template
    res.render('ticket', {ticket: ticket});
});

票證 EJS 範本定義下列 HTML,以轉譯 Bonjour Rail 票證範例。

<div>
  <div>
    <div class="left"><img width="200" src="/images/bonjour-rail-logo.png" /></div>
    <div class="right muted-text"><%= ticket.dateOfDeparture; %></div>
    <div class="cl"></div>
  </div>
  <div>
    <div class="left highlighted-text-color"><h2><%= ticket.startingLocation.city %></h2><br/><%= ticket.startingLocation.station %></div>
    <div class="right highlighted-text-color"><h2><%= ticket.endingLocation.city %></h2><br/><%= ticket.endingLocation.station %></div>
    <div class="cl"></div>
  </div>

  <div>
    <div class="left">
        <h3>PLATFORM <%= ticket.platform %></h3>
      <div>
        <div class="left">
          <div><h4>DEPART</h4></div>
          <div><%= ticket.departureTime %></div>
        </div>
        <div class="left">
          <div><h4>ARRIVE</h4></div>
          <div><%= ticket.arrivalTime %></div>
        </div>
        <div class="cl"></div>
      </div>
      <div>
        <div class="left">
          <div><h4>TICKET TYPE</h4></div>
          <div><%= ticket.ticketType %></div>
        </div>
        <div class="left">
          <div><h4>SEAT</h4></div>
          <div><%= ticket.seat %></div>
        </div>
        <div class="cl"></div>
      </div>
    </div>
    <div class="right">
      <img src="<%= ticket.qrCode %>" width="170" />
    </div>
    <div class="cl"></div>
  </div>
</div>

透過 HTML 建立圖片

我們已定義 HTML 來建構登機證,但需要將圖片轉換成圖片。

我們提供許多開放原始碼 Node.js 模組,可將原始 HTML 和網址轉換為圖片。在這個範例中,我們要使用 node-webshot,這是 PhantomJS 的輕量包裝函式。

PhantomJS 是可編寫的無頭瀏覽器,可將 HTML 轉譯成圖片。由於 PhantomJS 需要使用 WebKit 才能轉譯,因此可以處理含有圖片、CSS 和 JavaScript 的複雜網頁。

安裝節點 Webshot (npm install --save node-webshot) 後,可以將 HTML 轉換為圖片,

var webshot = require('node-webshot');
let url = '/getTicket?msisdn=' + msisdn;
let htmlAsImageFileLocation = 'ticket.png';

// Define screenshot options
var options = {
      screenSize: {
            width: 550,
            height: 450
      },
      shotSize: {
            width: 550,
            height: 450
      },
      userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };

// Save html as an image
webshot(url, htmlAsImageFileLocation, options, function(err) {
  // TODO: Upload image to a publicly accessible URL
});

將檔案儲存至可公開存取的網址

如要使用 Webshot 產生的圖片,我們需要可公開存取的網址。如果您要在專屬的網路伺服器上產生圖片,可以將檔案儲存到公用資料夾,但在這個範例中,我們會將檔案上傳至 Google Cloud Storage

以下函式會使用本機圖片位置,並上傳至 Google Cloud Storage,傳回新建立的媒體連結。

function uploadImage(imageLocation) {
    const {Storage} = require('@google-cloud/storage');

    // Creates a client
    const storage = new Storage();

    // Define the Cloud storage location and file name
    const bucketName = 'sample-image-uploads';
    const yourFileDestination = 'uploaded-image.png';

    // Set the options for the upload to be readable by anyone
    const options = {
        destination: yourFileDestination,
        predefinedAcl: 'publicRead'
    };

    // Return a promise that includes the storage upload
    return new Promise(function(resolve, reject) {
        // Uploads a local file to the bucket
        storage.bucket(bucketName).upload(imageLocation, options)
            .then(results => {
                // Return the image URL
                resolve(results[0].metadata.mediaLink);
            }).catch(error => {
                reject(error);
            });
    });
}

接著,我們需要先將註解 TODO 取代為呼叫,才能使用這個 uploadImage 函式。

// Save html as image
webshot(url, htmlAsImageFileLocation, options, function(err) {
      let uploadRequest = uploadImage(filename);

      uploadRequest.then(function(imageUrl) {
         // TODO: Use the imageUrl in a rich card to send to the user
      });
});

傳送含有圖片的複合式資訊卡

即將完成。請完成最後一個步驟,定義 sendBoardingPass(imageUrl, msisdn) 函式,此函式會使用上一個步驟中建立的圖片建立 RBM 複合式資訊卡,並傳送給使用者。

如要透過 RBM 傳送複合式資訊卡,請使用第一個代理程式範例中相同的 Node.js SDK。

function sendBoardingPass(imageUrl, msisdn) {
    let title = 'Here is your boarding pass.';

    let suggestions = [
                {
                    reply: {
                        text: 'See more options',
                        postbackData: 'more_options',
                    }
                },
            ];

    let params = {
        messageText: title,
        msisdn: msisdn,
        imageUrl: imageUrl,
        suggestions: suggestions,
        height: 'TALL',
    };

    // Send the boarding pass
    rbmApiHelper.sendRichCard(params);
}

以下是最終結果的螢幕截圖。

複合式資訊卡中的動態圖片

總結與總結

如要建立更豐富的複合式資訊卡,最簡單的方法是使用動態 HTML,並將 HTML 轉換為圖片。大多數的現代程式設計語言都支援程式庫或 API,協助您完成轉換。您可能會需要調整圖片大小,以便找出符合自身需求的方法,但這是在 RBM 代理程式中建立更有說服力的絕佳方法。

祝您一切順利!