Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsGeneralPHPASPPerlColdFusionFlashHTML, CSS, ScriptsBrowsers

Webmaster Forum / ColdFusion / Advanced Techniques / May 2006



Tip: Looking for answers? Try searching our database.

Return querystring from Payment Processor

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Andrew - 30 May 2006 19:34 GMT
Hi, I'm struggling with something that doesn't make any senses. Hopefully,
someone has seen something similar before.

I'm decoding a return value from a payment processor (Protx). The value is
returned as an encoded value in a querystring. Here's a sample (I've
manually broke it, but it is actually one long string):

test.cfm?crypt=AxcOGx89dnl9cDcHUhM+HBQGGw4DInZlQzUHFkAULRo8DxZPKzs/XlkkDQBWA2s7IgIBHAst
P19ZOEIlVgkvACI3FywFKi4LA2dUQwJBHT8DNxcmDnMwAgZnVTJyVH9CYCcpVkd6eAIAeyYwcVRmKRVT
XStcfQ4DBWVWDhUzMy4lFwchBXN8BQJvQjJeCD4BJF5aQVN3bXdgBSclAVoKIxxDIi4+DQMQdzIAAVYUO
D01EBoDHnMGd2IVLDZ3QRsAIxcsAA4rGVNFIwgHDioKOxMrKitMDR0EZDMXBl8TdiIRNywnLwptcV8wEDJ
aA3ZfdlArPA8tPkRTBRASRxI4Uh8oSSwrGB0LexgoKQoxADUBV1w1W35yBH4dUikBMA==

It is decoded with this call:

Decoded = SimpleXor(base64Decode(strCrypt),EncryptionPassword);

If I MANUALLY copy and paste the crypt string, i.e. strCrypt =
"AxcOGx89dnl9cDcHUhM+HBQGGw4 etc, etc ";

and then run the Decoded function call above, the decode works correctly,
returning:

Status=OK&StatusDetail=Successfully Authorised
Transaction&VendorTxCode=51001&VPSTxId={4011AA34-0DF9-4346-BCB3-FE02D63E5332}&TxAuthNo=7349&Amount=5.99&AVSCV2=ALL
MATCH&AddressResult=MATCHED&PostCodeResult=MATCHED&CV2Result=MATCHED&GiftAid=0&3DSecureStatus=OK&CAVV=MNLZ9VKZQ43Z1092HK6Z2W

Of course, that isn't possible. If I use the obvious: strCrypt = URL.crypt;

the Decoded string becomes:

