BOC follows OAuth 2.0 which is the industry standard for delegating authorization for accessing resources via HTTP. This enables giving access rights to services and accounts to an app without explicitly providing a password. Instead, a Subscription Id is handed to the app/service which represents the access rights for a particular resource for a prescribed amount of time.
Within banking context, this means that users have the granularity of choice in granting access to specific accounts for specific functions.
APIs called: POST Subscriptions, PATCH Subscriptions
Result: The Client acquires a Subscription ID
The client app should first call the create subscription API which will return the Subscription Id. Once we have the Subscription Id the client re-directs the user to their 1Bank login screen (browser re-direct/through application).
The user will be requested to login to 1Bank by supplying their User Name and password. Following they would then be requested to give authorization for what Accounts they would grant access and for the appropriate functionality. As part of this Authorization workflow the Client would be provided with a specific Temporary Authorization Code which is used to get an access token and then call PATCH subscription in order to activate the subscription.
The ‘Create Subscription’ process is described in the following sequence diagram:
The registration functionality outlined above is simulated within the Sandbox environment. In order to use it you will need to register as a developer. Similarly to the API-Store, you will need to log onto the portal and register your app. You may follow by subscribing to the required APIs you wish to use.
The client app should first call the initiate payment with the details of the payment including the amount and the beneficiary. The ordering account is optional and in case it is not provided the customer will be asked to select it when redirected to BOC. All kinds of transfers are supported by this set of APIs including transfers within BOC, SEPA and SWIFT. Once the payment is initiated a paymentId is returned which is passed as a query parameter when redirecting the user to BOC
The users will be requested to login to 1Bank by supplying a User Name and a password. They will then be requested to select an ordering account if it was not provided, review the payment details and confirm the payment. As part of this Authorization workflow the Client would be provided with a specific Temporary Authorization Code which is used to get an access token and then call the POST Execute Payment API to complete the payment.
Follow these steps to call Payments APIs.
Note, that the initiate payment API requires the Client to sign the payment payload with a Digital Certificate and provide it as a JWS. In sandbox an additional API is provided for simulating the API-Store signing functionality required for payments in order to assist the developers during implementation.
Your client secret will only be displayed once. If you forget or lose it, you can verify the secret to see if it's correct or reset it to get a new one. The verification screen will ask to enter the secret Id.
Below you can find the link to a test suite with the steps required to test the Creation of a Subscription ID APIs. It includes HTTP requests with sample headers and test data.
Postman is a free REST test tool; you can download the test suite from here: https://www.getpostman.com/
Save the content of the link below as a .json file and then import it in the tool as a test collection.
The rest of this document explains the steps implemented in the test suite. You can use this information as guidance for the logic you need to implement in your application to be able to create a subscription ID.
Before calling any of the APIs in the Accounts and Payments API families you must ensure that you follow the 'Create Subscription' process. BOC follows OAuth 2.0 which is the industry standard for delegating authorization for accessing resources via HTTP. This enables giving access rights to services and accounts to an app without explicitly providing a password. Instead, a Subscription Id is handed to the app/service which represents the access rights for a particular resource for a prescribed amount of time. Within banking context, this means that users have the granularity of choice in granting access to specific accounts for specific functions.
Steps for initiating and activating a subscription
In this step you use the TPP credentials to obtain the access token required to submit in each API call.
Call the POST /oauth2/token endpoint in the tppoauth2security API. The following parameters must be passed as headers in the HTTP request (Mandatory fields highlighted in Red).
curl --request POST \ --url https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/oauth2/token \ --header accept: application/json \ --header content-type: application/x-www-form-urlencoded \ --data grant_type=client_credentials&client_id={{your client id}}&client_secret={{your client secret}}&scope=TPPOAuth2Security
POSThttps://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/oauth2/token
{ "token_type": "bearer", "access_token": "6334262361656275", "expires_in": 3600, "consented_on": 1542264419, "scope": "TPPOAuth2Security", }
The access token received will be used in all the API calls.
2. Obtain a Subscription Id
The subscription Id will be used in all the API calls. The Subscription ID must be authorized in order to be used. For the POST subscription API you will need the Authorization Token from the previous call.
Variables
curl --request POST \ --url https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/subscriptions \--header Authorization: Bearer {{oauth_token}}\ --header Content-Type: application/json \ --header originUserId: {{userId}} \ --header timeStamp: {{$timestamp}} \ --header journeyId: {{$guid}} \ --header app_name: {{app-name}} \ --header Content-Type: application/json \ --data { "accounts": { "transactionHistory": true, "balance": true, "details": true, "checkFundsAvailability": true }, "payments": { "limit": 99999999, "currency": "EUR", "amount": 999999999 }
POSThttps://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/subscript...
{ "duration": { "startDate": "20/11/2017", "endDate": "20/11/2018" }, "subscriptionId": "Subid000001-1590333432791", "status": "inprogress", "description": "SUBSCRIPTION", "selectedAccounts": [], "accounts": { "transactionHistory": true, "balance": true, "details": true, "checkFundsAvailability": true }, "payments": { "limit": 99999999, "currency": "EUR", "amount": 999999999 } }
3. Select Accounts for the Subscription Id
After initiating the subscription the user needs to select the accounts to be used with this subscription and provide a consent. This can be done by redirecting the user to the below URL:
After entering the username=999999 and passcode=112233 we get the following screen.
After you select the accounts and provide your consent the user will be redirected back to your app’s redirect URL with the authorization code as a query parameter.
https://localhost/?https://localhost/?code= AAIB7CW9gOFNa6c3B5l9GsfSHT
4. Get second Access token for the update of subscription
Example Request
curl --request POST \ --url https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/oauth2/token \ --header accept: application/json \ --header content-type: application/x-www-form-urlencoded \ --data grant_type=authorization_code&client_id={{yourClientId}}&client_secret={(yourClientSecret}}&code= {{code from redirect}}&scope=UserOAuth2Security
{ "token_type": "bearer", "access_token": "6334262361656275", "expires_in": 3600, "consented_on": 1542264419, "scope": "UserOAuth2Security", }
5. Update Subscription Id
The last step is the activation of the subscription which is done by calling PATCH Subscription. Before calling it get the details of the subscription including the accounts as accepted by the user by calling the GET Subscription API and use the details when calling the PATCH API.
Example GET Subscription Request:
curl --location --request GET "https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/subscriptions/{{subscriptionId}}" \ --header "Authorization: Bearer {{oauth_code}}"\ --header "Content-Type: application/json" \ --header "journeyid: {{$guid}}" \ --header "originuserid: {{user_id}}" \ --header "timestamp: {{$timestamp}}" \
curl –-location --request PATCH
‘https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/subscriptions/{{subscriptionId}}’ \
--header ‘app_name: {{app-name}}’ \
--header ‘authorization: Bearer {{oauth_code}}’ \
--header ‘content-type: application/json’ \
--header ‘journeyid: {{$guid}}’ \
--header ‘originuserid: {{user_id}}’ \
--header ‘timestamp: {{$timestamp}}’ \
--data
‘{ "selectedAccounts":
[ {"accountId": "351012345671" },
{"accountId": "351092345672" }
],
"accounts": {
"transactionHistory": true,
"balance": true,
"details": true,
"checkFundsAvailability": true
},
"payments": {
"limit": 99999999,
"currency": "EUR",
"amount": 999999999
}’
1. Get Accounts for specific subscription IDs
curl --location --request GET "https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/accounts" --header "Content-Type: application/json" \ --header "Authorization: Bearer {{oauth_code}}"\ --header "subscriptionId: {{subscription_id}}" \ --header "originUserId: {{user_id}}" \ --header "timestamp: {{$timestamp}}" \
[ { "bankId": "12345671", "accountId": "351012345671", "accountAlias": "ANDREAS", "accountType": "CURRENT", "accountName": "ANDREAS MICHAEL", "IBAN": "CY11002003510000000012345671", "currency": "EUR", "infoTimeStamp": "1511779237", "interestRate": 0, "maturityDate": "19/11/2018", "lastPaymentDate": "19/11/2017", "nextPaymentDate": "19/12/2017", "remainingInstallments": 10, "balances": [] } ]
2. Get Accounts Details
curl --location --request GET "https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/accounts/{{account_number}}’ \ --header "Content-Type: application/json" \ --header "Authorization: Bearer {{oauth_code}}\ --header "subscriptionId: {{subscription_id}}" \ --header "originUserId: {{user_id}}" \ --header " timestamp: {{$timestamp}}" \
[ { "bankId": "12345671", "accountId": "351012345671", "accountAlias": "ANDREAS", "accountType": "CURRENT", "accountName": "ANDREAS MICHAEL", "IBAN": "CY11002003510000000012345671", "currency": "EUR", "infoTimeStamp": "1511779237", "interestRate": 0, "maturityDate": "19/11/2018", "lastPaymentDate": "19/11/2017", "nextPaymentDate": "19/12/2017", "remainingInstallments": 10, "balances": [ { "amount": 1000, "balanceType": "AVAILABLE" }, { "amount": 1000, "balanceType": "CURRENT" } ] } ]
3. Get Balances API
curl --location --request GET "https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/accounts/{{account_number}}/balance" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer {{oauth_code}}"\ --header "subscriptionId: {{subscription_id}}" \ --header "originUserId: {{user_id}}" \ --header "timestamp: {{$timestamp}}" \
[ { "bankId": "12345671", "accountId": "351012345671", "accountAlias": "ANDREAS", "accountType": "CURRENT", "accountName": "ANDREAS MICHAEL", "IBAN": "CY11002003510000000012345671", "currency": "EUR", "infoTimeStamp": "1511779237", "interestRate": 0, "maturityDate": "19/11/2018", "lastPaymentDate": "19/11/2017", "nextPaymentDate": "19/12/2017", "remainingInstallments": 10, "balances": [ { "amount": 1000, "balanceType": "AVAILABLE" }, { "amount": 1000, "balanceType": "CURRENT" } ] } ]
4. Get Account Statement API
curl --location --request GET "https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/accounts/{{account_number}}/statement?startDate=16/04/2020&endDate=16/04/2020&maxCount=0"\ --header "Content-Type: application/json" \ --header "Authorization: Bearer {{oauth_code}}"\ --header "subscriptionId: {{subscription_id}}" \ --header "originUserId: {{user_id}}" \ --header "timestamp: {{$timestamp}}" \
{ "account": { "bankId": "12345671", "accountId": "351012345671", "accountAlias": "ANDREAS", "accountType": "CURRENT", "accountName": "ANDREAS MICHAEL", "IBAN": "CY11002003510000000012345671", "currency": "EUR", "infoTimeStamp": "1511779237", "interestRate": 0, "maturityDate": "19/11/2018", "lastPaymentDate": "19/11/2017", "nextPaymentDate": "19/12/2017", "remainingInstallments": 10, "balances": [ { "amount": 1000, "balanceType": "AVAILABLE" }, { "amount": 1000, "balanceType": "CURRENT" } ] }, "transaction": [ { "id": "12345", "dcInd": "C", "transactionAmount": { "amount": 1000, "currency": "EUR" }, "description": "NEFT TRANSACTION", "postingDate": "20/11/2017", "valueDate": "25/11/2017", "transactionType": "NEFT", "merchant": { "name": "ANDREAS MICHAEL", "address": { "line1": "A-123", "line2": "APARTMENT", "line3": "STREET", "line4": "AREA", "city": "Nicosia", "postalcode": "CY-01", "state": "STATE", "country": "CYPRUS" } }, "terminalId": "12345" } ] }
APIs for different actions on Payments
1. Sign Request (JWS_Sign_Verify API)
curl --location --request POST "https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/jwssignverifyapi/sign" \ --header "Content-Type: application/json" \ --header "Content-Type: text/plain" \ --data-raw "{ "debtor": { "bankId": "", "accountId": "351012345671" }, "creditor": { "bankId": "CITIUS33", "accountId": "48193222324233" }, "transactionAmount": { "amount": 30, "currency": "EUR" }, "paymentDetails": "SWIFT Transfer" }"
Example Response { "payload": "eyAiZGVidG9yIjp7ICJiYW5rSWQiOiIiLCAiYWNjb3VudElkIjoiMzUxMDEyMzQ1NjcxIiB9LCAiY3JlZGl0b3IiOnsgImJhbmtJZCI6IkNJVElVUzMzIiwgImFjY291bnRJZCI6IjQ4MTkzMjIyMzI0MjMzIiB9LCAidHJhbnNhY3Rpb25BbW91bnQiOnsgImFtb3VudCI6MzAsICJjdXJyZW5jeSI6IkVVUiIgfSwgInBheW1lbnREZXRhaWxzIjoiU1dJRlQgVHJhbnNmZXIiIH0", "signatures": [ { "protected": "eyJhbGciOiJSUzI1NiJ9", "signature": "s9vy53hGobNDeuQGyQI1J4-Kopo7AsVPMNYuyku9PLV2UXSAzkEfPQQPHYsAHe4ZnArv06XDp2Qsnqti5v88IWIDQe1AlVmNLEiVmkIBwXjsSWcRaNqVPWVas70SuO6ddrqH1Vz_UbvBJD02e49iDhuuCnsKZYBU7jvo4o-JvHyWXneXFElQvXKSCA-iddaivXdKWEuv7R2pkDr3xOJKJ4xS8Ugt5vKUVWMVQhDK6fOfzh50VeCSxC0v-XByMC4wLZcb4HbPtH9YEtP0MqF_AkqFRGD8v5OBBYr6pQdQ7oBRe1N6a9UkAhG0UDrfZFPoD6m1Gbdd9__RspWOU7fMDA" } ] }
2. Initiate Payment
curl --location --request POST "https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/payments/initiate’\ --header "Content-Type: application/json" \ --header "lang: en" \ --header "Authorization: Bearer {{oauth_code}}\ --header "originUserId: {{user_id}}’ \ --header ‘timestamp: {{$timestamp}}’ \ --data-raw "{ "payload": "eyAiZGVidG9yIjp7ICJiYW5rSWQiOiIiLCAiYWNjb3VudElkIjoiMzUxMDEyMzQ1NjcxIiB9LCAiY3JlZGl0b3IiOnsgImJhbmtJZCI6IkNJVElVUzMzIiwgImFjY291bnRJZCI6IjQ4MTkzMjIyMzI0MjMzIiB9LCAidHJhbnNhY3Rpb25BbW91bnQiOnsgImFtb3VudCI6MzAsICJjdXJyZW5jeSI6IkVVUiIgfSwgInBheW1lbnREZXRhaWxzIjoiU1dJRlQgVHJhbnNmZXIiIH0", "signatures": [ { "protected": "eyJhbGciOiJSUzI1NiJ9", "signature": "s9vy53hGobNDeuQGyQI1J4-Kopo7AsVPMNYuyku9PLV2UXSAzkEfPQQPHYsAHe4ZnArv06XDp2Qsnqti5v88IWIDQe1AlVmNLEiVmkIBwXjsSWcRaNqVPWVas70SuO6ddrqH1Vz_UbvBJD02e49iDhuuCnsKZYBU7jvo4o-JvHyWXneXFElQvXKSCA-iddaivXdKWEuv7R2pkDr3xOJKJ4xS8Ugt5vKUVWMVQhDK6fOfzh50VeCSxC0v-XByMC4wLZcb4HbPtH9YEtP0MqF_AkqFRGD8v5OBBYr6pQdQ7oBRe1N6a9UkAhG0UDrfZFPoD6m1Gbdd9__RspWOU7fMDA" } ] }"
{ "authCodeNeeded": true, "payment": { "paymentId": "string_1590385634856", "transactionTime": "string", "status": { "code": "PNDG", "description": [ "Payment in pending status" ], "refNumber": "string" }, "debtor": { "bankId": "", "accountId": "351012345671" }, "creditor": { "bankId": "CITIUS33", "accountId": "48193222324233", "name": null, "address": null }, "transactionAmount": { "amount": 30, "currency": "EUR", "currencyRate": null }, "charges": null, "totalCharges": "string", "endToEndId": null, "paymentDetails": "SWIFT Transfer", "terminalId": null, "branch": null, "RUB": null, "executionDate": "25/05/2020", "valueDate": "25/05/2020", "totalDebitAmount": null, "attachments": null } }
3. Review The payment and Select Account:
https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/oauth2/authorize?response_type=code&redirect_uri={{yourAppRedirectionURL}}&scope=UserOAuth2Security&client_id={{yourClientId}}&paymentid={{PaymentId}}
After entering the username=999999 and passcode=112233 we get the following screen.
After you review the payment and provide your consent the user will be redirected back to your app’s redirect URL with the authorization code as a query parameter as seen below
https://localhost/?https://localhost/?code= AAIB7CW9gOFNa6c3B5l9GsfSHT
4. Get second Access token for the PATCH subscription
curl –-location --request POST https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/oauth2/token \ --header accept: application/json \ --header content-type: application/x-www-form-urlencoded \ --data grant_type=authorization_code&client_id={{client_id}}&client_secret={(client_secret}}&code={{code_from_redirect}}&scope=UserOAuth2Security
{ "token_type": "bearer", "access_token": "6334262361656275", "expires_in": 3600, "consented_on": 1542264419, "scope": "UserOAuth2Security", }
curl --location --request POST "https://sandbox-apis.bankofcyprus.com/df-boc-org-sb/sb/psd2/v1/payments/{{paymentId}}/execute’ \ --header "Content-Type: application/json" \ --header "lang: en" \ --header "Authorization: Bearer {{oauth_code}}\ --header "originUserId: {{user_id}}’ \ --header ‘timestamp: {{$timestamp}}’
{ { "code": "CPLT", "description": [ "The transaction has passed all validations and was successfully posted in bank systems" ], "refNumber": "12345678" }