Skip to main content

Zapisanie dostępu

Tworzenie formularza dodawania dostępu

Szczegóły dostawcy pobrane przy pomocy GET /api/billers zawierają pole z listą dostępnych sposobów logowania - "credentialsForms".
Na ich podstawie należy stworzyć formularz dodawania dostawcy.

{
...
"credentialsForms": [
{
"formId": "DEFAULT_LOGIN_PASSWORD_FORM",
"name": {
"EN": "Login and password",
"PL": "Login i hasło"
},
"hint": {
"EN": "Podaj login i hasło, którymi logujesz się do Mój Orange",
"PL": "Enter login and password with which you log in to My Orange"
},
"fields": [
{
"key": "principal",
"name": {
"EN": "Login",
"PL": "Login"
},
"hint": null,
"type": "TEXT",
"required": true,
"encrypted": false
},
{
"key": "secret",
"name": {
"EN": "Password",
"PL": "Hasło"
},
"hint": null,
"type": "PASSWORD",
"required": true,
"encrypted": true
}
]
},
{
"formId": "PHONE_NUMBER",
"name": {
"EN": "Phone number",
"PL": "Numer telefonu"
},
"hint": "Podaj numer telefonu, którym logujesz się do Mój Orange",
"fields": [
{
"key": "phoneNumber",
"name": {
"EN": "Phone number",
"PL": "Numer telefonu"
},
"hint": {
"EN": "A one-time SMS code will be sent to the provided phone number",
"PL": "Na podany numer telefonu zostanie wysłany jednorazowy kod SMS"
},
"type": "TEL",
"required": true,
"encrypted": false
}
]
}
]
}
info

Obecnie dostępne są jedynie dwa sposoby logowania: Login i Hasło oraz Numer telefonu, ale możliwe jest dodanie kolejnych sposobów w przyszłości. Wszystkie potrzebne parametry potrzebne do zbudowania formularza są zwracane przez API, dzięki czemu możliwa jest implementacja dynamicznego budowania formularza, która nie będzie wymagać zmian po stronie front-endu w przypadku konieczności dodania nowego sposobu logowania.

Bazując na credentialsForms.*.fields można stworzyć pole wyboru lub radio buttony jak na poniższej makiecie:


Jeśli na liście jest tylko jeden sposób logowania, można nie wyświetlać pola wyboru/radio buttona.

Dla aktualnie wybranego sposobu logowania (domyślnie pierwszy z listy), należy wyświetlić kolejno pola formularza, wykorzystując do tego konfigurację pól opisaną w credentialsForms.*.fields.

Wysłanie formularza

W przypadku formularza w procesie tworzenia nowego dostawcy, po zaakceptowaniu przez użytkownika, należy wywołać usługę POST /api/accounts z body w formacie:

{
"billerId": "<billerId>", // id dostawcy
"consent": true,
"accountType": "DIRECT_SYNC",
"credentials": {
"formId": "<formId>", // id wybranego sposobu logowania
"fields": {
"<key>": "<value>" // wartości pól formularza pod odpowiednim kluczem,
// zaszyfrowane kluczem publicznym,
// jeśli encrypted == true dla danego pola
}
}
}

Przykłady

