Stripe Connect - URL for onboarding crashes - node.js

I am building an onboarding flow for new customers on my platform, specifically the sellers right now, and I am running into an error I am unsure about. I have a node backend and a react frontend. I am able to create an account along with an onboarding link. I am in testing mode.
So my next step was to fill out the onboarding document and submit it for verification as if i was a seller. When I reach the final page and click submit my node server crashes with the following error. Am I misunderstanding how this should work? Or is this just success and now it's on me to redirect?
Error: ENOENT: no such file or directory, stat '/Users/mac/Documents/git_projects/client/index.html'
Node.js
app.post("/create-account-hosted", async (req, res) => {
const data = req.body;
try {
// Create account
var account = await stripe.accounts.create({
country: 'US',
type: 'custom',
business_type: 'individual',
capabilities: { card_payments: { requested: true }, transfers: { requested: true }, }
//requested_capabilities: ['card_payments', 'transfers'],
});
console.log('My Created Account..', account);
// Create accountLink
var accountLink = await stripe.accountLinks.create({
account: account.id,
success_url: 'http://localhost:4242?success',
failure_url: 'http://localhost:4242?failure',
type: 'custom_account_verification',
collect: 'eventually_due'
});
console.log('Account link info...', accountLink)
} catch (err) {
console.log(err);
res.status(400)
res.send({ error: err })
return;
}
res.send([accountLink, { "account_id": account.id }]);
});
Below are the pics of where I end up and at what part:
And then this happens:

Am I misunderstanding how this should work? Or is this just success and now it's on me to redirect?
The latter. You've successfully created the account link when you called the create()
var accountLink = await stripe.accountLinks.create({
account: account.id,
success_url: 'http://localhost:4242?success',
failure_url: 'http://localhost:4242?failure',
type: 'custom_account_verification',
collect: 'eventually_due'
});
The success_url would be a page on your site you'd want to redirect the user to. Same for the failure_url.
If you dig into the stripe docs we can see an example of their success.html page and it's just a sample dummy page users are sent to on payment success in this example.
success.html:
<html>
<head>
<title>Thanks for your order!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section>
<p>
We appreciate your business! If you have any questions, please email
orders#example.com.
</p>
</section>
</body>
</html>
This again confirms that you can redirect to any page you want on success. Hope that helped!

Related

How to access clientReferenceId on success using Stripe Checkout

I'm new to Stripe and using what appears to be a very simplistic setup to accept payments using Stripe Checkout. I'm passing a clientReferenceId which I need to access on the success page. Is this possible? Here's the code which is called on the Checkout button:
const stripeCheckout = async () => {
setLoading(true)
const stripe = await stripePromise;
const { error } = await stripe.redirectToCheckout({
lineItems: [
{
price: 'price_xxxxx',
quantity:1,
}
],
mode:"payment",
cancelUrl: window.location.origin,
successUrl: `${window.location.origin}/payment-complete`,
clientReferenceId: 'abc',
});
if (error) {
console.log("Error # Checkout: ",error)
setLoading(false)
}
}
Thank you for any help.
You can access the client_reference_id by retrieving the Checkout Session on the success page: https://stripe.com/docs/payments/checkout/custom-success-page
However a much easier solution would be to just encode your variable directly into the success URL:
successURL: `${window.location.origin}/payment-complete?id=abc`,
Then on your success page you can just access the query string variables.

Send data from bot to client in DirectLine WebChat - NodeJS Botframework

