How to fix error 'WooCommerce.get(...).then is not a function'? - javascript

I'm trying to start work with WooCommerce API - Node.js Client, which looks very straightforward.
But when I copy a simple example from WooCommerce official website, I get the following error:
TypeError: WooCommerce.get(...).then is not a function
Here is the code:
var WooCommerceAPI = require('woocommerce-api');
var WooCommerce = new WooCommerceAPI({
url: 'https://somewebsite.com/',
consumerKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
consumerSecret: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
wpAPI: true,
version: 'wc/v1'
});
WooCommerce.get("products/1359")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error.response.data);
});
https://woocommerce.github.io,
NPM package

Have found this at the bottom of the NPM package page:
Every method can be used in a promified way just adding Async to the method name. Like in:
WooCommerce.getAsync('products').then(function(result) {
return JSON.parse(result.toJSON().body);
});
Which actually makes the code works now.
I still want to understand what I was doing wrong, I don't think that the official API documents website of WooCommerce is showing all code examples as wrong.
I guess it got to do something with WooCommerce.get not returning a promise, but again that is the way it's in the documents.

Apparently woocommerce.github.io are referring to #woocommerce/woocommerce-rest-api NPM package where docs.woocommerce.com official website refer to WooCommerce API - Node.js Client NPM package.
Kinda confusing...but that solves the mystery.

I was facing a similar problem but with post method. Solved adding a function callback with response argument.
WooCommerce.post("orders", data,function(req,res){
console.log(res.statusMessage);
});

Related

How can I test that the user can link OAuth providers using Cypress?

I'm working on a project in which a user can log in using whether a phone number, using Google, or using Github. I use Firebase for authentication. I'm currently adding integration tests using Cypress. My problem is I can't properly test that the user can link or unlink a provider. To link a provider I use linkWithRedirect() firebase method.
At first, I tried to just simulate a button click. But this didn't work because Cypress doesn't allow visiting multiple domains in one test.
My next attempt was to use linkWithCredential() method. I get cookies and the provider's auth URL from the developer tools to get authorization code and use this code to get access token.
My Cypress command to get Google token:
Cypress.Commands.add(
'getGoogleToken',
() => {
cy.request({
url: Cypress.env("GOOGLE_AUTH_URL"),
headers: {
cookie: Cypress.env("GOOGLE_AUTH_COOKIE")
},
followRedirect: false
})
.its("redirectedToUrl")
.then(redirectedToUrl => {
const url = new URL(redirectedToUrl);
const code = url.searchParams.get("code");
cy.request({
url: "https://www.googleapis.com/oauth2/v4/token",
method: "POST",
form: true,
body: {
code,
redirect_uri: Cypress.env("GOOGLE_REDIRECT_URI"),
client_id: Cypress.env("GOOGLE_CLIENT_ID"),
client_secret: Cypress.env("GOOGLE_CLIENT_SECRET"),
grant_type: "authorization_code"
}
})
.its("body")
.then(body => body.access_token);
});
});
Using this token I call my own linkWithGoogleWithToken method which calls linkWithCredential method:
Cypress.Commands.add(
'linkWithGoogle',
() => {
cy.getGoogleToken()
.then(token => {
cy.get("#auth")
.invoke("linkWithGoogleWithToken", token);
});
});
In my tests, I call several functions to link one provider, then link another provider, then unlink provider, and so on. Sometimes this command works as expected, but sometimes it remains in the pending state forever. I can't find why. Searching doesn't help, it seems like no one has encountered this problem.
So, I am looking for ways to link OAuth provider programmatically, not using UI. I'm considering Firebase Admin SDK, but I can't find the way to link providers in its documentation. I would appreciate any help from anyone who was encountering this issue.
I found out why I was having this problem. The point is that after visiting the page, I add an alias to refer to my firebase functions:
Cypress.Commands.add(
'init',
() => {
cy.visit("/");
cy.window()
.its("firebase")
.its("auth").as("auth");
cy.nullifyUsername();
});
The first time when I called the invoke method, everything worked fine. Then I reloaded the page because I need to update the page with this information.
cy.linkGoogle();
cy.reload();
cy.get("#googleButton")
.contains(/^unlink$/i);
And after that, the next time I tried to link another provider the invoke method remained in the pending state. That happened because after reloading the page, my alias was referred to a function that was no longer exists. My solution is to add alias after reloading the page. So, I created custom command for this:
Cypress.Commands.add(
'refresh',
() => {
cy.reload();
cy.window()
.its("firebase")
.its("auth").as("auth");
});

