tamed-stripe-backend

1.1.13 • Public • Published

WHY?

This is the backend library for the Tamed Stripe architecture. This library aims to provide the backend integrations with the Stripe API servers for basic customer generation, connected account generation, subscription generation and payment functions.

SETUP

  1. Add the backend library to the backend of your project.
yarn add tamed-stripe-backend
  1. Modify the TAMED_STRIPE_SECRET_KEY environment parameter to use to connect to the Stripe.
export TAMED_STRIPE_SECRET_KEY="YOUR_STRIPE_SECRET_KEY" # starts with sk_
  1. Initialize parameters (modify below object according to your environment)

    Use this file as a template for your backend configuration. This file is to be required by your express server in the next step. You should modify the credentials, according to your environment.

    Key Type Value
    pgKeys Object PostgreSQL connection parameters.
    debugMode Boolean If true, the library will log debug messages.
  2. Call the init function of the library to initialize the db connection pool. And then start your server. As a reference you can use this file which utilize the tamed-express-server library for a quick start.

API

init

The init function initializes the database connection pool. Additionally it provides a method to increase the log level.

Parameter Type Description
p_params Object Parameters for the backend server.

p_params

Key Type Value
pgKeys Object PostgreSQL connection parameters.
debugMode Boolean If true, the library will log debug messages.

Returns

If successful, resolves to true. Otherwise, rejects with an error message.

Example

const tsb = require("../tamed-stripe-backend.js");
...
await tsb.init({
	debugMode: debugMode,
	// coming from database-setup
	pgKeys: {
		user: 'tamedstripeapp',
		password: 'tamedstripeapp.',
		database: 'tamedstripedb',
		host: 'localhost',
		port: 5432,
	},
});

generateCustomer

Generates a payer customer at Stripe and attaches a payment method to it so that the customer can do payments.

Reading Data from Database

Once a customer is generated, you can reach the customer within your database from the tamedstripe.customers table. The application_customer_id field of the tamedstripe.customers table is the applicationCustomerId parameter of this function. You can use this field to link your application's customer structure with the Stripe side customer id.

Parameter Type Description
body Object Parameters for the generating a payer customer at Stripe

body

Key Type Value
applicationCustomerId string This is your application's customer id that you can use to link your application customer structure with stripe side customer id.
paymentMethodId
(optional)
string Payment method id of the payment method to be attached to the customer. If this is omitted a new payment method will be generated with a checkout session.
description string Description of the customer.
email string Email of the customer.
metadata Object Metadata for the customer, you can embed andy data within this object, it is kept in Stripe servers also.
name string Name of the customer.
phone string Phone number of the customer.
address Object Address of the customer.
publicDomain string Public domain of the website.
successRoute string Route to redirect to on successful checkout. Defaults to /generate-customer-success-route which is handled by the library function generateCustomerSuccessRoute. We suggest you to keep this as undefined and use the default value because the default value signals frontend a method to close WebViews.
cancelRoute string Route to redirect to on cancelled checkout. Defaults to /generate-customer-cancel-route which is handled by the library function generateCustomerCancelRoute. We suggest you to keep this as undefined and use the default value because the default value signals frontend a method to close WebViews.
testClockId
(optional)
string This is an optional clock id that is a method that Stripe provides for future dated tests. For an example usage, you can refer to subscriptionPayment - next 2 months tests.
address
Key Type Value
city string City of the customer.
country string Country of the customer.
line1 string Line 1 of the address of the customer.
line2 string Line 2 of the address of the customer.
postal_code string Postal code of the customer.
state string State of the customer.

Returns

If successful, resolves to below JSON object. The checkoutSession object is optional and it holds the checkout session information which can be used to collect the default payment method information from users. Otherwise, rejects with an error message.

{
	result: 'OK',
	payload: {
		customer,
		checkoutSession
	},
}

Example

   ...
	const body = { applicationCustomerId, description, email, metadata, name, phone, address, publicDomain };
	let response = await tsb.generateCustomer(body);

generateCustomerSuccessRoute

This is the default route handler for the generateCustomer handler. This is used if the successRoute parameter of the generateCustomer handler is a falsy value. We suggest you to use this handler because the redirect signals frontend a method to close WebViews.

