This repository was archived by the owner on Feb 27, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
This repository was archived by the owner on Feb 27, 2025. It is now read-only.
Update HpsTokenService to support SSL pinning #7
Copy link
Copy link
Open
Description
Hello,
Please, update HpsTokenService to support SSL pinning. Updated implementation is provided below.
Thanks!
public class HpsTokenService {
private String mPublicKey;
private String mCertificateBase64EncodedPublicKey;
private String mUrl;
public HpsTokenService(String publicKey, String certificateBase64EncodedPublicKey) {
mPublicKey = publicKey;
mCertificateBase64EncodedPublicKey = certificateBase64EncodedPublicKey;
if (publicKey == null) {
throw new IllegalArgumentException("publicKey can not be null");
}
String[] components = mPublicKey.split("_");
if (components.length < 3) {
throw new IllegalArgumentException("publicKey format invalid");
}
String env = components[1].toLowerCase();
if (env.equals("prod")) {
mUrl = "https://api2.heartlandportico.com/SecureSubmit.v1/api/token";
} else {
mUrl = "https://cert.api2.heartlandportico.com/Hps.Exchange.PosGateway.Hpf.v1/api/token";
}
}
public HpsToken getToken(HpsCreditCard card) throws IOException {
HttpsURLConnection conn = (HttpsURLConnection) new URL(mUrl).openConnection();
HpsToken result = null;
byte[] creds = String.format("%s:", mPublicKey).getBytes();
String auth = String.format("Basic %s", Base64.encodeBase64URLSafeString(creds));
Gson gson = new Gson();
String payload = gson.toJson(new HpsToken(card));
byte[] bytes = payload.getBytes();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.addRequestProperty("Authorization", auth);
conn.addRequestProperty("Content-Type", "application/json");
conn.addRequestProperty("Content-Length", String.format("%s", bytes.length));
conn.connect();
if (isSslPinningSuccessful(conn)) {
DataOutputStream requestStream = new DataOutputStream(conn.getOutputStream());
requestStream.write(bytes);
requestStream.flush();
requestStream.close();
try {
InputStreamReader responseStream = new InputStreamReader(conn.getInputStream());
result = gson.fromJson(responseStream, HpsToken.class);
responseStream.close();
} catch (IOException e) {
if (conn.getResponseCode() == 400) {
InputStreamReader errorStream = new InputStreamReader(conn.getErrorStream());
result = gson.fromJson(errorStream, HpsToken.class);
errorStream.close();
} else {
throw new IOException(e);
}
}
}
return result;
}
private boolean isSslPinningSuccessful(HttpsURLConnection conn) {
try {
Certificate[] certs = conn.getServerCertificates();
MessageDigest md = MessageDigest.getInstance("SHA-256");
for (Certificate cert : certs) {
X509Certificate x509Certificate = (X509Certificate) cert;
byte[] encodedPublicKey = x509Certificate.getPublicKey().getEncoded();
byte[] encodedPublicKeySha256Bytes = md.digest(encodedPublicKey);
String encodedPublicKeyBase64String = Base64.encodeBase64URLSafeString(encodedPublicKeySha256Bytes);
if (mCertificateBase64EncodedPublicKey.equals(encodedPublicKeyBase64String)) {
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return false;
}
}Best regards,
Mikle Anokhin.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels