Paypal v2 express checkout integration in .NET - paypal

I am currently checking integration process of v2 express checkout and lot of documentation making confusion.
So far i am using checkout.js from paypal domain and using below code for order creation in client side as below
paypal.Button.render({
env: 'sandbox', // Or 'sandbox',
commit: true, // Show a 'Pay Now' button
style: {
color: 'gold',
shape: 'rect',
label: 'paypal',
size: 'medium',
tagline: false,
width: 150
},
payment: function (data, actions) {
/* Set up a url on your server to create the payment */
var CREATE_URL = '/paypal/createpaypalPayment';
/* Make a call to your server to set up the payment */
return paypal.request.post(CREATE_URL)
.then(function ({ result }) {
var test = JSON.parse(result);
return test.id;
});
},
onAuthorize: function (data, actions) {
/* Set up a url on your server to execute the payment */
var EXECUTE_URL = '/paypal/executepaypalPayment';
/* Set up the data you need to pass to your server */
var data = {
paymentID: data.paymentID,
payerID: data.payerID
};
return paypal.request.post(EXECUTE_URL, data)
.then(function (res) {
return null;
});
}
}, '#paypalcheckout');
});
Please find the server side code for create order.
[HttpPost]
public JsonResult createpaypalpayment()
{
var client = new WebClient();
string credentials = clientid + secretid;
client.Headers.Add("authorization", "Basic " + credentials);
client.Headers.Add("content-type", "application/json");
client.Headers.Add("accept-language", "en_US");
client.Headers.Add("accept", "application/json");
var body = #"{
""intent"": ""AUTHORIZE"",
""purchase_units"": [{
""amount"": {
""currency_code"": ""USD"",
""value"": ""100.00""
}
}]
}";
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var response = client.UploadString("https://api.sandbox.paypal.com/v2/checkout/orders/", "POST", body);
return Json(new { result = response }, JsonRequestBehavior.AllowGet);
}
}
}
I referred below documentation
https://developer.paypal.com/docs/archive/orders-integration-guide/#integration-steps
I am struct with how to show order details after order creation and get approval from customer end ?
Can anyone provide suggestion for this.
Thanks in advance

checkout.js is deprecated and that documentation is archived, so my suggestion is that you follow the current documentation on developer.paypal.com
In your other question, links were provided to that documentation.

Related

Cookie does not appear to be sent via fetch or hapi server is unable to receive cookie

