Link to home
Start Free TrialLog in
Avatar of Everet Milner
Everet Milner

asked on

PayPal Express Checkout and Classic ASP -- trying to get PayPal's return values

Using the PayPal sandbox environment, I am able to successful send an item for purchase to PayPal. PayPal displays the purchase screen with the correct information. I click the ‘Pay Now’ button and the transaction completes. The successful transaction shows in both the buyer and seller accounts.

PayPal returns to the specified url and has the PaymentID, Token, and PayerID.

The problem is there is nothing in the Response.Form. I search thru the items and there are no items. An objHTTP.Send returns INVALID from PayPal.
Using Telerik Fiddler, there is nothing being returned…other than the url items.

Below is the code I am using.

Thank you in advance for your assistance.

<%
Dim Item_name, Item_number, Payment_status, Payment_amount
Dim Txn_id, Receiver_email, Payer_email
Dim objHttp, str

Response.Write "PaymentID=" & Request.QueryString("PaymentID") & "*<BR>"
Response.Write "Token=" & Request.QueryString("Token") & "*<BR>"
Response.Write "PayerID=" & Request.QueryString("PayerID") & "*<BR>"

Response.Write "<table><tr><td>Name</td><td>Value</td></tr>"
For Each Item In Request.Form
    Response.Write "<tr><td>" & item & "</td><td>" & Request.Form(item) & "</td></tr>"
Next
Response.Write "</table>"
 
' read post from PayPal system and add 'cmd'
str = Request.Form & "&cmd=_notify-validate"

Response.Write "str: " & str & "*<BR>"
 
' post back to PayPal system to validate
' Note: either of these work
' SET objHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP")
SET objHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP.6.0")

' the following do not work
' SET objHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP.4.0")
' SET objHTTP = Server.CreateObject("Microsoft.XMLHTTP")

objHTTP.open "POST", "https://www.paypal.com/cgi-bin/webscr", false
objHTTP.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
objHTTP.Send str

' checking for form names that we know should exist
a = Split("item_name,item_number,payment_status,mc_gross,mc_currency,txn_id,receiver_email,payer_email",",")

Response.Write "<table>"
For j = 0 to UBound(a)
	Response.Write "<tr><td>" & a(j) & "</td><td>*" & Request.Form(a(j)) & "*</td></tr>"
Next
Response.Write "</table>"

' Check notification validation
IF objHttp.status <> 200 THEN
	' HTTP error handling
ELSEIF objHttp.responseText = "VERIFIED" THEN
	Response.Write "verified<br>"
	' check that Payment_status=Completed
	' check that Txn_id has not been previously processed
	' check that Receiver_email is your Primary PayPal email
	' check that Payment_amount/Payment_currency are correct
	' process payment
ELSEIF objHttp.responseText = "INVALID" THEN
	Response.Write "invalid<br>"
	' log for manual investigation
ELSE
	' error
END If
SET objHTTP = nothing
%>

Open in new window

Avatar of Scott Fell
Scott Fell
Flag of United States of America image

Which api are you using?

> PayPal returns to the specified url and has the PaymentID, Token, and PayerID.
Depending on which api you are using, you may need to set up a listener to accept the response.

In other words, you post your response to https://www.paypal.com/cgi-bin/webscr  Then your user goes to the paypal site and then back to your site. In this scenario  you don't have to worry about PCI because inputting cc data is done on Paypal's server.  The downside is there is no direct response to you in the way you expect. Instead  you have to have  listener https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNIntro/ 

The next step is to update your database via data you received from the listener url.  From there you will process the payment in your database and when your user goes back to the site you can show the results.

My steps would be"

1) User selects items to purchase.
2) Each item saves to a "cart" either via cookie or database (not a session)
3) User clicks paybutton - Generate an invoice record in the database with invoice id, date, customer and either item and amount or detail records for items in a related table.
4) Send to paypal
5) Set up listener
6) On payment success, paypal sends data to listenter
7) Update paypments database table with invoice id, payment amount and any other transaction information sent back.
8) When user is sent back to your site, load invoice and payments table and show needed information prior to doing any types of checks to make sure the payment was valid etc.



When your user lands back on your page,
Avatar of Everet Milner
Everet Milner

ASKER

I am using Express Checkout--no cart, no invoice.

Here is the script sending the information to PayPal.