Parametry sposobu logowania: DEFAULT_LOGIN_PASSWORD_FORM
{
"formId": "DEFAULT_LOGIN_PASSWORD_FORM",
"name": {
"EN": "Login and password",
"PL": "Login i hasło"
},
"hint": {
"EN": "Podaj login i hasło, którymi logujesz się do Mój Orange",
"PL": "Enter login and password with which you log in to My Orange"
},
"fields": [
{
"key": "principal",
"name": {
"EN": "Login",
"PL": "Login"
},
"hint": null,
"type": "TEXT",
"required": true,
"encrypted": false
},
{
"key": "secret",
"name": {
"EN": "Password",
"PL": "Hasło"
},
"hint": null,
"type": "PASSWORD",
"required": true,
"encrypted": true
}
]
}
Przykładowa wartość przy wysłaniu formularza
{
"billerId": "PLUS",
"consent": true,
"accountType": "DIRECT_SYNC",
"credentials": {
"formId": "DEFAULT_LOGIN_PASSWORD_FORM",
"fields": {
"principal": "[email protected]",
"secret": "TQdOytI9F6OSLAm1C8WnTt7GKh+IawQyNHGrPNHRimPmZoApWHF3DKiBYQN4oZCRh43cnx1CtwMPJi2EXyEtshCBMadJZuxJN8Lo+auMMtrrKFS4f9eh3MNyn6Bb8q7lq9M1Lr8o8kfA5d1KIHHnS1ZtkAdNkbokEDKtOdVcXzNSznuNZgIUKE+BoqI/Uth2U3NOspLsODgqR4I20xm4uckc2U56ZQwgCcfL6VSSVz7JH4YUrbXNhaDiJVK+vfwlRjy4oRAhZFwgrFLr6TXz1wgSOqUxws/8k7RVBm5zcNEMj0epMQdtlT74orTAKijt+4kcEgqRkdzOw9HiAYQ0SYQK6kseVRF+JANhUCizNBw3puVi9cqx9CNL1WOmT0HqgwAmOmuUQD8wEdwcF5owNigQ1uid6t+rA8fFYe11ogcX1z1t2mayte0y99BzouiHLZYqVxBU9o7sinm27tJJ+lxHZ/UHI33bbpLwo81CPiu1ncfzhETtPi6RssHSR4Mx7JhcnR3UedHeHbdECBbTYk3BE+PMog3F+cNhsqnoAuRh/8sRr5zPAdcsbA+qVoEkN3xkFvBXlE1RG+GXVuzbiGs4cbJ/8Slmcl7diZlwvi8rrg/DQ68hHZpUUnwGlephtWdE7T8IdM8v45+ipzA3XGXrAosR4wsVak0XGKHhpaY="
}
}
}

Parametry sposobu logowania: PHONE_NUMBER
{
"formId": "PHONE_NUMBER",
"name": {
"EN": "Phone number",
"PL": "Numer telefonu"
},
"hint": "Podaj numer telefonu, którym logujesz się do Mój Orange",
"fields": [
{
"key": "phoneNumber",
"name": {
"EN": "Phone number",
"PL": "Numer telefonu"
},
"hint": {
"EN": "A one-time SMS code will be sent to the provided phone number",
"PL": "Na podany numer telefonu zostanie wysłany jednorazowy kod SMS"
},
"type": "TEL",
"required": true,
"encrypted": false
}
]
}
Przykładowa wartość przy wysłaniu formularza
{
"consent": true,
"accountType": "DIRECT_SYNC",
"billerId": "PLAY",
"credentials": {
"formId": "PHONE_NUMBER",
"fields": {
"phoneNumber": "+48 512 345 678"
}
}
}

Drugi etap logowania

Czasami logowanie odbywa się w dwóch etapach (np. podanie numeru telefonu + podanie kodu z SMS), dlatego po dodaniu dostępu należy oczekiwać na Webhook.
Jeśli do ukończenia konfiguracji dostawcy wymagane jest podanie dodatkowych informacji, np. kodu z SMS, to szczegóły konta zawierają pole "followUpCredentialsForm" z wartością "required" true.

{
...
"followUpCredentialsForm": {
"required": true,
"formId": "OTP",
"hint": {
"EN": "Enter the code you received",
"PL": "Podaj otrzymany kod"
},
"fields": [
{
"key": "otp",
"name": {
"EN": "SMS Code",
"PL": "Kod SMS"
},
"hint": {
"EN": "Enter received one-time SMS code. It may take a few moments for the code to be shipped.",
"PL": "Wpisz otrzymany jednorazowy kod SMS. Wysyłka kodu może potrwać kilka chwil."
},
"type": "TEXT",
"required": true,
"encrypted": false
}
],
"reset": {
"available": true,
"text": {
"EN": "Resend",
"PL": "Wyślij ponownie"
}
}
}
}