Status=OK&StatusDetail=Successfully Authorised
Transaction&VendorTxCode=51001&VPSTxId={4011AA34-0DF9-4346-BCB3-FE02D63E5332}&TxAuthNo=7349&Amount=5.99&AVSCV2=ALL
MAi?+?V1?=h+V??2?F???{??Kl??;?"?Jü????'?H(zc?=???{?m?¨;?To????A?5?+?'?k?u{??\<?Q&??mA-?#b/??F`??{?g?
#

I've tried lots of different combinations to get the string decoded
properly, but nothing works. What changes between the actual querystring as
viewed in the address bar of the browser and CF grabbing it? Can I do
anything to stop CF changing it? This is a standard querystring returned to
thousands of systems, so it has to be something in CF. The code used is
provided by Protx as standard.

Any help much appreciated.
MikerRoo - 30 May 2006 20:39 GMT
You didn't say what CF version you were using.

Anyway, use the URLDecode function.   You may also need to specify the correct charset.
Andrew - 30 May 2006 21:51 GMT
> You didn't say what CF version you were using.
>
> Anyway, use the URLDecode function.   You may also need to specify the
> correct charset.

MX7 (7,0,1,116466)

This happens both on my development server and at the host (CrystalTech).

I've tried the URLDecode function, with UTF-8 and ISO-8859-1; neither makes
any difference, regrettably.

Any other ideas?
Cheers,
MikerRoo - 31 May 2006 01:35 GMT
You do not want to strip + or / -- those are vital base64 characters.

Also, the sample URL
"test.cfm?crypt=AxcOGx89dnl9cDcHUhM+HBQGGw4DInZlQzUHFkAULRo8DxZPKzs/XlkkDQBWA2s7
IgIBHAst

P19ZOEIlVgkvACI3FywFKi4LA2dUQwJBHT8DNxcmDnMwAgZnVTJyVH9CYCcpVkd6eAIAeyYwcVRmKRVT

XStcfQ4DBWVWDhUzMy4lFwchBXN8BQJvQjJeCD4BJF5aQVN3bXdgBSclAVoKIxxDIi4+DQMQdzIAAVYU
O

D01EBoDHnMGd2IVLDZ3QRsAIxcsAA4rGVNFIwgHDioKOxMrKitMDR0EZDMXBl8TdiIRNywnLwptcV8wE
DJ
aA3ZfdlArPA8tPkRTBRASRxI4Uh8oSSwrGB0LexgoKQoxADUBV1w1W35yBH4dUikBMA=="
is not valid.

Are you taking the Protx return value and then calling a template with it?
If so, you need to use URLEncodedFormat() like so:
<b><CFSET decodeURL = "test.cfm?crypt=" & URLEncodedFormat
(ProtxReturnValue)></b>

With CF7 you do not need to URL decode in test.cfm.

Finally, SimpleXor and base64Decode are not coldfusion functions.   You would
use BitXor and BinaryDecode.
Andrew - 31 May 2006 10:17 GMT
> You do not want to strip + or / -- those are vital base64 characters.

OK.

> Also, the sample URL
> "test.cfm?crypt=AxcOGx89dnl9cDcHUhM+HBQGGw4DInZlQzUHFkAULRo8DxZPKzs/XlkkDQBWA2s7
[quoted text clipped - 9 lines]
> aA3ZfdlArPA8tPkRTBRASRxI4Uh8oSSwrGB0LexgoKQoxADUBV1w1W35yBH4dUikBMA=="
> is not valid.

No, that's because I put in some hard returns; this is the working URL.crypt
(if I copy if from the address bar):
AxcOGx89dnl9cDcHUhM+HBQGGw4DInZlQzUHFkAULRo8DxZPKzs/XlkkDQBWA2s7IgIBHAstP19ZOEIlVgkvACI3FywFKi4LA2dUQwJBHT8DNxcmDnMwAgZnVTJyVH9CYCcpVkd6eAIAeyYwcVRmKRVTXStcfQ4DBWVWDhUzMy4lFwchBXN8BQJvQjJeCD4BJF5aQVN3bXdgBSclAVoKIxxDIi4+DQMQdzIAAVYUOD01EBoDHnMGd2IVLDZ3QRsAIxcsAA4rGVNFIwgHDioKOxMrKitMDR0EZDMXBl8TdiIRNywnLwptcV8wEDJaA3ZfdlArPA8tPkRTBRASRxI4Uh8oSSwrGB0LexgoKQoxADUBV1w1W35yBH4dUikBMA==

The crypt string above is being returned to my page by Protx. I have no
control over it; they provide functions to decode the string into valid
fields. If I manually paste in the above string, it works. If I use
URL.crypt, it doesn't. The problem therefore is that something is happening,
presumably only with CFMX7, to the qs before it is passed to the routine.

> Are you taking the Protx return value and then calling a template with it?
> If so, you need to use URLEncodedFormat() like so:
> <b><CFSET decodeURL = "test.cfm?crypt=" & URLEncodedFormat
> (ProtxReturnValue)></b>

That fails with an error: The parameter 1 of function ToBinary, which is now
"AxcOGx89dnl9cDcHUhM%20HBQGGw4DInZlQzUHFkAULRo8DxZPKzs%2FXlkkDQBWA2s7IgIBHAstP19ZOEIlVgkvACI3FywFKi4LA2dUQwJBHT8DNxcmDnMwAgZnVTJyVH9CYCcpVkd6eAIAeyYwcVRmKRVTXStcfQ4DBWVWDhUzMy4lFwchBXN8BQJvQjJeCD4BJF5aQVN3bXdgBSclAVoKIxxDIi4%20DQMQdzIAAVYUOD01EBoDHnMGd2IVLDZ3QRsAIxcsAA4rGVNFIwgHDioKOxMrKitMDR0EZDMXBl8TdiIRNywnLwptcV8wEDJaA3ZfdlArPA8tPkRTBRASRxI4Uh8oSSwrGB0LexgoKQoxADUBV1w1W35yBH4dUikBMA%3D%3D"
must be a Base-64 encoded string.

> Finally, SimpleXor and base64Decode are not coldfusion functions.   You
> would
> use BitXor and BinaryDecode.

No, they are functions provided by Protx. I've tried the native functions,
but they fail (BitXor in particular as that needs two integer values; the
password is a string).

Here's the simpleXor function:

function simpleXor(InString, Key) {

// Initialise key array
KeyList = ArrayNew(1);
// Initialise output variable
output = "";

// Convert $Key into array of ASCII values
// ColdFusion arrays are indexed at 1, not 0. Smart!
for(i = 1; i LTE Len(Key); i=i+1){
 KeyList[i] = Asc(Mid(Key, i, 1));
}

for(i = 0; i LTE Len(InString)-1; i=i+1){
 // Get ASCII code from string, get ASCII code from key (loop through with
MOD), XOR the two
 result = (bitXor((Asc(Mid(InString, i+1, 1))), (KeyList[(i MOD
Len(Key))+1])));

 // Horrible hack to avoid problem with chr(0)
 // If result is 0...
 if (result eq 0){
  // ...add the null character to output
  output = output & urldecode("%00");
 } else {
  // ...add the specified character to output
  output = output & Chr(result);
 }

}

// Return the result
return output;

}

