MasterCard Payment Gateway API Single Page App - javascript

I am using the Mastercard Payment Gateway API for Hosted Session: Mastercard Payment Gateway API Documentation
The integration works as expected on the first load but this has been written into a single page app. When the user goes back a page via the breadcrumbs (using javascript hash to load 'pages'). When the user then returns to the payment 'page' the Mastercard payment api should then be triggered a second time, this does not happen.
The documentation doesn't say if PaymentSession.configure({}) can be sent more than once but I am assuming that is my issue.
I have tried to 'reset' the PaymentSession and reload the session.js javascript but so far have not been able to get this particular case working. I was wondering if there is a way to 'reset' the configure() or if there was another way to approach this?
I would rather not copy and paste my code in as it's a payment integration although it's pretty much line for line the same as the example on the documentation. I would also say that the issue is unrelated my personal code and more towards how Mastercard's Payment API works and the fact that my website is a single page rather than only loading session.js when needed.

I don't like it when the answer is given by the op, but I have a solution:
$.getScript("<mastercard url + version + merchant id>/session.js", function() {
//PaymentSession && PaymentSession.configure();
});
This uses jQuery to load session.js every time the single page payment hash is called. Once the MasterCard payment script has been executed it then runs the PaymentSession.configure().
My company will be eventually moving away from the MasterCard payment api so this is a suitable solution and doesn't add too much to the page load.
I would still be very interested in learning whether or not this script can be reset another way.

install jquery first then do this in your component
declare const PaymentSession: any;
$.getScript(
<"mastercard url/version/merchantId>/session.js",
function () {
if (PaymentSession) {
PaymentSession.configure({
fields: {
// ATTACH HOSTED FIELDS TO YOUR PAYMENT PAGE FOR A CREDIT CARD
card: {
number: "#card-number",
securityCode: "#security-code",
expiryMonth: "#expiry-month",
expiryYear: "#expiry-year",
nameOnCard: "#cardholder-name",
},
},
session: "xxxxxxxxxxxxxxxx",
//SPECIFY YOUR MITIGATION OPTION HERE
frameEmbeddingMitigation: ["javascript"],
callbacks: {
initialized: function (response) {
console.log(response);
// HANDLE INITIALIZATION RESPONSE
},
formSessionUpdate: function (response) {
// HANDLE RESPONSE FOR UPDATE SESSION
if (response.status) {
if ("ok" == response.status) {
console.log(
"Session updated with data: " +
response.session.id
);
//check if the security code was provided by the user
if (
response.sourceOfFunds.provided.card
.securityCode
) {
console.log(
"Security code was provided."
);
}
//check if the user entered a Mastercard credit card
if (
response.sourceOfFunds.provided.card
.scheme == "MASTERCARD"
) {
console.log(
"The user entered a Mastercard credit card."
);
}
} else if (
"fields_in_error" == response.status
) {
console.log(
"Session update failed with field errors."
);
if (response.errors.cardNumber) {
console.log(
"Card number invalid or missing."
);
}
if (response.errors.expiryYear) {
console.log(
"Expiry year invalid or missing."
);
}
if (response.errors.expiryMonth) {
console.log(
"Expiry month invalid or missing."
);
}
if (response.errors.securityCode) {
console.log(
"Security code invalid."
);
}
} else if (
"request_timeout" == response.status
) {
console.log(
"Session update failed with request timeout: " +
response.errors.message
);
} else if (
"system_error" == response.status
) {
console.log(
"Session update failed with system error: " +
response.errors.message
);
}
} else {
console.log(
"Session update failed: " + response
);
}
},
},
interaction: {
displayControl: {
formatCard: "EMBOSSED",
invalidFieldCharacters: "REJECT",
},
},
});
}
}
);

Related

How to avoid double login in PHP?

