[매입] mg_recv_svc → 전문수신 @Service #3
1 changed files with 105 additions and 0 deletions
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
Reference in a new issue