Use git credential manager to fetch azure devops api instead of personal access token

I am trying to fetch git azure devops api to get information about repositories and branches in js.
In order to achieve that, I made a little application with the following code :
$(document).ready(function() {
var personalToken = btoa(':'+'<personnalAccessToken>');
fetch('https://dev.azure.com/<company>/<project>/_apis/git/repositories?api-version=5.1', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
'Authorization': 'Basic '+ personalToken
}
}).then(function(response) {
return response.json();
}).then(function(repositories) {
console.log("There are "+repositories.count+" repositories");
}).catch(function(error) {
console.log('Fetch error: ' + error.message);
});
This code is working great but as you can see there is my personnalAccessToken writen directly inside the code... which is really bad...
When I am using git in command line, I don't have to specify any credential information because I use git credential manager for windows. Which means my personnalAccessToken is already stored, cached and automatically used everytime I use a git command, like clone, etc.
So, I would like my js code to use the same thing, I would like it to use my stored credentials automatically to fetch the api without being required to set my personnalAccessToken in code.
I have already searched for hours but can't find out if it is possible.
I have already searched for hours but can't find out if it is
possible.
Sorry but as I know it's impossible. The way you're calling the Rest API is similar to use Invoke-RestMethod to call rest api in Powershell.
In both these two scenarios, the process will try to fetch PAT for authentication in current session/context and it won't even try to search the cache in Git Credential Manager.
You should distinguish the difference between accessing Azure Devops service via Rest API and by Code:
Rest API:
POST https://dev.azure.com/{organization}/{project}/{team}/_apis/wit/wiql?api-version=5.1
Request Body:
{
"query": "Select [System.Id], [System.Title], [System.State] From WorkItems Where [System.WorkItemType] = 'Task' AND [State] <> 'Closed' AND [State] <> 'Removed' order by [Microsoft.VSTS.Common.Priority] asc, [System.CreatedDate] desc"
}
Corresponding Code in C#:
VssConnection connection = new VssConnection(new Uri(azureDevOpsOrganizationUrl), new VssClientCredentials());
//create http client and query for resutls
WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>();
Wiql query = new Wiql() { Query = "SELECT [Id], [Title], [State] FROM workitems WHERE [Work Item Type] = 'Bug' AND [Assigned To] = #Me" };
WorkItemQueryResult queryResults = witClient.QueryByWiqlAsync(query).Result;
Maybe you can consider using a limited PAT, limit its scope to Code only:
I know there exists other Authentication mechanism
:
For Interactive JavaScript project: ADALJS and Microsoft-supported Client Libraries.
You can give it a try but I'm not sure if it works for you since you're not using real Code way to access the Azure Devops Service... Hope it makes some help :)
If you have the script set up in an Azure Runbook you can set it as an encrypted variable there and have it pull it from there before running rather than having it directly written into the code.
$encryptedPatVarName = "ADO_PAT"
$adoPat = Get-AutomationVariable -Name $encryptedPatVarName
$adoPatToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($adoPat)"))
$adoHeader = #{authorization = "Basic $adoPatToken"}
The above is the Powershell version of it. I have seen some people do it with other

Add Mailchimp susbscriber through Firebase Function

