We have been planning to build a Stripe payment plug-in module for Alpas for a while now and then create a tutorial on how to work with it.
Well, it was a little unplanned but I got called out and challenged to create an example Stripe payment plugin for Alpas by way of Twitter today.
That’s Ashok challenging me. He knows I’m competitive and can’t resist a good challenge. Especially, one against the clock! ⏰
This is before I even really knew what the challenge was. 😂
Then, I looked at what the source of the Twitter comment was.
Wow! The new tutorial format Stripe is testing out is pretty slick. They even have back-end examples for Node, PHP, Ruby, Python, Java, Go, and .NET. The only thing missing? Kotlin.
tl;dr — you can find the Kotlin / Alpas solution to Stripe’s Accept Payment on my GitHub repo.
Here are the parallel steps taken to get the example working using the Alpas starter template and the Kotlin development language.
1. Set up the server
Setup your server
Not much different than Stripe’s tutorial for this step. Select the Gradle tab, copy implementation "com.stripe:stripe-java:19.4.0"
and add to the list of dependencies in the build.gradle file.
Since we are already in build.gradle, we might as well add GSON as a dependency too since the Stripe example uses GSON for parsing JSON.
Add implementation 'com.google.code.gson:gson:2.8.5'
to the list of dependencies as well.
Once you have added the dependencies, import them by refreshing Gradle.
Create a PaymentIntent
I sliced up Stripe’s example a bit. I added the following post route to the routes.kt file.
post("/create-payment-intent", WelcomeController::payment)
Then, in the WelcomeController.kt file, added the following.
class WelcomeController : Controller() {
fun index(call: HttpCall) {
call.render("welcome")
}
fun payment(call: HttpCall) {
// This is a sample test API key. Sign in to see examples pre-filled with your key.
Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
// val request = call.jsonBody
val postBody: CreatePayment = gson.fromJson(call.body, CreatePayment::class.java)
val createParams = PaymentIntentCreateParams.Builder()
.setCurrency("usd")
.setAmount(calculateOrderAmount(postBody.items).toLong())
.build()
// Create a PaymentIntent with the order amount and currency
val intent = PaymentIntent.create(createParams)
val paymentResponse = CreatePaymentResponse(intent.clientSecret)
call.reply(gson.toJson(paymentResponse)).asJson()
}
private val gson: Gson = Gson()
fun calculateOrderAmount(items: Array<Any?>?): Int {
// Replace this constant with a calculation of the order's amount
// Calculate the order total on the server to prevent
// users from directly manipulating the amount on the client
return 1400
}
internal class CreatePayment {
@SerializedName("items")
lateinit var items: Array<Any?>
}
internal class CreatePaymentResponse(private val clientSecret: String)
}
This is the main piece that required converting Java to Kotlin. Not too difficult. Easier on the eyes. 😎
2. Build a checkout page on the client
Load Stripe.js
In the welcome.peb file, add the following before the close head tag.
<script _src_="https://js.stripe.com/v3/"></script>
Define the payment form
Also in the welcome.peb, you can copy and paste from the Stripe example.
Initialize Stripe.js
Add client.js to the web > js folder. The contents can be copied from the Stripe example and pasted into Alpas.
Fetch a PaymentIntent
This is where it gets quasi-tricky as you will need to verify a token for CSRF. You could pull from the cookie to pass the token. My solution was a little more simple. In the welcome.peb file, I added the following metadata:
<meta name="csrf-token" content="{{ _csrf }}">
This will add the CSRF token into the meta data. I’ll then use Javascript to fetch the value and pass along.
In the client.js file, I added the following to the post request header.
'X-CSRF-TOKEN': document.head.querySelector("[name~=csrf-token][content]").content
Admittedly, going into Javascript mode slowed me down greatly. Javascript just feels so dirty after being in Kotlin-bliss.
Initialize Stripe Elements
Not much to do here. Though, before this will actually work, you will need to connect the welcome.peb to the client.js file. Reference client.js from within welcome.peb by adding the following before the close head tag.
<script src="/js/client.js" defer></script>
Style the checkout form, create the card element, and surface card errors
These steps are mostly optional for you to tweak. But, you will want to copy all but the global and body styles from global.css and paste into the app.less file.
3. Complete the payment on the client
The pieces of this step are mainly showing you more around the client.js file and providing further explanation of the logic.
4. Run the application
First, you will want to re-compile and re-build the project. My recommendation is to install yarn in the project root then run yarn watch to recompile the project. Then, run via IntelliJ.
Note, I didn’t force a static port, Alpas will pick a free port for you when you run the app. Once the run is successful, go to your localhost and check out the goodness! Test credit cards are available in Stripe tutorial.
According to the Twitter timestamps, it took me a little under 2 hours. Not terrible!
I hope this example helps for those who are using a Kotlin back-end for their project. 🤙
Top comments (0)