# 1click-api [![Build Status](https://travis-ci.com/OystParis/1click-api.svg?token=Q1A95RbZGQpb1jK1qJ8Z&branch=master)](https://travis-ci.com/OystParis/1click-api)

---

## Handlers

#### _Merchant_

Needs an valid merchant ApiKey
Needs header `Authorization: Bearer <APIKEY>`

#### _Oyst_

Needs header `Oyst-Authorization: Oyst <DATA>`

Where `<DATA>` is a `base64` encoded `stringified` object

```json
{
    "m": "<MERCHANT_ID>",
    "t": "<MERCHANT_TOKEN>" // Generated by `POST` /orders/authorize
}
```
#### _Sessions_

Needs header `oyst-session`

Returns a `403` if header is not present

## Routes

### Error handling
When calling this API except for internal errors, the API should return a json

```json
{
    "success": false,
    "error": {
        "status": "<API-SHORT-CODE>-<ERROR-CODE>",
        "status_text": "<ERROR-MSG-USING-i18n>"
    }
}
```

### `POST` /orders/authorize

Handle the server to server authentication for the oneclick. This route should be called by the merchant during the `function getOneclickUrl()`.
The iframe url is returned.

###### Payload:
```javascript
Joi.object({
  product_reference: Joi.string().required(),
  variation_reference: Joi.string().optional(),
  user: Joi.object().optional(),
  quantity: Joi.number().integer().default(1)
})
```
###### Handler: _merchant_

###### Returns
* `403` on authentication failure
* On success

```json
{
    "success": true,
    "url": "http://url_to_front_application"
}
```

### `GET` /version

Informations are in `package.json`

###### Returns

```json
{
    "name": "APPLICATION_NAME",
    "version": "APPLICATION_VERSION"
}
```

### `POST` /orders

Handle the order creation when user is known.

It calls:

* payment-api
* user-api
* catalog-api

###### Payload

```javascript
Joi.object({
  encrypted_card: Joi.string().required()
}).allow(null)
```

`encrypted_card` should be send only when user changes his card

###### Handler: _Oyst_ _Session_

###### Returns

```json
{
    "success": true,
    "id": "ORDER_UUID",
    "product": {},
    "user": {},
    "order": {}
}
```

### `DELETE` /orders/{:id}

Delete specific order and clean associated session

It calls:

* payment-api
* user-api
* catalog-api

###### QueryParams

```javascript
Joi.object({
  id: Joi.string().guid().required()
})
```

###### Handler: _Oyst_ _Session_

###### Returns

```json
{
    "success": true
}
```

### `GET` /users

Check if user exists using the phone number. If found, sms is send with a link

###### QueryParams

```javascript
Joi.object({
  phone: phoneRule.phone().mobile().required()
})
```

Where `phoneRule` is the npm package `joi-phone-validator`


###### Handler: _Oyst_


###### Returns

```json
{
    "success": true, // When user is found or false otherwhise
    "sms": true, // Or false if sms was not send
    "channel": "PUSHER_CHANNEL_TO_LISTEN_TO",
    "event": "PUSHER_EVENT_TO_LISTEN_TO",
    "phone": "+33601020304",
    "can_retry": true // false if limit is reached
}
```

### `POST` /users/card

Called when user is not found. Store the `encrypted_card` in REDIS Session.
Then send a SMS with a link that display a code. Like 3DS

###### Payload

```javascript
Joi.object({
  encrypted_card: Joi.string().required()
})
```

###### Handler: _Oyst_


###### Returns

```json
{
    "success": true, // Or false if sms was not send
    "channel": "PUSHER_CHANNEL_TO_LISTEN_TO",
    "event": "PUSHER_EVENT_TO_LISTEN_TO",
    "phone": "+33601020304",
    "can_retry": true, // false if limit is reached
    "code": true
}
```

### `GET` /users/phone/mfa

Activate the code when user clicked on the SMS link

###### QueryParams

```javascript
Joi.object({
    id: Joi.string().guid().required(),
    p: phoneRule.phone().mobile().required()
})
```

Where `phoneRule` is the npm package `joi-phone-validator`

###### Returns

Redirects to `${DISPLAY_CODE_URL}?${Querystring.stringify({ id, phone: p })}` where `DISPLAY_CODE_URL` is the url of the ReactAPP to display the code on mobile

### `POST` /users/phone/valid

Activate the phone when user clicked on the SMS link. Send `PUSHER_EVENT` on success.

* Remove phone from `PhoneSession`
* Remove short-link from the `PhoneChecker`

###### Payload

```javascript
Joi.object({
    id: Joi.string().guid().required(),
    phone: phoneRule.phone().mobile().required(),
    session: Joi.string().guid().required(),
    user_id: Joi.string().guid().required()
})
```

Where `phoneRule` is the npm package `joi-phone-validator`

###### Returns

Redirects to `PHONE_SUCCESS_URL` that is the static url of success


### `GET` /mfa

* Get the code from `PhoneChecker`
* Send `PUSHER_EVENT` on success with params `code: true and uuid`


###### QueryParams

```javascript
Joi.object({
    id: Joi.string().guid().required(),
    phone: phoneRule.phone().mobile().required()
})
```

Where `phoneRule` is the npm package `joi-phone-validator`

###### Returns

```json
{
    "code": "SECRET_CODE",
    "success": true
}
```

### `POST` /mfa/codes

* Get the code from `PhoneChecker`
* Send `PUSHER_EVENT` on success with params `code: true and uuid`


###### Payload

```javascript
Joi.object({
  code: Joi.string().required(),
  uuid: Joi.string().guid().required(),
  phone: phoneRule.phone().mobile().required()
})
```

Where `phoneRule` is the npm package `joi-phone-validator`

###### Returns

```json
{
    "success": true,
    "can_retry": true // or false when success is false
}
```

### `POST` /users

* Add card with minimum authorization
* Create the user using user-api

###### Handler: _Oyst_ _Session_

###### Payload

```javascript
Joi.object({
  address: address.required(),
  billing_address: address.default(Joi.ref('address')),
  email: Joi.string().email().required(),
  first_name: Joi.string().required(),
  language: Joi.string().length(2).optional(),
  last_name: Joi.string().required()
})
```

where `address` is

```javascript
Joi.object({
  city: Joi.string().required(),
  company_name: allowEmpty,
  complementary: allowEmpty,
  country: Joi.string().required(),
  first_name: Joi.string().required(),
  label: Joi.string().required(),
  last_name: Joi.string().required(),
  postcode: allowEmpty,
  region: allowEmpty,
  street: Joi.string().required()
})
```

and `allowEmpty` is

```javascript
Joi.string().empty('').optional()
```

Where `phoneRule` is the npm package `joi-phone-validator`

###### Returns

```json
{
    "success": true,
    "user": {}
}
```

### `POST` /notifications

* Handle payment-api notifications

**For now notification are not treated this is only usefull for the payment-api not to crashed**

**TO FIX when order-api will be able to handle payment informations**

###### Payload

```javascript
Joi.object({
  live: Joi.boolean().required(),
  notification: Joi.object().keys({
    additional_data: Joi.object().optional(),
    amount: Joi.object().keys({
      currency: Joi.string().required(),
      value: Joi.number().required()
    }).required(),
    event_code: Joi.string().required(),
    event_date: Joi.date(),
    is_3d: Joi.boolean().required(),
    operations: Joi.array().items(Joi.string()).required(),
    order_id: Joi.string().required(),
    payment_id: Joi.string().guid().required(),
    success: Joi.boolean().required(),
  }).required()
})
```

###### Returns

`OK`