W wypadku skorzystania z opcji reset należy zlecić ponowną synchronizacje konta.

Jeśli, podanie hasła jednorazowego nie jest wymagane, "followUpCredentialsForm" wygląda następująco:

{
...
"followUpCredentialsForm": {
"required": false
}
}

Jeśli followUpCredentialsForm.required ma wartość true, to należy wyświetlić formularz dodatkowych danych dostępowych skonstruowany w oparciu o followUpCredentialsForm.fields, w sposób analogiczny do budowania standardowego formularza logowania.

Wysyłanie formularza

Wysłanie formularza z kodem jednorazowym odbywa się poprzez wywołanie usługi PUT /api/accounts/:accountId/follow-up-credential z body budowanym analogicznie jak w przypadku formularza edycji danych dostępowych:

{
"credentials": {
"formId": "<formId>", // wartość followUpCredentialsForm.formId
"fields": {
"<key>": "<value>" // wartości pól formularza pod odpowiednim kluczem
}
},
"encrypted": false
}

Przykłady

Konfiguracja formularza dodatkowych danych dostępowych
{
...
"followUpCredentialsForm": {
"required": true,
"formId": "OTP",
"hint": {
"EN": "Enter the code you received",
"PL": "Podaj otrzymany kod"
},
"fields": [
{
"key": "otp",
"name": {
"EN": "SMS Code",
"PL": "Kod SMS"
},
"hint": {
"EN": "Enter received one-time SMS code. It may take a few moments for the code to be shipped.",
"PL": "Wpisz otrzymany jednorazowy kod SMS. Wysyłka kodu może potrwać kilka chwil."
},
"type": "TEXT",
"required": true,
"encrypted": false
}
],
"reset": {
"available": true,
"text": {
"EN": "Resend",
"PL": "Wyślij ponownie"
}
}
}
}
Przykładowa wartość przy wysłaniu formularza
{
"credentials": {
"formId": "OTP",
"fields": {
"otp": "1234"
}
},
"encrypted": false
}

Istnieje również możliwość powrotu do pierwszego etapu uzupełniania danych dostępowych poprzez wywołanie usługi POST /api/accounts/:accountId/cancel-follow-up-credentials.

Szyfrowanie

Wartości CredentialsFormFields oznaczone jako encrypted należy zaszyfrować kluczem publicznym wykorzystując algorytm RSA-OAEP. Zaszyfrowane pole należy następnie zakodować do base64 i przekazać w formacie version:content, gdzie w miejsce version należy wstawić wersję klucza publicznego, którym zostało zaszyfrowane pole, a w miejsce content zaszyfrowaną treść pola w formacie base64.

v1:aHJ3V0hESld3TmpITmd3QXdJVmFyZzdSS0o2NHE5eVFrR3NsRVB3SElaenh5d3JEOFFEcVpOeXhycTJJbFJrckZiWUhSU29kK3krZitBMHpTcEw5bkJ0cy9CQ3NldnU1TVlhZFJhaXZiS2V3RDRwZis1WDZzSS80aThJVlFuQktxV1dSRm5mSmRpZVhNeGoxZUUyTkdjSzVtS1phaW9uY0tCNFpObWl0N2drOWNRNmF6d3VGUDN5OWJTSlJIMGxvY3BKLzdNL3BCL3NSdFdPVzZ4RjBRNWsvTFNKbnl5Mk1tdkdrZGkremhBV25FVUxtSnVacE5SQkFmVkpzWUdkN2RMejBaQVhnZWI4cnhiUDY1cXNDZUhtTTFUb0U5SDhseFZML0lUd25ZMkl5R0xwb0pyYVh4NkZPTlBmZUxBN2lJNHR6M2NQcWwrUkJnZ2tDY3pSUzVoNXBKemJRYUZBclNjYTVyWFlQR0lYVWh6Q200OTE3amJRVWRMVFMwNlZKclNsaGRXMTl5Tjl6ckNkNFRDMFBPZmRUVlZIRG5JUUIySVJxdlRJQVM2MkQ4N2QvN0hnOHhpVjQ5TmtUNXo0QWM0ZUZZSk5DN2RFNHpmOThrbHV0T0J6ZHhMbFkzVG5naDVzbG9QQzU2SlJUancvYlZveGZ6NURjbjF3M3JURXFqT3MxdWZIVkJ6RGZsOGlxVVpBcUc5Y2lzZHc0UnRYQkJDdmV6QzRCWkt1TTllZklGdVVsL1VKelhCNWUzUVpBN0VMS0JidHlPem9BdkxvUnNLQlUzS3ZhelZGWTkvc3dHQ20xVW5sVmtHczdha2o5ZTZwOWhOd1dGZlpFY0hDMklxTkhPWTM1WTd6Mk9LUlp3Rk9mcU8zSUpqZERZY0hCSmlidWs1VlVNY1E9

