working web based and intent
This commit is contained in:
+136
-33
@@ -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/uat/payin/paymentrequest";
|
||||
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();
|
||||
@@ -322,12 +324,12 @@ public class PaymentStartServiceImpl implements PaymentStartService {
|
||||
"&payload=" + URLEncoder.encode(encrypted, StandardCharsets.UTF_8);
|
||||
LOGGER.info("Form Payload: {}", formPayload);
|
||||
OutboundTraceLog outboundLog =
|
||||
helper.createOutboundLog(txnId, requestId, apiName, uatPaymentUrl,
|
||||
helper.createOutboundLog(txnId, requestId, apiName, uatPaymentUrlweb,
|
||||
BBPSConstant.HTTP_POST, formPayload);
|
||||
|
||||
// ----------- CALL API (FORM URL-ENCODED) -----------
|
||||
Map<String, String> responseMap =
|
||||
httpService.postFormRequest(uatPaymentUrl, formPayload);
|
||||
httpService.postFormRequest(uatPaymentUrlweb, formPayload);
|
||||
|
||||
LOGGER.info("Payment Start Response: {}", responseMap);
|
||||
|
||||
@@ -350,21 +352,122 @@ public class PaymentStartServiceImpl implements PaymentStartService {
|
||||
|
||||
// ❗❗ 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);
|
||||
|
||||
// Save record with HTML (optional)
|
||||
// bbpsMapperHelper.savePaymentStartHtmlRecord(request, respBody, txnId, orderNo);
|
||||
// Return HTML directly in API response
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("html", respBody);
|
||||
|
||||
// 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();
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user