Magento Soap cart.info isn't working for all carts - node.js

I am having a node application and I need a few informations about a shopping cart from a magento customer. So I wrote myself a little test script to test the results of the soap api (I am using magento to help me communication with the soap interface).
var MagentoAPI = require('magento');
var magento = new MagentoAPI({
host: '192.168.73.45',
port: 80,
path: '/magento/api/xmlrpc/',
login: 'dev',
pass: '123456'
});
magento.login(function(err, sessId) {
if (err) {
console.log(err);
return;
}
magento.checkoutCart.info({ quoteId: 696 }, magentoCallback);
});
function magentoCallback(err,response) {
if (err) {
return console.log(err);
}
console.log("Result: ");
console.log(response)
}
This script works fine. If I use some old quote ids (which are in the database from the sample data) I get a good result, but if I use an shopping cart from an user I created, then I get the following error:
{
"original": {
"message": "Unknown XML-RPC tag 'BR'",
"name": "Error"
},
"name": "Magento Error",
"message": "An error occurred while calling cart.info"
}

Related

NodeJS cannot import custom module although it exists

Note: What you see below is the updated description of my problem, because I have been going down a rabbit hole and finding the root cause of a problem.
So, I found what's causing it (read 'OLD DESCRIPTION' below to know the context), but I have zero idea why is it being caused. So, the thing is, apparently Node cannot find the utils.getHash function (I have a separate file called utils.js which exports the getHash function), so it is never called, and execution never moves forward.
utils.js
...
const getHash = (password) => {
return crypto.createHash('sha3-512').update(password).digest('hex')
}
...
module.exports = {
getHash: getHash
}
Someone help please :(
OLD DESCRIPTION
There's a weird problem I am facing. I wrote a backend API server in ExpressJS, and one of the task it performs is user authentication. I am using MongoDB as the database, and Mongoose to connect and perform operations on it.
The problem I am facing is that the checkUserCreds function does not proceed after a point (commented in code), and Express just returns a blank JSON response.
And I say it it's weird, because I tested with the SAME code just 2 days back, it worked correctly like it should.
user.js
userSchema.statics.checkUserCreds = function (email, password) {
return new Promise((resolve, reject) => {
// Execution goes upto '$and' line, then it goes nowhere; no exceptions are raised
User.findOne({
$and: [{ email: email }, { password: utils.getHash(password) }]
}, (err, userDoc) => {
if (err) {
reject({ status: "ERROR", message: err })
} else if (userDoc) { // If valid credential
console.log(`User with email '${email}' logged in`)
resolve({ status: "OK", message: "Login successful!" })
} else { // If invalid credential
reject({ status: "ERROR", message: "Invalid credential!" })
}
})
})
}
api.js
// Route - Login (POST: email, password)
router.post("/login", (req, res) => {
// If user is already logged in, reject further login
if (req.session.email) {
res.json({ status: "ERROR", message: "Already logged in!" }).status(403).end()
} else {
// Get data from body
var form = formidable()
form.parse(req, (err, fields, files) => {
if (err) {
res.json({ status: "ERROR", message: err }).status(500).end()
} else {
// Check if credentials are valid
User.checkUserCreds(fields.email, fields.password).then((result) => {
// This portion of code isn't reached either
req.session.email = fields.email
res.json(result).status(200).end()
}).catch((err) => {
res.json(err).status(401).end()
})
}
})
}
})
Can anyone tell me why this is happening?

Azure BotBuilder - How to get the user information of the OAuth Connection Settings

I've created a Azure Web App Bot and added a OAuth Connection Setting which takes the user to Salesforce. Everything works well, I'm able to authenticate the user through my bot and also, I can get the access token from Salesforce.
Problem
Can someone help me to get the user information from Salesforce? Because, I am able to get the access token alone and not sure, how to get the user id from Salesforce.
I've written the below code,
var salesforce = {};
salesforce.signin = (connector, session, callback) => {
builder.OAuthCard.create(connector,
session,
connectionName,
"Sign in to your Salesforce account",
"Sign in",
(createSignInErr, createSignInRes) => {
if (createSignInErr) {
callback({
status: 'failure',
data: createSignInErr.message
});
return;
}
callback({
status: 'success',
data: createSignInRes
});
});
};
salesforce.getUserToken = (connector, session, callback) => {
connector.getUserToken(session.message.address,
connectionName,
undefined,
(userTokenErr, userTokenResponse) => {
if (userTokenErr) {
callback({
status: 'failure',
data: userTokenErr.message
});
return;
}
callback({
status: 'success',
data: userTokenResponse
});
});
};
salesforce.accessToken = (connector, session, callback) => {
salesforce.getUserToken(connector, session, (userTokenResponse) => {
if (userTokenResponse.status == 'failure') {
// If the user token is failed, then trigger the sign in card to the user.
salesforce.signin(connector, session, (signinResponse) => {
// If the sign in is failed, then let the user know about it.
if (signinResponse.status == 'failure') {
session.send('Something went wrong, ', signinResponse.message);
return;
}
// If the sign in is success then get the user token and send it to the user.
salesforce.getUserToken(connector, session, (newUserTokenResponse) => {
if (newUserTokenResponse.status == 'failure') {
session.send('Something went wrong, ', newUserTokenResponse.message);
return;
}
callback(newUserTokenResponse);
return;
});
});
}
callback(userTokenResponse);
});
};
I can get the userTokenResponse here. But I need Salesforce user id so that I can start interacting with Salesforce behalf of the user.
If you have only OAuth access token you may query details about the user by invoking http GET against:
https://login.salesforce.com/services/oauth2/userinfo for PROD or
https://test.salesforce.com/services/oauth2/userinfo for sandbox
Add only Authorization: Bearer Y0UR0AUTHTOKEN to the header of the http GET request.
Based on my recent test the result returned from the server looks like:
{
"sub": "https://test.salesforce.com/id/[organizationid]/[userId]",
"user_id": "000",
"organization_id": "000",
"preferred_username": "me#mycompany.com",
"nickname": "myNick",
"name": "name lastname",
"urls": {
...
},
"active": true,
"user_type": "STANDARD",
...
}
You don't need a userId to get the user information where an accessToken is enough. I've installed jsforce and used the below code to get the identity information.
Solved by doing,
const jsforce = require('jsforce');
var connection = new jsforce.Connection({
instanceUrl: instanceUrl,
sessionId: accessToken
});
connection.identity((error, response) => {
if(error) {
callback({
status: 'failure',
message: error.message
});
return;
}
callback({
staus: 'success',
data: response
});
});

Route to the url when user clicks on notifications in pwa, angular 6 and web-push in Node.JS

I am working on pushing the notifications in PWA using SwPush in Angular6. For this I am using #angular/service-worker. I am able to send the notifications from node server. But when I click on the received notification, it is not able to route the desired url. I am using web-push module in node.js, and this is the payload:
"payload": {
"title": "Sample Notification",
"actions": [
{
"action": "opentweet",
"url":"https://pwa-sw-push-notifications.firebaseapp.com",
"title": "Open tweet"
}
],
"body": "A sample data to check the notification availability!",
"dir": "auto",
"icon": "https://pwa-sw-push-notifications.firebaseapp.com/assets/icons/icon-72x72.png",
"badge": "https://pwa-sw-push-notifications.firebaseapp.com/assets/icons/icon-72x72.png",
"lang": "en",
"url": "https://pwa-sw-push-notifications.firebaseapp.com",
"renotify": true,
"requireInteraction": true,
"tag": 926796012340920300,
"vibrate": [
100,
50,
100
],
"data": {
"url": "https://pwa-sw-push-notifications.firebaseapp.com",
"favorite_count": 0,
"retweet_count": 0
}
}
I am using
var webPush=require('web-push');
//sub is userSubscriptionObject to send the notifications to subscribed user browser.
webPush.sendNotification(sub, JSON.stringify(payload))))
In angular,
export class IndexComponent implements OnInit {
users: any = [];
constructor(
private http: HttpClient,
private router: Router,
private swPush: SwPush) {
console.log('this is index');
}
ngOnInit() {
this.getCoins();
}
subscribeNotifications(){
this.swPush.requestSubscription({
serverPublicKey: "BMW3STH0ODuNdhFVAZIy8FUDEwt2f8LLpWBiBnz8WE0_558rZc4aLbZUD9y-HxMlfCtyE5OD0mk3xa2oFJZu5n0"
}).then(sub => {
console.log("Notification Subscription: ", sub);
this
.http
.post('https://e1a2e469.ngrok.io/sub/subscribeNotifications', sub);.subscribe(
() => {
console.log('Sent push subscription object to server.');
},
err => console.log('Could not send subscription object to server, reason: ', err)
);
})
.catch(err => console.error("Could not subscribe to notifications", err));
}
unsubscribeNotifications(){
this.swPush.subscription.pipe(take(1)).subscribe(subscriptionValue=>{
console.log('this is un subscription', subscriptionValue);
this
.http
.post('https://e1a2e469.ngrok.io/sub/unsubscribeNotifications', subscriptionValue);
.subscribe(
res => {
console.log('[App] Delete subscriber request answer', res)
// Unsubscribe current client (browser)
subscriptionValue.unsubscribe()
.then(success => {
console.log('[App] Unsubscription successful', success)
})
.catch(err => {
console.log('[App] Unsubscription failed', err)
})
},
err => {
console.log('[App] Delete subscription request failed', err)
}
);
});
}
sendNotifications(){
console.log('subscribeNotifications')
this
.http
.post('https://e1a2e469.ngrok.io/sub/sendNotifications', null).subscribe(res=>{
console.log('subscribed successfully');
});
}
}
My intention is, when user clicks on the notification it is supposed to route to
https://pwa-sw-push-notifications.firebaseapp.com.
I have tried giving this URL in different parameters in the above object like actions[0].action.url URL data.url and nothing worked. So I am confused where to give the URL to make it possible. Could anyone help me out?
Thank you.
There's nothing wrong with your payload, as far as I can see. The payload is just a data which is delivered to your browser, on your browser side you need to implement notificationClick handler in order to process the payload data i.e., navigating to the desired URL. A simple notifictionClick handler can be implemented in service worker as follow:
this.scope.addEventListener('notificationclick', (event) => {
console.log('[Service Worker] Notification click Received. event', event);
event.notification.close();
if (clients.openWindow && event.notification.data.url) {
event.waitUntil(clients.openWindow(event.notification.data.url));
}
});
For reference check out the links below:
https://github.com/angular/angular/issues/20956#issuecomment-374133852
https://medium.com/google-developer-experts/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-2-practice-3221471269a1

