Importing inside a website a watson conversation chat - ibm-watson

I'm implementing a watson conversation chat, now i'm wondering, how i can import this chat in a existing website?
any helps?

You can see one example conversation-simple in Nodejs and Conversation-with-discovery in Java.
This repository it is from IBM Developers.
This example show one example how to call the API and has some front-end for show the conversation flow and Watson understands, all you have to know how to use Watson, context variables, intents, entities, etc.
In this case, you call conversation API with Service Credentials and Workspace_id from your Conversation created inside IBM Bluemix:
Example to call and invoke the result with Javascript language (nodejs):
var conversation = new Conversation({
// If unspecified here, the CONVERSATION_USERNAME and CONVERSATION_PASSWORD env properties will be checked
// username: '<username>', paste the Service Credentials here or paste in env archive
// password: '<password>',
url: 'https://gateway.watsonplatform.net/conversation/api',
version_date: '2016-10-21',
version: 'v1'
});
// Endpoint to be call from the client side
app.post('/api/message', function(req, res) {
var workspace = process.env.WORKSPACE_ID || '<workspace-id>'; //workspace id can be check inside Conversation Service, click View details
if (!workspace || workspace === '<workspace-id>') {
return res.json({
'output': {
'text': 'The app has not been configured with a <b>WORKSPACE_ID</b> environment variable.' //error if workspace_id is not set
}
});
}
var payload = {
workspace_id: workspace,
context: req.body.context || {},
input: req.body.input || {}
};
// Send the input to the conversation service
conversation.message(payload, function(err, data) {
if (err) {
return res.status(err.code || 500).json(err);
}
return res.json(updateMessage(payload, data));
});
});
You can use other languages (Python, curl, Java) see this Documentation.
Check the example here running.

Related

How do I avoid React Native GoogleSignIn by sending to google a password violation

