Glowb Dev Docs
Admin APIAdmin Finance API

POST /ai/admin/finance/card-refund/{transactionId}

캔디페이 카드 결제 취소 — 결제 전액을 카드로 돌려주고 기업 글로벌 크레딧에서 차감 (어드민)

카드 결제 취소 (전액 환불)

캔디페이로 결제한 크레딧 거래 하나를 골라 캔디페이 취소 API 를 호출하고, 기업 글로벌 크레딧(Business.remainCredit)에서 결제 금액 전액을 차감(REFUND 행)합니다. 결제 자체를 없던 일로 만드는 액션입니다. 카드·계좌이체 등 캔디페이 안의 결제 수단과 무관하게 같은 API 로 취소됩니다.

같은 행이 화면 API 마다 다른 이름으로 내려옵니다. 어느 쪽이든 취소 대상입니다.

어디서타입 필드id이미 취소됨
재무 타임라인 (GET /ai/admin/finance/business/{businessAccountId} 의 globalTimeline, GET .../collab/{collabNo} 의 timeline)type === "CARD_PAYMENT"sourceKey 가 creditTx:1234 → 1234paymentCancelled === true
원장 행 그대로 받는 곳 (CreditTransaction 원본)transactionType === "PAYMENT" 이고 candyPaymentId 있음id같은 candyPaymentId 의 REFUND 행 존재

원장 타입 PAYMENT 에 candyPaymentId 가 없으면 타임라인은 CREDIT_ADD 로 내려주며, 그 행은 취소 대상이 아닙니다(409).

기업 셀프 환불(POST /ai/payments/credit/{transactionId}/cancel)과 달리 캠페인 진행 단계를 보지 않습니다. 관리자는 언제든 취소할 수 있어야 하기 때문입니다. 대신 "돈이 지금 어디 있는지"만 봅니다.

카드 환불은 기업 글로벌 크레딧에서만 빠집니다. 크레딧이 캠페인 예산에 예치된 상태(모집 시작 이후)면 글로벌 잔액이 부족해 409 로 막힙니다. 먼저 캠페인 강제 종료(waiveForfeit=true 면 전액)로 크레딧을 글로벌로 되돌린 뒤 호출하세요.

운영 순서

상황순서
캠페인 시작 전 (크레딧이 지갑에 그대로)본 API 1회
캠페인 진행 중, 착수금은 뗄 때강제 종료 → 본 API
캠페인 진행 중, 전액 돌려줄 때강제 종료(waiveForfeit=true) → 본 API
잔액이 모자라도 무조건 돌려줘야 할 때본 API + force=true (기업 잔액 마이너스)

HTTP 요청

POST /ai/admin/finance/card-refund/{transactionId}
Authorization: Bearer {access_token}
Content-Type: application/json

Path Parameters

파라미터타입필수설명
transactionIdLong예취소할 캔디페이 결제 행의 크레딧 거래 id (TB_CREDIT_TRANSACTION.id). 타임라인 CARD_PAYMENT 행의 sourceKey 숫자 = 원장 PAYMENT 행의 id

Request Body (선택)

{
  "reason": "고객 요청 — 캠페인 진행 불가",
  "force": false
}
필드타입필수설명
reasonString아니오취소 사유. 캔디페이 취소 요청과 원장 memo 에 남습니다. 생략 시 관리자 결제 취소
forceboolean아니오기업 글로벌 잔액이 환불 금액보다 적어도 강행. 잔액이 마이너스가 되며 슬랙에 경고가 붙습니다. 기본 false

부분 환불은 지원하지 않습니다. 금액은 항상 원 결제 행의 amount 전액입니다.

동작

  1. 거래 조회 → PAYMENT 타입, 미삭제, candyPaymentId 존재 확인
  2. CandyPayment 조회 → 이미 CANCELLED 면 거부, 같은 주문번호에 활성 REFUND 행이 있으면 거부
  3. 기업 잔액 FOR UPDATE → remainCredit < amount 이고 force=false 면 409
  4. 캔디페이 POST /px/intents/{intentKey}/cancel 호출 → 실패 시 502, 원장 무변경
  5. CandyPayment.status = CANCELLED
  6. remainCredit -= amount, CreditTransaction(transactionType=REFUND, amount=-amount, collabNo, candyPaymentId, memo=reason, createdBy=adminId) 저장
  7. 커밋 후 결제·정산 알리미 슬랙 발송

캠페인 campaignSubStep 은 건드리지 않습니다 (기업 셀프 환불은 CAMPAIGN_PAYMENT 로 되돌리지만, 관리자 취소는 캠페인 상태와 분리).

응답 (200 OK)

{
  "status": 200,
  "code": null,
  "message": "결제가 취소되었습니다.",
  "data": {
    "paymentTransactionId": 1234,
    "refundTransactionId": 1301,
    "candyPaymentId": "glowb_20260901_abcd",
    "intentKey": "intent_xxxxxxxx",
    "businessAccountId": 57,
    "collabNo": 4321,
    "refundAmount": 1000000,
    "remainCreditBefore": 1000000,
    "remainCreditAfter": 0,
    "forced": false
  }
}
필드타입설명
paymentTransactionIdLong취소한 결제 행(원장 PAYMENT / 타임라인 CARD_PAYMENT) id
refundTransactionIdLong새로 기록된 REFUND 행 id
candyPaymentIdString캔디페이 주문번호
intentKeyString캔디페이 intentKey
refundAmountInteger환불 금액 (원 결제 전액)
remainCreditBefore / remainCreditAfterInteger기업 글로벌 잔액 변화
forcedboolean잔액 부족을 무시하고 강행했는지

에러 응답

상태 코드code사례
404NOT_FOUND거래·캔디페이 결제·기업 없음
409FINANCE_002원장 PAYMENT 타입이 아님 / 삭제된 행 / candyPaymentId 없는 행(세금계산서 입금 등 캔디페이 안 거친 충전) / 금액 0 이하
400ALREADY_CANCELED_PAYMENT캔디페이 결제가 이미 취소됨
400ALREADY_REFUND_PAYMENT같은 주문번호에 REFUND 행이 이미 있음
409FINANCE_001글로벌 잔액 부족 (force=false). 메시지에 캠페인 예치 금액과 안내 포함
502FINANCE_003캔디페이 취소 API 실패. 메시지에 캔디페이 응답 코드 포함. 원장 무변경
401—인증 실패

캔디페이 취소가 성공한 뒤 DB 커밋이 실패하면 카드만 환불된 상태가 됩니다. 이 경우 [ADMIN_CARD_REFUND] 캔디페이 취소는 성공했으나 원장 기록 실패 ERROR 로그에 intentKey 가 남으니 원장에 REFUND 행을 수동으로 기입해 정합을 맞춥니다.

API 테스트

On this page