generateCustomerCancelRoute

This is the default route handler for the generateCustomer handler. This is used if the cancelRoute parameter of the generateCustomer handler is a falsy value. We suggest you to use this handler because the redirect signals frontend a method to close WebViews, and it also unlinks a customer so that it can not provide hurdles for future operations.

getCustomer

Gets stripe customer information from the database, using the applicationCustomerId parameter.

Parameter Type Description
body Object Parameters for the generating a payer customer at Stripe

body

Key Type Value
applicationCustomerId string This is your application's customer id that you can use to link your application customer structure with stripe side customer id.

Returns

If successful, resolves to below JSON object. Otherwise, rejects with an error message.

{
	result: 'OK',
	payload: {
		customer // customer.rows[0] from DB with selected columns
	},
}

Example

   ...
	const body = { applicationCustomerId };
	let response = await tsb.getCustomer(body);

generateProduct

Generates a product that can be used in checkout sessions that is to be a basis for subscriptions. Once a product is generated, you can reach the product within your database from the tamedstripe.products table. The stripe_product_id field of the tamedstripe.products table is the Stripe's product id.

Parameter Type Description
body Object Parameters for the generating a payer customer at Stripe

body

Key Type Value
name string Name of the product.
description string Description of the product.
currency string Currency of the product.
unitAmountDecimal number Unit amount of the product in CENTS.
interval string Interval of the product. This can be one of following values; 'day', 'week', 'month', 'year'.
taxBehavior string Optional. Tax behavior of the product. This can be one of following values; 'exclusive', 'inclusive', 'unspecified'.
taxCode string Optional. Tax code of the product. Comes from the Stripe's Product Tax Categories.

Returns

If successful, resolves to below JSON object. Otherwise, rejects with an error message.

{
	result: 'OK',
	payload: {
		product,
		price
	},
}

Example

	const body = {
		name: 'Test Product',
		description: 'Test Product Description',
		currency: 'usd',
		unitAmountDecimal: 1000, // This value is in cents, so it is $10.00, 
		interval: 'month',
		taxBehavior: 'exclusive',
		taxCode: 'txcd_30060006' // Stripe tax code for hats. :-) 
	};
	let response = await tsb.generateProduct(body);

generateSubscription

Generates a subscription for a customer. Once a subscription is generated, you can reach the subscription within your database from the tamedstripe.subscriptions table. The stripe_subscription_id field of the tamedstripe.subscriptions table is the Stripe's subscription id. The stripe_product_id field of the tamedstripe.subscriptions table is the Stripe's product id. The state field can be one of following values; 'A' (active), 'C'(cancelled). As long as a subscription is active the Stripe will charge the customer automatically.

Reading Data from Database

Once Stripe charges a customer for a subscription, it is received via a 'invoice.paid' web hook. And when that webhook indicating a successfull payment is made, tamedstripe.subscription_payments table is modified accordingly. In this table you can check if current date-time is between the subscription_covered_from and subscription_covered_to fields of any row of the same subscription's payments. If it is, then the subscription is covered for that period. If it is not, then the subscription is not covered for that period. You can use this information to determine if a subscription is covered for a period or not and serve your functionality to your customer.

For example below row from the tamedstripe.subscription_payments table indicates that the subscription is covered for the period between 2023-03-23 14:36:36 and 2023-04-23 14:36:36. So if you want to check if a subscription is covered for the current date-time, you can check if the current date-time is between 2023-03-23 14:36:36 and 2023-04-23 14:36:36. If it is, then the subscription is covered for that period. If it is not, then the subscription is not covered for that period.

 id |    stripe_subscription_id    | unit_amount_decimal | currency | state | subscription_covered_from | subscription_covered_to 
----+------------------------------+---------------------+----------+-------+---------------------------+-------------------------
  1 | sub_1MopFoCDKfcpGwAfZiZTD1Gg |              100001 | usd      | P     | 2023-03-23 14:36:36       | 2023-04-23 14:36:36
Parameter Type Description
body Object Parameters for the generating a subscription at Stripe

body

