Skip to content

Commit

Permalink
Merge 41106a4 into 50814fd
Browse files Browse the repository at this point in the history
  • Loading branch information
aseveryn-epam committed Aug 8, 2018
2 parents 50814fd + 41106a4 commit 97d7761
Show file tree
Hide file tree
Showing 10 changed files with 648 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
0.2.0 (in progress)
-------------------

- Added Layer 7 encryption
- Added payment status transition endpoint
- Added paper check endpoint
- Added bank card endpoint
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"main": "lib/index.js",
"dependencies": {
"object-assign": "^4.1.0",
"superagent": "^2.0.0-alpha.3"
"superagent": "^2.0.0-alpha.3",
"node-jose": "^1.0.0"
},
"scripts": {
"lint": "eslint ./src && eslint ./test && eslint ./examples",
Expand Down
5 changes: 3 additions & 2 deletions src/Hyperwallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ export default class Hyperwallet {
* @param {string} config.username - The API username
* @param {string} config.password - The API password
* @param {string} [config.programToken] - The program token that is used for some API calls
* @param {Object} [config.encryptionData] - The JSON object of encryption data
* @param {string} [config.server=https://api.sandbox.hyperwallet.com] - The API server to connect to
*/
constructor({ username, password, programToken, server = "https://api.sandbox.hyperwallet.com" }) {
constructor({ username, password, programToken, encryptionData, server = "https://api.sandbox.hyperwallet.com" }) {
if (!username || !password) {
throw new Error("You need to specify your API username and password!");
}
Expand All @@ -26,7 +27,7 @@ export default class Hyperwallet {
* @type {ApiClient}
* @protected
*/
this.client = new ApiClient(username, password, server);
this.client = new ApiClient(username, password, server, encryptionData);

/**
* The program token that is used for some API calls
Expand Down
103 changes: 83 additions & 20 deletions src/utils/ApiClient.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import request from "superagent";
import packageJson from "../../package.json";
import Encryption from "./Encryption";

/**
* The callback interface for api calls
Expand All @@ -24,8 +25,9 @@ export default class ApiClient {
* @param {string} username - The API username
* @param {string} password - The API password
* @param {string} server - The API server to connect to
* @param {string} encryptionData - The API encryption data
*/
constructor(username, password, server) {
constructor(username, password, server, encryptionData) {
/**
* The API username
*
Expand Down Expand Up @@ -56,6 +58,21 @@ export default class ApiClient {
* @protected
*/
this.version = packageJson.version;

/**
* The flag shows if encryption is enabled
*
* @type {boolean}
* @protected
*/
this.isEncrypted = false;

if (encryptionData && encryptionData.clientPrivateKeySetPath && encryptionData.hyperwalletKeySetPath) {
this.isEncrypted = true;
this.clientPrivateKeySetPath = encryptionData.clientPrivateKeySetPath;
this.hyperwalletKeySetPath = encryptionData.hyperwalletKeySetPath;
this.encryption = new Encryption(this.clientPrivateKeySetPath, this.hyperwalletKeySetPath);
}
}

/**
Expand All @@ -67,15 +84,25 @@ export default class ApiClient {
* @param {api-callback} callback - The callback for this call
*/
doPost(partialUrl, data, params, callback) {
request
.post(`${this.server}/rest/v3/${partialUrl}`)
.auth(this.username, this.password)
.set("User-Agent", `Hyperwallet Node SDK v${this.version}`)
.type("json")
.accept("json")
.query(params)
.send(data)
.end(this.wrapCallback(callback));
let contentType = "json";
let processResponse = this.wrapCallback(callback);
let requestDataPromise = new Promise((resolve) => resolve(data));
if (this.isEncrypted) {
contentType = "application/jose+json";
processResponse = this.processEncryptedResponse("POST", callback);
requestDataPromise = this.encryption.encrypt(data);
}
requestDataPromise.then((requestData) => {
request
.post(`${this.server}/rest/v3/${partialUrl}`)
.auth(this.username, this.password)
.set("User-Agent", `Hyperwallet Node SDK v${this.version}`)
.type(contentType)
.accept("json")
.query(params)
.send(requestData)
.end(processResponse);
}).catch(() => new Error("Failed to encrypt body for POST request"));
}

/**
Expand All @@ -87,15 +114,25 @@ export default class ApiClient {
* @param {api-callback} callback - The callback for this call
*/
doPut(partialUrl, data, params, callback) {
request
.put(`${this.server}/rest/v3/${partialUrl}`)
.auth(this.username, this.password)
.set("User-Agent", `Hyperwallet Node SDK v${this.version}`)
.type("json")
.accept("json")
.query(params)
.send(data)
.end(this.wrapCallback(callback));
let contentType = "json";
let processResponse = this.wrapCallback(callback);
let requestDataPromise = new Promise((resolve) => resolve(data));
if (this.isEncrypted) {
contentType = "application/jose+json";
processResponse = this.processEncryptedResponse("PUT", callback);
requestDataPromise = this.encryption.encrypt(data);
}
requestDataPromise.then((requestData) => {
request
.put(`${this.server}/rest/v3/${partialUrl}`)
.auth(this.username, this.password)
.set("User-Agent", `Hyperwallet Node SDK v${this.version}`)
.type(contentType)
.accept("json")
.query(params)
.send(requestData)
.end(processResponse);
}).catch(() => new Error("Failed to encrypt body for PUT request"));
}

/**
Expand All @@ -106,13 +143,18 @@ export default class ApiClient {
* @param {api-callback} callback - The callback for this call
*/
doGet(partialUrl, params, callback) {
let contentType = "json";
if (this.isEncrypted) {
contentType = "application/jose+json";
}
request
.get(`${this.server}/rest/v3/${partialUrl}`)
.auth(this.username, this.password)
.set("User-Agent", `Hyperwallet Node SDK v${this.version}`)
.type(contentType)
.accept("json")
.query(params)
.end(this.wrapCallback(callback));
.end(this.isEncrypted ? this.processEncryptedResponse("GET", callback) : this.wrapCallback(callback));
}

/**
Expand Down Expand Up @@ -143,4 +185,25 @@ export default class ApiClient {
};
}

/**
* Makes decryption for encrypted response bodies
*
* @param {string} httpMethod - The http method that is currently processing
* @param {api-callback} callback - The callback method to be invoked after decryption
*
* @private
*/
processEncryptedResponse(httpMethod, callback) {
return (response) => {
if (response) {
this.encryption.decrypt(response.rawResponse)
.then((decryptedData) => {
callback(undefined, decryptedData.payload.toString(), decryptedData);
})
.catch(() => new Error(`Failed to decrypt response for ${httpMethod} request`));
} else {
this.wrapCallback(callback);
}
};
}
}
Loading

0 comments on commit 97d7761

Please sign in to comment.