spring boot starter toss payments
토스페이먼츠 API 버전 2022-11-16 으로 작성되었습니다.
To get a Git project into your build:
Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency
dependencies {
implementation 'com.github.herbaccara:spring-boot-starter-toss-payments:Tag'
}
toss:
payments:
enabled: true
client-key: 클라이언트 키
client-secret: 클라이언트 시크릿
fail-on-unknown-properties: false
webhook:
enabled: true
path: /toss/payments/webhook
auth:
enabled: true
path: /toss/payments/auth
class SpringComponent (
private val tossPaymentsService: TossPaymentsService
)
아래 2개의 인터페이스를 상속받은 class 를 만들고 bean 으로 등록
interface TossPaymentsRestTemplateBuilderCustomizer {
fun customize(restTemplateBuilder: RestTemplateBuilder)
}
interface TossPaymentsClientHttpRequestInterceptor : ClientHttpRequestInterceptor
toss.webhook.enabled 값이 true 인 경우 자동으로 TossPaymentsWebhookController 가 bean 으로 등록됩니다.
webhook event 는 applicationEventPublisher 에 즉시 publishEvent 됩니다.
직접 TossPaymentsWebhookController 를 상속받은 component 를 등록해서 사용 하실 수 있습니다.
@RestController
@RequestMapping("\${toss.payments.webhook.path:${TossPaymentsProperties.DEFAULT_WEBHOOK_PATH}}")
class TossPaymentsWebhookController(
private val applicationEventPublisher: ApplicationEventPublisher
) {
/**
* 가상계좌 결제 상태를 알려주는 웹훅
*/
@RequestMapping("/deposit-callback")
fun onDepositCallback(depositCallback: DepositCallback) {
applicationEventPublisher.publishEvent(depositCallback)
}
/**
* 카드, 계좌이체, 휴대폰, 상품권 결제 상태를 알려주는 웹훅입니다.
*/
@RequestMapping("/payment-status-changed")
fun onPaymentStatusChanged(paymentStatusChangedEvent: Event<PaymentStatusChanged>) {
applicationEventPublisher.publishEvent(paymentStatusChangedEvent)
}
/**
* 지급대행 요청 상태가 COMPLETED, FAILED로 변경되면 웹훅이 전송됩니다. 자세한 상태 설명은 status에서 확인하세요.
*/
@RequestMapping("/payout-status-changed")
fun onPayoutStatusChanged(payoutStatusChangedEvent: Event<PayoutStatusChanged>) {
applicationEventPublisher.publishEvent(payoutStatusChangedEvent)
}
/**
* 브랜드페이 고객의 결제 수단이 변경되면 웹훅이 전송됩니다.
*/
@RequestMapping("/method-updated")
fun onMethodUpdated(methodUpdatedEvent: Event<MethodUpdated>) {
applicationEventPublisher.publishEvent(methodUpdatedEvent)
}
/**
* 브랜드페이 고객의 상태가 변경되면 웹훅이 전송됩니다.
*/
@RequestMapping("/customer-status-changed")
fun onCustomerStatusChanged(customerStatusChangedEvent: Event<CustomerStatusChanged>) {
applicationEventPublisher.publishEvent(customerStatusChangedEvent)
}
}
AbstractTossPaymentsEventListener.kt 를 상속받은 component 를 bean 으로 등록해서 webhook event 를 처리 할 수 있습니다.
abstract class AbstractTossPaymentsEventListener {
@EventListener
abstract fun onDepositCallback(depositCallback: DepositCallback)
@EventListener
abstract fun onPaymentStatusChanged(paymentStatusChangedEvent: Event<PaymentStatusChanged>)
@EventListener
abstract fun onPayoutStatusChanged(payoutStatusChangedEvent: Event<PayoutStatusChanged>)
@EventListener
abstract fun onMethodUpdated(methodUpdatedEvent: Event<MethodUpdated>)
@EventListener
abstract fun onCustomerStatusChanged(customerStatusChangedEvent: Event<CustomerStatusChanged>)
}
@RestController
@RequestMapping("\${toss.payments.auth.path:$DEFAULT_WEBHOOK_PATH}")
class TossPaymentsAuthController(
private val tossPaymentsService: TossPaymentsService,
private val tossPaymentsAuthInterceptor: TossPaymentsAuthInterceptor
) {
companion object {
const val DEFAULT_WEBHOOK_PATH = "/toss/payments/auth"
}
@GetMapping
fun auth(
@RequestParam("code") code: String,
@RequestParam("customerKey") customerKey: String
): Map<String, Any> {
tossPaymentsAuthInterceptor.preHandle(code, customerKey)
val token = try {
tossPaymentsService.brandPayAuthorizationAccessToken(
customerKey,
GrantType.RefreshToken,
code
)
} catch (e: HttpClientErrorException.Forbidden) {
tossPaymentsService.brandPayAuthorizationAccessToken(
customerKey,
GrantType.AuthorizationCode,
code
)
}
tossPaymentsAuthInterceptor.postHandle(code, customerKey, token)
val (accessToken, refreshToken, tokenType, expiresIn) = token
return mapOf(
"accessToken" to accessToken,
"tokenType" to tokenType,
"expiresIn" to expiresIn
)
}
}
TossPaymentsAuthInterceptor 을 상속받은 class 를 Bean 을 등록 할 수 있습니다.
open class TossPaymentsAuthInterceptor {
fun preHandle(code: String, customerKey: String) {
// nothing
}
fun postHandle(code: String, customerKey: String, token: Token) {
// nothing
}
fun afterCompletion(code: String, customerKey: String, token: Token?, e: Throwable?) {
// nothing
}
}