What is causing this error with Square integration - javascript

I'm building my first integration with Squareup.com. In the docs as shown in their walkthrough page (https://developer.squareup.com/docs/payment-form/payment-form-walkthrough), I've copied the code as instructed but I there's an error coming from the 'catch error' in the callbacks.
[update]
OK so having been told applicationID was wrong, we have discovered that its the process-payment file that is empty and that is causing the error. I reinstalled npm and started it and we're chugging along :)
Final questions....
I'm thinking server.js needs to be updated with the data of the specific order. At what stage is it best to do that - presumably when card details are submitted within a hidden parameter. But what name should it be given? I haven't found anything in the docs.
[/update]
Thanks for comments and, in response, here's the complete code.
<body>
<div id="form-container">
<div id="sq-card-number"></div>
<div class="third" id="sq-expiration-date"></div>
<div class="third" id="sq-cvv"></div>
<div class="third" id="sq-postal-code"></div>
<button id="sq-creditcard" class="button-credit-card" onclick="onGetCardNonce(event)">Pay $1.00</button>
</div>
<!-- end #form-container -->
<script type="text/javascript">
const idempotency_key = uuidv4();
// Create and initialize a payment form object
const paymentForm = new SqPaymentForm({
// Initialize the payment form elements
applicationId: "edited-out-for-security",
inputClass: 'sq-input',
autoBuild: false,
// Customize the CSS for SqPaymentForm iframe elements
inputStyles: [{
fontSize: '16px',
lineHeight: '24px',
padding: '16px',
placeholderColor: '#a0a0a0',
backgroundColor: 'transparent',
}],
// Initialize the credit card placeholders
cardNumber: {
elementId: 'sq-card-number',
placeholder: 'Card Number'
},
cvv: {
elementId: 'sq-cvv',
placeholder: 'CVV'
},
expirationDate: {
elementId: 'sq-expiration-date',
placeholder: 'MM/YY'
},
postalCode: {
elementId: 'sq-postal-code',
placeholder: 'Postal'
},
// SqPaymentForm callback functions
callbacks: {
/*
* callback function: cardNonceResponseReceived
* Triggered when: SqPaymentForm completes a card nonce request
*/
cardNonceResponseReceived: function (errors, nonce, cardData) {
if (errors) {
// Log errors from nonce generation to the browser developer console.
console.error('Encountered errors:');
errors.forEach(function (error) {
console.error(' ' + error.message);
});
alert('Encountered errors, check browser developer console for more details');
return;
}
fetch('/cgi-bin/square-payment-processor/process-payment', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
nonce: nonce,
idempotency_key: idempotency_key,
location_id: "edited-out-for-security"
})
})
.catch(err => {
alert('Network error: ' + err);
})
.then(response => {
if (!response.ok) {
return response.json().then(
errorInfo => Promise.reject(errorInfo));
}
return response.json();
})
.then(data => {
console.log(data);
alert('Payment complete successfully!\nCheck browser developer
console for more details');
})
.catch(err => {
console.error(err);
alert('Payment failed to complete!\nCheck browser developer console for more details');
});
}
}
});
paymentForm.build();
//Generate a random UUID as an idempotency key for the payment request
// length of idempotency_key should be less than 45
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// onGetCardNonce is triggered when the "Pay $1.00" button is clicked
function onGetCardNonce(event) {
// Don't submit the form until SqPaymentForm returns with a nonce
event.preventDefault();
// Request a nonce from the SqPaymentForm object
paymentForm.requestCardNonce();
}
</script>
</body>

Related

How to add a process bar when you waiting for a response from the server

