{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://contracts.futa.invalid/checkout-frame-message-v1",
  "title": "Hosted checkout frame message v1",
  "description": "What a payment's hosted checkout page tells the merchant page that frames it, through window.postMessage to the origin the payment's embedding names and never \"*\", or a mobile SDK's WebView, through the futaCheckout script message handler on iOS and the one message port the app hands it on Android (D-038). From the checkout to its host only: the checkout takes no command. Advisory: the merchant confirms a payment by its signed webhook or GET /v1/payments/{id}. A page posts ready once, and state once the page showing that state has rendered, from what the server rendered into it, inferring nothing. It never carries a capability, an address, a number, a participant, a method or an amount.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "type",
    "version",
    "event",
    "payment"
  ],
  "properties": {
    "type": {
      "const": "futa.checkout"
    },
    "version": {
      "const": 1
    },
    "event": {
      "description": "ready: the checkout's page loaded in its frame or WebView; state: the page shows this state.",
      "enum": [
        "ready",
        "state"
      ]
    },
    "payment": {
      "description": "The payment's id, as the merchant's API and webhooks name it; never its reference or its capability.",
      "type": "string",
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
    },
    "state": {
      "description": "The state the server rendered the page in: the payment's own, a payment whose methods are all unavailable for now reading CREATED, and a payment link's cancelled attempt CANCELLED.",
      "enum": [
        "CREATED",
        "PENDING_APPROVAL",
        "UNCERTAIN",
        "APPROVED",
        "DECLINED",
        "EXPIRED",
        "CANCELLED"
      ]
    },
    "final": {
      "description": "Whether the page leaves the payer nothing more to do or check for this payment: true once it is approved, or declined, expired or cancelled with no replacement offered and nothing it tells the payer to check first; false otherwise. Never true while the payment is open, waiting or uncertain.",
      "type": "boolean"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "event": {
            "const": "state"
          }
        }
      },
      "then": {
        "required": [
          "state",
          "final"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "event": {
            "const": "ready"
          }
        }
      },
      "then": {
        "properties": {
          "state": false,
          "final": false
        }
      }
    },
    {
      "if": {
        "required": [
          "state"
        ],
        "properties": {
          "state": {
            "enum": [
              "CREATED",
              "PENDING_APPROVAL",
              "UNCERTAIN"
            ]
          }
        }
      },
      "then": {
        "properties": {
          "final": {
            "const": false
          }
        }
      }
    }
  ]
}
