@mft/moneyhub-api-client 4.12.1 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ name: npm audit
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ schedule:
8
+ - cron: '0 10 * * *'
9
+
10
+ jobs:
11
+ scan:
12
+ name: npm audit
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+ - name: install dependencies
17
+ run: npm ci
18
+ - uses: oke-py/npm-audit-action@v1.8.4
19
+ with:
20
+ audit_level: moderate
21
+ github_token: ${{ secrets.GITHUB_TOKEN }}
22
+ issue_assignees: oke-py
23
+ issue_labels: vulnerability,test
24
+ dedupe_issues: true
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ 4.13.0 / 2022-01-05
2
+ ==================
3
+
4
+ **Features**
5
+
6
+ * Add getRentalRecords
7
+ * Add createRentalRecord
8
+ * Add deleteRentalRecord
1
9
 
2
10
  4.0.0 / 2021-01-11
3
11
  ==================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mft/moneyhub-api-client",
3
- "version": "4.12.1",
3
+ "version": "4.15.0",
4
4
  "description": "Node.JS client for the Moneyhub API",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -22,7 +22,7 @@
22
22
  "license": "ISC",
23
23
  "dependencies": {
24
24
  "form-data": "^3.0.0",
25
- "got": "^11.8.1",
25
+ "got": "^11.8.3",
26
26
  "jose": "^2.0.5",
27
27
  "openid-client": "^4.2.2",
28
28
  "ramda": "^0.27.1"
@@ -37,8 +37,8 @@
37
37
  "eslint": "^7.32.0",
38
38
  "express": "^4.17.1",
39
39
  "husky": "^7.0.2",
40
- "mocha": "^9.1.2",
41
- "mocha-junit-reporter": "^2.0.0"
40
+ "mocha": "^9.2.0",
41
+ "mocha-junit-reporter": "^2.0.2"
42
42
  },
