安装
Gradle (Kotlin DSL)
在你的build.gradle.kts 中添加依赖:
build.gradle.kts
implementation("com.dodopayments.api:dodo-payments-kotlin:1.86.3")
Maven
在你的pom.xml 中添加依赖:
pom.xml
<dependency>
<groupId>com.dodopayments.api</groupId>
<artifactId>dodo-payments-kotlin</artifactId>
<version>1.86.3</version>
</dependency>
始终使用最新的 SDK 版本以访问最新的 Dodo Payments 功能。请查看 Maven Central 以获取最新版本。
该 SDK 需要 Java 8 或更高版本,并兼容 JVM 与 Android 平台。
快速开始
初始化客户端并创建结账会话:import com.dodopayments.api.client.DodoPaymentsClient
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionCreateParams
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionRequest
import com.dodopayments.api.models.checkoutsessions.ProductItemReq
// 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(ProductItemReq.builder()
.productId("product_id")
.quantity(1)
.build())
.build()
val checkoutSessionResponse: CheckoutSessionResponse = client.checkoutSessions().create(params)
println(checkoutSessionResponse.sessionId())
始终使用环境变量或加密配置安全存储 API 密钥。切勿将其提交到版本控制。
核心功能
Coroutines
全面支持 Kotlin 协程以进行异步操作
Null Safety
利用 Kotlin 的空安全性实现健壮的错误处理
Extension Functions
符合习惯用法的 Kotlin 扩展以增强功能性
Data Classes
具备复制与解构支持的类型安全数据类
配置
从环境变量
从环境变量或系统属性初始化: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()
测试模式
为 Test Mode 环境进行配置: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(
"pdt_123",
RequestOptions.builder()
.timeout(Duration.ofSeconds(10))
.build()
)
常见操作
创建结账会话
生成结账会话:val params = CheckoutSessionRequest.builder()
.addProductCart(ProductItemReq.builder()
.productId("pdt_123")
.quantity(1)
.build())
.returnUrl("https://yourdomain.com/return")
.build()
val session = client.checkoutSessions().create(params)
println("Checkout URL: ${session.checkoutUrl()}")
创建产品
创建具有详细配置的产品:import com.dodopayments.api.models.products.Price
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
import com.dodopayments.api.models.misc.TimeInterval
val createParams = ProductCreateParams.builder()
.name("Premium Subscription")
.description("Monthly subscription with all features")
.price(
Price.RecurringPrice.builder()
.currency(Currency.USD)
.price(2999) // $29.99 in cents
.discount(0L)
.purchasingPowerParity(false)
.paymentFrequencyCount(1)
.paymentFrequencyInterval(TimeInterval.MONTH)
.subscriptionPeriodCount(1)
.subscriptionPeriodInterval(TimeInterval.MONTH)
.build()
)
.taxCategory(TaxCategory.DIGITAL_PRODUCTS)
.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")
.name("user-laptop-01")
.build()
try {
val activationResult: LicenseActivateResponse = client.licenses()
.activate(activateParams)
println("License activated successfully")
println("Instance ID: ${activationResult.id()}")
println("License key ID: ${activationResult.licenseKeyId()}")
} catch (e: UnprocessableEntityException) {
println("License activation failed: ${e.message}")
}
基于使用的计费
记录使用事件
POST /subscriptions(SDK 的 subscriptions.create 方法)已弃用。对于现有集成,它仍然有效,但新集成应通过 Checkout Session 创建订阅。import com.dodopayments.api.models.payments.AttachExistingCustomer
import com.dodopayments.api.models.payments.BillingAddress
import com.dodopayments.api.models.misc.CountryCode
import com.dodopayments.api.models.subscriptions.SubscriptionChargeParams
import com.dodopayments.api.models.subscriptions.SubscriptionCreateParams
// Create a subscription
val subscriptionParams = SubscriptionCreateParams.builder()
.billing(BillingAddress.builder()
.city("San Francisco")
.country(CountryCode.US)
.state("CA")
.street("1 Market St")
.zipcode("94105")
.build())
.customer(AttachExistingCustomer.builder()
.customerId("cus_123")
.build())
.productId("pdt_456")
.quantity(1)
.build()
val subscription = client.subscriptions().create(subscriptionParams)
println("Subscription ID: ${subscription.subscriptionId()}")
// Charge an on-demand subscription
// productPrice is in the lowest currency denomination (e.g., 2500 = $25.00 USD)
val chargeParams = SubscriptionChargeParams.builder()
.subscriptionId(subscription.subscriptionId())
.productPrice(2500)
.build()
val chargeResponse = client.subscriptions().charge(chargeParams)
println("Payment ID: ${chargeResponse.paymentId()}")
billing 至少需要两位字母的 ISO country 代码。使用 AttachExistingCustomer 关联现有客户,或使用 NewCustomer 创建客户。productPrice 以货币的最小面额表示。基于使用量的计费
记录使用量事件
跟踪计量器的使用量:import com.dodopayments.api.models.usageevents.EventInput
import com.dodopayments.api.models.usageevents.UsageEventIngestParams
val usageParams = UsageEventIngestParams.builder()
.addEvent(EventInput.builder()
.customerId("cust_456")
.eventId("event_123")
.eventName("api_call")
.build())
.build()
client.usageEvents().ingest(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.paymentId()}")
} 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
safeCreatePayment(client)
.onSuccess { payment -> println("Created: ${payment.paymentId()}") }
.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.checkoutUrl())
} catch (e: Exception) {
handleError(e)
}
}
}
}
响应验证
启用响应验证:import com.dodopayments.api.core.RequestOptions
// Per-request validation
val product = client.products().retrieve(
"pdt_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.checkoutUrl()))
} catch (e: DodoPaymentsServiceException) {
call.respond(HttpStatusCode.BadRequest, mapOf("error" to e.message))
}
}
}
}
资源
GitHub Repository
查看源代码并参与贡献
API Reference
完整的 API 文档
Discord Community
获取帮助并与开发者交流
Report Issues
报告错误或请求新功能
支持
需要 Kotlin SDK 方面的帮助?- Discord:加入我们的社区服务器,获取实时支持
- Email:通过 support@dodopayments.com 联系我们
- GitHub:在代码仓库中提交 issue