Last active
December 23, 2020 23:08
-
-
Save biancadanforth/3510347614bb64bfcbc5af5b43055a52 to your computer and use it in GitHub Desktop.
Fetching an ephemeral OAuth2 bearer token from PayPal sandbox when we don't have one or it's expired and then calling a PayPal API that requires the token.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fetch = require("node-fetch"); | |
const { getPayPalBearerToken } = require("../../github/bin/get-oauth2-token/bin/getOAuth2Token"); | |
const PAYPAL_SANDBOX_BASE_URL = "https://api-m.sandbox.paypal.com"; | |
async function postToPayPalAPI(apiPath, body) { | |
const bearerToken = await getPayPalBearerToken(); | |
const metadata = { | |
body, | |
headers: { | |
"Content-Type": "application/json", | |
"Authorization": `Bearer ${bearerToken}`, | |
}, | |
method: "POST", | |
} | |
const response = await fetch(`${PAYPAL_SANDBOX_BASE_URL}${apiPath}`, metadata); | |
const json = await response.json(); | |
if (json.error) { | |
throw new Error(`Encountered error ${json.error}: ${json.error_description}`); | |
} | |
console.log(json); | |
} | |
const apiPath = "/v2/checkout/orders"; | |
const body = `{ | |
"intent": "CAPTURE", | |
"purchase_units": [ | |
{ | |
"amount": { | |
"currency_code": "USD", | |
"value": "100.00" | |
} | |
} | |
] | |
}`; | |
postToPayPalAPI(apiPath, body); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const fs = require("fs"); | |
const fetch = require("node-fetch"); | |
const PAYPAL_OAUTH2_ENDPOINT = "https://api-m.sandbox.paypal.com/v1/oauth2/token"; | |
const LAST_RESPONSE_PATH = `${__dirname}/lastOAuth2Response`; | |
function getLastResponse() { | |
const lastResponseJSON = fs.readFileSync(LAST_RESPONSE_PATH, { encoding: "utf8", flag: "a+" }); | |
const lastResponse = lastResponseJSON === "" ? {} : JSON.parse(lastResponseJSON); | |
return lastResponse; | |
} | |
async function main() { | |
const bearerToken = await getPayPalBearerToken(); | |
console.log(bearerToken); | |
} | |
if (require.main === module) { | |
main(); | |
} | |
function toBase64(str) { | |
return Buffer.from(str).toString("base64"); | |
} | |
/** | |
* Checks if the time elapsed since last fetching the token exceeds | |
* the duration in which the token is valid. | |
* | |
* @param expiresInMs { Number } Duration of time in ms for which the token is valid | |
* @param lastReceivedMs { Number } Date of the last request in ms elapsed since | |
* January 1, 1970 00:00:00 UTC | |
*/ | |
function isExpired(expiresInMs, lastReceivedMs) { | |
if (!expiresInMs || Date.now() - lastReceivedMs > expiresInMs) { | |
return true; | |
} | |
return false; | |
} | |
async function getPayPalBearerToken() { | |
// We may have previously requested the bearer token, so read in the last response | |
// data, if any. | |
let { bearerToken, expiresInMs, lastReceivedMs } = getLastResponse(); | |
// Check to see if we have previously fetched a token, and if it is | |
// still valid. | |
if (bearerToken && !isExpired(expiresInMs, lastReceivedMs)) { | |
return bearerToken; | |
} | |
// Else, get a new one, cache it and return it. | |
const username = toBase64(process.env.PAYPAL_SANDBOX_USERNAME); | |
const password = toBase64(process.env.PAYPAL_SANDBOX_PASSWORD); | |
const metadata = { | |
body: "grant_type=client_credentials", | |
headers: { | |
"Accept": "application/json", | |
"Accept-Language": "en_US", | |
"Authorization": `Basic ${username}:${password}`, | |
"Content-Type": "application/x-www-form-urlencoded", | |
}, | |
method: "POST", | |
} | |
const response = await fetch(PAYPAL_OAUTH2_ENDPOINT, metadata); | |
const json = await response.json(); | |
if (json.error) { | |
throw new Error(`Encountered error ${json.error}: ${json.error_description}`); | |
} | |
bearerToken = json["access_token"]; | |
expiresInMs = parseInt(json["expires_in"], 10) * 1000; | |
lastReceivedMs = Date.now(); | |
fs.writeFileSync(LAST_RESPONSE_PATH, JSON.stringify({bearerToken, expiresInMs, lastReceivedMs})); | |
return bearerToken; | |
} | |
module.exports = { | |
getPayPalBearerToken, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment