Link to home
Start Free TrialLog in
Avatar of Coast Line
Coast LineFlag for Canada

asked on

trying to run a java code or return value from jsp

Hii have the following code. i had 2 options with me, either i run the java code to convert into ColdFusion or create the java code as jsp and run it thru cfhttp by passing required parameters and accessing thm.

but probem is i do not know either way what to do and where to start

can someone guide me please

if i do call cfhttp, how do i pass and how do i call from that jsp page


long nonce = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong());
            returnMap.put(APIResourceConstants.SecurityConstants.NONCE, Long.toString(nonce));
            returnMap.put(APIResourceConstants.SecurityConstants.APIKEY, requestOptions.getApiKey());
            returnMap.put(APIResourceConstants.SecurityConstants.TIMESTAMP, Long.toString(System.currentTimeMillis()));
            returnMap.put(APIResourceConstants.SecurityConstants.TOKEN, requestOptions.getToken());
            returnMap.put(APIResourceConstants.SecurityConstants.APISECRET, requestOptions.getSecret());
            returnMap.put(APIResourceConstants.SecurityConstants.PAYLOAD, payLoad);

this is the parameters and this is how the data is generated !!!!!!!!!!!!!!!!

Mac mac=Mac.getInstance("HmacSHA256");
        String apiSecret= data.get(APIResourceConstants.SecurityConstants.APISECRET);
        SecretKeySpec secret_key = new SecretKeySpec(apiSecret.getBytes(), "HmacSHA256");
        mac.init(secret_key);
        String apikey = data.get(APIResourceConstants.SecurityConstants.APIKEY);
        String nonce = data.get(APIResourceConstants.SecurityConstants.NONCE);
        String timeStamp = data.get(APIResourceConstants.SecurityConstants.TIMESTAMP);
        String token = data.get(APIResourceConstants.SecurityConstants.TOKEN);
        String payload = data.get(APIResourceConstants.SecurityConstants.PAYLOAD);

        StringBuilder buff=new StringBuilder();
        buff.append(apikey)
                .append(nonce)
                .append(timeStamp);
        if(token!=null){
            buff.append(token);
        }
        if(payload != null){
            buff.append(payload);
        }
        String bufferData = buff.toString();
        byte[] macHash=mac.doFinal(bufferData.getBytes("UTF-8"));
        String authorizeString = new String(Base64.encodeBase64(toHex(macHash)));
        return authorizeString;

Open in new window


Thanks
Avatar of gurpsbassi
gurpsbassi
Flag of United Kingdom of Great Britain and Northern Ireland image

Please describe the architecture of your system.

I do not have enough information to help you.
Avatar of Coast Line

ASKER

architecture is a web based application, so i need to call this file as jsp file and it should return me the authorizeString caculated

so all i want to pass to this page using http is the apikey , apiSecret, payload and it should do from its page is the timestamp, nonce and club all the 5 elements and do its calculation and return me the authorizeString
why does it need to be done at the jsp level and what do u want to do with the auth string once retrieved?
i said its a web application code, so i am not well versed with JAVA, I Can do Java but not an expert, so this code is working in Authorisation but not in ColdFusion Language, I tried doing same thing but something is wrong on the TImestamp or the Other criteria where I am not able to fix it, ColdFusion is build upon java, i can use direct but it is not supported on shared host if you call java methods directly, so al i am trying is converting the java code to JSP to do the work and return me the authorizeString so i can use it and fix it
So you can't do this using createObject('java')?

>> this code is working in Authorisation but not in ColdFusion Language

Can you post the CF code you tried and explain what's wrong with the result?
I would move your jsp script code into a java bean that the jsp can access.
ok here is the coldfusion code

function GetEpochTime() {var datetime = 0;if (ArrayLen(Arguments) is 0) {datetime = Now();}else {if (IsDate(Arguments[1])) {
			datetime = Arguments[1];} else {return NULL;}}return DateDiff("s", "January 1 1970 00:00", datetime);}
			$apiKey = "#arguments.apiKey#";
			$apiSecret = "#arguments.apiSecret#";
			$token = "#arguments.token#";
			$timestamp = GetEpochTime(now());
			$payload = getPayLoad(merchant_ref='#merchant_ref#',amt_charge='#arguments.amt_charge#',cardtype='#arguments.cardtype#',
			card_holder_name='#arguments.card_holder_name#',card_number='#arguments.card_number#',card_exp='#arguments.card_exp#',
			cvvnumber='#arguments.cvvnumber#');