I added bot to an HTML page on our intranet using the following code:
<link href="https://cdn.botframework.com/botframework-webchat/latest/botchat.css" rel="stylesheet" />
<style>
#bot{
height: 600px;
}
</style>
<div>
<div id="bot" />
</div>
<script src="https://cdn.botframework.com/botframework-webchat/latest/botchat.js"></script>
<script>
var user = {
id: 'user-id',
name: 'user name'
};
var botConnection = new BotChat.DirectLine({
token: '[token]',
user: user
});
BotChat.App({
user: user,
botConnection: botConnection,
bot: { id: 'test', name: 'test' }
}, document.getElementById("bot"));
botConnection
.postActivity({
from: user,
name: 'WelcomeDialog',
type: 'event',
value: ''
})
.subscribe(function (id) {
console.log('"trigger requestWelcomeDialog" sent');
});
</script>
Now, I need to send data back to this client, to be executed on that HTML page, since the page exists within the context of our intranet (internal servers), so I want to have the intent return from LUIS and directed to specific dialog, then send the required entity value from this dialog to the client to be executed there, then send the result back to the server so I can display a formatted message to the user.
So basically, I would need to have 2-way communication between the client (added to my intranet) and the bot itself (the nodejs app hosted in azure)
Update:
I implemented the backchannel in my bot, so now the code looks like this:
jQuery(function () {
//get user name from the system
var userid = _spPageContextInfo.userId;
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";
var requestHeaders = { "accept": "application/json;odata=verbose" };
$.ajax({
url: requestUri,
contentType: "application/json;odata=verbose",
headers: requestHeaders,
success: onSuccess,
error: onError
});
function onSuccess(data, request) {
var loginName = data.d.Title;
var user = {
id: userid,
name: loginName
};
var botConnection = new BotChat.DirectLine({
token: '[token]',
user: user
});
let FindPerson = function (personName) {
let msg = `You asked for ${personName}`
botConnection
.postActivity({ type: "event", value: msg, from: { id: "me" }, name: "FindPersonResultFound" })
.subscribe(id => console.log("success"));
}
BotChat.App({
user: user,
botConnection: botConnection,
bot: { id: 'TestBot', name: 'test bot' }
}, document.getElementById("bot"));
botConnection
.postActivity({
from: user,
name: 'WelcomeDialog',
type: 'event',
value: ''
})
.subscribe(function (id) {
console.log('"trigger requestWelcomeDialog" sent');
});
botConnection.activity$
.filter(activity => activity.type === "event" && activity.name === "FindPerson")
.subscribe(activity => FindPerson(activity.value))
}
function onError(error) {
alert("error");
}
})
My server side code looks like this:
bot.on('event', function (message) {
if (message.name == 'WelcomeDialog') {
bot.beginDialog(message.address, message.name);
}
if (message.name === "FindPersonResultFound") {
bot.beginDialog(message.address, message.name, message.value)
}
});
However, if I send a message that's related to any dialog, it gets repeated as if the sender is me:
According to your output, I assumpt that your bot application would contain a default root dialog / which will return any thing you input.
If so, you can try to change beginDialog to replaceDialog in your bot event register functions, to clear the previous dialog stack.
Also, you could provide more code about your bot application, so that we can have a deeper looking over.

Trigger Bot with Drag & drop SharePoint Online

I want to be able to trigger my bot who's on my SharePoint online Site by Droping a local file to him.
I created a WebPart to use this bot on the site, and putting the embed code give by Azure.
But when i drop a file in the bot, it open the document in a new tab showing me the content.
I would like to start the conversation while drop a file like this :
Start of bot conversation by putting a file
I'd imagine some solution by using a drop zone on the iframe which contain the bot, but it's not working.
I visit some site who can help but i don't really know how to implement this : Bot in WebChat, DirectLine API, Send Activity to the bot
This GitHub could also be usefull.
You'll need to handle the ondragover and ondrop events (cancelling the default behavior) and post the activity manually:
html:
<div id="bot" ondrop="drop_handler(event);" ondragover="dragover_handler(event);" />
Javascript:
const dl = new BotChat.DirectLine({
secret: 'YourDLSecret',
webSocket: false
});
BotChat.App({
botConnection: dl,
user: { id: 'userid' },
bot: { id: 'botid' },
resize: 'detect'
}, document.getElementById("bot"));
function dragover_handler(ev) {
console.log("dragOver");
ev.preventDefault();
}
function drop_handler(ev) {
console.log("Drop");
ev.preventDefault();
ev.stopPropagation();
var files = [];
for (var i = 0; i < ev.dataTransfer.items.length; i++) {
// If dropped items aren't files, reject them
if (ev.dataTransfer.items[i].kind === 'file') {
var file = ev.dataTransfer.items[i].getAsFile();
files.push({
contentType: file.type,
contentUrl: window.URL.createObjectURL(file),
name: file.name
});
}
}
dl.postActivity({
from: { id: 'userid' },
type: 'message',
attachments: files
})
.subscribe(function (id) {
console.log('files sent');
});
}

Microsoft Bot: Offline DirectLine GSS Unable to post activity and receive data back

