Skip to content

Commit 60a53d1

Browse files
authored
Develop (#52)
Merge develop to Main
1 parent b94f35d commit 60a53d1

33 files changed

Lines changed: 833 additions & 67 deletions

.github/workflows/maven-action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
restore-keys: ${{ runner.os }}-maven-
2929

3030
- name: Step 3 - Setup JDK 17
31-
uses: actions/setup-java@v3
31+
uses: actions/setup-java@v4
3232
with:
3333
distribution: 'temurin'
3434
java-version: 17

.github/workflows/release.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
restore-keys: ${{ runner.os }}-maven-
2424

2525
- name: Setup JDK 17
26-
uses: actions/setup-java@v3
26+
uses: actions/setup-java@v4
2727
with:
2828
distribution: 'temurin'
2929
java-version: 17
@@ -47,5 +47,10 @@ jobs:
4747

4848
- name: Publish Client Package
4949
run: mvn versions:set -DnewVersion=${{ github.event.client_payload.version }} versions:commit -pl paystack-clients && mvn -B deploy -pl paystack-clients
50+
env:
51+
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
52+
53+
- name: Publish Client SpringBoot Starter Package
54+
run: mvn versions:set -DnewVersion=${{ github.event.client_payload.version }} versions:commit -pl paystack-clients-spring-boot-starter && mvn -B deploy -pl paystack-clients-spring-boot-starter
5055
env:
5156
GITHUB_TOKEN: ${{ secrets.GH_PAT }}

README.md

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,8 @@ The Client comes in 3 flavors:
1111
3. Reactive - Responses in Mono and Flux
1212

1313
## Setup
14-
1. Add the dependency to your project
15-
```xml
16-
<dependency>
17-
<groupId>com.chrisworks.paystackclient</groupId>
18-
<artifactId>paystack-clients</artifactId>
19-
<version>${VERSION}</version>
20-
</dependency>
21-
```
22-
2. Add GitHub Maven Package Repository to your POM
14+
15+
1. Add GitHub Maven Package Repository to your POM
2316
```xml
2417
<repositories>
2518
<repository>
@@ -29,8 +22,66 @@ The Client comes in 3 flavors:
2922
</repositories>
3023
```
3124

32-
## usage
25+
### 1. When Using SpringBoot
26+
- Add the dependency to your spring boot project:
27+
```xml
28+
<dependency>
29+
<groupId>com.chrisworks.paystackclient</groupId>
30+
<artifactId>paystack-clients-spring-boot-starter</artifactId>
31+
<version>${VERSION}</version>
32+
</dependency>
33+
```
34+
35+
- Add the following property to you `applications.properties` file
36+
```properties
37+
paystack-client.secret-key=INPUT_YOUR_PAYSTACK_SECRET_KEY_HERE
38+
paystack-client.definition-type=(REACTIVE|NON_REACTIVE) #This property is optional, it defaults to 'NON_REACTIVE' if not specified
39+
```
40+
41+
- Usage
42+
```java
43+
// Imports here
44+
45+
import com.chrisworks.paystackclient.definitions.simple.PlanClient; //When using the non-reactive type
46+
import com.chrisworks.paystackclient.definitions.reactive.PlanClient; //When using the reactive type
47+
48+
@Service
49+
class Example {
50+
51+
private final PlanClient planClient;
52+
53+
public Example(PlanClient planClient) {
54+
this.planClient = planClient;
55+
}
56+
57+
public void yourMethodThatDoesAndReturnsSomething() {
58+
59+
//A.
60+
PlanResponse.Single nonReactiveRes = planClient
61+
.createPlan(new CreatePlanRequest("Sample Plan 9", Interval.DAILY,
62+
Amount.actualValue(BigDecimal.valueOf(10_000)).ofCurrency(Currency.NGN)));
63+
64+
//Or B.
65+
Mono<PlanResponse.Single> reactiveRes = planClient
66+
.createPlan(new CreatePlanRequest("Sample Plan 9", Interval.DAILY,
67+
Amount.actualValue(BigDecimal.valueOf(10_000)).ofCurrency(Currency.NGN)));
68+
}
69+
}
70+
```
71+
NB: During injection of the client, you can only inject either the REACTIVE type or the NON_REACTIVE type and never both.
72+
The implementation here is powered by the popular Spring WebClient which is part of the Spring Framework Project Reactor.
73+
74+
### 2. Java/Maven Project without SpringBoot
75+
- Add the dependency to your project
76+
```xml
77+
<dependency>
78+
<groupId>com.chrisworks.paystackclient</groupId>
79+
<artifactId>paystack-clients</artifactId>
80+
<version>${VERSION}</version>
81+
</dependency>
82+
```
3383

84+
- usage
3485
```java
3586
// Imports here
3687

@@ -82,4 +133,5 @@ class Example {
82133
.executeAsync();
83134
}
84135
}
85-
```
136+
```
137+
NB: The implementation here is powered by the popular OkHttp library.

paystack-clients-spring-boot-starter/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
<artifactId>paystack-domain</artifactId>
2828
<version>${project.version}</version>
2929
</dependency>
30+
<dependency>
31+
<groupId>org.springframework.boot</groupId>
32+
<artifactId>spring-boot-configuration-processor</artifactId>
33+
<version>3.1.4</version>
34+
<optional>true</optional>
35+
</dependency>
3036
</dependencies>
3137

3238
<repositories>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.chrisworks.paystackclient;
2+
3+
import com.chrisworks.paystackclient.definitions.DefinitionType;
4+
import org.springframework.boot.context.properties.ConfigurationProperties;
5+
6+
@ConfigurationProperties("paystack-client")
7+
public class PaystackClientsProperties {
8+
9+
private String secretKey;
10+
private DefinitionType definitionType = DefinitionType.NON_REACTIVE;
11+
12+
public String getSecretKey() {
13+
return secretKey;
14+
}
15+
16+
public void setSecretKey(String secretKey) {
17+
this.secretKey = secretKey;
18+
}
19+
20+
public DefinitionType getDefinitionType() {
21+
return definitionType;
22+
}
23+
24+
public void setDefinitionType(DefinitionType definitionType) {
25+
this.definitionType = definitionType;
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.chrisworks.paystackclient;
2+
3+
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.core.env.PropertiesPropertySource;
6+
import org.springframework.core.env.PropertySource;
7+
import org.springframework.core.io.support.EncodedResource;
8+
import org.springframework.core.io.support.PropertySourceFactory;
9+
import org.springframework.lang.NonNull;
10+
11+
import java.util.Objects;
12+
import java.util.Properties;
13+
14+
@Configuration
15+
public class YamlPropertySourceFactory implements PropertySourceFactory {
16+
@NonNull
17+
@Override
18+
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) {
19+
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
20+
factory.setResources(encodedResource.getResource());
21+
22+
Properties properties = factory.getObject();
23+
24+
assert properties != null;
25+
return new PropertiesPropertySource(Objects.requireNonNull(encodedResource.getResource().getFilename()), properties);
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.chrisworks.paystackclient.autoconfigure;
2+
3+
import com.chrisworks.paystackclient.PaystackClientsProperties;
4+
import com.chrisworks.paystackclient.YamlPropertySourceFactory;
5+
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
6+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
7+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
8+
import org.springframework.context.annotation.Configuration;
9+
import org.springframework.context.annotation.PropertySource;
10+
11+
@Configuration
12+
@EnableConfigurationProperties(PaystackClientsProperties.class)
13+
@ConditionalOnProperty(prefix = "paystack-client", name = "secret-key")
14+
@PropertySource(value = "classpath:application-paystack-clients-config.yml", factory = YamlPropertySourceFactory.class)
15+
public class PaystackClientsAutoConfiguration {
16+
17+
/**
18+
* Non Reactive Client configuration
19+
*/
20+
@Configuration
21+
@ConditionalOnProperty(prefix = "paystack-client", name = "definition-type", havingValue = "NON_REACTIVE", matchIfMissing = true)
22+
@AutoConfigurationPackage(basePackages = "com.chrisworks.paystackclient.definitions.simple")
23+
public static class NonReactiveClientConfiguration {}
24+
25+
/**
26+
* Reactive Client configuration
27+
*/
28+
@Configuration
29+
@ConditionalOnProperty(prefix = "paystack-client", name = "definition-type", havingValue = "REACTIVE")
30+
@AutoConfigurationPackage(basePackages = "com.chrisworks.paystackclient.definitions.reactive")
31+
public static class ReactiveClientConfiguration {}
32+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.chrisworks.paystackclient.definitions;
2+
3+
public final class Constants {
4+
5+
private Constants() {}
6+
7+
public static final String PLAN_CLIENT = "plan-client";
8+
public static final String APPLE_PAY_CLIENT = "apple-pay-client";
9+
public static final String TRANSACTION_CLIENT = "transaction-client";
10+
public static final String PRODUCT_CLIENT = "product-client";
11+
public static final String SUB_ACCOUNT_CLIENT = "sub-account-client";
12+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.chrisworks.paystackclient.definitions;
2+
3+
public enum DefinitionType {
4+
REACTIVE,
5+
NON_REACTIVE
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.chrisworks.paystackclient.definitions.reactive;
2+
3+
import com.chrisworks.paystackclient.domain.applepay.ApplePayRequest;
4+
import com.chrisworks.paystackclient.domain.applepay.ApplePayResponse;
5+
import com.chrisworks.paystackclient.domain.request.QueryParamConstants;
6+
import com.chrisworks.paystackclient.domain.response.EmptyDataResponse;
7+
import com.chrisworks.paystackclient.definitions.Constants;
8+
import com.maciejwalkowiak.spring.http.annotation.HttpClient;
9+
import org.springframework.web.bind.annotation.RequestBody;
10+
import org.springframework.web.bind.annotation.RequestParam;
11+
import org.springframework.web.service.annotation.DeleteExchange;
12+
import org.springframework.web.service.annotation.GetExchange;
13+
import org.springframework.web.service.annotation.PostExchange;
14+
import reactor.core.publisher.Mono;
15+
16+
@HttpClient(Constants.APPLE_PAY_CLIENT)
17+
public interface ApplePayClient {
18+
19+
@PostExchange
20+
Mono<EmptyDataResponse> register(@RequestBody ApplePayRequest request);
21+
22+
@DeleteExchange
23+
Mono<EmptyDataResponse> unregister(@RequestBody ApplePayRequest request);
24+
25+
@GetExchange
26+
Mono<ApplePayResponse.Multiple> list(
27+
@RequestParam(name = QueryParamConstants.NEXT, required = false) String next,
28+
@RequestParam(name = QueryParamConstants.PREVIOUS, required = false) String previous,
29+
@RequestParam(name = QueryParamConstants.USE_CURSOR, required = false) Boolean useCursor
30+
);
31+
}

0 commit comments

Comments
 (0)