XMPPHP as live support chat - php

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.

Related

Push notification overrides previous notifications

I'm using codeigniter-gcm library on top of codeigniter to send messages to Google Cloud Messaging service. It sends the message and the message is received at the mobile device, but if I send multiple messages, only the latest message appears on the device (as if it is overriding the previous messages).
I'm seeing that I might need to create a unique notification ID, but I'm not seeing how it's done anywhere on the codeigniter-gcm documentation or Google's documentation for downstream messages.
Any idea how this should be done?
Here's my code in the codeigniter controller. It is worth mentioning that Google's response contains a different message_id for each time I send a push...
public function index() {
$this->load->library("gcm");
$this->gcm->setMessage("Test message sent on " . date("d.m.Y H:i:s"));
$this->gcm->addRecepient("*****************");
$this->gcm->setData(array(
'title' => 'my title',
'some_key' => 'some_val'
));
$this->gcm->setTtl(false);
$this->gcm->setGroup(false);
if ($this->gcm->send())
echo 'Success for all messages';
else
echo 'Some messages have errors';
print_r($this->gcm->status);
print_r($this->gcm->messagesStatuses);
}
After three exhausting days I found the solution. I'm posting it here in hope of saving someone else's time...
I had to add a parameter to the data object inside the greater JSON object, named "notId" with a unique integer value (which I chose to use a random integer from a wide range). Now why Google didn't include this in their docs? Beats me...
Here's how my JSON looks now, when it creates separate notifications instead of overriding:
{
"data": {
"some_key":"some_val",
"title":"test title",
"message":"Test message from 30.09.2015 12:57:44",
"notId":14243
},
"registration_ids":["*******"]
}
Edit:
I'm now thinking that the notId parameter is not really determined by Google, but by a plugin I use on the mobile app side.
To extend further on my environment, my mobile app is developed using Phonegap, so to get push notification I use phonegap-plugin-push which I now see in its docs that parameter name.
I'm kinda' lost now as far as explaining the situation - but happy it is no longer a problem for me :-)
You need to pass a unique ID to each notification. Once you have clicked on the notification you use that ID to remove it.
...
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.cancel(SIMPLE_NOTFICATION_ID_A);
...
But I'm sure you shouldn't have so much of notifications for user at once. You should show a single notification that consolidates info about group of events like for example Gmail client does. Use Notification.Builder for that purpose.
NotificationCompat.Builder b = new NotificationCompat.Builder(c);
b.setNumber(g_push.Counter)
.setLargeIcon(BitmapFactory.decodeResource(c.getResources(), R.drawable.list_avatar))
.setSmallIcon(R.drawable.ic_stat_example)
.setAutoCancel(true)
.setContentTitle(pushCount > 1 ? c.getString(R.string.stat_messages_title) + pushCount : title)
.setContentText(pushCount > 1 ? push.ProfileID : mess)
.setWhen(g_push.Timestamp)
.setContentIntent(PendingIntent.getActivity(c, 0, it, PendingIntent.FLAG_UPDATE_CURRENT))
.setDeleteIntent(PendingIntent.getBroadcast(c, 0, new Intent(ACTION_CLEAR_NOTIFICATION), PendingIntent.FLAG_CANCEL_CURRENT))
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE)
.setSound(Uri.parse(prefs.getString(
SharedPreferencesID.PREFERENCE_ID_PUSH_SOUND_URI,
"android.resource://ru.mail.mailapp/raw/new_message_bells")));

Implementing chat between webpage and android

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".

Quickbooks integration (intranet)

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
...
}

Collect data from email message

I want to collect data from email to mysql database using php.
If some one is sent a mail to their mail account to my mail id. I want that mail information to store in my database. for further operation. It is possible in PHP because I saw this feature in one hosting support application Kayako Fusion which developed by PHP.
So plese give some information to do this task.
If you want to parse with PHP the best way is to use a 3rd party API to revive the email and then send it to your PHP script with a HTTP Post.
I'd recommend using either sendgrid.com or mailgun.com
Both of these services will parse the email and send you the information in a http POST that you can then insert into mysql. API docs for both: MailGun Incoming Parse API / SendGrid Incoming Parse API
You can use the imap functions, for example:
<?php
$imap = imap_open("{server.example.com:143}INBOX" , 'login' , 'password');
if( $imap ) {
//Check no.of.msgs
$num = imap_num_msg($imap);
//if there is a message in your inbox
if( $num >0 ) {
//read that mail recently arrived
$the_message = imap_body($imap, $num);
//Do the stuff with $the_message
}
//close the stream
imap_close($imap);
}
You'll have to setup a cronjob (scheduled task on Windows) that connects to the Exchange or POP server, retrieve's all new emails sinds the last run and insert them into the DB.
In case of a POP mail server(I think POP will be easier), there is a comment here with all functions you need right -> here. If that doesn't work, try Googling for "PHP POP wrapper" or something similar.
In case of a Microsoft Exchange server, you'd have to use a PHP Exchange wrapper, found one here for you.
Goodluck!
You can pipe your email to a php script and then extract each part of email and store it in data base.
check this example
when you get content of email you can do what ever you want