Issue with Hapi-jwt: Hapi-jwt authentication not running the handler function

I am not sure why, but I am having an issue implementing JWT authentication on my API. I'm using the https://www.npmjs.com/package/hapi-jwt package.
Creating the token works without issue, I'm getting a reply back on my /api/v1/login (auth) route, giving me a status:200 and the token:hash.
However, using my basic validation function on any route causes the route's handler to no longer run, and instead the validation function replies with the {"credentials": ... } object.
I'm also using Good and good-console, but I don't believe they are causing any problems in this.
Here's the server code (in the order it appears in my index.js file):
// SERVER SETUP
var server = new hapi.Server();
server.connection({ port: hapiPortNo });
// JWT SERVER REGISTRATIONS
server.register(require('hapi-jwt'), function(err) {
if(err) throw err;
server.auth.strategy('simple', 'bearer-access-token', {
validateFunc: auth.validateJWT,
secret: jwtCodeString
});
});
function defaultHandler(req, reply) {
reply('success!');
}
server.route({
method: 'GET',
path: '/',
handler: defaultHandler,
config: { auth: 'simple' }
});
server.route({
method: 'POST',
path: '/api/v1/login',
handler: auth.authHandler
});
server.register({
register: good,
options: {
reporters: [{
reporter: require('good-console'),
args: [{ log: '*', response: '*' }]
}]
}
}, function (err) {
if(err) {
throw err;
}
// START SERVER
server.start(function () {
server.log('info', 'Server running at: ' + server.info.uri);
});
});
And these are my auth and validation functions (kept in a seperate file, ./lib/auth.js and imported as a requirement):
//Authentication
function authHandler( request, reply ) {
var data = request.payload;
var tokenData = {
"user": data.user
};
var encoded = jwt.sign( tokenData, _codeString);
reply({ "status": 200, "token": encoded });
}
// Validation
function validateJWT( decoded, request, next ) {
var isValid = false;
if(decoded.user == 'me') {
isValid = true;
}
return next(null, isValid, {token: decoded} );
}
The hapi server runs without issues and replies all my routes' data normally when I drop the config: { auth: 'simple' } but for some reason adding authentication is resulting in every route replying with:
{
"credentials": {
"token": {
"user": "me",
"iat": 1425689201
}
}
}
Any thoughts? I'd be open to switching to another JWT auth package if someone has a recommendation.
The issue is with the hapi-jwt plugin, it hasn't been updated to work with hapi 8. Line 81 should be changed from
return reply(null, { credentials: credentials });
to
return reply.continue({ credentials: session });
You can either create a issue in the repository of hapi-jwt and ask the author to update the module, or you can try to use an other module like hapi-auth-jwt2 which is compatible with hapi 8.

