import { MAX_CARD_ATTEMPTS, PAYMENT_API_SHARED_KEY, PAYMENT_API_URL, USER_API_SHARED_KEY, USER_API_URL } from '../../lib/constants' import { OystAPIS, makeError, replies } from '@oyst/utils' import { cardSession, orderSession } from '../../sessions' import { isEmpty, isNil, merge, omit } from 'ramda' import { card as Card } from './../../lib/utils' import UUID from 'uuid/v1' import authorizeHandler from '../../handlers/authorize' import { session as headers } from '../../validators/headers' import log from '../../lib/log' import { create as payload } from '../../validators/users' import sessionHandler from '../../handlers/session' const { error } = replies export default { config: { pre: [authorizeHandler, sessionHandler], validate: { headers, payload } }, handler: async (req, reply) => { try { const sessionID = req.pre.authorization.data.id as string const { email, address, billing_address } = req.payload try { const { success } = await orderSession.getData<{ success: boolean }>(sessionID, 'mfa-validated') if (!success) { return error(makeError('CLICK-403', 'mfa-not-validated'), reply) } } catch (err) { return error(makeError('CLICK-403', 'mfa-not-validated'), reply) } const { phone } = await orderSession.getData<{ phone: string }>(sessionID, 'phone') if (!phone) { return error(makeError('CLICK-404', 'user-not-found'), reply) } await cardSession.setMaxAttempts(sessionID, MAX_CARD_ATTEMPTS) if (req.payload.encrypted_card) { await cardSession.increment(sessionID) } if (!(await cardSession.isValid(sessionID)).success) { await orderSession.del(sessionID) return error(makeError('CLICK-429', 'too-many-attempts'), reply) } const { encrypted_card } = isNil(req.payload.encrypted_card) ? await cardSession.getData(sessionID) : req.payload const paymentApi = OystAPIS('payment', { endpoint: PAYMENT_API_URL, req: {}, type: 'http', sharedKey: PAYMENT_API_SHARED_KEY }) const userApi = OystAPIS('user', { endpoint: USER_API_URL, req: {}, sharedKey: USER_API_SHARED_KEY, type: 'http' }) const card = await paymentApi.checkBinCard({ encrypted_card }) await userApi.isCardUsed({ phone, card_id: card.id }) const id = UUID() const usedCard = await paymentApi.addCard({ encrypted_card, user: { id, email } }) if (isEmpty(usedCard)) { return error(makeError('CLICK-500', 'card-not-saved'), reply) } const userData = merge(omit(['address', 'billing_address', 'encrypted_card'], req.payload), { id, phone, addresses: [merge(address, { type: 'shipping' }), merge(address, { type: 'billing' })], card: merge({ id: usedCard.id, preview: Card.preview(usedCard.number) }, Card.expire(usedCard)), language: req.i18n.getLocale().toLowerCase() || 'fr', last_session_id: req.headers['oyst-session'] }) await userApi.create(userData) replies.success({}, reply) } catch (err) { log({ errCreateUser: err }) error(makeError(err), reply) } }, method: 'POST', path: '/v1/users' }