@billing-js/react-billing-js
TypeScript icon, indicating that this package has built-in type declarations

1.1.18 • Public • Published

React Billing.js

Setup pricing page and a customer portal by copy pasting code snippets.

Install

Using NPM:

npm i @billing-js/react-billing-js

Using Yarn:

yarn add @billing-js/react-billing-js

Stripe account Id

Get your Billing.js Stripe account id on billingjs.com.

Billing.js is using Stripe Connect on the background to access your products and manage the subscriptions for you.

Documentation

Checkout the full Billing.js documentation on docs.billingjs.com.

Usage

Wrap your App with the BillingProvider component to give it access to the billing context.

index.tsx - Root component of your react app

import React from "react"
import { render } from "react-dom"
import { BillingProvider } from "react-billing-js"

import YourApp from "./YourApp"

const ReactApp = (
    // Wrap your app with the billing provider with your stripe account id
    <BillingProvider
        stripeAccount={"acct_..."} // Your stripe account id that you can find in the billing.js dashboard (https://billingjs.com)
        options={{ termsAndConditionsUrl: "/terms", productPageUrl: "/pricing" }} // Optional
        onError={(error) => {}} // Optional for error handling
    >
        <YourApp />
    </BillingProvider>
)

render(<ReactApp />, document.getElementById("root"))

Authentication

Set your router to require authentication when accessing the customer portal.

App.tsx - Root component

import { useAuth, CustomerPortal } from "react-billing-js"
import { Switch, Route, Redirect, BrowserRouter as Router } from "react-router-dom"

import Pricing from "./Pricing"

export default () => {

    // use the useAuth hook to get the current user
    const { loading, user, signOut } = useAuth()

    const renderPrivateRoute = (Component, redirect = "/login") => () => {
        if (user) {
            return React.isValidElement(Component) ? Component : <Component />
        }
        return <Redirect to={redirect} />
    }

    if (loading) {
        return <div>loading...</div>
    }

    <Router>
        <Switch>
            <Route exact={true} path="/subscription" render={renderPrivateRoute(CustomerPortal)} />
            <Route exact={true} path="/pricing" component={Pricing} />
            <Route exact={true} path="/login" component={Login} />
            <Redirect to="/pricing" />
        </Switch>
    </Router>
)

Fetch the HMAC signature from your server to authenticate the user on the Billing.js module.

Login.tsx - Login page component

import { useAuth } from "react-billing-js"
const { loading, user, signIn } = useAuth()

// fetch the hmac now or retrieve it from the the app state, then sign in the user
// follow the steps in the [billingjs.com](https://billingjs.com) documentation to get the HMAC
const onSignIn = () => fetch("/URL_TO_GET_THE_HMAC").then((res) => signIn({ hmac: res?.data?.hmac, email: user.email }))

if (loading) {
    return <div>loading...</div>
}

if (user) {
    return <div>Signed in!</div>
}

return (
    <div>
        <button onClick={onSignIn}>Sign in</button>
    </div>
)

Pricing page

Show the pricing of the products of your choices to the user.

Pricing.tsx - Pricing page component

import { useProducts, PaymentModal } from "react-billing-js"
import { useHistory } from "react-router-dom"

export default () => {
    const history = useHistory() // optional, if you are using react-router

    // Billing.js useProducts hook
    const {
        loading, // loading state
        products: [premiumPlan], // list of the products fetched
        activeSubscriptions, // list of active subscriptions of the user
        pricingFilter: {
            currency: {
                selectedCurrency, // current currency (USD by default)
                availableCurrencies, // list of the available currencies
                setCurrency // function to set the desired currency
            },
            recurrence: {
                selectedRecurrence, // current recurrence
                availableRecurrences, // list of the available recurrences
                setRecurrence // function to set the desired recurrence
            }
        }
    } = useProducts(["prod_..."], {
        modal: {
            maskClassName: "bg-white opacity-75" // modal mask class name
        },
        normalizePriceOnRecurrence: "monthly", // Normalize price on recurrence
        defaultCurrency: "usd", // Default currency
        defaultRecurrence: "Yearly", // Default recurrence
        signIn: () => history.push("/login"), // Function to sign in the user
        onPaymentSuccessful: () => console.log(`Payment successful`), // Callback when payment is successful
        onPaymentError: (error) => console.log(`Payment error`, error) // Callback when payment is unsuccessful
    })

    return (
        <div>
            {/*Payment modal that will open when a pricing is selected*/}
            <PaymentModal />

            {/*Plan description and price*/}
            <h3>{premiumPlan.name}</h3>
            <h2>
                {selectedCurrency.symbol} {premiumPlan.selectedPricing.priceInteger}.
                {premiumPlan.selectedPricing.priceDecimal}/{premiumPlan.selectedPricing.pricingRecurrence}
            </h2>
            {/* Payment button */}
            {loading ||
            activeSubscriptions.find(
                (subscription) => subscription.items?.data[0]?.price?.id === premiumPlan.selectedPricing.id
            ) ? ( // If the user has an active subscription to this product
                <button disabled={true}>{loading ? "Loading..." : "Current plan"}</button>
            ) : (
                // If the user does not have an active subscription to this product
                <button onClick={premiumPlan.selectedPricing.onSelectPricing}>
                    {
                        activeSubscriptions.length > 0
                            ? "Switch plan" // If the user has an active subscription to another product
                            : premiumPlan.selectedPricing?.recurring?.trial_period_days
                            ? "Start your trial" // If the product has a trial period
                            : "Get started" // If the product is billed immediately
                    }
                </button>
            )}
        </div>
    )
}

Package Sidebar

Install

npm i @billing-js/react-billing-js

Weekly Downloads

2

Version

1.1.18

License

MIT

Unpacked Size

919 kB

Total Files

91

Last publish

Collaborators

  • mathias_gilson