eformsign API Service

Create a Service Class

EformSignService.java
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import reactor.core.publisher.Mono;
@Service
public class EformSignService {
	
    private static String apiKey = "your api key";
    private static String privateKeyHex = "your private key";
    private static String publickKeyHex = "your public key";
    private WebClient webClient = WebClient.create();

Provide your API key, private key, and public key.

Verify eformsign Signature

/**
 * verifySignature - verify Webhook signature using data and PublicKey
 * 
 * @input	response header(signature) and body(data)
 * @input	publickKey
 * @return	true/false
 */
public static boolean verifySignature(String resSignature, String resData) {
	
    Signature signature;
    boolean valid = false;
    
    try {
    	KeyFactory publicKeyFact = KeyFactory.getInstance("EC");
    	X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(new BigInteger(publickKeyHex,16).toByteArray());
    	PublicKey publicKey = publicKeyFact.generatePublic(x509KeySpec);
    	
    	signature = Signature.getInstance("SHA256withECDSA");
    	signature.initVerify(publicKey);
    	signature.update(resData.getBytes("UTF-8"));
    	
    	if(signature.verify(new BigInteger(resSignature,16).toByteArray())) {valid = true;}
    	else {valid = false;}
        	
    } catch (Exception e) {
    	e.printStackTrace(); 
    }

return valid;
}

Get Access Token

// Access Token Structure for your understanding. Do not add to the project.
{
  "api_key": {
    "name": "Tutorial",
    "alias": "Tutorial",
    "company": {
      "company_id": "2b99ef0cac464344b1983d44ec4af427",
      "name": "eformsign Bootcamp",
      "api_url": "https://sg-api.eformsign.com"
    }
  },
  "oauth_token": {
    "expires_in": 3600,
    "token_type": "JWT",
    "refresh_token": "8a43b797-xxxx-xxxx-xxxx-3ea8f4b872e0",
    "access_token": "eyJh...WijgnU" // 4Kbytes
  }
}
/**
 * getEformsignSignature - generate eformsign signature using privateKey
 * 
 * @input	privateKey
 * @return	execution_time, eformsign_signature
 */
private static String[] getEformsignSignature() throws Exception {

    KeyFactory keyFact = KeyFactory.getInstance("EC");
    PKCS8EncodedKeySpec psks8KeySpec = new PKCS8EncodedKeySpec(new BigInteger(privateKeyHex,16).toByteArray());
    PrivateKey privateKey = keyFact.generatePrivate(psks8KeySpec);

    String execution_time = String.valueOf(new Date().getTime());
    Signature ecdsa = Signature.getInstance("SHA256withECDSA");
    ecdsa.initSign(privateKey);
    ecdsa.update(execution_time.getBytes("UTF-8"));			
    String eformsign_signature = new BigInteger(ecdsa.sign()).toString(16);

    String[] res = new String[2];
    res[0]= execution_time;
    res[1]= eformsign_signature;
    return res;
}  
/**
 * getAccessToken
 * 
 * @method	POST
 * @path	/api_auth/refresh_token
 * @header	Bearer API Key    
 * @header	eformsign_signature    
 * @body	memberId "[email protected]"
 * @body	execution_time
 * @return	access token in JSON
 * accessToken expires in 3600 seconds
 */
public Mono<JsonNode> getAccessToken(String memberId) throws Exception {
	
    String base64ApiKey = Base64.getEncoder().encodeToString(apiKey.getBytes("UTF-8"));
    String[] signature = getEformsignSignature();
    String execution_time = signature[0];
    String eformsign_signature = signature[1];

    Map<String, Object> reqBody = new HashMap<>();
    reqBody.put("execution_time", execution_time);
    reqBody.put("member_id", memberId);
    
    return webClient.post()
            .uri("https://api.eformsign.com", uriBuilder -> uriBuilder
                .path("/v2.0/api_auth/access_token")
                .build())
            .header("Authorization", "Bearer " + base64ApiKey)
            .header("eformsign_signature", eformsign_signature)
            .bodyValue(reqBody)
            .retrieve()
            .onStatus(HttpStatus::isError, res -> res.bodyToMono(String.class)
                .flatMap(error -> Mono.error(new RuntimeException(error))))
            .bodyToMono(JsonNode.class);
}

Get Refresh Token

/**
 * getRefreshToken - call when the token expired (3600 seconds have passed)
 * 
 * @method	POST
 * @path	/v2.0/api_auth/refresh_token
 * @header	access_token
 * @param	refresh_token
 * @return	new access_token
 */
public Mono<JsonNode> getRefreshToken(JsonNode token) {

    return webClient.post()
	.uri(token.get("apiUrl").asText(), uriBuilder -> uriBuilder
            .path("/v2.0/api_auth/refresh_token")
            .queryParam("refresh_token", token.get("refreshToken").asText())
            .build())
        .header("Authorization", "Bearer " + token.get("accessToken").asText())
        .retrieve()
        .onStatus(HttpStatus::isError, res -> res.bodyToMono(String.class)
            .flatMap(error -> Mono.error(new RuntimeException(error))))
        .bodyToMono(JsonNode.class);
}

Download Documents

/**
 * Download Document File
 * 
 * @method	GET
 * @path	/v2.0/api/documents/{document_id}/download_files
 * @header	access_token
 * @param	fileType   file type : "document" | "audit_trail" | "document,audit_trail"
 * @return	files in byte stream
 */
public  Mono<byte[]> downloadDocument(JsonNode token,  String documentId, String fileType) {
	
    return webClient.get()
        .uri(token.get("apiUrl").asText(), uriBuilder -> uriBuilder
            .path("/v2.0/api/documents/" + documentId + "/download_files")
            .queryParam("file_type", fileType)
            .build(documentId))
        .header("Authorization", "Bearer " + token.get("accessToken").asText())
        .retrieve()
	.onStatus(HttpStatus::isError, res -> res.bodyToMono(String.class)
	    .flatMap(error -> Mono.error(new RuntimeException(error))))
	.bodyToMono(byte[].class);
}

Delete Document

/**
 * Delete Document
 * 
 * @method		DELETE
 * @path		/v2.0/api/documents/
 * @header		access_token
 * @body		document id array
 * @return		{"code": "-1", "message": "Completed.", "status": "200"}
 */
public  Mono<JsonNode> deleteDocument(JsonNode token, String documentId) {
		
    ObjectMapper objectMapper = new ObjectMapper();
    ObjectNode objectNode = objectMapper.createObjectNode();
    ArrayNode arrayNode = objectNode.withArray("document_ids");
    arrayNode.add(documentId);

    return webClient.method(HttpMethod.DELETE)
        .uri(token.get("apiUrl").asText(), uriBuilder -> uriBuilder
            .path("/v2.0/api/documents/")
            .build())
        .header("Authorization", "Bearer " + token.get("accessToken").asText())
        .bodyValue(objectNode)
        .retrieve()
        .onStatus(HttpStatus::isError, res -> res.bodyToMono(String.class)
            .flatMap(error -> Mono.error(new RuntimeException(error))))
        .bodyToMono(JsonNode.class);
} 

Last updated