Call Magento SOAP inside Meteor method invoked by the client - javascript

I'm using zardak:soap package in Meteor to connect with Magento SOAP v2 API. I've created a file inside the 'server' folder where I create a soap connection on Meteor.startup. Then I run a ticker that invokes random soap method every 30sec just to keep the connection up.
let soapConnection;
Meteor.startup(() => {
soapConnection = createAPIConnection('http://magento.site.com/api/v2_soap/?wsdl=1', {username: 'user', apiKey: 'password'});
});
function createAPIConnection(url, credentials) {
try {
let client = Soap.createClient(url);
let loginResult = client.login(credentials);
let sessionId = loginResult.loginReturn.$value;
return {
conn: client,
sessionId: sessionId
};
} catch (e) {
if (e.error === 'soap-creation') {
console.log('SOAP Client creation failed');
}
return null;
}
}
function tick() {
try {
soapConnection.conn.catalogCategoryInfo({
sessionId: soapConnection.sessionId,
categoryId: 1
}, (err, result) => { });
} catch (e) { }
}
Then I have a Meteor method that is called from the client. When it is called, the soap method call fails and I'm getting a 'soap error' message in console.
Meteor.methods({
'createMagentoCustomer'(customer) {
try {
soapConnection.conn.customerCustomerCreate({
sessionId: soapConnection.sessionId,
customerData: customer
}, (err, res) => {
if (err)
console.log('soap error');
else
console.log(res);
});
} catch (e) {
console.log('SOAP Method <customerCustomerCreate> call failed');
}
},
});
So, the ticker works well with no problems, but when I try to call soap via Meteor method, it fails. Notice that the soapConnection method is not null and I do receive error in the soap method callback.
Any suggestions?
Meteor version 1.3.4.1

Related

Why socket.io listener in android side not called?