So I have a simple backend server created with Hapi API and the frontend I'm using fetch. These are on different ports so I have CORs enabled and all the sweet stuff. I'm currently trying to set a refresh token in the browser using a http only cookie. As far as I can verify, the http only cookie is being set in the browser when login function is completed. I'm currently trying to send the http only cookie back to the server so I can set up the refresh token route and I can't seem to send or even verify that http token is sent back to the server.
Here's the server setting.
"use strict";
require("dotenv").config();
const Hapi = require("#hapi/hapi");
const Jwt = require("#hapi/jwt");
const routes = require("./routes/routes");
exports.init = async () => {
const server = Hapi.server({
port: 3000,
host: "localhost",
routes: {
cors: {
origin: ["*"],
credentials: true,
},
},
});
require("./models");
await server.register(Jwt);
server.auth.strategy("jwt", "jwt", {
keys: { key: process.env.SECRET_KEY, algorithms: ["HS256"] },
verify: { aud: false, iss: false, sub: false, exp: true },
validate: false,
});
server.state("refresh", {
ttl: 1000 * 60 * 60 * 24,
isSecure: true,
isHttpOnly: true,
encoding: "base64json",
clearInvalid: true,
strictHeader: true,
isSameSite: "None",
});
server.route(routes);
return server;
};
process.on("unhandledRejection", (err) => {
console.log(err);
process.exit(1);
});
Here's the login request and returns the http only cookie. This part works, the http cookie is returned and set.
const validateUserAndReturnToken = async (req, h) => {
const user = await User.findOne({
$or: [{ email: req.payload.username }, { username: req.payload.username }],
});
if (user) {
const match = await bcrypt.compare(req.payload.password, user.passwordHash);
if (match) {
const token = await createToken(match);
const refreshToken = await createRefreshToken(match);
h.state("refresh", refreshToken);
return { id_token: token, user: formatUser(user) };
} else {
throw boom.notAcceptable("Username and password did not match.");
}
} else {
throw boom.notAcceptable("Username or email was not found.");
}
};
Here's the fetch request I'm using to test sending a http cookie only back. I have credential: include so I don't know what is problem?
import type { DateInfo } from "#/stores/application";
const api = "http://localhost:3000/report";
let token = localStorage.getItem("user-token");
const headers = new Headers();
headers.append("Authorization", `Bearer ${token}`);
headers.append("Content-Type", "application/json");
export const getJobReport = async (dateFilter: DateInfo) => {
let response = await fetch(
`${api}/${dateFilter.startDate}/${dateFilter.endDate}`,
{
method: "GET",
headers,
credentials: "include",
}
);
return await response.json();
};
I have checked the application tab as well as the network request so I know set cookie is being sent and set on the browser. The problem is I can't seem to get the cookie back from the browser when fetch request is sent back to the server.
Here's the code I'm using to just check the existence of the cookie. According to Hapi Doc , req.state[cookie-name] which in this case is 'refresh' should have the cookie value. Refresh is returning undefined so I went up one level and check for req.state and gets an empty object {}.
route
{
method: "GET",
path: "/report/{startDate}/{endDate}",
options: {
auth: "jwt",
state: {
parse: true,
failAction: "error",
},
validate: {
params: Joi.object({
startDate: Joi.string(),
endDate: Joi.string(),
}),
},
},
handler: handlers.report.getJobApplicationReport,
},
handler
const getJobApplicationReport = async (req, h) => {
console.log("TEST", req.state);
const start = new Date(req.params.startDate);
const end = new Date(req.params.endDate);
try {
const applications = await Application.find({
dateApplied: { $gte: start, $lt: end },
});
// 'Applied', 'In Process', 'Rejected', 'Received Offer'
const total = applications.length;
let rejectedCount = 0;
let inProcessCount = 0;
applications.forEach((app) => {
if (app.status === "Rejected") {
rejectedCount++;
}
if (app.status === "In Process") {
inProcessCount++;
}
});
return {
total,
rejectedCount,
inProcessCount,
};
} catch (error) {
console.log(error);
throw boom.badRequest(error);
}
};
I've looked through all the Hapi documentation, fetch documentation and stackoverflow question/answers but can't seem to find a solution. I can't verify whether it's the fetch request that's not sending the http only cookie or the server setting that's not parsing it. Any help to determine the issue or solution would be greatly appreciated.
I've looked through all the Hapi documentation, fetch documentation and stackoverflow question/answers but can't seem to find a solution. I can't verify whether it's the fetch request that's not sending the http only cookie or the server setting that's not parsing it. Any help to determine the issue or solution would be greatly appreciated.

Braintree PCI compliance issue

