-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial webhook autoconfiguration setup (#1)
* add typed handler to use objects of stripe framework * adds exception handling * setup dependencies properly * use properties set in gradle properties for plugin mgmt * add more examples and fix test * add workflows * add jacoco test report * rename workflows and jobs * move sonar into subproject description * add jacocoTestReport to sonar workflow * define sonar on root project * exclude sample project from analysis * add first set of tests * test handler support methods * fix event mock * add publishing task * define publication in same project that should be published * add execution results to stripe * add json property annotations * adds quickstart guide * add combined onCondition function * add stripe class conditonal for autoconfiguration * simplify and add tests * add readme and getting started guide * previousAttributes optional * use event istead of event type * pass original event onReceive * add conditional evaluation debug log * add test for evaluation report * add conditon test
- Loading branch information
1 parent
8869454
commit 708882c
Showing
24 changed files
with
1,487 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
name: gradle | ||
|
||
# Controls when the action will run. | ||
on: | ||
pull_request: | ||
branches: [ main ] | ||
|
||
# Allows you to run this workflow manually from the Actions tab | ||
workflow_dispatch: | ||
|
||
jobs: | ||
check: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: git checkout | ||
uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: setup java | ||
uses: actions/setup-java@v1 | ||
with: | ||
java-version: '11' | ||
|
||
- name: gradle cache | ||
uses: actions/cache@v2 | ||
with: | ||
path: | | ||
~/.gradle/caches | ||
~/.gradle/wrapper | ||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} | ||
restore-keys: | | ||
${{ runner.os }}-gradle- | ||
- name: test | ||
run: | | ||
./gradlew check |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
name: gradle | ||
|
||
# Controls when the action will run. | ||
on: | ||
push: | ||
tags: | ||
- v* | ||
|
||
# Allows you to run this workflow manually from the Actions tab | ||
workflow_dispatch: | ||
|
||
jobs: | ||
publish: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: git checkout | ||
uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: setup java | ||
uses: actions/setup-java@v1 | ||
with: | ||
java-version: '11' | ||
|
||
- name: setup build cache | ||
uses: actions/cache@v2 | ||
with: | ||
path: | | ||
~/.gradle/caches | ||
~/.gradle/wrapper | ||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} | ||
restore-keys: | | ||
${{ runner.os }}-gradle- | ||
- name: publish | ||
env: | ||
SONATYPE_USER: ${{ secrets.SONATYPE_USER }} | ||
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} | ||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }} | ||
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} | ||
run: | | ||
./gradlew publish |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
name: gradle | ||
|
||
# Controls when the action will run. | ||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
branches: [ main ] | ||
types: [ opened, synchronize, reopened ] | ||
|
||
# Allows you to run this workflow manually from the Actions tab | ||
workflow_dispatch: | ||
|
||
jobs: | ||
analyse: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: git checkout | ||
uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: setup java | ||
uses: actions/setup-java@v1 | ||
with: | ||
java-version: '11' | ||
|
||
- name: gradle cache | ||
uses: actions/cache@v2 | ||
with: | ||
path: | | ||
~/.gradle/caches | ||
~/.gradle/wrapper | ||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} | ||
restore-keys: | | ||
${{ runner.os }}-gradle- | ||
- name: sonar cache | ||
uses: actions/cache@v1 | ||
with: | ||
path: ~/.sonar/cache | ||
key: ${{ runner.os }}-sonar | ||
restore-keys: ${{ runner.os }}-sonar | ||
|
||
- name: analyse | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any | ||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | ||
run: ./gradlew check jacocoTestReport sonarqube --info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
.DS_Store | ||
.gradle | ||
**/build/ | ||
!gradle/wrapper/gradle-wrapper.jar | ||
|
||
|
||
### STS ### | ||
.apt_generated | ||
.classpath | ||
.factorypath | ||
.project | ||
.settings | ||
.springBeans | ||
.sts4-cache | ||
|
||
### IntelliJ IDEA ### | ||
.idea | ||
*.iws | ||
*.iml | ||
*.ipr | ||
**/out/ | ||
|
||
### NetBeans ### | ||
/nbproject/private/ | ||
/build/ | ||
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
### What You Will Build | ||
|
||
You will build an application that receives a subscription update stripe event by using ```StripeEventHandler```. | ||
|
||
### What You Need | ||
|
||
- About 15 minutes | ||
- A favorite text editor or IDE | ||
- JDK 11 or later | ||
- Gradle | ||
|
||
### Starting with Spring Initializr | ||
|
||
For all Spring applications, you should start with the [Spring Initializr](https://start.spring.io/). The Initializr | ||
offers a fast way to pull in all the dependencies you need for an application and does a lot of the set up for you. This | ||
example needs only the Spring Web dependency, Java 11 and Gradle | ||
|
||
Add the following to your ```build.gradle.kts``` or ```build.gradle``` | ||
|
||
```kotlin | ||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile | ||
|
||
plugins { | ||
id("org.springframework.boot") version "2.4.2" | ||
id("io.spring.dependency-management") version "1.0.11.RELEASE" | ||
kotlin("jvm") version "1.4.21" | ||
kotlin("plugin.spring") version "1.4.21" | ||
} | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
// add the stripe spring boot starter to your gradle build file | ||
implementation("io.hndrs:stripe-spring-boot-starter:1.0.0") | ||
|
||
// add the stripe java library | ||
implementation("com.stripe:stripe-java:20.37.0") | ||
|
||
|
||
implementation("org.springframework.boot:spring-boot-starter-web") | ||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin") | ||
implementation("org.jetbrains.kotlin:kotlin-reflect") | ||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") | ||
testImplementation("org.springframework.boot:spring-boot-starter-test") | ||
} | ||
|
||
tasks.withType<KotlinCompile> { | ||
kotlinOptions { | ||
freeCompilerArgs = listOf("-Xjsr305=strict") | ||
jvmTarget = "11" | ||
} | ||
} | ||
|
||
tasks.withType<Test> { | ||
useJUnitPlatform() | ||
} | ||
|
||
|
||
``` | ||
|
||
### Configure the stripe webhook | ||
|
||
To configure the stripe webhook we need to set its ```signingSecret``` and the ```webhook-path```. Add the following | ||
properties to ```src/main/resources/application``` | ||
|
||
```properties | ||
hndrs.stripe.signingSecret=whsc_********** | ||
hndrs.stripe.webhook-path=/stripe-events | ||
``` | ||
|
||
> The signing secret can be obtained on your [Stripe Dashboard](https://dashboard.stripe.com/test/webhooks) or with the [Stripe CLI](https://stripe.com/docs/stripe-cli/webhooks) | ||
### Create a Stripe Event Handler | ||
|
||
With any webhook-event-based application, you need to create a receiver that responds to published webhook events. The | ||
following implementation shows how to do so: | ||
|
||
```kotlin | ||
@Component | ||
open class ExampleReceiver : StripeEventReceiver<Subscription>(Subscription::class.java) { | ||
|
||
override fun onCondition(event: Event): Boolean { | ||
// check the event type | ||
return event.type == "customer.subscription.updated" | ||
} | ||
|
||
companion object { | ||
private val LOG = LoggerFactory.getLogger(ExampleReceiver::class.java) | ||
} | ||
} | ||
``` | ||
|
||
### Send a Test Message | ||
|
||
Use the [Stripe Cli](https://stripe.com/docs/stripe-cli/webhooks) to send a test event. | ||
|
||
#### Listen for events | ||
|
||
```shell | ||
stripe listen | ||
``` | ||
|
||
#### Trigger an event | ||
|
||
```shell | ||
stripe trigger customer.subscription.updated | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
[![Current Version](https://img.shields.io/maven-central/v/io.hndrs/hndrs_stripe-spring-boot-starter?style=for-the-badge&logo=sonar)](https://search.maven.org/search?q=io.hndrs) | ||
[![Coverage](https://img.shields.io/sonar/coverage/hndrs_stripe-spring-boot-starter?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge)](https://sonarcloud.io/dashboard?id=hndrs_stripe-spring-boot-starter) | ||
[![Supported Java Version](https://img.shields.io/badge/Supported%20Java%20Version-11%2B-informational?style=for-the-badge)]() | ||
[![License](https://img.shields.io/github/license/hndrs/stripe-spring-boot-starter?style=for-the-badge)]() | ||
[![Sponsor](https://img.shields.io/static/v1?logo=GitHub&label=Sponsor&message=%E2%9D%A4&color=ff69b4&style=for-the-badge)](https://github.com/sponsors/marvinschramm) | ||
|
||
# stripe-spring-boot-starter | ||
|
||
Follow the [Getting Started Guide](GETTING_STARTED_GUIDE.md) or look at the [Sample](/sample) to help setting up | ||
stripe-spring-boot-starter. | ||
|
||
#### Dependency | ||
|
||
```kotlin | ||
implementation("io.hndrs:stripe-spring-boot-starter:1.0.0") | ||
|
||
//skip this if you already have the stripe dependency in your project | ||
implementation("com.stripe:stripe-java:<version>") | ||
``` | ||
|
||
> Gradle | ||
#### Configuration | ||
|
||
```properties | ||
hndrs.stripe.signing-secret=whsec_******************* | ||
hndrs.stripe.webhook-path=/stripe-events | ||
``` | ||
|
||
> application.properties | ||
#### StripeEventReceiver | ||
|
||
There are 3 conditional methods that can be used to narrow the execution condition (Note: there is an | ||
internal ```class``` conditional that makes sure that the receiver only receives the defined generic type. You can | ||
override any of the following methods (by default they return true) | ||
|
||
- ```onCondition(event: Event)``` | ||
- *It is recommended to use this conditional to check at least the event type* | ||
- ```onReceive(stripeObject: Subscription)``` | ||
- *It is recommended to use this when your condition **only** needs values from the ```stripeObject``` for your | ||
business logic | ||
- ```onCondition(previousAttributes: Map<String, Any?>?)``` | ||
- *It is recommended to use this conditional when your condition needs **only** values from | ||
the ```previousAttributes```* | ||
- ```onCondition(previousAttributes: Map<String, Any?>?, stripeObject: Subscription)``` | ||
- *It is recommended to use this conditional when your condition needs a combination of the ```previousAttributes``` | ||
and the received ```stripeObject```* | ||
|
||
Implementing a ```StripeEventReceiver``` looks like the following: | ||
|
||
```kotlin | ||
@Component | ||
open class ExampleReceiver : StripeEventReceiver<Subscription>(Subscription::class.java) { | ||
|
||
override fun onCondition(event: Event): Boolean { | ||
// conditional based stripe event | ||
return event.type == "customer.subscription.updated" | ||
} | ||
|
||
override fun onCondition(stripeObject: Subscription): Boolean { | ||
// conditional based stripe object | ||
return true | ||
} | ||
|
||
override fun onCondition(previousAttributes: Map<String, Any>): Boolean { | ||
// conditional based on previousAttributes | ||
return true | ||
} | ||
|
||
override fun onCondition(previousAttributes: Map<String, Any>, stripeObject: Subscription): Boolean { | ||
// conditional based previousAttributes and stripe object | ||
return true | ||
} | ||
|
||
override fun onReceive(stripeObject: Subscription) { | ||
// do something with the received object | ||
} | ||
} | ||
``` | ||
|
||
> The ```StripeEventReceiver``` generic needs to be subclass of a [StripeObject](https://github.com/stripe/stripe-java/blob/master/src/main/java/com/stripe/model/StripeObject.java) | ||
Oops, something went wrong.