-
Notifications
You must be signed in to change notification settings - Fork 14
/
SwedbankJson.php
433 lines (374 loc) · 14.8 KB
/
SwedbankJson.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
<?php
namespace SwedbankJson;
use Exception;
use SwedbankJson\Auth\AbstractAuth;
use SwedbankJson\Exception\UserException;
/**
* Class SwedbankJson
*/
class SwedbankJson
{
/** @var AbstractAuth */
private $_auth;
/** @var string */
private $_profileID;
/**
* SwedbankJson constructor.
*
* @param AbstractAuth $auth One of the authentication types.
*/
public function __construct(AbstractAuth $auth)
{
$this->_auth = $auth;
}
/**
* Profile information
*
* List of available user profile(s) with per session IDs. Each user can only have one private profile but several corporate profiles.
* Profile ID is a 40 characters long string that looks like a SHA1 hash, found in privateProfile->id or corporateProfiles->id.
*
* @return object JSON decoded response from the API.
* @throws Exception
*/
public function profileList()
{
$client = $this->_auth->getClient();
if (empty($client))
$this->_auth->login();
$output = $this->_auth->getRequest('profile/');
if (!isset($output->hasSwedbankProfile))
throw new Exception('Unknown error with the profile page.', 20);
if (!isset($output->banks[0]->bankId))
{
if (!$output->hasSwedbankProfile AND $output->hasSavingsbankProfile)
{
throw new UserException(
"The user is not a customer in Swedbank. Please choose one of the Sparbanken's bank types (sparbanken or sparbanken_foretag)",
21
);
}
elseif ($output->hasSwedbankProfile AND !$output->hasSavingsbankProfile)
{
throw new UserException(
"The user is not a customer in Sparbanken. Please choose one of the Swedbank's bank types (swedbank or swedbank_foretag)",
22
);
}
else
throw new Exception('The profile do not contain any bank accounts.', 23);
}
return $output->banks[0];
}
/**
* Selecting profile
*
* @param string $profileID ProfileID
*
* @return null If profile already selected.
* @throws Exception
*/
private function selectProfile($profileID = '')
{
// If profile ID not defined, choose default profile
if (empty($profileID))
{
if ($this->_profileID)
return null; // If profile already selected
$profiles = $this->profileList();
$profileData = $profiles->{$this->_auth->getProfileType()}; // Depending on selected bank type, it will wither choose a private or corporate profile
$profileID = (isset($profileData->id)) ? $profileData->id : $profileData[0]->id; // Default profile
}
// Request profile cahnge
$this->_auth->postRequest('profile/'.$profileID);
$this->_profileID = $profileID;
}
/**
* Reminders and notifications
*
* Lists number of rejected payments, payments signed, unsigned transfers and incoming e-invoices.
*
* @return object Decoded JSON reminder and notification list
* @throws Exception
*/
public function reminders()
{
$this->selectProfile();
return $this->_auth->getRequest('message/reminders');
}
/**
* Lists accounts available to the profile.
*
* Type of accounts that are listed:
*
* * transactionAccounts - Regular accounts
* * transactionDisposalAccounts - Disposal accounts
* * loanAccounts - Loans (including mortgage)
* * savingAccounts - Savings accounts
* * cardAccounts - Credit cards
* * cardCredit - Credit information
*
* NOTE: Use quickBalanceAccounts() to list quick balance accounts. Do not rely on the 'selectedForQuickbalance' attribute.
*
* @param string $profileID Profile ID
*
* @return object Decoded JSON detailed account list
* @throws Exception
*/
public function accountList($profileID = '')
{
$this->selectProfile($profileID);
$output = $this->_auth->getRequest('engagement/overview');
if (!isset($output->transactionAccounts))
throw new Exception("Can not fetch account list.", 30);
return $output;
}
/**
* Lists investment savings available to the profile.
*
* @param string $profileID Profile ID
*
* @return object Decoded JSON investment savings list
* @throws Exception
*/
public function portfolioList($profileID = '')
{
$this->selectProfile($profileID);
$output = $this->_auth->getRequest('portfolio/holdings');
if (!isset($output->savingsAccounts))
throw new Exception('Can not fetch investment savings list.', 40);
return $output;
}
/**
* Account details and bank statements.
*
* @param string $accountID Account ID. If left blank, the default account is chosen.
* @param int $transactionsPerPage Bank statements per page. Default 50.
* @param int $page Bank statements paging index.
*
* @return object Decoded JSON with account information
* @throws Exception Not valid AccountID
*/
public function accountDetails($accountID = '', $transactionsPerPage = 0, $page = 1)
{
// If account ID not defined, choose default account
if (empty($accountID))
$accountID = $this->accountList()->transactionAccounts[0]->id;
$query = [];
if ($transactionsPerPage > 0 AND $page >= 1)
$query = ['transactionsPerPage' => (int)$transactionsPerPage, 'page' => (int)$page,];
$output = $this->_auth->getRequest('engagement/transactions/'.$accountID, $query);
if (!isset($output->transactions))
throw new Exception('Not a valid AccountID', 50);
return $output;
}
/**
* Get detailed information about a transaction.
*
* @param string $detailsTransactionID Detailed transaction ID
*
* @return object Decoded JSON with detailed transaction information
* @throws Exception Not a valid DetailsTransactionID
*/
public function transactionDetails($detailsTransactionID)
{
$output = $this->_auth->getRequest('engagement/transactions/details/'.$detailsTransactionID);
if (!isset($output->transactionDate))
throw new Exception('Not a valid DetailsTransactionID', 60);
return $output;
}
/**
* Information to create a payment
*
* Lists accounts that are can be send or receive a payment. In order to crate a payment transaction, both sender and receiver account must be selected from this list.
*
* The list contains following account types:
*
* * Payment - External accounts. Mostly Bankgiro and Plusgiro accounts typically used by organizations and companies. Used for eg. paying bills.
* * Transfer - External bank accounts.
* * TransactionAccountGroups - Personal/private bank accounts.
* * InternationalRecipients - External international accounts.
*
* NOTE: Currently this project dose not actions that needs to be signed. In this case, adding new receptions or do payments to a external accounts require to be signed.
* Generally accounts listed in "TransactionAccountGroups" do not require to be signed to confirm a payment. However make sure that the sender account have "TRANSFER_FROM"
* scope type, and the receive account have the "TRANSFER_TO" scope type.
*
* For periodicity transferees, allowed types are listed under "transfare->periodicities".
*
* @return object Decode JSON with base payment and transfer information
* @throws Exception
*/
public function transferBaseInfo() {
$this->selectProfile();
return $this->_auth->getRequest('payment/baseinfo');
}
/**
* Add and prepare a transfer for confirmation
*
* The money will not be sent until the transfer have been confirmed, including direct transfers.
*
* NOTE: Transfers that need to be signed to confirm (eg. accounts with groupID ACCOUNT_SIGNED) are currently not supported.
* It is possible to register the transaction and than open the mobile app, to sign and confirm the transaction.
*
* @param float $amount Amount to be transferred
* @param string $fromAccountId From AccountID
* @param string $recipientAccountId Recipient AccountID
* @param string $fromAccountNote From message
* @param string $recipientAccountMessage Recipient message
* @param string $transferDate Date when the transfer will take place. Date format is YYYY-MM-DD (today's date onwards). If not specified, it is a direct transfer
* @param string $periodicity Periodicity. For possible selectable periods, see 'Periodicity' from the result of @see transferBaseInfo()
*
* @return object
*/
public function transferRegisterPayment($amount, $fromAccountId, $recipientAccountId, $fromAccountNote = '', $recipientAccountMessage = '', $transferDate = '', $periodicity = '')
{
$data = [
'amount' => number_format((float)$amount, 2, ',', ''),
'noteToSender' => $fromAccountNote,
'noteToRecipient' => $recipientAccountMessage,
'recipientId' => $recipientAccountId,
'fromAccountId' => $fromAccountId,
'date' => $transferDate,
];
if(!empty($periodicity)) {
$data['periodicity'] = $periodicity;
}
$this->_auth->postRequest('payment/registered/transfer', $data);
return $this->transferListRegistered();
}
/**
* List registered transfers
*
* Unconfirmed transfers waits to be approved/confirmed.
*
* @return object
*/
public function transferListRegistered()
{
return $this->_auth->getRequest('payment/registered');
}
/**
* List confirmed scheduled transfers
*
* Both one time feature transfers and active periodicity scheduled transfers are listed.
* Historical transfers, direct transfers and inactivated periodicity scheduled transfers are not listed.
*
* @return object
*/
public function transferListConfirmed()
{
return $this->_auth->getRequest('payment/confirmed');
}
/**
* Delete a transfer
*
* Deletes registered and confirmed transfers.
*
* @param string $transferId Transaction ID. Get ID from @see listConfirmedTransfers() or @see listRegisteredTransfers()
*/
public function transferDeletePayment($transferId)
{
$this->_auth->getRequest('payment/'.$transferId);
$this->_auth->deleteRequest('payment/'.$transferId);
}
/**
* Confirms transfers
*
* When a transfer is confirmed, the money will be sent at the scheduled time and will be listed in @see transferListRegistered().
* With transferDeletePayment(), you can cancel a transfer before the money have been sent. However confirmed direct transfers cannot be cancelled, since the money is sent
* immediately.
*
* NOTE: Transfers that need to be signed to confirm are currently not supported.
* It is possible to open the mobile app to sign and confirm the transaction.
*
* @return object
*/
public function transferConfirmPayments()
{
$transactions = $this->transferListRegistered();
if (empty($transactions->links->next->uri))
throw new UserException('There are no registered transactions to confirm.', 55);
// confirmTransferId
preg_match('#payment/confirmed/(.+)#iu', $transactions->links->next->uri, $m);
$confirmTransferId = $m[1];
return $this->_auth->putRequest('payment/confirmed/'.$confirmTransferId);
}
/**
* List of possible accounts for fetch quick balance
*
* @param string $profileID Profile ID
*
* @return object List of possible quick balance accounts. Each account have a quick balance subscription ID needed for subscription.
* @throws Exception
*/
public function quickBalanceAccounts($profileID = '')
{
$this->selectProfile($profileID);
$output = $this->_auth->getRequest('quickbalance/accounts');
if (!isset($output->accounts))
throw new Exception('Quick balance accounts cannot be listed.', 60);
return $output;
}
/**
* Subscribes a account to quick balance
*
* After successful subscription, it's important to save the SubscriptionID ("subscriptionId" attribute) on a permanent storage (eg. database).
* SubscriptionID is used to fetch quick balance and when it's time to unsubscribe.
*
* @param string $accountQuickBalanceSubID Account quick balance subscription ID.
*
* @return object A successful subscription will return a subscription ID.
* @throws Exception
*/
public function quickBalanceSubscription($accountQuickBalanceSubID)
{
$output = $this->_auth->postRequest('quickbalance/subscription/'.$accountQuickBalanceSubID);
if (!isset($output->subscriptionId))
throw new Exception('Cannot subscribe to account. Please check the ID is from "quickbalanceSubscription".', 61);
return $output;
}
/**
* Fetch quick balance
*
* Will get basic balance information (eg. account total amount)
*
* @param string $subscriptionId Subscription ID. @see quickBalanceSubscription()
*
* @return object Balance information
* @throws Exception
*/
public function quickBalance($subscriptionId)
{
$output = $this->_auth->getRequest('quickbalance/'.$subscriptionId);
if (!isset($output->balance))
throw new Exception('Cannot fetch quick balance. Please check the Subscription ID.', 62);
return $output;
}
/**
* Unsubscribes quick balance account
*
* @param string $subscriptionId Subscription ID. @see quickBalanceSubscription()
* @param string $profileID Profile ID.
*
* @return object
* @throws Exception
*/
public function quickBalanceUnsubscription($subscriptionId, $profileID = '')
{
$this->selectProfile($profileID);
$output = $this->_auth->deleteRequest('quickbalance/subscription/'.$subscriptionId);
if (!isset($output->subscriptionId))
throw new Exception('Cannot unsubscribe account. Please check the Subscription ID.', 63);
return $output;
}
/**
* Sign out
*
* Alias for @see AbstractAuth::terminate()
*
* @return object @see AbstractAuth::terminate();
*/
public function terminate()
{
return $this->_auth->terminate();
}
}