@mft/moneyhub-api-client 4.8.0 → 4.12.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mft/moneyhub-api-client",
3
- "version": "4.8.0",
3
+ "version": "4.12.1",
4
4
  "description": "Node.JS client for the Moneyhub API",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -34,10 +34,10 @@
34
34
  "command-line-args": "^5.1.1",
35
35
  "command-line-usage": "^6.1.1",
36
36
  "config": "^3.3.6",
37
- "eslint": "^6.8.0",
37
+ "eslint": "^7.32.0",
38
38
  "express": "^4.17.1",
39
- "husky": "^4.3.6",
40
- "mocha": "^8.2.1",
39
+ "husky": "^7.0.2",
40
+ "mocha": "^9.1.2",
41
41
  "mocha-junit-reporter": "^2.0.0"
42
42
  },
43
43
  "husky": {
package/readme.md CHANGED
@@ -369,6 +369,20 @@ const tokens = await moneyhub.createAuthRequest({
369
369
  })
370
370
  ```
371
371
 
372
+ Creates a reverse payment auth request
373
+
374
+ ```javascript
375
+ const tokens = await moneyhub.createAuthRequest({
376
+ redirectUri: "redirect-uri,
377
+ userId: "user-id",
378
+ connectionId: "connection-id",
379
+ scope:"openid reverse_payment",
380
+ reversePayment: {
381
+ paymentId: "payment-id"
382
+ },
383
+ })
384
+ ```
385
+
372
386
  #### `completeAuthRequest`
373
387
 
374
388
  Completes an auth request succesfully
@@ -721,6 +735,31 @@ const transactions = await moneyhub.addTransaction({
721
735
  })
722
736
  ```
723
737
 
738
+ #### `addTransactions`
739
+
740
+ Add up to 50 transactions for a user. Please note, transaction must belong to an account that is transaction-able. This function uses the scopes `transactions:read:all transactions:write:all`.
741
+
742
+ ```javascript
743
+ const transactions = await moneyhub.addTransactions({
744
+ userId: "userId",
745
+ transactions: [
746
+ {
747
+ amount: {
748
+ value: 10
749
+ }
750
+ },
751
+ {
752
+ amount: {
753
+ value: 25
754
+ }
755
+ }
756
+ ],
757
+ params: {
758
+ categorise: true // optional - enable categorisatio for transactions
759
+ }
760
+ })
761
+ ```
762
+
724
763
  #### `deleteTransaction`
725
764
 
726
765
  Delete a transaction for a user. This function uses the scopes `transactions:write:all`..
@@ -925,6 +964,32 @@ const categoryGroups = await moneyhub.getCategoryGroups({
925
964
  },
926
965
  })
927
966
  ```
967
+
968
+ #### `getStandardCategories`
969
+
970
+ Get standard categories.
971
+
972
+ ```javascript
973
+
974
+ const categories = await moneyhub.getStandardCategories({
975
+ params: {
976
+ type: "personal" // optional personal|business|all
977
+ },
978
+ })
979
+ ```
980
+
981
+ #### `getStandardCategoryGroups`
982
+
983
+ Get standard categories.
984
+
985
+ ```javascript
986
+
987
+ const categoryGroups = await moneyhub.getStandardCategoryGroups({
988
+ params: {
989
+ type: "personal" // optional personal|business|all
990
+ },
991
+ })
992
+ ```
928
993
  #### `createCustomCategory`
929
994
 
930
995
  Create a custom category. This function uses the scopes `categories:read categories:write`.
@@ -1035,10 +1100,10 @@ This is a helper function that returns an authorize url to authorize a payment t
1035
1100
 
1036
1101
  ```javascript
1037
1102
  const url = await moneyhub.getPaymentAuthorizeUrl({
1038
- bankId: "Bank id to authorise payment from",
1039
- payeeId: "Id of payee",
1103
+ bankId: "Bank id to authorise payment from", // required
1104
+ payeeId: "Id of payee", // required
1040
1105
  payeeType: "Payee type [api-payee|mh-user-account]", // optional - defaults to api-payee
1041
- payerId: "Id of payer", // requird only if payerType is defined
1106
+ payerId: "Id of payer", // required only if payerType is defined
1042
1107
  payerType: "Payer type [mh-user-account]", // required only if payerId is used
1043
1108
  amount: "Amount in pence to authorize payment",
1044
1109
  payeeRef: "Payee reference",
@@ -1048,6 +1113,7 @@ const url = await moneyhub.getPaymentAuthorizeUrl({
1048
1113
  state: "your state value",
1049
1114
  nonce: "your nonce value", // optional
1050
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
1051
1117
  claims: claimsObject, // optional
1052
1118
  })
1053
1119
 
@@ -1078,6 +1144,41 @@ const defaultClaims = {
1078
1144
  }
1079
1145
  ```
1080
1146
 
1147
+ #### `getReversePaymentAuthorizeUrl`
1148
+
1149
+ This is a helper function that returns an authorize url to authorize a reverse payment for a payment that is reversible. This function uses the following scope with the value of the bankId provided `reverse_payment openid id:${bankId}`. It also requires the authentication to be `client_secret_jwt` or `private_key_jwt`.
1150
+
1151
+ ```javascript
1152
+ const url = await moneyhub.getReversePaymentAuthorizeUrl({
1153
+ bankId: "Bank id to authorise payment from",
1154
+ paymentId: "Id of payment to reverse",
1155
+ state: "your state value",
1156
+ nonce: "your nonce value", // optional
1157
+ claims: claimsObject, // optional
1158
+ })
1159
+
1160
+ // Scope used with the bankId provided
1161
+ const scope = `reverse_payment openid id:${bankId}`
1162
+
1163
+ // Default claims if none are provided
1164
+ const defaultClaims = {
1165
+ id_token: {
1166
+ "mh:con_id": {
1167
+ essential: true,
1168
+ },
1169
+ "mh:payment": {
1170
+ essential: true,
1171
+ },
1172
+ "mh:reversePayment": {
1173
+ essential: true,
1174
+ value: {
1175
+ paymentId
1176
+ },
1177
+ },
1178
+ },
1179
+ }
1180
+ ```
1181
+
1081
1182
  #### `addPayee`
1082
1183
 
1083
1184
  This method will add a Payee. This will return an id that it is
@@ -1147,10 +1248,10 @@ This is a helper function that returns an authorize url to authorize a standng o
1147
1248
 
1148
1249
  ```javascript
1149
1250
  const url = await moneyhub.getStandingOrderAuthorizeUrl({
1150
- bankId: "Bank id to authorise payment from",
1151
- payeeId: "Id of payee",
1251
+ bankId: "Bank id to authorise payment from", // required
1252
+ payeeId: "Id of payee", // required
1152
1253
  payeeType: "Payee type [api-payee|mh-user-account]", // optional - defaults to api-payee
1153
- payerId: "Id of payer", // requird only if payerType is defined
1254
+ payerId: "Id of payer", // required only if payerType is defined
1154
1255
  payerType: "Payer type [mh-user-account]", // required only if payerId is used
1155
1256
  reference: "The reference for standing order",
1156
1257
  frequency: {
@@ -1233,7 +1334,7 @@ const standingOrder = await moneyhub.getStandingOrder({
1233
1334
 
1234
1335
  #### `getRegularTransactions`
1235
1336
 
1236
- 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`
1337
+ 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`
1237
1338
 
1238
1339
  ```javascript
1239
1340
  const queryParams = {accountID}
@@ -4,10 +4,8 @@ const config = require("../../test/test-client-config")
4
4
  const {expect} = require("chai")
5
5
 
6
6
  describe("Accounts", () => {
7
- let moneyhub
8
- let accountId
9
- let pensionId
10
- const userId = config.testUserId
7
+ let manualAccountId, moneyhub
8
+ const {testUserId: userId, testAccountId: accountId, testPensionId: pensionId} = config
11
9
 
12
10
  before(async () => {
13
11
  moneyhub = await Moneyhub(config)
@@ -15,9 +13,12 @@ describe("Accounts", () => {
15
13
 
16
14
  it("get accounts", async () => {
17
15
  const accounts = await moneyhub.getAccounts({userId})
18
- expect(accounts.data.length).to.eql(11)
19
- accountId = accounts.data.find(a => a.type === "cash:current").id
20
- pensionId = accounts.data.find(a => a.type === "pension").id
16
+ expect(accounts.data.length).to.be.at.least(11)
17
+ const cashAccount = accounts.data.find(a => a.type === "cash:current")
18
+ const pension = accounts.data.find(a => a.type === "pension")
19
+
20
+ expect(cashAccount).to.not.be.undefined
21
+ expect(pension).to.not.be.undefined
21
22
  })
22
23
 
23
24
  it("get account", async () => {
@@ -64,12 +65,12 @@ describe("Accounts", () => {
64
65
  }
65
66
 
66
67
  const {data: {id}} = await moneyhub.createAccount({userId, account})
67
- accountId = id
68
+ manualAccountId = id
68
69
  expect(id).to.not.be.undefined
69
70
  })
70
71
 
71
72
  it("deletes manual account", async () => {
72
- const status = await moneyhub.deleteAccount({userId, accountId})
73
+ const status = await moneyhub.deleteAccount({userId, accountId: manualAccountId})
73
74
  expect(status).to.eql(204)
74
75
  })
75
76
  })
@@ -13,6 +13,16 @@ describe("Categories", () => {
13
13
  moneyhub = await Moneyhub(config)
14
14
  })
15
15
 
16
+ it("get standard categories", async () => {
17
+ const categories = await moneyhub.getStandardCategories({params: {type: "personal"}})
18
+ expect(categories.data.length).to.be.at.least(50)
19
+ })
20
+
21
+ it("get standard category groups", async () => {
22
+ const categories = await moneyhub.getStandardCategoryGroups({params: {type: "all"}})
23
+ expect(categories.data.length).to.be.at.least(24)
24
+ })
25
+
16
26
  it("get personal categories", async () => {
17
27
  const categories = await moneyhub.getCategories({userId, params: {limit: 100}})
18
28
  expect(categories.data.length).to.be.at.least(50)
@@ -57,6 +57,7 @@ describe("API client", () => {
57
57
  "getTransactions",
58
58
  "getTransaction",
59
59
  "addTransaction",
60
+ "addTransactions",
60
61
  "updateTransaction",
61
62
  "deleteTransaction",
62
63
  "addFileToTransaction",
@@ -80,8 +81,10 @@ describe("API client", () => {
80
81
  "deleteUserConnection",
81
82
  "deleteUser",
82
83
  "getCategories",
84
+ "getStandardCategories",
83
85
  "getCategory",
84
86
  "getCategoryGroups",
87
+ "getStandardCategoryGroups",
85
88
  "createCustomCategory",
86
89
  "getStandingOrder",
87
90
  "getStandingOrders",
@@ -94,6 +97,7 @@ describe("API client", () => {
94
97
  "getReauthAuthorizeUrlForCreatedUser",
95
98
  "getRefreshAuthorizeUrlForCreatedUser",
96
99
  "getPaymentAuthorizeUrl",
100
+ "getReversePaymentAuthorizeUrl",
97
101
  "getStandingOrderAuthorizeUrl",
98
102
  "exchangeCodeForTokensLegacy",
99
103
  "exchangeCodeForTokens",
@@ -2,40 +2,61 @@
2
2
  const Moneyhub = require("..")
3
3
  const config = require("../../test/test-client-config")
4
4
  const {expect} = require("chai")
5
- const userId = config.testUserId
5
+ const {testUserId: userId, testAccountId: accountId} = config
6
6
  const R = require("ramda")
7
+
7
8
  describe("Transaction Splits", () => {
8
9
  let moneyhub
9
- let transaction
10
10
  let transactionId
11
11
  let splitId
12
+
13
+ const splitTestBaseInput = {
14
+ userId,
15
+ splits: [
16
+ {
17
+ categoryId: "std:39577c49-350f-45a4-8ec3-48ce205585fb",
18
+ amount: -1500,
19
+ description: "Split 1"
20
+ },
21
+ {
22
+ categoryId: "std:7daf3d79-98dd-4c85-b3cc-6d7ffd83fce9",
23
+ amount: -800,
24
+ description: "Split 2"
25
+ }
26
+ ]
27
+ }
28
+
12
29
  before(async () => {
13
30
  moneyhub = await Moneyhub(config)
14
- const {data} = await moneyhub.getTransactions({
15
- userId,
16
- params: {limit: 1},
17
- })
18
- transaction = R.head(data)
19
- transactionId = transaction.id
31
+ const transaction = {
32
+ accountId,
33
+ "amount": {
34
+ "value": -2300
35
+ },
36
+ "categoryId": "std:4b0255f0-0309-4509-9e05-4b4e386f9b0d",
37
+ "categoryIdConfirmed": true,
38
+ "longDescription": "New transaction",
39
+ "shortDescription": "transaction",
40
+ "notes": "notes",
41
+ "status": "posted",
42
+ "date": "2018-07-10T12:00:00+00:00"
43
+ }
44
+
45
+ const {data} = await moneyhub.addTransaction({userId, transaction})
46
+ transactionId = data.id
47
+ })
48
+
49
+ beforeEach(async () => {
50
+ const {data} = await moneyhub.splitTransaction({...splitTestBaseInput, transactionId})
51
+ splitId = data[0].id
52
+ })
53
+
54
+ after(async () => {
55
+ await moneyhub.deleteTransaction({userId, transactionId})
20
56
  })
21
57
 
22
58
  it("can split a transaction", async () => {
23
- const {data: splits} = await moneyhub.splitTransaction({
24
- userId,
25
- transactionId,
26
- splits: [
27
- {
28
- categoryId: "std:39577c49-350f-45a4-8ec3-48ce205585fb",
29
- amount: transaction.amount.value / 2,
30
- description: "Split 1"
31
- },
32
- {
33
- categoryId: "std:7daf3d79-98dd-4c85-b3cc-6d7ffd83fce9",
34
- amount: transaction.amount.value / 2,
35
- description: "Split 2"
36
- }
37
- ]
38
- })
59
+ const {data: splits} = await moneyhub.splitTransaction({...splitTestBaseInput, transactionId})
39
60
 
40
61
  expect(splits).to.have.length(2)
41
62
  })
@@ -45,8 +66,9 @@ describe("Transaction Splits", () => {
45
66
  userId,
46
67
  transactionId,
47
68
  })
48
- splitId = R.path([0, "id"], splits)
49
69
  expect(splits).to.have.length(2)
70
+ expect(R.path([0, "amount"], splits)).to.be.oneOf([-1500, -800])
71
+ expect(R.path([0, "description"], splits)).to.be.oneOf(["Split 1", "Split 2"])
50
72
  })
51
73
 
52
74
  it("can update a transactions splits", async () => {
@@ -58,7 +80,6 @@ describe("Transaction Splits", () => {
58
80
  description: "New Description"
59
81
  }
60
82
  })
61
-
62
83
  expect(splits).to.have.length(2)
63
84
  expect(R.path([0, "description"], splits)).to.equal("New Description")
64
85
  })
@@ -218,6 +218,8 @@ module.exports = ({client, config}) => {
218
218
  state,
219
219
  nonce,
220
220
  context,
221
+ readRefundAccount,
222
+ userId,
221
223
  claims = {},
222
224
  }) => {
223
225
  if (!state) {
@@ -247,8 +249,65 @@ module.exports = ({client, config}) => {
247
249
  payerId,
248
250
  payerType,
249
251
  context,
252
+ readRefundAccount,
253
+ },
254
+ },
255
+ ...userId && {
256
+ sub: {
257
+ value: userId
258
+ }
259
+ }
260
+ },
261
+ }
262
+
263
+ const _claims = R.mergeDeepRight(defaultClaims, claims)
264
+
265
+ const request = await requestObject({
266
+ scope,
267
+ state,
268
+ claims: _claims,
269
+ nonce,
270
+ })
271
+
272
+ const requestUri = await getRequestUri(request)
273
+ const url = getAuthorizeUrlFromRequestUri({
274
+ requestUri,
275
+ })
276
+ return url
277
+ },
278
+
279
+ getReversePaymentAuthorizeUrl: async ({
280
+ bankId,
281
+ paymentId,
282
+ state,
283
+ nonce,
284
+ claims = {},
285
+ }) => {
286
+ if (!state) {
287
+ console.error("State is required")
288
+ throw new Error("Missing parameters")
289
+ }
290
+
291
+ if (!paymentId) {
292
+ console.error("PayeeId is required")
293
+ throw new Error("Missing parameters")
294
+ }
295
+
296
+ const scope = `reverse_payment openid id:${bankId}`
297
+ const defaultClaims = {
298
+ id_token: {
299
+ "mh:con_id": {
300
+ essential: true,
301
+ },
302
+ "mh:reverse_payment": {
303
+ essential: true,
304
+ value: {
305
+ paymentId,
250
306
  },
251
307
  },
308
+ "mh:payment": {
309
+ essential: true,
310
+ },
252
311
  },
253
312
  }
254
313
 
@@ -6,6 +6,8 @@ module.exports = ({config, request}) => {
6
6
  createAuthRequest: async ({
7
7
  redirectUri,
8
8
  payment,
9
+ reversePayment,
10
+ standingOrder,
9
11
  userId,
10
12
  connectionId,
11
13
  categorisationType,
@@ -20,6 +22,8 @@ module.exports = ({config, request}) => {
20
22
  body: {
21
23
  redirectUri,
22
24
  payment,
25
+ reversePayment,
26
+ standingOrder,
23
27
  userId,
24
28
  connectionId,
25
29
  scope,
@@ -11,6 +11,11 @@ module.exports = ({config, request}) => {
11
11
  },
12
12
  }),
13
13
 
14
+ getStandardCategories: async ({params = {}}) =>
15
+ request(`${resourceServerUrl}/standard-categories`, {
16
+ searchParams: params,
17
+ }),
18
+
14
19
  getCategory: async ({userId, categoryId, params = {}}) =>
15
20
  request(`${resourceServerUrl}/categories/${categoryId}`, {
16
21
  searchParams: params,
@@ -29,6 +34,11 @@ module.exports = ({config, request}) => {
29
34
  },
30
35
  }),
31
36
 
37
+ getStandardCategoryGroups: async ({params = {}}) =>
38
+ request(`${resourceServerUrl}/standard-category-groups`, {
39
+ searchParams: params,
40
+ }),
41
+
32
42
  createCustomCategory: async ({userId, category: {group, name}}) =>
33
43
  request(`${resourceServerUrl}/categories`, {
34
44
  method: "POST",
@@ -26,6 +26,16 @@ module.exports = ({config, request}) => {
26
26
  },
27
27
  body: transaction
28
28
  }),
29
+ addTransactions: ({userId, transactions, params = {}}) =>
30
+ request(`${resourceServerUrl}/transactions-collection`, {
31
+ method: "POST",
32
+ searchParams: params,
33
+ cc: {
34
+ scope: "transactions:read:all transactions:write:all",
35
+ sub: userId,
36
+ },
37
+ body: transactions
38
+ }),
29
39
  updateTransaction: ({userId, transactionId, transaction}) =>
30
40
  request(`${resourceServerUrl}/transactions/${transactionId}`, {
31
41
  method: "PATCH",