Key Type Value
customerId string Stripe customer id that the subscription will be generated for.
recurringPriceId string Stripe price id of the recurring price, which should be previously generated using generateProduct function.
description string Description of the subscription.
automaticTax object Optional. Automatic tax settings of the subscription. If to be used following object should be passed: { enabled: true }
unlinkIfSubscriptionFails boolean Optional. If set to true, then the customer will be unlinked from the application if the subscription fails.

Returns

If successful, resolves to below JSON object. Otherwise, rejects with an error message.

{
	result: 'OK',
	payload: subscription,
}

Example

const productProps = {
	name: 'Test',
	description: 'Test',
	currency: 'usd',
	unitAmountDecimal: '1234567', // This value is in cents, so it is $12345,67,
	interval: 'month',
	taxBehavior: 'exclusive',
	taxCode: 'txcd_30060006' // Stripe tax code for hats. :-)
};
const response2 = await tsb.generateProduct(productProps);
const priceData = response2.payload.price;
...
await tsb.generateSubscription({
	applicationCustomerId: applicationCustomerId,
	recurringPriceId: priceData.id,
	description: description,
	automaticTax: { enabled: true },
	unlinkIfSubscriptionFails: true,
});

getSubscriptionPayments

Gets the payments of an application customer id for all subscriptions. The retrieved list can be filtered to find the needed payments.

Parameter Type Description
body Object Parameters for the generating a payer customer at Stripe

body

Key Type Value
applicationCustomerId string Application customer id of the customer that the subscription payments will be retrieved for.

Returns

If successful, resolves to below JSON object. Otherwise, rejects with an error message.

{
	result: 'OK',
	payload: subscriptionPayments,
}

Example

const response = await tsb.getSubscriptionPayments({
	applicationCustomerId: applicationCustomerId,
});

cancelSubscription

Cancels a subscription.

Parameter Type Description
body Object Parameters for the generating a payer customer at Stripe

body

Key Type Value
subscriptionId string Id of the subscription to be cancelled.

Returns

If successful, resolves to below JSON object where subscription object is coming from Stripe. Otherwise, rejects with an error message.

{
	result: 'OK',
	payload: subscription,
}

Example

	const body = {
		subscriptionId: 'sub_1234567890',
	};
	let response = await tsb.cancelSubscription(body);

generateAccount

Generates a payee account (aka connected account) at Stripe and its associated account link for the end user to complete the account generation process on Stripe.

The account link is generated for the end user to complete the account generation process on Stripe. The end user should be redirected to the Stripe's website to complete the account generation process using the returned link. After the account generation process is completed, the end user will be redirected to the return URL of the account link.

Reading Data from Database

The connected account information for a customer is kept in the tamedstripe.connected_accounts table. In this table application_customer_id is the customer id of your system and it is to be used to link your software to the generated application_customer_id. The state field can be either 'W' or A. W means the account is waiting for the end user to complete the account generation process on Stripe. 'A' means the account is active and ready to be used. For 'W' rows, you can re-call this function to recieeve an active URL that you can use to direct your users to complete their account generation process on Stripe.

Parameter Type Description
body Object Parameters for the generating a payee account at Stripe

body

Key Type Value
applicationCustomerId string Id of the application customer that the account will be generated for.
email string Email of the account.
publicDomain String Public domain of the server, to use the return URLs.
refreshUrlRoute String Route for the refresh URL. Defaults to /generate-account-cancel-route for which the route can be handled by this library.
returnUrlRoute String Route for the return URL. Defaults to /generate-account-success-route for which the route can be handled by this library.
country String Country of the account. Defaults to US.
capabilities JSON Defaults to {transfers: { requested: true }}

Returns

You should expect 3 different responses from this function.

  • If there is a successfully generated account for the given applicationCustomerId, then the response will be as below, and the payload.id can be used as Stripe side payee (connected_account) id.
{
	result: 'OK',
	payload: {
		id: result.rows[0].stripe_account_id,
		accountLinkURL: ''
	}
}
  • If previously account generation process started but the end user did not complete the process, then the response will be as below, and the payload.accountLinkURL can be used to redirect the end user to the Stripe's website to complete the account generation process. Use the accountLinkURL field to redirect the end user to the Stripe's website to complete the account generation process.
{
	result: 'OK',
	payload: {
		id: result.rows[0].stripe_account_id,
		accountLinkURL: accountLinkForW.url,
		urlRegenerated: true
	}
}
  • If there is no account for the given applicationCustomerId, then the response will be as below, and the payload.accountLinkURL can be used to redirect the end user to the Stripe's website to start the account generation process.
{
	result: 'OK',
	payload: {
		result: 'OK',
		payload: account,
	}
}

