skip to Main Content

Node.js
Using paypal sandbox env

const PAYPAL_BASE_URL = "https://api.sandbox.paypal.com";
const PAYPAL_TOKEN_URL = `${PAYPAL_BASE_URL}/v1/oauth2/token`;

const tokenOptions = {
  method: "post",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded",
    "Access-Control-Allow-Credentials": true,
  },
  data: qs.stringify({ grant_type: "client_credentials" }),
  auth: {
    username: `${CLIENT_ID}`,
    password: `${CLIENT_SECRET}`,
  },
  url: `${PAYPAL_TOKEN_URL}`,
};

async function getToken() {
  return await axios(tokenOptions)
    .then((res) => {
      console.log(res.data.access_token);
      console.log(res.data.expires_in);
      console.log(res.data);
      return res.data;
    })
    .catch((err) => {
      console.log(err);
    });
}

Response

 "scope": "https://uri.paypal.com/services/invoicing https://uri.paypal.com/services/disputes/read-buyer https://uri.paypal.com/services/payments/realtimepayment https://uri.paypal.com/services/disputes/update-seller https://uri.paypal.com/services/payments/payment/authcapture openid https://uri.paypal.com/services/disputes/read-seller https://uri.paypal.com/services/payments/refund https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/payments/.* https://uri.paypal.com/payments/payouts https://api.paypal.com/v1/vault/credit-card/.* https://uri.paypal.com/services/subscriptions https://uri.paypal.com/services/applications/webhooks",
    "access_token": "xxxxxxxx",
    "token_type": "Bearer",
    "app_id": "xxxx",
    "expires_in": 32346,
    "nonce": "2020-11-07T20:09:09Zmc3xM34owS0WsAI5rHVx2eOJb80xJ06Z6tFQx6LT_i0"

As you can see I am not getting the refresh_token. Reading the documentation I wanted to use the refresh token to get a new access_token when the expire time is getting close.
Should I not be getting a refresh_token here?

2

Answers


  1. Chosen as BEST ANSWER

    @Preston PHX

    Adding a comment here as the comments does not allow that many characters. Can I do something to get a refresh_token? Problems I have is that I am using node as a proxy with http-proxy-middleware.

    app.use("/", PROXY_TO_PAYPAL);
    

    On app startup I authenticate and store the token in a variable that will expire.

      console.log(`Starting proxy at ${HOST}:${PORT}`);
      console.log(`PAYPAL_TOKEN_URL: ${PAYPAL_TOKEN_URL}`);
      // set the token on startup
      getToken().then((data) => {
        token = data.access_token;
        console.log(`expires_in ${parseInt(data.expires_in)} seconds`);
        const timeoutDate = getTimeoutDate(parseInt(data.expires_in) * 1000);
        tokenTimeOut = timeoutDate.getUTCMilliseconds();
        console.log(`Token times out at ${timeoutDate.toUTCString()}`);
      });
    });
    

    I need to update the token BEFORE it expires, otherwise I risk that a proxy request will fail as it could potentially use an expired token. I created a scheduler that will watch the when the token is getting close to expire and will renew it (call the authentication again), like say 15 min before.

    
    async function getToken() {
      return await axios(tokenOptions)
        .then((res) => {
          console.log(res.data.access_token);
          console.log(res.data.expires_in);
          console.log(res.data);
          return res.data;
        })
        .catch((err) => {
          console.log(err);
        });
    }
    
    cron.schedule("* * * * *", function () {
      console.log("running a task every minute");
      // refresh token
      if (tokenTimeOut - new Date().getUTCMilliseconds() < 900*1000) {
        getToken().then((data) => {
          token = data.access_token;
          const timeoutDate = getTimeoutDate(parseInt(data.expires_in) * 1000);
          tokenTimeOut = timeoutDate.getUTCMilliseconds();
          console.log(`Token times out at ${timeoutDate.toUTCString()}`);
        });
      }
    });
    
    

    I am adding the Bearer header on each request bore it is proxied

    const middlewareOptions = {
      target: `${PAYPAL_BASE_URL}`, // target host
      changeOrigin: true,
      onProxyReq(proxyReq, req, res) {
        if (!token) {
          getToken().then((data) => {
            token = data.access_token;
            tokenTimeOut = data.expires_in;
          });
        }
        proxyReq.setHeader("Authorization", `Bearer ${token}`);
      },
    };
    

    I might get the same token again until I am closer to the expire date (I think) - which could work. Eventually I would get a new token and a new expire time.

    I am confused about the documentation. Here they talk about the refresh_token https://developer.paypal.com/docs/connect-with-paypal/integrate/#6-get-access-token But here there are not refresh_token https://developer.paypal.com/docs/api/get-an-access-token-curl/

    What I wanted to do is when I am close to the expire time I would use the refresh_token to get a new token.


  2. A client credentials request using a clientid/secret does not give a refresh_token.

    Just repeat the same request when needed.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search