跳转到主要内容
Kotlin SDK 提供了从 Kotlin 编写的应用程序访问 Dodo Payments REST API 的便捷方式。它具有可空值、Sequence、挂起函数和其他 Kotlin 特有的功能,以便于使用。

安装

Gradle (Kotlin DSL)

将依赖项添加到您的 build.gradle.kts
build.gradle.kts
implementation("com.dodopayments.api:dodo-payments-kotlin:1.61.5")

Maven

将依赖项添加到您的 pom.xml
pom.xml
<dependency>
  <groupId>com.dodopayments.api</groupId>
  <artifactId>dodo-payments-kotlin</artifactId>
  <version>1.61.5</version>
</dependency>
始终使用最新的 SDK 版本以访问最新的 Dodo Payments 功能。请查看 Maven Central 以获取最新版本。
SDK 需要 Kotlin 1.6 或更高版本,并与 JVM 和 Android 平台兼容。

快速开始

初始化客户端并创建结账会话:
import com.dodopayments.api.client.DodoPaymentsClient
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionRequest
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionResponse

// Configure using environment variables (DODO_PAYMENTS_API_KEY, DODO_PAYMENTS_BASE_URL)
// Or system properties (dodopayments.apiKey, dodopayments.baseUrl)
val client: DodoPaymentsClient = DodoPaymentsOkHttpClient.fromEnv()

val params: CheckoutSessionRequest = CheckoutSessionRequest.builder()
    .addProductCart(CheckoutSessionRequest.ProductCart.builder()
        .productId("product_id")
        .quantity(1)
        .build())
    .build()
    
val checkoutSessionResponse: CheckoutSessionResponse = client.checkoutSessions().create(params)
println(checkoutSessionResponse.sessionId())
始终使用环境变量或加密配置安全存储您的 API 密钥。切勿将其提交到版本控制中。

核心功能

协程

完全支持 Kotlin 协程进行异步操作

空安全性

利用 Kotlin 的空安全性进行稳健的错误处理

扩展函数

习惯用法的 Kotlin 扩展以增强功能

数据类

类型安全的数据类,支持复制和解构

配置

从环境变量

从环境变量或系统属性初始化:
val client: DodoPaymentsClient = DodoPaymentsOkHttpClient.fromEnv()

手动配置

手动配置所有选项:
import java.time.Duration

val client = DodoPaymentsOkHttpClient.builder()
    .bearerToken("your_api_key_here")
    .baseUrl("https://live.dodopayments.com")
    .maxRetries(3)
    .timeout(Duration.ofSeconds(30))
    .build()

测试模式

为测试/沙盒环境配置:
val testClient = DodoPaymentsOkHttpClient.builder()
    .fromEnv()
    .testMode()
    .build()

超时和重试

全局或每请求配置:
import com.dodopayments.api.core.RequestOptions

// Global configuration
val client = DodoPaymentsOkHttpClient.builder()
    .fromEnv()
    .timeout(Duration.ofSeconds(45))
    .maxRetries(3)
    .build()

// Per-request timeout override
val product = client.products().retrieve(
    "prod_123",
    RequestOptions.builder()
        .timeout(Duration.ofSeconds(10))
        .build()
)

常见操作

创建结账会话

生成结账会话:
val params = CheckoutSessionRequest.builder()
    .addProductCart(CheckoutSessionRequest.ProductCart.builder()
        .productId("prod_123")
        .quantity(1)
        .build())
    .returnUrl("https://yourdomain.com/return")
    .build()

val session = client.checkoutSessions().create(params)
println("Checkout URL: ${session.url()}")

创建产品

创建具有详细配置的产品:
import com.dodopayments.api.models.products.Product
import com.dodopayments.api.models.products.ProductCreateParams
import com.dodopayments.api.models.misc.Currency
import com.dodopayments.api.models.misc.TaxCategory

val createParams = ProductCreateParams.builder()
    .name("Premium Subscription")
    .description("Monthly subscription with all features")
    .price(
        ProductCreateParams.RecurringPrice.builder()
            .currency(Currency.USD)
            .preTaxAmount(2999) // $29.99 in cents
            .paymentFrequencyInterval(ProductCreateParams.RecurringPrice.TimeInterval.MONTH)
            .paymentFrequencyCount(1)
            .build()
    )
    .taxCategory(TaxCategory.DIGITAL_GOODS)
    .build()

val product: Product = client.products().create(createParams)
println("Created product ID: ${product.productId()}")

激活许可证密钥

为客户激活许可证密钥:
import com.dodopayments.api.models.licenses.LicenseActivateParams
import com.dodopayments.api.models.licenses.LicenseActivateResponse