I have created a Microsoft bot on-premise (i.e. Hosted bot in IIS and Used Offline Directline for emulation using node package offline-directline-gss).
I am able to chat with the service but the issue I am facing is, since 'ConversationUpdate' doesn't work in webchat, I am posting the activity of type 'conversationupdate', text 'conversationupdate' on page load, and in the bot solution's Post method, I wrote a condition to check if activity.text is equal to 'conversationupdate' and wrote code to send a welcome message. But this is not happening.
In the command prompt which runs index.js, I can see the activity getting posted but the bot solution is not returning anything (or) something.
This the html page code:
<!DOCTYPE html>
<html>
<head>
<meta name="WebPartPageExpansion" content="full" />
<link href="BotChat/botchat.css" rel="stylesheet" />
</head>
<body>
<div id="bot"/>
<script src="Masterfiles/js/jquery-1.11.0.min.js"></script>
<script src="BotChat/botchat.js"></script>
<script>
$(window).on('load', function () {
try
{
botWindowExpandAndCollapse();
}
catch(err)
{
console.log(err.message);
}
});
function botWindowExpandAndCollapse()
{
try
{
var directLine = new BotChat.DirectLine({
secret: params['s'],
user: user,
bot: bot,
token: params['t'],
domain: 'http://127.0.0.1:3000/directline',
webSocket: false // defaults to true
});
directLine
.postActivity({ type: "conversationupdate", from: user, user:user, text:"conversationupdate"})
.subscribe(id => alert("Conversation updated"));
$('#bot .wc-chatview-panel').css('height','50px');
$('#bot .wc-chatview-panel').addClass('IconView');
//Script to hide
$( "<span class='DPfigure need-help'>Need Help</span>" ).insertAfter( ".wc-chatview-panel" );
if ($(".wc-chatview-panel").hasClass("fullHeight"))
{
$(".need-help").hide();
$('#bot .wc-chatview-panel').css('right','17px');
}
else
{
$(".need-help").show();
$('#bot .wc-chatview-panel').css('right','105px');
}
$('.DPfigure').click(function(){
$('#bot .wc-chatview-panel').toggleClass('fullHeight');
$('#bot .wc-chatview-panel').toggleClass('IconView');
if ($(".wc-chatview-panel").hasClass("fullHeight"))
{
$(".need-help").hide();
$('#bot .wc-chatview-panel').css('right','17px');
}
else
{
$(".need-help").show();
$('#bot .wc-chatview-panel').css('right','105px');
}
});
}
catch(err)
{
console.log(err.message);
}
}
var params = BotChat.queryParams(location.search);
debugger;
var user = {
id: Math.random().toString(36).substring(7),
name: params["username"] || 'username'
};
var bot = {
id: params['botid'] || 'botid',
name: params["botname"] || 'botname'
};
window['botchatDebug'] = params['debug'] && params['debug'] === "true";
BotChat.App({
directLine: {
secret: params['s'],
token: params['t'],
domain: 'http://127.0.0.1:3000/directline',
webSocket: false // defaults to true
},
user: user,
bot: bot,
locale: params['locale'],
resize: 'detect'
// sendTyping: true, // defaults to false. set to true to send 'typing' activities to bot (and other users) when user is typing
}, document.getElementById("bot"));
</script>
</body>
</html>
This is the index.js code:
const url = require("url");
const directline = require("offline-directline-gss/dist/bridge");
const express = require("express");
const app = express();
const config = {
localDirectLine: {
hostUrl: "http://localhost",
port: "3000"
},
apbots:[
{
botId:"TestingBot",
botUrl:"http://localhost:3374/api/messages",
"msaAppId": "",
"msaPassword": ""
},
]
};
directline.initializeRoutes(app, config);
command prompt indicating post message is successful:
Can anyone please throw some light on what could be the reason for this. Thank You!

Login with Amazon button to retrieve the customer profile?

<script type='text/javascript'>
window.onAmazonLoginReady = function() {
amazon.Login.setClientId('-your-client-id');
};
</script>
<script type='text/javascript' src='https://static-eu.payments-amazon.com/OffAmazonPayments/uk/sandbox/lpa/js/Widgets.js'></script>
<div id="AmazonPayButton"></div>
<script type="text/javascript">
var authRequest;
OffAmazonPayments.Button("AmazonPayButton", "-emailid-", {
type: "LwA",
authorization: function() {
loginOptions = {
scope: "profile payments:widget payments:shipping_address payments:billing_address", popup: "true"
};
authRequest = amazon.Login.authorize(loginOptions, "return url");
},
onError: function(error) {
// your error handling code
}
});
could you please check and let me know what else i need to amend for retriving the amazon customer profile.
source:
https://payments.amazon.co.uk/developer
Thanks
This code is supposed to pop up a window where the user can login and authorize the scopes you've requested. It will then redirect them to the "return url" you've specified.
The code running under your return URL must be able to take the info provided in the query string attached to the URL and then fetch the profile data from Amazon on the back-end.
I believe the JavaScript you're using defaults to an Implicit grant and will return an access token good for one hour plus a refresh token which can be used to retrieve a new access token when the current one expires.
You can use a current access token to call the profile API and get the profile information.
See their developer documentation and SDKs for different languages at: https://payments.amazon.co.uk/developer/documentation
<script type="text/javascript">
var authRequest;
OffAmazonPayments.Button("AmazonPayButton", "---Your Seller ID---", {
type: "LwA",
authorization: function() {
loginOptions = { scope: "profile payments:widget payments:shipping_address payments:billing_address" };
authRequest = amazon.Login.authorize(loginOptions, function(response) {
amazon.Login.retrieveProfile(response.access_token, function(response) {
alert('Hello, ' + response.profile.Name);
alert('Your e-mail address is ' + response.profile.PrimaryEmail);
alert('Your unique ID is ' + response.profile.CustomerId);
if (window.console && window.console.log)
window.console.log(response);
window.location.href = "--Return Url--";
});
});
}
});
</script>

Resources