43
43
  "husky": {
44
44
  "hooks": {
package/readme.md CHANGED
@@ -289,7 +289,7 @@ Creates a request object
289
289
  const tokens = await moneyhub.requestObject({
290
290
  scope: "the-required-scope",
291
291
  state: "state",
292
- nonce: "nonce,
292
+ nonce: "nonce",
293
293
  claims: claimsObject,
294
294
  })
295
295
  ```
@@ -322,7 +322,7 @@ Creates a connection auth request
322
322
 
323
323
  ```javascript
324
324
  const tokens = await moneyhub.createAuthRequest({
325
- redirectUri: "redirect-uri,
325
+ redirectUri: "redirect-uri",
326
326
  userId: "user-id",
327
327
  scope:"openid 1ffe704d39629a929c8e293880fb449a", // replace bank id with the bank you want to connect to
328
328
  categorisationType: "personal", // optional - defaults to personal
@@ -334,7 +334,7 @@ Creates a reauth auth request
334
334
 
335
335
  ```javascript
336
336
  const tokens = await moneyhub.createAuthRequest({
337
- redirectUri: "redirect-uri,
337
+ redirectUri: "redirect-uri",
338
338
  userId: "user-id",
339
339
  connectionId: "connection-id",
340
340
  scope:"openid reauth",
@@ -345,7 +345,7 @@ Creates a refresh auth request
345
345
 
346
346
  ```javascript
347
347
  const tokens = await moneyhub.createAuthRequest({
348
- redirectUri: "redirect-uri,
348
+ redirectUri: "redirect-uri",
349
349
  userId: "user-id",
350
350
  connectionId: "connection-id",
351
351
  scope:"openid refresh",
@@ -356,14 +356,14 @@ Creates a payment auth request
356
356
 
357
357
  ```javascript
358
358
  const tokens = await moneyhub.createAuthRequest({
359
- redirectUri: "redirect-uri,
359
+ redirectUri: "redirect-uri",
360
360
  userId: "user-id",
361
361
  connectionId: "connection-id",
362
362
  scope:"openid payment",
363
363
  payment: {
364
364
  payeeId: "payee-id",
365
365
  amount: 200,
366
- payeeRef: "Payee ref,
366
+ payeeRef: "Payee ref",
367
367
  payerRef: "Payer ref"
368
368
  },
369
369
  })
@@ -373,7 +373,7 @@ Creates a reverse payment auth request
373
373
 
374
374
  ```javascript
375
375
  const tokens = await moneyhub.createAuthRequest({
376
- redirectUri: "redirect-uri,
376
+ redirectUri: "redirect-uri",
377
377
  userId: "user-id",
378
378
  connectionId: "connection-id",
379
379
  scope:"openid reverse_payment",
@@ -438,7 +438,7 @@ Helper method that gets the correct client credentials access token and then reg
438
438
 
439
439
  ```javascript
440
440
  const user = await moneyhub.registerUser({
441
- clientUserId: "your user id" /* optional */
441
+ clientUserId: "your user id" // optional
442
442
  })
443
443
  ```
444
444
 
@@ -1113,7 +1113,7 @@ const url = await moneyhub.getPaymentAuthorizeUrl({
1113
1113
  state: "your state value",
1114
1114
  nonce: "your nonce value", // optional
1115
1115
  context: "Payment context [Other,BillPayment,PartyToParty]", // optional - defaults to PartyToParty
1116
- userId: "Moneyhub API User ID you wish to attach to the payment" // optional
1116
+ userId: "Moneyhub API User ID you wish to attach to the payment", // optional
1117
1117
  claims: claimsObject, // optional
1118
1118
  })
1119
1119
 
@@ -1153,6 +1153,7 @@ const url = await moneyhub.getReversePaymentAuthorizeUrl({
1153
1153
  bankId: "Bank id to authorise payment from",
1154
1154
  paymentId: "Id of payment to reverse",
1155
1155
  state: "your state value",
1156
+ amount: "reverse payment amount" // optional
1156
1157
  nonce: "your nonce value", // optional
1157
1158
  claims: claimsObject, // optional
1158
1159
  })
@@ -1332,6 +1333,122 @@ const standingOrder = await moneyhub.getStandingOrder({
1332
1333
  })
1333
1334
  ```
1334
1335
 
1336
+ ### Recurring Payments (VRP)
1337
+
1338
+ #### `getRecurringPaymentAuthorizeUrl`
1339
+
1340
+ This is a helper function that returns an authorize url to authorize a recurring payment with the selected bank. This function uses the following scope with the value of the bankId provided `recurring_payment:create openid id:${bankId}`. It also requires the authentication to be `client_secret_jwt` or `private_key_jwt`.
1341
+
1342
+ ```javascript
1343
+ const url = await moneyhub.getRecurringPaymentAuthorizeUrl({
1344
+ bankId: "Bank id to authorise payment from",
1345
+ payeeId: "Id of payee",
1346
+ payeeType: "Payee type [api-payee|mh-user-account]", // optional - defaults to api-payee
1347
+ payerId: "Id of payer", // requird only if payerType is defined
1348
+ payerType: "Payer type [mh-user-account]", // required only if payerId is used
1349
+ reference: "The reference for recurring payment",
1350
+ validFromDate: "The date from which the authorisation is effective" , // should be in an international format, e.g. 15-MAR-2021 or ISO date
1351
+ validToDate: "The date to which the authorisation is effective", // should be in an international format, e.g. 15-MAR-2021 or ISO date
1352
+ maximumIndividualAmount: "The maimum single amount that will be allowed", // the valid in whole minor units (i.e. pence)
1353
+ currency: "The currency code for the maxiumum recurring payment amount [GBP]",
1354
+ periodicLimits: [
1355
+ {
1356
+ amount: "The maximum amount for this recurring payment limit", // the valid in whole minor units (i.e. pence)
1357
+ currency: "The currency code for this recurring payment limit [GBP]",
1358
+ periodType: "The period over which the limit is effective [Day, Week, Fortnight, Month, Half-year, Year]",
1359
+ periodAlignment: "Specifies whether the period starts on the date of consent creation or lines up with a calendar [Consent, Calendar]",
1360
+ }
1361
+ ],
1362
+ type: [
1363
+ "Sweeping", // Specifies that the recurring payment is for the purpose of sweeping payments
1364
+ "Other" // Specifies that the recurring payment is for other payments of another purpose
1365
+ ],
1366
+ context: "Payment context [Other,BillPayment,PartyToParty]", // optional - defaults to PartyToParty
1367
+ state: "your state value",
1368
+ nonce: "your nonce value", // optional
1369
+ claims: claimsObject, // optional
1370
+ })
1371
+
1372
+ // Scope used with the bankId provided
1373
+ const scope = `recurring_payment:create openid id:${bankId}`
1374
+
1375
+ // Default claims if none are provided
1376
+ const defaultClaims = {
1377
+ id_token: {
1378
+ "mh:con_id": {
1379
+ essential: true,
1380
+ },
1381
+ "mh:recurring_payment": {
1382
+ essential: true,
1383
+ value: {
1384
+ payeeId,
1385
+ payeeType,
1386
+ payerId,
1387
+ payerType,
1388
+ reference,
1389
+ validFromDate,
1390
+ validToDate,
1391
+ maximumIndividualAmount,
1392
+ currency,
1393
+ periodicLimits,
1394
+ context,
1395
+ },
1396
+ },
1397
+ },
1398
+ }
1399
+ ```
1400
+
1401
+ #### `getRecurringPayments`
1402
+
1403
+ This method returns a list of initiated recurring payment consents. This function uses the scope `recurring_payment:read`
1404
+
1405
+ ```javascript
1406
+ const recurringPayments = await moneyhub.getRecurringPayments({
1407
+ limit: "limit", // optional
1408
+ offset: "offset", // optional
1409
+ userId: "user-id", // optional
1410
+ payeeId: "payee-id", // optional
1411
+ startDate: "2020-01-01", // optional
1412
+ endDate: "2020-12-31", // optional
1413
+ })
1414
+ ```
1415
+
1416
+ #### `getRecurringPayment`
1417
+
1418
+ This method gets a recurring payment consent. This function uses the scope `recurring_payment:create`
1419
+
1420
+ ```javascript
1421
+ const recurringPayment = await moneyhub.getRecurringPayment({
1422
+ recurringPaymentId: "Id of the recurring payment consent"
1423
+ })
1424
+ ```
1425
+
1426
+ #### `makeRecurringPayment`
1427
+
1428
+ This method creates a payment using the recurring payment consent. This function uses the scope `recurring_payment:create`
1429
+
1430
+ ```javascript
1431
+ const recurringPayments = await moneyhub.getRecurringPayments({
1432
+ recurringPaymentId: "Id of the recurring payment consent",
1433
+ payment: {
1434
+ payeeId: "payee-id", // optional
1435
+ amount: 200,
1436
+ payeeRef: "Payee ref",
1437
+ payerRef: "Payer ref"
1438
+ }
1439
+ })
1440
+ ```
1441
+
1442
+ #### `revokeRecurringPayment`
1443
+
1444
+ This method revokes a recurring payment consent. This function uses the scope `recurring_payment:create`
1445
+
1446
+ ```javascript
1447
+ const revokedRecurringPayment = await moneyhub.revokeRecurringPayment({
1448
+ recurringPaymentId: "Id of the recurring payment consent"
1449
+ })
1450
+ ```
1451
+
1335
1452
  #### `getRegularTransactions`
1336
1453
 
1337
1454
  Get all the regular transactions for a user, there is an option to pass an account ID as a parameter as a filter. This function uses the scope `accounts:read`, `transactions:read:all` and `regular_transactions:read`
@@ -1344,6 +1461,57 @@ const regulartransactions = await moneyhub.getRegularTransactions({
1344
1461
  })
1345
1462
  ```
1346
1463
 
1464
+ ### Rental records
1465
+
1466
+ #### `getRentalRecords`
1467
+
1468
+ This method will return the rental record for the user. Requires the scope `rental_records:read`.
1469
+
1470
+ ```javascript
1471
+ const getRentalRecordResponse = await moneyhub.getRentalRecords({
1472
+ userId: "user-id"
1473
+ })
1474
+ const rentalRecord = getRentalRecordResponse.data[0]
1475
+ ```
1476
+
1477
+ #### `createRentalRecord`
1478
+
1479
+ This method will create a rental record for the user. Requires the scope `rental_records:write`. Please note only one rental record can exist for a user.
1480
+
1481
+ ```javascript
1482
+ const createRentalRecordResponse = await moneyhub.createRentalRecord({
1483
+ userId: "user-id",
1484
+ rentalData: {
1485
+ title: "Title",
1486
+ firstName: "firstName",
1487
+ lastName: "lastName",
1488
+ birthdate: "2000-11-19",
1489
+ addressLine1: "First address line",
1490
+ addressLine2: "Second address line", // optional
1491
+ addressLine3: "Third address line", // optional
1492
+ addressLine4: "Fourth address line", // optional
1493
+ postalCode: "CA12345",
1494
+ tenancyStartDate: "2020-11-19",
1495
+ rentalAmount: {
1496
+ value: 10000
1497
+ },
1498
+ rentalFrequency: "monthly",
1499
+ }
1500
+ })
1501
+ const createdRentalRecord = createRentalRecordResponse.data
1502
+ ```
1503
+
1504
+ #### `deleteRentalRecord`
1505
+
1506
+ This method deletes the rental record for a user.
1507
+
1508
+ ```javascript
1509
+ await moneyhub.deleteRentalRecord({
1510
+ userId: "user-id",
1511
+ rentalId: "rental-id"
1512
+ })
1513
+ ```
1514
+
1347
1515
  ### Financial Connections
1348
1516
 
1349
1517
  #### `listConnections`
@@ -89,6 +89,13 @@ describe("API client", () => {
89
89
  "getStandingOrder",
90
90
  "getStandingOrders",
91
91
  "getRegularTransactions",
92
+ "getRentalRecords",
93
+ "createRentalRecord",
94
+ "deleteRentalRecord",
95
+ "getRecurringPayments",
96
+ "getRecurringPayment",
97
+ "makeRecurringPayment",
98
+ "revokeRecurringPayment",
92
99
  "getAuthorizeUrl",
93
100
  "getAuthorizeUrlFromRequestUri",
94
101
  "requestObject",
@@ -98,6 +105,7 @@ describe("API client", () => {
98
105
  "getRefreshAuthorizeUrlForCreatedUser",
99
106
  "getPaymentAuthorizeUrl",
100
107
  "getReversePaymentAuthorizeUrl",
108
+ "getRecurringPaymentAuthorizeUrl",
101
109
  "getStandingOrderAuthorizeUrl",
102
110
  "exchangeCodeForTokensLegacy",
103
111
  "exchangeCodeForTokens",
@@ -0,0 +1,90 @@
1
+ /* eslint-disable max-nested-callbacks */
2
+ const Moneyhub = require("..")
3
+ const config = require("../../test/test-client-config")
4
+ const {expect, assert} = require("chai")
5
+
6
+ const testRentalData = {
7
+ title: "Title",
8
+ firstName: "firstName",
9
+ lastName: "lastName",
10
+ birthdate: "2000-11-19",
11
+ addressLine1: "First address line",
12
+ addressLine2: "Second address line",
13
+ addressLine3: "Third address line",
14
+ addressLine4: "Fourth address line",
15
+ postalCode: "CA12345",
16
+ tenancyStartDate: "2020-11-19",
17
+ rentalAmount: {
18
+ value: 10000
19
+ },
20
+ rentalFrequency: "monthly",
21
+ }
22
+
23
+ describe("Rental records", () => {
24
+ let moneyhub
25
+ let seriesId
26
+ let rentalId
27
+ const userId = config.testUserIdWithconnection
28
+
29
+ before(async () => {
30
+ moneyhub = await Moneyhub(config)
31
+ const {data: regularTransactions} = await moneyhub.getRegularTransactions({userId})
32
+ seriesId = regularTransactions[0].seriesId
33
+ const {data: rentals} = await moneyhub.getRentalRecords({userId})
34
+ if (rentals.length) {
35
+ const existingRentalId = rentals[0].id
36
+ await moneyhub.deleteRentalRecord({userId, rentalId: existingRentalId})
37
+ }
38
+ })
39
+
40
+ beforeEach(async () => {
41
+ const {data} = await moneyhub.createRentalRecord({rentalData: {...testRentalData, seriesId}, userId})
42
+ rentalId = data.id
43
+ })
44
+
45
+ afterEach(async () => {
46
+ try {
47
+ await moneyhub.deleteRentalRecord({userId, rentalId})
48
+ } catch (e) {
49
+ if (!e.message.includes("404")) {
50
+ throw e
51
+ }
52
+ }
53
+
54
+ })
55
+
56
+ it("get rental record", async () => {
57
+ const {data} = await moneyhub.getRentalRecords({userId})
58
+ expect(data.length).to.be.above(0)
59
+ expect(data[0]).to.have.property("seriesId")
60
+ })
61
+
62
+ it("create rental record", async () => {
63
+ const {data} = await moneyhub.getRentalRecords({userId})
64
+ expect(data.length).to.be.above(0)
65
+ assert.containsAllKeys(data[0], {
66
+ title: "Title",
67
+ firstName: "firstName",
68
+ lastName: "lastName",
69
+ birthdate: "2000-11-19",
70
+ addressLine1: "First address line",
71
+ addressLine2: "Second address line",
72
+ addressLine3: "Third address line",
73
+ addressLine4: "Fourth address line",
74
+ postalCode: "CA12345",
75
+ tenancyStartDate: "2020-11-19",
76
+ rentalAmount: {
77
+ value: 10000,
78
+ currency: "GBP"
79
+ },
80
+ rentalFrequency: "monthly",
81
+ })
82
+ })
83
+
84
+ it("delete rental record", async () => {
85
+ await moneyhub.deleteRentalRecord({userId, rentalId})
86
+ const {data} = await moneyhub.getRentalRecords({userId})
87
+ expect(data.length).to.eql(0)
88
+ })
89
+
90
+ })
@@ -281,6 +281,7 @@ module.exports = ({client, config}) => {
281
281
  paymentId,
282
282
  state,
283
283
  nonce,
284
+ amount,
284
285
  claims = {},
285
286
  }) => {
286
287
  if (!state) {
@@ -303,6 +304,7 @@ module.exports = ({client, config}) => {
303
304
  essential: true,
304
305
  value: {
305
306
  paymentId,
307
+ amount,
306
308
  },
307
309
  },
308
310
  "mh:payment": {
@@ -327,6 +329,77 @@ module.exports = ({client, config}) => {
327
329
  return url
328
330
  },
329
331
 
332
+ getRecurringPaymentAuthorizeUrl: async ({
333
+ bankId,
334
+ payeeId,
335
+ payeeType,
336
+ payerId,
337
+ payerType,
338
+ reference,
339
+ validFromDate,
340
+ validToDate,
341
+ maximumIndividualAmount,
342
+ currency,
343
+ periodicLimits,
344
+ type,
345
+ context,
346
+ state,
347
+ nonce,
348
+ userId,
349
+ claims = {},
350
+ }) => {
351
+ if (!state) {
352
+ console.error("State is required")
353
+ throw new Error("Missing parameters")
354
+ }
355
+
356
+ const scope = `recurring_payment:create openid id:${bankId}`
357
+ const defaultClaims = {
358
+ id_token: {
359
+ "mh:con_id": {
360
+ essential: true,
361
+ },
362
+ "mh:recurring_payment": {
363
+ essential: true,
364
+ value: {
365
+ payeeId,
366
+ payeeType,
367
+ payerId,
368
+ payerType,
369
+ reference,
370
+ validFromDate,
371
+ validToDate,
372
+ maximumIndividualAmount,
373
+ currency,
374
+ periodicLimits,
375
+ type,
376
+ context,
377
+ },
378
+ },
379
+ ...userId && {
380
+ sub: {
381
+ value: userId
382
+ }
383
+ }
384
+ },
385
+ }
386
+
387
+ const _claims = R.mergeDeepRight(defaultClaims, claims)
388
+
389
+ const request = await requestObject({
390
+ scope,
391
+ state,
392
+ claims: _claims,
393
+ nonce,
394
+ })
395
+
396
+ const requestUri = await getRequestUri(request)
397
+ const url = getAuthorizeUrlFromRequestUri({
398
+ requestUri,
399
+ })
400
+ return url
401
+ },
402
+
330
403
  getStandingOrderAuthorizeUrl: async ({
331
404
  bankId,
332
405
  payeeId,
package/src/index.js CHANGED
@@ -20,6 +20,8 @@ const requestFactories = [
20
20
  require("./requests/categories"),
21
21
  require("./requests/standing-orders"),
22
22
  require("./requests/regular-transactions"),
23
+ require("./requests/rental-records"),
24
+ require("./requests/recurring-payments"),
23
25
  ]
24
26
  const DEFAULT_TIMEOUT = 60000
25
27
 
@@ -51,8 +53,6 @@ module.exports = async (apiClientConfig) => {
51
53
  timeout,
52
54
  })
53
55
 
54
- Issuer.defaultHttpOptions = {timeout}
55
-
56
56
  const moneyhubIssuer = await Issuer.discover(identityServiceUrl + "/oidc")
57
57
 
58
58
  const client = new moneyhubIssuer.Client(
@@ -0,0 +1,37 @@
1
+ module.exports = ({config, request}) => {
2
+ const {identityServiceUrl} = config
3
+
4
+ return {
5
+ getRecurringPayments: async (params = {}) =>
6
+ request(`${identityServiceUrl}/recurring-payments`, {
7
+ searchParams: params,
8
+ cc: {
9
+ scope: "recurring_payment:read",
10
+ },
11
+ }),
12
+
13
+ getRecurringPayment: async ({recurringPaymentId}) =>
14
+ request(`${identityServiceUrl}/recurring-payments/${recurringPaymentId}`, {
15
+ cc: {
16
+ scope: "recurring_payment:read",
17
+ },
18
+ }),
19
+
20
+ makeRecurringPayment: async ({recurringPaymentId, payment}) =>
21
+ request(`${identityServiceUrl}/recurring-payments/${recurringPaymentId}/pay`, {
22
+ method: "POST",
23
+ body: payment,
24
+ cc: {
25
+ scope: "recurring_payment:create",
26
+ },
27
+ }),
28
+
29
+ revokeRecurringPayment: async ({recurringPaymentId}) =>
30
+ request(`${identityServiceUrl}/recurring-payments/${recurringPaymentId}`, {
31
+ method: "DELETE",
32
+ cc: {
33
+ scope: "recurring_payment:create",
34
+ },
35
+ }),
36
+ }
37
+ }
@@ -0,0 +1,41 @@
1
+ module.exports = ({config, request}) => {
2
+ const {resourceServerUrl} = config
3
+
4
+ return {
5
+ getRentalRecords: async ({userId}) =>
6
+ request(
7
+ `${resourceServerUrl}/rental-records`,
8
+ {
9
+ cc: {
10
+ scope: "rental_records:read",
11
+ sub: userId,
12
+ },
13
+ },
14
+ ),
15
+ createRentalRecord: async ({userId, rentalData}) => {
16
+ return await request(
17
+ `${resourceServerUrl}/rental-records`,
18
+ {
19
+ method: "POST",
20
+ cc: {
21
+ scope: "rental_records:write",
22
+ sub: userId,
23
+ },
24
+ body: rentalData,
25
+ },
26
+ )
27
+ },
28
+ deleteRentalRecord: async ({userId, rentalId}) => {
29
+ return await request(
30
+ `${resourceServerUrl}/rental-records/${rentalId}`,
31
+ {
32
+ method: "DELETE",
33
+ cc: {
34
+ scope: "rental_records:write",
35
+ sub: userId,
36
+ },
37
+ },
38
+ )
39
+ },
40
+ }
41
+ }