Custom Checkout and Subscription Tiers with Stripe and Kotlin
Want to get ahead in your business by offering personalized payment and subscription options that fit your customer’s specific needs? Stripe can make this easier with an SDK that lets you easily create complex pricing plans. In this post, I delve into how you can streamline your Stripe integration with Kotlin.
Table of Contents
Custom Checkout
Stripe Checkout supports custom payment flows, allowing developers to tailor the customer experience according to their business needs. Below is an example code from Stripe’s documentation. It creates a custom Checkout Session for a purchased item.
import com.stripe.model.checkout.Session
Stripe.apiKey = "sk_test_your_key";
List<Object> lineItems = new ArrayList<>();
Map<String, Object> lineItem1 = new HashMap<>();
lineItem1.put("price", "price_H5ggYwtDq4fbrJ");
lineItem1.put("quantity", 2);
lineItems.add(lineItem1);
Map<String, Object> params = new HashMap<>();
params.put(
"success_url",
"https://example.com/success"
);
params.put("line_items", lineItems);
params.put("mode", "payment");
Session session = Session.create(params);
// Use the session URL to redirect your customer to the Stripe's checkout page
session.url
The example creates a checkout session in Stripe. Subsequently, you can use the session’s link, session.url, to redirect your customer to a Stripe’s checkout page. Moving on, the method types specify how the customer can pay, such as using a credit card. Additionally, the line items are the products or services being sold. Furthermore, depending upon the success or cancellation of the payment, you redirect the customer either to a success or a cancellation endpoint.
As much as this code excerpt makes for a great documentation of how the feature should be used, making it usable requires a bit of extra work.
Checkout Session Builder In Kotlin
First of all, in real-life project the list of purchased items varies. Let’s assume that we need a component that allows us to build an arbitrary list of items and submit them all of them at once in a single transaction. A Builder pattern seems to be good fit here.
Switching from Java to Kotlin, the implementation of a checkout session builder looks as follows.
package com.tomaszezula.stripe101.examples.payments
import com.stripe.model.checkout.Session
typealias LineItem = Map<String, Any>
class CheckoutSessionBuilder {
private var lineItems: List<LineItem> = mutableListOf()
fun addLineItem(priceId: String, quantity: Long): CheckoutSessionBuilder {
val lineItem = mapOf(
"price" to priceId,
"quantity" to quantity
)
lineItems += lineItem
return this
}
fun build(successUrl: String, cancelUrl: String): Session {
return Session.create(
mapOf(
"payment_method_types" to listOf("card"),
"line_items" to lineItems,
"mode" to "subscription",
"success_url" to successUrl,
"cancel_url" to cancelUrl
)
)
}
}
Here is how we would use it.
fun main() {
Stripe.apiKey = "your api key"
val builder = CheckoutSessionBuilder()
val session = builder
.addLineItem(priceId = "price_1NtOfQGyWpmEflR8il6mXoFE", quantity = 1)
.addLineItem(priceId = "price_1NtOj5GyWpmEflR8UyQMt48n", quantity = 5)
.build(
successUrl = "https://example.com/success",
cancelUrl = "https://example.com/cancel"
)
println(session.url)
}
Visiting the session’s link leads to a custom checkout page.
Subscription Tiers
Subscription tiers refer to different pricing levels within a subscription plan. They enable customers to choose a package that suits their needs or budget. The tier is represented by a Price object constructed identically to the checkout session. If there is one thing I love about Stripe, it’s the uniformity of their API.
Now, let’s explore an example of creating a subscription with a tiered pricing plan in Kotlin.
package com.tomaszezula.stripe101.examples.payments
import com.stripe.Stripe
import com.stripe.model.Price
typealias PriceTier = Map<String, Any>
class TieredPriceBuilder {
private var priceTiers: List<PriceTier> = mutableListOf()
fun addPriceTier(quantity: Long? = null, unitAmount: Long): TieredPriceBuilder {
val priceTier = mapOf(
"up_to" to (quantity ?: "inf"),
"unit_amount" to unitAmount
)
priceTiers += priceTier
return this
}
fun build(currency: String, productId: String, tiersMode: String): Price {
return Price.create(
mapOf(
"currency" to currency,
"product" to productId,
"tiers_mode" to tiersMode,
"tiers" to priceTiers,
"recurring" to mapOf(
"interval" to "month",
"interval_count" to 1
),
"billing_scheme" to "tiered"
)
)
}
}
Usage:
fun main() {
Stripe.apiKey = "your api key"
val builder = TieredPriceBuilder()
val price = builder
.addPriceTier(quantity = 5, unitAmount = 1000)
.addPriceTier(unitAmount = 750)
.build(
currency = "usd",
productId = "prod_OgmmKvjqDCDvcM",
tiersMode = "graduated"
)
println(price)
}
Here, we create two price tiers, each with unique characteristics. The first tier provides up to 10 units at a unit price of $10.00, while the second tier provides an unlimited number of units at reduced unit costs of $7.50.
Now I can purchase the product at a discounted price.
Summary
Through these examples, you get a taste of the flexibility and power Stripe provides developers with its robust, feature-packed Java SDK. With the help of Stripe’s checkout sessions and subscription tiers, developers can create complex custom payment structures catering to the evolving needs of their customers. The transition from Java to Kotlin is not only instinctive but also offers the added benefit of a more concise and manageable code.
Thanks for reading. Feel free to explore the code examples on GitHub.