Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,33 @@

## Requirements

* npm 6.4.1
* axios 0.18.0
* express 4.16.4
* nodemon 1.18.4
* [Sandbox Clover developer account](https://sandbox.dev.clover.com/developers)
- npm 6.4.1
- axios 0.18.0
- express 4.16.4
- nodemon 1.18.4
- [Sandbox Clover developer account](https://sandbox.dev.clover.com/developers)

## Set Up

Follow these [instructions](https://docs.clover.com/build/web-apps/) for creating a Clover web app and installing it to your sandbox test merchant. When creating the app, select the [permissions](https://docs.clover.com/build/permissions/) you want the OAuth token to have.

* On the app's **Settings** page, note _App ID_ and _App Secret_. Set them as `appID` and `appSECRET` at the top of index.js.
* Under **Web Configuration**, set _Site URL_ and _CORS Domain_ to `http://localhost:5000`.
- On the app's **Settings** page, note _App ID_ and _App Secret_. Set them as `appID` and `appSECRET` at the top of `index.js`.
- Under **Web Configuration**, set _Site URL_ and _CORS Domain_ to `http://localhost:5000`.

### OAuth Version 1 and Version 2 Endpoints

- The application exposes two versions of the API:
- **V1**: [http://localhost:5000](http://localhost:5000)
- **V2**: [http://localhost:5000/v2](http://localhost:5000/v2) (OAuth 2.0 required)

Run:
* `npm install`
* `npm run server`

In your web browser, visit [http://localhost:5000/](http://localhost:5000/).
- `npm install`
- `npm run server`

In your web browser, visit:

- [http://localhost:5000](http://localhost:5000) to access V1
- [http://localhost:5000/v2](http://localhost:5000/v2) to access V2

**Note**: The Clover v2 OAuth flow is only available in North America.
64 changes: 52 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,78 @@
const express = require('express');
const axios = require('axios');
const session = require('express-session');

// Config Set Up
const targetEnv = 'https://sandbox.dev.clover.com'; // Pointing to Sandbox Environment
// const targetEnv = 'https://www.clover.com'; // Pointing to Prod Environment

const appID = ''; // Input your app ID here
const appSecret = ''; // Input your app secret here
const sessionSecret = 'your-super-secret-key'; // Input your session secret here

// Initialize Express
const app = express();

// Setup session middleware
app.use(
session({
secret: sessionSecret,
resave: false,
saveUninitialized: true,
})
);

// Function to determine the version path from the URL
const getVersionPath = (req) => {
return req.originalUrl.startsWith('/v2') ? '/v2/' : '/';
};

// Root Route
app.get('/', (req, res) => authenticate(req, res));

// v2 Route
app.get('/v2', (req, res) => authenticate(req, res));

// Steps 1 & 2 - Request merchant authorization to receive authorization code
const authenticate = async (req, res) => {
const url = `${targetEnv}/oauth/authorize?client_id=${appID}`;
const versionPath = getVersionPath(req);
const url = `${targetEnv}/oauth${versionPath}authorize?client_id=${appID}`;

/* If there is no code parameter in the query string of the current url
redirect user for authentication. If there isn't then request API token */
!req.query.code ? await res.redirect(url) : await requestAPIToken(res, req.query);
}
// If there is no code parameter in the query string, redirect user for authentication
if (!req.query.code) {
// Store the version path in the session for future use
req.session.versionPath = versionPath;
return res.redirect(url); // Use return to ensure no further code execution after redirect
} // If is code parameter in the query string, then request API token
else {
// Retrieve the version path from the session
const versionPath = req.session.versionPath || versionPath;
return requestAPIToken(res, req.query.code, versionPath);
}
};

// Steps 3 & 4 - Request and serve up API token using the received authorization code
const requestAPIToken = async (res, query) => {
const url = `${targetEnv}/oauth/token?client_id=${appID}&client_secret=${appSecret}&code=${query.code}`;
const requestAPIToken = async (res, code, versionPath) => {
const url = `${targetEnv}/oauth${versionPath}token`;
const data = {
client_id: appID,
client_secret: appSecret,
code: code,
};

// Request
await axios.get(url)
await axios
.post(url, data)
.then(({ data }) => res.send(data))
.catch(err => res.send(err.message));
}
.catch((err) => res.send(err.message));
};

// Dynamic Port Binding
const port = process.env.port || 5000
app.listen(port, () => console.log(`🍀 Run http://localhost:${port} in your browser`));
const port = process.env.port || 5000;
app.listen(port, () => {
console.log(
'🍀 Server is running. Access the application at the following URLs:'
);
console.log(` - V1: http://localhost:${port}`);
console.log(` - V2: http://localhost:${port}/v2 (OAuth 2.0 required)`);
});
Loading