Embedded Integration — Java

Build your own checkout in Java — hash, direct sale, 3DS, capture, webhooks.

Embedded Integration lets you collect card data on your website and charge via DigetPay from your Java backend. You build the checkout UI — including Apple Pay if needed (separate guide).

PCI DSS: Embedded Integration requires secure handling of card data (SAQ D or equivalent). Prefer Hosted Checkout unless compliance approves embedded card collection.

Never send card data from browser JavaScript directly to DigetPay. Post card fields to your server first, then your server calls the embedded sale APIs.

Prerequisites: Embedded Integration Overview, Sandbox Setup, Java 17+ with HttpClient.


Architecture

sequenceDiagram
  participant Browser as Customer Browser
  participant Shop as Your Java Server
  participant API as DigetPay API

  Browser->>Shop: POST checkout form (card fields)
  Shop->>Shop: Compute MD5 hash
  Shop->>API: POST /payment/s2s/sale
  API-->>Shop: status + html (3DS if needed)
  Shop->>Browser: Render 3DS or success page
  API->>Shop: Webhook notification

Step 1 — Configuration

// DigetPayConfig.java
public final class DigetPayConfig {
    private static final Map<String, String> API_BASES = Map.of(
        "staging", "https://fin-api.digetpay.com/v1",
        "production", "https://api.digetpay.com/v1"
    );

    public static String environment() {
        return System.getenv().getOrDefault("DIGETPAY_ENV", "staging");
    }

    public static String apiKey() {
        String key = System.getenv("DIGETPAY_API_KEY");
        if (key == null || key.isBlank()) throw new IllegalStateException("DIGETPAY_API_KEY is not set");
        return key;
    }

    public static String apiBase() {
        return API_BASES.get(environment());
    }
}

Step 2 — Hash helper

// DigetPayHash.java
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public final class DigetPayHash {
    public static String embeddedHash(String email, String cardNumber, String apiKey) throws Exception {
        String card = cardNumber.replaceAll("\\s+", "");
        String reversedEmail = new StringBuilder(email).reverse().toString();
        String reversedCard = new StringBuilder(card.substring(0, 6) + card.substring(card.length() - 4)).reverse().toString();
        String raw = (reversedEmail + apiKey + reversedCard).toUpperCase();
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(raw.getBytes(StandardCharsets.UTF_8));
        StringBuilder hex = new StringBuilder();
        for (byte b : digest) hex.append(String.format("%02x", b));
        return hex.toString();
    }
}

Full explanation: Request Hash (MD5).


Step 3 — Embedded client

// DigetPayEmbeddedClient.java
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.*;
import java.util.*;

public class DigetPayEmbeddedClient {
    private final HttpClient http = HttpClient.newHttpClient();
    private final ObjectMapper mapper = new ObjectMapper();
    private final String apiBase = DigetPayConfig.apiBase();
    private final String apiKey = DigetPayConfig.apiKey();

    @SuppressWarnings("unchecked")
    private Map<String, Object> request(String method, String path, Map<String, Object> body) throws Exception {
        HttpRequest.Builder builder = HttpRequest.newBuilder()
            .uri(URI.create(apiBase + path))
            .header("Content-Type", "application/json")
            .header("x-api-key", apiKey);
        if (body != null) {
            builder.method(method, HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(body)));
        } else {
            builder.method(method, HttpRequest.BodyPublishers.noBody());
        }
        HttpResponse<String> resp = http.send(builder.build(), HttpResponse.BodyHandlers.ofString());
        if (resp.statusCode() >= 400) throw new RuntimeException("DigetPay HTTP " + resp.statusCode());
        return mapper.readValue(resp.body(), Map.class);
    }

    public Map<String, Object> directSale(Map<String, Object> order, Map<String, String> card,
            Map<String, String> customer, String successUrl, String failureUrl) throws Exception {
        String cardNumber = card.get("cardNumber").replaceAll("\\s+", "");
        String hash = DigetPayHash.embeddedHash(customer.get("email"), cardNumber, apiKey);
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("orderId", order.get("orderId"));
        body.put("amount", order.get("amount"));
        body.put("currency", order.getOrDefault("currency", "SAR"));
        body.put("paymentMethod", "card");
        body.put("auth", order.getOrDefault("auth", "N"));
        body.put("card", Map.of(
            "cardNumber", cardNumber,
            "cardExpiryMonth", card.get("cardExpiryMonth"),
            "cardExpiryYear", card.get("cardExpiryYear"),
            "cardCvv", card.get("cardCvv"),
            "cardHolder", card.get("cardHolder")
        ));
        body.put("customer", customer);
        body.put("successUrl", successUrl);
        body.put("failureUrl", failureUrl);
        body.put("hash", hash);
        return request("POST", "/payment/s2s/sale", body);
    }

    public Map<String, Object> capture(String transactionId, double amount) throws Exception {
        return request("POST", "/payment/s2s/capture", Map.of("transactionId", transactionId, "amount", amount));
    }

    public Map<String, Object> voidTransaction(String transactionId) throws Exception {
        return request("POST", "/payment/s2s/void", Map.of("transactionId", transactionId));
    }
}

Step 4 — Process payment controller

@PostMapping("/process-payment")
public ResponseEntity<?> processPayment(@RequestParam Map<String, String> form) throws Exception {
    DigetPayEmbeddedClient client = new DigetPayEmbeddedClient();
    Map<String, Object> result = client.directSale(
        Map.of("orderId", form.get("order_id"), "amount", Double.parseDouble(form.get("amount")), "auth", "N"),
        Map.of("cardNumber", form.get("card_number"), "cardExpiryMonth", form.get("exp_month"),
               "cardExpiryYear", form.get("exp_year"), "cardCvv", form.get("cvv"), "cardHolder", form.get("card_holder")),
        Map.of("name", form.get("card_holder"), "email", form.get("email"), "phone", form.get("phone")),
        "https://yourstore.com/payment/3ds-return",
        "https://yourstore.com/payment/failed"
    );
    // Handle 3DS html or redirect on APPROVED
    return ResponseEntity.ok(result);
}

For Apple Pay, use a separate button and server flow — Apple Pay Embedded. See Apple Pay Code (Java).


Step 5 — Capture, void, and webhooks

client.capture("2232e99b-0257-47d5-bbfd-022c8951767f", 10.0);
client.voidTransaction("2232e99b-0257-47d5-bbfd-022c8951767f");

Webhook handler — see Webhooks Code (Java).


Next steps


Did this page help you?