Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save petyagrill/f0d3d98191de95eb834b64aeba3b4a93 to your computer and use it in GitHub Desktop.
Save petyagrill/f0d3d98191de95eb834b64aeba3b4a93 to your computer and use it in GitHub Desktop.
Mono Corp API Proxy

Mono Corp API Proxy Protocol

This document describes the protocol of Mono Corp API Proxy (MCAP). This protocol is created for Mono PWA project.

Entities

  • Root: describes the publicly available URL path, which contains methods as subfolders;
  • Method: Named public command, the way to interact with MCAP for different actions. A simulated subfolder of Root;
  • Response: JSON marshaled output of Method with application/json Content-Type and 200 OK response code;
  • Error: A Response with an error key instead of the expected output. The key contains error description -> {"error": "description"};
  • Long-Polling: Keeping an HTTP request alive without outputting the response body until a trigger;
  • %METHOD% /%resource% Monobank Request: An HTTP %METHOD% (GET|POST|...) request to https://api.monobank.ua/%resource% -> POST /personal/auth/request Monobank Request. See Sending requests to Monobank;
  • Roll-In Token: A random string, which is paired with a Monobank Token Request ID;
  • Request Token: A random string, which is paired with a Monobank token and a roll-in token;
  • Private Key: An OpenSSL generated key, which was passed to Monobank team while Corporative API set up;
  • Public Key: A public key, which was extracted from the Private key;
  • Key-ID: Marshaled Public key representation, hashed with sha1 (in hex). Received from Monobank team.

Public Methods

The methods are placed in the auth lifecycle order:

Method Server action
check-proto Describes itself by telling name, author, protocol version, homepage and optionally setting a UI message
roll-in Creates a roll-in token
exchange-token Checks if there are available Monobank user tokens for current roll-in token, and if so, creates a pair request token and gives it
request Sends requests to Monobank

Every method should always return Access-Control-Allow-Origin: * header

Sending requests to Monobank

Note

Monobank API is sensible to HTTP method

Root

The Root for Monobank API is https://api.monobank.ua

Headers

Header Content Description
X-Time Unix timestamp php time()
X-Sign Sign See Signing the request
X-Key-Id Key-ID See Entities
X-Token Monobank token If present

Signing the request

Not to be confused with encryption

1. The ingredients

The signed string contains 3 ingredients:

  1. Timestamp from X-Time
  2. Monobank token
  3. Requested Monobank /%resource%

If it's an auth request to /personal/auth/request, token permissions from X-Permissions are being used instead of 2nd ingredient

2. Make the string to sign

The string contains all the ingredients concatenated together ($ing1.$ing2.$ing3 for PHP, ${ing1}${ing2}${ing3} or ing1+ing2+ing3 for JavaScript)

3. Create the sign

  1. Make a sign of the string, that corresponds to the OpenSSL signing
Property Value
Algorithm SHA256
Key Private Key
  1. Encode the sign to Base64

Examples

PHP
$key = openssl_get_privatekey("file://private.key", "");
    $str = $time.$t.$url;
    openssl_sign($str, $sig, $key, OPENSSL_ALGO_SHA256);
    openssl_free_key($key);
    return base64_encode($sig);
Python
import base64
import ecdsa
...
data = (timestamp + permissions + url).encode('utf-8')
sign = PrivateSigningKey.sign(data, hashfunc=hashlib.sha256)
signB64 = base64.b64encode(sign)
Go
See https://github.com/shal/mono

check-proto

Server action

Describes itself by telling name, author, protocol version, homepage and optionally setting a UI message

Response

All fields are required unless otherwise specified

{
    // Describes used MCAP protocol
  "proto": {
    "version": 1,
    "patch": 0
  },
    // Describes the implementation of protocol
  "implementation": {
    "name": "PHP Mono Corp API Proxy",
    "author": "Sominemo",
    "homepage": "https://github.com/Sominemo/Mono-Corp-API-Proxy-PHP"
  },
    // Describes the state of the running instance of this implementation
  "server": {
      // Tells the client to display a message to the user, optional
    "message": {
       // The text to display
      "text": "content",
       // Adds clickable URL at the end of text, optional
      "link": "https://example.com"
    }
  }
}

roll-in

Creates an auth request in Monobank, generates a paired roll-in token and returns both

User interacts with Monobank interface and confirms the auth request, then Monobank sends a request to a Webhook. More details in Getting the Monobank token.

Server actions

  1. POST /personal/auth/request Monobank request Headers(X-Callback: %webhook%; X-Permissions: %permissions%)
  • %webhook% is a public http resource to receive the resulting request from Monobank
  • %permissions%:
List of rights that the service wants to receive from the client (1 letter per 1 permission). List of possible rights:

s - statement (includes balance and statement itself)
p - Personal information (name and surname)

  1. Get Monobank Token Request ID %requestId% from the response {"tokenRequestId": "***"} and Auth URL %url% {"acceptUrl": "***"}
  2. Error, if the request went wrong
  3. Generate Roll-In token %token% and a random %proof% string for it, pair the token with Monobank Token Request ID
  4. Generate QR code from Auth URL (250px, e.g. using Google Charts API)
  5. Encode the QR to Base64 %qr%

Response

{
    "token": %token%,
    "requestId": %requestId%,
    "url": %url%,
    "qr": %qr%
}

Getting the Monobank token

  1. Set up an endpoint, that will receive a %proof% and %token% as GET parameters or in-uri (e.g. /webhook/%token%/%proof% or /webhook?token=%token%&proof=%proof%)
  2. Receive the Monobank User Token in X-Request-Id (can be also x-request-id) incoming header
  3. Check if %proof% and %token% from GET correspond each other, else Error
  4. Generate a Request Token, pair Roll-In and the Monobank User tokens with it
  5. Response 200 OK

exchange-token

Long-polling until received roll-in token won't get a corresponding request token or the request will timeout. Checks if there are available Monobank user tokens for current roll-in token, and if so, creates a pair request token and gives it

Server actions

  1. Receive an existing roll-in token from user
  2. Error, if the token does not exist
  3. Check if Request Token that corresponds to the Roll-In Token already exists
  4. If so, skip to authed
  5. Start Long-Polling until token receive. On trigger skip to authed
  6. If current Long-Polling session is out of time, %return_token% = false & Response (In this case client will send a request to this method again)
  7. Error, if current Roll-In Token is out of time
  • authed
  1. Discontinue & Unlink Roll-In token
  2. %return_token% = Request Token & Response

Response

{
    "token": %return_token%
}

request

This method is a synthetic path, which signs and redirects requests to Monobank. e.g. : POST /request/personal/auth/request turns to a Monobank request POST /personal/auth/request

Server actions

  1. Get Monobank token paired with Request token from X-Token incoming header, else Error
  2. Clone incoming headers %headers%
  3. Clone the raw HTTP request body (e.g. php://input)
  4. Remove Host header from the request (there also can be more inappropriate headers added by your HTTP server, such as SSL or GeoIp-Country-Code). Replace the original X-Token with paired Monobank token
  5. Send the request to Monobank with the same HTTM method as incoming request, get the answer
  6. Clone response headers and answer to output
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment