@nlabs/reaktor 0.1.2 → 0.1.4
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/.DS_Store +0 -0
- package/.eslintrc +18 -0
- package/lib/config.d.ts +21 -0
- package/lib/config.js +130 -0
- package/lib/data/conversations.d.ts +6 -0
- package/lib/data/conversations.js +197 -0
- package/lib/data/dynamodb.d.ts +8 -0
- package/lib/data/dynamodb.js +139 -0
- package/lib/data/email.d.ts +7 -0
- package/lib/data/email.js +163 -0
- package/lib/data/files.d.ts +16 -0
- package/lib/data/files.js +406 -0
- package/lib/data/groups.d.ts +13 -0
- package/lib/data/groups.js +354 -0
- package/lib/data/images.d.ts +12 -0
- package/lib/data/images.js +667 -0
- package/{src/data/index.ts → lib/data/index.d.ts} +1 -5
- package/lib/data/index.js +24 -0
- package/lib/data/ios.d.ts +6 -0
- package/lib/data/ios.js +302 -0
- package/lib/data/locations.d.ts +3 -0
- package/lib/data/locations.js +132 -0
- package/lib/data/messages.d.ts +9 -0
- package/lib/data/messages.js +248 -0
- package/lib/data/notifications.d.ts +5 -0
- package/lib/data/notifications.js +42 -0
- package/lib/data/payments.d.ts +11 -0
- package/lib/data/payments.js +748 -0
- package/lib/data/posts.d.ts +22 -0
- package/lib/data/posts.js +579 -0
- package/lib/data/reactions.d.ts +6 -0
- package/lib/data/reactions.js +218 -0
- package/lib/data/s3.d.ts +6 -0
- package/lib/data/s3.js +103 -0
- package/lib/data/search.d.ts +3 -0
- package/lib/data/search.js +98 -0
- package/lib/data/sms.d.ts +3 -0
- package/lib/data/sms.js +59 -0
- package/lib/data/subscription.d.ts +7 -0
- package/lib/data/subscription.js +284 -0
- package/lib/data/tags.d.ts +14 -0
- package/lib/data/tags.js +304 -0
- package/lib/data/users.d.ts +12 -0
- package/lib/data/users.js +310 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +8 -0
- package/lib/types/apps.d.ts +43 -0
- package/lib/types/apps.js +2 -0
- package/lib/types/arangodb.d.ts +17 -0
- package/lib/types/arangodb.js +2 -0
- package/lib/types/auth.d.ts +10 -0
- package/lib/types/auth.js +2 -0
- package/lib/types/conversations.d.ts +6 -0
- package/lib/types/conversations.js +2 -0
- package/lib/types/email.d.ts +12 -0
- package/lib/types/email.js +2 -0
- package/lib/types/files.d.ts +26 -0
- package/lib/types/files.js +2 -0
- package/lib/types/google.d.ts +27 -0
- package/lib/types/google.js +2 -0
- package/lib/types/groups.d.ts +21 -0
- package/lib/types/groups.js +2 -0
- package/lib/types/images.d.ts +24 -0
- package/lib/types/images.js +2 -0
- package/{src/types/index.ts → lib/types/index.d.ts} +0 -4
- package/lib/types/index.js +22 -0
- package/lib/types/locations.d.ts +20 -0
- package/lib/types/locations.js +2 -0
- package/lib/types/messages.d.ts +12 -0
- package/lib/types/messages.js +2 -0
- package/lib/types/notifications.d.ts +19 -0
- package/lib/types/notifications.js +2 -0
- package/lib/types/payments.d.ts +114 -0
- package/lib/types/payments.js +2 -0
- package/lib/types/posts.d.ts +28 -0
- package/lib/types/posts.js +2 -0
- package/lib/types/reactions.d.ts +4 -0
- package/lib/types/reactions.js +2 -0
- package/lib/types/tags.d.ts +9 -0
- package/lib/types/tags.js +2 -0
- package/lib/types/users.d.ts +78 -0
- package/lib/types/users.js +2 -0
- package/lib/utils/analytics.d.ts +3 -0
- package/lib/utils/analytics.js +47 -0
- package/lib/utils/arangodb.d.ts +9 -0
- package/lib/utils/arangodb.js +98 -0
- package/lib/utils/auth.d.ts +7 -0
- package/lib/utils/auth.js +80 -0
- package/lib/utils/graphql.d.ts +1 -0
- package/lib/utils/graphql.js +7 -0
- package/{src/utils/index.ts → lib/utils/index.d.ts} +0 -4
- package/lib/utils/index.js +11 -0
- package/lib/utils/objects.d.ts +3 -0
- package/lib/utils/objects.js +34 -0
- package/lib/utils/redis.d.ts +1 -0
- package/lib/utils/redis.js +15 -0
- package/package.json +8 -7
- package/.vscode/extensions.json +0 -15
- package/.vscode/settings.json +0 -82
- package/lex.config.js +0 -4
- package/src/config.ts +0 -127
- package/src/data/conversations.ts +0 -181
- package/src/data/dynamodb.ts +0 -157
- package/src/data/email.ts +0 -163
- package/src/data/files.ts +0 -352
- package/src/data/groups.ts +0 -308
- package/src/data/images.ts +0 -606
- package/src/data/ios.ts +0 -249
- package/src/data/locations.ts +0 -114
- package/src/data/messages.ts +0 -237
- package/src/data/notifications.ts +0 -48
- package/src/data/payments.ts +0 -675
- package/src/data/posts.ts +0 -580
- package/src/data/reactions.ts +0 -186
- package/src/data/s3.ts +0 -117
- package/src/data/search.ts +0 -74
- package/src/data/sms.ts +0 -60
- package/src/data/subscription.ts +0 -228
- package/src/data/tags.ts +0 -230
- package/src/data/users.ts +0 -254
- package/src/index.ts +0 -7
- package/src/types/apps.ts +0 -56
- package/src/types/arangodb.ts +0 -23
- package/src/types/auth.ts +0 -20
- package/src/types/conversations.ts +0 -11
- package/src/types/email.ts +0 -17
- package/src/types/files.ts +0 -31
- package/src/types/google.ts +0 -37
- package/src/types/groups.ts +0 -27
- package/src/types/images.ts +0 -32
- package/src/types/locations.ts +0 -24
- package/src/types/messages.ts +0 -16
- package/src/types/notifications.ts +0 -26
- package/src/types/payments.ts +0 -129
- package/src/types/posts.ts +0 -34
- package/src/types/reactions.ts +0 -8
- package/src/types/tags.ts +0 -13
- package/src/types/users.ts +0 -89
- package/src/utils/analytics.ts +0 -41
- package/src/utils/arangodb.ts +0 -100
- package/src/utils/auth.ts +0 -61
- package/src/utils/graphql.ts +0 -7
- package/src/utils/objects.ts +0 -34
- package/src/utils/redis.ts +0 -17
- package/tsconfig.json +0 -45
package/src/data/payments.ts
DELETED
|
@@ -1,675 +0,0 @@
|
|
|
1
|
-
import {createHash, parseChar, parseId, parseNum, parseString, parseVarChar} from '@nlabs/utils';
|
|
2
|
-
import {aql} from 'arangojs';
|
|
3
|
-
import {AqlQuery} from 'arangojs/lib/cjs/aql-query';
|
|
4
|
-
import {ArrayCursor} from 'arangojs/lib/cjs/cursor';
|
|
5
|
-
import {UserError} from 'graphql-errors';
|
|
6
|
-
import isEmpty from 'lodash/isEmpty';
|
|
7
|
-
import {DateTime} from 'luxon';
|
|
8
|
-
import * as stripe from 'stripe';
|
|
9
|
-
|
|
10
|
-
import {Config} from '../config';
|
|
11
|
-
import {ApiContext, PaymentBankAccount, PaymentCardType, PaymentCharge, PaymentTransfer, UserType} from '../types';
|
|
12
|
-
import {logError} from '../utils/analytics';
|
|
13
|
-
import {useDb} from '../utils/arangodb';
|
|
14
|
-
import {getUser} from './users';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Copyright (c) 2019-Present, Nitrogen Labs, Inc.
|
|
18
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
19
|
-
*/
|
|
20
|
-
const eventCategory: string = 'payments';
|
|
21
|
-
|
|
22
|
-
export const addCustomerAccount = (context: ApiContext): Promise<boolean> => {
|
|
23
|
-
const action: string = 'addCustomerAccount';
|
|
24
|
-
const {database, userId: sessionId, username} = context;
|
|
25
|
-
|
|
26
|
-
// Stripe
|
|
27
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
28
|
-
|
|
29
|
-
return stripeClient.customers
|
|
30
|
-
.create({
|
|
31
|
-
metadata: {
|
|
32
|
-
userId: sessionId,
|
|
33
|
-
username
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
.then((customer) => {
|
|
37
|
-
// Create session
|
|
38
|
-
const now: number = Date.now();
|
|
39
|
-
const update: UserType = {
|
|
40
|
-
modified: now,
|
|
41
|
-
stripeCustomerId: customer.id
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const aqlQry: AqlQuery = aql`UPDATE ${sessionId} WITH ${update} IN users LIMIT 1 RETURN NEW`;
|
|
45
|
-
|
|
46
|
-
return useDb(database).query(aqlQry)
|
|
47
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
48
|
-
.then((updatedUser: UserType = {}) => !isEmpty(updatedUser))
|
|
49
|
-
.catch((error: Error) => logError({
|
|
50
|
-
action,
|
|
51
|
-
category: eventCategory,
|
|
52
|
-
label: 'db_error'
|
|
53
|
-
}, error, context).then(() => null));
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const addPaymentAccountBank = (context: ApiContext, bankAccount: PaymentBankAccount): Promise<boolean> => {
|
|
58
|
-
const action: string = 'addPaymentAccountBank';
|
|
59
|
-
const {database, userId: sessionId} = context;
|
|
60
|
-
|
|
61
|
-
// Params
|
|
62
|
-
const {
|
|
63
|
-
accountNumber,
|
|
64
|
-
fullName,
|
|
65
|
-
routing
|
|
66
|
-
} = bankAccount;
|
|
67
|
-
|
|
68
|
-
const formatAccount: string = parseString(accountNumber, 32);
|
|
69
|
-
|
|
70
|
-
if(formatAccount === '') {
|
|
71
|
-
throw new UserError('required_account_number');
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const formatFullName: string = parseVarChar(fullName, 128);
|
|
75
|
-
|
|
76
|
-
if(formatFullName === '') {
|
|
77
|
-
throw new UserError('required_full_name');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const formatRouting: string = parseString(routing, 32);
|
|
81
|
-
|
|
82
|
-
if(formatRouting === '') {
|
|
83
|
-
throw new UserError('required_routing_number');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return getUser(context, sessionId)
|
|
87
|
-
.then((user: UserType) => {
|
|
88
|
-
// Stripe
|
|
89
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
90
|
-
|
|
91
|
-
return stripeClient.customers
|
|
92
|
-
.createSource(user.stripeAccountId, {
|
|
93
|
-
source: {
|
|
94
|
-
account_holder_name: formatFullName,
|
|
95
|
-
account_holder_type: 'individual',
|
|
96
|
-
account_number: formatAccount,
|
|
97
|
-
country: 'US',
|
|
98
|
-
currency: 'USD',
|
|
99
|
-
object: 'bank_account',
|
|
100
|
-
routing_number: formatRouting
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
.then((account) => {
|
|
104
|
-
const update: any = {
|
|
105
|
-
bankAccount: account.last4,
|
|
106
|
-
bankFullName: formatFullName,
|
|
107
|
-
bankId: account.id,
|
|
108
|
-
bankRouting: account.routing_number,
|
|
109
|
-
modified: Date.now()
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const aqlQry: AqlQuery = aql`UPDATE ${sessionId} WITH ${update} IN users LIMIT 1 RETURN NEW`;
|
|
113
|
-
|
|
114
|
-
return useDb(database).query(aqlQry)
|
|
115
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
116
|
-
.then((updatedUser: UserType = {}) => updatedUser);
|
|
117
|
-
})
|
|
118
|
-
.catch((error: Error) => {
|
|
119
|
-
const msg = error.message;
|
|
120
|
-
|
|
121
|
-
if(msg === 'A bank account with that routing number and account number ' +
|
|
122
|
-
'already exists for this customer.') {
|
|
123
|
-
return logError({
|
|
124
|
-
action,
|
|
125
|
-
category: eventCategory,
|
|
126
|
-
label: 'bank_account_exists'
|
|
127
|
-
}, error, context).then(() => null);
|
|
128
|
-
}
|
|
129
|
-
return logError({
|
|
130
|
-
action,
|
|
131
|
-
category: eventCategory,
|
|
132
|
-
label: 'payment_error'
|
|
133
|
-
}, error, context).then(() => null);
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
export const addPaymentAccountCard = (context: ApiContext, card: PaymentCardType, requestData): Promise<UserType> => {
|
|
139
|
-
const action: string = 'addPaymentAccountCard';
|
|
140
|
-
const {database, userId: sessionId} = context;
|
|
141
|
-
|
|
142
|
-
return getUser(context, sessionId)
|
|
143
|
-
.then((user: UserType) => {
|
|
144
|
-
// User
|
|
145
|
-
const {
|
|
146
|
-
_key: userKey,
|
|
147
|
-
country = 'US',
|
|
148
|
-
city,
|
|
149
|
-
currency = 'USD',
|
|
150
|
-
dob,
|
|
151
|
-
email,
|
|
152
|
-
first,
|
|
153
|
-
last,
|
|
154
|
-
username
|
|
155
|
-
}: UserType = user;
|
|
156
|
-
|
|
157
|
-
// Birthday
|
|
158
|
-
const dobDay: number = +(DateTime.fromMillis(dob).toFormat('d'));
|
|
159
|
-
const dobMonth: number = +(DateTime.fromMillis(dob).toFormat('M'));
|
|
160
|
-
const dobYear: number = +(DateTime.fromMillis(dob).toFormat('y'));
|
|
161
|
-
|
|
162
|
-
// Card
|
|
163
|
-
const {
|
|
164
|
-
accountNumber,
|
|
165
|
-
acceptedTerms,
|
|
166
|
-
expMonth,
|
|
167
|
-
expYear,
|
|
168
|
-
state,
|
|
169
|
-
street1,
|
|
170
|
-
zip
|
|
171
|
-
}: PaymentCardType = card;
|
|
172
|
-
|
|
173
|
-
// Acceptance
|
|
174
|
-
const accepted: number = acceptedTerms ? DateTime.local().millisecond : 0;
|
|
175
|
-
|
|
176
|
-
// Stripe
|
|
177
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
178
|
-
|
|
179
|
-
return stripeClient.accounts
|
|
180
|
-
.create({
|
|
181
|
-
country,
|
|
182
|
-
email,
|
|
183
|
-
external_account: {
|
|
184
|
-
currency,
|
|
185
|
-
exp_month: expMonth,
|
|
186
|
-
exp_year: expYear,
|
|
187
|
-
number: accountNumber,
|
|
188
|
-
object: 'card'
|
|
189
|
-
},
|
|
190
|
-
legal_entity: {
|
|
191
|
-
address: {
|
|
192
|
-
city,
|
|
193
|
-
line1: street1,
|
|
194
|
-
postal_code: zip,
|
|
195
|
-
state
|
|
196
|
-
},
|
|
197
|
-
dob: {
|
|
198
|
-
day: dobDay,
|
|
199
|
-
month: dobMonth,
|
|
200
|
-
year: dobYear
|
|
201
|
-
},
|
|
202
|
-
first_name: first,
|
|
203
|
-
last_name: last,
|
|
204
|
-
// ssn_last_4: ssn.substr(-4),
|
|
205
|
-
// personal_id_number: ssn,
|
|
206
|
-
type: 'individual'
|
|
207
|
-
},
|
|
208
|
-
managed: true,
|
|
209
|
-
metadata: {
|
|
210
|
-
userId: userKey,
|
|
211
|
-
username
|
|
212
|
-
},
|
|
213
|
-
tos_acceptance: {
|
|
214
|
-
date: accepted,
|
|
215
|
-
ip: requestData.ip,
|
|
216
|
-
user_agent: requestData.userAgent.source
|
|
217
|
-
}
|
|
218
|
-
})
|
|
219
|
-
.then((customer) => {
|
|
220
|
-
// Create session
|
|
221
|
-
const now: number = Date.now();
|
|
222
|
-
const update: UserType = {
|
|
223
|
-
modified: now,
|
|
224
|
-
stripeAccountId: customer.id
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
const aqlQry: AqlQuery = aql`UPDATE ${userKey} WITH ${update} IN users LIMIT 1 RETURN NEW`;
|
|
228
|
-
|
|
229
|
-
return useDb(database).query(aqlQry)
|
|
230
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
231
|
-
.then((updatedUser: UserType = {}) => !isEmpty(updatedUser))
|
|
232
|
-
.catch((error: Error) => logError({
|
|
233
|
-
action,
|
|
234
|
-
category: eventCategory,
|
|
235
|
-
label: 'db_error'
|
|
236
|
-
}, error, context).then(() => null));
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
export const addCreditCard = (context: ApiContext, card: PaymentCardType): Promise<PaymentCardType> => {
|
|
242
|
-
const action: string = 'addCreditCard';
|
|
243
|
-
const {database, userId: sessionId} = context;
|
|
244
|
-
|
|
245
|
-
const {
|
|
246
|
-
accountNumber,
|
|
247
|
-
city,
|
|
248
|
-
country,
|
|
249
|
-
cvc,
|
|
250
|
-
expMonth,
|
|
251
|
-
expYear,
|
|
252
|
-
fullName,
|
|
253
|
-
street1,
|
|
254
|
-
state,
|
|
255
|
-
zip
|
|
256
|
-
}: PaymentCardType = card;
|
|
257
|
-
const formatNumber: number = parseNum(accountNumber, 16);
|
|
258
|
-
|
|
259
|
-
if(!formatNumber) {
|
|
260
|
-
throw new UserError('required_credit_card_number');
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const formatExpMonth: number = parseNum(expMonth, 2);
|
|
264
|
-
|
|
265
|
-
if(!formatExpMonth) {
|
|
266
|
-
throw new UserError('required_credit_card_exp_month');
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const formatExpYear: number = parseNum(expYear, 2);
|
|
270
|
-
|
|
271
|
-
if(!formatExpYear) {
|
|
272
|
-
throw new UserError('required_credit_card_exp_year');
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const formatCvc: number = parseNum(cvc, 3);
|
|
276
|
-
|
|
277
|
-
if(!formatCvc) {
|
|
278
|
-
throw new UserError('required_credit_card_cvc');
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const paymentCard: PaymentCardType = {};
|
|
282
|
-
const formatCity: string = parseVarChar(city, 32);
|
|
283
|
-
|
|
284
|
-
if(formatCity) {
|
|
285
|
-
paymentCard.city = formatCity;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const formatCountry: string = parseVarChar(country, 32);
|
|
289
|
-
|
|
290
|
-
if(formatCountry) {
|
|
291
|
-
paymentCard.country = formatCountry;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const formatFullName: string = parseVarChar(fullName, 32);
|
|
295
|
-
|
|
296
|
-
if(formatFullName) {
|
|
297
|
-
paymentCard.fullName = formatFullName;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const formatStreet: string = parseVarChar(street1, 32);
|
|
301
|
-
|
|
302
|
-
if(formatStreet) {
|
|
303
|
-
paymentCard.street1 = formatStreet;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const formatState: string = parseVarChar(state, 32);
|
|
307
|
-
|
|
308
|
-
if(formatState) {
|
|
309
|
-
paymentCard.state = formatState;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const formatZip: string = parseVarChar(zip, 32);
|
|
313
|
-
|
|
314
|
-
if(formatZip) {
|
|
315
|
-
paymentCard.zip = formatZip;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Get stripe id
|
|
319
|
-
return getUser(context, sessionId)
|
|
320
|
-
.then((user: UserType = {}) => {
|
|
321
|
-
// Stripe
|
|
322
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
323
|
-
|
|
324
|
-
return stripeClient.customers
|
|
325
|
-
.createSource(user.stripeCustomerId, {
|
|
326
|
-
source: {
|
|
327
|
-
address_city: formatCity,
|
|
328
|
-
address_country: formatCountry,
|
|
329
|
-
address_line1: formatStreet,
|
|
330
|
-
address_state: formatState,
|
|
331
|
-
address_zip: formatZip,
|
|
332
|
-
currency: 'usd',
|
|
333
|
-
cvc: formatCvc,
|
|
334
|
-
exp_month: formatExpMonth,
|
|
335
|
-
exp_year: formatExpYear,
|
|
336
|
-
name: formatFullName,
|
|
337
|
-
number: formatNumber,
|
|
338
|
-
object: 'card'
|
|
339
|
-
}
|
|
340
|
-
})
|
|
341
|
-
.then((stripeObj) => {
|
|
342
|
-
const now: number = Date.now();
|
|
343
|
-
const insert = {
|
|
344
|
-
...paymentCard,
|
|
345
|
-
_key: createHash(`user-payment-${sessionId}`),
|
|
346
|
-
accountNumber: stripeObj.last4,
|
|
347
|
-
added: now,
|
|
348
|
-
brand: stripeObj.brand,
|
|
349
|
-
cvc: stripeObj.cvc_check,
|
|
350
|
-
expMonth,
|
|
351
|
-
expYear,
|
|
352
|
-
modified: now,
|
|
353
|
-
userId: sessionId
|
|
354
|
-
};
|
|
355
|
-
const insertAqlQry: AqlQuery = aql`INSERT ${insert} IN creditCards RETURN NEW`;
|
|
356
|
-
|
|
357
|
-
return useDb(database).query(insertAqlQry)
|
|
358
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
359
|
-
.then((newCard: PaymentCardType = {}) => {
|
|
360
|
-
if(!isEmpty(newCard)) {
|
|
361
|
-
// Add linked edge
|
|
362
|
-
const {_id: cardId, _key: cardKey} = card;
|
|
363
|
-
const edgeCollection = useDb(database).edgeCollection('hasPayment');
|
|
364
|
-
const edgeId = createHash(`payment-${cardKey}`);
|
|
365
|
-
const edge: any = {
|
|
366
|
-
_key: edgeId
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
return edgeCollection.save(edge, `users/${sessionId}`, cardId).then(() => card);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return newCard;
|
|
373
|
-
});
|
|
374
|
-
})
|
|
375
|
-
.catch((error: Error) => logError({
|
|
376
|
-
action,
|
|
377
|
-
category: eventCategory,
|
|
378
|
-
label: 'payment_error'
|
|
379
|
-
}, error, context).then(() => null));
|
|
380
|
-
});
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
export const updateCreditCard = (context: ApiContext, card: PaymentCardType): Promise<PaymentCardType> => {
|
|
384
|
-
const {database, userId: sessionId} = context;
|
|
385
|
-
|
|
386
|
-
const {
|
|
387
|
-
city,
|
|
388
|
-
country,
|
|
389
|
-
expMonth,
|
|
390
|
-
expYear,
|
|
391
|
-
fullName,
|
|
392
|
-
id,
|
|
393
|
-
street1,
|
|
394
|
-
state,
|
|
395
|
-
zip
|
|
396
|
-
}: PaymentCardType = card;
|
|
397
|
-
|
|
398
|
-
const formatId: string = parseId(id);
|
|
399
|
-
|
|
400
|
-
if(formatId) {
|
|
401
|
-
throw new UserError('required_credit_card_id');
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
const paymentCard: PaymentCardType = {};
|
|
405
|
-
const formatExpMonth: number = parseNum(expMonth, 2);
|
|
406
|
-
const formatExpYear: number = parseNum(expYear, 2);
|
|
407
|
-
const formatCity: string = parseVarChar(city, 32);
|
|
408
|
-
const formatCountry: string = parseVarChar(country, 2);
|
|
409
|
-
const formatFullName: string = parseVarChar(fullName, 32);
|
|
410
|
-
const formatStreet1: string = parseString(street1, 32);
|
|
411
|
-
const formatState: string = parseVarChar(state, 2);
|
|
412
|
-
const formatZip: string = parseVarChar(zip, 10);
|
|
413
|
-
|
|
414
|
-
if(formatExpMonth) {
|
|
415
|
-
paymentCard.expMonth = formatExpMonth;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
if(formatExpYear) {
|
|
419
|
-
paymentCard.expYear = formatExpYear;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if(formatCity) {
|
|
423
|
-
paymentCard.city = formatCity;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
if(formatCountry) {
|
|
427
|
-
paymentCard.country = formatCountry;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
if(formatFullName) {
|
|
431
|
-
paymentCard.fullName = formatFullName;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
if(formatStreet1) {
|
|
435
|
-
paymentCard.street1 = formatStreet1;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
if(formatState) {
|
|
439
|
-
paymentCard.state = formatState;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
if(formatZip) {
|
|
443
|
-
paymentCard.zip = formatZip;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
const update: any = paymentCard;
|
|
447
|
-
const aqlQry: AqlQuery = aql`
|
|
448
|
-
LET updatedCard = FIRST(
|
|
449
|
-
FOR c IN creditCards
|
|
450
|
-
FILTER c._key == ${formatId} && c.userId == ${sessionId}
|
|
451
|
-
UPDATE c WITH ${update} IN creditCards
|
|
452
|
-
LIMIT 1
|
|
453
|
-
RETURN NEW
|
|
454
|
-
)
|
|
455
|
-
LET user = FIRST(
|
|
456
|
-
FOR u IN users
|
|
457
|
-
FILTER u._key == ${sessionId}
|
|
458
|
-
LIMIT 1
|
|
459
|
-
RETURN u
|
|
460
|
-
)
|
|
461
|
-
RETURN {user: user, card: updatedCard}`;
|
|
462
|
-
|
|
463
|
-
return useDb(database).query(aqlQry)
|
|
464
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
465
|
-
.then((results = {card: {}, user: {}}) => {
|
|
466
|
-
const updatedCard: PaymentCardType = results.card;
|
|
467
|
-
const {user} = results;
|
|
468
|
-
|
|
469
|
-
if(isEmpty(updatedCard)) {
|
|
470
|
-
throw new UserError('not_found');
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Stripe
|
|
474
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
475
|
-
|
|
476
|
-
return stripeClient.customers
|
|
477
|
-
.updateCard(user.stripeCustomerId, card.stripeId, {
|
|
478
|
-
address_city: formatCity,
|
|
479
|
-
address_country: formatCountry,
|
|
480
|
-
address_line1: formatStreet1,
|
|
481
|
-
address_state: formatState,
|
|
482
|
-
address_zip: formatZip,
|
|
483
|
-
exp_month: formatExpMonth,
|
|
484
|
-
exp_year: formatExpYear,
|
|
485
|
-
name: formatFullName
|
|
486
|
-
})
|
|
487
|
-
.then(() => card)
|
|
488
|
-
.catch((error: Error) => {
|
|
489
|
-
console.log('payments::updateCard::error', error);
|
|
490
|
-
throw new UserError('payment_error');
|
|
491
|
-
});
|
|
492
|
-
});
|
|
493
|
-
};
|
|
494
|
-
|
|
495
|
-
export const getCreditCards = (context: ApiContext): Promise<PaymentCardType[]> => {
|
|
496
|
-
const action: string = 'getCreditCards';
|
|
497
|
-
const {database, userId: sessionId} = context;
|
|
498
|
-
const aqlQry: AqlQuery = aql`FOR c IN creditCards
|
|
499
|
-
FILTER c.userId == ${sessionId}
|
|
500
|
-
RETURN c`;
|
|
501
|
-
|
|
502
|
-
return useDb(database).query(aqlQry)
|
|
503
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
504
|
-
.then((list: PaymentCardType[] = []) => list)
|
|
505
|
-
.catch((error: Error) => logError({
|
|
506
|
-
action,
|
|
507
|
-
category: eventCategory,
|
|
508
|
-
label: 'db_error'
|
|
509
|
-
}, error, context).then(() => null));
|
|
510
|
-
};
|
|
511
|
-
|
|
512
|
-
export const deleteCreditCard = (context: ApiContext, cardId: string): Promise<boolean> => {
|
|
513
|
-
const {database, userId: sessionId} = context;
|
|
514
|
-
const formatCardId: string = parseId(cardId);
|
|
515
|
-
const aqlQry: AqlQuery = aql`
|
|
516
|
-
LET card = FIRST(
|
|
517
|
-
FOR c IN creditCards
|
|
518
|
-
FILTER c._key == ${formatCardId} && c.userId == ${sessionId}
|
|
519
|
-
LIMIT 1
|
|
520
|
-
REMOVE c IN creditCards
|
|
521
|
-
RETURN OLD
|
|
522
|
-
)
|
|
523
|
-
LET user = FIRST(
|
|
524
|
-
FOR u IN users
|
|
525
|
-
FILTER u._key == ${sessionId}
|
|
526
|
-
LIMIT 1
|
|
527
|
-
RETURN u
|
|
528
|
-
)
|
|
529
|
-
RETURN {user: user, card: card}`;
|
|
530
|
-
|
|
531
|
-
return useDb(database).query(aqlQry)
|
|
532
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
533
|
-
.then((result = {card: {}, user: {}}) => {
|
|
534
|
-
if(isEmpty(result)) {
|
|
535
|
-
return false;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
const {card, user} = result;
|
|
539
|
-
const {_key: cardKey} = card;
|
|
540
|
-
|
|
541
|
-
// Remove linked edges
|
|
542
|
-
const edgeCollection = useDb(database).edgeCollection('hasPayment');
|
|
543
|
-
|
|
544
|
-
return edgeCollection.outEdges(cardKey)
|
|
545
|
-
.then((edges) => {
|
|
546
|
-
if(edges.length) {
|
|
547
|
-
return Promise.all(
|
|
548
|
-
edges.map((edge) => {
|
|
549
|
-
const {_key: edgeKey} = edge;
|
|
550
|
-
const removeAqlQry: AqlQuery = aql`REMOVE {_key:${edgeKey}} IN hasPayment`;
|
|
551
|
-
return useDb(database).query(removeAqlQry);
|
|
552
|
-
}))
|
|
553
|
-
.then(() => {
|
|
554
|
-
// Stripe
|
|
555
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
556
|
-
|
|
557
|
-
return stripeClient.customers
|
|
558
|
-
.deleteCard(user.stripeCustomerId, card.stripeId)
|
|
559
|
-
.then(() => true)
|
|
560
|
-
.catch((error: Error) => {
|
|
561
|
-
console.log('payments::deleteCard::error', error);
|
|
562
|
-
throw new UserError('payment_error');
|
|
563
|
-
});
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
return false;
|
|
568
|
-
});
|
|
569
|
-
});
|
|
570
|
-
};
|
|
571
|
-
|
|
572
|
-
export const deletePaymentAccountBank = (context: ApiContext, bankId: string): Promise<boolean> => {
|
|
573
|
-
const {database, userId: sessionId} = context;
|
|
574
|
-
|
|
575
|
-
// Clean db
|
|
576
|
-
const update: UserType = {
|
|
577
|
-
bankAccount: '',
|
|
578
|
-
bankFullName: '',
|
|
579
|
-
bankId: '',
|
|
580
|
-
bankRouting: '',
|
|
581
|
-
modified: Date.now()
|
|
582
|
-
};
|
|
583
|
-
const aqlQry: AqlQuery = aql`UPDATE ${sessionId} WITH ${update} IN users LIMIT 1 RETURN NEW`;
|
|
584
|
-
|
|
585
|
-
return useDb(database).query(aqlQry)
|
|
586
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
587
|
-
.then((user: UserType = {}) => {
|
|
588
|
-
// Stripe
|
|
589
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
590
|
-
|
|
591
|
-
return stripeClient.customers
|
|
592
|
-
.deleteSource(user.stripeAccountId, bankId)
|
|
593
|
-
.then((response = {deleted: false}) => response.deleted)
|
|
594
|
-
.catch(() => Promise.resolve(false));
|
|
595
|
-
});
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
export const createPaymentTransfer = (context: ApiContext, transfer: PaymentTransfer): Promise<PaymentTransfer> => {
|
|
599
|
-
const {database, userId: sessionId} = context;
|
|
600
|
-
const {amount, currency} = transfer;
|
|
601
|
-
const formatAmount: number = parseNum(amount);
|
|
602
|
-
const formatCurrency: string = parseChar(currency, 3, 'USD').toUpperCase();
|
|
603
|
-
|
|
604
|
-
return getUser(context, sessionId)
|
|
605
|
-
.then((user: UserType) => {
|
|
606
|
-
// Stripe
|
|
607
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
608
|
-
|
|
609
|
-
return stripeClient.transfers
|
|
610
|
-
.create({
|
|
611
|
-
amount: formatAmount,
|
|
612
|
-
currency: formatCurrency,
|
|
613
|
-
destination: user.stripeAccountId
|
|
614
|
-
})
|
|
615
|
-
.then((stripeTransfer) => {
|
|
616
|
-
console.log(stripeTransfer);
|
|
617
|
-
const now: number = Date.now();
|
|
618
|
-
const insert: PaymentTransfer = {
|
|
619
|
-
added: now,
|
|
620
|
-
amount: formatAmount,
|
|
621
|
-
currency: formatCurrency,
|
|
622
|
-
modified: now,
|
|
623
|
-
userId: sessionId
|
|
624
|
-
};
|
|
625
|
-
const aqlQry: AqlQuery = aql`INSERT ${insert} IN transfers RETURN NEW`;
|
|
626
|
-
|
|
627
|
-
return useDb(database).query(aqlQry)
|
|
628
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
629
|
-
.then((newTransfer: PaymentTransfer) => newTransfer);
|
|
630
|
-
});
|
|
631
|
-
});
|
|
632
|
-
};
|
|
633
|
-
|
|
634
|
-
export const createPaymentHold = (context: ApiContext, payment: PaymentCharge): Promise<PaymentCharge> => {
|
|
635
|
-
const {database, userId: sessionId} = context;
|
|
636
|
-
const {amount, capture, cardId, currency, description} = payment;
|
|
637
|
-
const formatCurrency = parseChar(currency, 3, 'USD').toUpperCase();
|
|
638
|
-
|
|
639
|
-
const stripeClient = stripe(Config.get('stripe.token'));
|
|
640
|
-
|
|
641
|
-
return stripeClient.charges
|
|
642
|
-
.create({
|
|
643
|
-
amount,
|
|
644
|
-
capture,
|
|
645
|
-
currency: formatCurrency,
|
|
646
|
-
description,
|
|
647
|
-
source: cardId
|
|
648
|
-
})
|
|
649
|
-
.then((stripeCharge) => {
|
|
650
|
-
const now: number = Date.now();
|
|
651
|
-
const insert: PaymentCharge = {
|
|
652
|
-
added: now,
|
|
653
|
-
amount,
|
|
654
|
-
capture,
|
|
655
|
-
cardId,
|
|
656
|
-
chargeFailCode: stripeCharge.failure_code,
|
|
657
|
-
chargeFailMsg: stripeCharge.failure_message,
|
|
658
|
-
chargeId: stripeCharge.id,
|
|
659
|
-
chargeStatus: stripeCharge.status,
|
|
660
|
-
currency: formatCurrency,
|
|
661
|
-
description,
|
|
662
|
-
modified: now,
|
|
663
|
-
userId: sessionId
|
|
664
|
-
};
|
|
665
|
-
const aqlQry: AqlQuery = aql`INSERT ${insert} IN payments RETURN NEW`;
|
|
666
|
-
|
|
667
|
-
return useDb(database).query(aqlQry)
|
|
668
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
669
|
-
.then((newPayment: PaymentCharge) => newPayment);
|
|
670
|
-
})
|
|
671
|
-
.catch((error: Error) => {
|
|
672
|
-
console.log('payments::createHold::error', error);
|
|
673
|
-
throw new UserError('payment_error');
|
|
674
|
-
});
|
|
675
|
-
};
|