For completeness, here's the base64Decode function also:

function base64Decode(scrambled) {
// Initialise output variable
output = "";

// Fix plus to space conversion issue
scrambled = Replace(scrambled," ","+");

// Do decoding
output = toString(toBinary(scrambled));
// output = ToString(BinaryDecode(scrambled,"Base64"));

// Return the result
return output;

}
Steve Sommers - 30 May 2006 20:43 GMT
My guess is that the + in the string is causing the problem. URL decoding
changes the + to a space and I beleive CF does the URL decoding for you
automatically (depending on the version you are running). You may be able to
simply replace all the spaces with +'s sing spaces are not valid B64 encode
characters. You may also have similar issues with the trailing = signs.

To confirm this, place a <!-- #string# --> in your code and view the page
source (simply displaying it on the screen may hide some of the text, viewing
in notepade is more reliable for this stuff). Do this for the URL parameter
test and the cut & paste test and compare.

Hope this helps.

On a side note, XOR encryption/decryption is a VERY weak form of encryption
and will not comply with any of the card association regs. Hopefully something
stronger is being used in the production environment.
Andrew - 30 May 2006 21:59 GMT
> My guess is that the + in the string is causing the problem. URL decoding
> changes the + to a space and I beleive CF does the URL decoding for you
[quoted text clipped - 18 lines]
> something
> stronger is being used in the production environment.

Thanks for the reply.

This is the base64 function:

function base64Decode(scrambled) {
// Initialise output variable
output = "";

// Fix plus to space conversion issue
scrambled = Replace(scrambled," ","+");

// Do decoding
output = toString(toBinary(scrambled));

// Return the result
return output;

}

I've already got a test page outputting various options:

<cfscript>
 crypt1 =
"AxcOGx89dnl9cDcHUhM+HBQGGw4DInZlQzUHFkAULRo8DxZPKzs/XlkkDQBWA2s7IgIBHAstP19ZOEIlVgkvACI3FywFKi4LA2dUQwJBHT8DNxcmDnMwAgZnVTJyVH9CYCcpVkd6eAIAeyYwcVRmKRVTXStcfQ4DBWVWDhUzMy4lFwchBXN8BQJvQjJeCD4BJF5aQVN3bXdgBSclAVoKIxxDIi4+DQMQdzIAAVYUOD01EBoDHnMGd2IVLDZ3QRsAIxcsAA4rGVNFIwgHDioKOxMrKitMDR0EZDMXBl8TdiIRNywnLwptcV8wEDJaA3ZfdlArPA8tPkRTBRASRxI4Uh8oSSwrGB0LexgoKQoxADUBV1w1W35yBH4dUikBMA==";
 crypt2 = "AxcOGx89dnl9cDcHUhM