could someone help me with one problem? I want to add a process bar when you waiting for a response from the server (Django 3.x).
Step to reproduce:
On the page 'A' we have the form.
Enter data to form.
Submit POST request by clicking to button on the page 'A'.
Waiting for getting the result on the page 'A'.
Get the result on the page 'A'.
So, I want to add process bar after 4th and before 5th points on the page 'A'. When you will get the result on the page 'A' it should disappear.
Python 3.7
Django 3.x
You can use nprogress, it's a library used for progress bars. Use this inside the interceptor where you can config it for displaying only when request is in progress until finished.
There are lots of ways to do this. I think using jquery would be easier. Basically you just need to prevent submitting the page and do an Ajax request to server. something like
<script type='text/javascript'>
$(document).ready(function () {
$("form").submit(function (e) {
// prevent page loading
e.preventDefault(e);
$('#loadinAnimation').show();
// preapre formdata
$.ajax({
type: "yourRequestType",
url: "yourUrlEndpoint",
data: formdata,
success: function (data) {
$('#loadinAnimation').hide();
// do rest of the work with data
}
});
});
});
</script>
and show appropriate loading animation in your html part
<div id='loadinAnimation' style='display:none'>
<div>loading gif</div>
</div>
You can also do it using UiKit Library in Javascript on your Django Template Page.
Below code is when a file is Uploaded
In your template file (template.html)
<body>
..
<form>
<progress id="js-progressbar" class="uk-progress" value="0" max="100" hidden></progress>
...
<div class="uk-alert-danger uk-margin-top uk-hidden" id="upload_error" uk-alert></div>
...
</form>
</head>
<script type="text/javascript">
$(document).ready(function(){
var bar = document.getElementById('js-progressbar');
UIkit.upload('.js-upload-list', {
url: '',
name : "customer-docs",
params :{
"csrfmiddlewaretoken":"{{csrf_token}}"
},
method : "POST",
concurrent:1,
allow:'*.(csv|xlsx)',
beforeSend: function (environment) {
console.log('beforeSend', arguments);
// The environment object can still be modified here.
// var {data, method, headers, xhr, responseType} = environment;
},
beforeAll: function (args,files) {
console.log('beforeAll', arguments);
},
load: function () {
console.log('load', arguments);
},
error: function (files) {
console.log("---------------")
},
complete: function () {
console.log('complete', arguments);
},
loadStart: function (e) {
console.log('loadStart', arguments);
bar.removeAttribute('hidden');
bar.max = e.total;
bar.value = e.loaded;
},
progress: function (e) {
console.log('progress', arguments);
bar.max = e.total;
bar.value = e.loaded;
},
loadEnd: function (e) {
console.log('loadEnd', arguments);
bar.max = e.total;
bar.value = e.loaded;
},
completeAll: function (data) {
console.log('completeAll', arguments);
console.log('completeAll', data);
let redirect_loc = ""
setTimeout(function () {
bar.setAttribute('hidden', 'hidden');
}, 1000);
// This is the response from your POST method of views.py
data.responseText = JSON.parse(data.responseText)
if(data.responseText.status == 201){
// swal is another library to show sweet alert pop ups
swal({
icon: data.responseText.status_icon,
closeOnClickOutside: true,
text: data.responseText.message,
buttons: {
Done: true
},
}).then((value) => {
switch (value) {
case "Done":
window.location.href = ""
break;
}
});
}
else if(data.responseText.status == 500){
swal({
icon: data.responseText.status_icon,
closeOnClickOutside: true,
text: data.responseText.message,
buttons: {
Ok: true
},
}).then((value) => {
switch (value) {
case "Ok":
window.location.href = ""
break;
}
});
}
}
});
// This block of code is to restrict user to upload only specific FILE formats (below example is for CSV & XLSX files)
(function() {
var _old_alert = window.alert;
window.alert = function(e) {
console.log(e)
if(e.includes("csv|xlsx") || e.includes("Invalid file type")) {
$("#upload_error").html("Invalid file format. Valid formats are CSV, XLSX").removeClass('uk-hidden')
}else if(e.includes("Internal Server Error")) {
$("#upload_error").html("Internal Server Error Kindly upload Documents again").removeClass('uk-hidden')
}
else {
_old_alert.apply(window,arguments);
$("#upload_error").addClass('uk-hidden').html("")
}
};
})();
});
</script>
On your views.py you can do your computation and once done, you can return a response like below
resp_json = {
"status" : 201,
"status_icon" : "success",
"url" : "/",
"message": message
}
return HttpResponse(json.dumps(resp_json))
For more info on SWAL (Sweet Alerts), visit https://sweetalert.js.org/guides/