Example

const props = {
	applicationCustomerId,
	email,
	publicDomain,
	country,
};
const response1 = await tsb.generateAccount(props);

generateAccountSuccessRoute

Provides the default route content for th /generate-account-success-route route. This route is used to handle the return URL of the account link. The default route content can be used as is, or you can use it as a template to create your own route content.

generateAccountCancelRoute

Provides the default route content for th /generate-account-cancel-route route. This route is used to handle the refresh URL of the account link. The default route content can be used as is, or you can use it as a template to create your own route content.

getAccount

Gets the account information for the given applicationCustomerId.

Parameter Type Description
body Object Parameters for the generating a payee account at Stripe

body

Key Type Value
applicationCustomerId string Id of the application customer that the account will be generated for.

Returns

If successful, resolves to below JSON object. Otherwise, rejects with an error message.

{
	result: 'OK',
	payload: account, // account.rows[0] from DB with selected columns
}

Example

	const response2 = await tsb.getAccount({applicationCustomerId});

oneTimePayment

Generates a one time payment checkout session at Stripe. You can use that session URL to direct your users to the Stripe's website to complete the payment process.

Reading Data from Database

The payment data is kept in the tamedstripe.one_time_payments table. In this table application_customer_id is the customer id of your system and it is to be used to link your software to the generated checkout_session_id. The state field can be either 'W', 'P' or F. W means the payment is waiting for the end user to complete the payment process on Stripe. 'P' means the payment is completed. 'F' means payment is failed.

Additionally, for successfully paid customers, if you need to show your customer the related invoice, you can call the url residing in the hosted_invoice_url field.

Parameter Type Description
body Object Parameters for the generating a one time payment checkout session at Stripe

body

Key Type Value
applicationCustomerId string Id of the application customer that the payment will be generated for.
currency string Currency of the payment.
items Array Array of items to be paid.
payoutData Object Payout data for the payment.
publicDomain String Public domain of the server, to use the return URLs.
automaticTax Object (Optional) Automatic tax data for the payment. If sent, should be the object: { enabled: true }
newCustomerParams Object (Optional) This is only for oneTimePayment scenarios where no persistent customer exists, like the subscription or saved payment method scenarios. If sent, a new customer will be generated with the given parameters if there is no existing customer with the applicationCustomerId parameter.
items
Key Type Value
name string Name of the item.
amount string Amount of the item, in cents.
tax_code string Tax code of the item. Comes from the Stripe's Product Tax Categories.
payoutData
Key Type Value
payoutAmount string Amount to be paid to the payee, in cents.
payoutAccountId string Stripe account id of the payee.
newCustomerParams
Key Type Value
email string Email of the customer.
description string Description of the customer.
metadata Object Metadata for the customer, you can embed andy data within this object, it is kept in Stripe servers also.
name string Name of the customer.
phone string Phone number of the customer.
address Object Address of the customer.

Returns

Returns the checkoutSession object created by Stripe. The url field of the returned payload can be used to redirect the end user to the Stripe's website to complete the payment process.

{
	result: 'OK',
	payload: checkoutSession,
}

Example

const currency = 'eur';
const items = [
	// txcd_30060006 is the tax code for the "Hats" category in https://stripe.com/docs/tax/tax-categories
	{ name: "Red Hat", unitAmountDecimal: "100000", tax_code: 'txcd_30060006' }, 
	{ name: "Green Hat", unitAmountDecimal: "200000", tax_code: 'txcd_30060006' },
	{ name: "Blue Hat", unitAmountDecimal: "300000", tax_code: 'txcd_30060006' },
];
const payoutData = {
	payoutAmount: "225000",
	payoutAccountId: "some-account-id-who-will-receive-the-payment",
	useOnBehalfOf: true
};
const automaticTax = { enabled: true };
const props = {
	applicationCustomerId,
	currency,
	items,
	payoutData,
	publicDomain,
	automaticTax,
};
const response3 = await tsb.oneTimePayment(props);