HBQGGw4DInZlQzUHFkAULRo8DxZPKzs/XlkkDQBWA2s7IgIBHAstP19ZOEIlVgkvACI3FywFKi4LA2dUQwJBHT8DNxcmDnMwAgZnVTJyVH9CYCcpVkd6eAIAeyYwcVRmKRVTXStcfQ4DBWVWDhUzMy4lFwchBXN8BQJvQjJeCD4BJF5aQVN3bXdgBSclAVoKIxxDIi4
DQMQdzIAAVYUOD01EBoDHnMGd2IVLDZ3QRsAIxcsAA4rGVNFIwgHDioKOxMrKitMDR0EZDMXBl8TdiIRNywnLwptcV8wEDJaA3ZfdlArPA8tPkRTBRASRxI4Uh8oSSwrGB0LexgoKQoxADUBV1w1W35yBH4dUikBMA==";
 crypt3 = URLDecode(URL.crypt,"ISO-8859-1");
 crypt4 = CGI.QUERY_STRING;
 crypt5 = URL.crypt;

 // ** Decode the crypt field that was sent back to us **
 Decoded1 = SimpleXor(base64Decode(crypt1),EncryptionPassword);
 Decoded2 = SimpleXor(base64Decode(crypt2),EncryptionPassword);
 Decoded3 = SimpleXor(base64Decode(crypt3),EncryptionPassword);
 Decoded4 = SimpleXor(base64Decode(crypt4),EncryptionPassword);
 Decoded5 = SimpleXor(base64Decode(URL.crypt),EncryptionPassword);
</cfscript>

<body>
<h3>Crypt1</h3>
<p><cfoutput>#Decoded1#</cfoutput></p>

<h3>Crypt2</h3>
<p><cfoutput>#Decoded2#</cfoutput></p>

<h3>Crypt3</h3>
<p><cfoutput>#Decoded3#</cfoutput></p>

<h3>CGI</h3>
<p><cfoutput>#CGI.QUERY_STRING#</cfoutput></p>

<h3>Crypt4</h3>
<p><cfoutput>#Decoded4#</cfoutput></p>

<h3>Crypt5</h3>
<p><cfoutput>#Decoded5#</cfoutput></p>

> You may also have similar issues with the trailing = signs.

So you think I should do a replace on = as well?

Any other ideas?

> On a side note, XOR encryption/decryption is a VERY weak form of
> encryption
> and will not comply with any of the card association regs. Hopefully
> something
> stronger is being used in the production environment.

This is actually the only method available with the payment processor.
However, the credit card details are not obtained until the user is on the
Protx site and are never passed in the URL variables.
Steve Sommers - 31 May 2006 01:03 GMT
Assuming that crypt1 and crypt2 are your cut & paste and URL examples -- then simply replacing the spaces with + signs should work: crypt2=Replace(crypt2," ","+","ALL")
Andrew - 31 May 2006 10:24 GMT
> Assuming that crypt1 and crypt2 are your cut & paste and URL examples --  
> then simply replacing the spaces with + signs should work:
> crypt2=Replace(crypt2," ","+","ALL")

Got that in the base64Decode function:

function base64Decode(scrambled) {
// Initialise output variable
output = "";

// Fix plus to space conversion issue
scrambled = Replace(scrambled," ","+");

// Do decoding
output = toString(toBinary(scrambled));
// output = ToString(BinaryDecode(scrambled,"Base64"));

// Return the result
return output;

}

... but, my Replace function call was missing a crucial "ALL" !!! With that
in place, it works perfectly. Thanks for that; can't believe I missed it,
but something so simple could bugger it up so completely!

Thanks again <g>.
Steve Sommers - 31 May 2006 16:34 GMT
<blockquote>quote:<br><hr><i>Originally posted by: <b><b>Newsgroup
User</b></b></i>

... but, my Replace function call was missing a crucial "ALL" !!! With that
in place, it works perfectly. Thanks for that; can't believe I missed it,
but something so simple could bugger it up so completely!

Thanks again <g>. <hr></blockquote>
Yeah, that bites me now and then as well as many others who have posted issues
on this forum. I really think defaulting the scope to "ONE" was a design flaw
since almost every language other than ColdFusion only has an "ALL" version of
the replace function.

Glad it worked.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.