I write socket middleware for user Authentication but I don't know what's my problem!
in android side "unauthorized" event not called.
Server-side :
async function (socket, next) {
if (socket.handshake.query && socket.handshake.query.token) {
jwt.verify(socket.handshake.query.token, process.env.SECRET_JWT_KEY, function (err, decoded) {
if (err) {
socket.emit( "unauthorized", "unauthorized user") <==send to sender you'r authentication is failed
console.log("Query: ", "unauthorized"); <==This line is lunched
return next(new Error('Authentication error'));
}
socket.decoded = decoded;
next();
});
} else {
next(new Error('Authentication error'));
}
Client-side :
val socket = IO.socket("http://192.168.1.6:3000", IO.Options().apply {
path = "/sockets/chat"
query = "token=wrongtoken"
})
socket.on("unauthorized", object : Emitter.Listener { <== THIS NOT LUNCED!!
override fun call(vararg args: Any?) {
println("user authentication failed" )
}
}
I think you need to connect to the socket first by calling this line inside apply block
this.connect()
Finally found the solution no need to emit from middleware when throwing an error you can get predefined events in an android client like this:
socket.on(Socket.EVENT_ERROR) { args -> println(args.contentToString()) }

How can I send messages to my queue and a post request?

I have a function that posts data to the database. It works fine but I would also like to use the same function to send a message to trigger another function.
I have tried to simultaneouslysend the message and make the post request but at this moment only the post request works
Here is what my code looks like
const params = {
"TableName": "sites",
"Item": {
userId: event.requestContext.identity.cognitoIdentityId,
siteId: siteIdFinal,
...data,
createdAt: Date.now()
}
};
const messageParams = {
MessageBody: 'Waddup fam',
QueueUrl: ' https://sqs.eu-west-1.amazonaws.com/106845550704/MyQueue'
};
try {
await dynamoDbLib.call("put", params);
sqs.sendMessage(messageParams, (err, data) => {
if (err) {
console.log("Error: "+err);
} else {
console.log("Success: "+data.MessageId);
}
});
return success(params.Item);
} catch (e) {
console.log(e);
return failure({ status: false });
}
I am not getting any error I am just getting returned back the data that has been posted. I thought i should receive the message Id of the message I sent but I am not getting that. When ever I look at the cloudwatch logs, the message isnt sent
Your async function returns params.Item before sendMessage executes a callback.
Use a promise to make sure that both methods finish properly
await sqs.sendMessage(messageParams).promise()
.then(function(data) {
console.log("Success: "+data.MessageId);
}).catch(function(err) {
console.log("Error: "+err);
});
More on aws-sdk and promises:
https://aws.amazon.com/blogs/developer/support-for-promises-in-the-sdk/

Cannot insert to collection from NPM using Meteor 1.3

I am using the imap-simple NPM package to check emails, and I am having trouble getting the insert to work properly.
I have already read through this page: https://guide.meteor.com/using-npm-packages.html#async-callbacks - and I have tried the suggestions but none of them are working!
I've also simplified the code a bit just to try to get it working, but still have no luck.
The problem should be very easy to reproduce - meteor npm install imap-simple, throw the above code on the server, add some email credentials, and call the method.
Here is my code:
var imaps = require('imap-simple');
var config = {
imap: {
user: '<removed>',
password: '<removed>',
host: 'imap.gmail.com',
port: 993,
tls: true,
authTimeout: 3000
}
};
Meteor.methods({
api_connectEmail: function () {
console.log('Received call to connect email');
imaps.connect(config).then(function (connection) {
return connection.openBox('INBOX').then(function () {
var searchCriteria = [
'UNSEEN'
];
var fetchOptions = {
bodies: ['HEADER', 'TEXT'],
markSeen: true
};
return connection.search(searchCriteria, fetchOptions).then(function (results) {
results.map(function (res) {
var subject = res.parts.filter(function (part) {return part.which === 'HEADER';})[0].body.subject[0];
console.log("Subject: " + subject);
// insert
var attributes = {
subject: subject
};
console.log("Attempting to insert to collection...");
var newData = TempEmailCollection.insert(attributes);
console.log("New Database Entry ID: " + newData);
});
});
});
})
}
});
The console.log with the subject is working. The insert is not working. No error, no console.log post insert, nothing.
I've tried both strategies recommended in the guide, neither work.
The problem is that you are calling a Meteor function inside asynchronously called Promise handlers.
However, all Meteor functions that are called on the server have to run in a fiber.
Meteor actually throws an error in this case but you are ignoring it because you haven't specified catch functions for the Promises.
Consider the following simplified example (it just connects to the server and tries to insert a new document):
import { Meteor } from 'meteor/meteor';
import imaps from 'imap-simple';
const Storage = new Mongo.Collection('storage');
const config = {
imap: {
…
}
};
Meteor.methods({
connect() {
console.log('Method called');
imaps.connect(config).then(function(connection) {
console.log('Connected');
Storage.insert({
value: 'success'
});
console.log('Document inserted');
})
.catch(function(err) {
console.error(err);
});
}
});
The following message will arrive in the catch function:
[Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.]
You could do something like this to wrap the insert call:
Meteor.methods({
connect() {
console.log('Method called');
const insert = Meteor.bindEnvironment(function() {
Storage.insert({
value: 'success'
});
});
imaps.connect(config).then(function(connection) {
console.log('Connected');
insert();
console.log('Document inserted');
})
.catch(function(err) {
console.error(err);
});
}
});
Then the document will be inserted as expected.

Communicate with C# host from edge.js

I'm trying to put together a quick node.js/edge.js/C# bridge for a demo.
I have to use the ".Net calling Node.js" style, as the existing C# code uses a number of config values, which I can't add to node.exe.config as I will need to run several versions concurrently.
So I have this code:
private static async Task Start() {
Func<object, Task<object>> edge = EdgeJs.Edge.Func(#"
var login = require('login.js');
var edge = require('edge')
login({ email: 'user#example.com', password: 'shh' }, function callback(err, api) {
if (err) return console.error(err);
// This will keep listening until terminated
api.listen(function callback(err, message) {
if (err) return console.error(err);
// At this point I need to send the message back to this class so it can be processed..
console.log(message); // send the message to C#
// ... and then return the response via the api
api.send('response goes here');
});
});
return function (data, callback) {
callback(null, er...);
}
");
}
So, the code is waiting for messages in an event loop and responding. This all works with hardcoded values. But I need to submit the message back to the C# for processing, and I cannot work out how to communicate back and forth between edge.js and the C# app.
It must surely be via the callback, but I can't seem to start figure out how to structure it, and time is getting short. And I'm by no means a JavaScript expert.
How can I communicate between the edge code and the C# code from within the event loop using the callback?
You're right, it's via the callback. Since you're using async code, you have to wrap all your code inside the returned (edge) function, like this:
private static async Task Start() {
Func<object, Task<object>> edge = EdgeJs.Edge.Func(#"
// edge_callback is used to return values to the C# code
return function(data, edge_callback) {
var login = require('login.js');
var edge = require('edge')
login({
email: 'user#example.com',
password: 'shh'
}, function callback(err, api) {
if (err) return console.error(err);
// possible enhancement here by letting C# know there is an error
// edge_callback(err);
// This will keep listening until terminated
api.listen(function callback(err, message) {
if (err) return console.error(err);
// same thing here: edge_callback(err);
// At this point I need to send the message back to this class so it can be processed..
console.log(message); // send the message to C#
// use the callback, first param is error if there is any, second is the data
edge_callback(null, message);
// ... and then return the response via the api
api.send('response goes here');
});
});
}
");
}
I have ended up with something like this: there's a function defined on the data passed to edge, which edge then calls when a new message is received. That function then waits for the response, and passes it back to edge, which receives the result in (of course) another callback.
private static async Task Start() {
dynamic payload = new ExpandoObject();
payload.msgHook = NewMessage;
payload.login = new {
email,
password
};
var receive = Edge.Func(#"
return function(payload, edge_callback) {
var login = require('index.js');
login({
email: payload.login.email,
password: payload.login.password
}, function callback(err, api) {
if (err) {
edge_callback(err);
}
api.listen(function callback(err, message) {
if (err) { edge_callback(err); }
payload.msgHook(message,
function callback(err, result) {
if (err) {
edge_callback(err);
}
var msg = {
body: result.body,
url: result.url
}
api.sendMessage(msg, result.threadId);
});
});
});
}
");
var _ = await receive(payload) as IDictionary<string, object>;
}
private static Func<object, Task<object>> NewMessage {
get {
Func<object, Task<object>> hook = async m => {
string body, threadId;
if (!ProcessMessage(m as IDictionary<string, object>, out body, out threadId)) {
log.Error("Failed to process message: " + m.ToString());
}
api.SendMessage(body, threadId, phone);
var reply = await waitForReply(threadId);
var result = new {
body = reply
};
// Return the _result_ of the task.
return Task.FromResult<object>(result).Result;
};
return hook;
}
}

Why is my Meteor app logging to server but not client?

I'm building a meteor app that hooks into the twitter api and I've had no luck so far getting it to work. I'm using the twit package to make the call on the server side, and it logs the data to the server console, but when the client console goes to log it there is no data.
The client doesn't throw an error, it runs the console.log in the else statement for the result parameter, but it comes through as undefined. It's as if the result callback runs before the data comes back, but my understanding of the Meteor.call method is that it's supposed to wait until it hears back from the server before it runs.
What am I doing wrong here?
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to testing.";
};
Template.hello.recentFollows = function () {
return Session.get("recentFollows");
};
Template.hello.events({
'click #fetchButton': function () {
console.log("Recent tweets from stream!");
userName = "josiahgoff";
Meteor.call('getBananaTweets', function(err, result) {
if(err) {
console.log("error occurred on receiving data on server. ", err);
} else {
console.log("result: ", result);
Session.set("recentFollows", result);
}
});
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
Twit = new TwitMaker({
consumer_key: '******',
consumer_secret: '******',
access_token: '******',
access_token_secret: '******'
});
});
Meteor.methods({
getBananaTweets: function () {
Twit.get('search/tweets', { q: 'banana since:2011-11-11', count: 1 }, function(err, result) {
if (err) {
console.log("Error", err);
return err;
} else {
console.log(result);
return result;
}
});
}
});
}
You are using return in your server code in a place where it must not be used: in an asynchronous call-back. The Twit.get call returns immediately and the function ends (with no return value). So the client doesn't receive anything. Some time later the Twit.get comes back, but the return in that case goes nowhere.
This is a pretty common question. The solution is to wrap your Twit.get call into a fiber in some shape or form to make it synchronous. See for instance this answer: Iron Router Server Side Routing callback doesn't work

Categories

Resources