I need to integrate vTiger CRM with Quickbooks 2010. So it is PHP. QB server and Linux box running vTiger are sitting in the same office. I try to figure out if there is a way to make PHP talk directly to QB server without using web connector. We need real time data access. Not like real 'real time', but report needs to be generated in like 5-30 seconds. Only reading of data, no writing. Any way to send/receive qbXML directly to QB server?
Thanks in advance.
Michael
This can be done... but be aware that QuickBooks isn't always the most reliable piece of software to integrate with for real-time data access - connections to QuickBooks tend to be both slow and fragile, which is why you usually see a queued model with the Web Connector.
What you could do is write a custom C# component (look at the examples included with the SDK, specifically this one: C:\Program Files (x86)\Intuit\IDN\QBSDK12.0\samples\qbdt\c-sharp\qbXML\CustomerAdd) which opens a connection to QuickBooks, and then does whatever.
"Whatever" might be something like:
Run a query against QuickBooks, and then HTTP POST the data back to vTiger
or
Open a socket and listen for incoming requests, in which case PHP could connect to the socket and feed the component requests which it could relay to QuickBooks, and then return the response
Be aware that generating a report in QuickBooks every 5 seconds is probably going to slow QuickBooks down considerably. Depending on how much data you're talking and what filters, it might not even be possible to get QuickBooks to generate a report that quickly.
Likewise, be aware that certain things cause connections to QuickBooks to fail, so you'll have to handle those gracefully. Specifically:
QuickBooks automatic updates will lock out integrated apps
If you have too many users logged in at once you'll get locked out
If someone else goes into single-user mode you'll get locked out
etc.
Maybe if you can provide more detail about why you need such frequent access to reports, we can provide some additional information.
Your code would look something like this:
while (true)
{
string input = "your fancy qbXML request goes here";
RequestProcessor2 rp = null;
string ticket = null;
string response = null;
try
{
rp = new RequestProcessor2 ();
rp.OpenConnection("", "Your App Name");
ticket = rp.BeginSession("", QBFileMode.qbFileOpenDoNotCare );
response = rp.ProcessRequest(ticket, input);
}
catch( System.Runtime.InteropServices.COMException ex )
{
MessageBox.Show( "COM Error Description = " + ex.Message, "COM error" );
return;
}
finally
{
if( ticket != null )
{
rp.EndSession(ticket);
}
if( rp != null )
{
rp.CloseConnection();
}
};
// Do something with the response here
...
}
Related
I'm trying to listen for subscription changes (new and existing) of my Google Play app on the server. Here's the code I'm using. This uses the google/cloud-pubsub composer package:
$projectId = 'app-name';
$keyFile = file_get_contents(storage_path('app/app-name.json'));
$pubsub = new PubSubClient([
'projectId' => $projectId,
'keyFile' => json_decode($keyFile, true)
]);
$httpPostRequestBody = file_get_contents('php://input');
$requestData = json_decode($httpPostRequestBody, true);
info(json_encode($requestData));
$message = $pubsub->consume($requestData);
info(json_encode($message));
The code above works but the problem is that the data I get doesn't match the one I'm getting in the app side. This is a sample data:
{
"message":{
"data":"eyJ2ZXJ...",
"messageId":"16797998xxxxxxxxx",
"message_id":"1679799xxxxxxxxx",
"publishTime":"2020-12-15T02:09:23.27Z",
"publish_time":"2020-12-15T02:09:23.27Z"
},
"subscription":"projects\/app-name\/subscriptions\/test-subs"
}
If you base64_decode() the data, you'll get something like this:
{
version: "1.0",
packageName: "com.dev.app",
eventTimeMillis: "1607997631636",
subscriptionNotification: {
version: "1.0",
notificationType: 4,
purchaseToken: "kmloa....",
subscriptionId: "app_subs1"
}
}
This is where I'm expecting the purchaseToken to be the same as the one I'm getting from the client side.
Here's the code in the client-side. I'm using Expo in-app purchases to implement subscriptions:
setPurchaseListener(async ({ responseCode, results, errorCode }) => {
if (responseCode === IAPResponseCode.OK) {
const { orderId, purchaseToken, acknowledged } = results[0];
if (!acknowledged) {
await instance.post("/subscribe", {
order_id: orderId,
order_token: purchaseToken,
data: JSON.stringify(results[0]),
});
finishTransactionAsync(results[0], true);
alert(
"You're now subscribed! You can now use the full functionality of the app."
);
}
}
});
I'm expecting the purchaseToken I'm extracting from results[0] to be the same as the one the Google server is returning when it pushes the notification to the endpoint. But it doesn't.
Update
I think my main problem is that I'm assumming all the data I need will be coming from Google Pay, so I'm just relying on the data published by Google when a user subscribes in the app.
This isn't actually the one that publishes the message:
await instance.post("/subscribe")
It just updates the database with the purchase token. I can just use this to subscribe the user but there's no guarantee that the request is legitimate. Someone can just construct the necessary credentials based on an existing user and they can pretty much subscribe without paying anything. Plus this method can't be used to keep the user subscribed. So the data really has to come from Google.
Based on the answer below, I now realized that you're supposed to trigger the publish from your own server? and then you listen for that? So when I call this from the client:
await instance.post("/subscribe", {
purchaseToken
});
I actually need to publish the message containing the purchase token like so:
$pubsub = new PubSubClient([
'projectId' => $projectId,
]);
$topic = $pubsub->topic($topicName);
$message = [
'purchaseToken' => request('purchaseToken')
];
$topic->publish(['data' => $message]);
Is that what you're saying? But the only problem with this approach is how to validate if the purchase token is legitimate, and how to renew the subscription in the server? I have a field that needs to be updated each month so the user stays "subscribed" in the eyes of the server.
Maybe, I'm just overcomplicating things by using pub/sub. If there's actually an API which I could pull out data from regularly (using cron) which allows me to keep the user subscription data updated then that will also be acceptable as an answer.
First of all - I have a really bad experience with php and pubsub because of the php PubSubClient. If your script is only waiting for push and checking the messages then remove the pubsub package and handle it with few lines of code.
Example:
$message = file_get_contents('php://input');
$message = json_decode($message, true);
if (is_array($message)) {
$message = (isset($message['message']) && isset($message['message']['data'])) ? base64_decode($message['message']['data']) : false;
if (is_string($message)) {
$message = json_decode($message, true);
if (is_array($message)) {
$type = (isset($message['type'])) ? $message['type'] : null;
$data = (isset($message['data'])) ? $message['data'] : [];
}
}
}
I'm not sure how everything works on your side but if this part publishes the message:
await instance.post("/subscribe", {
order_id: orderId,
order_token: purchaseToken,
data: JSON.stringify(results[0]),
});
It looks like it's a proxy method to publish your messages. Because payload sent with it is not like a PubSub described schema and in the final message it doesn't look like IAPQueryResponse
If I was in your situation I will check few things to debug the problem:
How I publish/read a message to/from PubSub (topic, subscription and message payload)
I will write the publish mechanism as it is described in Google PubSub publish documentation
I will check my project, topic and subscription
If everything is set-up correctly then I will compare all other message data
If the problem persist then I will try to publish to PubSub minimal amount of data - just purchaseToken at the start to check what breaks the messages
For easier debug:
Create pull subscription
When you publish a message check pull subscription messages with "View messages"
For me the problem is not directly in PubSub but in your implementation of publish/receiving of messages.
UPDATE 21-12-2020:
Flow:
Customer create/renew subscription
Publish to pubsub with authentication
PubSub transfers the message to analysis application via "push" to make your analysis.
If you need information like:
New subscribers count
Renews count
Active subscriptions count
You can create your own analysis application but if you need something more complicated then you have to pick a tool to met your needs.
You can get the messages from pubsub also with "pull" but there are few cases I've met:
Last time I've used pull pubsub returns random amount of messages - if my limit is 50 and I have more than 50 messages in the queue I'm expecting to get 50 messages but sometimes pubsub gives me less messages.
PubSub returned messages in random order - now there is an option to use ordering key but it's something new.
To implement "pull" you have to run crons or something with "push" you receive the message as soon as possible.
With "pull" you have to depend on library/package (or whatever in any language it's called) but on "push" you can handle the message with just few lines of code as my php exapmle.
I'm working on trace logger of sorts that pushes log message requests onto a Queue on a Service Bus, to later be picked off by a worker role which would insert them into the table store. While running on my machine, this works just fine (since I'm the only one using it), but once I put it up on a server to test, it produced the following error:
HTTP_Request2_MessageException: Malformed response: in D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php on line 1013
0 HTTP_Request2_Response->__construct('', true, Object(Net_URL2)) D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php:1013
1 HTTP_Request2_Adapter_Socket->readResponse() D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php:139
2 HTTP_Request2_Adapter_Socket->sendRequest(Object(HTTP_Request2)) D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2.php:939
3 HTTP_Request2->send() D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\Http\HttpClient.php:262
4 WindowsAzure\Common\Internal\Http\HttpClient->send(Array, Object(WindowsAzure\Common\Internal\Http\Url)) D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\RestProxy.php:141
5 WindowsAzure\Common\Internal\RestProxy->sendContext(Object(WindowsAzure\Common\Internal\Http\HttpCallContext)) D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\ServiceRestProxy.php:86
6 WindowsAzure\Common\Internal\ServiceRestProxy->sendContext(Object(WindowsAzure\Common\Internal\Http\HttpCallContext)) D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\ServiceBus\ServiceBusRestProxy.php:139
7 WindowsAzure\ServiceBus\ServiceBusRestProxy->sendMessage('<queuename>/mes…', Object(WindowsAzure\ServiceBus\Models\BrokeredMessage)) D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\ServiceBus\ServiceBusRestProxy.php:155
⋮
I've seen previous posts that describe similar issues; Namely:
Windows Azure PHP Queue REST Proxy Limit (Stack Overflow)
Operations on HTTPS do not work correctly (GitHub)
That imply that this is a known issue regarding the PHP Azure Storage libraries, where there are a limited amount of HTTPS connections allowed. Before requirements were changed, I was accessing the table store directly, and ran into this same issue, and fixed it in the way the first link describes.
The problem is that the Service Bus endpoint in the connection string, unlike Table Store (etc.) connection string endpoints, MUST be 'HTTPS'. Trying to use it with 'HTTP' will return a 400 - Bad Request error.
I was wondering if anyone had any ideas on a potential workaround. Any advice would be greatly appreciated.
Thanks!
EDIT (After Gary Liu's Comment):
Here's the code I use to add items to the queue:
private function logToAzureSB($source, $msg, $severity, $machine)
{
// Gather all relevant information
$msgInfo = array(
"Severity" => $severity,
"Message" => $msg,
"Machine" => $machine,
"Source" => $source
);
// Encode it to a JSON string, and add it to a Brokered message.
$encoded = json_encode($msgInfo);
$message = new BrokeredMessage($encoded);
$message->setContentType("application/json");
// Attempt to push the message onto the Queue
try
{
$this->sbRestProxy->sendQueueMessage($this->azureQueueName, $message);
}
catch(ServiceException $e)
{
throw new \DatabaseException($e->getMessage, $e->getCode, $e->getPrevious);
}
}
Here, $this->sbRestProxy is a Service Bus REST Proxy, set up when the logging class initializes.
On the recieving end of things, here's the code on the Worker role side of this:
public override void Run()
{
// Initiates the message pump and callback is invoked for each message that is received, calling close on the client will stop the pump.
Client.OnMessage((receivedMessage) =>
{
try
{
// Pull the Message from the recieved object.
Stream stream = receivedMessage.GetBody<Stream>();
StreamReader reader = new StreamReader(stream);
string message = reader.ReadToEnd();
LoggingMessage mMsg = JsonConvert.DeserializeObject<LoggingMessage>(message);
// Create an entry with the information given.
LogEntry entry = new LogEntry(mMsg);
// Set the Logger to the appropriate table store, and insert the entry into the table.
Logger.InsertIntoLog(entry, mMsg.Service);
}
catch
{
// Handle any message processing specific exceptions here
}
});
CompletedEvent.WaitOne();
}
Where Logging Message is a simple object that basically contains the same fields as the Message Logged in PHP (Used for JSON Deserialization), LogEntry is a TableEntity which contains these fields as well, and Logger is an instance of a Table Store Logger, set up during the worker role's OnStart method.
This was a known issue with the Windows Azure PHP, which hasn't been looked at in a long time, nor has it been fixed. In the time between when I posted this and now, We ended up writing a separate API web service for logging, and had our PHP Code send JSON strings to it over cURL, which works well enough as a temporary work around. We're moving off of PHP now, so this wont be an issue for much longer anyways.
A very open question which I need some advice on and more importantly pointers in the right direction.
I'm looking at using openstack for my private cloud (currently using VMware) as the main aim is to be able to launch a new VM instance from within our web application so this could be trigger via a php page to deploy new apache worker server for example. The next aim is to develop our code to be able to see when a server load is getting high or needs more worker servers to preform a task to auto launch an instance?
I've been looking at the openstack API to see if this is the best approach? But also looking at juju to see if you can use charms to do this and seeing if the api for juju to is best?
The aim is get this working with VMware or to replace vmware.
My current setup is running openstack on a laptop using nova as the storage so any help with the pointers would be great
I know its a open question
Well there is an SDK page listing many of the OpenStack API client SDKs that exist.
Ref:
https://wiki.openstack.org/wiki/SDKs#PHP
Listed in there are two PHP SDKs for OpenStack currently:
Ref:
https://github.com/rackspace/php-opencloud
https://github.com/zendframework/ZendService_OpenStack
I wouldn't use Juju as an interface. And frankly I am not sure OpenStack is the right tool for what you are doing. But, if you want to play with devstack and get an idea, I think rackspace's php client SDK is probably a good start. Devstack is not a bad way to get that experience either.
example of spinning up a server with php-opencloud:
$server = $compute->server();
try {
$response = $server->create(array(
'name' => 'My lovely server',
'image' => $ubuntu,
'flavor' => $twoGbFlavor
));
} catch (\Guzzle\Http\Exception\BadResponseException $e) {
// No! Something failed. Let's find out:
$responseBody = (string) $e->getResponse()->getBody();
$statusCode = $e->getResponse()->getStatusCode();
$headers = $e->getResponse()->getHeaderLines();
echo sprintf("Status: %s\nBody: %s\nHeaders: %s", $statusCode, $responseBody, implode(', ', $headers));
}
This would be a polling function:
use OpenCloud\Compute\Constants\ServerState;
$callback = function($server) {
if (!empty($server->error)) {
var_dump($server->error);
exit;
} else {
echo sprintf(
"Waiting on %s/%-12s %4s%%",
$server->name(),
$server->status(),
isset($server->progress) ? $server->progress : 0
);
}
};
$server->waitFor(ServerState::ACTIVE, 600, $callback);
This is my situation. I have a chat-room website. People are publicly chatting together and everyone see who is writing what. All the chats are stored in database (mysql)
Now I want to implement this chatting on Android. So when user sends a text from his phone it should be sent to the chat-room website and vice versa, meaning the Android user should see all texts which are being sent from the chat webpage.
As a result:
1: Android user should see all the texts which people send via the webpage,
2: Android user should be able to send a text to this chat-room webpage (so other users which are using the webpage to chat should see his text).
The big question is, what is the best way to achieve this?
Could this process happen in real time like XMPP?
Is GCM the only way (although it is not real time)?
If i use web services to send the messages to the web, how can i set a listener for the incoming messages?
I don't know if i am clear. Any help is appreciated. Just give the head of the string i will go to the end...
Edit: a server side question: Is there anyway to make the server do something when a specific table in MYSQL is changed (for example when a new row is added)?
The first thing that leapt into my mind was that this fits fairly well into the Pub/Sub paradigm. Clients publish chat messages to specific channels (rooms,) and also subscribe to the channels; the server subscribes to a channel and stores the data in a MySQL database.
You might try using an external real-time network like PubNub. PubNub is free for up to 1m messages (see the pricing page.) They have an Android SDK and PHP SDK (I assume you're using PHP on your server due to your use of the PHP tag.)
In your case, in your Android client, you'd subscribe to a channel:
Pubnub pubnub = new Pubnub("demo", "demo");
try {
pubnub.subscribe("my_channel", new Callback() {
//See full example for all Callback methods
#Override
public void successCallback(String channel, Object message) {
System.out.println("SUBSCRIBE : " + channel + " : "
+ message.getClass() + " : " + message.toString());
}
}
} catch (PubnubException e) {
System.out.println(e.toString());
}
(Full example here.) Then, when you want to publish a message:
Callback callback = new Callback() {
public void successCallback(String channel, Object response) {
Log.d("PUBNUB",response.toString());
}
public void errorCallback(String channel, PubnubError error) {
Log.d("PUBNUB",error.toString());
}
};
pubnub.publish("my_channel", "This is an important chat message!" , callback);
Neat! But what about your server, how does it receive these messages?
$pubnub = new Pubnub(
"demo", ## PUBLISH_KEY
"demo", ## SUBSCRIBE_KEY
"", ## SECRET_KEY
false ## SSL_ON?
);
$pubnub->subscribe(array(
'channel' => 'my_channel', ## REQUIRED Channel to Listen
'callback' => function($message) { ## REQUIRED Callback With Response
## Time to log this to MySQL!
return true; ## Keep listening (return false to stop)
}
));
I hope this helps your project. Let me know how it goes.
SHORT ANSWER
Here's link to CODETUTS
and to a SAMPLE
LONG ANSWER
For make a chat in realtime compatible with android using db like mysql you have various way. the first who come up to me is to do some api but is not the most good way cause you will have to do many request to your server. So i advice you to use technology like nodeJs and socketIO (just google them...you will find tons of example), take a look to the link i've found for you. Have a nice day. Antonio
You need websockets on the web to do this in real time, in android you need to send push notifications.
Maybe you want to check "Google Cloud Messaging for Android".
My idea is to integrate a live support chat on a website. The users text is send with xmpphp to my jabber client with the jabberbot sender id and if I answer, the jabber bot, takes my answer and transfers the text to the user.
There is only one problem. How do I separate different users or different chats? I don't want all users to see the answer, but the user who asks. Is there a kind of unique chat id or another possibility, that I might just missed?
User => Website => Chatbot => me
I want to answer and send it back to the user, but how can I find out the correct user from my answer?
Last time I have to solve this problem I used this architecture:
Entlarge image
The Webserver provides an JavaScript / jQuery or flash chat.
After chat is started, the client ask the server all 1 Second for new Messages.
Alternative for 1 Sec Polling
If that is to slow for you, have a look at websockets.
http://martinsikora.com/nodejs-and-websocket-simple-chat-tutorial
http://demo.cheyenne-server.org:8080/chat.html
But Websockets could no provided by php. There for you need to change php + apchache agaist node.js or java.
Plain HTTP PHP Methode
In PHP you will connect to the PsyBnc with is polling the messages from the supporter for you.
The PsyBnc is an IRC bot.
The reason why don't directly connect to XMPP or BitlBee is that those protocols don't like the flapping connect, disconnect from PHP. Because you can not keep the session alive, you need something that is made for often and short connects. This is the PsyBnc.
I would use something like this:
http://pear.php.net/package/Net_SmartIRC/download
<?php
session_start();
$message = $_GET['message'];
$client_name = $_GET['client_name'];
if (empty($_SESSION['chat_id'])) {
$_SESSION['chat_id'] = md5(time(). mt_rand(0, 999999));
}
if (empty($_SESSION['supporter'])) {
// how do you select the supporter?
// only choose a free?
// We send first message to all supporter and the first who grapped got the chat (where only 3 gues)
}
$irc_host = "127.0.0.1";
$irc_port = 6667; // Port of PsyBnc
$irc_password = "password_from_psy_bnc";
$irc_user = "username_from_psy_bnc";
include_once('Net/SmartIRC.php');
class message_reader
{
private $messages = array();
public function receive_messages(&$irc, &$data)
{
// result is send to #smartirc-test (we don't want to spam #test)
$this->messages[] = array(
'from' => $data->nick,
'message' => $data->message,
);
}
public function get_messages() {
return $this->messages;
}
}
$bot = &new message_reader();
$irc = &new Net_SmartIRC();
$irc->setDebug(SMARTIRC_DEBUG_ALL);
$irc->setUseSockets(TRUE);
$irc->registerActionhandler(SMARTIRC_TYPE_QUERY|SMARTIRC_TYPE_NOTICE, '^' . $_SESSION['chat_id'], $bot, 'receive_messages');
$irc->connect($irc_host, $irc_port);
$irc->login($_SESSION['chat_id'], $client_name, 0, $irc_user, $irc_password);
$irc->join(array('#bitlbee'));
$irc->listen();
$irc->disconnect();
// Send new Message to supporter
if (!empty($message)) {
$irc->message(SMARTIRC_TYPE_QUERY, $_SESSION['supporter'], $message);
}
echo json_encode(array('messages' => $bot->get_messages()));
Connect the support instant messanger to PHP
We have allready an IRC connection to the PsyBnc, now we need to send messages from IRC to ICQ, XMPP, GOOGLE TALK, MSN, YAHOO, AOI...
Here for is a nice solution named BitlBee.
BitlBee offers an IRC Server with can transfer message from and to nearly all instant messager protocols. By aliasing those accounts. For example you need for your system only 1 Server account at google talk, icq ... and at all your supporter to the buddylist of those accounts. Now BitleBee will provide your boddylist as an irc chat.
Your requirements are rather confusing. As Joshua said, you don't need a Jabber bot for this. All you need is a Jabber server - which you should already have. What you do is, you create a volatile user account sessionid#*yourdomain.com* whenever the chat feature is used and then you can just reply to any incoming message like normal while your website client can fetch the messages meant for it whenever.
Alternatively you could create one user account - qa#yourdomain.com - and use XMPP resource identifiers for the routing part. XMPP allows for something like qa#yourdomain.com/*sessionid* and you should be able to tell your XMPP library to only query a specific resource. Most XMPP client software will also reply to a specific resource by default and open a new conversation when applicable. This method is less "clean" than the first, but it would work somewhat better if you can't arbitrarily create user accounts for some reason.
I don't know what XMPP server you are using, but you could also try the Fastpath plugin and webchat for Openfire. Which is meant to provide a support team service over XMPP.
That being said, your question itself seems to imply nothing more than the standard chat feature of XMPP, which is between two users. It just means that the support person has a unique chat with each user asking a question. No other user will see that conversation.