eBay / ebay-oauth-nodejs-client

🔑 Generate an OAuth token that can be used to call the eBay Developer REST APIs.
https://ebay.github.io/ebay-oauth-nodejs-client/
Apache License 2.0
63 stars 29 forks source link

TypeError: Cannot read property 'clientId' of undefined #15

Open sarmadfolio3 opened 2 years ago

sarmadfolio3 commented 2 years ago

When trying to invoke the getApplicationToken function with proper credentials it throws an error in the console TypeError: Cannot read property 'clientId' of undefined.

Framwork: NestJs with TypeScript

dhruvxylisys commented 2 years ago

@sarmadfolio3, I have also got the same error of clinetId undefined, I have passed "env" : "SANDBOX" in EbayAuthToken object and resolved an error, please try it

const EbayAuthToken = require("ebay-oauth-nodejs-client");
    const ebayAuthToken = new EbayAuthToken({
         clientId:---Your client id---,
         env: "SANDBOX",
         clientSecret: ---Your Client secret id---
         redirectUri: ---Your redirect URL---
    });
    let token = await ebayAuthToken.getApplicationToken("SANDBOX");
    token = JSON.parse(token)
joeymigs commented 11 months ago

Having the same issue here.

b5414 commented 7 months ago

same

b5414 commented 7 months ago
const ebayAuthToken = new EbayAuthToken({
    clientId: 'clientId_clientId_clientId',
    clientSecret: 'clientSecret_clientSecret_clientSecret',
    redirectUri: 'redirectUri_redirectUri_redirectUri',
    env: 'SANDBOX',
});

const response = await ebayAuthToken.getApplicationToken('SANDBOX');
const token = JSON.parse(response).access_token;

// or
const token = await ebayAuthToken.getApplicationToken('SANDBOX').then(JSON.parse).then(({access_token})=>access_token);

// or
const token = await ebayAuthToken.getApplicationToken('SANDBOX').then((r)=>JSON.parse(r).access_token);

// or
const {access_token: token} = await ebayAuthToken.getApplicationToken('SANDBOX').then(JSON.parse);
Goldziher commented 5 months ago

same issue.

It works when I use env: "SANDBOX". But when i switch to using the production credentials (clientId, clientSecret and redirectUri) and switch to using env: "PRODUCTION", it repeats the issue.

Any chance for some maintainer attention?

nonInfelix commented 1 month ago

any solution?

Goldziher commented 1 month ago

any solution?

I'm posting the client I ended up writing:

import { InvocationContext } from '@azure/functions';
import EbayAuthToken from 'ebay-oauth-nodejs-client';

import { HttpMethod } from '@/constants/generic.js';
import {
    EbayBrowseItemsErrorResponse,
    EbayBrowseItemsSuccessResponse,
} from '@/ebay/types.js';
import { parseEbayResponse } from '@/ebay/utils.js';
import { FindProductsParameters } from '@/types.js';
import { loadEnv } from '@/utils/env.js';
import { ConfigurationError } from '@/utils/errors.js';
import { fetcher } from '@/utils/fetcher.js';

const EBAY_AFFILIATE_HEADER = 'X-EBAY-C-ENDUSERCTX';
const EBAY_MARKETPLACE_HEADER = 'X-EBAY-C-MARKETPLACE-ID';
const EBAY_BROWSE_API_ITEMS_SUMMARY_ENDPOINT =
    '/buy/browse/v1/item_summary/search';
const EBAY_API_BASE_URL_PRODUCTION = 'https://api.ebay.com';
const EBAY_API_BASE_URL_SANDBOX = 'https://api.sandbox.ebay.com';

const isErrResponse = (
    value:
        | EbayBrowseItemsErrorResponse
        | EbayBrowseItemsSuccessResponse
        | Record<string, never>,
): value is EbayBrowseItemsErrorResponse => Reflect.has(value, 'warnings');

const isSuccessResponse = (
    value: EbayBrowseItemsSuccessResponse | Record<string, never>,
): value is EbayBrowseItemsSuccessResponse =>
    Reflect.has(value, 'itemSummaries');

