PayPal IPN validation - validation

Following is from PayPal Order Management Integration Guide:
Processing the PayPal Response to Your Postback
PayPal responds to your postbacks with a single word in the body of the response: VERIFIED
or INVALID.
When you receive a VERIFIED postback response, perform the following checks on data in
the IPN:
Check that the payment_status is Completed.
If the payment_status is Completed, check the txn_id against the previous PayPal
transaction that you processed to ensure it is not a duplicate.
Check that the receiver_email is an email address registered in your PayPal account.
Check that the price, carried in mc_gross, and the currency, carried in mc_currency, are correct for the item, carried in item_name or item_number.
After you complete the above checks, notification validation is complete. You can update your database with the information provided, and you can initiate other appropriate automated back-end processing.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_cart" />
<input type="hidden" name="upload" value="1" />
<input type="hidden" name="business" value="GXLC9H9VFPLQE">
.....
<input type="submit" name="Submit" value="Submit" />
</form>
In step 3 I should check receiver_email, but I don't want to.
I don't want to keep my paypal account email in my application.
My question is: can I check business variable instead?

I have an answer here:
The 'checks' provided are just recommendation and not a requirement to use the IPN. You can check for "business" instead of "receiver_email". However, if you pass in the form, the value of "business" that is returned to you in the IPN will be the merchant email address on your account while the value of "receiver_id" will be GXLC9H9VFPLQE.
So if you want to check for your merchant ID instead of email address, then check for "receiver_id".

Related

Opayo (SagePay) Amex payments fail since 3DSv2 (Using Direct V4)

