库
表盘和数据字段
表盘无法响应按键,也无法在前台联网。因此库会在后台向我们的服务器检查,你的表盘在你选择的位置绘制 QR 码,而 Garmin 的登录通知让买家无需扫码即可付款。数据字段同理。
工作原理
- 后台询问。表盘的后台服务在服务器指定的时间,向我们的服务器发送与应用相同的请求。
- 时间始终在最上层。对表盘来说,看时间是主要功能,Garmin 建议不要用付费墙挡住它。锁定时,表盘在你选择的位置绘制 QR 码。数据字段则在自己的区域内绘制。
- 链接在设置中。表盘还会把购买链接写入其设置,手机上的 Connect IQ 应用会显示它。买家可以直接在那里打开,无需扫码。
- 通知省去扫码。表盘锁定且手机已连接时,它会发送 Garmin 的登录通知。买家点开、付款,表盘几秒内即可解锁。
添加到表盘或数据字段
表盘和数据字段只使用 lib/watch/face:PayFace.mc 和 PayFaceScope.mc。
monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/facemanifest.xml
<iq:permissions>
<iq:uses-permission id="Background"/>
<iq:uses-permission id="Communications"/>
</iq:permissions>配置文件标注为 (:background),因为后台会读取它。请在其中保留 TRIAL_DAYS,不设试用时设为 0:表盘部分会直接读取它。
source/PaywallConfig.mc
// PaywallConfig.mc: from your dashboard (Trail Face). Public, not a secret.
import Toybox.Lang;
(:background)
module PaywallConfig {
const URL = "https://pay.example/api/K7Q2/c"; // your app's address
const TRIAL_DAYS = 7;
}钩子
| 位置 | 调用 |
|---|---|
getInitialView() | 每次启动时调用 Paywall.startTrial(); Paywall.schedule(false); |
getServiceDelegate() | return [new PayBg()]; |
onBackgroundData(data) | Paywall.take(data); |
onSettingsChanged() | Paywall.soon(); |
onUpdate(dc) | if (!Paywall.unlocked()) { Paywall.drawQr(dc, x, y, side); } |
一个完整的表盘,锁定时时间在上、QR 码在下:
source/PayFaceApp.mc
import Toybox.Application;
import Toybox.Background;
import Toybox.Graphics;
import Toybox.Lang;
import Toybox.System;
import Toybox.Time;
import Toybox.WatchUi;
// A small face for measuring: the time, and the QR code under it while locked.
(:background)
class PayFaceApp extends Application.AppBase {
function initialize() {
AppBase.initialize();
}
function onStart(state as Dictionary or Null) as Void {
}
function getInitialView() {
Paywall.startTrial();
Paywall.schedule(false);
return [new PayFaceView()];
}
function getServiceDelegate() {
return [new PayBg()];
}
function onBackgroundData(data) as Void {
Paywall.take(data);
}
// Saving the face's settings on the phone (the buy page suggests it after paying): ask now
// (5 minutes after the last check at the soonest, Garmin's rule).
function onSettingsChanged() as Void {
Paywall.soon();
}
}
class PayFaceView extends WatchUi.WatchFace {
function initialize() {
WatchFace.initialize();
}
function onUpdate(dc as Graphics.Dc) as Void {
var w = dc.getWidth();
var h = dc.getHeight();
var t = System.getClockTime();
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_BLACK);
dc.clear();
dc.drawText(w / 2, h * 30 / 100, Graphics.FONT_NUMBER_MEDIUM, t.hour.format("%02d") + ":" + t.min.format("%02d"),
Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER);
if (!Paywall.unlocked()) {
Paywall.drawQr(dc, w / 2, h * 68 / 100, w * 36 / 100);
}
}
}设置链接
添加一个只读的 unlock 属性。表盘会用服务器应答中的购买链接填入它。在你自己的资源中定义 UnlockTitle 字符串。
resources/settings/settings.xml
<resources>
<!-- The buy link, written by the face from the server's answer: the phone's Connect IQ app
shows it in this face's settings, so a buyer can open it without scanning. -->
<properties>
<property id="unlock" type="string"></property>
</properties>
<settings>
<setting propertyKey="@Properties.unlock" title="@Strings.UnlockTitle">
<settingConfig type="alphaNumeric" readonly="true"/>
</setting>
</settings>
</resources>绘制 QR 码
Paywall.drawQr(dc, x, y, side)在白色方块上绘制宽side的 QR 码,中心位于x,y。收到第一次应答前不绘制任何内容。- 只在
!Paywall.unlocked()时调用。 - 只在屏幕完全点亮时绘制,切勿在 AMOLED 手表的常亮模式下绘制。
Garmin 的登录通知
- 发送时机:检查首次发现表盘处于锁定状态时(试用结束或没有试用)发送一次。表盘锁定期间,买家每次保存表盘设置时会再次发送。仅在手机已连接时发送:它需要手机本身,而不是 Wi-Fi。
- 买家看到的:手机上 Garmin 自己的通知。文字由 Garmin 撰写(“<app> needs you to sign in”),任何应用都无法更改。点按后会在 Garmin Connect 自带的浏览器中打开你的结账页面。
- 付款之后:页面结束,手机把结果交给手表,表盘的后台向我们的服务器询问。仅凭结果不会解锁任何东西,因为任何人都能输入它的地址。只有我们服务器的应答才能解锁。
- 绝不会误发两次:后台会自行标记为已发送(CIQ 3.2 及更高版本),即使表盘之后没有马上运行。在无法发送的手表上,QR 码和设置链接仍然有效。
应用不发送它。应用的购买界面在付款约一秒后就已解锁。
解锁需要多久
我们的服务器无法主动联系手表。表盘只有在下次检查时才知道付款,而 Garmin 最多每 5 分钟允许一次后台检查。
| 买家的付款方式 | 表盘解锁 |
|---|---|
| 点按了登录通知 | 几秒内 |
| 在安装或试用结束后的 2 天内扫码或使用了设置链接 | 10 分钟内 |
| 同上,但稍晚 | 一小时内 |
| 付款后在手机上保存了表盘设置 | 在 Garmin 允许的最早一次检查时:距上次至少 5 分钟 |
- 一旦检查发现结账页面已打开,表盘会在半小时内每 5 分钟检查一次。
- 试用期间,表盘在试用结束时检查;如果每日检查更早,则每天检查。
- 检查失败(没有手机)后,下一次在一小时后。
注解与作用域
概览和后台代码只能访问为其加了注解的代码。保留库自带的注解,并让你自己的注解与之匹配。
- 表盘和数据字段:
PaywallConfig标注为(:background),你的AppBase类也一样(如示例所示):它的getServiceDelegate()在后台运行。PayBg和PayFaceScope.mc已加好注解。 - 带概览的应用:
glance/PayScope.mc和PaywallConfig标注为(:glance)。概览只能调用Paywall.active()、Paywall.unlocked()和Paywall.trialLeft(),不能调用其他内容。 - 自带后台服务的应用:
glance-bg/PayScope.mc、注解为(:glance, :background)的PaywallConfig,以及 Background 权限。 - 仅限应用:
Pay.mc中的所有内容,包括Paywall.open()、购买界面及其字符串。切勿在概览或后台代码中调用。