Sitemap

Unlocking Feature: How to Call Third-Party APIs from Your BigCommerce Stencil Theme

5 min readAug 26, 2024

--

Press enter or click to view image in full size

Prerequisite

Set up a custom app with BigCommerce, we are not going into details to set up a custom app. If you want to set up a custom app with BigCommerce refer to documentation and GitHub code. Also, we are using a cornerstone theme for frontend (stencil)

https://developer.bigcommerce.com/docs/integrations/apps/quick-start

Developer Portal Account(opens in a new tab) (required to register apps)

https://github.com/bigcommerce/sample-app-nodejs

Once you have created a Single Click app from Developer Tools then download the CLIENT_SECRET and CLIENT_ID.

Assuming you have set the application which is up and running

Since In this article, we are using Next Js so we will be doing the rest of the code in NextJs only

STEP — 1

Go to the BigCommerce Script Manager of your selected channel and enter the below code. This is just a javascript object added in the window object, you can give any name for the Client ID and URL.

Here, the Client ID will be the same as the custom app client ID, and the URL will be your hosted app's public URL.


<script>
window.custom_app = {
oc_demo : {
setting: {
oc_demo_client_id: "<your-custom-app-client-id>",
oc_demo_url: "https://tidy-cloths-sit.loca.lt"
}
}
}
</script>

<!-- Get current customer JWT token using app_client_id -->
{{#if customer}}
<script>
const app_client_id = window.custom_app.oc_demo.setting.oc_demo_client_id;
const app_url = window.custom_app.oc_demo.setting.oc_demo_url;
const customerJWT = (apiAccountClientId) => {
let resource = `/customer/current.jwt?app_client_id=${apiAccountClientId}`;
return fetch(resource)
.then(response => {
if(response.status === 200) {
return response.text();
} else {
return new Error(`response.status is ${response.status}`);
}
})
.then(jwt => {
console.log(jwt); // JWT here
// call your API with JWT
fetch(`${app_url}/api/test`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({token: jwt})
})

})
.catch(error => console.error(error));
}
customerJWT(app_client_id);
</script>
{{/if}}

Press enter or click to view image in full size
PART — 1
Press enter or click to view image in full size
Part — 2

You can add the above script to the base.html file for local development purposes.

STEP — 2

Now login from the stencil theme and open the browser’s dev tools you will see an Ajax call will appear in the network tab

Press enter or click to view image in full size

In the above screenshot, we can see a network call is going to our custom app server /api/test

STEP — 3

Now Let’s set Authorization in our custom app

Go to lib/auth.ts file in the custom app (Already available in sample next js app)

Get Gaurav Kumar’s stories in your inbox

Join Medium for free to get updates from this writer.

Add the below code as a library function for your JWT token created using the above code.

Press enter or click to view image in full size

export function decodeJwtToken(jwtToken: string) {
try {
const secret = CLIENT_SECRET;
// Decode the JWT token
const signedData = jwt.verify(jwtToken, secret, {
algorithms: ['HS256', 'HS384', 'HS512', 'RS256'],
});

return signedData;
} catch (error) {
console.error('Error decoding JWT token:', error);
throw error;
}
}

STEP — 4

Go to the .env file and add the below environment variable

ALLOWED_ORIGIN="<your-app-public-url>"

STEP — 5

In our custom application install Cors library from the terminal

npm install cors --save

STEP — 6

Now create a middleware folder under lib and create a new typescript file called cors.ts

Add the below code in the cors.ts file. We can use this middleware in our other API endpoints.

import Cors from 'cors';
import { NextApiRequest, NextApiResponse } from 'next';

// Initialize the CORS middleware
const cors = Cors({
methods: ['GET', 'HEAD', 'POST', 'OPTIONS'], // Allowed methods
origin: process.env.ALLOWED_ORIGIN, // Replace with your allowed origin
credentials: true, // Enable cookies and other credentials
});

// Helper method to wait for a middleware to execute before continuing
function runMiddleware(req: NextApiRequest, res: NextApiResponse, fn: any) {
return new Promise((resolve, reject) => {
fn(req, res, (result: any) => {
if (result instanceof Error) {
return reject(result);
}

return resolve(result);
});
});
}

export default async function applyCors(req: NextApiRequest, res: NextApiResponse, next: () => void) {
await runMiddleware(req, res, cors);
next();
}

STEP — 7

Create a new API called test.ts in pages/api/ and add the below code in the test.ts file

Press enter or click to view image in full size
import { NextApiRequest, NextApiResponse } from 'next';
import { decodeJwtToken } from '@lib/auth';
import applyCors from '@lib/middleware/cors';
//import { bigcommerceClient } from '../../lib/auth';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
await applyCors(req, res, () => null);
const {
body : {token},
method,
} = req;

if (method === 'POST') {
const decodedPayload = decodeJwtToken(token);
res.status(200).json({ message: decodedPayload});
} else {
res.setHeader('Allow', ['POST']);
res.status(405).end(`Method ${method} Not Allowed`);
}

}

STEP — 8

Restart your app using the below command

npm run dev

STEP — 9

Now refresh the stencil theme page, you will see the JSON response of the decoded payload

Here CLIENT_SECRET is used to decrypt the JWT token, if we use a different client secret value then we will not be able to decode the JWT token and will get the error/exception.

STEP — 10

Once we have the decoded value then we can assure that it is a valid token and can proceed further.

Press enter or click to view image in full size

In the above example, we are just returning the decoded value of the token, but in production, we are not going to return the decoded values. This is just for the demo purpose.

--

--

Gaurav Kumar
Gaurav Kumar

Written by Gaurav Kumar

I am experienced in cloud-based enterprise applications and have over 9 years of industry experience across varied domains and technologies.