SignatureDoesNotMatch when calling MWS GetOrder - java

If I use Action=GetServiceStatus, the program below works fine, returning "200 OK" and an XML response as MWS scratchpad.
But if I just change Action="GetOrder" (and add the required extra string AmazonOrderId.Id.1=xxx-5684184-6801000) then it gives me error 403 "SignatureDoesNotMatch" <RequestID>b055a685-dfbb-494b-8cf5-bcec31e2fa3a</RequestID>.
The program, except for sending the request to read the URL, is taken from Amazon documentation. I copied the query string with the URL.
public class AmazonExample {
private static final String CHARACTER_ENCODING = "UTF-8";
final static String ALGORITHM = "HmacSHA256";
public static void main(String[] args) throws Exception {
String secretKey = "/ioTb2imZWZ/IHTKKfc62BFvBxxxxxxxxxxxxxxx";
// Use the endpoint for your marketplace
String serviceUrl = "https://mws.amazonservices.ca/";
// Create set of parameters needed and store in a map
HashMap<String, String> parameters = new HashMap<String,String>();
// Add required parameters. Change these as needed.
parameters.put("AWSAccessKeyId", urlEncode("AKIAJUTBJCxxxxxxxxxx"));
parameters.put("Action", urlEncode("GetServiceStatus")); //GetOrder
parameters.put("AmazonOrderId.Id.1", urlEncode("xxx-5684184-6801000"));
parameters.put("MWSAuthToken", urlEncode("amzn.mws.xxxxx7b8-5c81-3abc-06c2-c09e7dfd6ef3"));
parameters.put("SellerId", urlEncode("xxxxYI70TZB97A"));
parameters.put("SignatureMethod", urlEncode(ALGORITHM));
parameters.put("SignatureVersion", urlEncode("2"));
parameters.put("SubmittedFromDate",urlEncode("2015-03-14T17:02:05.264Z"));
parameters.put("Timestamp", urlEncode("2015-03-14T17:02:05.264Z"));
parameters.put("Version", urlEncode("2013-09-01"));
String formattedParameters = calculateStringToSignV2(parameters, serviceUrl);
String signature = sign(formattedParameters, secretKey);
// Add signature to the parameters and display final results
parameters.put("Signature", urlEncode(signature));
System.out.println(calculateStringToSignV2(parameters, serviceUrl));
try {
URL url = new URL("https://mws.amazonservices.ca/Orders/2013-09-01/?AWSAccessKeyId=xxxxxxxBJCIA4YSSWYNA&Action=GetServiceStatus&AmazonOrderId.Id.1=xxx-5684184-6801000&MWSAuthToken=amzn.mws.xxxxxxxx-5c81-3abc-06c2-c09e7dfd6ef3&SellerId=xxxxYI70TZB97A&Signature=yyO%2BrwMAtCcuEsYhG4KZILz2cyiSUcrAAWKqf3%2BZ454%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&SubmittedFromDate=2015-03-14T17%3A02%3A05.264Z&Timestamp=2015-03-14T17%3A02%3A05.264Z&Version=2013-09-01");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setConnectTimeout(50000);
BufferedReader br = null;
StringBuffer sbOrderResponse= new StringBuffer();
String order = ""; String str = "";
InputStream inputstream = null;
if(conn.getResponseCode() != 200 ) {
inputstream = conn.getErrorStream();
} else{
inputstream = conn.getInputStream();
}
br = new BufferedReader(new InputStreamReader((inputstream)));
StringBuffer buffer = new StringBuffer();
while ((order = br.readLine()) != null) {
sbOrderResponse.append(order);
str = str + order + "\n";
}
System.out.println(conn.getResponseCode() + " " + conn.getResponseMessage());
System.out.println(str);
} catch(Exception e)
{
System.out.println("Error " + e);
}
}
private static String calculateStringToSignV2(Map<String, String> parameters, String serviceUrl)
throws SignatureException, URISyntaxException {
// Sort the parameters alphabetically by storing
// in TreeMap structure
Map<String, String> sorted = new TreeMap<String, String>();
sorted.putAll(parameters);
// Set endpoint value
URI endpoint = new URI(serviceUrl.toLowerCase());
// Create flattened (String) representation
StringBuilder data = new StringBuilder();
data.append("GET\n");
data.append(endpoint.getHost());
data.append("\n/"); // /Orders/2013-09-01
data.append("\n");
Iterator<Entry<String, String>> pairs = sorted.entrySet().iterator();
while (pairs.hasNext()) {
Map.Entry<String, String> pair = pairs.next();
if (pair.getValue() != null) {
data.append( pair.getKey() + "=" + pair.getValue());
}
else {
data.append( pair.getKey() + "=");
}
// Delimit parameters with ampersand (&)
if (pairs.hasNext()) {
data.append( "&");
}
}
return data.toString();
}
/*
* Sign the text with the given secret key and convert to base64
*/
private static String sign(String data, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException,
IllegalStateException, UnsupportedEncodingException {
Mac mac = Mac.getInstance(ALGORITHM);
mac.init(new SecretKeySpec(secretKey.getBytes(CHARACTER_ENCODING), ALGORITHM));
byte[] signature = mac.doFinal(data.getBytes(CHARACTER_ENCODING));
String signatureBase64 = new String(Base64.encodeBase64(signature), CHARACTER_ENCODING);
return new String(signatureBase64);
}
private static String urlEncode(String rawValue) {
String value = (rawValue == null) ? "" : rawValue;
String encoded = null;
try {
encoded = URLEncoder.encode(value, CHARACTER_ENCODING)
.replace("+", "%20")
.replace("*", "%2A")
.replace("%7E","~");
} catch (UnsupportedEncodingException e) {
System.err.println("Unknown encoding: " + CHARACTER_ENCODING);
e.printStackTrace();
}
return encoded;
}}

Related

Handling POST Requests in Java Http server

I'm trying to handle a simple base64 string in my HTTP server by sending a POST request from postman with the String i need.
When I debug my server, i can see the request coming in, but the parameter is not transmitted.
I found this piece of code to handle POST request, but even though i see the request coming in, I cannot retrieve the value.
Any help would be appreciated, this is what I got now, and the response is empty:
public void handle(HttpExchange t) throws IOException, FileNotFoundException {
Map<String, Object> parameters = new HashMap<String, Object>();
InputStreamReader isr = new InputStreamReader(t.getRequestBody(), "utf-8");
BufferedReader br = new BufferedReader(isr);
String query = br.readLine();
parseQuery(query, parameters);
// send response
String response = "lol";
for (String key : parameters.keySet()) {
response += key + " = " + parameters.get(key) + "\n ";
}
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.toString().getBytes());
os.close();
public static void parseQuery(String query, Map<String, Object> parameters) throws UnsupportedEncodingException {
if (query != null) {
String pairs[] = query.split("[&]");
for (String pair : pairs) {
String param[] = pair.split("[=]");
String key = null;
String value = null;
if (param.length > 0) {
key = URLDecoder.decode(param[0],
System.getProperty("file.encoding"));
}
if (param.length > 1) {
value = URLDecoder.decode(param[1],
System.getProperty("file.encoding"));
}
if (parameters.containsKey(key)) {
Object obj = parameters.get(key);
if (obj instanceof List<?>) {
List<String> values = (List<String>) obj;
values.add(value);
} else if (obj instanceof String) {
List<String> values = new ArrayList<String>();
values.add((String) obj);
values.add(value);
parameters.put(key, values);
}
} else {
parameters.put(key, value);
}
}
}
}

error :- {"code":"403", "message":"HMAC validation Failure"}

Here i am attaching code and a link consist of full code , have a look on it:-
My authorization header seams to be coming of same length as mentioned in official site of payeezy.I have also make my hmacString of same order as mentioned in this link (https://developer.payeezy.com/content/hmac-validation-failure) . After doing all this i am still getting this same issue
public static String excutePost(String urlParameters) throws IOException {
URL url = new URL("https://api-cert.payeezy.com/v1/transactions");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
// Create connection
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", headerContentType);
connection.setRequestProperty("apikey ", apikey);
connection.setRequestProperty("token", MerchantToken);
connection
.setRequestProperty("Authorization", authorizationHeader);
connection.setRequestProperty("timestamp", ""+epoch);
connection.setRequestProperty("nonce", ""+nonce);
connection.setDoOutput(true);
connection.setReadTimeout(30000);
// Send request
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
// Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while ((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
Here is full java class code :- http://piratepad.net/ep/pad/view/ro.WwZ9v6FX1a6/latest
I finally solve this error by sending direct String as parameter in api url hit.Here i am posting some of my code which solve my error :-
String str = "{\"amount\":\"1299\",\"merchant_ref\":\"Astonishing-Sale\",\"transaction_type\":\"authorize\",\"credit_card\":{\"card_number\":\"4788250000028291\",\"cvv\":\"123\",\"exp_date\": \"1020\",\"cardholder_name\": \"John Smith\",\"type\": \"visa\"},\"method\": \"credit_card\",\"currency_code\": \"USD\"}";
now this String will be used in generating my authorisation key.
the whole process is defined below :-
getSecurityKeys(apikey, pzsecret,str);
private static Map<String, String> getSecurityKeys(String appId,
String secureId, String payLoad) throws Exception {
Map<String, String> returnMap = new HashMap<String, String>();
try {
returnMap.put(NONCE, Long.toString(nonce));
returnMap.put(APIKEY, appId);
returnMap.put(TIMESTAMP, Long.toString(System.currentTimeMillis()));
returnMap.put(TOKEN, MerchantToken);
returnMap.put(APISECRET, pzsecret);
returnMap.put(PAYLOAD, payLoad);
returnMap.put(AUTHORIZE, getMacValue(returnMap));
authorizationHeader = returnMap.get(AUTHORIZE);
return returnMap;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public static String getMacValue(Map<String, String> data) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
String apiSecret = data.get(APISECRET);
SecretKeySpec secret_key = new SecretKeySpec(apiSecret.getBytes(),
"HmacSHA256");
mac.init(secret_key);
StringBuilder buff = new StringBuilder();
buff.append(data.get(APIKEY)).append(data.get(NONCE))
.append(data.get(TIMESTAMP));
if (data.get(TOKEN) != null)
buff.append(data.get(TOKEN));
if (data.get(PAYLOAD) != null)
buff.append(data.get(PAYLOAD));
byte[] macHash = mac.doFinal(buff.toString().getBytes("UTF-8"));
String authorizeString = Base64.encodeBase64String(toHex(macHash));
return authorizeString;
}
Now finally you can pass direct String(i.e str) as parameter in hitting post api in java.
hope it helps other to integrate payeezy payment gateway without using any dependencies.
Happy Codeing!!!
You must generate a new timestamp and nonce for every request, i.e., every new request must have its unique timestamp and nonce.
In java, timestamp can be set as System.currentTimeMillis() and nonce can be set using UUID (UUID.randomUUID().toString()).
Finally, make sure that your Authorization is correctly computed (I see they use HMAC-SHA1 using API secret key).
I hope this helps.
Edit: As suspected, it's your HMAC-SHA1 Authorization value that is incorrect. I get the following response when running your code (after few coding of my own).
Connection = keep-alive
Content-Length = 51
Content-Type = application/json
{"code":"403", "message":"HMAC validation Failure"}
Make sure that you compute your HMAC-SHA1 value correctly (as I said above).
See the below (updated) code that you can compile and run for yourself. You will need Java 8 as it comes with Base 64 encoder/decoder now.
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.net.URI;
import java.net.URL;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.TimeZone;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
//import org.apache.commons.codec.binary.Base64;
public class MainJava {
private static final String myEncoding = "UTF-8";
private static final String myMessageDigest = "SHA-1";
private static final String myKeySpec = "HmacSHA1";
private static String NEWLINE = "\n";
private static String authorizationHeader;
private static String contentSha1;
// private static String keyId = "230297";
// private static String hmacKey = "tcwR9r1OR85V9bcV5tc7a9d1XkWigjqY";
private static String ApiSecretkey = "0779eb593286b278aaf8cfcf83c8e33bc757d53a8a642b53d24d63bda844da5b";
private static String MerchantToken = "fdoa-a480ce8951daa73262734cf102641994c1e55e7cdf4c02b6";
private static String reportingToken = "e56a0223d0415067";
private static String apikey = "XSjbv8PLDINJ28qXLEYAhcrz8rxKXQ4Y";
private static long nonce;
public static String headerContentType = "application/json";
private static long epoch;
public static void main(String[] args) throws Exception {
String json_string_dataTwo = "{\"type\":\"visa\",\"cardholder_name\":\"John Smith\",\"card_number\":\"4788250000028291\",\"exp_date\":1020,\"cvv\":\"123\"}";
// String json_string =
// "{\"gateway_id\":\"AI2010-01\",\"password\":\"w226638qtot48xu503zumwt2iy46g26q\",\"transaction_type\":\"00\",\"amount\":10,\"cardholder_name\":\"test\",\"cc_number\":\"4111111111111111\",\"cc_expiry\":\"1219\"}";
String json_string_data = "{\"merchant_ref\":\"Astonishing-Sale\",\"transaction_type\":\"authorize\",\"method\":\"credit_card\",\"amount\":1299,\"currency_code\":\"USD\",\"credit_card\":"
+ json_string_dataTwo + "}";
// "{\r\n \"merchant_ref\": \"Astonishing-Sale\",\r\n \"transaction_type\": \"authorize\",\r\n \"method\": \"credit_card\",\r\n \"amount\": \"1299\",\r\n \"currency_code\": \"USD\",\r\n \"credit_card\": {\r\n \"type\": \"visa\",\r\n \"cardholder_name\": \"John Smith\",\r\n \"card_number\": \"4788250000028291\",\r\n \"exp_date\": \"1020\",\r\n \"cvv\": \"123\"\r\n }\r\n}";
epoch = System.currentTimeMillis();// / 1000;
// nonce = UUID.randomUUID().toString();
nonce = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong());
contentSha1 = contentSha1(json_string_data);
authorizationHeader = authHeader(epoch, contentSha1);
System.out.println(excutePost(json_string_data));
}
private static String authHeader(long hashTime, String contentSha1) {
String authorizationHeader = null;
try {
String hmacString = "POST" + NEWLINE + "application/json" + NEWLINE + contentSha1 + NEWLINE + hashTime + NEWLINE + apikey + NEWLINE
+ new URI("https://api-cert.payeezy.com/v1/transactions");
return sha1(hmacString, ApiSecretkey);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static String contentSha1(String content) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] sha1hash = new byte[40];
md.update(content.getBytes("UTF-8"), 0, content.length());
sha1hash = md.digest();
return convertToHex(sha1hash);
}
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = data[i] >>> 4 & 0xF;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) (48 + halfbyte));
else
buf.append((char) (97 + (halfbyte - 10)));
halfbyte = data[i] & 0xF;
} while (two_halfs++ < 1);
}
return buf.toString();
}
// private static String sha1(String s, String keyString) {
// Base64 base64 = new Base64();
// try {
// SecretKeySpec key = new SecretKeySpec(keyString.getBytes("UTF-8"),
// "HmacSHA1");
// Mac mac = Mac.getInstance("HmacSHA1");
// mac.init(key);
// byte[] bytes = mac.doFinal(s.getBytes("UTF-8"));
//
// return new String(base64.encode(bytes));
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// }
private static String sha1(String s, String keyString) {
byte[] bytes = null;
try {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(keyString.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);
bytes = sha256_HMAC.doFinal(s.getBytes("UTF-8"));
//return new String(Base64.encodeBase64String(bytes));
} catch (Exception e) {
System.out.println("Error");
}
return Base64.getEncoder().encodeToString(bytes);
}
private static String hashTime() {
String time = getUTCFormattedDate("yyyy-MM-dd'T'HH:mm:ss'Z'");
return time;
}
private static String getUTCFormattedDate(String format) {
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return dateFormat.format(new Date());
}
public static String excutePost(String urlParameters) throws IOException {
System.out.println(urlParameters);
System.out.println(headerContentType);
System.out.println(MerchantToken);
System.out.println(authorizationHeader);
System.out.println(epoch);
System.out.println(nonce);
URL url = new URL("https://api-cert.payeezy.com/v1/transactions");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
// Create connection
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", headerContentType);
connection.setRequestProperty("apikey ", apikey);
connection.setRequestProperty("token", MerchantToken);
connection.setRequestProperty("Authorization", authorizationHeader);
connection.setRequestProperty("timestamp", "" + epoch);
connection.setRequestProperty("nonce", "" + nonce);
connection.setDoOutput(true);
connection.setReadTimeout(30000);
// Send request
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
// Get Response
InputStream is = null;
int statusCode = connection.getResponseCode();
try {
is = connection.getInputStream();
} catch (IOException e) {
if (statusCode >= 400) {
is = connection.getErrorStream();
}
}
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while ((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
My only issue is with the character encoding, where I assume UTF-8. I suspect that the error lies elsewhere.
// Send request
byte[] data = urlParameters.getBytes(StandardCharsets.UTF_8);
BufferedOutputStream wr = new BufferedOutputStream(connection.getOutputStream());
wr.writeBytes(data);
wr.close();
// Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is,
StandardCharsets.UTF_8));
And \r, CR, does not serve as line separator (apart from old MacOS).
response.append("\r\n"); // Or '\n'

HTTP client not working

I am trying to build a simple HTTP client program that sends a request to a web server and prints the response out to the user.
I have got the following error when I run my code and I am not sure what is causing it:
-1
Exception in thread "main" java.lang.IllegalArgumentException: port out of range:-1
at java.net.InetSocketAddress.(InetSocketAddress.java:118)
at java.net.Socket.(Socket.java:189)
at com.example.bookstore.MyHttpClient.execute(MyHttpClient.java:18)
at com.example.bookstore.MyHttpClientApp.main(MyHttpClientApp.java:29)
Java Result: 1
Below is my MyHttpClient.java class
public class MyHttpClient {
MyHttpRequest request;
public MyHttpResponse execute(MyHttpRequest request) throws IOException {
this.request = request;
int port = request.getPort();
System.out.println(port);
//Create a socket
Socket s = new Socket(request.getHost(), request.getPort());
//Create I/O streams
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter outToServer = new PrintWriter(s.getOutputStream());
//Get method (POST OR GET) from request
String method = request.getMethod();
//Create response
MyHttpResponse response = new MyHttpResponse();
//GET Request
if(method.equalsIgnoreCase("GET")){
//Construct request line
String path = request.getPath();
String queryString = request.getQueryString();
//Send request line to server
outToServer.println("GET " + path + " HTTP/1.0");
//=================================================\\
//HTTP RESPONSE
//RESPONSE LINE
//Read response from server
String line = inFromServer.readLine();
//Get response code - should be 200.
int status = Integer.parseInt(line.substring(9, 3));
//Get text description of response code - if 200 should be OK.
String desc = line.substring(13);
//HEADER LINES
//Loop through headers until get to blank line...
//Header name: Header Value - structure
do{
line = inFromServer.readLine();
if(line != null && line.length() == 0){
//line is not blank
//header name start of line to the colon.
String name = line.substring(0, line.indexOf(": "));
//header value after the colon to end of line.
String value = String.valueOf(line.indexOf(": "));
response.addHeader(name, value);
}
}while(line != null && line.length() == 0);
//MESSAGE BODY
StringBuilder sb = new StringBuilder();
do{
line = inFromServer.readLine();
if(line != null){
sb.append((line)+"\n");
}
}while(line != null);
String body = sb.toString();
response.setBody(body);
//return response
return response;
}
//POST Request
else if(method.equalsIgnoreCase("POST")){
return response;
}
return response;
}
}
This is the MyHttpClientApp.java class
public class MyHttpClientApp {
public static void main(String[] args) {
String urlString = null;
URI uri;
MyHttpClient client;
MyHttpRequest request;
MyHttpResponse response;
try {
//==================================================================
// send GET request and print response
//==================================================================
urlString = "http://127.0.0.1/bookstore/viewBooks.php";
uri = new URI(urlString);
client = new MyHttpClient();
request = new MyHttpRequest(uri);
request.setMethod("GET");
response = client.execute(request);
System.out.println("=============================================");
System.out.println(request);
System.out.println("=============================================");
System.out.println(response);
System.out.println("=============================================");
}
catch (URISyntaxException e) {
String errorMessage = "Error parsing uri (" + urlString + "): " + e.getMessage();
System.out.println("MyHttpClientApp: " + errorMessage);
}
catch (IOException e) {
String errorMessage = "Error downloading book list: " + e.getMessage();
System.out.println("MyHttpClientApp: " + errorMessage);
}
}
}
MyHttpRequest
public class MyHttpRequest {
private URI uri;
private String method;
private Map<String, String> params;
public MyHttpRequest(URI uri) {
this.uri = uri;
this.method = null;
this.params = new HashMap<String, String>();
}
public String getHost() {
return this.uri.getHost();
}
public int getPort() {
return this.uri.getPort();
}
public String getPath() {
return this.uri.getPath();
}
public void addParameter(String name, String value) {
try {
name = URLEncoder.encode(name, "UTF-8");
value = URLEncoder.encode(value, "UTF-8");
this.params.put(name, value);
}
catch (UnsupportedEncodingException ex) {
System.out.println("URL encoding error: " + ex.getMessage());
}
}
public Map<String, String> getParameters() {
return this.params;
}
public String getQueryString() {
Map<String, String> parameters = this.getParameters();
// construct StringBuffer with name/value pairs
Set<String> names = parameters.keySet();
StringBuilder sbuf = new StringBuilder();
int i = 0;
for (String name : names) {
String value = parameters.get(name);
if (i != 0) {
sbuf.append("&");
}
sbuf.append(name);
sbuf.append("=");
sbuf.append(value);
i++;
}
return sbuf.toString();
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
#Override
public String toString() {
StringBuilder sbuf = new StringBuilder();
sbuf.append(this.getMethod());
sbuf.append(" ");
sbuf.append(this.getPath());
if (this.getMethod().equals("GET")) {
if (this.getQueryString().length() > 0) {
sbuf.append("?");
sbuf.append(this.getQueryString());
}
sbuf.append("\n");
sbuf.append("\n");
}
else if (this.getMethod().equals("POST")) {
sbuf.append("\n");
sbuf.append("\n");
sbuf.append(this.getQueryString());
sbuf.append("\n");
}
return sbuf.toString();
}
}
MyHttpResponse
public class MyHttpResponse {
private int status;
private String description;
private Map<String, String> headers;
private String body;
public MyHttpResponse() {
this.headers = new HashMap<String, String>();
}
public int getStatus() {
return this.status;
}
public void setStatus(int status) {
this.status = status;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public Map<String, String> getHeaders() {
return this.headers;
}
public void addHeader(String header, String value) {
headers.put(header, value);
}
public String getBody() {
return body;
}
public void setBody(String is) {
this.body = is;
}
#Override
public String toString() {
StringBuilder sbuf = new StringBuilder();
sbuf.append("Http Response status line: ");
sbuf.append("\n");
sbuf.append(this.getStatus());
sbuf.append(" ");
sbuf.append(this.getDescription());
sbuf.append("\n");
sbuf.append("---------------------------------------------");
sbuf.append("\n");
sbuf.append("Http Response headers: ");
sbuf.append("\n");
for (String key: this.getHeaders().keySet()) {
String value = this.getHeaders().get(key);
sbuf.append(key);
sbuf.append(": ");
sbuf.append(value);
sbuf.append("\n");
}
sbuf.append("---------------------------------------------");
sbuf.append("\n");
sbuf.append("Http Response body: ");
sbuf.append("\n");
sbuf.append(this.getBody());
sbuf.append("\n");
return sbuf.toString();
}
}
Any ideas what might be happening? Many thanks in advance.
I guess your request don't specify a port explicitly and so your request.getPort() is returning -1. And then you try to connect to port -1. And this is illegal.
Instead of that, before using the port : check if it is <= 0 and in this case use 80 as default value.
int port = request.getPort();
if(port<=0) port=80;
since there is no set port in the URI, as of javadocs -1 is returned from port:
http://docs.oracle.com/javase/6/docs/api/java/net/URI.html#getPort()
The port component of this URI, or -1 if the port is undefined
Lots of recreating the wheel going on here. Why not use Java's in-built HTTP client (at least; there are also many third-party HTTP clients out there that do very nicely).
URL url = new URL("http://stackoverflow.com");
final HttpURLConnection connection = url.openConnection();
connection.setDoInput(true);
connection.connect();
int responseCode = connection.getResponseCode();
etc.
use
uri = URIUtil.encodeQuery(urlString)
instead
uri = new URI(urlString);

Java - Creating Github v3 Public Key

I can't figure this one out. I'm trying to dynamically roll keys. I can create the POST request fine, but receive a 400 error and a stacktrace with an IOException when I call post. Below is a self-contained example. I'm using JSCH to generate keys. API doc: http://developer.github.com/v3/users/keys/
The API call: POST /user/keys
public static class LiberalHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
public static String post(String requestUrl, Map<String, String> params,
String username, String password) throws Exception {
String data = "";
int paramCount = 1;
for (Entry<String, String> param : params.entrySet()) {
if (paramCount == 1) {
data = URLEncoder.encode(param.getKey(), "UTF-8") + "="
+ URLEncoder.encode(param.getValue(), "UTF-8");
} else {
data += "&" + URLEncoder.encode(param.getKey(), "UTF-8") + "="
+ URLEncoder.encode(param.getValue(), "UTF-8");
}
paramCount++;
}
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) (url).openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setHostnameVerifier(new LiberalHostnameVerifier());
BASE64Encoder enc = new BASE64Encoder();
String userAuth = username + ":" + password;
String encodedAuthorization = enc.encode(userAuth.getBytes());
conn.setRequestProperty("Authorization", "Basic " + encodedAuthorization);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
BufferedReader rd = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line;
String response = "";
while ((line = rd.readLine()) != null) {
response += line;
}
wr.close();
rd.close();
return response;
}
public static KeyPair generateKey(String filename) throws Exception {
JSch jsch = new JSch();
try {
KeyPair kpair = KeyPair.genKeyPair(jsch, KeyPair.RSA);
kpair.setPassphrase("");
kpair.writePrivateKey(filename + ".pem");
kpair.writePublicKey(filename + ".pub", "Auto-generated.");
System.out.println("Finger print: " + kpair.getFingerPrint());
// kpair.dispose();
return kpair;
} catch (Exception e) {
System.out.println(e);
}
return null;
}
public static String getFileContents(File file) throws Exception {
byte[] buffer = new byte[(int) file.length()];
FileInputStream f = new FileInputStream(file);
f.read(buffer);
return new String(buffer);
}
public static String createKey(String title) throws Exception {
generateKey(title);
final String key = getFileContents(new File(
"/Users/franklovecchio/Desktop/development/" + title
+ ".pub"));
System.out.println("key: " + key);
Map<String, String> params = new HashMap<String, String>() {
{
put("title", title);
put("key", key);
}
};
return post("https://api.github.com/user/keys", params, "username",
"password");
}
// call createKey("key);
Thanks to #nico_ekito and #J-16 SDiZ for helping in the right direction. If you look closely at the documentation, the request doesn't use standard POST parameters, but rather takes JSON as Raw Input, and the ssh-rsa key can NOT be encoded. Next up, I can't get GSON to not encode a string, even using disableHtmlEscaping. So, I had to fake it:
String json = "{\"title\":\"" + title + "\",\"key\":\"" + key.trim() + "\"}";
Did you try a ssh library (e.g. JSch). They can generate RSA key in SSH consumable format.

blackberry linkedin integration error when getting OAuth Token

I am trying to integrate Linkedin in Blackberry. I followed Linkedin's instructions on Getting an OAuth Token.
I get the request token successfully. After that I send a request to get the access token. Then it's showing the error code 401. How to resolve the error?
oauth_problem=signature_invalid&oauth_problem_advice=com.linkedin.security.auth.pub.LoginDeniedInvalidAuthTokenException%20while%20obtaining%20request%20token%20for%20%3APOST%26https%253A%252F%252Fapi.linkedin.com%252Fuas%252Foauth%252FaccessToken%26oauth_consumer_key%ffffffffffff%2526oauth_nonce%253D8928851959000826448%2526oauth_signature_method%253DHMAC-SHA1%2526oauth_timestamp%253D1329997670%2526oauth_token%253Dc98f4ecf-26b5-44aa-a11f-8384ecdacac0%2526oauth_verifier%253D85932%2526oauth_version%253D1.0%0AOAU%3Adkkyeudmhykb%7Cc98f4ecf-26b5-44aa-a11f-8384ecdacac0%7C%2A01%7C%2A01%3A1329997670%3AUDYg4juNLVHzmP7vk%2FRSfhihLlI%3DAccess tockenem=signature_invalid
The problem advice decodes to
com.linkedin.security.auth.pub.LoginDeniedInvalidAuthTokenException while obtaining request token for :POST&https%3A%2F%2Fapi.linkedin.com%2Fuas%2Foauth%2FaccessToken&oauth_consumer_key▒ffffffffff%26oauth_nonce%3D8928851959000826448%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1329997670%26oauth_token%3Dc98f4ecf-26b5-44aa-a11f-8384ecdacac0%26oauth_verifier%3D85932%26oauth_version%3D1.0OAU:dkkyeudmhykb|c98f4ecf-26b5-44aa-a11f-8384ecdacac0|*01|*01:1329997670:UDYg4juNLVHzmP7vk/RSfhihLlI=Access tockenem=signature_invalid
That embedded URL decodes do
https://api.linkedin.com/uas/oauth/accessToken&oauth_consumer_key▒ffffffffff&oauth_nonce=8928851959000826448&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1329997670&oauth_token=c98f4ecf-26b5-44aa-a11f-8384ecdacac0&oauth_verifier=85932&oauth_version=1.0OAU:dkkyeudmhykb|c98f4ecf-26b5-44aa-a11f-8384ecdacac0|*01|*01:1329997670:UDYg4juNLVHzmP7vk/RSfhihLlI=
My code is -
InputStream input = null;
HttpConnection connection = null;
String url = "https://api.linkedin.com/uas/oauth/accessToken";
if ((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) && RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) {
url += ";interface=wifi";
}
String header = oauth_header1(url, HttpProtocolConstants.HTTP_METHOD_POST);
requestTokenUrl = concatURL(url, header);
Dialog.alert("=============="+requestTokenUrl);
try{
connection = (HttpConnection) Connector.open(requestTokenUrl);
connection.setRequestMethod(HttpProtocolConstants.HTTP_METHOD_POST);
input = connection.openDataInputStream();
int resp = connection.getResponseCode();
Dialog.alert(resp+"");
if (resp == HttpConnection.HTTP_OK) {
StringBuffer buffer = new StringBuffer();
int ch;
while ( (ch = input.read()) != -1){
buffer.append( (char) ch);
}
String content = buffer.toString();
Dialog.alert(content);
}
public static String oauth_header1(String url, String method) {
String nonce = nonce();
long timestamp = timestamp();
Const.nonce=nonce;
Const.time=Long.toString(timestamp);
Hashtable pairs = new Hashtable();
String ll=Const.OAUTH_TOKEN_val;
pairs.put("oauth_consumer_key",Const.consumerKey);
pairs.put("oauth_nonce",nonce);
pairs.put("oauth_signature_method",Const.SIGNATURE_METHOD);
pairs.put("oauth_timestamp",Long.toString(timestamp));
pairs.put("oauth_token",ll);
pairs.put("oauth_verifier",Const.ver);
pairs.put("oauth_version","1.0");
String sig1 = signature(method, url, pairs);
//http://linkedin_oauth/success
StringBuffer header_sb = new StringBuffer();
header_sb.append("oauth_consumer_key=").append(URLUTF8Encoder.encode(Const.consumerKey)).append("&");
header_sb.append("oauth_nonce=").append(URLUTF8Encoder.encode(nonce)).append("&");
header_sb.append("oauth_signature_method=").append(URLUTF8Encoder.encode(Const.SIGNATURE_METHOD)).append("&");
header_sb.append("oauth_signature=").append(URLUTF8Encoder.encode(sig1)).append("&");
header_sb.append("oauth_timestamp=").append(Long.toString(timestamp)).append("&");
header_sb.append("oauth_token=").append(URLUTF8Encoder.encode(ll)).append("&");
header_sb.append("oauth_verifier=").append(URLUTF8Encoder.encode(Const.ver)).append("&");
header_sb.append("oauth_version=").append(URLUTF8Encoder.encode("1.0"));
return header_sb.toString();
}
private static String signature(String method, String requestURL, Hashtable pairs) {
StringBuffer sb = new StringBuffer();
String[] keys = new String[pairs.size()];
Enumeration e = pairs.keys();
int i = 0;
while(e.hasMoreElements()) {
String k = (String)e.nextElement();
keys[i++] = k + "=" + URLUTF8Encoder.encode((String)pairs.get(k));
}
Arrays.sort(keys, new Comparator() {
public int compare(Object arg0, Object arg1) {
return ((String)arg0).compareTo((String)arg1);
}
});
for(i = 0; i < keys.length; i++) {
sb.append(keys[i]).append('&');
}
sb.deleteCharAt(sb.length()-1);
String msg = method.toUpperCase() +"&" + URLUTF8Encoder.encode(requestURL) + "&" + URLUTF8Encoder.encode(sb.toString());
System.out.println(msg);
StringBuffer key = new StringBuffer();
if(Const.consumerSecret != null) key.append(URLUTF8Encoder.encode(Const.consumerSecret));
key.append('&');
if(Const.tokenSecret != null){
key.append(URLUTF8Encoder.encode(Const.tokenSecret));
}
try {
return hmacsha1(key.toString(), msg);
} catch (Exception ex) {
return null;
}
}
public static String concatURL(String url, String header){
String newurl=url;
header = header.replace(',', '&');
newurl = newurl+"?"+header;
return newurl;
}
private static String hmacsha1(String key, String message)
throws CryptoTokenException, CryptoUnsupportedOperationException, IOException {
HMACKey k = new HMACKey(key.getBytes());
HMAC hmac = new HMAC(k, new SHA1Digest());
hmac.update(message.getBytes());
byte[] mac = hmac.getMAC();
return Base64OutputStream.encodeAsString(mac, 0, mac.length, false, false);
}

Categories

Resources