I have been continuously getting an email by brain tree on PCI Compliance regards and need confirmation on following two things which have been asked.
What is the Braintree payment integration method on our website? (Hint: It’s one of these)
Drop in UI or hosted field
Braintree SDK Custom integration
Following is the javascript code we've used . I went through the Braintree site on this regards but couldn't conclude upon this.
Additional Notes : We've made some changes on braintree vendor file.
var subscribed_user = "1";
$('#cc').on('click', function (e) {
$('#cc-info').show().attr('aria-hidden', true).css('visibility', 'visible');
});
var button = document.querySelector('#paypal-button');
var button1 = document.querySelector('#card-button');
var form = document.querySelector('#checkout-form');
var authorization = 'AuthHeaderxxxxxxxx=';
// Create a client.
braintree.client.create({
authorization: authorization
}, function (clientErr, clientInstance) {
// Stop if there was a problem creating the client.
// This could happen if there is a network error or if the authorization
// is invalid.
if (clientErr) {
console.error('Error creating client:', clientErr);
return;
}
/* Braintree - Hosted Fields component */
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {
'font-size': '10pt',
'color': '#e3e3e3 !important; ',
'border-radius': '0px'
},
'input.invalid': {
'color': 'red'
},
'input.valid': {
'color': 'green'
}
},
fields: {
number: {
selector: '#card-number',
placeholder: '4111 1111 1111 1111',
},
cvv: {
selector: '#cvv',
placeholder: '123'
},
expirationDate: {
selector: '#expiration-date',
placeholder: '10/2019'
}
}
}, function (hostedFieldsErr, hostedFieldsInstance) {
if (hostedFieldsErr) { /*Handle error in Hosted Fields creation*/
return;
}
button1.addEventListener('click', function (event) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (tokenizeErr, payload) {
if (tokenizeErr) { /* Handle error in Hosted Fields tokenization*/
document.getElementById('invalid-field-error').style.display = 'inline';
return;
}
/* Put `payload.nonce` into the `payment-method-nonce` input, and thensubmit the form. Alternatively, you could send the nonce to your serverwith AJAX.*/
/* document.querySelector('form#bt-hsf-checkout-form input[name="payment_method_nonce"]').value = payload.nonce;*/
document.querySelector('input[name="payment-method-nonce"]').value = payload.nonce;
form.submit();
button1.setAttribute('disabled', 'disabled');
});
}, false);
});
// Create a PayPal component.
braintree.paypal.create({
client: clientInstance,
paypal: true
}, function (paypalErr, paypalInstance) {
// Stop if there was a problem creating PayPal.
// This could happen if there was a network error or if it's incorrectly
// configured.
if (paypalErr) {
console.error('Error creating PayPal:', paypalErr);
return;
}
if ($('select#paypal-subs-selector option:selected').val() == '') {
button.setAttribute('disabled', 'disabled');
}
$('select#paypal-subs-selector').change(function () {
if ($('select#paypal-subs-selector option:selected').val() == '') {
button.setAttribute('disabled', 'disabled');
} else {
// Enable the button.
button.removeAttribute('disabled');
}
});
button.addEventListener('click', function () {
if(subscribed_user) {
// Popup Error for changing subscription.
swal({
html: true,
title: "",
text: "You are cancelling in the middle of subscription.<br/>If you do so you will not be refunded remaining days of your subscription.",
confirmButtonColor: '#605ca8',
confirmButtonText: 'Yes',
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Proceed !",
closeOnConfirm: true
}, function (isConfirm) {
if (isConfirm) {
show_payment_methods(paypalInstance);
}
});
} else{
show_payment_methods(paypalInstance);
}
}, false);
});
});
Any help would be highly appreciated.
Your code says Braintree - Hosted Field component And you don’t use anything like this which I found by searching “Braintree api”. I think you’re safe to say you use hosted fields.

When I launch an event, this call to the intent but not show in the client app

I have this event:
Image of the intent
And I have this code in the Fullfillment:
function LanzarEvento(session) {
//var user = firebase.auth().currentUser;
const uuid = require('uuid');
const sessionId = uuid.v1();//user.uid;
// Imports the Dialogflow library
const dialogflow = require('dialogflow');
// Instantiates a sessison client
const sessionClient = new dialogflow.SessionsClient();
// The path to identify the agent that owns the created intent.
const sessionPath = session;//sessionClient.sessionPath(projectId, sessionId);
console.log('sessionPath -> ' + sessionPath);
let responseToUser = {
'fulfillmentText': 'Voy a buscar los mejores alojamientos, dame unos segundos.'
};
sendResponse(responseToUser);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
event: {
name: 'PruebaEvento',
parameters: jsonToStructProto({user_name: 'Andres',name: 'Andres'}),
languageCode: languageCode,
},
},
};
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
logQueryResult(sessionClient, responses[0].queryResult);
})
.catch(err => {
console.error('ERROR:', err);
});
}
And this is the conversation in the Training section of Dialogflow:
Trainning capture
How you can see, the event was returning "Hola Andres", but this never appears in the Facebook Messenger or in the Slack.
Please, I need your help. Can you help me?
Thanks in advance,
Andrés Gilabert

SAPUI5 and NW Portal

