复合信息卡是 RCS Business Messaging 中最强大、最多样化的内容类型之一。借助复合信息卡,您可以在一条消息中发送大量相关信息,包括图片或视频、标题、说明,以及最多四条建议的回复或操作。
独立复合信息卡和复合信息卡轮播界面是一种强大的功能,可帮助您为用户打造引人入胜的体验。只要您要分享的图片是静态图片(如优惠券或产品),这些广告就非常实用。但是,如果您需要根据用户的相关信息(例如登机牌)发送动态内容,该怎么办?
在本文中,我们将向您介绍如何使用 HTML 即时创建图片,以及如何将这些图片嵌入到代理发送的复合信息卡中。我们先来看看如何将 HTML 转换为图片。
从 HTML 到图片
HTML 非常适合布局文字和媒体。作为开发者,如果我们要构建一个产品来向用户发送登机牌、数据使用情况图表或任何其他类型的用户特定信息之类的内容,我们可能会使用动态生成的 HTML。在 RCS Business Messaging 中,复合信息卡仅支持图片和视频媒体类型,因此为了将 HTML 的强大功能用于生成动态内容,首先需要将 HTML 转换为图片。
幸运的是,大多数现代编程语言都支持用于截取网页或组件屏幕截图的网页库(例如 JEditorPane),您可以使用这些库生成图片。
还有一些 API 可用于拍摄网页照片。例如,Google 的 Insights API 可以通过网址自动生成屏幕截图。
例如:
https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=https://www.google.com&screenshot=true
接下来,我们使用 Node.js Express 应用通过 HTML 生成用户专用登机牌,将其转换为图片,将其上传到可公开访问的网址,然后将图片附加到复合信息卡中以发送给用户。
创建动态登机牌
首先,我们需要 HTML 生成如下所示的登机牌。
有多种方法可以实现这一点,但我们将在 Node.js 应用中定义一个名为 /getTicket?msisdn=+12223334444
的网址端点,以用于使用 EJS 视图引擎呈现登机牌所需的 HTML。
假设有一个名为 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 的复杂网页。
安装节点网络拍摄 (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
});
将文件存储到可公开访问的网址
为了使用通过网络拍摄生成的图片,我们需要一个可公开访问的网址。如果您要在专用网络服务器上生成图片,只需将文件保存到公共文件夹即可,但在此示例中,我们要将文件上传到 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 代理中制作更具吸引力的视觉效果的妙招。
祝您好运,编码愉快!