diff --git a/pom.xml b/pom.xml
index 7c233abaa..4b12e3dcb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -508,6 +508,25 @@
sd-jwt
1.5
+
+
+
+ io.mosip.injivcrenderer
+ injivcrenderer-jvm
+ 0.1.0-SNAPSHOT
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ 2.0.0
+
+
+
+ com.github.jknack
+ handlebars
+ 4.3.1
+
diff --git a/src/main/java/io/mosip/mimoto/config/InjiVcRendererConfig.java b/src/main/java/io/mosip/mimoto/config/InjiVcRendererConfig.java
new file mode 100644
index 000000000..dd55cb3b2
--- /dev/null
+++ b/src/main/java/io/mosip/mimoto/config/InjiVcRendererConfig.java
@@ -0,0 +1,13 @@
+package io.mosip.mimoto.config;
+
+import io.mosip.injivcrenderer.InjiVcRenderer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class InjiVcRendererConfig {
+ @Bean
+ public InjiVcRenderer injiVcRenderer() {
+ return new InjiVcRenderer();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/mosip/mimoto/controller/CredentialsController.java b/src/main/java/io/mosip/mimoto/controller/CredentialsController.java
index cd1e62ae2..95a6ddb10 100644
--- a/src/main/java/io/mosip/mimoto/controller/CredentialsController.java
+++ b/src/main/java/io/mosip/mimoto/controller/CredentialsController.java
@@ -2,6 +2,7 @@
import io.mosip.mimoto.constant.SwaggerLiteralConstants;
import io.mosip.mimoto.core.http.ResponseWrapper;
+import io.mosip.mimoto.dto.CredentialResponse;
import io.mosip.mimoto.dto.idp.TokenResponseDTO;
import io.mosip.mimoto.exception.ApiNotAccessibleException;
import io.mosip.mimoto.exception.InvalidCredentialResourceException;
@@ -63,12 +64,12 @@ public ResponseEntity> downloadCredentialAsPDF(@RequestParam Map getVerifiableCredential(
String dispositionType = "download".equalsIgnoreCase(action) ? "attachment" : "inline";
String contentDisposition = String.format("%s; filename=\"%s\"", dispositionType, walletCredentialResponseDTO.getFileName());
+ MediaType contentType = walletCredentialResponseDTO.getFileName().endsWith(".svg") ?
+ MediaType.valueOf("image/svg+xml") : MediaType.APPLICATION_PDF;
+
return ResponseEntity.ok()
.header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION)
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
- .contentType(MediaType.APPLICATION_PDF)
+ .contentType(contentType)
.body(walletCredentialResponseDTO.getFileContentStream());
} catch (CredentialNotFoundException e) {
log.error("Credential not found for walletId: {} and credentialId: {}", walletId, credentialId, e);
diff --git a/src/main/java/io/mosip/mimoto/dto/CredentialResponse.java b/src/main/java/io/mosip/mimoto/dto/CredentialResponse.java
new file mode 100644
index 000000000..974350be9
--- /dev/null
+++ b/src/main/java/io/mosip/mimoto/dto/CredentialResponse.java
@@ -0,0 +1,16 @@
+package io.mosip.mimoto.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.http.MediaType;
+import java.io.ByteArrayInputStream;
+
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CredentialResponse {
+ private ByteArrayInputStream content;
+ private MediaType mediaType;
+}
\ No newline at end of file
diff --git a/src/main/java/io/mosip/mimoto/service/CredentialPDFGeneratorService.java b/src/main/java/io/mosip/mimoto/service/CredentialPDFGeneratorService.java
index ae3b4112e..a30303b03 100644
--- a/src/main/java/io/mosip/mimoto/service/CredentialPDFGeneratorService.java
+++ b/src/main/java/io/mosip/mimoto/service/CredentialPDFGeneratorService.java
@@ -4,6 +4,8 @@
import com.authlete.sd.SDJWT;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.github.jknack.handlebars.Handlebars;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
@@ -27,18 +29,20 @@
import io.mosip.pixelpass.PixelPass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
+import io.mosip.injivcrenderer.InjiVcRenderer;
+import org.springframework.web.client.RestTemplate;
+import io.mosip.mimoto.dto.CredentialResponse;
import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.StringWriter;
+import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
@@ -68,6 +72,12 @@ private record SelectedFace(String key, String face) {}
@Autowired
private CredentialFormatHandlerFactory credentialFormatHandlerFactory;
+ @Autowired
+ private InjiVcRenderer injiVcRenderer;
+
+ @Autowired
+ private RestTemplate restTemplate;
+
@Value("${mosip.inji.ovp.qrdata.pattern}")
private String ovpQRDataPattern;
@@ -86,7 +96,13 @@ private record SelectedFace(String key, String face) {}
@Value("${mosip.injiweb.mask.disclosures:true}")
private boolean maskDisclosures;
- public ByteArrayInputStream generatePdfForVerifiableCredential(String credentialConfigurationId, VCCredentialResponse vcCredentialResponse, IssuerDTO issuerDTO, CredentialsSupportedResponse credentialsSupportedResponse, String dataShareUrl, String credentialValidity, String locale) throws Exception {
+ public CredentialResponse generatePdfForVerifiableCredential(String credentialConfigurationId, VCCredentialResponse vcCredentialResponse, IssuerDTO issuerDTO, CredentialsSupportedResponse credentialsSupportedResponse, String dataShareUrl, String credentialValidity, String locale) throws Exception {
+ // ByteArrayInputStream renderedVcStream = renderVcWithHandlebars(vcCredentialResponse);
+ CredentialResponse credentialResponse = renderVcWithInjiRender(vcCredentialResponse);
+ if (credentialResponse != null) {
+ return credentialResponse;
+ }
+
// Get the appropriate processor based on format
CredentialFormatHandler processor = credentialFormatHandlerFactory.getHandler(vcCredentialResponse.getFormat());
@@ -214,17 +230,25 @@ private String formatValue(Object val, String locale) {
return String.join(", ", (List) list);
} else if (list.getFirst() instanceof Map, ?>) {
return list.stream()
+ .filter(Objects::nonNull)
.map(item -> (Map, ?>) item)
- .filter(m -> LocaleUtils.matchesLocale(m.get("language").toString(), locale))
- .map(m -> m.get("value").toString())
+ .filter(m -> {
+ Object lang = m.get("language"); // Safely get language
+ return lang != null && LocaleUtils.matchesLocale(lang.toString(), locale);
+ })
+ .map(m -> {
+ Object value = m.get("value"); // Safely get value
+ return value != null ? value.toString() : null;
+ })
+ .filter(Objects::nonNull)
.findFirst()
.orElse("");
}
}
- return val.toString();
+ return val != null ? val.toString() : "";
}
- private ByteArrayInputStream renderVCInCredentialTemplate(Map data, String issuerId, String credentialConfigurationId) {
+ private CredentialResponse renderVCInCredentialTemplate(Map data, String issuerId, String credentialConfigurationId) {
String credentialTemplate = utilities.getCredentialSupportedTemplateString(issuerId, credentialConfigurationId);
Properties props = new Properties();
props.setProperty("resource.loader", "class");
@@ -243,7 +267,7 @@ private ByteArrayInputStream renderVCInCredentialTemplate(Map da
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setFontProvider(defaultFont);
HtmlConverter.convertToPdf(mergedHtml, pdfwriter, converterProperties);
- return new ByteArrayInputStream(outputStream.toByteArray());
+ return new CredentialResponse(new ByteArrayInputStream(outputStream.toByteArray()), MediaType.APPLICATION_PDF);
}
private String constructQRCodeWithVCData(VCCredentialResponse vcCredentialResponse) throws JsonProcessingException, WriterException {
@@ -267,5 +291,219 @@ private String constructQRCode(String qrData) throws WriterException {
BufferedImage qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
return Utilities.encodeToString(qrImage, "png");
}
+
+ private CredentialResponse renderVcWithInjiRender(VCCredentialResponse vcCredentialResponse) throws JsonProcessingException {
+ // Parsing renderMethod with strict typing
+ if (vcCredentialResponse.getCredential() == null) {
+ return null;
+ }
+ // Convert VCCredentialResponse.credential to JSON string
+ String vcJson = objectMapper.writeValueAsString(vcCredentialResponse.getCredential());
+
+ @SuppressWarnings("unchecked")
+ Map credentialMap = objectMapper.convertValue(vcCredentialResponse.getCredential(),
+ new TypeReference