Scenario :
I'm trying to create a Firebase Function to add a subscriber to a Mailchimp list using the Mailchimp API but after three days of trying different methods I've had little luck.
Currently my function resembles:
exports.addSubscriber = functions.https.onRequest((req, res) => {
const Mailchimp = require('mailchimp-api-v3')
const mailchimp = new Mailchimp('MY_API_KEY');
mailchimp.post('/lists/'MY_LIST_ID'/members', {
"email_address": 'test#gmail.com',
"status": 'pending'
}).then(function(results) {
console.log('added new user to mailchimp list');
})
.catch(function(err) {
console.log(err);
})
return null
});
When I try to trigger the function it results in a 'crash' with Error: Cannot find module 'mailchimp-api-v3' in the logs.
I've already ran npm install mailchimp-api-v3 in my local Firebase
directory so the module should be available.
Where am I going wrong?
Is there a simpler way to use the Mailchimp API with Javascript?
Try to run
npm install mailchimp-api-v3 --save
It seams the above package is missing.

How to set up Stripe API for Parse Cloud Code

How do we set up Stripe API for Parse Cloud Code. I've managed to get the code working, but I'd like to edit it. The function below is "stripe.customers.create", it only works when I remove the source line. How can I request the token? I am also trying to connect the Stripe customer to the parse user.t
Parse.Cloud.define("customer", function(request, response){
stripe.customers.create({
description: request.params.description
//source: request.params.token
}, function(err, customer) {
if(err){
console.log(err);
response.error(err);
}
else{
console.log(customer);
response.success(customer);
}
});
});
I already answered this question before. You can find my here
The idea is that in parse-server you can install any npm module that you want so in my answer i explain how you can first install the stripe npm module and then call it from your cloud code function.

Meteor Braintree -- Create Client Token via Meteor Method

I'm trying to get Braintree Payments working in a Meteor app. I'm stuck at trying to return the result of generating a token (server side, via a Meteor Method) to be used client side.
I've tried this:
/server/braintree.js
Meteor.methods({
createClientToken: function() {
var token = gateway.clientToken.generate({
customerId: this.userId
}, function(err, response) {
clientToken = response.clientToken
return clientToken
}
)
console.log(token)
return token
}
})
which returns true.
I've also tried this:
Meteor.methods({
createClientToken: function() {
var clientToken
gateway.clientToken.generate({
customerId: this.userId
}, function(err, response) {
clientToken = response.clientToken
}
)
console.log(clientToken)
return clientToken
}
})
Which returns undefined.
The function(err, response) is being called asynchronously, yes? If so, that would be the explanation of the problem. Seems that trying to return a value from an asynchronous function is a bit of a pain point in Javascript. I've read a number of SO answers on it (like this one, this one and this one) but none have seemed to lead me in the right direction.
Also, I believe I may need to be using Meteor's wrapAsync method, correct? I've tried this (and found this and this relevant SO questions on it), but still can't seem to get things right.
Grateful for any feedback.
Update:
For a working approach to integrating Braintree with Meteor, check out the example repo (many thanks #Nick Tomlin for this)
Disclaimer: I work for Braintree :)
I'm not familiar with Meteor, but as #mrak noted clientToken.generate is asynchronous and you will definitely handle that appropriately in your method.
In your current code, clientToken is undefined because console.log(clientToken) executes immediately, before you receive a clientToken from the callback for clientToken.generate. Asynchronous programming can take a while to wrap your head around if you are used to coding in a synchronous matter, but there are many resources out there to help you (here is one).
It appears that Meteor.wrapAsync will indeed provide what you need, here is an untested example implementation.
Meteor.methods({
createClientToken: function() {
var createToken = Meteor.wrapAsync(gateway.clientToken.generate, gateway.clientToken);
var response = createToken({});
return response.clientToken;
}
});
Update
I've created a very basic Braintree + Meteor application that may be of some use to you (if it is not, please file an issue on the GH repo to help improve it!)

Categories

Resources