Docs

La biblioteca

Añade la biblioteca

La biblioteca dibuja todas las pantallas de pago por ti. Tú añades sus carpetas, un permiso, un pequeño archivo de configuración y una línea de código.

Los archivos

Descarga la biblioteca desde la pestaña Instalar de tu app. Se descomprime en una carpeta wearcheckout.

RutaQué hace
lib/watch/app/Pay.mcApps: la consulta a nuestro servidor, la pantalla de compra dibujada a partir de la respuesta del servidor, su límite de tiempo y el desbloqueo con su tono y vibración.
lib/watch/glance/PayScope.mcactive(), unlocked() y trialLeft(), con la anotación (:glance): para apps sin servicio en segundo plano.
lib/watch/glance-bg/PayScope.mcLo mismo, con la anotación (:glance, :background): para apps con servicio en segundo plano. Usa exactamente uno de los dos.
lib/watch/face/PayFace.mc, PayFaceScope.mcEsferas y campos de datos: la consulta en segundo plano, drawQr y el enlace de los ajustes. Consulta Esferas y campos de datos.
lib/watch/extras/PayExtras.mcSolo si vendes Valoraciones y respuestas o usas una página de tienda: la petición de valoración, tus respuestas y la pantalla "¿Ya pagaste?". Consulta Extras en tu app. Los relojes anteriores a Connect IQ 3.1 la omiten.
lib/watch/export/PayExport.mcSolo si vendes Exportar al teléfono: los datos de tu app como hoja de cálculo, cifrados en el reloj, con su enlace enviado al teléfono del comprador.
lib/watch/feeds/PayFeeds.mcSolo si tu app usa fuentes de datos: clima, sol y luna, horarios de oración, mareas y más. Consulta Fuentes de datos.
lib/watch/resources/strings/pay.xmlLas 4 líneas que muestra la pantalla de compra sin el servidor, en inglés.
lib/watch/resources-<lang>/strings/pay.xmlLas mismas 4 líneas en los otros 7 idiomas.

Añádela a tu proyecto

Descomprime la biblioteca junto a la carpeta de tu app:

IntervalTimer/
    manifest.xml
    monkey.jungle
    resources/
    source/
        PaywallConfig.mc
wearcheckout/
    lib/watch/...

Luego añade sus carpetas a tu jungle:

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance
base.resourcePath = resources;../wearcheckout/lib/watch/resources
  • Solo rutas relativas. Un espacio en una ruta absoluta rompe el jungle.
  • O copia los archivos. Copiada en tus propias carpetas source y resources (y en cada carpeta resources-<lang>), la biblioteca no necesita ninguna línea en el jungle.
  • Sin anotaciones que configurar. Una sola compilación sirve para todos los relojes. La subpantalla del Instinct se detecta en tiempo de ejecución.

Con un servicio en segundo plano

Si tu app tiene su propio servicio en segundo plano, usa glance-bg en lugar de glance, anota PaywallConfig con (:glance, :background) y añade el permiso Background. Cualquier código (:background) hace que el compilador pida ese permiso; por eso hay dos versiones.

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance-bg

Permite la red

El reloj consulta a nuestro servidor a través de la conexión del teléfono, o por Wi-Fi en los relojes que lo tienen. Añade el permiso Communications:

manifest.xml
<iq:permissions>
    <iq:uses-permission id="Communications"/>
</iq:permissions>

PaywallConfig.mc

Descárgalo desde la pestaña Instalar de tu app: tiene la dirección real de tu app. La dirección es pública, no un secreto.

source/PaywallConfig.mc
// PaywallConfig.mc: from your dashboard (Interval Timer). Public, not a secret.
import Toybox.Lang;

(:glance)
module PaywallConfig {
    const URL = "https://pay.example/api/K7Q2/c";   // your app's address
    const TRIAL_DAYS = 7;
}
  • URL: la dirección de tu app. Todas las consultas van ahí.
  • TRIAL_DAYS: omítelo si no hay prueba. Mantenlo igual que la prueba de tu panel: el reloj nunca cuenta más días que TRIAL_DAYS.
  • La anotación corresponde al PayScope.mc que uses: (:glance), o (:glance, :background) con glance-bg.

