This is a REST service providing "Subscription as a service".
It provides endpoints for the following user subscription APIs:
- Getting the current subscription plan.
- Subscribing/Upgrading/downgrading a plan.
If the new subscription is an upgrade/downgrade, the API checks if there is any left over amount (due to cancelling the previous plan in case of upgrade) and call the payment API with the credentials of the user. Only after the payment succeeds does the database gets updated.
The service maintains a single subscription plan for the user i.e. if you make a subscription in the future and re-subscribe to any other plan, you will be either charged or refunded on a pro-rata basis. This is done to reduce complexity because eventually a user can only have one active plan at any point in time.
The plans provided by the subscription service are shown in the table below:
Plan ID | Validity (in days) | Cost (USD) |
---|---|---|
FREE | 36500(100 years) | 0.0 |
TRIAL | 7 | 0.0 |
LITE_1M | 30 | 100.0 |
PRO_1M | 30 | 200.0 |
LITE_6M | 180 | 500.0 |
PRO_6M | 180 | 900.0 |
- While the Free plan was required to be infinity, 100 years should suffice.
- Trial can only be activated once. If a user activates trial and then upgrades/downgrades before trial expires, It can not be reactivated.
- node
- mysql
- express.js for building apis.
- moment.js for handling dates.
For Local testing (without containerizing)
- switch to
develop
branch - Execute the queries in
/db/sql-scripts/
cd /payment-server
npm start
cd /subscription-server
npm start
Deploying to docker:
- from the root directory run
docker-compose up
. Note: because the application is built on windows machine, the values for container ip's are hard-coded into the routes, they can be replaced by your own machine's containers' ip by runningdocker-machine ip
, which is only needed to be changed in one place; insidesubscription.js
.
The default value is usually 192.168.99.100
Inputs:
In JSON format:
- User name
- Time stamp (in YYYY-MM-DD format)
- New plan ID
- contact number (Additional input to maintain uniqueness)
End point: :3001/subscription
Request type: POST
Request body:
{
"user_name": <string>,
"New_plan_id":<string: Plan id>,
"contact_number":<string: contact number>,
"startdate":<string>
}
Response:
Successfully updated plan.
on success.
You already have that plan!
on duplicate plans.
Trial exhausted, cant reuse.
on reactivation of trial.
Payment failed, please retry.
on payment failure.
outputs:
- Status:
SUCCESS
if the payment API request succeeded.FAILURE
otherwise.
Inputs:
- User name
- Time stamp (in
YYYY-MM-DD
format) // Removed this because we only have one active plan per user.
The input is in JSON format.
End point: :3001/currentPlan
Request type: POST
Request body:
{
"user_name": <string>
}
Response body:
{
"Plan": <strin: Plan id> // eg. "24242-3443-sdstg-3343",
"days left": <number: number of days left in the plan>
}
Outputs:
- Plan id that will be active for user at specified date (see table in Plans section below)
- Number of days left in plan, from the moment the query is made to the service. If the plan has not started, the service returns the total validity.
This repo contains a NodeJS server that provides the following service that you will have to access from the user subscriptions service.
This service provides a single API endpoint described below:
End point: :3000/payment
Request type: POST
Request body:
{
"user_name": <string>,
"payment_type": <one of "DEBIT"|"CREDIT">,
"amount": <number>
}
Response body:
{
"payment_id": <uuid> // eg. "24242-3443-sdstg-3343",
"status": <one of "SUCCESS"|"FAILIURE">
}
Additional points of Note:
- This service is implemented so that it intentionally errors out sometimes (approx 25% calls fail). To handle this, the subscription API rejects the subscription request stating "Payment Failed" and asks the user to reinitiate the payment.