如何通过 HTML 创建图片以创建动态复合信息卡

RCS Business 中功能最强大、用途最广的内容之一 消息功能就像复合信息卡。 利用复合搜索卡,您可以在一个 消息,包括图片或视频、标题、说明,最多四条 建议的回复或操作。

独立的复合信息卡和复合信息卡轮播界面具有强大的功能, 可帮助您为用户打造富有吸引力的体验。只要 优惠券或产品等静态图片。但 如果您需要根据用户的相关信息发送动态内容, 像登机牌?

在本文档中,我将向大家展示如何使用 HTML 实时创建图片, 将这些图片嵌入到代理发送的复合搜索卡中了解如何转换 将 HTML 转换为图片

从 HTML 到图片

HTML 非常适合对文字和媒体进行组合布局。作为开发者,如果 我们需要构建一个产品来向用户发送登机牌、数据 或任何其他类型的用户特定信息 可能是我们要用到的工具RCS Business Messaging 的丰富功能 卡片仅支持图片和视频媒体类型,因此为了使用 使用 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 来生成如下所示的登机牌 图片。

登机牌示例

有多种方法可以实现此目标,但我们将定义一个网址端点 (在名为 /getTicket?msisdn=+12223334444 的 Node.js 应用中,用于呈现 HTML) 我们需要使用 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 火车票。

<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
});

将文件存储到可公开访问的网址

为了利用 WebView 生成的图片,我们需要一个可以公开访问的 网址。如果是在专用网络服务器上生成图片 将文件保存到公共文件夹中,但在本示例中,我们要上传 将文件保存到 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 filename
    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 发送复合信息卡,我使用的是 第一个代理示例

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 代理。

祝您好运,编程愉快!