I am creating a system where the objective is that only one person per user can access the system, for this I have in my DB two tables called: users and accesses What I am doing is that when person 1 logs in, it is saved in my DB the id of the session in the two tables, if person 2 with the same user tries to access then the first person to log in takes it out of the system. I do this with help with AJAX, comparing if the last user who started has the same session id then he can navigate without problem, if he does not close session.
The problem is that I make this ajax request every 10s, but I would have problems if 10,000 people or more log in, then the request will be sent to the server every 10 seconds and this could saturate the server.
Try an active field if the session is equal to 1 and if the session is equal to 0, then discard this since if the user closes the browser then I never close session and the person will not be able to access, I also tried using a ajax method to detect if you close the browser but it is not very reliable. Has anyone had the same problem? I would thank you a lot.
I leave my php and js code to display as I do:
Code JS:
$(function() {
cron(); // Lanzo cron la primera vez
function cron() {
$.ajax({
method: "POST",
url: "closeuser.php",
data: { action: 1 }
})
.done(function(msg) {
var trimmedString = msg.trim();
console.log(trimmedString)
if( trimmedString == 'success' ) { // Valida si el server devolvió 'success'
location.href='logoutuser.php';
}
});
}
setInterval(function() {
cron();
}, 10000); // cada 10 segundos
});
Code PHP:
<?php
require_once 'Connections/sesionunica.php';
$connection_s = new sesionunica();
if(!isset($_SESSION["id_user"])){
echo"<script>location.href='index.php';</script>";
}
if(isset($_POST["action"])) { // Se pasa una acción
switch(sprintf("%d", $_POST["action"])) { // ¿Qué acción?
case 1:
cerrar();
break;
default:
echo "default";
}
}
function cerrar(){
$ses = session_id();
$connection_s = new sesionunica();
$userById = $connection_s->getUsers($_SESSION["id_user"]);
if ($userById["id_sesion"] <> $ses) {
echo "success";
}
}
?>
In the same way, I cannot use websockets since there are accessibility problems with the server.
I think you could create an "access filter" that would check if the "access token" is valid or not in every request the users would make.
If the "access token" is expired, then return an HTTP status 401 (unauthorized), and, in client-side, redirect the user to login page.
Request filter is a very common resource that many REST frameworks have.

Server Sent Events with ASP.Net is not communicating properly

Im trying to get SSE working. I have a simple web with two buttons. Each one send a POST request to the server that adds a message to a list.
When the eventsource is listening, the server checks the list once each second and sends all the available messages to the client, at the same time that it marks them as readed so they won't be sent again to that client.
It kind of works but does all sorts of weird stuff:
Sometimes the button POST requests are delayed for no apparent reason and then sent all at once.
Sometimes the EventSource restarts itself making a GET request to the server.
Sometimes the server generates an exception when calling Response.Flush() after spamming the buttons: "The remote host closed the connection. The error code is 0x800704CD"
After pressing the buttons a few times, when I try to reload the page, it stays "loading" forever.
After starting the EventSource in javascript it generates a GET request that stays open and after that, any POST request that the buttons send is never sent until the event source GET request ends. Once the EventSource connection ends, all POST requests from the buttons are sent.
I know a lot of things from this code can be improved but I simplified it a lot by leaving just the essential for it to "work".
Also note that:
NotificationSystem.GetNotifications() gets all messages available for the user in a thread safe way.
NotificationSystem.AddNotification() adds the messages.
So here is the server code:
public void GetNotifs() {
try {
Response.ContentType = "text/event-stream";
while(true) {
List<string> Notifs = NotificationSystem.GetNotifications( GetUserId() );
if(Notifs != null && Notifs.Count > 0) {
foreach(var Text in Notifs) {
Response.Write( string.Format( "data: {0}\n\n", Text ) );
}
Response.Flush();
}
Thread.Sleep( 1000 );
}
} catch(Exception ex) {
Response.Close();
}
}
public ActionResult AddButton1() {
NotificationSystem.AddNotification( GetUserId(), "BTN1 (" + GetUserId() + ")" );
return Json( "OK" );
}
public ActionResult AddButton2() {
NotificationSystem.AddNotification( GetUserId(), "BTN2 (" + GetUserId() + ")" );
return Json( "OK" );
}
And the client JS code:
var urlMessages = "/Notifs/GetNotifs";
var urlButton1 = "/Notifs/AddButton1";
var urlButton2 = "/Notifs/AddButton2";
function PushBtn1() {
$.post(urlButton1);
}
function PushBtn2() {
$.post(urlButton2);
}
var myEventSource;
$(document).ready(function () {
myEventSource = new EventSource(urlMessages);
myEventSource.onmessage = function (e) {
console.log(e.data);
$('#EventLog').append("<li>Received: " + e.data + "<li>");
}
});

submitLoginForm() does not send the data to the authentication server - MobileFirst Cordova client