<cffunction access="public" name="getPayLoad" returntype="any">
		<cfargument name="merchant_ref" default="000000000" type="any">
		<cfargument name="transactionType" default="authorize" type="any">
		<cfargument name="amt_charge" default="" type="any">
		<cfargument name="cardtype" default="" type="any">
		<cfargument name="card_holder_name" default="" type="any">
		<cfargument name="card_exp" default="" type="any">
		<cfargument name="cvvnumber" default="" type="any">
		<cfargument name="card_number" default="" type="any">
		<cfset var str = "">
		<cfset cardnumber = reReplace(arguments.card_number, "[[:space:]]", "", "ALL") />
		<cfset carholderName = reReplace(arguments.card_holder_name, "[[:space:]]", "", "ALL") />
		<cfset st = {}>
		<cfset st['method'] = "credit_card">
		<cfset st['merchant_ref'] = "#trim(arguments.merchant_ref)#">
		<cfset st['transaction_type'] = "#arguments.transactionType#">
		<cfset st['amount'] = "#trim(arguments.amt_charge)#">
		<cfset st['currency_code'] = "USD">
		<cfset st['credit_card'] = {}>
		<cfset st['credit_card']['type'] = "#trim(arguments.cardtype)#">
		<cfset st['credit_card']['cardholder_name'] = "#trim(carholderName)#">
		<cfset st['credit_card']['card_number'] = "#trim(cardnumber)#">
		<cfset st['credit_card']['exp_date'] = "#trim(arguments.card_exp)#">
		<cfset st['credit_card']['cvv'] = "#trim(arguments.cvvnumber)#">
		<cfset results = jsonencode(st)>
		<cffile action="write" file="#ExpandPath('response.json')#" output="#results#">
		<cfreturn True>
	</cffunction>

Open in new window

1. To confirm, you can't use createObject('java') correct?
2. What's different about the CF result vs. the Authorisation result?
This is the closest you can get IF you can't use createObject('java')

<cfscript>
	// Closest equivalent to Math.abs(SecureRandom.getInstance("SHA1PRNG")) without using createObject('java')
	seed = randRange(-1000000000,1000000000);
	randomize(seed);
	nonce = ABS( Rand("SHA1PRNG") );

	// Fill in your values here
	apiKey = "Your API Key";
	// change now()  to UTC if needed
	timeStamp = DateDiff("s", "January 1 1970 00:00", now());
	token = "your Token Value";
	apiSecret = "your API Secret";
	payLoad = "your Pay Load value";
	
	// Build string to hash. Equivalent of StringBuilder buff=new StringBuilder();, buff.append(apikey)....
	stringToHash = apikey & nonce & timeStamp;
	if (structKeyExists(variables, "token") && len(token)) {
		stringToHash &= token;
	}
	else {
		stringToHash &= payload;
	}
	
	// Generate hash and convert to base64 string
	// Equivalent of =mac.doFinal(bufferData.getBytes("UTF-8")) ....
	binaryKey = charsetDecode(apiSecret, "utf-8");
	resultHex = hmac(stringToHash, binaryKey, "HMACSHA256", "UTF-8");
    authorizeString = binaryEncode(binaryDecode(resultHex, "hex"), "base64");
	writeDump("authorizeString="& authorizeString);
</cfscript>

Open in new window

@agx: the stringToHash is the combination of apikey + nonce + timestamp + payload + token

i want to try the createobject java on local, do let me know how?
if (structKeyExists(variables, "token") && len(token)) {
     // ...
}
else {
            stringToHash &= payload;
}

Change the ELSE to an IF and append "payload" if it's empty.  Just like the "token" code.

You don't really need java code for any of it. Except for this part:

         long nonce = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong());

CF can't create longs natively.  Other than that, the CF code is identical.

     Math = createObject('java', 'java.lang.Math');
     SecureRandom = createObject('java', 'java.security.SecureRandom');
     nonce = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong());

Open in new window

can you club all of these the way you did in your last comment

binaryKey = charsetDecode(apiSecret, "utf-8");
      resultHex = hmac(stringToHash, binaryKey, "HMACSHA256", "UTF-8");
    authorizeString = binaryEncode(binaryDecode(resultHex, "hex"), "base64");
all i need is the authorizeString
issue also seems to be in timestamp i need to get the epochtime in milliseconds why it always endup with 000 at last and that is in the function
i think i had done most

just need this to be generated with createobject java

String bufferData = buff.toString();
        byte[] macHash=mac.doFinal(bufferData.getBytes("UTF-8"));
        String authorizeString = new String(Base64.encodeBase64(toHex(macHash)));