I used #react-native-google-signin/google-signin": "^8.0.0" to create a google sign in button into my app.
When I used it, google recognised it as not trusted app, so send my an email to advice of a violation, and now every time I use a password saved on my google account to login on any site or application, he gives me a message telling me to change all of my passwords. I solved to remove the message, by ignoring for every passwords, almost 200 :/. But it's just temporary solution, cause if I do login again to my app it will happen again. How can I say to google that it is an app in developing, is there any mode to activate? Here's my code:
GoogleSignin.configure({
scopes: ['https://www.googleapis.com/auth/drive.readonly'], // what API you want to access on behalf of the user, default is email and profile
webClientId: '15299853035-njb79hdij6h1svo22drigurca1qb4djb.apps.googleusercontent.com', // client ID of type WEB for your server (needed to verify user ID and offline access)
offlineAccess: true, // if you want to access Google API on behalf of the user FROM YOUR SERVER
// hostedDomain: '', // specifies a hosted domain restriction
// forceCodeForRefreshToken: true, // [Android] related to `serverAuthCode`, read the docs link below *.
// accountName: '', // [Android] specifies an account name on the device that should be used
iosClientId: '15299853035-siujgcjtol0lfja83n7p6fk55cq6jinn.apps.googleusercontent.com', // [iOS] if you want to specify the client ID of type iOS (otherwise, it is taken from GoogleService-Info.plist)
// googleServicePlistPath: '', // [iOS] if you renamed your GoogleService-Info file, new name here, e.g. GoogleService-Info-Staging
// openIdRealm: '', // [iOS] The OpenID2 realm of the home web server. This allows Google to include the user's OpenID Identifier in the OpenID Connect ID token.
// profileImageSize: 120, // [iOS] The desired height (and width) of the profile image. Defaults to 120px
});
try {
await GoogleSignin.hasPlayServices();
const { idToken } = await (await GoogleSignin.signIn());
const googleCredential = await GoogleAuthProvider.credential(idToken);
await signInWithCredential(authApp, googleCredential)
.then(async(userCredential) => {
if(!authApp.currentUser.emailVerified)
{
sendEmailVerification(authApp.currentUser)
.then(() => {
// Email verification sent!
// ...
})
.catch((error)=>{
setLoading(false)
console.log(error)
})
}
......

Trigger an event to private channel in react app

I want to trigger an event to pusher private channel and my server side language is laravel I reviewed a lot of resources, but I did not find a comprehensive approach which covers both the server side and the front side Finally I got this solution
in the first step :
export const SendChat = () => {
try {
var pusher = new Pusher('YOUR_APP_KEY', {
cluster: 'ap2',
forceTLS: true,
authTransport: 'jsonp',
authEndpoint: `${baseUrl}pusher/auth`,
});
var channel = pusher.subscribe('private-channel');
channel.bind('pusher:subscription_succeeded', function() {
var triggered = channel.trigger('client-EVENT_NAME', { 'message': 'Hi ....' });
console.log(triggered)
});
} catch (error) {
console.error(error);
}
}
and call it somewhere
<Button onClick={this.props.SendChat} waves='light' >Send</Button>
you must Enable client events in pusher account setting
login to your pusher account -> select the channel ->App Settings -> select Enable client events -> update
add your app key, channel name and event name after that we need authorization in server side this is sample laravel code first add this route in web.php
Route::get('pusher/auth', 'PusherController#pusherAuth');
make PusherController.php like this :
public function pusherAuth()
{
$user = auth()->user();
if ($user) {
$pusher = new Pusher('auth_key', 'secret', 'app_id');
$auth= $pusher->socket_auth(Input::get('channel_name'), Input::get('socket_id'));
$callback = str_replace('\\', '', $_GET['callback']);
header('Content-Type: application/javascript');
echo($callback . '(' . $auth . ');');
return;
}else {
header('', true, 403);
echo "Forbidden";
return;
}
}
test it you should see something like this
Pusher : State changed : connecting -> connected with new socket ID 3953.****556
Pusher : Event sent : {"event":"pusher:subscribe","data":{"auth":"83045ed1350e63c912f5:328fb78165d01f7d6ef3bb6d4a30e07c9c0ad0283751fc2c34d484d4fd744be2","channel":"private-chat"}}
Pusher : Event sent : {"event":"client-MessageSent","data":{"message":"Hi ...."},"channel":"private-chat"}
true
It doesn't matter much which client-side language you are using. Angular, Vue, React they all are JS framework and libraries. And, you can consider using a generic JS code which you can place in all 3 apps.
Let me try to give you a detailed answer I can give as per my knowledge.
In order to get started, you should first complete try to complete Chat scenario without pusher. i.e: user should be able to send a message from front-end via the API and it should be stored inside the database.
Once you have done this it is very easy to include pusher in the flow. ( In simple words, you'll have to broadcast an event and that'll inform the Socket Server to broadcast a message to all/other user(s) on the channel )
For Pusher Authentication, you don't need to explicitly create a route and a method. Once you have uncommented BroadcastServiceProvider inside config/app.php. You can run:
php artisan route:list
and, you'll see a route for broadcast broadcasting/auth.
You can use this route to authenticate. Although, you can make few changes and prepend /api before this.
Go into BroadcastServiceProvider.php and replace your boot method with:
public function boot()
{
Broadcast::routes(
[
'prefix' => 'api',
'as' => 'api.broadcasting.auth',
'middleware' => ['auth:sanctum'],
]
);
require base_path('routes/channels.php');
}
I assume you're using Laravel Sanctum for Authentication. If not you need to change the authentication middleware to your provider.
Once done, you can authenticate from frontend using this auth route. So, what I have done is created a service in ReactJS and in the constructor I have created a Pusher instance :
this.pusher = new Pusher(PUSHER_APP_KEY, {
authEndpoint: 'http:localhost:8000/api/broadcasting/auth',
cluster: PUSHER_CLUSTER,
useTLS: true,
auth: {
headers: {
Authorization: 'Bearer ' + authHeader
}
}
});
You only need to instantiate your Pusher once and use this instance throughout the app. So, that's why I have created a service class for Pusher.
If you want things to be simple for now you need to execute this code on the page where you will use pusher. Once the Page load, you need to call this code. So, you'll do:
let pusher = null;
useEffect(() => {
pusher = new Pusher(PUSHER_APP_KEY, {
authEndpoint: 'http:localhost:8000/api/broadcasting/auth',
cluster: PUSHER_CLUSTER,
useTLS: true,
auth: {
headers: {
Authorization: 'Bearer ' + authHeader
}
}
});
}, []);
So, this way we have an instance of Pusher in our functional component or page.
Now, we need to subscribe to channel.
Using this instance of pusher we can subscribe to channels. If you have followed the useEffect approach on the same page then, right after getting the instance you can subscribe to channels and bind to events using this code:
const channel = pusher.subscribe('private-chat.' + channelName)
And, to bind to an event you can do:
channel.bind('event.name', function(data) {
console.log(data);
});
Make sure to replace "channelName" and "event.name" with your channel and event name respectively.
Now you'll be able to listen to your event once broadcasted from the backend.
So, you'll do something like this from the backend. You'll have a method that will store the message inside the database so, let's say that code is:
public function sendMessage (Request $request){
//.... Rest of the logic
$user = $request->user();
// Store the message
$chatMessage = $chat->messages()->create([
'message' => $message,
'sender_id' => $user->id
]);
broadcast(new NewMessage($user, $chatMessage))->toOthers();
//... Rest of the logic
}
This broadcast message will send this message to other user in the chat.
I hope this answer gives you a good idea and direction.
For work with WebSockets via Pusher on Laravel, I recommended using the package Laravel Echo for React part. And on the backend side in config/broadcasting.php setup configuration for Pusher.
See more detail on official documentation Laravel how to use Pusher on the backend side and frontend side.
https://laravel.com/docs/8.x/broadcasting#pusher-channels

JWT Authentication in Google Cloud Functions

I'm having trouble troubleshooting the cause for a 403 response from the Google Dataflow API while called using the module "googleapis" inside a Google Cloud Function.
The code works when run on my PC using the same code that is being run on Cloud Functions.
The JWT .json file is being retrieved from an object stored on a Google Storage bucket.
The code looks like this:
...
return getToken(). //Retrieves the JWT Client from Google Storage
then(function (jwtToken) {
console.log("Token: ", JSON.stringify(jwtToken));
return dataFlowList({
projectId: adc.projectId,
auth: jwtToken,
filter: "TERMINATED"
}).then(list => filterDataflowJobList(list))
...
Here the getToken function:
...
let storage: CloudStorage.Storage = CloudStorage({
projectId: adc.projectId
});
var bucket: CloudStorage.Bucket = storage.bucket(bucketName);
var bucketGetFiles = PromiseLab.denodeify(bucket.getFiles);
var stream = bucket.file(jwtJsonFileName).createReadStream();
return toString(stream)
.then(function (msg) {
var jsonJwt = JSON.parse(msg);
var jwtClient = new google.auth.JWT(
jsonJwt.client_email,
null,
jsonJwt.private_key,
['https://www.googleapis.com/auth/cloud-platform'], // an array of auth scopes
null
);
return jwtClient;
}).catch(function (error) {
console.log("Error while trying to retrieve JWT json");
throw error;
})
}
...
I'm based in EU and Cloud Functions are US-bound, could that be the case?
Dataflow jobs are also run in US
While running on Google Function, the authentication retrieval method I'm using is not retrieving the projectId, hence the unauthorized.
async function getADC() {
// Acquire a client and the projectId based on the environment. This method looks
// for the GCLOUD_PROJECT and GOOGLE_APPLICATION_CREDENTIALS environment variables.
const res = await auth.getApplicationDefault();
let client = res.credential;
// The createScopedRequired method returns true when running on GAE or a local developer
// machine. In that case, the desired scopes must be passed in manually. When the code is
// running in GCE or a Managed VM, the scopes are pulled from the GCE metadata server.
// See https://cloud.google.com/compute/docs/authentication for more information.
if (client.createScopedRequired && client.createScopedRequired()) {
// Scopes can be specified either as an array or as a single, space-delimited string.
const scopes = ['https://www.googleapis.com/auth/cloud-platform'];
client = client.createScoped(scopes);
}
return {
client: client,
projectId: res.projectId
}
}
I discovered it by looking at the Header request in the error log, it was in the form of: url: 'https://dataflow.googleapis.com/v1b3/projects//jobs' (notice the double "//" between projects and jobs.

Plaid: how to create public token in the front end (Ionic/angular) and send to server

I am follow this tutorial in order to get a transactions/accounts detail from the plaid API. Plaid'd quickstart guide user ejs in order to send to the server with the onSuccess function. How do I create this token using ionic?
Plaid quick guide also suggests that we use code blow
var linkHandler = Plaid.create({
env: 'sandbox',
clientName: 'Client Name',
key: '<PUBLIC_KEY>',
product: ['auth', 'transactions'],
token: '<GENERATED_PUBLIC_TOKEN>',
onSuccess: function(public_token, metadata) {
// You do not need to repeat the /item/public_token/exchange
// process when a user uses Link in update mode.
// The Item's access_token has not changed.
},
and also suggest to use this code
// Create a public_token for use with Plaid Link's update mode
client.createPublicToken(ACCESS_TOKEN, (err, result) => {
// Handle err
// Use the generated public_token to initialize Plaid Link in update
// mode for a user's Item so that they can provide updated credentials
// or MFA information
const publicToken = result.public_token;
});
in order to create a public token and get the access token. I can't use this function because I'm getting an error 'Plaid and/or client is not defined
How do I create this public token using Ionic front end and node back end?
What's the workflow here?
Thanks in advance
On the server side, you'll need to initialize the Plaid node client library first. You will also want to make an exchange token call, to exchange the public_token from Link for an API access_token. You'll then save the access_token and use it to retrieve transaction and account data:
// Initialize the Plaid API client with your API keys (https://dashboard.plaid.com/account/keys)
// Use plaid.environments.production, plaid.environments.development, or plaid.environments.sandbox
const plaid = require('plaid');
const client = new plaid.Client(client_id, secret, public_key, plaid.environments.sandbox);
client.exchangePublicToken(PUBLIC_TOKEN, function(error, tokenResponse) {
if (error != null) {
var msg = 'Could not exchange public_token!';
console.log(msg + '\n' + error);
}
const ACCESS_TOKEN = tokenResponse.access_token;
const ITEM_ID = tokenResponse.item_id;
console.log('Access Token: ' + ACCESS_TOKEN);
console.log('Item ID: ' + ITEM_ID);
// Now retrieve transactions or account information with the access_token
});
For the client-side in your Ionic app, you'll need to include the link-initialize.js script before calling Plaid.create. Specifically:
<script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js">
</script>
Here's a full client-side HTML example:
<button id="link-button">Link Account</button>
<script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script type="text/javascript">
var handler = Plaid.create({
clientName: 'Plaid Walkthrough Demo',
env: 'sandbox',
key: '[PUBLIC_KEY]', // public_key is at https://dashboard.plaid.com/account/keys
product: ['auth'],
onLoad: function() {
// Optional, called when Link loads
},
onSuccess: function(public_token, metadata) {
// Send the public_token to your app server.
// The metadata object contains info about the institution the
// user selected and the account ID, if `selectAccount` is enabled.
$.post('/get_access_token', {
public_token: public_token,
});
},
onExit: function(err, metadata) {
// The user exited the Link flow.
}
});
</script>
An Angular library was recently created: click here and here
I had some issues implementing Plaid successfully at first; these tips should help:
Implement the library as shown in the second link above. Make sure for step two you import in your app.module.ts file. Don't use the jQuery provided in the documentation.
Using this library, a button will be automatically created within the Angular element <mr-ngx-plaid-link-button>. This button will act as a submit button unless you use DOM or other methods to change it to type button on ngAfterViewInit()
All five events in step three are listeners for various events. The onSuccess() callback will return the public token - only after you have (a) successfully submitted bank credentials (user_good / pass_good on Sandbox) and (b) clicked the Continue button to exit the Plaid Link

Implementation of Paypal in single page application

I am currently working on a game, which will consist out of an API-based backend, along with a web frontend (which is a single page app, in AngularJS) and on several mobile devices (using Cordova). I am planning on serving the SPA over the main domain name, along with a CDN. The SPA (and homepage) will all be static HTML/Javascript/CSS files, so the only part which is dynamic is the api. The domain name for the "main server" hosting the static sites will be in the style of example.com, the one for the api will be api.example.com
I am wondering how I can integrate Paypal into this scenario though. The internet doesn't seem to offer much advice on how to integrate it into S.P.A's like this...or my google-fu could be off. Thanks for the replies.
Below is how I am handling the situation,
I have a button to say pay with paypal and onClick I open a new window -> window.open("/paypalCreate", width = "20px", height = "20px");
and I capture this get request "/paypalCreate" in my node.js server and call create method which looks liek below
exports.create = function (req, res) {
//Payment object
var payment = {
//fill details from DB
};
//Passing the payment over to PayPal
paypal.payment.create(payment, function (error, payment) {
if (error) {
console.log(error);
} else {
if (payment.payer.payment_method === 'paypal') {
req.session.paymentId = payment.id;
var redirectUrl;
for (var i = 0; i < payment.links.length; i++) {
var link = payment.links[i];
if (link.method === 'REDIRECT') {
redirectUrl = link.href;
}
}
res.redirect(redirectUrl);
}
}
});
};
This redirects user to paypal and once user confirms or cancels payment, the redirect urls are called. And in the success redirect url I capture the payment details into the databse and render a html in this opened window with the confirmation.
exports.execute = function (req, res) {
var paymentId = req.session.paymentId;
var payerId = req.param('PayerID');
// 1. if this is executed, then that means the payment was successful, now store the paymentId, payerId and token into the database
// 2. At the close of the popup window open a confirmation for the reserved listing
var details = {"payer_id": payerId};
paypal.payment.execute(paymentId, details, function (error, payment) {
if (error) {
console.log(error);
} else {
//res.send("Hell yeah!");
res.render('paypalSuccess', {payerId: payerId, paymentId: paymentId});
}
});
};
Once the user closes the opened window in which paypal was being handled the orginal SPA window will be refreshed and thus getting the payment details from the DB and here you can handle the SPA in whatever way you want.
I know that this is a dirty hack, but like you I couldnt find a better way. Please let me know if this works for you or if you have a found a better way to do tihs.
cheers,
Chidan

Resources