Skip to main content

Java Client

Code example for Java

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.Instant;
import java.util.HexFormat;
import java.util.Map;

public class PaymentEngineClient {
private final String apiKey;
private final String secretKey;
private final String baseUrl;
private final HttpClient httpClient;
private final ObjectMapper mapper;

public PaymentEngineClient(String apiKey, String secretKey) {
this(apiKey, secretKey, "https://api.2settle.io");
}

public PaymentEngineClient(String apiKey, String secretKey, String baseUrl) {
this.apiKey = apiKey;
this.secretKey = secretKey;
this.baseUrl = baseUrl;
this.httpClient = HttpClient.newHttpClient();
this.mapper = new ObjectMapper();
}

private SignedRequest sign(String method, String path, Object body) throws Exception {
String timestamp = String.valueOf(Instant.now().toEpochMilli());
String bodyStr = mapper.writeValueAsString(body == null ? Map.of() : body);
String bodyHash = sha256(bodyStr);
String payload = timestamp + "|" + method + "|" + path + "|" + bodyHash;
String hmacKey = sha256(secretKey);
String signature = hmacSha256(hmacKey, payload);

return new SignedRequest(timestamp, signature, bodyStr);
}

private Map<String, Object> request(String method, String path, Object body) throws Exception {
SignedRequest signed = sign(method, path, body);

HttpRequest.Builder builder = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + path))
.header("Content-Type", "application/json")
.header("X-API-Key", apiKey)
.header("X-Timestamp", signed.timestamp())
.header("X-Signature", signed.signature());

if ("GET".equals(method)) {
builder.GET();
} else {
builder.method(method, HttpRequest.BodyPublishers.ofString(signed.body()));
}

HttpResponse<String> response = httpClient.send(
builder.build(),
HttpResponse.BodyHandlers.ofString()
);

return mapper.readValue(response.body(), Map.class);
}

public Map<String, Object> createPayment(Map<String, Object> options) throws Exception {
return request("POST", "/v1/payments", options);
}

public Map<String, Object> getPayment(String reference) throws Exception {
return request("GET", "/v1/payments/" + reference, Map.of());
}

public Map<String, Object> claimGift(String reference, Map<String, Object> receiver) throws Exception {
return request(
"POST",
"/v1/payments/gifts/" + reference + "/claim/confirm",
Map.of("receiver", receiver)
);
}

public Map<String, Object> fulfillRequest(
String reference,
Map<String, Object> payer,
String crypto,
String network
) throws Exception {
return request(
"POST",
"/v1/payments/requests/" + reference + "/fulfill",
Map.of(
"payer", payer,
"crypto", crypto,
"network", network
)
);
}

private static String sha256(String value) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(value.getBytes(StandardCharsets.UTF_8));
return HexFormat.of().formatHex(hash);
}

private static String hmacSha256(String key, String payload) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] hash = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8));
return HexFormat.of().formatHex(hash);
}

private record SignedRequest(String timestamp, String signature, String body) {}

public static void main(String[] args) throws Exception {
PaymentEngineClient client = new PaymentEngineClient("pk_xxx", "sk_xxx");

Map<String, Object> transfer = client.createPayment(Map.of(
"type", "transfer",
"fiatAmount", 10000,
"fiatCurrency", "NGN",
"crypto", "USDT",
"network", "trc20",
"chargeFrom", "fiat",
"payer", Map.of("chatId", "7389201648"),
"receiver", Map.of(
"bankCode", "090405",
"accountNumber", "8012345678"
)
));

Map<String, Object> payment = (Map<String, Object>) transfer.get("payment");

System.out.println("Deposit " + payment.get("cryptoAmount") + " USDT to:");
System.out.println(payment.get("depositAddress"));
}
}