val activateParams = LicenseActivateParams.builder()
    .licenseKey("XXXX-XXXX-XXXX-XXXX")
    .instanceName("user-laptop-01")
    .build()

try {
    val activationResult: LicenseActivateResponse = client.licenses()
        .activate(activateParams)

    println("License activated successfully")
    println("Instance ID: ${activationResult.instanceId()}")
    println("Expires at: ${activationResult.expiresAt()}")
} catch (e: UnprocessableEntityException) {
    println("License activation failed: ${e.message}")
}

基于使用的计费

记录使用事件

跟踪计量的使用情况:
import com.dodopayments.api.models.usageevents.UsageEventCreateParams
import java.time.OffsetDateTime

val usageParams = UsageEventCreateParams.builder()
    .meterId("meter_123")
    .customerId("cust_456")
    .value(150)
    .timestamp(OffsetDateTime.now())
    .build()

client.usageEvents().create(usageParams)
println("Usage event recorded")

异步操作

异步客户端

使用异步客户端进行基于协程的操作:
import com.dodopayments.api.client.DodoPaymentsClientAsync
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClientAsync
import kotlinx.coroutines.runBlocking

val asyncClient: DodoPaymentsClientAsync = DodoPaymentsOkHttpClientAsync.fromEnv()

runBlocking {
    val customer = asyncClient.customers().retrieve("cust_123")
    println("Customer email: ${customer.email()}")
}

错误处理

使用 Kotlin 的异常处理处理错误:
import com.dodopayments.api.errors.*

try {
    val payment = client.payments().create(params)
    println("Success: ${payment.id()}")
} catch (e: AuthenticationException) {
    println("Authentication failed: ${e.message}")
} catch (e: InvalidRequestException) {
    println("Invalid request: ${e.message}")
    e.parameter?.let { println("Parameter: $it") }
} catch (e: RateLimitException) {
    println("Rate limit exceeded, retry after: ${e.retryAfter}")
} catch (e: DodoPaymentsServiceException) {
    println("API error: ${e.statusCode()} - ${e.message}")
}

函数式错误处理

使用 Result 进行函数式错误处理:
fun safeCreatePayment(client: DodoPaymentsClient): Result<Payment> = runCatching {
    client.payments().create(params)
}

// Usage
safe CreatePayment(client)
    .onSuccess { payment -> println("Created: ${payment.id()}") }
    .onFailure { error -> println("Error: ${error.message}") }
使用 Kotlin 的 runCatching 以更函数式的方式处理错误,使用 Result 类型。

Android 集成

与 Android 应用程序一起使用:
import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dodopayments.api.client.DodoPaymentsClient
import kotlinx.coroutines.launch

class PaymentViewModel(application: Application) : ViewModel() {
    private val client = DodoPaymentsOkHttpClient.builder()
        .bearerToken(BuildConfig.DODO_API_KEY)
        .build()
    
    fun createCheckout(productId: String) {
        viewModelScope.launch {
            try {
                val session = client.async().checkoutSessions().create(params)
                // Open checkout URL in browser or WebView
                openUrl(session.url())
            } catch (e: Exception) {
                handleError(e)
            }
        }
    }
}

响应验证

启用响应验证:
import com.dodopayments.api.core.RequestOptions

// Per-request validation
val product = client.products().retrieve(
    "prod_123",
    RequestOptions.builder()
        .responseValidation(true)
        .build()
)

// Or validate explicitly
val validatedProduct = product.validate()

高级功能

代理配置

配置代理设置:
import java.net.InetSocketAddress
import java.net.Proxy

val client = DodoPaymentsOkHttpClient.builder()
    .fromEnv()
    .proxy(
        Proxy(
            Proxy.Type.HTTP,
            InetSocketAddress("proxy.example.com", 8080)
        )
    )
    .build()

临时配置

临时修改客户端配置:
val customClient = client.withOptions {
    it.baseUrl("https://example.com")
    it.maxRetries(5)
}

Ktor 集成

与 Ktor 服务器应用程序集成:
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun Application.configureRouting() {
    val client = DodoPaymentsOkHttpClient.builder()
        .bearerToken(environment.config.property("dodo.apiKey").getString())
        .build()
    
    routing {
        post("/create-checkout") {
            try {
                val request = call.receive<CheckoutRequest>()
                val session = client.checkoutSessions().create(params)
                call.respond(mapOf("checkout_url" to session.url()))
            } catch (e: DodoPaymentsServiceException) {
                call.respond(HttpStatusCode.BadRequest, mapOf("error" to e.message))
            }
        }
    }
}

资源

支持

需要 Kotlin SDK 的帮助吗?

贡献

我们欢迎贡献!请查看 贡献指南 开始。