I have an SAPUI5 application deployed on my portal.
I am trying get the user login logged on portal in my SAPUI5.
But when I run my application it is not get any data.
Bellow is my code
sap.ui.define([
'jquery.sap.global',
'sap/ui/core/Fragment',
'sap/ui/core/mvc/Controller',
'sap/ui/model/Filter',
'sap/ui/model/json/JSONModel'
], function(jQuery, Fragment, Controller, Filter, JSONModel) {
"use strict";
var CController = Controller.extend("sap.m.ZHRUI001.C", {
inputId: '',
valueHelpRequest: function(oController) {
this.inputId = oController.oSource.sId;
var sServiceUrl = "http://<my server host>:<my server port>/sap/bc/ui2/start_up";
var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, true, "user", "password");
var oJsonModel = new sap.ui.model.json.JSONModel();
oModel.read("/?", null, null, true, function(oData, response) {
oJsonModel.setData(oData);
});
sap.ui.getCore().setModel(oJsonModel);
// Handling of both confirm and cancel; clear the filter
var that = this;
var handleClose = function(oEvent) {
var oSelectedItem = oEvent.getParameter("selectedItem");
if (oSelectedItem) {
that.byId(that.inputId).setValue(oSelectedItem.getTitle());
}
oEvent.getSource().getBinding("items").filter([]);
};
// Create a SelectDialog and display it; bind to the same
// model as for the suggested items
if (!this._valueHelpSelectDialog) {
this._valueHelpSelectDialog = new sap.m.SelectDialog("valueHelpSelectDialog", {
title: "{fullName}",
items: {
template: new sap.m.StandardListItem({
title: "{fullName}",
active: true
})
},
search: function(oEvent) {
var sValue = oEvent.getParameter("value");
var oFilter = new sap.ui.model.Filter(
"name",
sap.ui.model.FilterOperator.Contains, sValue
);
oEvent.getSource().getBinding("items").filter([oFilter]);
},
confirm: handleClose,
cancel: handleClose
});
this._valueHelpSelectDialog.setModel(oJsonModel);
} else {
this._valueHelpSelectDialog.setModel(oJsonModel);
}
this._valueHelpSelectDialog.open();
}
});
return CController;
});
From what I'm reading you are speaking of a SAP Portal, I expect you have a 7.3+ version.
I have found the SAP doc you used to find the user, be careful because this is not the code for a SAPUI5 application running on a portal but for one running on a R/3 system, the endpoint /sap/bc/ui2/start_up doesn't exist on a NetWeaver portal.
What you could do is develop a simple REST service (by developping a Servlet) that will send back the user and all the details that you need.
These details can be found in the PortalComponentRequest which holds a IUser object, you can find a sample portal servlet on my Git here :
https://gitlab.com/Almiriad/sap-portal-samples
You simply have to send a GET request to the url
http[s]://youserver:your port/irj/servlet/prt/portal/prtroot/UserServletSample.UserInfoSampleServlet
and you'll get a JSo
{
"user": {
"user-name":"<LASTNAME>, <FIRSTNAME>",
"user-id":"<USER_ID>",
"user-email":"<USER#EMAIL.COM>"
}
}
I hope this will help you.
`
var oUserData;
var y = "/sap/bc/ui2/start_up";
var xmlHttp = null;
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
oUserData = JSON.parse(xmlHttp.responseText);
}
};
xmlHttp.open("GET", y, false);
xmlHttp.send(null);
`
console oUserData to get login details of that user who logged in.

Using QUnit and sinon.spy, how can I access my spy within an async callback?

I am new to QUnit and sinon.js and working to build tests for an ember-cli package. I am having problems getting sinon.spy(Ember.run, 'later') to work with the code below. inside the callback Ember.run.later is not being spied / has no .getCalls() etc...
How can I handle this type of test?
test('#authenticate rejects with invalid credentials', function() {
sinon.spy(Ember.run, 'later');
var jwt = JWT.create(),
expiresAt = (new Date()).getTime() + 60000;
var token = {};
token[jwt.identificationField] = 'test#test.com';
token[jwt.tokenExpireName] = expiresAt;
token = window.btoa(JSON.stringify(token));
var credentials = {
identification: 'username',
password: 'password'
};
App.server.respondWith('POST', jwt.serverTokenEndpoint, [
400,
{
'Content-Type': 'application/json'
},
'{"message":["Unable to login with provided credentials."]}'
]);
Ember.run(function(){
App.authenticator.authenticate(credentials).then(null, function(){
// Check that Ember.run.later was not called.
equal(Ember.run.later.getCall(0), null);
});
});
Ember.run.later.restore();
});
PS I currently am able to get this working by moving the sinon.spy and corresponding Ember.run.later.restore() to the module.setup() and module.teardown() methods respectively. Is there anything wrong with that that strategy other than it means they are spied for every test in my suite?
Thanks!
EDIT: Here is my authenticate method:
authenticate: function(credentials) {
var _this = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
var data = _this.getAuthenticateData(credentials);
_this.makeRequest(_this.serverTokenEndpoint, data).then(function(response) {
Ember.run(function() {
var tokenData = _this.getTokenData(response),
expiresAt = tokenData[_this.tokenExpireName];
_this.scheduleAccessTokenRefresh(expiresAt, response.token);
response = Ember.merge(response, { expiresAt: expiresAt });
resolve(_this.getResponseData(response));
});
}, function(xhr) {
Ember.run(function() {
reject(xhr.responseJSON || xhr.responseText);
});
});
});
},