export class EbayClient {
    private readonly auth: EbayAuthToken;
    private readonly baseUrl: string;
    private readonly ebayCampaignId: string;
    private readonly ebayEnv: 'PRODUCTION' | 'SANDBOX';

    private apiAccessToken: { expiration: number; value: string } | null = null;

    constructor() {
        const ebayEnv = (this.ebayEnv = loadEnv<'PRODUCTION' | 'SANDBOX'>(
            'EBAY_ENV',
        ));

        this.ebayCampaignId = loadEnv('EBAY_CAMPAIGN_ID');

        const clientSecret = loadEnv(`EBAY_${ebayEnv}_CLIENT_SECRET`);
        const clientId = loadEnv(`EBAY_${ebayEnv}_CLIENT_ID`);
        const redirectUri = loadEnv(`EBAY_${ebayEnv}_REDIRECT_URI`);

        this.auth = new EbayAuthToken({
            clientId,
            clientSecret,
            env: ebayEnv,
            redirectUri,
        });

        this.baseUrl =
            ebayEnv === 'PRODUCTION'
                ? EBAY_API_BASE_URL_PRODUCTION
                : EBAY_API_BASE_URL_SANDBOX;
    }

    async getToken() {
        if (
            this.apiAccessToken &&
            this.apiAccessToken.expiration < Date.now()
        ) {
            return this.apiAccessToken.value;
        }

        const encodedToken = await this.auth.getApplicationToken(this.ebayEnv);
        const { access_token, expires_in } = JSON.parse(encodedToken) as {
            access_token: string;
            expires_in: number;
            token_type: string;
        };

        this.apiAccessToken = {
            expiration: Date.now() + expires_in * 1000,
            value: access_token,
        };

        return access_token;
    }

    async search(
        context: InvocationContext,
        {
            keywords,
            minPrice,
            maxPrice,
            allowRefurbished,
        }: FindProductsParameters,
    ) {
        const filters = [
            'deliveryCountry:US',
            'buyingOptions:{FIXED_PRICE}',
            // see: https://developer.ebay.com/devzone/finding/callref/Enums/conditionIdList.html
            `conditionIds:{1000|1500${allowRefurbished ? '|2000|2010|2020|2030|2500' : ''}}`,
        ];

        if (minPrice ?? maxPrice) {
            filters.push(
                'priceCurrency:USD',
                minPrice === undefined
                    ? `price:[..${maxPrice}]`
                    : maxPrice === undefined
                        ? `price:[${minPrice}]`
                        : `price:[${minPrice}..${maxPrice}]`,
            );
        }

        const queryParams = {
            auto_correct: 'KEYWORD',
            fieldgroups: 'EXTENDED,MATCHING_ITEMS',
            filter: filters.join(','),
            limit: '25',
            // the keyword combinations have an OR relation
            // see: https://developer.ebay.com/api-docs/buy/browse/resources/item_summary/methods/search
            q: `(${keywords.join(', ')})`,
        };

        const response = await fetcher<
            | EbayBrowseItemsSuccessResponse
            | EbayBrowseItemsErrorResponse
            | Record<string, never>
        >({
            headers: {
                Authorization: `Bearer ${await this.getToken()}`,
                [EBAY_AFFILIATE_HEADER]: `affiliateCampaignId=${this.ebayCampaignId}`,
                [EBAY_MARKETPLACE_HEADER]: 'EBAY_US',
            },
            method: HttpMethod.Get,
            queryParams,
            url: this.baseUrl + EBAY_BROWSE_API_ITEMS_SUMMARY_ENDPOINT,
        });

        if (isErrResponse(response)) {
            context.warn('ebay warnings', response.warnings);
            throw new ConfigurationError(
                'ebay API returned warnings',
                response.warnings,
            );
        }

        if (isSuccessResponse(response)) {
            return parseEbayResponse(response);
        }

        return null;
    }
}