Skip to content

Commit

Permalink
Merge pull request #6 from Fintecture/connect-v2-migration
Browse files Browse the repository at this point in the history
Migrate to use Connect V2 for both AIS and PIS
  • Loading branch information
fintecturegit authored Jul 22, 2021
2 parents 112090f + 6fe741a commit 69f2598
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 126 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ let config = {
country: 'fr'
}

let connect = client.getAisConnect(null, config)
let connect = await client.getAisConnect(null, config)
window.href.location = connect.url;
```

Expand Down
2 changes: 1 addition & 1 deletion fintecture-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export class FintectureClient {
return this.connect.getPisConnect(accessToken, connectConfig);
}

public getAisConnect(accessToken: string, connectConfig: any): IAisConnect {
public async getAisConnect(accessToken: string, connectConfig: any): Promise<IAisConnect> {
return this.connect.getAisConnect(accessToken, connectConfig);
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fintecture-client",
"version": "1.0.27",
"version": "2.0.0",
"description": "Fintecture Open Banking API Gateway enabling secure bank connections and payments",
"main": "lib/fintecture-client.js",
"types": "lib/fintecture-client.d.ts",
Expand Down
8 changes: 2 additions & 6 deletions spec/connect.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { FintectureClient } from '../fintecture-client';
import { BaseUrls } from './../src/utils/URLBuilders/BaseUrls';
import { IPisSetup, IAisSetup } from './../src/interfaces/connect/ConnectInterface';
import { TestConfig } from './constants/config';

Expand Down Expand Up @@ -34,20 +33,17 @@ const client = new FintectureClient({ app_id: TestConfig.appIdMerchant, app_secr

describe('Connect', () => {
it('#PIS getPisConnect', async (done) => {
const mockConnectUrl = BaseUrls.FINTECTURECONNECTURL_SBX + '/pis?config=';
const tokens: any = await client.getAccessToken();
const connectMin = await client.getPisConnect(tokens.access_token, connectPisConfigMin);
expect(connectMin.url).toContain(mockConnectUrl);
expect(!!connectMin.session_id).toBe(true);
const connectFull = await client.getPisConnect(tokens.access_token, connectPisConfigFull);
expect(connectFull.url).toContain(mockConnectUrl);
expect(!!connectFull.session_id).toBe(true);
expect(connectFull.url.length).toBeGreaterThan(connectMin.url.length)
done();
});

it('#AIS getAisConnectUrl', (done) => {
const connect = client.getAisConnect(null, connectAisMin);
it('#AIS getAisConnectUrl', async (done) => {
const connect = await client.getAisConnect(null, connectAisMin);
expect(!!connect.url).toBe(true);
done();
});
Expand Down
143 changes: 41 additions & 102 deletions src/Connect.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import * as UtilsCrypto from './utils/Crypto.js';
import { BaseUrls } from './utils/URLBuilders/BaseUrls';
import * as connectService from './services/ConnectService';
import { IPisSetup, IPisConnectConfig, IAisConnectConfig, IPaymentPayload, IData, IAttributes, IMeta } from './interfaces/connect/ConnectInterface';
import { ISessionPayload } from './interfaces/pis/PisInterface';
import qs from 'qs';

import { Endpoints } from './utils/URLBuilders/Endpoints';
import { IPisSetup, IPaymentPayload, IData, IAttributes, IMeta } from './interfaces/connect/ConnectInterface';
import { IFintectureConfig } from './interfaces/ConfigInterface';
import { Constants } from './utils/Constants.js';
import { PIS } from './Pis';
import * as apiService from './services/ApiService';

export class Connect {
public pis: PIS;
public axios: any;
public axiosInstance: any;
public config: IFintectureConfig;
public connectConfig: IPisSetup;

private signatureType: string;

constructor(config: IFintectureConfig) {
this.pis = new PIS(config);
this.axios = connectService;
this.axiosInstance = apiService.getInstance(config.env);
this.config = config;
this.signatureType = 'rsa-sha256';
}

/**
Expand All @@ -29,44 +25,30 @@ export class Connect {
* @param {string} accessTOken
* @param {payment} State
*/
public getAisConnect(accessToken: string, connectConfig: any) {
public async getAisConnect(accessToken: string, connectConfig: any) {
this.config = this._validateConfigIntegrity(this.config);

const headers: any = this._buildHeaders(accessToken, 'get', null, this.config.private_key, this.signatureType);

const config: IAisConnectConfig = {
app_id: this.config.app_id,
signature_type: this.signatureType,
signature: headers['Signature'],
const queryParameters = qs.stringify({
redirect_uri: connectConfig.redirect_uri,
origin_uri: connectConfig.origin_uri,
state: connectConfig.state,
psu_type: connectConfig.psu_type,
country: connectConfig.country,
date: headers['Date'],
request_id: headers['X-Request-ID'],
provider: connectConfig.provider
state: connectConfig.state
});
const url = `${Endpoints.AISCONNECT}?${queryParameters}`;

// Extend the headers with Connect specific headers if they are defined
const extraHeaders = {
'x-provider': connectConfig.provider,
'x-psu-type': connectConfig.psu_type,
'x-country': connectConfig.country,
'x-language': connectConfig.language,
};

if (accessToken) {
config.access_token = accessToken;
}

const psuType = connectConfig.psu_type ? connectConfig.psu_type : 'retail';
const country = connectConfig.country ? connectConfig.country : 'fr';

const url = `${
this.config.env === Constants.SANDBOXENVIRONMENT
? BaseUrls.FINTECTURECONNECTURL_SBX
: BaseUrls.FINTECTURECONNECTURL_PRD
}/ais/${psuType}/${country}`;
const headers = apiService.getHeaders('get', url, null, this.config, null, extraHeaders);

const connect = {
url: `${url}?config=${Buffer.from(JSON.stringify(config)).toString('base64')}`,
}

return connect;
const { data } = await this.axiosInstance.get(url, { headers });

return {
url: data.meta.url
};
}

/**
Expand All @@ -81,40 +63,29 @@ export class Connect {

const paymentPayload: IPaymentPayload = this._buildPaymentPayload(connectConfig);

const prepare: any = await this.pis.prepare(accessToken, paymentPayload);

const sessionPayload: ISessionPayload = this._buildSessionPayload(prepare);

const headers: any = this._buildHeaders(accessToken, 'post', sessionPayload, this.config.private_key, this.signatureType);

const config: IPisConnectConfig = {
app_id: this.config.app_id,
access_token: accessToken,
signature_type: this.signatureType,
signature: headers['Signature'],
redirect_uri: connectConfig.redirect_uri,
const queryParameters = qs.stringify({
origin_uri: connectConfig.origin_uri,
state: connectConfig.state,
payload: sessionPayload,
psu_type: connectConfig.psu_type,
country: connectConfig.country,
date: headers['Date'],
request_id: headers['X-Request-ID'],
provider: connectConfig.provider
redirect_uri: connectConfig.redirect_uri,
state: connectConfig.state
});
const url = `${Endpoints.PISCONNECT}?${queryParameters}`;

// Extend the headers with Connect specific headers if they are defined
const extraHeaders = {
'x-provider': connectConfig.provider,
'x-psu-type': connectConfig.psu_type,
'x-country': connectConfig.country,
'x-language': connectConfig.language,
};

const url = `${
this.config.env === Constants.SANDBOXENVIRONMENT
? BaseUrls.FINTECTURECONNECTURL_SBX
: BaseUrls.FINTECTURECONNECTURL_PRD
}/pis`;
const headers = apiService.getHeaders('post', url, accessToken, this.config, paymentPayload, extraHeaders);

const connect = {
url: `${url}?config=${Buffer.from(JSON.stringify(config)).toString('base64')}`,
session_id: prepare.meta.session_id
}
const { data } = await this.axiosInstance.post(url, paymentPayload, { headers });

return connect;
return {
session_id: data.meta.session_id,
url: data.meta.url,
};
}

private _validatePisConnectConfigIntegrity(connectConfig: any) {
Expand Down Expand Up @@ -143,14 +114,6 @@ export class Connect {
return connectConfig as IPisSetup;
}


private _buildHeaders(accessToken: string, method: string, payload: any, privateKey: string, algorithm: string): any {
const headers = apiService.getHeaders(method, '', accessToken, this.config, payload);
const signingString = UtilsCrypto.buildSigningString(headers, Constants.CONNECTHEADERPARAMETERLIST)
headers["Signature"] = UtilsCrypto.signPayload(signingString, this.config.private_key);
return headers;
}

private _buildPaymentPayload(payment: any) {
const attributes: IAttributes = {
amount: payment.amount,
Expand Down Expand Up @@ -184,30 +147,6 @@ export class Connect {
return payload;
}

private _buildSessionPayload(payment) {
const payload = {
meta: {
session_id: payment.meta.session_id,
},
data: {
attributes: {
amount: payment.data.attributes.amount,
currency: payment.data.attributes.currency
}
}
} as ISessionPayload;

if (payment.data.attributes.beneficiary) {
payload.data.attributes.beneficiary = {name: payment.data.attributes.beneficiary.name};
}

if (payment.data.attributes.execution_date) {
payload.data.attributes.execution_date = payment.data.attributes.execution_date;
}

return payload;
}

private _validateConfigIntegrity(config) {
if (!config.private_key) {
throw Error('private_key must be set to use this function');
Expand Down
8 changes: 7 additions & 1 deletion src/services/ApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ export const getHeaders = (method: string, url: string, accessToken: string, con
headers['Signature'] = Crypto.createSignatureHeader(headers, config, Constants.SIGNEDHEADERPARAMETERLIST);
delete headers['(request-target)'];

// Extend with extra headers in case they are not undefined. `undefined` as value of a header
// is not allowed by Node.js
if (extraHeaders) {
Object.assign(headers, extraHeaders);
Object.entries(extraHeaders).forEach(([headerName, headerValue]) => {
if (headerValue !== undefined) {
headers[headerName] = headerValue;
}
})
}

return headers;
Expand Down
10 changes: 0 additions & 10 deletions src/services/ConnectService.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/utils/URLBuilders/BaseUrls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@ export class BaseUrls {
process.env.FINTECTUREOAUTHURL_DEV || 'https://oauth-sandbox.fintecture.com';
public static readonly FINTECTUREAPIURL_SBX: string =
process.env.FINTECTUREAPIURL_DEV || 'https://api-sandbox.fintecture.com';
public static readonly FINTECTURECONNECTURL_SBX: string =
process.env.FINTECTURECONNECTURL_DEV || 'https://connect-sandbox.fintecture.com';
public static readonly FINTECTUREOAUTHURL_PRD: string =
process.env.FINTECTUREOAUTHURL_DEV || 'https://oauth.fintecture.com';
public static readonly FINTECTUREAPIURL_PRD: string =
process.env.FINTECTUREAPIURL_DEV || 'https://api.fintecture.com';
public static readonly FINTECTURECONNECTURL_PRD: string =
process.env.FINTECTURECONNECTURL_DEV || 'https://connect.fintecture.com';
}
2 changes: 2 additions & 0 deletions src/utils/URLBuilders/Endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ export class Endpoints {
public static readonly PIS: string = '/pis/v1';
public static readonly AISPROVIDER: string = '/ais/v1/provider';
public static readonly AISCUSTOMER: string = '/ais/v1/customer';
public static readonly AISCONNECT: string = '/ais/v2/connect';
public static readonly PISCONNECT: string = '/pis/v2/connect';
}

0 comments on commit 69f2598

Please sign in to comment.