Is anybody else having issues taking Amex payments with Opayo (SagePay) Direct protocol V4 since the 6th July?
Everything was fine before then, seems to be related to 3DSv2 but I'm successfully using the V4 protocol and taking 3DSv2 payments against Visa/Mastercard.
I get all the way through the transaction including successfully completing the 3DSv2/Safekey pages and then when I pass the CRes back to Opayo I get a "5086 : Unexpected CRes" response
When I base64 decode the CRes I get the below. (trimmed to remove full ID's)
{"threeDSServerTransID":"5bfe447a-5443-...","acsTransID":"00f9a54d-84f0-...","messageType":"CRes","messageVersion":"2.1.0","transStatus":"N"}
The data I send to SafeKey looks like the below (form auto submits with JS) threeDSSessionData is the VPSTxID base64 encoded including the {} brackets
<form name="form" action="https://acs-safekey.americanexpress.com/GravityACS/processing3ds" method="POST">
<input type="hidden" name="TermUrl" value="https://...?action=return3d&VendorTxCode=XXX">
<input type="hidden" name="creq" value="ewog...ICIwMiIKfQ">
<input type="hidden" name="threeDSSessionData" value="ezg1NTA5MzM.......UU1OH0=">
<input class="button" type="submit" value="Continue">
</form>
The transStatus:N response makes me wonder if its something on the way to SafeKey and Opayo aren't handling the decline? i.e. is it because I'm doing the following and hence they are declining the transaction - but then wouldn't it do that before it got to 3DS?
COFUsage=FIRST&InitiatedType=CIT&MITType=UNSCHEDULED
Thanks
Dave

Opayo 3ds2 - sagepay PI integration rsa3dsauth.co.uk fails to return the threeDSSessionData

Opayo returns from our payment request asking us to contact https://www.rsa3dsauth.co.uk/3ds2/cReqWebBased?issuer=barclays" for 3D Secure auth, so we send this:
<form id="c-form" method="POST" action="https://www.rsa3dsauth.co.uk/3ds2/cReqWebBased?issuer=barclays">
<input type="hidden" name="creq" value="*removed for data protection*" />
<input type="hidden" name="threeDSSessionData" value="tQtpVHCcCVGEhPNDaeCtMK9I%2fREJERnarovmuZPsM4M6xy6gks9rOYix36waoxOn1wukcobCFbfd2jpmVDVDwZjrd3MzJtmpyFDEAu5R9azVveH6kBEXc5F2ETnFijQfEj5l6EzmH7EnMzbTlFHgbkDGR%2fH9CtURo0K2VSUKHN4%3d" />
<script>
document.addEventListener("DOMContentLoaded", function()
{
var b = document.getElementById("c-form");
b && b.submit();
});
</script>
</form>
And we get back
POST https://xxxxx.xxxxxxx.xxx/api/payment/3dsecurechallenge?eid=ctl00_cphMain_Payment_SagePay_ThreeD
cres=*removed for data protection*&threeDSSessionData=
Note there is nothing following &threeDSSessionData=, where it should be returning our string back to us.
The documentation says:
Anyone else having this issue?
Just to add some more context - we had the same issue but only with rsasecure.co.uk at the start of June. Other banks worked correctly. We have an open case with Opayo about this but there has not been a lot of communication.
We turned off 3DS while this issue is occurring but have been advised to try again today (23.07.21) as it may have been an issue at the banks side.
threeDSSessionData seems to be URL encoded in the input tag. Have you tried this without the URL encoding? I believe it should only be base64 encoded.
I've now received a response from Opayo. I also think they may have changed something because I'm positive I tried this previously and it didn't work...
threeDSSessionData is the base64 encoded of VPSTxId (including the curled braces). It is not base64url encoded - talking about url encoding is a massive red herring because the browser auto submit handles this without us having to do anything.
Here's an example that worked for me.
I curl post the card details to vpsdirect-register.vsp (or whatever flavour you're using). This must include a ThreeDSNotificationURL value that contains the URL of the your callback page.
The following response was received.
Status=3DAUTH
StatusDetail=StatusDetail=2021 : Please redirect your customer to the ACSURL, passing CReq.
VPSTxId={1F3F8015-FFEB-E897-0643-58841AD5DB03}
ACSURL=https://test.sagepay.com/3ds-simulator/html_challenge
CReq=ewogICJtZXNzY...iA6ICIwNSIKfQ
I base64 encode the VPSTxId value into a threeDSSessionData value and get the customers browser to autosubmit the following form
<form action="https://test.sagepay.com/3ds-simulator/html_challenge" method="post" id="autopostform">
<input type="hidden" name="threeDSSessionData" value="ezFGM0Y4MDE1LUZGRUItRTg5Ny0wNjQzLTU4ODQxQUQ1REIwM30=">
<input type="text" name="creq" value="ewogICJtZXNzY...iA6ICIwNSIKfQ">
</form>
Customer will then do the necessary gubbins and the callback URL will have something similar to the following posted to it
cres=ewogICJtZXNzYWd...OiAiWSIKfQ
threeDSSessionData=ezFGM0Y4MDE1LUZGRUItRTg5Ny0wNjQzLTU4ODQxQUQ1REIwM30=
Both of these values are base64 encoded (the cres actually contains the acsTransID that was in the original response). We now need to base64 decode the threeDSSessionData back into a VPSTxId which we then need to curl post along with the (still encoded) cres value.
VPSTxId={1F3F8015-FFEB-E897-0643-58841AD5DB03}
CRes=ewogICJtZXNzYWd...OiAiWSIKfQ
Hopefully that'll give us a successful response and the transaction should go through.
In short it's a complete pita. In reality the encoding element should be dealt with via Opayo's API rather than us needing to code this up.
Edit: Original Reply
Yes! We flicked over to v4 with 3DSv2 last week and have had a couple of dozen customers reporting that they try to pay, and basically just returned back to the checkout. Looking at one now for barclays, but have had others too - including one where they 3dauth and don't get returned to our checkout at all...

How to test CAS with jmeter?

request:
I send a "get" http request, has no parameters;
path: http://192.168.22.139:8080/KSP
response:
<input id="username" type="text" name="username" required/>
<input id="password" type="password" name="password" required/>
<input type="hidden" name="lt" value="LT-697-vbNmm6NKOZ0cd7Wg1ywzbMKLa0DnOc" />
<input type="hidden" name="execution" value="e1s1" />
<input type="hidden" name="_eventId" value="submit" />
And I add two XPath Extractor to get lt and execution:
reference name: lt;
xPath query: //*[#id="login"]/input[3]
reference name: execution;
xPath query: //*[#id="login"]/input[4]
Then I send another request with username/password/service/It/execution/_eventId:
Error: ticket and execution I get is empty, I get the xpath by chrome, so what is the problem?
From the first response, can use Regular Expression Extractor to extract ticke and lt.
Then send the second request with parameter:
username/password/It/execution/_eventId/_eventId
By the way, you should add HTTP Cookie Manager,
I didnot see parameters of your first request. At least I didnot see the lt.
The second request should be a GET request, and the parameters are: service and ticket(This is not jsessionid, the value is generated by CAS, and it is the same with the parameter lt in the first request to the CAS login ).
There is a few things you need to change in the second request:
add execution parameter (extract it from the first request, eg. with XPath Extractor or Regular Expression Extractor),
the XPath expression would be something like .//*[#id='fm1']//*[#name='execution']/#value
add _eventId=submit parameter,
the lt parameter (the login ticket) should be extracted from the login form, too - it changes each time; see XPath Extractor or Regular Expression Extractor,
XPath expression: .//*[#id='fm1']//*[#name='lt']/#value,
not required, but will look nicer - change GET to POST.
If you're testing CAS login itself I can suggest using JMeter HTTP Proxy server to record login process, catch all values which are being passed, detect those, which are dynamic and deal with them via Regular Expression Extractor, XPath, Beanshell, etc. Post Processors - what you're most comfortable with.
In case if your application is behind CAS I guess that CAS login simply adds a cookie and your application considers user authenticated basing on it. In this case you can simply store cookies somewhere in CSV file and use them via HTTP Cookie Manager to simulate authenticated users.

ValidateAntiForgeryToken and Authorize timeout

I have an ActionResult decorated with ValidateAntiForgeryToken and Authorize. Once my forms authorization timeout limit is reached, I'm receiving a "A required anti-forgery token was not supplied or was invalid" error instead of being routed to my login page.
Can someone explain why this happens?
The ValidateAntiForgeryTokenAttribute
'Represents an attribute that is used to detect whether a server
request has been tampered with.'
to quote MSDN. What Html.AntiForgeryToken() does is output a hidden field into the form, something like: <input name="__RequestVerificationToken" type="hidden" value="XXX" />.
What the ValidateAntiForgeryTokenAttribute does on post back is compare the posted value to a previously stored cookie, to verify that they match. See http://aspnet.codeplex.com/SourceControl/changeset/view/72551#338576 (the OnAuthorization method) for details. The cookie has a name of RequestVerificationToken_Lw (you can use a cookie inspection tool like FireCookie to see this).
The cookie stored is a session cookie (the important bit). This means that when your authorization timeout is reached (30 mins by default in .NET), the cookie expires, doesn't get sent with the next request and the comparison to the hidden field value fails, throwing a HttpAntiForgeryException.
Make sure to use #Html.AntiForgeryToken() with in the BeginForm(){....} in the view
#using(Html.BeginForm()){
#Html.AntiForgeryToken()
.
.
.
.
}
Then this will be validated in the action filter attribute [ValidateAntiForgeryToken]

Php session variable instead of GET method

I have a form that has name, Id, address etc. It needs to refresh after user enters the ID inorder to query and retrieve other information such as major based the entered ID.
Once it refreshes, I retrieve back the entered values via Get method so to retain the entered form values.
Shown below
<?php
$_SESSION['Bid']=#$_GET['Bid'];
$_SESSION['Stufname']=$_GET['fname'];
$_SESSION['Stulname']=$_GET['lname'];
?>
<form name="form1" method="post" action="registration.php" >
<input type="text" name="Bid" value="<?php echo $_SESSION['Bid'];?>"
MAXLENGTH=9 size="9">
</form>
All works fine but i know GET method is unsecure since the variables are now shown in the URL and I want to get away from using get.
I tried session variable in other scripts but in this case, because the page refreshes after entering ID, I am not really sure how to capture and store the form values in the session variables on page refresh without using the GET method as I did above.
Any help would be appreciated.
thanks,
You can use POST rather. You'll be able to figure out the syntax from here: http://www.w3schools.com/php/php_post.asp but I'd recommend doing more research before posting a question.

Resources