Inserting Google Analytics Content Experiments using the Node.JS Client Library

I'm trying to configure a content experiment using the Node.js Client Library, and have not been able to work out the syntax. Where do I put the body (an Experiment resource) as described here?
https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtExperimentsGuide#insert
This code, for listing existing experiments, works as expected:
var listExperiments = function(){
googleapis
.discover('analytics', 'v3')
.execute(function(err, client) {
var request = client
.analytics.management.experiments.list({
accountId : accountId,
webPropertyId : webPropertyId,
profileId : profileId
})
.withApiKey(browserAPIKey)
.withAuthClient(oauth2Client)
request.execute(function(err,result){
if (err){
console.log(err);
res.send(402);
} else {
console.log(result);
res.send(200);
}
});
});
}
However, when I try to insert a new experiment thusly, I receive a "Field resource is required" error.
var body = {
"name": "myExperimentName",
"status": "READY_TO_RUN",
"objectiveMetric":"ga:bounces",
"variations": [
{ "name": "text1", "url":"http://www.asite.net", "status":"ACTIVE" },
{ "name": "text2", "url":"http://www.asite.net", "status":"ACTIVE" }
]
};
var insertExperiment = function(){
googleapis
.discover('analytics', 'v3')
.execute(function(err, client) {
var request = client
.analytics.management.experiments.insert({
accountId : accountId,
webPropertyId : webPropertyId,
profileId : profileId,
resource : body
})
.withApiKey(browserAPIKey)
.withAuthClient(oauth2Client)
request.execute(function(err,result){
if (err){
console.log(err);
res.send(402);
} else {
console.log(result);
res.send(200);
}
});
});
}
I've tried a few configurations. Management API writes are in limited beta, but I have beta access, so that's not the problem. I've tried inserting the new experiment information directly into the insert() object, calling the experiment info object "body : body " instead of "resource : body", JSON.stringifying the body, and a few other configurations. No luck.
Any help would be great!
I'm aware of this answer, but it uses the Javascript Client Library and makes RESTful requests, whereas I'd like to use the Node Library.
EDIT: Thanks to Burcu Dogan at Google. Here's the correct syntax:
.analytics.management.experiments.insert({
accountId : accountId,
webPropertyId : webPropertyId,
profileId : profileId
}, body)

Resources