La única línea

En getInitialView(), devuelve tus vistas a través de la biblioteca:

source/YourApp.mc
return Paywall.gate([new MainView(), new MainDelegate()]);   // the whole app is paid for
return Paywall.start([new MainView(), new MainDelegate()]);  // or: only some features are
  • gate inicia la prueba, consulta al servidor cuando toca y, mientras está bloqueada, muestra la pantalla de compra en lugar de tu app. BACK sale de la app. Una vez pagada, BACK o START abre tus propias vistas.
  • start abre tu app como siempre, con la pantalla de compra una vez cuando termina la prueba. Después, cada función de pago comprueba primero:
source/HistoryDelegate.mc
if (Paywall.unlocked()) { showHistory(); } else { Paywall.open(); }

Con cualquiera de las dos, una compra hecha en el teléfono con la pantalla de compra cerrada abre el desbloqueo por sí sola cuando el reloj se entera. Bloquear funciones de pago enumera todas las llamadas.

Un elemento Premium en tus ajustes

El elemento "Premium" de un menú de ajustes abre la pantalla de compra. Si ya hay una abierta, te lleva a esa: nunca hay una segunda.

source/SettingsDelegate.mc
Paywall.open();

Borrar datos

Si tu app tiene una opción "Borrar datos", conserva las claves que devuelve Paywall.keys(). El resto vuelve del servidor en el siguiente inicio.

source/SettingsDelegate.mc
// Delete data: everything except the payment keys
var st = Application.Storage;
var keep = Paywall.keys();
var saved = [];
for (var i = 0; i < keep.size(); i++) {
    saved.add(st.getValue(keep[i]));
}
st.clearValues();
for (var j = 0; j < keep.size(); j++) {
    if (saved[j] != null) {
        st.setValue(keep[j], saved[j]);
    }
}

Extras en tu app

Tres de los extras de pago necesitan su propia carpeta, así las apps sin ellos siguen siendo pequeñas. Estadísticas de relojes no necesita ninguna.

Valoraciones y respuestas, y "¿Ya pagaste?"

Añade la carpeta extras y actívala antes de esa única línea:

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance;../wearcheckout/lib/watch/extras
source/YourApp.mc
PayExtras.on();
return Paywall.gate([new MainView(), new MainDelegate()]);
  • La solicitud de reseña aparece el día 3, 7 o 14: las estrellas y luego un código QR que abre tu página en la tienda y una nota para ti.
  • Tu respuesta aparece una vez sobre tu app. En relojes pequeños, una respuesta larga ocupa dos pantallas: START muestra el resto.
  • "¿Ya pagaste?" muestra una vez el código de un reloj nuevo cuando su comprador pagó antes en tu página de tienda.
  • Sin la carpeta, los relojes de esa app no reciben la petición, tus respuestas esperan en el servidor y un comprador de tu página de tienda escanea la pantalla de compra normal. Los relojes anteriores a Connect IQ 3.1 también omiten la carpeta.

Exportar al teléfono

Añade la carpeta export, ofrece la exportación mientras PayExport.ready() sea true e iníciala con un método que devuelva una fila cada vez:

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance;../wearcheckout/lib/watch/export
source/ExportDelegate.mc
// Row 0 is the header; rows 1 to n are your data.
function row(i as Number) as Array {
    if (i == 0) { return ["Date", "Minutes"]; }
    var s = sessions[i - 1];
    return [s[:date], s[:minutes]];
}

if (PayExport.ready()) {
    PayExport.start(method(:row), sessions.size());
}
  • Los valores pueden ser texto, números, true o false, o null.
  • La biblioteca hace el resto: envía las partes cifradas y luego manda el enlace al teléfono del comprador como notificación de Garmin Connect. El comprador la toca y su teléfono abre la hoja de cálculo. START vuelve a enviar el enlace. El enlace necesita el teléfono del comprador conectado al reloj.
  • Las fórmulas nunca se ejecutan. Al texto que empieza por =, +, - o @ se le antepone un '.

Fuentes de datos