<script>
		paypal.Button.render({
			env: 'sandbox', // sandbox | production
			client: {
				sandbox:    'AZDxjDScFpQtjWTOUtWKbyN_bDt4OgqaF4eYXlewfBP4-8aqX3PiV8e1GWU6liB2CUXlkA59kJXE7M6R',
				production: '<insert production client id>'
			},
			// Show tagline under button
			style: { tagline: true },
			// Show the buyer a 'Pay Now' button in the checkout flow
			commit: true,
			payment: function(data, actions) {
				// Make a client-side call to the REST api to create the payment
				return actions.payment.create({
					payment: {
	  					transactions: [
							{
								amount: {
									total: '5.99', // no $, must contain , and 2 decimal places
									currency: 'USD',
									details: {
										subtotal: '5.99',
										tax: '0.00',
										shipping: '0.00',
										handling_fee: '0.00',
										insurance: '0.00',
										shipping_discount: '0'
									}
	        					},
								description: 'See Course Documentation for refund/cancellation policy. Email support@theplacewithince.org for any questions on your order.',
								item_list: {
									items: [
										{
											name: 'Mental Health Parity Act of 2018',
											description: 'CE Course',
											quantity: '1',
											price: '5.99',
											tax: '0.00',
											sku: '2105',
											currency: 'USD'
										}
									]
								}
							}
						],
						redirect_urls: {

								return_url: 'xxx.com/paymentverify.asp',
								cancel_url: 'xxx.com/payment.asp?Authorization=456890'

						}
					}
				});
			},
			// Wait for the payment to be authorized by the customer
			onAuthorize: function(data, actions) {
				// Execute the payment
				return actions.payment.execute().then(function() {
//					window.alert('Payment Complete!');
					actions.redirect();
				});
			},
			onCancel: function(data, actions) {
			// Show a cancel page or return to cart
				actions.redirect();
			}
		}, '#paypal-button-container');
	</script>

Open in new window

redirect_urls: {

								return_url: 'xxx.com/paymentverify.asp',
								cancel_url: 'xxx.com/payment.asp?Authorization=456890'

						}

Open in new window

https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/customize-the-checkout-flow/
Note: You must show a confirmation without redirecting the page. Otherwise the actions.payment.execute() and actions.payment.get() functions become unavailable. Alternatively, you can use the server-side REST or Braintree server-side SDK to execute the payment on the server.

You are using a redirect and that may be your issue.

Just remember if you are sending all of this information on the client side you can't trust the data because it may be possible for somebody to change prices etc so before shipping anything, make sure to verify either manually or via code.   My own preference would be to do this all server side https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/advanced-payments-api/create-express-checkout-payments/  On the form, you just send an id and on paypal register products so the pricing is associated with that product id.  Then the only thing you are submitting is the id and people can't mess with the price. On paypal's end, they will charge the amount associated with the product id.    

Anyway, I think the issue is you are using a redirect.
Since Scott is helping you with the Paypal part, I wanted to bring up something that I believe all ASP Classic programmers should know.
And that is the right way to code your ASP Pages.
If you use a Visual program, like Dreamweaver, or another type of program that lets you visually see what you are designing while you're creating the page, then you will want to see what you are doing.

Copy and paste this code into a new page, and run it, and you should get the same results as you do with the original code.
Good Luck
Wayne

<%
Dim Item_name, Item_number, Payment_status, Payment_amount
Dim Txn_id, Receiver_email, Payer_email
Dim objHttp, str
%>
PaymentID=<%Request.QueryString("PaymentID")%>*<br />
Token=<%Request.QueryString("Token")%>*<br />
PayerID=<%Request.QueryString("PayerID")%>*<br />

<table><tr><td>Name</td><td>Value</td></tr>"
<%For Each Item In Request.Form%>
    <tr><td><%item%></td><td><%Request.Form(item)%></td></tr>"
<%Next%>
</table>
 <%
' read post from PayPal system and add 'cmd'
str = Request.Form & "&cmd=_notify-validate"%>

str: <%=str%>*<br />
<% 
' post back to PayPal system to validate
' Note: either of these work
' SET objHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP")
SET objHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP.6.0")

' the following do not work
' SET objHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP.4.0")
' SET objHTTP = Server.CreateObject("Microsoft.XMLHTTP")

objHTTP.open "POST", "https://www.paypal.com/cgi-bin/webscr", false
objHTTP.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
objHTTP.Send str

' checking for form names that we know should exist
a = Split("item_name,item_number,payment_status,mc_gross,mc_currency,txn_id,receiver_email,payer_email",",")
%>
<table>
<%
For j = 0 to UBound(a)%>
	<tr><td><%=a(j)%></td><td>*<%Request.Form(a(j))%>*</td></tr>
<%Next%>
</table>
<%
' Check notification validation
IF objHttp.status <> 200 THEN
	' HTTP error handling
ELSEIF objHttp.responseText = "VERIFIED" THEN%>
	verified<br />
    <%
	' check that Payment_status=Completed
	' check that Txn_id has not been previously processed
	' check that Receiver_email is your Primary PayPal email
	' check that Payment_amount/Payment_currency are correct
	' process payment
ELSEIF objHttp.responseText = "INVALID" THEN%>
	invalid<br />
	<%' log for manual investigation
ELSE
	' error
END If
SET objHTTP = nothing
%>

Open in new window

This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.