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.
Related
I'm trying to connect jira server using java, I'm receiving "404 error".
I'm sharing the base url and code using which i'm trying to connect the jira server, please let me know what is wrong
public class Automate {
public static void main(String[] args) {
String baseURL = "https://thread.atlassian.net/";
String loginURL = "auth/1/session";
String loginUserName = "*********.com";
String loginPassword = "*******";
if (!errorOccurred) {
loginResponse = loginToJira(baseURL, loginURL, loginUserName, loginPassword);
if (loginResponse == "ERROR") {
errorOccurred = true;
}
}
public static String loginToJira(String baseURL, String loginURL, String loginUserName, String loginPassword) {
String loginResponse = "";
URL url = null;
HttpURLConnection conn = null;
String input = "";
OutputStream outputStream = null;
BufferedReader bufferedReader = null;
String output = null;
try {
//Create URL
url = new URL(baseURL + loginURL);
//Use URL to create connection
conn = (HttpURLConnection) url.openConnection();
//Set properties
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("content.type", "application/json");
//Create Json post object
input = "{\"Username\" :\"" + loginUserName + "\" \"Password\" :\"" + loginPassword + "\"}";
//Send our request
outputStream = conn.getOutputStream();
//System.out.println("outputStream:"+outputStream);
outputStream.write(input.getBytes());
//System.out.println("outputStream after writing input:"+outputStream);
outputStream.flush();
//System.out.println("outputStream after Flushing:"+outputStream);
//Handle our response
System.out.println("Get Response :"+ conn.getResponseCode() );
if (conn.getResponseCode() == 200) {
bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
System.out.println("Connection Stream:"+bufferedReader);
while ((output = bufferedReader.readLine()) != null) {
loginResponse += output;
}
conn.disconnect();
}
} catch (Exception ex) {
//Handle errors
System.out.println("Error in login Jira" + ex.getMessage());
return loginResponse = "ERROR";
}
System.out.println("\nloginResponse:");
System.out.println(loginResponse);
return loginResponse;
}
}
Please check the URL again. The page does not exist even when accessed from a browser. Try using just base URL as it redirects to login or a different login URL.
I'm trying to access another server for uploading files with Java. I'm able to connect to the server but I'm unable to upload the file.
The server (Spring Boot application) accepts the file in this way.
#PostMapping(value = ("multipart-store"), headers = ("content-type=multipart/*"))
CustomResponse gridFs(#RequestPart("file") MultipartFile multipartFile) throws Exception {
return new CustomResponse(storageService.storeObject(multipartFile));
}
I had tried couple of ways to access the server.
My Java code to access the server is below.
1st way
try {
final File uploadFile2 = new File("/home/thrymr/Desktop/invoicesample.pdf");
final String requestURL = "http://localhost:8082/data/multipart-store";
final MultipartUtility multipart = new MultipartUtility(requestURL, charset);
multipart.addFilePart("file", uploadFile2);
final List<String> response = multipart.finish();
System.out.println("SERVER REPLIED:");
for (final String line : response) {
System.out.println(line);
}
} catch (final IOException ex) {
System.err.println(ex);
}
public class MultipartUtility {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private final HttpURLConnection httpConn;
private final String charset;
private final OutputStream outputStream;
private final PrintWriter writer;
public MultipartUtility(final String requestURL, final String charset) throws IOException {
this.charset = charset;
this.boundary = "" + System.currentTimeMillis() + "";
final URL url = new URL(requestURL);
this.httpConn = (HttpURLConnection) url.openConnection();
this.httpConn.setUseCaches(false);
this.httpConn.setDoOutput(true); // indicates POST method
this.httpConn.setDoInput(true);
this.httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + this.boundary);
this.outputStream = this.httpConn.getOutputStream();
this.writer = new PrintWriter(new OutputStreamWriter(this.outputStream, charset), true);
}
public void addFilePart(final String fieldName, final File uploadFile) throws IOException {
final String fileName = uploadFile.getName();
this.writer.append("file : "+uploadFile);
this.writer.flush();
final FileInputStream inputStream = new FileInputStream(uploadFile);
final byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
this.outputStream.write(buffer, 0, bytesRead);
}
this.outputStream.flush();
inputStream.close();
this.writer.append(LINE_FEED);
this.writer.flush();
}
public List<String> finish() throws IOException {
final List<String> response = new ArrayList<String>();
this.writer.append(LINE_FEED).flush();
this.writer.append("--" + this.boundary + "--").append(LINE_FEED);
this.writer.close();
final int status = this.httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
final BufferedReader reader = new BufferedReader(new InputStreamReader(this.httpConn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
response.add(line);
}
reader.close();
this.httpConn.disconnect();
} else {
throw new IOException("Server returned non-OK status: " + status);
}
return response;
}
}
2nd way
final File file = new File("/home/thrymr/Desktop/invoicesample.pdf");
final HttpPost post = new HttpPost("http://localhost:8082/data/multipart-store");
final FileBody fileBody = new FileBody(file, ContentType.MULTIPART_FORM_DATA);
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("file", fileBody);
final HttpEntity entity = builder.build();
post.setHeader("Content-Type", "multipart/form-data; boundary=gv");
final CloseableHttpClient client = HttpClients.createDefault();
post.setEntity(entity);
final HttpResponse response = client.execute(post);
System.out.println(response);
In the above addFilePart() method, by replacing this.writer.append("file : "+uploadFile); with below lines of code, i'm able to solve the issue.
this.writer.append("--" + this.boundary).append(LINE_FEED);
this.writer.append("Content-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
this.writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(fileName)).append(LINE_FEED);
this.writer.append(LINE_FEED);
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;
}}
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'
I am new to PHP. I am building an android project which needs to upload images to my server. The problem i am having is that when I send just a key and a value (no file) to the server, it works perfectly fine. However, as soon as I try to send a file, the superglobals $_POST and $_FILES in php are empty! The file sent is very small, so its not go to do with the file_max_upload_size. The file is not corrupted. I think it is something to do with the encoding of of the InputStream sent by the app on the android emulator. My code is below:
Java code in the app that sends the image along with a key-value pair:
public Future<JSONObject> asyncSendPOSTRequest(String URL, Map<String, String> params, Map<String, Pair<String,InputStream>> files) throws InterruptedException, ExecutionException, JSONException, UnsupportedEncodingException {
HttpPost request = new HttpPost(URL);
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
if(params!=null) {
for(String key : params.keySet()) {
multipartEntity.addTextBody(key, params.get(key), ContentType.TEXT_PLAIN);
}
}
if(files!=null) {
for(String key : files.keySet()) {
multipartEntity.addPart(key, new InputStreamBody(files.get(key).second,ContentType.MULTIPART_FORM_DATA, files.get(key).first));
}
}
request.setEntity(multipartEntity.build());
Future<JSONObject> future = threadPool.submit(new executeRequest(request));
return future;
}
//Thread to communicate with server.
private class executeRequest implements Callable<JSONObject> {
HttpRequestBase request;
public executeRequest(HttpRequestBase request) {
this.request = request;
}
#Override
public JSONObject call() throws Exception {
HttpResponse httpResponse = httpClient.execute(request);
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
StringBuilder stringReply = new StringBuilder();
String replyLine;
while ((replyLine = reader.readLine()) != null) {
stringReply.append(replyLine);
}
return new JSONObject(stringReply.toString());
}
}
The code on the server:
#!/usr/bin/php
<?php
$uploads_dir = __DIR__ . '/uploads';
$status = -1;
if ($_FILES["picture"]["error"] == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["picture"]["tmp_name"];
$name = $_FILES["picture"]["name"];
$status = move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
$response["status"] = $status;
$response["user_id"] = $_POST["user_id"];
$response["name"] = $name;
$response["extension"] = end (explode(".", $name));
echo json_encode($response);
?>
The possible problem that you set wrong datatype
enctype="multipart/form-data"
public class Helpher extends AsyncTask<String, Void, String> {
Context context;
JSONObject json;
ProgressDialog dialog;
int serverResponseCode = 0;
DataOutputStream dos = null;
FileInputStream fis = null;
BufferedReader br = null;
public Helpher(Context context) {
this.context = context;
}
protected void onPreExecute() {
dialog = ProgressDialog.show(Main2Activity.this, "ProgressDialog", "Wait!");
}
#Override
protected String doInBackground(String... arg0) {
try {
File f = new File(arg0[0]);
URL url = new URL("http://localhost:8888/imageupload.php");
int bytesRead;
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
String contentDisposition = "Content-Disposition: form-data; name=\"keyValueForFile\"; filename=\""
+ f.getName() + "\"";
String contentType = "Content-Type: application/octet-stream";
dos = new DataOutputStream(conn.getOutputStream());
fis = new FileInputStream(f);
dos.writeBytes(SPACER + BOUNDARY + NEW_LINE);
dos.writeBytes("Content-Disposition: form-data; name=\"parameterKey\""
+ NEW_LINE);
dos.writeBytes(NEW_LINE);
dos.writeBytes("parameterValue" + NEW_LINE);
dos.writeBytes(SPACER + BOUNDARY + NEW_LINE);
dos.writeBytes(contentDisposition + NEW_LINE);
dos.writeBytes(contentType + NEW_LINE);
dos.writeBytes(NEW_LINE);
byte[] buffer = new byte[MAX_BUFFER_SIZE];
while ((bytesRead = fis.read(buffer)) != -1) {
dos.write(buffer, 0, bytesRead);
}
dos.writeBytes(NEW_LINE);
dos.writeBytes(SPACER + BOUNDARY + SPACER);
dos.flush();
int responseCode = conn.getResponseCode();
if (responseCode != 200) {
Log.w(TAG,
responseCode + " Error: " + conn.getResponseMessage());
return null;
}
br = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
Log.d(TAG, "Sucessfully uploaded " + f.getName());
} catch (MalformedURLException e) {
} catch (IOException e) {
} finally {
try {
dos.close();
if (fis != null)
fis.close();
if (br != null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return String.valueOf(serverResponseCode);
}
#Override
protected void onPostExecute(String result) {
dialog.dismiss();
}
}
This is the AsyncTask "Helpher" class used for upload image from Android. To call this class use like syntax below.
new Main2Activity.Helpher(this).execute(fileUri.getPath(),parameterValue);
Here fileUri.getPath() local image location.If you want to see the server response value is avilable in " StringBuilder sb" you can print sb value