文档

库

给付费功能加锁

用 Paywall.gate 出售整个应用,或用 Paywall.start 出售部分功能,每个功能检查一次。本页列出库中的所有公开调用和常量,以及试用的工作方式。

整个应用还是部分功能

Paywall.gate(views)Paywall.start(views)
适用于整体付费的应用出售部分功能的应用
启动时,锁定状态以购买界面代替你的应用照常显示你的应用
试用期间照常显示你的应用照常显示你的应用
试用结束时每次启动都显示购买界面,标题为“试用结束”显示一次购买界面,标题为“试用结束”
在购买界面按 BACK退出应用进入你的应用
付款后按 BACK 或 START 打开你的视图按 BACK 或 START 进入你的应用
每个付费功能无需添加先检查 Paywall.unlocked()

两者接受的数组与你从 getInitialView() 返回的相同:一个视图,或一个视图及其委托。

给功能加锁

使用 start 时,在每个付费功能的入口处检查:按钮、菜单项或页面。

source/MainDelegate.mc
function onHistory() as Void {
    if (Paywall.unlocked()) {
        showHistory();
    } else {
        Paywall.open();
    }
}
  • 一把锁,全部打开。一次购买即可开启应用内所有付费功能。每个应用只有一个价格。
  • 在概览中,只能调用 active()、unlocked() 和 trialLeft()。购买界面仅限应用使用。
  • 只应向买家显示(试用期间不显示)的致谢小细节,请检查 Paywall.active()。

参考

除非表中另有说明,这里的所有内容都在 module Paywall 中(Pay.mc 以及你使用的 PayScope.mc)。

你调用的接口

调用返回值作用可用于
Paywall.gate(views)要返回的视图在 getInitialView() 中使用,适用于整体付费的应用。开始试用,按时询问服务器,锁定期间返回购买界面代替你的应用。付费后,按 BACK 或 START 打开你的视图。应用
Paywall.start(views)要返回的视图在 getInitialView() 中使用,适用于出售部分功能的应用。开始试用,按时询问服务器,并返回你的视图。试用结束时显示一次购买界面。应用
Paywall.unlocked()Boolean已付费,或处于试用期(包括试用开始前)。每个付费功能都用它检查。应用、概览
Paywall.active()Boolean已付费,且服务器在过去 30 天内确认过。试用期间为 false。超前 5 分钟以上的“已付费”时间戳(时钟被调回)不算数。应用、概览
Paywall.trialLeft()Number试用剩余的整天数,向上取整。永远不超过 TRIAL_DAYS。试用开始前为完整的 TRIAL_DAYS;试用结束后或没有试用时为 0。应用、概览
Paywall.open()PaywallView推入购买界面,或返回已显示的那个。用于付费功能的 else,以及设置中的“Premium”项。应用
Paywall.keys()Array你的“删除数据”必须保留的存储键:"pp"、"ts" 和 "te"。应用
Paywall.startTrial()Void旧调用。首次启动时开始限时试用;没有 TRIAL_DAYS 时不执行任何操作。gate 和 start 会调用它。应用
Paywall.launch()Void旧调用。到时间时询问服务器;如果手表时钟被调回,则立即询问。gate 和 start 会调用它。应用
Paywall.showOver()Void旧调用,从第一个界面的 onShow() 中调用。此后,在手表之外完成的购买会自动打开解锁界面;有试用时,会在试用结束时打开一次购买界面。gate 和 start 会替你完成这些。应用

由库自己调用

库会自己调用这些。不要在你的代码中调用。

函数作用
check()向服务器发送一个询问,从不同时发送两个。一分钟无应答的询问不再计入。
onAnswer(code, data)处理服务器的回复。只保留完整的应答,即带有版本和下次检查时间的应答。失败时设置“离线”或“稍后再试”,以及下次尝试前的等待时间。
take(d)保存应答、试用结束时间和“已付费”。购买到账时打开解锁界面。
first(views)gate 和 start 的共用部分。
close()离开购买界面:付费后(或 start 的试用结束界面之后)进入你的视图;在锁定的 gate 应用中则退出应用;或者回到调用 open() 的地方。
cheer()手表的成功提示音和振动(如果手表已开启)。

