The user billing management embed allows your users to self service actions like entering/upgrading their credit card, switching pricing tiers, and viewing their invoices. This integration involves a piece of server-side code to generate a JSON web token to authenticate the user, and a piece of client-side code to display the UI. 

  1. Go to 'Embeds'
  2. Click on 'Billing Settings'
  3. Select your backend language/framework

Server Side

Let’s start by creating a route that's protected with authentication middleware (whether that be the Servicebot Auth set up before, or a custom one).  The generateJWT method uses the Servicebot instance secret and the user’s email. In the example (controllers/user.js), we get the Servicebot secret from a global variable and the users email from the req variable.
We then render the client side code and pass it the token we generated and the Servicebot URL.

exports.getBilling = (req, res) => {
    function generateJWT(email, key) {
        var crypto = require('crypto');
        var hmac = crypto.createHmac('sha256', key);

        var payload = {
            "email": email
        };
        var header = {
            "alg": "HS256",
            "typ": "JWT"
        };
        function cleanBase64(string) {
            return string.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_")
        }

        function base64encode(object) {
            return cleanBase64(Buffer.from(JSON.stringify(object)).toString("base64"));
        }

        var data = base64encode(header) + "." + base64encode(payload);
        hmac.update(data);
        return data + "." + cleanBase64(hmac.digest('base64'));
    }

    var SECRET_KEY = process.env.SERVICEBOT_SECRET; //keep this key safe!
    var userToken = generateJWT(req.user.email, SECRET_KEY);


    res.render('account/billing', {
        user: req.user, // get the user out of session and pass to template
        userToken: userToken,
        servicebotUrl: process.env.SERVICEBOT_URL || "http://localhost:3000",
        title: 'Billing'
    });
};

Client Side

To display the client side code we grab the embed code from our Servicebot instance. Create a new file in the ‘views’ folder and paste in the embed code (views/account/billing.pug).
The key pieces of the Client side embed code are:

  • url: The Servicebot instance URL. This should be automatically assigned from the embed code. It is the URL of the Servicebot instance. We will assign it to a global variable so we can use it in other places.
  • token: This is the token passed form the server-side code. It will authenticate the user, giving them permission to view their billing settings. The default expiration time for this token is 3 hours. We recommend keeping that, but to change it: …..
  • handleResponse: A function called after billing operations. You can perform any actions needed after billing operations like a user changing tiers, cancelling, or resubscribing. For business critical operations like these, we recommend using the webhooks for these events to ensure that the javascript is not tampered with. 

Response object example:

{
   "event":"change_plan",
   "response":{
      "id":117,
      "service_id":33,
      "user_id":196,
      "requested_by":196,
      "payment_plan":{
         "id":"Standard-123-ID117-pqi8",
         "name":"Standard-123",
         "tiers":null,
         "active":true,
         "amount":6000,
         "object":"plan",
         "created":1548217817,
         "product":"prod_EOQDfbM0EDFJdd",
         "currency":"usd",
         "interval":"year",
         "livemode":false,
         "metadata":{

         },
         "nickname":null,
         "tiers_mode":null,
         "usage_type":"licensed",
         "billing_scheme":"per_unit",
         "interval_count":1,
         "aggregate_usage":null,
         "transform_usage":null,
         "trial_period_days":14,
         "statement_descriptor":"Subscription"
      },
      "name":"SaaS with Auth",
      "description":null,
      "subscription_id":"sub_EONkA33xiqcKPg",
      "subscribed_at":1548208627,
      "trial_end":1549418227,
      "status":"running",
      "type":"subscription",
      "split_configuration":null,
      "created_at":"2019-01-23T01:57:06.991Z",
      "updated_at":"2019-01-23T04:30:18.276Z",
      "payment_structure_template_id":123,
      "references":{
         "service_templates":[
            {
               "id":33,
               "category_id":null,
               "created_by":1,
               "name":"SaaS with Auth",
               "published":true,
               "created_at":"2018-10-26T02:08:56.897Z",
               "updated_at":"2018-11-18T20:21:13.902Z"
            }
         ],
         "service_instance_properties":[
            {
               "id":142,
               "name":"__usage",
               "type":"metric",
               "data":{
                  "value":0
               },
               "config":{
                  "unit":"User",
                  "value":{
                     "name":"User"
                  },
                  "isSeat":true,
                  "pricing":{
                     "tiers":[
                        "Basic",
                        "Plus"
                     ],
                     "operation":"multiply"
                  }
               },
               "prop_class":null,
               "prop_label":"__usage",
               "prop_description":null,
               "created_at":"2018-10-26T02:08:56.917Z",
               "updated_at":"2018-10-26T02:08:56.917Z",
               "parent_id":117,
               "private":false,
               "prompt_user":true,
               "required":false
            }
         ],
         "users":[
            {
               "id":196,
               "role_id":3,
               "name":null,
               "email":"exampleuser@example.com",
               "provider":"local",
               "status":"active",
               "customer_id":"cus_EONkEEIeiJn44q",
               "phone":null,
               "last_login":null,
               "created_at":"2019-01-23T01:57:06.970Z",
               "updated_at":"2019-01-23T01:57:06.970Z",
               "google_user_id":null,
               "google_refresh_token":null
            }
         ],
         "payment_structure_templates":[
            {
               "id":123,
               "tier_id":81,
               "trial_period_days":14,
               "amount":6000,
               "type":"subscription",
               "currency":"usd",
               "interval":"year",
               "interval_count":1,
               "subscription_prorate":true,
               "statement_descriptor":null,
               "split_configuration":null,
               "created_at":"2018-11-06T19:16:16.471Z",
               "updated_at":"2018-11-06T19:16:16.471Z"
            }
         ]
      }
   }
}
  • disablePlanChange: If true, a customer will not be able to change their plan using the embeddable.
  • serviceInstanceId: If specified, only pull up the billing settings for this specific instance, useful if your customers can have multiple subscriptions and you don't want them to see all of them on one page.
Servicebot.BillingSettings({        
  url : "https://example.serviceshop.io",        
  selector : document.getElementById('servicebot-management-form'),
  handleResponse : (response) => {            
    console.log(response);        
  },        
  token: "INSERT_TOKEN_HERE",        
  disablePlanChange: false    
})

Tips:

  • If your language/framework is not available, you can use a JSON Web Token library to generate a token, or, using an administrator account, use this API to get a token for a specific customer
  • The server side code can be reused for the seat management embed as it also uses a JSON Web Token
  • Changing a pricing plan will trigger a webhook call
Did this answer your question?