update code

This commit is contained in:
Mohd-Arham
2025-12-03 11:48:50 +05:30
13 changed files with 409 additions and 71 deletions
@@ -59,22 +59,7 @@ public class PaymentController {
}
@PostMapping(value="/callback/paymentIntiate", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseModel> handleBillValidateCallback(@RequestBody TransactionStatusResponse transactionStatusResponse) {
ResponseModel genralResp=paymentService.handlePaymentIntiateCallback(transactionStatusResponse);
// Return a response indicating successful receipt
return ResponseEntity.ok(genralResp);
}
@PostMapping(value = "/startPayment", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseModel> startPayment(@Validated @RequestBody PaymentStartUserRequest paymentStartUserRequest) {
if (this.paymentStartService == null) {
// Defensive: if bean not injected, return failure
return ResponseEntity.badRequest().body(new ResponseModel("PaymentStartService not available", "FAILED", 400, null));
}
ResponseModel response = paymentStartService.startPayment(paymentStartUserRequest);
return ResponseEntity.ok(response);
}
}
@@ -1,17 +1,23 @@
package com.billpaymentservice.bbps.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.billpaymentservice.bbps.dto.ResponseModel;
import com.billpaymentservice.bbps.dto.request.PaymentStartUserRequest;
import com.billpaymentservice.bbps.dto.request.CallbackRequest;
import com.billpaymentservice.bbps.service.PaymentStartService;
@RestController
@RequestMapping("/payment")
public class PaymentStartController {
private final PaymentStartService paymentStartService;
@@ -20,12 +26,28 @@ public class PaymentStartController {
}
@PostMapping(value = "/startWebPayment", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseModel> startPayment(@Validated @RequestBody PaymentStartUserRequest paymentStartUserRequest) {
public ResponseEntity<ResponseModel> startWebPayment(@Validated @RequestBody PaymentStartUserRequest paymentStartUserRequest) {
ResponseModel response = paymentStartService.startWebPayment(paymentStartUserRequest);
return ResponseEntity.ok(response);
}
@PostMapping(value = "/callback/startPayment", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String, String>> handleCallback(@RequestBody CallbackRequest callbackRequest) {
ResponseModel resp = paymentStartService.handleStartCallback(callbackRequest);
Map<String, String> result = new HashMap<>();
// Use the status field from ResponseModel as merchant status code string
result.put("status", resp.getStatus());
return ResponseEntity.ok(result);
}
@PostMapping(value = "/startIntentPayment", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseModel> startIntentPayment(@Validated @RequestBody PaymentStartUserRequest paymentStartUserRequest) {
if (this.paymentStartService == null) {
// Defensive: if bean not injected, return failure
return ResponseEntity.badRequest().body(new ResponseModel("PaymentStartService not available", "FAILED", 400, null));
}
ResponseModel response = paymentStartService.startPayment(paymentStartUserRequest);
ResponseModel response = paymentStartService.startIntentPayment(paymentStartUserRequest);
return ResponseEntity.ok(response);
}
}
}
@@ -0,0 +1,31 @@
package com.billpaymentservice.bbps.dto.request;
public class CallbackRequest {
private String mid;
private String data;
private String signature;
public String getMid() {
return mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
}
@@ -52,4 +52,30 @@ public class PaymentStartRecord {
@Column(name = "created_on", nullable = false)
private String createdOn;
}
// New callback-related fields
@Column(name = "callback_status")
private String callbackStatus;
@Column(name = "bank_response", columnDefinition = "TEXT")
private String bankResponse;
@Column(name = "signature")
private String signature;
// Store original request body and full response body
@Column(name = "request_body", columnDefinition = "TEXT")
private String requestBody;
@Column(name = "response_body", columnDefinition = "TEXT")
private String responseBody;
@Column(name = "response_type")
private String responseType; // e.g., "QR", "HTML", "JSON"
@Column(name = "txn_status")
private String txnStatus;
@Column(name = "callback_received_on")
private String callbackReceivedOn;
}
@@ -1,5 +1,7 @@
package com.billpaymentservice.bbps.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@@ -7,4 +9,7 @@ import com.billpaymentservice.bbps.entites.PaymentStartRecord;
@Repository
public interface PaymentStartRecordRepository extends JpaRepository<PaymentStartRecord, Long> {
}
Optional<PaymentStartRecord> findByOrderNo(String orderNo);
Optional<PaymentStartRecord> findByTxnId(String txnId);
Optional<PaymentStartRecord> findByRequestId(String requestId);
}
@@ -14,7 +14,6 @@ public interface PaymentService {
ResponseModel checkTrasactionStatusByClientReqId(TrasactionStatusByClientReqIdRequest transactionStatusRequest);
ResponseModel handlePaymentIntiateCallback(TransactionStatusResponse transactionStatusResponse);
}
@@ -2,7 +2,12 @@ package com.billpaymentservice.bbps.service;
import com.billpaymentservice.bbps.dto.ResponseModel;
import com.billpaymentservice.bbps.dto.request.PaymentStartUserRequest;
import com.billpaymentservice.bbps.dto.request.CallbackRequest;
public interface PaymentStartService {
ResponseModel startPayment(PaymentStartUserRequest request);
}
ResponseModel startWebPayment(PaymentStartUserRequest request);
ResponseModel handleStartCallback(CallbackRequest callbackRequest);
ResponseModel startIntentPayment(PaymentStartUserRequest paymentStartUserRequest);
}
@@ -141,6 +141,46 @@ public class HttpService {
return response;
}
public HashMap<String, String> postFormRequest(String url, String formBody) {
HashMap<String, String> response = new HashMap<>();
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
log.info("🌐 Sending FORM POST to: {}", url);
log.info("📦 Payload: {}", formBody);
ResponseEntity<String> restResponse = restClient.post()
.uri(url)
.headers(h -> h.addAll(headers))
.body(formBody)
.retrieve()
.toEntity(String.class);
response.put("respCode", String.valueOf(restResponse.getStatusCode().value()));
// HTML RESPONSE directly stored
response.put("data", restResponse.getBody());
log.info("✅ FORM POST Response Status: {}", restResponse.getStatusCode());
} catch (HttpClientErrorException e) {
log.error("❌ FORM POST Error: {} - {}", e.getStatusCode(), e.getMessage());
response.put("respCode", String.valueOf(e.getStatusCode().value()));
response.put("data", e.getResponseBodyAsString()); // still HTML or error string
} catch (Exception e) {
log.error("❌ FORM POST Exception: {}", e.getMessage(), e);
response.put("respCode", "500");
response.put("data", "HttpService FORM Error: " + e.getMessage());
}
return response;
}
@@ -393,22 +393,7 @@ public class PaymentServiceImpl implements PaymentService {
}
}
@Override
public ResponseModel handlePaymentIntiateCallback(TransactionStatusResponse transactionStatusResponse) {
String apiName = "HANDLE_PAYMENT_INITIATE_CALLBACK";
LOGGER.info("[{}] START | payload={} ", apiName, transactionStatusResponse);
LOGGER.info("Received Call Back: {}", transactionStatusResponse);
if (transactionStatusResponse.getGeneralResp().getStatusCode().equals(BBPSConstant.SUCCESS_CODE_STR)) {
LOGGER.info("Callback indicates SUCCESS with status={}", transactionStatusResponse.getGeneralResp().getStatus());
} else {
LOGGER.info("Callback indicates FAILURE with status={}", transactionStatusResponse.getGeneralResp().getStatus());
}
LOGGER.info("[{}] END | callback processed", apiName);
return new ResponseModel(BBPSConstant.CALLBACK_RECEIVED_SUCCESS,
BBPSConstant.SUCCESS_CODE_STR,
BBPSConstant.HTTP_OK_INT,
"");
}
}
@@ -6,6 +6,7 @@ import java.util.Map;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,6 +18,7 @@ import org.springframework.stereotype.Service;
import com.billpaymentservice.bbps.dto.PaymentStartReturnDto;
import com.billpaymentservice.bbps.dto.ResponseModel;
import com.billpaymentservice.bbps.dto.request.PaymentStartUserRequest;
import com.billpaymentservice.bbps.dto.request.CallbackRequest;
import com.billpaymentservice.bbps.dto.response.PaymentStartApiResponse;
import com.billpaymentservice.bbps.dto.response.PaymentStatusResponse;
import com.billpaymentservice.bbps.dto.sentRequest.PaymentDetailSentRequest;
@@ -36,13 +38,15 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.billpaymentservice.bbps.entites.OutboundTraceLog;
import com.billpaymentservice.bbps.entites.BharatConnectMaster;
import com.billpaymentservice.bbps.entites.PaymentStartRecord;
@Service
public class PaymentStartServiceImpl implements PaymentStartService {
private static final Logger LOGGER = LoggerFactory.getLogger(PaymentStartServiceImpl.class);
private String uatPaymentUrl="https://uat.godemo.in/api/UATIntegration/paymentrequest/seamless";
private String uatPaymentUrlweb="https://uat.godemo.in/api/UATIntegration/uat/payin/paymentrequest";
private String uatPaymentUrlintent="https://uat.godemo.in/api/UATIntegration/paymentrequest/seamless";
private final PaymentStartRecordRepository paymentStartRecordRepository;
private final HttpService httpService;
@@ -69,7 +73,7 @@ public class PaymentStartServiceImpl implements PaymentStartService {
this.bbpsMapperHelper = bbpsMapperHelper;
}
@Override
public ResponseModel startPayment(PaymentStartUserRequest request) {
public ResponseModel startIntentPayment(PaymentStartUserRequest request) {
String requestId = request.getReqId();
String apiName = "StartPayment";
@@ -97,15 +101,17 @@ public class PaymentStartServiceImpl implements PaymentStartService {
PaymentRequestPayload finalPayload = new PaymentRequestPayload();
finalPayload.setMid(BBPSConstant.mid);
finalPayload.setPayload(encrypted);
String forwardJson = helper.convertObjectToJson(finalPayload);
LOGGER.info("Payment Start Request Payload: " + forwardJson);
OutboundTraceLog outboundLog =
helper.createOutboundLog(txnId, requestId, apiName, uatPaymentUrl,
helper.createOutboundLog(txnId, requestId, apiName, uatPaymentUrlintent,
BBPSConstant.HTTP_POST, forwardJson);
// --- CALL EXTERNAL API ---
Map<String, String> responseMap =
httpService.postRequest(uatPaymentUrl, forwardJson, null);
httpService.postRequest(uatPaymentUrlintent, forwardJson, null);
LOGGER.info("Payment Start Response: " + responseMap);
@@ -166,19 +172,7 @@ public class PaymentStartServiceImpl implements PaymentStartService {
String message = String.valueOf(payload.getOrDefault("message", top.getOrDefault("message", "")));
// Map outcome codes according to provided table:
// Success: 200
// Success without warnings: 205
// Warning -> success (fraud accepted): 206 (treat as success)
// Warning -> failed (fraud rejected): 207 (treat as failure)
// Transaction processing: 198 (treat as pending/processing)
// Fail/Exception: 417 -> failure
// Failed: 99 -> failure
// Rejected by acquirer: 197 -> failure
// Declined: 194 -> failure
// Auth success but recurring error: 193 -> failure
// Warning: 1003 -> warning (non-fatal)
// Handle special cases
if (outcomeCode == 200 || outcomeCode == 205 || outcomeCode == 206) {
// success - build apiResponse from wrapper or direct payload
@@ -238,7 +232,15 @@ public class PaymentStartServiceImpl implements PaymentStartService {
}
// Save record
bbpsMapperHelper.savePaymentStartRecord(request, apiResponse, txnId, orderNo);
// Determine response type: QR if qrString present, else JSON
String responseType = "JSON";
String rawResponse = respBody == null ? "" : respBody;
if (apiResponse != null && apiResponse.getResponseData() != null
&& apiResponse.getResponseData().getQrString() != null
&& !apiResponse.getResponseData().getQrString().isEmpty()) {
responseType = "QR";
}
bbpsMapperHelper.savePaymentStartRecord(request, apiResponse, txnId, orderNo, requestJson, rawResponse, responseType);
// Prepare DTO
PaymentStartReturnDto responseData = new PaymentStartReturnDto();
@@ -289,5 +291,183 @@ public class PaymentStartServiceImpl implements PaymentStartService {
sent.setUdf14(request.getUdf14());
return sent;
}
@Override
public ResponseModel startWebPayment(PaymentStartUserRequest request) {
}
String requestId = request.getReqId();
String apiName = "StartPayment";
String txnId = helper.generateTxnId(15);
helper.validateMerchant(request.getMid());
// inbound log
String requestJson = helper.convertObjectToJson(request);
InboundTraceLog inboundLog =
helper.createInboundLog(requestId, txnId, apiName, request.getMid(),
BBPSConstant.HTTP_POST, requestJson);
// Prepare request payload
PaymentDetailSentRequest sent = createPaymentSentRequest(request);
String orderNo = "ORD" + helper.generateTxnId(12);
sent.setOrderNo(orderNo);
String plaintext = helper.convertObjectToJson(sent);
String encKey = BBPSConstant.enckey;
sent.setEnckey(encKey);
String encrypted = encryptionUtil.encryptMData(plaintext, encKey);
// ----------- BUILD x-www-form-urlencoded PAYLOAD -----------
String formPayload =
"mid=" + URLEncoder.encode(BBPSConstant.mid, StandardCharsets.UTF_8) +
"&payload=" + URLEncoder.encode(encrypted, StandardCharsets.UTF_8);
LOGGER.info("Form Payload: {}", formPayload);
OutboundTraceLog outboundLog =
helper.createOutboundLog(txnId, requestId, apiName, uatPaymentUrlweb,
BBPSConstant.HTTP_POST, formPayload);
// ----------- CALL API (FORM URL-ENCODED) -----------
Map<String, String> responseMap =
httpService.postFormRequest(uatPaymentUrlweb, formPayload);
LOGGER.info("Payment Start Response: {}", responseMap);
int httpCode = Integer.parseInt(responseMap.getOrDefault("respCode", "500"));
String respBody = responseMap.getOrDefault("data", "");
helper.updateOutboundLogResponse(outboundLog, respBody);
// ---- HTTP FAILURE ----
if (httpCode != 200) {
helper.updateInboundLogFailure(inboundLog, respBody, String.valueOf(httpCode));
throw new CustomException("Upstream HTTP Error", "FAILED", httpCode, respBody);
}
// ---- EMPTY RESPONSE ----
if (respBody.isEmpty()) {
helper.updateInboundLogFailure(inboundLog, "Empty response from PG", "500");
throw new CustomException("Empty response from PG", "FAILED", 500, null);
}
// ❗❗ PG RETURNS HTML → NO JSON PARSING REQUIRED
helper.updateInboundLogSuccess(inboundLog, respBody, "200");
// Save record with HTML (persist original request and HTML response)
String responseTypeWeb = "HTML";
String rawResponseWeb = respBody == null ? "" : respBody;
// bbpsMapperHelper.savePaymentStartRecord(request, null, txnId, orderNo, requestJson, rawResponseWeb, responseTypeWeb);
// Return HTML directly in API response
Map<String, String> result = new HashMap<>();
result.put("html", respBody);
return ResponseModel.builder()
.status("SUCCESS")
.statusCode(200)
.message("HTML Response Received")
.data(result)
.build();
}
@Override
public ResponseModel handleStartCallback(CallbackRequest callbackRequest) {
String apiName = "HANDLE_START_CALLBACK";
LOGGER.info("[{}] START | payload={}", apiName, callbackRequest);
if (callbackRequest == null) {
LOGGER.warn("Callback payload is null");
return new ResponseModel("Invalid callback", "205", 200, null);
}
String mid = callbackRequest.getMid();
String encryptedData = callbackRequest.getData();
String signature = callbackRequest.getSignature();
// Decrypt data
String decrypted = encryptionUtil.decryptMData(encryptedData, BBPSConstant.enckey);
if (decrypted == null) {
LOGGER.error("Failed to decrypt callback payload for mid={}", mid);
return new ResponseModel("Decryption failed", "207", 200, null);
}
LOGGER.info("Decrypted callback data: {}", decrypted);
// Parse decrypted JSON
Map<String, Object> payloadMap;
try {
payloadMap = objectMapper.readValue(decrypted, new TypeReference<Map<String, Object>>(){});
} catch (JsonProcessingException e) {
LOGGER.error("Failed to parse decrypted callback JSON: {}", e.getMessage(), e);
return new ResponseModel("Invalid decrypted JSON", "207", 200, null);
}
String txnId = String.valueOf(payloadMap.getOrDefault("txnId", payloadMap.getOrDefault("txn_id", "")));
String orderNo = String.valueOf(payloadMap.getOrDefault("orderNo", payloadMap.getOrDefault("order_no", "")));
String txnStatus = String.valueOf(payloadMap.getOrDefault("txnStatus", payloadMap.getOrDefault("txn_status", payloadMap.getOrDefault("status", ""))));
// Compute checksum: Mid + txnId + orderNo + txnStatus
String checksumStr = mid + txnId + orderNo + txnStatus;
String computedChecksum = encryptionUtil.getChecksumCRC32(checksumStr);
boolean signatureMatches = false;
if (computedChecksum != null && signature != null) {
signatureMatches = computedChecksum.equals(signature) || computedChecksum.equals(String.valueOf(Long.parseLong(signature)));
}
// Find DB record
Optional<PaymentStartRecord> recordOpt = Optional.empty();
if (orderNo != null && !orderNo.isEmpty()) {
recordOpt = paymentStartRecordRepository.findByOrderNo(orderNo);
}
if (recordOpt.isEmpty() && txnId != null && !txnId.isEmpty()) {
recordOpt = paymentStartRecordRepository.findByTxnId(txnId);
}
PaymentStartRecord record = recordOpt.orElse(null);
if (record == null) {
LOGGER.warn("No PaymentStartRecord found for orderNo={} txnId={}", orderNo, txnId);
// still return 205 to acknowledge receipt
return new ResponseModel("No matching record", "205", 200, null);
}
// Update record with bank response and signature
record.setBankResponse(decrypted);
record.setSignature(signature);
// update txn status and callback timestamp
record.setTxnStatus(txnStatus);
record.setCallbackReceivedOn(java.time.LocalDateTime.now().toString());
String merchantStatus;
if (!signatureMatches) {
LOGGER.error("Signature mismatch. computed={} provided={}", computedChecksum, signature);
record.setCallbackStatus("SIGNATURE_MISMATCH");
paymentStartRecordRepository.save(record);
merchantStatus = "207"; // treat as rejected/failure
LOGGER.info("[{}] END | returning status={}", apiName, merchantStatus);
return new ResponseModel("Signature mismatch", merchantStatus, 200, null);
}
// signature ok - decide response based on txnStatus
if (txnStatus.equalsIgnoreCase("SUCCESS") || txnStatus.equalsIgnoreCase("SUCCESSFUL") || txnStatus.equalsIgnoreCase("SUCCESSFULL")) {
record.setCallbackStatus("SUCCESS");
paymentStartRecordRepository.save(record);
merchantStatus = "206"; // accepted by merchant
} else if (txnStatus.equalsIgnoreCase("FAILED") || txnStatus.equalsIgnoreCase("FAIL")) {
record.setCallbackStatus("FAILED");
paymentStartRecordRepository.save(record);
merchantStatus = "207"; // rejected
} else {
record.setCallbackStatus("RECEIVED");
paymentStartRecordRepository.save(record);
merchantStatus = "205"; // generic ack
}
LOGGER.info("Callback processed for orderNo={} txnId={} status={} returning merchantStatus={}", orderNo, txnId, txnStatus, merchantStatus);
LOGGER.info("[{}] END", apiName);
return new ResponseModel("Callback processed", merchantStatus, 200, null);
}
}
@@ -1081,18 +1081,25 @@ public class BillerMapperHelper {
}
public void savePaymentStartRecord(PaymentStartUserRequest request, PaymentStartApiResponse apiResponse,
String txnId, String orderNo) {
String txnId, String orderNo, String requestJson, String rawResponse, String responseType) {
PaymentStartRecord record = new PaymentStartRecord();
record.setOrderNo(orderNo);
record.setRequestId(request.getReqId());
record.setClientMid(request.getMid());
record.setClientUserId(request.getClientUserId());
record.setInternalTxnId(txnId);
record.setAmount(apiResponse.getResponseData().getAmount());
record.setMid(apiResponse.getResponseData().getMid());
record.setTxnId(apiResponse.getResponseData().getTxnId());
record.setQrString(apiResponse.getResponseData().getQrString());
record.setCreatedOn(apiResponse.getResponseData().getCreatedOn());
if (apiResponse != null && apiResponse.getResponseData() != null) {
record.setAmount(apiResponse.getResponseData().getAmount());
record.setMid(apiResponse.getResponseData().getMid());
record.setTxnId(apiResponse.getResponseData().getTxnId());
record.setQrString(apiResponse.getResponseData().getQrString());
record.setCreatedOn(apiResponse.getResponseData().getCreatedOn());
}
// store the original request body and raw response
record.setRequestBody(requestJson);
record.setResponseBody(rawResponse);
record.setResponseType(responseType);
paymentStartRecordRepository.save(record);
}
@@ -1,7 +1,11 @@
package com.billpaymentservice.bbps.util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.zip.CRC32;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
@@ -18,12 +22,9 @@ public class EncryptionUtil {
/**
* Encrypts plaintext using AES/CBC/PKCS5Padding.
* If the provided key length is not 16/24/32 bytes it will be adjusted to 16 bytes (padded/truncated).
* NOTE: This follows the algorithm snippet provided by the user but pads/truncates the key to avoid
* common runtime errors when key lengths are incorrect.
*/
public String encryptMData(String plaintext, String encryptKey) {
try {
// Ensure key length is 16 bytes (AES-128). If callers provide a longer key this will truncate.
byte[] keyBytes = normalizeKey(encryptKey);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
@@ -61,4 +62,56 @@ public class EncryptionUtil {
}
return normalized;
}
}
/**
* Decrypts data encrypted by encryptMData: Base64(iv + ciphertext) with AES/CBC/PKCS5Padding
*/
public String decryptMData(String base64Payload, String encryptKey) {
if (base64Payload == null) return null;
try {
byte[] combined = Base64.getDecoder().decode(base64Payload);
// IV is first 16 bytes for AES
if (combined.length < 16) {
LOGGER.warn("Encrypted payload too short to contain IV");
return null;
}
byte[] iv = new byte[16];
System.arraycopy(combined, 0, iv, 0, 16);
byte[] cipherText = new byte[combined.length - 16];
System.arraycopy(combined, 16, cipherText, 0, cipherText.length);
byte[] keyBytes = normalizeKey(encryptKey);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
byte[] plain = cipher.doFinal(cipherText);
return new String(plain, StandardCharsets.UTF_8);
} catch (Exception ex) {
LOGGER.error("Error decrypting payload: {}", ex.getMessage());
return null;
}
}
/**
* Compute CRC32 checksum value for the provided input string and return the numeric value as String
*/
public String getChecksumCRC32(String input) {
if (input == null) input = "";
try (InputStream is = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8))) {
CRC32 crc = new CRC32();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
crc.update(buffer, 0, len);
}
long value = crc.getValue();
LOGGER.debug("Computed CRC32: {} for input: {}", value, input);
return String.valueOf(value);
} catch (IOException e) {
LOGGER.error("Error computing CRC32: {}", e.getMessage());
return null;
}
}
}