Quick Start Guide

Quick Start Guide

Cancel Flow Quick Start Guide

icon
Get Churnkey up and running. Easily.

Step One: Place Script Element

The following code will pull in the Churnkey client-side module and add it under the window.churnkey namespace so that you can later initialize the Churnkey Cancel Flow for your customers. Place it in the HTML <head> element. YOUR_APP_ID can be found in Your Account.

<script>
!function(){  
  if (!window.churnkey || !window.churnkey.created) {
    window.churnkey = { created: true };
    const a = document.createElement('script');
    a.src = 'https://assets.churnkey.co/js/app.js?appId=YOUR_APP_ID';
    a.async = true;
    const b = document.getElementsByTagName('script')[0];
    b.parentNode.insertBefore(a, b);
  }
}();
</script>

Step Two: Generate Secure HMAC Hash

icon
Note for Paddle Users Use the Subscription ID instead of Customer ID for creating the HMAC hash

To ensure that all customer requests processed by Churnkey are authorized, server-side verification is implemented. This involves generating an HMAC hash on the customer ID (or subscription ID for Paddle users) using SHA-256 hashing. Before triggering the Churnkey flow, a request is sent to the server to (a) validate the request's authenticity, typically using existing authorization measures, and (b) compute the customer's ID hash. Below are examples in various backend languages.

Node.js
const crypto = require("crypto");
const user_hash = crypto.createHmac(
    "sha256",
    API_KEY // Your Churnkey API Key (keep this safe)
).update(CUSTOMER_ID).digest("hex"); // Send to front-end
Node.js
Next.js
import crypto from "crypto";
import type { NextApiRequest, NextApiResponse } from "next";

type Data = {
  userHash?: string;
  error?: string;
};

export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>
) {
  const { customerId } = req.body;

  if (!customerId) {
    return res.status(400).json({ error: "Missing customerId" });
  }

  const API_KEY = process.env.CHURNKEY_API_KEY || ""; // Your Churnkey API Key
  const userHash = crypto
    .createHmac("sha256", API_KEY)
    .update(customerId)
    .digest("hex");

  return res.status(200).json({ userHash });
}
Python (Django)
import hmac
import hashlib
email_hash = hmac.new(
    API_KEY, # Your Churnkey API Key (keep safe)
    CUSTOMER_ID, # Stripe Customer ID
    digestmod=hashlib.sha256
).hexdigest() # Send to front-end
Python (Django)
Ruby (Rails)
OpenSSL::HMAC.hexdigest(
  "sha256",
  API_KEY, # Your Churnkey API Key (keep safe)
  CUSTOMER_ID # Stripe Customer ID
) #send to front-end
Ruby (Rails)
PHP
<?php
echo hash_hmac('sha256', CUSTOMER_ID, API_KEY); // Stripe Customer Id
?>
PHP
Go
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
)

func main() {
	hash := hmac.New(sha256.New, API_KEY)
	hash.Write(CUSTOMER_ID)	
	hex.EncodeToString(hash.Sum(nil))
}
Go
Java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class Test {
  public static void main(String[] args) {
  try {
      String secret = API_KEY; // API Secret
      String message = CUSTOMER_ID; // Stripe Customer Id

      Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
      SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
      sha256_HMAC.init(secret_key);

      byte[] hash = (sha256_HMAC.doFinal(message.getBytes()));
      StringBuffer result = new StringBuffer();
      for (byte b : hash) {
        result.append(String.format("%02x", b));
      }
      System.out.println(result.toString());
    }
    catch (Exception e){
      System.out.println("Error");
    }
  }
}
Java
.Net
using System;
using System.Security.Cryptography;
using System.Text;

public class Test
{
    public static void Main(string[] args)
    {
        try
        {
            string secret = "API_KEY"; // API Secret
            string message = "CUSTOMER_ID"; // Customer ID

            using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
            {
                byte[] hash = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(message));
                StringBuilder result = new StringBuilder();
                foreach (byte b in hash)
                {
                    result.Append(b.ToString("x2")); // Converts to hexadecimal
                }
                Console.WriteLine(result.ToString());
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
        }
    }
}

Step Three: Launch Churnkey

Once the HMAC hash has been generated, you can initialize and display the Churnkey Cancel Flow by calling window.churnkey.init('show'). Typically, you will attach an event listener to a "cancel" button.

Adding the authHash

Simply use the Server Side Authentication section above to implement an HMAC hash function and pass that value into the authHash parameter.

document.getElementById('cancel-button').addEventListener('click', function () {
  window.churnkey.init('show', {
    subscriptionId: 'SUBSCRIPTION_ID' // recommended unless Paddle
    customerId: 'CUSTOMER_ID', // required unless Paddle
    authHash: 'HMAC_HASH', // required
    appId: 'YOUR_APP_ID', // required
    mode: 'live', // set to 'test' to hit test billing provider environment
    provider: 'stripe', // set to 'stripe', 'chargebee', 'braintree', 'paddle'
    record: true, // set to false to skip session playback recording
  })
})
Next.js
const customerId = user.customerId // get your customerId
const res = await fetch("/api/churnkey", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    customerId,
  }),
});

if (!res.ok) {
  console.error("Failed to fetch user_hash");
  return;
}

const { userHash } = await res.json();

document.getElementById('cancel-button').addEventListener('click', function () {
  window.churnkey.init('show', {
    customerId: customerId, // required unless Paddle
    authHash: userHash, // required
    subscriptionId: 'SUBSCRIPTION_ID' // recommended unless Paddle
    appId: 'YOUR_APP_ID', // required
    mode: 'live', // set to 'test' to hit test billing provider environment
    provider: 'stripe', // set to 'stripe', 'chargebee', 'braintree', 'paddle'
    record: true, // set to false to skip session playback recording
  })
})
💠
h

Log In Sign up

© Churnkey, Inc. 2024