Our authorize.net processing is done in some OLD perl cgi code - any perl programmers out there?
We are trying to convert to the SHA-512 hashing. Our current processing uses MD5, via the perl module Digest::MD5.
I use LWP::UserAgent to POST directly to the secure.authorize.net gateway transact dll URL.
What I get returned is an array of values. The MD5 hash is currently in the 38th array element. Authorize.net has been unable to tell me where I can find the returned SHA-512 hash value to compare to what I am generating in the program.
For my test:
I changed it to use Digest::SHA for the hashing. I generated the signature key and have it stored in hex in our database.
my $sha512_string = '^' . $auth_net_login_id . '^' . $tranid . '^' . $grandtotal . '^';
my $key = pack 'H*', $sig_key; ##to convert the store hex value to binary - as recommended here
my $sha512 = Digest::SHA->new;
my $sent_sha512_hash = $sha512->hmac_sha512($sha512_string, $key);
When I display that value, it just shows a bunch of weird characters on the screen - I don't know if that's expected or not. I am only displaying it to compare to what comes from authorize.net.
When the values are returned from Authorize.net (in the array), I display all the elements. There is a value in element 68 that looks like a hex value but that isn't what is in the hash that I generated.
So, isn't the hash returned from Authorize.net in the array? If not, then how do I obtain it using the methods we currently have in place? I don't consider this as using the API. Or is the problem that I am hashing it wrong on my end?
I obtained the perl code for our current processing via Authorize.net MANY years ago from one of their perl customers. It has worked fine ever since. I do not have the knowledge, experience or brain power to change the whole process, unless someone could provide all the perl code (I know that's asking a lot). I also have a general knowlege of php but unfortunately the examples on this forum are too different from our perl process to be able to correlate the two.
I hope someone can help! Thanks in advance!
Solved! Go to Solution.
01-16-2019 11:07 AM
01-21-2019 08:43 PM
i understand what you’re saying, but yes, it returns a fair number of other things that I don’t send in the original request. And the values are not easily identifiable as far as what field name they represent. When I get back to this, I might re-read the full SIM documentation to see if I can figure out another way to do the POST. Another developer posted his perl cgi code where he accessed the field names and values like regular query params. I might check with him to see the code that he used to get to that point. I’ve never initiated 2 queries in the same script but I don’t know why it can’t be done as long as I call it by another name. I would REALLY like to implement the API so it would all be so much easier, well documented, and supported by authorize.net. But I just don’t feel qualified to do that.
I’m not giving up —- yet. But I’m only part time, have had limited exposure to programming over the last few years. PLUS I’m old as dirt. I could handle these marathons when I was younger, but no longer.
01-21-2019 10:01 PM
Yeah I think Perl should have the capability to make multiple arrays out of the same variable. This is actually pretty easy now that I look at it a 3rd time. I’ll do it one piece at a time-
1|1|1|(TESTMODE) This transaction has been approved.|000000|P|0|8478||39.00|CC|auth_capture|10001253|
I think the first set of three 1’s is the response code and response reason code. (TESTMODE) is x_test_request. Then we have response reason text, x_auth_code, x_avs_code, x_trans_id, x_invoice_num, a | representing the empty description field, then x_amount, x_method, x_type
The 10001253 maybe you have an idea of. It could be numerous things. Maybe customer Id.
|Sharon|Shatest||123 Somewhere Street|Anywhere|PA|19666|US|||sharon.shatest@test.com
This is all self-explanatory. Name, address and email. The | after sharons last name is the empty company field.
||||||||||||||5E3E841F808768EA1E68EB5800CD0A48|||||||||||||XXXX0002|American Express|||||||||||||||||422E3EF8AA729B89FC102825EA9FEE6DCCB701D861B4248CF24C12600AB1EAF04371257B7163091AFCD883D57C3F9B83424717C7317BCFD90392CE33E87BFCE2
Here is md5 hash, x_account_number, and x_card_type, followed by the sha512 hash value.
Of these you need the values of x_trans_id, x_respone_code, x_auth_code, x_sha_512, and x_method (maybe on x_method, you can probably pass this in your call too).
The remaining values to calculate your string for verification are in your original request. That cuts you down to 4 to 5 values to extract, which is better than 30. You don’t care what all those other pipe bars are because they’re all empty. You could trade them out for one another with no effect.
01-22-2019 01:32 AM
@smorrow123 You might take a look at this near the bottom. Again, I've never used LWP so I can't add a lot of input here.
http://forums.devshed.com/perl-programming-6/reading-post-data-lwp-response-object-536104.html
If no help there you could consider trying simple CGI as a work araound.
If you already have or can add this near the top of your script?
use CGI; $cgi = new CGI;
Then do a quick check to see if CGI will give you the name/value pairs.
if( $response->is_success ) { #$apiresponse = $response->content; #foreach $pair(@responses) #{ # The next statement splits based on the pipe character: | # not sure what this accomplishes since it isn't referenced by name or val # ($name,$val) = split(/\Q|/,$pair); #} # split the words using the pipe character (|) as the delimiter. #@words = split /\Q|/, $apiresponse; #$response_code = $words[0]; ############################################### use CGI; ### Could also place this $cgi = new CGI; ### here if not elsewhere foreach $name ($cgi->param) { $value=$cgi->param($name); $response{$name}=$value; } while (($name,$value) = each(%response)) { $debug.="$name = $value "; } print qq~Content-type: text/html\n\n <html> $response{x_response_code}<br> $response{x_amount}<br> $response{x_SHA2_Hash}<br> <br>Full Set = $debug<br> </html>~; exit; ############################################## #additional processing; check response code, hashing, checking hash, etc. } }
01-22-2019 10:12 AM
Thanks! I've been considering the cgi alternative, but the script was already doing cgi (the program does more than just obtain authorizations) and I've never done two "new cgi's" in the same script. As I said in a recent email, I would imagine that if I call it by another name (I use $q as a standard) it should be ok. The only problem is actually generating the "post". I would normally do it via forms and since this currently uses LWP for posting, I'd have to figure out how to code it to post with a regular cgi post rather than LWP. (Don't know if that makes sense).
I will read the LWP reference on devshed - I also have an email into our server host to see if he can get me some LWP documentation.
I'm on hold with this at least until tomorrow due to other obligations. Please know that I am reading all the suggestions and appreciate the amount of time and effort you and the others have put into helping me with this problem. I've been ready to give up multiple times, but you guys manage to draw me back in to keep trying! ;-) If I finally get this working - no matter how - I will post to let everyone know what the resolution was.
01-22-2019 11:15 AM
@smorrow123Just noticed I should have used a different hash name for testing to avoid any issues with how "response" is already being used. Changed response to responseT.
############################################### use CGI; ### Could also place this $cgi = new CGI; ### here if not elsewhere foreach $name ($cgi->param) { $value=$cgi->param($name); $responseT{$name}=$value; } while (($name,$value) = each(%responseT)) { $debug.="$name = $value "; } print qq~Content-type: text/html\n\n <html> $responseT{x_response_code}<br> $responseT{x_amount}<br> $responseT{x_SHA2_Hash}<br> <br>Full Set = $debug<br> </html>~; exit; ##############################################
01-23-2019 07:13 AM
I checked out the LWP reference in the link from DevShed, and it seems like I SHOULD be able to get name/value pairs back, so I'm going to try their sample code. That isn't what I was seeing when I displayed the response (I only saw values). One post there said LWP doesn't return name/value pairs - then they proceeded to provide code that would split out the name/value pairs. Made no sense. But I'm still going to try it.
THEN, if that doesn't work, I'm going to try the cgi route. However, using your example below, is this IN ADDITION TO using LWP, or INSTEAD OF? In other words, can I access the cgi params if I've used LWP - or do I need a different kind of POST statement to use CGI? And if so, all of my cgi posts have been via forms - and since there isn't a form per-say in this case, how do I generate the CGI POST statement to use THIS method?
Hope this is making sense. In the meantime, I'm going to try the LWP suggestion from DevShed and see what happens.
01-23-2019 07:49 AM
It looks like you are using AIM, take a look at https://www.authorize.net/content/dam/authorize/documents/AIM_guide.pdf. Page 52 lists the fileds in the response. Based on some old code of mine I believe they added more fields later, but I don't think they are important in this context.
With AIM you submit data in name value pairs - x-login=xxxx&x_tran-key=zzz etc.
The response is not in name value pairs, it is one delimited string. So there are no names to extract via perl or any other language.
The response needs to be first split into an array, then addressed by the array index.
my @responses = split( /\Q|/, $response->content );
This line is splitting the response string into an array, so $responses[0] is the Response Code, $response[2] is the Response Reason Code, etc.
If you want to address the fields by name, you must assign the names. For example
$ResponseCode = $responses[0]; or $respone_hash = (ResponseCode => $responses[0], ResponseReasonCode => $responses[2]);
This is quite easy as long as you remember that perl arrays are 0 based, so the first field in the response is $responses[0].
01-23-2019 08:20 AM
Thanks!!
The old code I inherited (as you showed) does make it sound like I'm using AIM. Someone else thought SIM. Who knows WHAT it's using!! All I know is that it isn't using an API.
SO, yes, I am only getting values returned and separated by pipe symbols - no names - and I understand what you are saying about assigning names. I can do that. But it says that the values can be returned in a different order so it was best to access by field-names. That's where I started on this crazy journey and where I still am.
SO, assuming that the order on the returned values are the same as the current version of the documentation - can you tell me where I can get a list of the returned values IN THE ORDER THEY ARE RETURNED? Another developer helped me figure out most, but there are some questionable ones. The HMAC SHA-512 Hash section in the SIM Developer Guide that I was sent says that the response fields will be incorporated into the hash calculation in the sequence shown in the table on page 73. But that is NOT the order they are returned in the response. Where can I get information on THAT order?
I tried just hashing with the first 30 fields that were returned to me, hoping they were being returned in the same order as the hash response, but that didn't work either - so I can only assume they are in a different order for the hashing than they are actually returned. WHY? Who knows!
Please - if you can get me information on the returned data order - I think I will actually be able to get this implemented!!!
01-23-2019 08:50 AM
01-23-2019 09:14 AM