常量

常量值类型
K_ANS"pa"存储键:服务器的最后一次应答。
K_PAID"pp"存储键:服务器最后一次确认“已付费”的时间,以秒为单位。为空:未付费。
K_TRIAL"ts"存储键:试用结束时间。首次启动时设置,之后由服务器设置。
K_OVER"te"存储键:“试用结束”界面已显示。
STALE259200030 天的秒数:没有服务器新应答时,“已付费”的有效时长。
DAY86400一天的秒数。

模块变量

购买界面自身的状态。需要时可以读取;切勿设置。

变量内容
listener已打开的购买界面,或 null。
status问题提示行(“离线”或“稍后再试”),或 null。
busy, sentAt有一个询问已发出,以及发出时间。
hold, held购买界面显示期间,服务器可保持询问的时长(起初 15 秒,如果手机提前中断则减半)。
changedAt, limit界面上次变化的时间,以及无变化时可保持打开的秒数。
fails, nextAt连续失败的询问次数,以及下一次可以发出的时间。
shown应用的第一个界面已显示:购买可能会自动打开解锁界面。
quick购买界面已打开:第一次询问会立即返回。
app, whole购买界面代替显示期间你的视图,以及是否使用了 gate。

类

类类型
PaywallView购买界面。它绘制服务器发来的界面并播放解锁动画。
PaywallDelegate购买界面的按键:START 和 BACK。
PayReply网络请求的回调对象。
PayBg仅限表盘和数据字段:向服务器询问的后台服务。

PaywallConfig

常量类型
URL必填。你的应用地址,来自控制台。
TRIAL_DAYS应用:可选,不设试用就省略。表盘和数据字段:必填,不设试用用 0。

表盘和数据字段

表盘和数据字段使用 lib/watch/face,其 module Paywall 有自己的调用。active()、unlocked() 和 trialLeft() 的用法同上。

调用作用
Paywall.startTrial()每次启动时从 getInitialView() 调用:首次调用时开始试用,并让已完成的登录页面唤醒后台。
Paywall.schedule(false)每次启动时从 getInitialView() 调用:预约下一次后台检查。
Paywall.take(d)从 onBackgroundData(d) 调用:保存后台的应答并预约下一次检查。
Paywall.soon()从 onSettingsChanged() 调用:在 Garmin 允许时尽快检查,锁定期间再次发送登录通知。
Paywall.drawQr(dc, x, y, side)在白色方块上绘制宽 side 的 QR 码,中心位于 x, y。收到第一次应答前不绘制。
Paywall.book(n)由库调用:预约一次后台检查,距上次不少于 5 分钟。
K_SIGN"pg":登录通知的存储键(1 为待发送,2 为已发送)。

完整设置见表盘和数据字段。

试用

  • 在 PaywallConfig 中设置 TRIAL_DAYS,与控制台中的免费试用一致。不设试用就省略:这样永远不会显示“试用结束”。
  • 试用在首次启动时开始。结束前 Paywall.unlocked() 一直为 true。
  • 重新安装不会重新开始试用。我们的服务器从第一次见到该手表时开始计算试用期,并在第一次应答时用它的计数替换手表上的计数。
  • 把时钟调回也无法延长。服务器发送的是剩余时间而不是日期,手表计算的天数也永远不会超过 TRIAL_DAYS。
  • 购买界面的标题依次显示“剩余 7 天”、“最后一天”、“试用结束”。

由应用计时的试用

如果按使用次数而不是天数试用,请省略 TRIAL_DAYS,在存储中保留你自己的计数器(“删除数据”时也要保留),并检查 active():

source/MainDelegate.mc
// 20 free sessions, then Premium
if (Paywall.active() || sessionsUsed < 20) {
    startSession();
} else {
    Paywall.open();
}

库存储的内容

  • 应用:"pa"(应答)、"pp"(上次确认“已付费”的时间)、"ts"(试用结束时间)和 "te"(已显示“试用结束”)。
  • 表盘和数据字段:"pa"、"pp"、"ts" 和 "pg",外加用于设置链接的 unlock 属性。
  • 你自己的键请使用其他名称。
Esc