[매입] mg_recv_svc → 전문수신 @Service (ACM-MG-004)

This commit is contained in:
forge-bot 2026-07-18 11:05:31 +00:00
parent 8bc30e2917
commit 867a51a1cd

View file

@ -0,0 +1,105 @@
package com.klaro.acquirecore.acquiring.codec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 전문 언팩/ 커덱 (codec)
* 바이너리 전문 파싱 조립 담당
*/
@Component
public class MessageCodec {
private static final Logger log = LoggerFactory.getLogger(MessageCodec.class);
// 전문 헤더 길이
private static final int HEADER_LENGTH = 20;
// 전문 트레일러 길이
private static final int TRAILER_LENGTH = 4;
/**
* 원시 전문 언팩
* @param rawMessage 원시 바이트 배열
* @return 파싱된 전문 객체
*/
public ParsedMessage unpack(byte[] rawMessage) {
log.debug("전문 언팩 시작 - 길이: {}", rawMessage.length);
if (rawMessage == null || rawMessage.length < HEADER_LENGTH + TRAILER_LENGTH) {
throw new IllegalArgumentException("전문 길이 오류");
}
ParsedMessage parsed = new ParsedMessage();
// 헤더 파싱
parsed.setMessageType(decodeString(rawMessage, 0, 4));
parsed.setTxId(decodeString(rawMessage, 4, 12));
parsed.setTxCode(decodeString(rawMessage, 16, 4));
// 바디 파싱 (가변 길이)
int bodyLength = rawMessage.length - HEADER_LENGTH - TRAILER_LENGTH;
if (bodyLength > 0) {
parsed.setMerchantId(decodeString(rawMessage, HEADER_LENGTH, 15));
parsed.setCardNumber(decodeString(rawMessage, HEADER_LENGTH + 15, 20));
parsed.setAmount(decodeString(rawMessage, HEADER_LENGTH + 35, 12));
parsed.setApprovalCode(decodeString(rawMessage, HEADER_LENGTH + 47, 10));
}
// 트레일러 검증
byte[] trailer = new byte[TRAILER_LENGTH];
System.arraycopy(rawMessage, rawMessage.length - TRAILER_LENGTH, trailer, 0, TRAILER_LENGTH);
parsed.setTrailer(new String(trailer));
log.debug("전문 언팩 완료 - TX_ID: {}, TX_CODE: {}", parsed.getTxId(), parsed.getTxCode());
return parsed;
}
/**
* 전문 (응답 전문 생성)
* @param parsed 파싱된 전문
* @return 원시 바이트 배열
*/
public byte[] pack(ParsedMessage parsed) {
log.debug("전문 팩 시작 - TX_ID: {}", parsed.getTxId());
StringBuilder sb = new StringBuilder();
sb.append(padRight(parsed.getMessageType(), 4));
sb.append(padRight(parsed.getTxId(), 12));
sb.append(padRight(parsed.getTxCode(), 4));
sb.append(padRight(parsed.getMerchantId(), 15));
sb.append(padRight(parsed.getCardNumber(), 20));
sb.append(padRight(parsed.getAmount(), 12));
sb.append(padRight(parsed.getApprovalCode(), 10));
sb.append("ETX");
return sb.toString().getBytes();
}
/**
* 바이트 배열에서 문자열 추출
*/
private String decodeString(byte[] data, int offset, int length) {
if (offset + length > data.length) {
return "";
}
byte[] sub = new byte[length];
System.arraycopy(data, offset, sub, 0, length);
return new String(sub).trim();
}
/**
* 문자열을 지정 길이만큼 패딩
*/
private String padRight(String value, int length) {
if (value == null) value = "";
if (value.length() >= length) {
return value.substring(0, length);
}
StringBuilder sb = new StringBuilder(value);
while (sb.length() < length) {
sb.append(' ');
}
return sb.toString();
}
}