I tried the following but still get 401 Unauthorized: [no body]
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("access_key", accessKey);
long currentTimestamp = (System.currentTimeMillis() / 1000) - 10;
headers.add("timestamp", String.valueOf(currentTimestamp));
String randomSalt = generateRandomAlphanumericString();
headers.add("salt", randomSalt);
JSONObject body = new JSONObject();
body.put("amount", 123.45);
body.put("complete_payment_url", "http://example.com/complete");
body.put("country", "ID");
body.put("currency", "IDR");
body.put("error_payment_url", "IDR");
body.put("merchant_reference_id", "IDR");
body.put("cardholder_preferred_currency", "IDR");
body.put("language", "en");
body.put("metadata", "something");
body.put("payment_method_types_include", List.of("id_ovo_ewallet",
"id_dana_ewallet",
"id_linkaja_ewallet"));
String tobeSigned = HttpMethod.POST.toString().toLowerCase() + "/v1/checkout" + randomSalt + currentTimestamp + accessKey
+ secretKey + body;
log.info("to_sign {}",tobeSigned);
String encodedString = encode(secretKey,tobeSigned);
log.info("rapyd_signature {}", encodedString);
headers.add("signature", encodedString);
HttpEntity<String> entity = new HttpEntity<>(body.toString(), headers);
ResponseEntity<String> result = restTemplate.exchange(baseUrl + "/checkout", HttpMethod.POST, entity, String.class);
Use this example from the docs - Message Security (rapyd.net)
Once the body is created, try to do a string replacement of spaces. (You’ll get a signature mismatch if you don’t - in some cases)
body.replace(" ", "");
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Random;
public class GetPOS {
public static String hash256(String data) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(data.getBytes());
return bytesToHex(md.digest());
}
public static String bytesToHex(byte[]bytes) {
StringBuffer result = new StringBuffer();
for (byte byt: bytes)
result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1));
return result.toString();
}
public static String hmacDigest(String msg, String keyString, String algo) {
String digest = null;
try {
SecretKeySpec key = new SecretKeySpec((keyString).getBytes("ASCII"), algo);
Mac mac = Mac.getInstance(algo);
mac.init(key);
byte[]bytes = mac.doFinal(msg.getBytes("UTF-8"));
StringBuffer hash = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
hash.append('0');
}
hash.append(hex);
}
digest = hash.toString();
} catch (UnsupportedEncodingException e) {
System.out.println("hmacDigest UnsupportedEncodingException");
}
catch (InvalidKeyException e) {
System.out.println("hmacDigest InvalidKeyException");
}
catch (NoSuchAlgorithmException e) {
System.out.println("hmacDigest NoSuchAlgorithmException");
}
return digest;
}
public static String givenUsingPlainJava_whenGeneratingRandomStringUnbounded_thenCorrect() {
int leftLimit = 97; // letter 'a'
int rightLimit = 122; // letter 'z'
int targetStringLength = 10;
Random random = new Random();
StringBuilder buffer = new StringBuilder(targetStringLength);
for (int i = 0; i < targetStringLength; i++) {
int randomLimitedInt = leftLimit + (int)
(random.nextFloat() * (rightLimit - leftLimit + 1));
buffer.append((char)randomLimitedInt);
}
String generatedString = buffer.toString();
return (generatedString);
}
public static void main(String[]args)throws Exception {
try {
System.out.println("GetPOS Start");
String httpMethod = "get"; // get|put|post|delete - must be lowercase
String urlPath = "/v1/" + "data/countries"; // hardkeyed for this example
String salt = givenUsingPlainJava_whenGeneratingRandomStringUnbounded_thenCorrect(); // Randomly generated for each request.
long timestamp = System.currentTimeMillis() / 1000L; // Unix time (seconds).
String accessKey = "AAAAAAAAAAA"; // The access key received from Rapyd.
String secretKey = "SSSSSSSSSSS"; // Never transmit the secret key by itself.
bodyString = ""; // Always empty for GET; strip nonfunctional whitespace.
// Must be a String or an empty String.
String toEnc = httpMethod + urlPath + salt + Long.toString(timestamp) + accessKey + secretKey + bodyString;
System.out.println("String to be encrypted::" + toEnc);
String StrhashCode = hmacDigest(toEnc, secretKey, "HmacSHA256");
String signature = Base64.getEncoder().encodeToString(StrhashCode.getBytes());
HttpClient httpclient = HttpClients.createDefault();
try {
HttpGet httpget = new HttpGet("/v1/data/countries");
httpget.addHeader("Content-Type", "application/json");
httpget.addHeader("access_key", accessKey);
httpget.addHeader("salt", salt);
httpget.addHeader("timestamp", Long.toString(timestamp));
httpget.addHeader("signature", signature);
// Create a custom response handler
ResponseHandler < String > responseHandler = new ResponseHandler < String > () {
@ Override
public String handleResponse(
final HttpResponse response)throws ClientProtocolException,
IOException {
int status = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
}
};
String responseBody = httpclient.execute(httpget, responseHandler);
System.out.println("----------------------------------------");
System.out.println(responseBody);
}
finally {
}
} catch (Exception e) {
}
}
}
1 Like
In addition to solution posted @sandy_inspires. These are my own observations in your body parameters. You will need to enter correct value where appropriate
1.) The error_payment_url should be a working url under http or https. Entering anything other thing like localhost will create a no body error message
2.) and Many more.
Finally, here is a clear documentations on how to create a checkout page. checkout page creation doc.
I hope this will also help you in trouble shooting you error
2 Likes
@CharlesDorsett ,you are right. decimal points is not a problem. After I trouble shoot my php codes, I found out they are some whitespaces and little err on my code from my own end. I have fixed it and everything is working great now. Thanks for pointing me out in the right direction…
1 Like
Glad got it working now. Thanks everyone!
4 Likes