Añade la carpeta feeds y pide una fuente donde tu app la necesite. Tu método recibe el código HTTP y la respuesta:

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance;../wearcheckout/lib/watch/feeds
source/MainView.mc
PayFeeds.get("weather", {
    "lat" => lat, "lon" => lon,
    "tz" => System.getClockTime().timeZoneOffset
}, method(:onWeather));

function onWeather(code as Number, data as Dictionary or Null) as Void {
    if (code == 200) {
        temp = data["now"]["temp"];
        WatchUi.requestUpdate();
    }
}
  • Las fuentes: sol, luna, horarios de oración, reloj mundial, tipos de cambio, clima, alertas meteorológicas (EE. UU.), terremotos, auroras, mareas (EE. UU.) y festivos. Los parámetros y campos de cada una están en la página Fuentes de datos del panel, donde puedes probarlas.
  • Guardada en el reloj. Cada respuesta vale durante su ttl en segundos. Si vuelves a preguntar antes, por la misma fuente y casi el mismo lugar, la respuesta guardada vuelve al instante sin consultar.
  • Los lugares van en grados. Las horas llegan en segundos Unix y las unidades son métricas.
  • Muestra la atribución cuando la tarjeta de la fuente la pide, por ejemplo "Clima: MET Norway".
  • Otros códigos traen null: 403 significa que Extras está desactivado para esta app, 429 o 503 significa que lo intentes más tarde, y un código negativo es de Garmin (sin teléfono, sin red). Los relojes de prueba tienen todas las fuentes gratis.
  • Precio: 2 US$ por millón de peticiones de relojes en vivo, en tu factura mensual. Una respuesta guardada en el reloj no cuesta nada.

Estadísticas de relojes

Sin código: el modelo del reloj llega con cada consulta. Para ver también las versiones de tu app, añade una versión a PaywallConfig:

source/PaywallConfig.mc
const VERSION = "1.3";

Idiomas

La biblioteca habla inglés, alemán, francés, español, portugués, coreano y chino (simplificado y tradicional). Elige el idioma del propio reloj. Cualquier otro idioma recibe inglés.

  • Las pantallas vienen de nuestro servidor en el idioma del reloj, así que corregir un texto no requiere actualizar la app.
  • Solo 4 líneas viven en el reloj, para cuando aún no hay respuesta del servidor.
StringInglésCuándo aparece
PwWaitCargando…Antes de la primera respuesta
PwPhoneSin redSin teléfono, Bluetooth ni internet
PwBusyMás tardeEl servidor no respondió bien
PwBackBACK: cerrarSin ninguna respuesta que mostrar

Añade una línea al jungle por idioma. Pon primero tu propia carpeta; omite esa parte en los idiomas para los que tu app no tiene carpeta.

monkey.jungle
base.lang.deu = resources-deu;../wearcheckout/lib/watch/resources-deu
base.lang.fre = resources-fre;../wearcheckout/lib/watch/resources-fre
base.lang.spa = resources-spa;../wearcheckout/lib/watch/resources-spa
base.lang.por = resources-por;../wearcheckout/lib/watch/resources-por
base.lang.kor = resources-kor;../wearcheckout/lib/watch/resources-kor
base.lang.zhs = resources-zhs;../wearcheckout/lib/watch/resources-zhs
base.lang.zht = resources-zht;../wearcheckout/lib/watch/resources-zht

Qué comprobar

  • El texto con el nombre de tu app. Sin respuesta que mostrar, la pantalla de compra muestra tu texto AppName. Mantén ese texto en tus recursos.
  • Temporizadores. La pantalla de compra usa un temporizador, y PayExtras otro más. Los relojes permiten solo unos pocos, y "Too Many Timers" cierra la app: si la tuya ya usa dos o más, comprueba que no pasas del límite.
  • Pulsaciones largas. Mantener un botón demasiado tiempo abre el menú del propio reloj. La pantalla de compra solo reacciona a pulsaciones cortas.
  • Las llamadas antiguas siguen funcionando. Paywall.startTrial(); Paywall.launch(); en getInitialView(), y Paywall.showOver() en el onShow() de tu primera pantalla, hacen lo que gate y start hacen en una línea.
Esc