Amount not showing in PayPal payment in Braintree

Hi the amount does not display in paypal when making payment. The JavaScript code is shown below:
var form = document.querySelector('#payment-form');
var client_token = '{{ client_token }}';
braintree.dropin.create({
authorization: client_token,
container: '#bt-dropin',
card: {
cardholderName: {
required: true
}
},
applePay: {
displayName: 'Merchant Name',
paymentRequest: {
label: 'Localized Name',
total: '10.00'
}
},
paypal: {
flow: 'checkout',
amount: '10.00',
currency: 'USD'
},
paypalCredit: {
flow: 'checkout',
amount: '10.00',
currency: 'USD'
},
venmo: true
}, function (createErr, instance) {
if (createErr) {
// Handle any errors that might've occurred when creating Drop-in
console.error(err);
return;
}
form.addEventListener('submit', function (event) {
event.preventDefault();
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Error', err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
From the code, the amount is $10, but does not display in the PayPal payment page. Please what am i doing wrong?
Unless you pass line item information, an amount will not show during the PayPal checkout approval process.
very simple. I included the following to paypal option in the code :
commit: true,

MS BOT Framework (adaptive cards): How to send value (Stepcontext.Value) from directline

I have deployed a Bot in Azure, the Bot displays a welcome message OnMemberAdd. Its adaptive card so the entered value are sent to stepcontext.value. I have integrated it with multiple channels, for directline, I would like to bypass the welcome card and pass the message directly to stepcontext.value so the second prompt is displayed instead of first. I have tried the below but it does not work, please help.
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Send welcome event</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<style>
html,
body {
height: 100%;
}
body {
margin: 0;
}
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat"></div>
<script>
(async function() {
// In this demo, we are using Direct Line token from MockBot.
// Your client code must provide either a secret or a token to talk to your bot.
// Tokens are more secure. To learn about the differences between secrets and tokens
// and to understand the risks associated with using secrets, visit https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication?view=azure-bot-service-4.0
const { token } = { token};
// We are using a customized store to add hooks to connect event
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'userInfo',
value: { fname:'user', lname:'test', pnumber:'0678775453'}
}
});
}
return next(action);
});
const styleOptions = {
botAvatarImage:
'',
botAvatarInitials: 'Chatbot',
userAvatarImage: '',
userAvatarInitials: 'User',
showNub: true,
bubbleFromUserNubOffset: 'bottom',
bubbleFromUserNubSize: 10,
bubbleFromUserBorderColor: '#0077CC',
bubbleNubOffset: 'top',
bubbleNubSize: 0,
bubbleBorderColor: '#009900',
sendBoxButtonColor: '#009900',
hideUploadButton: true,
hideSendBox : true
};
window.WebChat.renderWebChat(
{
directLine: window.WebChat.createDirectLine({ token }),
store,
styleOptions
},
document.getElementById('webchat')
);
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>
I have tried to send the data via postman and it works well but when I do it using above code it does not work.
Postman body
{
"type": "message",
"from": {
"id": "user1"
},
"value":
{
"fname":"user",
"lname":"test",
"pnumber":"0678787543"
}
}
You're so close! You have two options:
Change to WEB_CHAT/SEND_EVENT and include the name property:
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'userInfo',
value: { fname:'user', lname:'test', pnumber:'0678775453'}
}
});
}
return next(action);
});
Use WEB_CHAT/SEND_MESSAGE, include the text property, and change to channelData:
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_MESSAGE',
payload: {
text: 'userInfo',
channelData: { fname:'user', lname:'test', pnumber:'0678775453'}
}
});
}
return next(action);
});
===
Update
I can see it coming through just fine using your code. Put a breakpoint in onTurn/OnTurnAsync and you'll see that when a user connects you get:
conversationUpdate for the bot
conversationUpdate for the user
WebChat's Event with the user data you want:

how to send a message to direct line chat bot from the UI using JavaScript

