@trilo/hippopotamus
Version:
Make requests to the Trilo ecosystem
450 lines (449 loc) • 22.1 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Trilo = void 0;
var node_fetch_1 = require("node-fetch");
// import { AgreementUndertaking } from "../../../baobab/src/API";
// import {
// TAgreement,
// TSendingBank,
// TSendingBankAccount,
// } from "../../../baobab/types";
var constants_1 = require("./constants");
var getStagePrefix_1 = require("./getStagePrefix");
var setupCredentials_1 = require("./setupCredentials");
var urls_1 = require("./urls");
var sanitisation_1 = require("./sanitisation");
var Trilo = /** @class */ (function () {
function Trilo(_a) {
var _this = this;
var credentials = _a.credentials, stage = _a.stage, debug = _a.debug, redirectUri = _a.redirectUri;
this.key = "";
this.secret = "";
this.expireAt = 0;
this.stagePrefix = "";
this.debug = false;
this.redirectUri = "";
this.logger = function () {
var what = [];
for (var _i = 0; _i < arguments.length; _i++) {
what[_i] = arguments[_i];
}
if (_this.debug) {
console.log.apply(console, what);
}
};
this.init = function () { return __awaiter(_this, void 0, void 0, function () {
var _a, canEnterAgreement, allowedRedirectUris;
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(this.key && this.secret)) return [3 /*break*/, 3];
return [4 /*yield*/, setupCredentials_1.default({
stagePrefix: this.stagePrefix,
key: this.key,
secret: this.secret,
})];
case 1:
(_b = _c.sent(), this.accessToken = _b.accessToken,
// basicString: this.basicString,
this.expireAt = _b.expireAt);
this.logger("Obtained credentials, expiring at " + this.expireAt);
return [4 /*yield*/, this.setupConfig()];
case 2:
_a = _c.sent(), canEnterAgreement = _a.canEnterAgreement, allowedRedirectUris = _a.allowedRedirectUris;
if (!canEnterAgreement) {
this.logger("Merchant is unable to entire an agreemnt");
}
if (allowedRedirectUris && allowedRedirectUris.length === 1) {
// only have 1 so just use it
if (!this.redirectUri) {
// haven't already set in init config
this.redirectUri = allowedRedirectUris[0];
}
}
_c.label = 3;
case 3: return [2 /*return*/];
}
});
}); };
this.setupConfig = function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.baobabFetcher({
content: {},
path: constants_1.EPATH.GET_CONFIG,
})];
});
}); };
/**
* Obtain a trilo id to submit with a new Agreement to identify your consumer
*/
this.getTriloId = function (_a) {
var userAttribute = _a.userAttribute, email = _a.email, phone = _a.phone;
return __awaiter(_this, void 0, void 0, function () {
var response;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
this.logger("getTriloId", {
userAttribute: userAttribute,
email: email,
phone: phone,
});
return [4 /*yield*/, this.baobabFetcher({
content: { userAttribute: userAttribute, email: email, phone: phone },
path: constants_1.EPATH.GET_TRILOID,
})];
case 1:
response = _b.sent();
this.logger(response);
return [2 /*return*/, response];
}
});
});
};
/**
* use the key and secret to get an access token from the OAuth server Cognito
*/
this.newAgreement = function (_a) {
var amount = _a.amount, _b = _a.currency, currency = _b === void 0 ? "gbp" : _b, _c = _a.triloId, triloId = _c === void 0 ? undefined : _c;
return __awaiter(_this, void 0, void 0, function () {
var response, agreementId, status_1, authenticationUri, sendingBankAccounts, sendingBanks, agreement, version, error_1;
var _d, _e, _f;
return __generator(this, function (_g) {
switch (_g.label) {
case 0:
_g.trys.push([0, 9, , 10]);
amount = sanitisation_1.checkAmount(amount);
return [4 /*yield*/, this.makeAgreementId({
amount: amount,
currency: currency,
redirectUri: this.redirectUri,
})];
case 1:
response = _g.sent();
agreementId = response.agreementId;
status_1 = constants_1.SESSION_STATE.PERFORM_AUTH;
authenticationUri = undefined;
sendingBankAccounts = [];
sendingBanks = [];
if (!triloId) return [3 /*break*/, 7];
return [4 /*yield*/, this.camelFetcher({
path: constants_1.EPATH.COLLECT_AGREEMENT,
content: {
triloId: triloId,
agreementId: agreementId,
},
})];
case 2:
agreement = (_g.sent()).agreement;
return [4 /*yield*/, this.listBanks({ triloId: triloId })];
case 3:
// get the user's preferred banks
(_d = _g.sent(), _e = _d.sendingBankAccounts, sendingBankAccounts = _e === void 0 ? [] : _e, _f = _d.sendingBanks, sendingBanks = _f === void 0 ? [] : _f);
if (!sendingBankAccounts.length) return [3 /*break*/, 5];
version = agreement.version;
return [4 /*yield*/, this.camelFetcher({
path: constants_1.EPATH.ACCEPT_AGREEMENT,
content: {
triloId: triloId,
agreementId: agreementId,
version: version,
accepted: true,
sendingBankAccountId: sendingBankAccounts[0].id,
},
})];
case 4:
// have at least one, use index 0 to collect agreement
(authenticationUri = (_g.sent()).authUrl);
return [3 /*break*/, 6];
case 5:
status_1 = constants_1.SESSION_STATE.SELECT_BANK;
_g.label = 6;
case 6: return [3 /*break*/, 8];
case 7:
// generic agreement so return generic getway url
authenticationUri = urls_1.makePayUrl({
stagePrefix: this.stagePrefix,
agreementId: agreementId,
});
_g.label = 8;
case 8: return [2 /*return*/, {
status: status_1,
sendingBankAccounts: sendingBankAccounts,
sendingBanks: sendingBanks,
agreementId: agreementId,
authenticationUri: authenticationUri,
success: true,
}];
case 9:
error_1 = _g.sent();
return [2 /*return*/, {
error: error_1,
success: false,
}];
case 10: return [2 /*return*/];
}
});
});
};
this.listBanks = function (_a) {
var triloId = _a.triloId;
return _this.camelFetcher({
path: constants_1.EPATH.FIND_BANKS,
content: {
triloId: triloId,
undertaking: "SingleImmediate",
},
});
};
this.makeAgreementId = function (_a) {
var redirectUri = _a.redirectUri, amount = _a.amount, _b = _a.currency, currency = _b === void 0 ? "gbp" : _b;
return __awaiter(_this, void 0, void 0, function () {
var response;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, this.baobabFetcher({
path: constants_1.EPATH.INITIATE,
content: {
amount: amount,
currency: currency,
redirectUri: redirectUri,
},
})];
case 1:
response = _c.sent();
if (response.success) {
return [2 /*return*/, { agreementId: response.agreementId }];
}
throw JSON.stringify(response);
}
});
});
};
this.cancelAgreement = function (_a) {
var agreementId = _a.id;
return _this.baobabFetcher({
content: {
agreementId: agreementId,
cancel: true,
},
path: constants_1.EPATH.CANCEL,
});
};
this.baobabFetcher = function (_a) {
var content = _a.content, path = _a.path, _b = _a.headers, headers = _b === void 0 ? {} : _b;
return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_c) {
return [2 /*return*/, this.fetcher({
url: urls_1.baobabUrl({ path: path, stagePrefix: this.stagePrefix }),
content: content,
headers: headers,
})];
});
});
};
this.camelFetcher = function (_a) {
var content = _a.content, path = _a.path, _b = _a.headers, headers = _b === void 0 ? {} : _b;
return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_c) {
return [2 /*return*/, this.fetcher({
url: urls_1.camelApiUrl({ path: path, stagePrefix: this.stagePrefix }),
content: content,
headers: headers,
})];
});
});
};
this.fetcher = function (_a) {
var content = _a.content, url = _a.url, _b = _a.headers, extraHeaders = _b === void 0 ? {} : _b;
return __awaiter(_this, void 0, void 0, function () {
var headers, req;
var _this = this;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, this.getAuthHeaders()];
case 1:
headers = _c.sent();
Object.entries(extraHeaders).forEach(function (_a) {
var key = _a[0], value = _a[1];
return headers.set(key, value);
});
req = new node_fetch_1.Request(url, {
method: "POST",
headers: headers,
body: JSON.stringify(content),
});
return [2 /*return*/, node_fetch_1.default(req).then(function (response) { return __awaiter(_this, void 0, void 0, function () {
var json;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, response.json()];
case 1:
json = _a.sent();
this.logger(json);
return [2 /*return*/, json];
}
});
}); })];
}
});
});
};
this.getAuthHeaders = function () { return __awaiter(_this, void 0, void 0, function () {
var headers;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.isReady()];
case 1:
_a.sent();
headers = new node_fetch_1.Headers();
headers.set("Authorization", "Bearer " + this.accessToken);
headers.set("Content-Type", "application/json");
return [2 /*return*/, headers];
}
});
}); };
this.signup = function (_a) {
var email = _a.email, password = _a.password;
return __awaiter(_this, void 0, void 0, function () {
var triloId, UserSub;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.camelFetcher({
path: constants_1.EPATH.GET_CREDENTIALS,
content: {},
})];
case 1:
triloId = (_b.sent()).identityId;
return [4 /*yield*/, this.camelFetcher({
path: constants_1.EPATH.SIGNUP,
content: {
email: email,
password: password,
triloId: triloId,
},
})];
case 2:
UserSub = (_b.sent()).UserSub;
return [2 /*return*/, {
triloId: triloId,
}];
}
});
});
};
this.login = function (_a) {
var email = _a.email, password = _a.password;
return __awaiter(_this, void 0, void 0, function () {
var triloId;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.camelFetcher({
path: constants_1.EPATH.SIGNUP,
content: {
username: email,
password: password,
},
})];
case 1:
triloId = (_b.sent()).identityId;
return [2 /*return*/, {
triloId: triloId,
}];
}
});
});
};
this.checkIdentity = function (_a) {
var triloId = _a.triloId;
return __awaiter(_this, void 0, void 0, function () {
var identityId;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.camelFetcher({
path: constants_1.EPATH.GET_CREDENTIALS,
content: {
triloId: triloId,
},
})];
case 1:
identityId = (_b.sent()).identityId;
return [2 /*return*/, {
loggedIn: identityId === triloId,
}];
}
});
});
};
this.isReady = function () {
return new Promise(function (res, rej) {
if (_this.accessToken) {
res();
}
else {
var failureTime_1 = 2000;
var readyInterval_1 = setInterval(function () {
failureTime_1--;
if (_this.accessToken) {
clearInterval(readyInterval_1);
res();
}
else if (failureTime_1 < 0) {
clearInterval(readyInterval_1);
rej("No Access Token recieved within 2s");
}
}, 1);
}
});
};
if (debug) {
this.debug = debug;
}
if (redirectUri) {
this.redirectUri = redirectUri;
}
(this.stagePrefix = getStagePrefix_1.default(stage, this.logger).stagePrefix);
this.key = credentials === null || credentials === void 0 ? void 0 : credentials.key;
this.secret = credentials === null || credentials === void 0 ? void 0 : credentials.secret;
this.init();
}
return Trilo;
}());
exports.Trilo = Trilo;