Manual Implementation
Overview
This page describes manual implementation without the SDK, the authentication mechanism (launch URL, payload, canonicalization, signature), and a signature example.
If you wish to integrate myFlowpay without using the SDK, you must implement several key aspects yourself to ensure a secure and robust connection. Specifically, you are responsible for:
- Payload Canonicalization: Build a function to transform your login payload to a canonical JSON string, following the canonicalization rules strictly (correct property order, formatting, etc.).
- Signature Generation: Create Base64URL-encoded HMAC-SHA256 signatures for the canonicalized payload using your partner shared secret. Never expose your shared secret in client-side code; always sign payloads on your server and transmit only the final signature to the frontend.
- Message Envelope Construction: Format all messages to match the required structure (see Message Protocol), including channel, version, event, payload, signature, and meta fields.
- Event Handling: Implement
window.addEventListener("message", ...)handlers to process all incoming events from the iframe and send required host-initiated events (e.g., fp:LOGIN, fp:LOGOUT) to the embedded app. - Session Lifecycle Management: Detect and respond to session lifecycle events such as
fp:SESSION_EXPIRING, ensuring you refresh the session by sending a new signed payload before the JWT expires. See Communication for event details.
Recommended Steps:
- See Implementation with SDK for examples of payload sorting and Base64URL encoding.
- Review the Embed Sandbox App for complete sample code.
- Thoroughly test your implementation for all possible authentication and error cases.
Manually implementing the integration gives you maximum control, but requires careful adherence to protocol specifications and robust security practices.
Authentication flow
This section defines the secure authentication mechanism required to launch the embedded myFlowpay application from a partner's ("host") system. The authentication flow ensures that only verified partners can initiate sessions, that users are properly authorized and that all transmitted data maintains integrity and authenticity.
To establish trust between the host application and myFlowpay, the host must generate a signed launch payload containing information about the partner, merchant, user and optional activation metadata. This payload is cryptographically signed using a shared secret provided during onboarding. The embedded myFlowpay app validates this signature before granting access, guaranteeing that the session originates from an authorized host and has not been tampered with.
The following subsections describe how the launch URL is constructed, how the payload is structured and canonicalized, and how signatures are generated and validated. For session lifecycle (login, logout, token expiration), see Communication.
The embedded myFlowpay application is loaded via a fixed launch URL:
Each runtime environment includes its own configuration settings and is secured with separate credentials. As part of partner onboarding process we will provide you with YOUR_PARTNER_CODE and YOUR_PARTNER_SECRET for all environments.
After the iframe is loaded, the embedded app waits for the host application to provide authentication details using postMessage API. The host must send a signed payload identifying the partner, merchant, user, and optional metadata. A valid signature establishes trust and allows the embedded app to initiate a session.
Message Protocol
All communication between the host and embedded app uses a structured message envelope format sent via postMessage. Messages must conform to the following envelope structure:
{
"channel": "flowpay-embedded",
"version": "1.0",
"event": "fp:LOGIN",
"payload": "...",
"signature": "...",
"meta": {
"sentAt": "2025-09-21T10:00:00Z",
"reason": "initial"
}
}
Envelope Fields:
| Field | Type | Required | Description |
|---|---|---|---|
channel |
string | Yes | Must be "flowpay-embedded" |
version |
string | Yes | Protocol version, currently "1.0" |
event |
string | Yes | Event name (e.g., "fp:LOGIN", "fp:LOGOUT") |
payload |
varies | Depends on event | Event-specific payload data |
signature |
string | Depends on event | Base64URL-encoded signature (required for fp:LOGIN) |
meta |
object | Depends on event | Required for fp:LOGIN events (must include reason field). Optional for all other events. The reason field in meta differentiates between "initial" login and "refresh" (session refresh after fp:SESSION_EXPIRING) |
Example of the host app sending login parameters:
// Host App posting login message
document.getElementById("fp-embedded").contentWindow.postMessage(
{
channel: "flowpay-embedded",
version: "1.0",
event: "fp:LOGIN",
payload: PAYLOAD,
signature:
"e4c1621fb7598cb6d6f2d809f0a6552fe1863b452e52eb95acca6174fad23f3f",
meta: {
sentAt: "2025-09-21T10:00:00Z",
reason: "initial",
},
},
"https://my.flowpay.io"
);
Payload Structure
The launch payload contains all information required for myFlowpay to authenticate the session, identify the partner and merchant, and prefill user-related onboarding steps when available. After decoding, the payload must conform to a strict JSON structure to ensure consistent processing and signature validation.
{
"country": "CZ",
"createdAt": "2025-09-21T10:00:00Z",
"email": "info@flowpay.io",
"merchantId": "merchant-123",
"partnerCode": "YOUR_PARTNER_CODE",
"phone": "+420123456789",
"regNum": "12345678",
"tenants": [
{"id": "tenant-a", "name": "Tenant A"},
{"id": "tenant-b", "name": "Tenant B"}
],
"userId": "user-999"
}
The following defines the required structure and semantics of the decoded JSON payload:
| Attribute | Type / Constraints | Description |
|---|---|---|
partnerCode |
string | YOUR_PARTNER_CODE identifier assigned by Flowpay during onboarding. |
merchantId |
string, max 36 chars | Unique identifier of the merchant's legal entity in the partner's system. MUST be used in business data exchanged for scoring. |
tenants |
array (optional) | Represents merchant branches (e-shops, restaurants, locations, etc.). Each item: • id (string, max 36 chars) – tenant identifier; MUST match transaction data. • name (string, max 36 chars, optional) – user-friendly display name. |
country |
string | ISO 3166-1 alpha-2 two-letter country code for the merchant's legal entity. |
regNum |
string, max 36 chars | Registration number / business identification of the merchant's legal entity. |
userId |
string, max 36 chars | Identifier of an authenticated end user in the host app. Host app MUST ensure the user is authorized for the merchant. |
email |
string, max 36 chars (optional) | If provided, the user does not need to enter an email during onboarding. |
phone |
string, max 36 chars (optional) | If provided, the user does not need to enter a phone number during onboarding. |
createdAt |
string | ISO 8601 timestamp indicating when the payload was generated. |
Canonicalization Rules
The payload MUST be canonicalized before JSON encoding, Base64URL encoding, and signing. The canonicalization process ensures deterministic signature generation regardless of the order fields are provided or how the JSON is formatted.
- Omission of optional fields
- Fields not present (e.g., no tenants) MUST be omitted entirely.
- Tenant ordering
- When tenants is present:
- Sort tenants lexicographically by id (ascending).
- The order MUST be reflected in the canonical JSON.
- When tenants is present:
- JSON canonicalization
- All JSON object properties MUST appear in alphabetical order of keys.
- No additional whitespace beyond standard JSON syntax, no newline at end, no whitespace.
- Arrays MUST preserve the sorted order defined above.
- Character constraints
- All string fields in the payload MUST be encoded using UTF-8.
- However, to ensure interoperability, deterministic canonicalization, and consistent matching with business data exchanged for scoring, the technical identifier fields (merchantId, tenants[].id and userId) fields MUST conform to strict constraints and contain only the following:
- Alphanumeric (ASCII, no accents, no whitespace - spaces, tabs, line breaks)
- The at sign (@) character; The caret (^) character; The dollar sign ($) character; The dot (.) character; The exclamation (!) character; The grave accent (`) character; The minus (-) character; The number sign (#) character; The plus (+) character; The single quote (') character; The tilde (~) character; The underscore (_) character.
- No additional characters are permitted outside this list.
Signature
A signature MUST be computed using:
where:
- payload is the exact canonicalized payload string,
- secret is the shared YOUR_PARTNER_SECRET provided by Flowpay during onboarding,
- Flowpay rejects any request with missing or malformed signature, expired signature (older than 5 minutes from
createdAtcompared to server time) or incorrect HMAC.
Signature example
Given configuration
and a launch payload
{
"country": "CZ",
"createdAt": "2025-09-21T10:00:00Z",
"email": "info@flowpay.io",
"merchantId": "merchant-123",
"partnerCode": "SomePartner",
"phone": "+420123456789",
"regNum": "12345678",
"tenants": [
{"id": "tenant-a", "name": "Tenant A"},
{"id": "tenant-b", "name": "Tenant B"}
],
"userId": "user-999"
}
the resulting signature is as follows