oneTimePaymentSuccessRoute

Provides the default route content for th /one-time-payment-success-route route. This route is used to handle the return URL of the checkout session. The default route content can be used as is, or you can use it as a template to create your own route content. We suggest to use this route because it helps to manage the frontend application web view state.

oneTimePaymentCancelRoute

Provides the default route content for th /one-time-payment-cancel-route route. This route is used to handle the refresh URL of the checkout session. The default route content can be used as is, or you can use it as a template to create your own route content. We suggest to use this route because it helps to manage the frontend application web view state.

getOneTimePaymentStatus

Returns the status of a one time payment.

Parameter Type Description
body Object Parameters for the generating a one time payment checkout session at Stripe

body

Key Type Value
checkoutSessionId string Id of the checkout session.

Returns

The payload holds the database state of the requested payment.

{
	result: 'OK',
	payload: rows,
}

The payload.rows[0] is a database row in the following form:

 id |              application_customer_id               | stripe_customer_id |                        checkout_session_id                         |        update_time         | total_amount_decimal | currency | state |         invoice_id          |                                                                      hosted_invoice_url                                                                       | payout_amount |   payout_account_id   | payout_state 
----+----------------------------------------------------+--------------------+--------------------------------------------------------------------+----------------------------+----------------------+----------+-------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-----------------------+--------------
  2 | Application Customer-1679582193973                 | cus_... | cs_xxxx... | 2023-03-24 14:34:57.000013 |               450000 | eur      | P     | in_... | https://invoice.stripe.com/i/acct_.../test_...?s=ap |        225000 | acct_... | W

Here the state = 'P' means the payment is completed. And you can ues the url in the hosted_invoice_url field to show the invoice to the customer.

refundOneTimePayment

Refunds a completed one time payment using the checkout session id.

Parameter Type Description
body Object The object that holds the parmeters

body

Key Type Value
checkoutSessionId string Id of the checkout session.

Returns

The payload holds the refund object coming from Stripe.

{
	result: 'OK',
	payload: refund,
}

Example

const checkoutSessionIdToRefund = "cs_XXX"; // completed checkout session id of the payment to be refunded
await tsb.refundOneTimePayment({ checkoutSessionId: checkoutSessionIdToRefund });

webhook

This is a webhook endpoint that can be used to handle the Stripe events. The events are directed to different functions.

This library handles following events

Event Function Description
checkout.session.completed webhookCheckoutSessionCompletedSetup or webhookCheckoutSessionCompletedPayment Stripe sends this event when
a checkout session for a new customer payment method is completed
or when a one time payment is done. This library checks the event.data.object.mode parameter to differentiate these 2 events.
invoice.paid webhookSubscriptionInvoicePaid We use this event to detect subscription payments. For this purpose we check if the event.data.object.billing_reason field is subscription related or not. (If it is not subscription related, it is ignored.)
account.updated webhookAccountUpdated We use this event to detect connected account updates. And we check the event.data.object.charges_enabled and the event.data.object.payouts_enabled parameters to decide if the connected account is successfully generated or not.

Using the data in the DB

The tamed-stripe libraries provide the fundamental functionalities connecting to the Stripe. However, if there is no change at Stripe, the data in the database can be used to get latest state of the customers, connected accounts, subscriptions and payments without calling Stripe.

For these purposes we suggest to familiarize yourself with the database structure. The ERD of the database can be found below.

ERD

More Examples

The example application can be found here. Also the jest test cases can be used as examples, which can be found here.

License

The license is MIT and full text here.

Used Modules

Please refer to the main github page for the list of used modules.

Readme

Keywords

none

Package Sidebar

Install

npm i tamed-stripe-backend

Weekly Downloads

0

Version

1.1.13

License

MIT

Unpacked Size

112 kB

Total Files

16

Last publish

Collaborators

  • mehmet.kaplan