Giter Site home page Giter Site logo

sachgits / subscription-service Goto Github PK

View Code? Open in Web Editor NEW

This project forked from weld-io/subscription-service

0.0 2.0 0.0 146 KB

REST API service managing subscription pricing, services, consumables, VAT, etc. Built in Node.js.

License: MIT License

JavaScript 100.00%

subscription-service's Introduction

Subscription Service

Subscription Service is a REST API service managing subscription pricing, services, consumables, VAT, etc. Built in Node.js.

It allows you to be more agile with your product offering, pricing, discounts, VAT, etc. Like Segment, but for payments.

This is not a payment platform - instead it’s a layer between your app and the payment platform (Stripe being the default).


Made by the team at Weld (www.weld.io), the #codefree web/app creation tool:

Weld

How to Run

Set JWT auth secret:

export JWT_SECRET=...

or no JWT:

export DISABLE_JWT=true

Optional:

export STRIPE_SECRET_KEY=...
export WEBHOOK_RENEW_SUBSCRIPTION=...

Then, just start with:

npm run dev # development

or

npm start # production

Server will default to http://localhost:3034

How to Test

npm test

Entities

For B2C apps, one Account has only one User. For B2B apps, there can be multiple Users on each Account.

  • Accounts
    • name
    • reference (slug)
    • email
    • company
      • name
      • vatNumber
    • countryCode
    • discountCoupon
    • metadata (free form data)
      • stripeCustomer
    • subscriptions (array of Subscriptions)
  • Users (on an Account)
    • reference (e.g. user ID in another app)
    • account (reference to Account)
    • consumables
      • projects: 2
    • metadata (free form data)
  • Plans
    • name
    • reference (slug)
    • description
    • featureDescriptions (string array)
    • tags (string array)
    • position (order in a list)
    • isAvailable: true/false
    • allowMultiple: true/false (false = disable all other subscriptions unless they are allowMultiple=true)
    • services (array of Services)
    • price
      • month
      • year
      • once
      • vatIncluded
    • consumables: { projects: 10 }
    • trialDays: 30
    • metadata (free form data)
  • Subscriptions (an Account subscribes to one or more Plans)
    • plan (reference to Plan)
    • reference (e.g. domains, User can’t have multiple subscriptions with same Reference)
    • dateExpires
    • metadata (free form data)
      • stripeSubscription
  • Services (e.g. access to a feature, included in Plan)
    • name
    • reference (slug)
    • description
    • metadata (free form data)
  • Consumables (e.g. projects, users - limited by Plan, consumed by Users not Accounts)

Environment variables

  • DISABLE_JWT: set to "true" if you don’t want JWT authentication.
  • JWT_SECRET: secret key for JSON Web Token authentication.
  • PAYMENT_PROVIDER: defaults to 'stripe'. Add new Payment Providers in folder /app/paymentProviders.
  • STRIPE_SECRET_KEY: secret key from Stripe dashboard.
  • VAT_PERCENT: defaults to "20" (%), as in if the price incl. VAT is $10, VAT is $2.
  • WEBHOOK_RENEW_SUBSCRIPTION: a complete URL that will receive a POST request whenever a subscription is renewed.

API

Accounts

Create new account

curl -X POST http://localhost:3034/api/accounts -H "Content-Type: application/json" -d '{ "name": "My Company" }'

Users

Create new user

Note: reference is where you use your main permanent user ID, e.g. from another app.

curl -X POST http://localhost:3034/api/users -H "Content-Type: application/json" -d '{ "reference": "userId1", "account": "my-company" }'

Create new user and account

curl -X POST http://localhost:3034/api/users -H "Content-Type: application/json" -d '{ "reference": "userId2", "account": { "name": "My Company 2", "email": "[email protected]" } }'

Create new user and account and subscription

curl -X POST http://localhost:3034/api/users -H "Content-Type: application/json" -d '{ "reference": "userId2", "account": { "name": "My Company 2", "email": "[email protected]" }, "subscription": { "plan": "trial", "dateExpires": "2018-04-01" } }'

Get user

curl -X GET http://localhost:3034/api/users/:reference

Returns:

{
	reference: xxx,
	account: { reference: ... },
	activePlan: {
		reference: 'b2b_small',
		dateExpires: '2017-12-31',
	},
	plans: ['b2b_small'],
	services: {
		remove_watermark: {
			name: 'Remove watermark'
		}
	},
	consumables: {
		projects: {
			max: 10,
			current: 8,
			remaining: 2
		}
	},
	subscriptions: [
		…
	]
}

Update user

curl -X PUT http://localhost:3034/api/users/12345 -H "Content-Type: application/json" -d '{ "account": "my-company" }'

Services

Create new service

curl -X POST http://localhost:3034/api/services -H "Content-Type: application/json" -d '{ "name": "Image hosting", "description": "Store unlimited images in our cloud service." }'

Plans

Create new plan

curl -X POST http://localhost:3034/api/plans -H "Content-Type: application/json" -d '{ "name": "Standard package", "price": { "month": 9.99 }, "services": ["image-hosting"] }'

List plans

curl -X GET http://localhost:3034/api/plans

Get plan info

curl -X GET http://localhost:3034/api/plans/:reference

Returns:

