- Java 88.7%
- Kotlin 11.3%
BREAKING CHANGE: API 주문 응답에서 cafe24{mallId, shopNo, orderId}가 빠지고 shopOrder{platform, storeId, shopNo, orderId}가 들어와 Invoice.cafe24()와 Invoice.Cafe24를 Invoice.shopOrder()와 Invoice.ShopOrder로 바꿉니다.
- ShopPlatform(CAFE24, SIXSHOP, GODOMALL) 추가, InvoiceSource에 SIXSHOP, GODOMALL 추가
- ActorType에 연결된 앱(CONNECTED_APP) 추가
- ErrorCode에 연결된 앱 토큰 오류 380009, 380010 추가
- 은행별 연결할 수 있는 계좌 종류 문서화 (하나은행 기업 계좌 지원)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|---|---|---|
| gradle | ||
| paysync-sdk | ||
| paysync-sdk-kotlin | ||
| .gitattributes | ||
| .gitignore | ||
| build.gradle.kts | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| LICENSE | ||
| README.md | ||
| settings.gradle.kts | ||
PaySync Java SDK
PaySync API를 Java와 Kotlin에서 쓰는 SDK입니다. API 명세는 PaySync API 문서를 참고하세요.
| 모듈 | 설명 |
|---|---|
kr.paysync:paysync-sdk |
Java SDK. Java 17 이상 |
kr.paysync:paysync-sdk-kotlin |
Kotlin 확장. 코루틴, Flow, 람다 빌더. Kotlin 2.2 이상 |
설치
repositories {
mavenCentral()
maven("https://forgejo.verchase.com/api/packages/paysync/maven")
}
dependencies {
implementation("kr.paysync:paysync-sdk:1.0.0")
// Kotlin
implementation("kr.paysync:paysync-sdk-kotlin:1.0.0")
}
<repositories>
<repository>
<id>paysync</id>
<url>https://forgejo.verchase.com/api/packages/paysync/maven</url>
</repository>
</repositories>
<dependency>
<groupId>kr.paysync</groupId>
<artifactId>paysync-sdk</artifactId>
<version>1.0.0</version>
</dependency>
Java
PaySyncClient client = PaySyncClient.create(System.getenv("PAYSYNC_API_KEY"));
Invoice invoice = client.invoices().create(InvoiceCreateParams.builder()
.customerName("홍길동")
.amount(50_000)
.expireAfterDays(3)
.build());
| API | 메서드 |
|---|---|
client.invoices() |
create, get, list, listAll, update, markPaid, cancel |
client.transactions() |
get, list, listAll |
client.cashReceipts() |
issue, get, list, listAll, cancel, reissue, urls, sendEmail |
메서드마다 CompletableFuture를 돌려주는 ...Async 버전이 있습니다.
목록 조회
list는 한 페이지를, listAll은 조건에 맞는 항목을 모두 조회합니다.
Page<Invoice> page = client.invoices().list(InvoiceListParams.builder()
.status(InvoiceStatus.PENDING)
.limit(50)
.build());
for (Transaction transaction : client.transactions().listAll()) {
System.out.println(transaction.depositorName());
}
주문 수정
넣은 값만 바뀝니다. 값을 지우려면 clear...를 씁니다.
client.invoices().update(invoice.id(), InvoiceUpdateParams.builder()
.amount(55_000)
.clearCustomerPhoneNumber()
.build());
응답 값
카페24, 식스샵 프로 같은 쇼핑몰 연동으로 만든 주문은 source()가 그 플랫폼이고, shopOrder()에 플랫폼, 쇼핑몰 아이디, 멀티쇼핑몰 번호, 쇼핑몰 주문번호가 담깁니다. 다른 주문은 shopOrder()가 null입니다.
Invoice.ShopOrder shopOrder = invoice.shopOrder();
if (shopOrder != null && shopOrder.platform() == ShopPlatform.CAFE24) {
System.out.println(shopOrder.storeId() + " " + shopOrder.orderId());
}
입금의 bankAccount().provider()와 type()은 은행과 계좌 종류(PERSONAL, CORPORATE)입니다. 국민은행과 하나은행은 개인, 기업 계좌를, 농협은행과 신한은행은 개인 계좌를, 기업은행은 기업 계좌를 연결할 수 있습니다. 자세한 내용은 지원 은행을 참고하세요.
열거형은 SDK가 모르는 새 값을 받으면 UNKNOWN이 됩니다.
오류 처리
PaySync가 오류를 응답하면 PaySyncApiException을 던집니다. code()로 오류를 구분하고, 자주 쓰는 값은 ErrorCode에 있습니다.
| 예외 | HTTP |
|---|---|
AuthenticationException |
401 |
PermissionDeniedException |
403 |
NotFoundException |
404 |
ConflictException |
409 |
InvalidRequestException |
400, 422 등 |
RateLimitException |
429 |
ServerException |
5xx |
PaySyncConnectionException |
연결 실패, 응답 시간 초과 |
try {
client.invoices().create(params);
} catch (ConflictException e) {
if (ErrorCode.INVOICE_ALREADY_EXISTS.equals(e.code())) {
String existingId = e.duplicateInvoice().invoiceId();
}
}
웹훅
대시보드에서 확인한 서명 키(whsec_...)로 검증합니다. 본문은 받은 문자열을 그대로 넣으세요.
Webhook webhook = new Webhook(System.getenv("PAYSYNC_WEBHOOK_SECRET"));
WebhookEvent event = webhook.verify(rawBody, headers);
switch (event) {
case WebhookEvent.InvoiceEvent e when e.type() == WebhookEventType.INVOICE_PAID -> fulfill(e.invoice());
case WebhookEvent.InvoiceEvent e -> { }
case WebhookEvent.TransactionEvent e -> { }
case WebhookEvent.UnknownEvent e -> { }
}
서명이 맞지 않으면 WebhookVerificationException을 던집니다. 같은 이벤트가 여러 번 올 수 있으니 event.id()로 중복을 거르세요.
Kotlin
val client = SuspendingPaySyncClient(System.getenv("PAYSYNC_API_KEY"))
val invoice = client.invoices.create {
customerName("홍길동")
amount(50_000)
}
client.invoices.update(invoice.id()) {
clearExpiresAt()
}
client.transactions.listAll { status(TransactionStatus.UNMATCHED) }
.collect { println(it.depositorName) }
이미 만든 클라이언트는 client.suspending()으로 코루틴용으로 바꿉니다. 블로킹 클라이언트에서도 client.invoices().create { ... }처럼 람다로 요청을 만들 수 있습니다.
when (val event = webhook.verify(rawBody, headers)) {
is WebhookEvent.InvoiceEvent -> fulfill(event.invoice())
is WebhookEvent.TransactionEvent -> log(event.transaction())
is WebhookEvent.UnknownEvent -> Unit
}