I am trying to write a cordova hybrid application test application on MobileFirst platform. In my challenge handler, I have included a code to send a login information to my authentication server using submitLoginForm() java script API.
I check using wireshark if any auth request to my authentication server is getting generated, but it does not.
Can you please help me identify the issue with my code?
I can see the alert until Inside handleChallenge3, but does not see the alert for Closing Challenge Handler.
One more thing, I am trying to use isCustomResponse() API just to see what kind of challenge/response is coming to my challenge handler, but it seems not to be getting triggered. Has this been deprecated in MobileFirst Platform 8?
Thanks
var LtpaAuthChallengeHandler = function(){
LtpaAuthChallengeHandler = WL.Client.createWLChallengeHandler("LtpaBasedSSO");
LtpaAuthChallengeHandler.isCustomResponse = function(transport) {
alert ("Inside isCustomResponse");
return true;
};
LtpaAuthChallengeHandler.loginResponse = function(response) {
alert ("Inside loginResponse");
LtpaAuthChallengeHandler.submitSuccess();
alert ("After loginResponse");
};
// handleFailure
LtpaAuthChallengeHandler.handleFailure = function(error) {
// WL.Logger.debug("Challenge Handler Failure!");
if(error.failure !== null && error.failure !== undefined){
alert(error.failure);
}
else {
alert("Unknown error");
}
};
LtpaAuthChallengeHandler.handleChallenge = function(challenge) {
alert ("Inside handleChallenge");
var msg = "";
alert ("Inside handleChallenge1");
var options = {
"headers" : {},
"parameters" : {
"username" : "admin",
"password" : "admin",
'login-form-type' : 'pwd'
}
};
alert ("Inside handleChallenge2");
var loginUrl = "<URI for forms based auth of auth server>";
alert ("Inside handleChallenge3");
LtpaAuthChallengeHandler.submitLoginForm (loginUrl, options, LtpaAuthChallengeHandler.loginResponse);
alert ("Closing Challenge Handler");
};
};
Once the credentials have been collected from the UI, use WLChallengeHandler's submitChallengeAnswer() to send an answer back to the security check.
isCustomResponse() is not applicable from MFP 8.0.
Refer to the Authentication and Security topic here.

get facebook user email and user first/last name with Phonegap FB Plugin for IOS app

Working on my first phonegap ios app.
Trying to incorporate this plugin https://github.com/Wizcorp/phonegap-facebook-plugin/tree/master/platforms/ios/www
Basically I just need to alert the users email and first/last name, although I'm a bit stuck on how to do so using this plugin.
What I wanted to do was retrieve that information, then pre populate some forms to create a new user to use with Parse.
I'm able to get a response from this function that displays a status and an authResponse with tokens and the user ID:
var login = function () {
if (!window.cordova) {
var appId = prompt("Enter FB Application ID", "");
facebookConnectPlugin.browserInit(appId);
}
facebookConnectPlugin.login( ["email"],
function (response) { alert(JSON.stringify(response)) },
function (response) { alert(JSON.stringify(response)) });
}
I'm just unsure in terms of next steps on how to go about retrieving the users email and first/lastname..and whther or not I have to dig deeper into facebooks API.
any help is appreciated.
* UPDATED *
Figured it out. I was missing a step that i found over at the facebook api page
var login = function() {
if (!window.cordova) {
facebookConnectPlugin.browserInit('APPID');
facebookConnectPlugin.browserInit(appId);
}
facebookConnectPlugin.login(["email"], function(response) {
if (response.authResponse) {
facebookConnectPlugin.api('/me', null,
function(response) {
alert('Good to see you, ' +
response.email + response.name + '.');
});
}
});
}
Try this plugin(http://plugins.cordova.io/#/package/com.ccsoft.plugin.cordovafacebook) this covers all of your needs.

Parsley remote validate

I have the following input field for username:
<input type="email" class="form-control" id="txt_username" name="username" data-parsley-trigger="change" data-parsley-remote="/User/user_exists" data-parsley-remote-options='{ "type": "POST", "dataType": "json", "data": { "request": "ajax" } }'>
This works fine and calls my PhP function:
public function user_exists()
{
if($this->isAjax())
{
$user = $this->getDatabase()->prepTemplate('SELECT * FROM User WHERE username = ? ', 's', array($_POST['username']), MySqlTemplates::RFQ_FM);
if($user != null)
{
print json_encode("400");
}
else
{
print json_encode("200");
}
}
}
However i am unsure what to do to either deny or allow the validation.
the documentation isnt much of help (atleast i have trouble finding it)
Can anyone give me a push in the right direction?
By default, parsley.remote will consider all 2xx ajax responses as a valid response, and all the others as wrong response.
We have the same concern in our app, leveraging Parsley to tell a user if the username / email he wants is available in our database. To do so, and keep a correct REST API response (200 if user found, 404 if not), you need to tell parsley.remote to do the opposite of this behavior either by:
using data-parsley-remote-reverse="true"
using data-parsley-remote-validator="reverse" to tell to use the reverse validator (exact same thing as above)
last but not least, create your own validator (that we did in our project) for this check:
window.ParsleyExtend.asyncValidators['remote-email'] = function (xhr) {
return xhr.status === 404;
};
and use data-parsley-remote-validator="remote-email"
All that is explained here in the doc.
Hope that helped.
Best
In your php file:
public function user_exists()
{
if($this->isAjax())
{
$user = $this->getDatabase()->prepTemplate('SELECT * FROM User WHERE username = ? ', 's',array($_POST['username']), MySqlTemplates::RFQ_FM);
if($user != null)
{
header("HTTP/1.0 404 Not Found");
}
else
{
header("HTTP/1.1 200 Ok");
}
}
}

Categories