{
	reference: 'standard-package',
	name: 'Standard Package',
	price: {
		month: 149,
		year: 1490,
		once: 150000
	},
	vat: {
		vatIncluded: true,
		month: 15,
		year: 149,
		once: 15000,
	},
	services: {
		remove_watermark: {
			name: 'Remove watermark'
		}
	},
	consumables: {
		projects: {
			max: 10,
			per: 'user'***,
		},
		users: {
			max: 2,
			per: 'account',
		}
	},
}

***Support consumables over time? E.g 10 projects/month.

Update plan

Partial update:

curl -X PUT http://localhost:3034/api/accounts/my-company/plans/:reference -H "Content-Type: application/json" -d '{ "services": ["video-hosting"] }'

Delete plan

curl -X DELETE http://localhost:3034/api/accounts/my-company/plans/:reference

Subscriptions

Start subscription

curl -X POST http://localhost:3034/api/accounts/:accountReference/subscriptions -H "Content-Type: application/json" -d '{ "plan": "standard-package", "billing": "year" }'

or:

curl -X POST http://localhost:3034/api/users/:userReference/subscriptions -H "Content-Type: application/json" -d '{ "plan": "standard-package" }'

Note: billing defaults to "month".

Update subscription

Partial update:

curl -X PUT http://localhost:3034/api/accounts/:accountReference/subscriptions/:id -H "Content-Type: application/json" -d '{ "reference": "ref1" }'

or:

curl -X PUT http://localhost:3034/api/users/:userReference/subscriptions/:id -H "Content-Type: application/json" -d '{ "reference": "ref1" }'

Stop subscription

Note: when you stop a subscription, it’s not deleted but a dateStopped is set and the subscription won’t be listed in Account/User.subscriptions.

curl -X DELETE http://localhost:3034/api/accounts/:accountReference/subscriptions/:id

or:

curl -X DELETE http://localhost:3034/api/users/:userReference/subscriptions/:id

Stop all subscriptions:

curl -X DELETE http://localhost:3034/api/accounts/:accountReference/subscriptions

or:

curl -X DELETE http://localhost:3034/api/users/:userReference/subscriptions

Implementation

Built on Node.js, Express, MongoDB, mongoose-crudify.

Deploying on Heroku

# Set up and configure app
heroku create MYAPPNAME
heroku addons:add mongolab
heroku config:set JWT_SECRET=...
heroku config:set STRIPE_SECRET_KEY=...
heroku config:set WEBHOOK_RENEW_SUBSCRIPTION=...

Payment providers (including Stripe)

Stripe is currently the only payment provider supported, but the idea is that it should be easy to add more payment provider integrations to /app/paymentProviders and change the PAYMENT_PROVIDER environment variable.

  • Stripe plan references are currently derived from Plan reference + billing period, e.g. basicplan_month.
  • Stripe customer ID is saved in Accounts metadata.stripeCustomer.
  • Stripe subscription ID is saved in Subscriptions metadata.stripeSubscription.

Stripe example webhook

See https://stripe.com/docs/api#invoice_object

Smaller version with only the fields needed for Subscription Service:

{
	"type": "invoice.payment_succeeded",
	"data": {
		"object": {
			"customer": "cus_BpmeYvqhVnkuY9",
			"subscription": "sub_9PpDkJFsxRMEg5",
			"lines": {
				"data": [
					{
						"plan": {
							"interval": "year",
							"interval_count": 1
						}
					}
				]
			}
		}
	}
}

Complete:

{
	"type": "invoice.payment_succeeded",
	"data": {
		"object": {
			"id": "in_196zZUCjkwdpPaFTm8GgPYth",
			"object": "invoice",
			"amount_due": 11880,
			"application_fee": null,
			"attempt_count": 1,
			"attempted": true,
			"billing": "charge_automatically",
			"charge": "ch_196zZUCjkwdpPaFTCG1T4BZX",
			"closed": true,
			"currency": "sek",
			"customer": "cus_BpmeYvqhVnkuY9",
			"date": 1477043056,
			"description": null,
			"discount": null,
			"ending_balance": 0,
			"forgiven": false,
			"lines": {
				"data": [
					{
						"id": "sub_BpmewCPihjSysf",
						"object": "line_item",
						"amount": 2000,
						"currency": "sek",
						"description": null,
						"discountable": true,
						"livemode": true,
						"metadata": {

						},
						"period": {
							"start": 1514221509,
							"end": 1516899909
						},
						"plan": {
							"id": "professional_yearly_10",
							"object": "plan",
							"amount": 9504,
							"created": 1473759356,
							"currency": "sek",
							"interval": "year",
							"interval_count": 1,
							"livemode": false,
							"metadata": {

							},
							"name": "Weld professional website (yearly)",
							"statement_descriptor": null,
							"trial_period_days": null
						},
						"proration": false,
						"quantity": 1,
						"subscription": null,
						"subscription_item": "si_BpmejWAFkv1rLv",
						"type": "subscription"
					}
				],
				"has_more": false,
				"object": "list",
				"url": "/v1/invoices/in_196zZUCjkwdpPaFTm8GgPYth/lines"
			},
			"livemode": false,
			"metadata": {

			},
			"next_payment_attempt": null,
			"paid": true,
			"period_end": 1477043056,
			"period_start": 1477043056,
			"receipt_number": null,
			"starting_balance": 0,
			"statement_descriptor": null,
			"subscription": "sub_9PpDkJFsxRMEg5",
			"subtotal": 9504,
			"tax": 2376,
			"tax_percent": 25.0,
			"total": 11880,
			"webhooks_delivered_at": 1477043069
		}
	}
}

subscription-service's People

Contributors

tomsoderlund avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.