# RFC: Support a new payment method in the BoFH API
## Abstract
This RFC aims to discuss how we will add a new payment method in the BoFH API, and consequently at checkout,
which is one of the consumers of this application.
Initially we will start by adding the debit card, but we should prepare to add other options in the future.
## Problem
We currently only support credit cards as a payment option on our Checkout, so we are no longer serving
customers who have only a debit card or only a bank account.
As we are currently only supporting one payment method at our endpoints, we will have to do some interface changes
to initially support the debit card, but given that we will have other payment options in the future.
The new changes should be made without consumer compatibility issues.
## Proposal
I think we can consider two paths, one simpler that doesn't need a new version of endpoints and another more elaborate and extensible that needs a new version of endpoints.
In both will not be broken the interface of old consumers.
### 1. Add new attributes to endpoints GET /v1/payment-options and POST /v1/book
This is the simplest approach. It consists of adding new attributes to both endpoints.
At this path we will only support card-based payment methods.
**Response of GET /v1/payment-options:**
Here we will add the *type* attribute to the endpoint */v1/payment-options* objects, this attribute will inform consumers if the payment option is credit or debit.
```json
[
{
"code": "AX",
"mandatoryText": null,
"name": "American Express",
"processorCountryCode": null,
"type": "credit" # or debit
}
]
```
**Request to POST /v1/book:**:
At endpoint */v1/book* we will also accept two new attributes within the *payment* object:
* option: Must be debit or credit
* iban: Attribute that should be used only when it is debit
The API should handle when the *payment.option* attribute is empty, to treat the request as a credit card, not to break the old version's consumer interface.
```json
{
"rooms": [
{
"firstName": "Pedro",
"lastName": "Bonamides",
"email": "pedro@bo.com",
"phone": {
"countryCode": "+31",
"number": "23469873"
},
"bedTypeId": "15",
"guests": "2:1",
"smoking": false,
"specialRequest": null
}
],
"payment": {
"type": "AX",
"option": "credit", # or debit
"iban": "", # optional for credit
"number": "5555555555554444",
"securityCode": "123", # optional for debit
"expirationMonth": "02", # optional for debit
"expirationYear": "2022", # optional for debit
"billing": {
"firstName": "Pedro",
"lastName": "Bonamides",
"email": "pedro@bo.com",
"phone": {
"countryCode": "+31",
"number": "23469873"
},
"address": {
"line1": "Frederiksplein 1",
"line2": "FindHotel",
"city": "Amsterdam",
"stateCode": null,
"postalCode": "1017 XK",
"countryCode": "NL"
}
}
}
}
```
#### Advantages
- Simple implementation
- It will not break the interface with any of the consumers
#### Disadvantages
- The request body will not be semantic (containing optional and required attributes based on the *payment.option* attribute)
- It will not be extended to non-card based payment methods
### 2. Create new versions of the endpoints GET /v1/payment-options and POST /v1/book
This approach involves creating the endpoints */v2/payment-options* and */v2/book*.
**Response of GET /v2/payment-options**:
In endpoint */v2/payment-options* would be returned objects representing the type, with their specific attributes.
```json
[
"credit": [
{
"code": "AX",
"mandatoryText": null,
"name": "American Express",
"processorCountryCode": null
}
],
"debit": [
{
"code": "AX",
"mandatoryText": null,
"name": "American Express",
"processorCountryCode": null
}
],
"gateways": [
{
"name": "Paypal",
...
}
]
]
```
**Request to POST /v2/book for credit:**
At endpoint */v2/book* you will need to send the attribute *payment.option* which will represent the type of payment. Also within *payment*, you should send a new object representing the type, below some examples:
```json
{
"rooms": [
{
"firstName": "Pedro",
"lastName": "Bonamides",
"email": "pedro@bo.com",
"phone": {
"countryCode": "+31",
"number": "23469873"
},
"bedTypeId": "15",
"guests": "2:1",
"smoking": false,
"specialRequest": null
}
],
"payment": {
"option": "credit",
"credit": {
"code": "AX",
"number": "5555555555554444",
"securityCode": "123",
"expirationMonth": "02",
"expirationYear": "2022",
},
"billing": {
"firstName": "Pedro",
"lastName": "Bonamides",
"email": "pedro@bo.com",
"phone": {
"countryCode": "+31",
"number": "23469873"
},
"address": {
"line1": "Frederiksplein 1",
"line2": "FindHotel",
"city": "Amsterdam",
"stateCode": null,
"postalCode": "1017 XK",
"countryCode": "NL"
}
}
}
}
```
**Request to POST /v2/book for debit:**
```json
{
"rooms": [
{
"firstName": "Pedro",
"lastName": "Bonamides",
"email": "pedro@bo.com",
"phone": {
"countryCode": "+31",
"number": "23469873"
},
"bedTypeId": "15",
"guests": "2:1",
"smoking": false,
"specialRequest": null
}
],
"payment": {
"option": "debit",
"debit": {
"code": "AX",
"number": "5555555555554444",
"iban": "123"
},
"billing": {
"firstName": "Pedro",
"lastName": "Bonamides",
"email": "pedro@bo.com",
"phone": {
"countryCode": "+31",
"number": "23469873"
},
"address": {
"line1": "Frederiksplein 1",
"line2": "FindHotel",
"city": "Amsterdam",
"stateCode": null,
"postalCode": "1017 XK",
"countryCode": "NL"
}
}
}
}
```
### Advantages
- Support non-card based payment options in the future (paypal, alipay)
- Simple response for consumers (don't depend on filtering by type)
### Disadvantages
- Maintain two API versions (at least temporarily)
## Conclusion
Since the idea of the BoFH API is to extend to new providers and payment methods, I believe the option of creating a new version is the best solution to this problem.
We must ensure and inform consumers about this new version of the API, and ensure that it will be depreciated in the future.