I'm developing a chat bot (v4 using MS Azure bot framework & QnAmaker),
I've added a feature in that, i.e. while the users starts typing the questions, the bot will get prompt and show the relevant questions form the QnAmaker , and the user can select one of them , then that particular question will sent to the bot.
Following is the full code which I'm using,
<html>
<body>
<div id="webchat" role="main"></div>
<script>
(async function () {
const styleOptions = {
hideUploadButton: true,
bubbleBackground: '#D8F4FF',
bubbleFromUserBackground: '#E8E8E8',
botAvatarImage: '../botavatar.PNG',
botAvatarInitials: 'bot',
userAvatarInitials: initial,
userAvatarImage: userimg,
rootHeight: '100%',
rootWidth: '50%'
};
const styleSet = window.WebChat.createStyleSet({
bubbleBackground: 'rgba(0, 0, 255, .1)',
bubbleFromUserBackground: 'rgba(0, 255, 0, .1)'
});
styleSet.textContent = {
fontFamily: "'Comic Sans MS', 'Arial', sans-serif",
fontWeight: 'bold'
};
const secret = secret;
const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate',
{
headers: {
Authorization: `Bearer ${secret}`,
},
method: 'POST'
});
const { token } = await res.json();
const store = window.WebChat.createStore(
{},
({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'webchat/join',
}
});
}
return next(action);
}
);
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
store,
styleOptions,
userID: emailid,
username: fullname,
locale: 'en-US',
userAvatarInitials: initial
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
document.querySelectorAll('[aria-label="Sendbox"]')[0].placeholder = "Type your question and press enter";
$("[aria-label='Sendbox']").keypress(function () {
if ($("[aria-label='Sendbox']")[0].defaultValue.length > 4) {
getquestion(this.value);
} else {
$('#ques').remove();
}
});
$('div.probing').click(function () { alert(this.innerText); });
$('div.probing').click(function () {
document.querySelectorAll('[aria-label="Sendbox"]')[0].value = (this.innerText);
document.querySelectorAll('[aria-label="Sendbox"]')[0].defaultValue = (this.innerText);
$('.css-115fwte').trigger('click');
$('#ques').remove();
});
})().catch(err => console.error(err));
function getquestion(value) {
var token = secret;
var questionquery =
{
question: value,
top: 2,
scoreThreshold: 50,
"strictFilters": [
{
"name": "message",
"value": "text"
}],
}
$.ajax({
type: "POST",
url: "https://endpoint/qnamaker/knowledgebases/KBID/generateAnswer",
data: JSON.stringify(questionquery),
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', secret);
},
dataType: "json",
contentType: "application/json",
success: function (data) {
var questions = "";
$('#ques').remove();
for (var i = 0; i < 4; i++) {
if (data.answers[0].questions[i] != null && data.answers[0].questions[i] != 'undefined')
questions = questions + "<div class='probing'>" + data.answers[0].questions[i] + "</div>";
}
$('.content').last().append("<div id='ques'>" + questions + "</div>");
$('div.probing').click(function () {
document.querySelectorAll('[aria-label="Sendbox"]')[0].value = (this.innerText);
document.querySelectorAll('[aria-label="Sendbox"]')[0].defaultValue = (this.innerText);
$('.css-115fwte').trigger('click');
$('#ques').remove();
});
},
error: function (data) {
alert(data.responseText);
}
});
}
</script>
</body>
</html>
Please check the below image of my bot with the prompted questions, it will look like this, these questions are get appended to the last reply given by the bot, after selecting the question, this div will get removed. On the next question this cycle will continue again.
Problem I'm facing is here, with the following code the value is getting entered in the input box, however the bot does not received any question, and hence it failed to answer.
$('div.probing').click(function () {
document.querySelectorAll('[aria-label="Sendbox"]')[0].value = (this.innerText);
document.querySelectorAll('[aria-label="Sendbox"]')[0].defaultValue = (this.innerText);
$('.css-115fwte').trigger('click');
$('#ques').remove();
});
With this code the value is getting entered in the input box, however the bot does not received any question, and hence it failed to answer.
this is how it will in console after adding the question by script.
Note that I've used all the required reference JS and CSS Files in my code.
So please help me with the correct approach to achieve my requirement, Thanks in Advance.
Here's a working demo that should get you started, using a similar method from the sample:
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Programmatic access to post activity</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!--
This CDN points to the latest official release of Web Chat. If you need to test against Web Chat's latest bits, please refer to pointing to Web Chat's MyGet feed:
https://github.com/microsoft/BotFramework-WebChat#how-to-test-with-web-chats-latest-bits
-->
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<style>
html,
body {
height: 100%;
}
body {
margin: 0;
}
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat" role="main"></div>
<script>
(async function () {
// In this demo, we are using Direct Line token from MockBot.
// Your client code must provide either a secret or a token to talk to your bot.
// Tokens are more secure. To learn about the differences between secrets and tokens
// and to understand the risks associated with using secrets, visit https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication?view=azure-bot-service-4.0
// We are creating the Web Chat store here so we can dispatch WEB_CHAT/SEND_MESSAGE action later.
const store = window.WebChat.createStore();
window.WebChat.renderWebChat(
{
directLine: window.WebChat.createDirectLine({ token: '<your token>' }),
// We are passing our own version of Web Chat store.
store
},
document.getElementById('webchat')
);
document.querySelector('#webchat > *').focus();
// THIS IS THE IMPORTANT STUFF
const sendbox = document.querySelector("[aria-label='Sendbox']");
function removeQuestions() {
const questionDivs = document.querySelectorAll('.questions');
questionDivs.forEach((div) => {
div.remove();
})
}
// This ensures that we create unique listeners for each question
let totalQuestions = 0;
// Track the keypress events in the Send Box
sendbox.addEventListener('keypress', () => {
if (sendbox.defaultValue.length > 4) {
getQuestion();
} else {
removeQuestions();
}
});
// Send a message containing the innerText of the target element
function send(event) {
store.dispatch({
type: 'WEB_CHAT/SEND_MESSAGE',
payload: { text: event.currentTarget.innerText }
});
event.currentTarget.remove();
}
// This generates some test questions
function getQuestion() {
// Create questions div
const questions = document.createElement('DIV');
questions.setAttribute('class', 'questions');
document.querySelector('.content').appendChild(questions);
// Generate test questions
for (var i = 0; i < 4; i++) {
// Create question div
const question = document.createElement('DIV');
question.setAttribute('id', `question${totalQuestions}`);
question.setAttribute('class', 'probing');
question.innerText = `this is a test ${totalQuestions}`;
questions.appendChild(question);
// Create listener for question
const element = document.querySelector(`#question${totalQuestions}`);
element.addEventListener('click', send, false);
totalQuestions++;
}
}
})().catch(err => console.error(err));
</script>
</body>
</html>
There are likely more elegant ways to do this, but I wanted to get an answer out to you ASAP.
Note: I used vanilla javascript over jQuery to cut down on page load times and because I'm more familiar with it.

Paypal express checkout button

I am integrating Paypal express checkout button on my site and I have the following code:
paypal.Button.render({
env: 'sandbox', // Optional: specify 'sandbox' environment
style: {
size: 'medium',
color: 'blue',
shape: 'rect'
},
payment: function(resolve, reject) {
var CREATE_PAYMENT_URL = 'http://example.com/create-payment';
paypal.request.post(CREATE_PAYMENT_UR)
.then(function(data) {
resolve(data.paymentID);
})
.catch(function(err) {
reject(err);
});
},
onAuthorize: function(data) {
// Note: you can display a confirmation page before executing
var EXECUTE_PAYMENT_URL = 'http://example.com/execute-payment';
paypal.request.post(EXECUTE_PAYMENT_URL, {
paymentID: data.paymentID,
payerID: data.payerID,
})
.then(function(data) { /* Go to a success page */ })
.catch(function(err) { /* Go to an error page */ });
}
}, '#paypal-button');
I want to set the payment and onAuthorize separately. Is there any way to do it?
Something like: paypal.Button.onAuthorize = function() { };
You can create the functions separately, if it helps
function payment() {
...
}
function onAuthorize() {
...
}
paypal.Button.render({
payment: payment,
onAuthorize: onAuthorize
});

Categories