W aplikacji web można wykorzystać do tego skrypt encryption.js

import { encryptWithKey, importPublicKey } from 'encryption.js';
...
const publicKey = await fetch(BASE_URL + '/api/public-keys/encryption')
.then(response => response.json())
.then(importPublicKey)
const encryptedSecret = await encryptWithKey(secret, publicKey)

Szyfrowanie hasła po stronie klienta

W typowym scenariuszu, użytkownik wpisuje dane do logowania w aplikacji web lub mobilnej, następnie te dane przekazywane są do backendu Systemu Klienta i dalej do Bill Presentment. Po stronie Klienta może pojawić się wymaganie, aby backend Systemu Klienta nigdy nie był "w posiadaniu" niezaszyfrowanego hasła. W takim przypadku możliwe jest zaimplementowanie szyfrowania asymetrycznego w przeglądarce lub aplikacji mobilnej z wykorzystaniem klucza publicznego Bill Presentment.

Pobranie klucza publicznego

Request
GET /api/public-keys/encryption HTTP/1.1
Host: <api_host>
Authorization: Bearer <auth_token>
Response
{
"version": "v1",
"key": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwH+lDJP0o3qxWNR6L6uY\nYpwXt7bEY6XIIt7ZTOK1wwgpFjhYAaTzZAbPodCWFQ9cSipliQLEBER9Q3qwnUnr\nUrn1ZEuKjC4kCNcZfHpXSzD9RnfTz2YDsB0JIpagblcpVlLXtE5ycLgB+D2DYSEU\n5yZSpHqYAmKCJyE7VtA4H9Ae3Fr7yOYQ2ySMmUwzIocx3HMxJhpkKj96RMvVOkg+\nd58DNQWAtjyaBV0X+9cMP15CrzntfB88f8O81/tGowAds21a/nYoAS4WdB77p7wR\n7PqvC6lyaxAdspUkcWUPOpyyxiHU2f86bwbwN7/gs+q5kDKxnnR1+b7QyofkzZWl\nBDdse+8IKliyE13rV4zjrT/i75YE2M03Qb47mYb6UcJ1s9Pye/7JCNa/gudLjxYw\nmGeSfIGVTSnSE/lBScfLkSToUT7rS0SnHZW5SHAsfZTmkk9tEX2MmfAQP4XxWw4O\nUJd7u18heBjex+kCt/N/cK7t7aecRsS+QbqeMg5agCLfx9ZEV+iwVkpC4nDZvnHk\nlRsZrzN5KMtWQxMO65pIoZeHYCo5XLvn7HZHu3WHpSO1KkQiN4IoUliUDReLx1Wi\na0bJiQHzO5f7iYZwBTJPDRYeAB4BZ+C5VZpx8Jn10RnEyVf8jqWg5p9ROWT6OC3h\n4doRZdP12EGJo0TVds75eVECAwEAAQ==\n-----END PUBLIC KEY-----\n
"
}