Best way to implement Single-Sign-On with all major providers?

I already did a lot of research on this topic and have implemented a lot of solutions myself.
Including OpenID, Facebook Connect (using the old Rest API and the new Graph OAuth 2.0 API), Sign in with twitter (which has been upgraded to fully qualified OpenID by now as far as I know), and so on...
But what I'm still missing is the perfect all in one solution.
During my research I stumbled about some interesting projects:
Janrain (formerly RPX) - a commercial solution
Gigya - a free but externally hosted solution with javascript and rest apis
AnyOpenID - a free solution for clients, commercial for websites
But I don't want to rely on an external provider and I would like a free solution as well, so I am not limited in implementation.
I have also seen developers implementing one service after another dutifully following the providers instructions and setting up models and database tables for everything.
Of course this will work but it is a shitload of work and always needs development and changes in your application etc.
What I am looking for is an abstraction layer that takes all the services out there to one standard that can be integrated in my website. Once a new service appears I only want to add one model that deals with the abstraction of that specific provider so I can seamlessly integrate it into my application.
Or better, find an already existing solution that I can just dowonload.
Ideally this abstraction service would be hosted independently from my application so it can be used for several applications and be upgraded independently.
The last of the 3 solutions above looks promising from the concept.
Everything is just ported to an synthetic OpenID, and the website jut has to implement OpenID.
After a while i found Django socialauth, a python based authentication system for the Django Webframework. But it looks like it operates as described above and i think this is the same login system that Stackoverflow uses (or at least some modified fork...).
I downloaded it and tried to set it up and to see whether it could be set up as a standalone solution but I had no luck, as I am not so into python either.
I would love a PHP based solution.
So after this long text my question precisely is:
How would you implement SSO, any better idea than porting everything and have OpenID as basis?
What are the pros and cons of that?
Do you know any already existing solutions? Preferrably open source.
I hope this question is not too subjective, thanks in advance.
Update:
I concluded that building a proxy / wrapper or what you might call it for Facebook, to port it to an OpenID so it becomes an OpenID endpoint / provider would be the best option.
So that exactly what i did.
Please see my answer below.
I added the bounty to get feedback/discussion on it. Maby my approach is not so good as i currently think it is!
As original author of this answer, I want to note that I regard it as
OUTDATED. Since most providers decided to exclusively implement Oauth instead of Openid. Newer Openid services will also likely use
openid connect, which is based on oauth. There are good libraries like for example: https://github.com/hybridauth/hybridauth
After the discussion of the already existing answer i sum up:
Almost every major provider is an openid provider / endpoint including Google, Yahoo, Aol.
Some of them requrie the user to specify the username to construct the openid endpoint.
Some of them (the ones mentioned above) do have discovery urls, where the user id is automatically returned so that the user only has to click. (i would be glad if someone could explain the technical background)
However the only pain in the ass is Facebook, because they have their Facebook connect where they use an adapted version of OAuth for authentication.
Now what I did for my project is to set up an openid provider that authenticates the user with the credentials of my facebook Application - so the user gets connected to my application - and returns a user id that looks like:
http://my-facebook-openid-proxy-subdomain.mydomain.com/?id=facebook-user-id
I also configured it to fetch email adress and name and return it as AX attributes.
So my website just has to implement opend id and i am fine :)
I build it upon the classes you can find here: http://gitorious.org/lightopenid
In my index.php file i just call it like this:
<?php
require 'LightOpenIDProvider.php';
require 'FacebookProvider.php';
$op = new FacebookProvider;
$op->appid = 148906418456860; // your facebook app id
$op->secret = 'mysecret'; // your facebook app secret
$op->baseurl = 'http://fbopenid.2xfun.com'; // needs to be allowed by facebook
$op->server();
?>
and the source code of FacebookProvider.php follows:
<?php
class FacebookProvider extends LightOpenIDProvider
{
public $appid = "";
public $appsecret = "";
public $baseurl = "";
// i have really no idea what this is for. just copied it from the example.
public $select_id = true;
function __construct() {
$this->baseurl = rtrim($this->baseurl,'/'); // no trailing slash as it will be concatenated with
// request uri wich has leading slash
parent::__construct();
# If we use select_id, we must disable it for identity pages,
# so that an RP can discover it and get proper data (i.e. without select_id)
if(isset($_GET['id'])) {
// i have really no idea what happens here. works with or without! just copied it from the example.
$this->select_id = false;
}
}
function setup($identity, $realm, $assoc_handle, $attributes)
{
// here we should check the requested attributes and adjust the scope param accordingly
// for now i just hardcoded email
$attributes = base64_encode(serialize($attributes));
$url = "https://graph.facebook.com/oauth/authorize?client_id=".$this->appid."&redirect_uri=";
$redirecturl = urlencode($this->baseurl.$_SERVER['REQUEST_URI'].'&attributes='.$attributes);
$url .= $redirecturl;
$url .= "&display=popup";
$url .= "&scope=email";
header("Location: $url");
exit();
}
function checkid($realm, &$attributes)
{
// try authenticating
$code = isset($_GET["code"]) ? $_GET["code"] : false;
if(!$code) {
// user has not authenticated yet, lets return false so setup redirects him to facebook
return false;
}
// we have the code parameter set so it looks like the user authenticated
$url = "https://graph.facebook.com/oauth/access_token?client_id=148906418456860&redirect_uri=";
$redirecturl = ($this->baseurl.$_SERVER['REQUEST_URI']);
$redirecturl = strstr($redirecturl, '&code', true);
$redirecturl = urlencode($redirecturl);
$url .= $redirecturl;
$url .= "&client_secret=".$this->secret;
$url .= "&code=".$code;
$data = $this->get_data($url);
parse_str($data,$data);
$token = $data['access_token'];
$data = $this->get_data('https://graph.facebook.com/me?access_token='.urlencode($token));
$data = json_decode($data);
$id = $data->id;
$email = $data->email;
$attribute_map = array(
'namePerson/friendly' => 'name', // we should parse the facebook link to get the nickname
'contact/email' => 'email',
);
if($id > 0) {
$requested_attributes = unserialize(base64_decode($_GET["attributes"]));
// lets be nice and return everything we can
$requested_attributes = array_merge($requested_attributes['required'],$requested_attributes['optional']);
$attributes = array();
foreach($requested_attributes as $requsted_attribute) {
if(!isset($data->{$attribute_map[$requsted_attribute]})) {
continue; // unknown attribute
}
$attributes[$requsted_attribute] = $data->{$attribute_map[$requsted_attribute]};
}
// yeah authenticated!
return $this->serverLocation . '?id=' . $id ;
}
die('login failed'); // die so we dont retry bouncing back to facebook
return false;
}
function get_data($url) {
$ch = curl_init();
$timeout = 5;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
}
Its just a first working version (quick and dirty)
Some dynamic stuff is hardcoded to my needs.
It should show how and that it can be done.
I am happy if someone picks up and improves it or re writes it or whatever :)
Well i consider this question answered
but I add a bounty just to get discussion. I would like to know what you think of my solution.
I will award the bounty to the best answer/comment beside this one.
OpenID is going to be your best bet for this application. It is supported by many, providers:
Google
Yahoo
MyOpenID
AOL
The Only problem is that twitter has not implemented OpenID yet. This is probably due to the fact that they are a proprietery based company, so they wanted their 'own' solution.
To solve that solution, you might write a wrapper class to provide compatibility with OpenID, but the chance is that even if your users don't have a twitter account, they might have a Facebook, Google, or Yahoo account.
Facebook Supports oauth, so you will have to port oauth to OpenID
Some PHP libraries for OpenID can be found here.
Now, some questions have been raised about facebook being an oauth provider.
Their oauth URL is "https://graph.facebook.com/oauth/authorize"
If you still do not belive me, then you can look at this javascript file, where I got that URL. If you don't believe that javascript file, then notice that it is hosted by stackexchange, the provider of this site. Now you must beleive that.
Fast forward two years and the answer of "OpenID is the answer" appears to be falling by the wayside by a number of the big providers. Most of the major third-party integration sites seem to have moved onto some flavor of OAuth (usually OAuth2). Also, if you don't mind NOT using OpenID/OAuth, there is a now complete SSO solution written in PHP (Disclaimer and full disclosure: This product is developed and maintained by myself under the CubicleSoft banner):
Single Sign-On Server/Client
Which didn't exist when this question was originally asked. It has a liberal license (MIT or LGPL) and meets your requirement of being an abstraction layer. The project tends to be focused toward enterprise sign ins but has some social media sign ins in the mix too (Google and Facebook).
You might also want to look at HybridAuth, which is only focused on social media sign ins but is more of a library than a prebuilt solution that you can throw onto a server and be done with it. So there is a bit more work involved with setting it up. It really depends on what you are after.
If you are happy with your OpenID solution, then great, but there are more options today than there were two years ago and people are still finding this thread.

Categories