문서

라이브러리

워치 페이스와 데이터 필드

워치 페이스는 화면에서 버튼 입력을 받거나 네트워크에 연결할 수 없습니다. 그래서 라이브러리가 백그라운드에서 서버에 확인하고, 워치 페이스는 원하는 위치에 QR 코드를 그리며, Garmin의 로그인 알림으로 구매자가 스캔 없이 결제할 수 있습니다. 데이터 필드도 같은 방식입니다.

작동 방식

  • 백그라운드가 묻습니다. 워치 페이스의 백그라운드 서비스가 서버가 알려 준 시각에 앱과 같은 요청을 서버로 보냅니다.
  • 시간은 항상 위에 보입니다. 워치 페이스에서 시간 보기는 기본 기능이므로 Garmin은 그 위에 결제 벽을 두지 말라고 권합니다. 잠겨 있는 동안 워치 페이스는 원하는 위치에 QR 코드를 그립니다. 데이터 필드는 자기 영역 안에 그립니다.
  • 링크는 설정에 있습니다. 워치 페이스는 구매 링크를 설정에도 적어 두며, 휴대폰의 Connect IQ 앱이 이를 보여 줍니다. 구매자는 스캔 없이 거기서 열 수 있습니다.
  • 알림으로 스캔을 건너뜁니다. 워치 페이스가 잠기고 휴대폰이 연결되면 Garmin의 로그인 알림을 보냅니다. 구매자가 탭해서 결제하면 몇 초 안에 워치 페이스가 잠금 해제됩니다.

워치 페이스나 데이터 필드에 추가하기

워치 페이스와 데이터 필드는 lib/watch/face만 씁니다: PayFace.mc와 PayFaceScope.mc.

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/face
manifest.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); }

잠긴 동안 위에 시간, 그 아래에 코드가 있는 전체 워치 페이스:

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>

코드 그리기

  • Paywall.drawQr(dc, x, y, side)는 흰 사각형 위에 너비 side로 코드를 그리며, 중심은 x, y입니다. 첫 응답 전에는 아무것도 그리지 않습니다.
  • !Paywall.unlocked()인 동안에만 호출하세요.
  • 화면이 완전히 켜졌을 때만 그리고, AMOLED 시계의 상시 표시 모드에서는 절대 그리지 마세요.

Garmin 로그인 알림

  • 보내는 때: 확인 결과 워치 페이스가 처음 잠긴 것으로 나올 때(체험 종료 또는 체험 없음) 한 번. 잠긴 동안 구매자가 워치 페이스 설정을 저장할 때마다 다시. 휴대폰이 연결된 동안에만 보냅니다. Wi-Fi가 아니라 휴대폰 자체가 필요합니다.
  • 구매자에게 보이는 것: 휴대폰에 뜨는 Garmin 자체 알림입니다. 문구("<app> needs you to sign in")는 Garmin이 정하며 어떤 앱도 바꿀 수 없습니다. 탭하면 Garmin Connect 자체 브라우저에서 결제 페이지가 열립니다.
  • 결제 후: 페이지가 끝나고, 휴대폰이 결과를 시계에 넘기면 워치 페이스의 백그라운드가 서버에 묻습니다. 누구나 그 주소를 입력할 수 있으므로 결과만으로는 아무것도 잠금 해제되지 않습니다. 서버의 응답만이 잠금을 해제합니다.
  • 실수로 두 번 보내지 않습니다: 워치 페이스가 곧바로 실행되지 않아도 백그라운드가 직접 전송됨으로 표시합니다(CIQ 3.2 이상). 보낼 수 없는 시계에서도 QR 코드와 설정 링크는 작동합니다.

앱은 보내지 않습니다. 앱의 구매 화면은 이미 결제 후 약 1초 만에 잠금 해제됩니다.

잠금 해제에 걸리는 시간

서버는 시계에 먼저 연결할 수 없습니다. 워치 페이스는 다음 확인 때에야 결제를 알게 되며, Garmin은 백그라운드 확인을 최대 5분에 한 번만 허용합니다.

구매자의 결제 방법워치 페이스 잠금 해제
로그인 알림을 탭함몇 초 안에
설치 또는 체험 종료 후 2일 안에 코드를 스캔했거나 설정 링크를 사용함10분 안에
같은 방식, 더 늦게1시간 안에
결제 후 휴대폰에서 워치 페이스 설정을 저장함Garmin이 허용하는 가장 빠른 확인 때: 빨라도 마지막 확인 5분 뒤
  • 결제 페이지가 열린 것을 확인하면 워치 페이스는 30분 동안 5분마다 확인합니다.
  • 체험 중에는 워치 페이스가 체험 종료 시점에, 또는 그보다 이르면 매일 확인합니다.
  • 확인에 실패하면(휴대폰 없음) 다음 확인은 1시간 뒤입니다.

주석과 범위

글랜스와 백그라운드 코드는 해당 주석이 달린 코드에만 접근할 수 있습니다. 라이브러리의 주석은 그대로 두고 내 코드도 맞추세요.

  • 워치 페이스와 데이터 필드: 샘플처럼 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 권한.
  • 앱 전용: Paywall.open(), 구매 화면과 그 문자열을 포함한 Pay.mc의 모든 것. 글랜스나 백그라운드 코드에서 절대 호출하지 마세요.
Esc