정산 계좌 변경에 예금주 조회 API 붙이기: 검수부터 반영까지

판매자가 정산 계좌를 바꾸는 기능은 새 계좌번호를 저장하는 폼만으로 완성되지 않습니다. 입력한 은행과 계좌가 맞는지, 조회를 정상적으로 마쳤는지, 변경을 승인할 담당자가 무엇을 확인해야 하는지를 함께 설계해야 합니다. 조회 중 은행 점검이 발생했는데 기존 정산 계좌부터 덮어쓰면 운영팀은 무엇을 기준으로 복구해야 할지 곤란해집니다.
APICK 계좌 예금주 실명 조회 API를 계좌 변경 검수 단계에 붙이면, 신청자가 제출한 계좌의 명의 조회 결과를 검토 화면에 모을 수 있습니다. 이 글은 변경 요청을 받고, 서버에서 조회하고, 담당자 검토를 거쳐 반영하는 흐름을 다룹니다. 조회 API 자체가 송금하거나 계좌 변경을 승인하는 것은 아닙니다.
먼저 구분할 것: 명의 조회, 소유 확인, 변경 승인
계좌 예금주 조회는 은행이 반환하는 계좌 명의를 확인하는 기능입니다. 조회된 이름이 신청자의 제출 정보와 같다고 해도 그 사람이 해당 계좌에 접근할 수 있다는 사실까지 확인되는 것은 아닙니다. 신청자 인증, 판매자와 계좌의 관계 검토, 계좌 변경 권한, 최종 지급 승인은 서비스가 별도로 정해야 합니다. 이미 확보한 개인정보 처리 근거와 공급자의 허용 목적도 확인하세요.
이 구분을 화면에도 반영하면 혼선을 줄일 수 있습니다. 버튼을 눌러 API 응답이 왔다고 바로 “본인인증 완료”를 표시하는 대신 “예금주 조회 완료, 변경 검토 중”처럼 실제로 확인한 범위를 보여줍니다. 신청자에게 결과를 보여줄 때도 업무상 필요한 범위만 표시하고 계좌번호는 마스킹하는 편이 좋습니다.
1. 변경 요청을 현재 계좌와 분리해 저장하기
- 현재 사용 계좌: 기존 승인 상태와 적용 시점을 유지합니다.
- 변경 신청: 변경 요청 ID, 신청자, 대상 판매자, 은행 코드, 새 계좌를 별도 요청으로 관리합니다.
- 조회 결과: 조회 시각, 성공/실패 상태, 비용 메타데이터를 요청 ID에 연결합니다.
- 검토 결과: 담당자가 확인한 근거와 승인·반려·추가 확인 상태를 남깁니다.
예를 들어 내부 상태를 pending_lookup, ready_for_review, lookup_unavailable, approved, rejected로 구분할 수 있습니다. 이것은 애플리케이션 설계 예시이며 APICK이 반환하는 상태 목록이 아닙니다. 이전 신청의 응답이 늦게 도착해 최신 신청을 덮어쓰지 않도록, 저장 시 변경 요청 ID와 버전을 함께 확인하세요. 승인 전에는 기존 계좌를 그대로 두는 정책도 검토할 수 있습니다.
2. 요청 계약: 계좌번호와 은행 식별값
호출 경로는 POST https://apick.app/rest/account_realname입니다. account_num은 숫자만 포함한 계좌번호 문자열이며 bank_code와 bank_name 중 하나가 필요합니다. 둘 다 보내면 bank_code가 우선합니다. 은행코드 조회는 POST /rest/bank_code이며, 응답 data.result 안의 code와 content를 선택 목록에 사용할 수 있습니다. 코드의 앞자리 0이 사라지지 않도록 숫자로 변환하지 마세요.
Bearer 인증키는 서버 환경변수로 보관하고 multipart/form-data로 전송합니다. 폼의 경계값은 클라이언트가 정하므로 Node.js FormData 사용 시 Content-Type을 직접 고정하지 않습니다. 계좌번호가 숫자라는 형식 검사만으로 해당 은행의 유효한 계좌임을 판단할 수는 없습니다. 길이 규칙을 임의로 하나로 통일해 정상 계좌를 거르는 것도 피하세요.
3. cURL로 요청 구조 확인하기
환경변수에는 이용 목적과 권한이 확인된 테스트 대상만 넣습니다. 실제 계좌번호를 글이나 저장소에 적지 않습니다. 아래 예제는 응답 전체가 터미널·CI 로그에 노출되지 않도록 권한이 제한된 파일로 받습니다. 파일에는 명의 정보가 포함될 수 있으므로 접근을 제한하고 테스트 후 보관 정책에 따라 정리하세요.
umask 077
curl --fail-with-body --request POST 'https://apick.app/rest/account_realname' \
--header "Authorization: Bearer ${APICK_API_KEY:?Set a server-side key}" \
--form-string "bank_code=${APICK_TEST_BANK_CODE:?Set an approved bank code}" \
--form-string "account_num=${APICK_TEST_ACCOUNT:?Set an authorized test account}" \
--connect-timeout 10 --max-time 60 \
--output account-response.private.json4. Node.js에서는 조회 완료까지만 판단하기
다음 함수는 입력 형식과 응답의 성공 상태를 확인합니다. 호출 전에 신청자의 로그인 상태와 변경 권한을 검사하고, 요청을 적법하게 처리할 수 있는지 확인하는 코드는 각 서비스에서 구현해야 합니다. 반환되는 holderName은 서버의 보호된 검토 흐름에서만 사용하세요. 함수는 계좌를 승인하거나 결제를 실행하지 않습니다.
export async function lookupPayoutAccount({ bankCode, accountNumber }) {
const apiKey = process.env.APICK_API_KEY;
if (!apiKey) throw new Error("APICK_API_KEY is required");
if (typeof bankCode !== "string" || !/^\d+$/.test(bankCode))
throw new TypeError("Use a bank code string from the bank list");
if (typeof accountNumber !== "string" || !/^\d+$/.test(accountNumber))
throw new TypeError("Use an account number containing digits only");
const form = new FormData();
form.set("bank_code", bankCode);
form.set("account_num", accountNumber);
const response = await fetch("https://apick.app/rest/account_realname", {
method: "POST",
headers: { Authorization: `Bearer ${apiKey}` },
body: form,
signal: AbortSignal.timeout(60_000)
});
if (!response.ok) {
// Keep the raw response and submitted identifiers out of logs.
return { state: "lookup_unavailable", httpStatus: response.status };
}
const payload = await response.json();
const costPoints = typeof payload.api?.cost === "number"
&& Number.isFinite(payload.api.cost) && payload.api.cost >= 0
? payload.api.cost : null;
if (payload.api?.success !== true || payload.data?.success !== 1)
return { state: "lookup_unavailable", costPoints };
const holderName = payload.data["계좌실명"];
if (typeof holderName !== "string" || holderName.trim() === "")
return { state: "lookup_unavailable", costPoints };
return {
state: "ready_for_review",
holderName,
checkedAt: new Date().toISOString(),
costPoints,
paymentLogId: payload.api.pl_id
};
}네트워크 오류나 시간 초과, JSON 해석 오류는 함수 밖에서 잡아 lookup_unavailable로 정리하세요. 조회 결과를 얻지 못했다는 이유로 타인 명의라고 기록하지 않습니다. 또 계좌실명은 일부 은행에서 길이가 잘린 값으로 돌아올 수 있습니다. 정상 조회라는 사실과 제출 명의에 대한 비교 판정은 다른 단계입니다.
5. 실무에서 필요한 중복 방지와 검토 화면
변경 버튼을 두 번 눌렀을 때 같은 요청 ID가 여러 번 처리되지 않도록 우리 서버에서 중복 제출을 제어합니다. APICK에 이미 전달한 요청이 클라이언트 시간 초과로 보이지 않더라도 서버에서 처리됐을 수 있으므로, 재시도를 무료라고 가정하지 않습니다. 호출 기록과 api.cost·api.pl_id를 연결해 중복 조회를 추적하세요. 이 엔드포인트가 별도의 중복 과금 방지 키를 제공한다고 확인한 것은 아닙니다.
검토 화면은 신청자, 마스킹한 새 계좌, 조회한 시각, 조회 성공 여부, 명의 비교의 근거를 보여주도록 구성할 수 있습니다. 담당자에게 전체 계좌가 꼭 필요하지 않다면 마지막 일부 자리만 표시하세요. 계좌 원문은 운영 분석 로그에 남기지 않고, 검토 이력에는 요청 ID와 상태 전이 중심으로 기록합니다. 승인 정책과 보관 기간은 내부 업무 기준에 맞춰 정해야 합니다.
비용과 도입 조건
2026-10-11 공식 요금표 기준 예금주 조회는 건당 60P, 은행코드 조회는 0P입니다. 동일한 단가로 과금되는 조회 1,000건이면 60,000P입니다. 예산에는 변경 신청 건수뿐 아니라 재조회와 검토 과정에서 추가한 호출을 포함하세요. 공개 시작 가이드는 예금주 조회를 최초 1회 이상 결제가 필요한 API 목록에 포함합니다. 무료 포인트만으로 모든 연동 검증이 가능하다고 가정하지 마세요.
이 금액은 포인트 사용량 예시입니다. 원화 환산, 부가세, 개별 계정 계약이나 할인 조건은 이 글에서 확인하지 않았으므로 현재 충전·계약 조건을 확인해야 합니다. 은행 점검 시간에는 조회할 수 없다는 문서상 제한도 함께 고려해, 처리 실패 시 추가 확인이 가능한 운영 경로를 마련하세요.
자주 묻는 질문
예금주 이름이 같으면 변경을 자동 승인해도 되나요?
이름 조회와 계좌 접근·소유 확인, 변경 권한 검증은 별개입니다. 서비스가 정한 추가 확인과 승인 절차를 적용하세요.
bank_code와 bank_name을 같이 보내야 하나요?
둘 중 하나가 필요하며 함께 보내면 bank_code가 우선합니다. 이 예제는 코드 기반 선택 목록을 사용합니다.
은행 점검으로 조회에 실패하면 새 계좌를 삭제하나요?
조회 실패를 명의 불일치로 해석하지 말고, 변경 신청을 보류한 채 다시 확인할 수 있는 상태로 관리하는 설계를 검토하세요.
APICK으로 연동 범위와 운영 조건 확인하기
계좌 예금주 실명 조회 개발가이드에서 입력과 응답을 확인한 뒤, 실제로 허용된 테스트 대상과 기준 명의로 연동을 검토해 보세요. 은행코드 조회와 함께 구성하면 은행 선택값을 문자열 코드로 관리할 수 있습니다. 구체적인 조회 목적과 개인정보 처리 조건은 공급자 안내 및 서비스의 처리 근거와 맞춰야 합니다.
문서·가격 확인: 2026-10-11 UTC. 공식 요금표 · 인증·이용 시작 안내. 공개 문서를 기준으로 작성했으며 실제 API 호출이나 금융 거래는 실행하지 않았습니다. 코드는 설명용 서버 예제입니다. 인증키와 계좌·명의 정보는 자리표시자로만 다룹니다.
댓글
댓글 쓰기