Unless you're using a really old version, you don't need java for the hmac part.  Just use the hmac() function like in my earlier example.

>> issue also seems to be in timestamp

CF may be rounding the value to an INT.  Try using  now().getTime() instead , ie

        timestamp = now().getTime();
i agree, but can you check my last comment and see if that can be converted to java the same way you did for nonce
This is pure hackery.
I wouldn't go to production with this sort of design/impl.
well whatever it is, but sometimes we had to make it work.
@myselfrandhawa - You do not need java code to generate an HMAC.  Can you please answer my earlier question and provide an example of "What's different about the CF result vs. the Authorisation result?"?
This is pure hackery.
I wouldn't go to production with this sort of design/impl.

What specifically are you referring to?
yes, its hmac authentication failure because the way coldfusion is generating the hmac is totally different from what the api from java is generating
Can you post an example using dummy keys?
i cannot post the keys, my apologies for this, but instead if you can help me that portion of authoriseString to java, i think i might be able to fix the issue

Thanks
No need to apologize.  Never post real keys, no matter who asks! However, you misunderstood me. I asked if you could post an example using dummy keys .  In other words, create some fake strings of the appropriate length and encoding (plain string, base64, hex, etc...) that you can share.  If you're not sure how to do that

https://www.random.org/bytes/
https://www.random.org/strings/

Edit:  Is there a public URL for this API?
This is what i am doing

<cfscript>	
			Math = createObject('java', 'java.lang.Math');
			SecureRandom = createObject('java', 'java.security.SecureRandom');
			nonce = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong());
			stime = createObject('java','java.time.Instant');
			timestamp = stime.now().toEpochMilli();
			$apiKey = "#arguments.apiKey#";
			$apiSecret = "#arguments.apiSecret#";
			$token = "#arguments.token#";
			$timestamp = timestamp;
			$payload = getPayLoad(merchant_ref='#merchant_ref#',amt_charge='#arguments.amt_charge#',cardtype='#arguments.cardtype#',
			card_holder_name='#arguments.card_holder_name#',card_number='#arguments.card_number#',card_exp='#arguments.card_exp#',
			cvvnumber='#arguments.cvvnumber#');
			httpService = new http(); 
			httpService.setMethod("get"); 
			httpService.setCharset("utf-8"); 
			httpService.setUrl("http://website.in/remote/template.php?_apiKey=#$apiKey#&_token=#$token#&_apiSecret=#$apiSecret#&_timestamp=#$timestamp#&_nonce=#nonce#"); 
			result = httpService.send().getPrefix();
			binaryKey = charsetDecode(apiSecret, "utf-8");
			resultHex = hmac(result.filecontent, binaryKey, "HMACSHA256", "UTF-8");
			authorizeString = binaryEncode(binaryDecode(resultHex, "hex"), "base64");
			result = authorizeString;
		</cfscript>

the template.php is doing this 

<?php 
	$reqbody = file_get_contents('./response.json', true);
	$data = $_GET["_apiKey"] + $_GET["_nonce"] + $_GET["_timestamp"] + $_GET["_token"] + $reqbody;
	echo $data;
?>

Open in new window


the above failed but if i run the java code, it works through a JAR complied file, i want to understand what is wrong with it

response.json is the json file having creditcard information in json string which is correct and i had verified that
getpayload Function is returning me json which is store i the response.json file
Just plug fake values into the java code and print out the authorizeString.  It doesn't need to validate with their API. We just want to compare the string java generates vs. the one CF generates.

>> String authorizeString = new String(Base64.encodeBase64(toHex(macHash)));

What is the java code for toHex() ?  Is there a public URL for this API?
to be honest i seriously do not know what you are asking, i know u are asking about the string value but i do not have an environment to run java code all i can run jar file but that only returns me the success or failure as to what i need

also is there any kind of java fiddle where we can test it, we do have coldfusion fiddle called as trycf.com but kind of java will probably work
i am giving u the demo keys so u can compare

apiKey = "bfvCs2v0BlGr2GlKn55b5iDeRDcX0AMs";
apiSecret = "4012faf411afc618b77f0703ad1c37be8eff8d8337e8e7571364d35c49edf003";
token = "fdoa-a480ce8951daa73262734cf102641994c1e55e7cdf4c02b6";

Open in new window

What API is this? Please post the URL.
its an internal, i cannot post sorry, will not be accessible with the url , its ip restricted

I hope the amount of data i shared, we can do something
ASKER CERTIFIED SOLUTION
Avatar of _agx_
_agx_
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This example returns the same result as the java example in the Payeezy API.