Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: improvements based on reviews #11

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0487253
tests: reuse global test config
lrosenfeldt Aug 7, 2024
7a7a5bc
feature: add integrator field to be send as part of the ServerMetaInfo
lrosenfeldt Aug 7, 2024
4a39a0c
chore: use single expression for initializing and assigning json stri…
lrosenfeldt Aug 7, 2024
a98a1e8
refactor: use constant for http header name 'Content-Type'
lrosenfeldt Aug 7, 2024
fed58c8
chore: fix typo of 'gradle'
lrosenfeldt Aug 7, 2024
4e070b2
chore: add sonarcloud scanner
ehrdi Aug 7, 2024
dd4a1d8
chore: adjust sonar scanner
ehrdi Aug 7, 2024
8fb0599
refactor(NoSuchAlgorithm): Use meaningful AssertionError instead of R…
lrosenfeldt Aug 7, 2024
ae33d6e
refactor(handleError): avoid unneccessary null check for responseBody
lrosenfeldt Aug 7, 2024
e9c77ad
chore: add classpath to sonarcloud in build gradle
ehrdi Aug 7, 2024
3ed231e
chore: update sonar scanner
ehrdi Aug 7, 2024
bc297e6
refactor(illegal-argument-messages): use constants for errors on requ…
lrosenfeldt Aug 7, 2024
274361b
chore: udpate gradle version to 8.9
ehrdi Aug 7, 2024
c7912ce
refactor: hide constructor, remove unneccessary exception declaration
lrosenfeldt Aug 7, 2024
0afb6f3
Merge pull request #12 from PAYONE-GmbH/feature/sonarcloud
ehrdi Aug 7, 2024
07a5943
chore: adjust name of sonar scanner workflow
ehrdi Aug 7, 2024
f7efeb6
Merge branch 'feature/sonarcloud' into develop
ehrdi Aug 7, 2024
edb085b
tests: only declare possible exceptions
lrosenfeldt Aug 7, 2024
406428d
tests: remove visibilty modifier from class, use idiomatic order of a…
lrosenfeldt Aug 7, 2024
c40584d
chore: update sonar scanner workflow
ehrdi Aug 7, 2024
2681352
Merge branch 'feature/sonarcloud' into develop
ehrdi Aug 7, 2024
e1063ff
tests: reuse global test config
lrosenfeldt Aug 7, 2024
134ece1
feature: add integrator field to be send as part of the ServerMetaInfo
lrosenfeldt Aug 7, 2024
61d315d
chore: use single expression for initializing and assigning json stri…
lrosenfeldt Aug 7, 2024
68922e5
refactor: use constant for http header name 'Content-Type'
lrosenfeldt Aug 7, 2024
e01a355
chore: fix typo of 'gradle'
lrosenfeldt Aug 7, 2024
1ef3a02
refactor(NoSuchAlgorithm): Use meaningful AssertionError instead of R…
lrosenfeldt Aug 7, 2024
c242ec2
refactor(handleError): avoid unneccessary null check for responseBody
lrosenfeldt Aug 7, 2024
50339ed
refactor(illegal-argument-messages): use constants for errors on requ…
lrosenfeldt Aug 7, 2024
850accc
refactor: hide constructor, remove unneccessary exception declaration
lrosenfeldt Aug 7, 2024
500af52
tests: only declare possible exceptions
lrosenfeldt Aug 7, 2024
cdf3928
tests: remove visibilty modifier from class, use idiomatic order of a…
lrosenfeldt Aug 7, 2024
72b7daf
Merge branch 'refactor/review-report-results' of github.com:PAYONE-gm…
lrosenfeldt Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/sonar_scanner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Run SonarCloud Scan

on:
workflow_call:
workflow_dispatch:

jobs:
sonar-scan:
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
# Shallow clones should be disabled for a better relevancy of analysis
fetch-depth: 0
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: ${{ runner.os }}-gradle
- name: Cache SonarCloud packages
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Build and analyze
run: ./gradlew build jacocoTestReport sonarqube --info
env:
# Needed to get some information about the pull request, if any
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# SonarCloud access token should be generated from https://sonarcloud.io/account/security/
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:
with:
java-version: ${{ matrix.java }}
distribution: 'adopt'
- name: Setup Gradle 8.8
- name: Setup Gradle 8.9
uses: gradle/actions/setup-gradle@v3
with:
gradle-version: 8.8
gradle-version: 8.9
- name: Test
run: |
./gradlew :lib:test
10 changes: 7 additions & 3 deletions .github/workflows/test_and_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ jobs:
test:
uses: ./.github/workflows/test.yml

build-and-publish:
sonar-scan:
needs: [test]
uses: ./.github/workflows/sonar_scanner.yml

build-and-publish:
needs: [test, sonar-scan]
runs-on: ubuntu-20.04
steps:
- name: Checkout code
Expand All @@ -21,10 +25,10 @@ jobs:
with:
java-version: '17'
distribution: 'adopt'
- name: Setup Gradle 8.8
- name: Setup Gradle 8.9
uses: gradle/actions/setup-gradle@v3
with:
gradle-version: 8.8
gradle-version: 8.9
- name: Build Lib
run: ./gradlew :lib:build
- name: Publish package
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class App {

This repo contains a demo app that showcases how to implement common use cases, like a [Step-by-Step Checkout](https://docs.payone.com/pcp/checkout-flows/step-by-step-checkout) and an [One-Stop-Checkout](https://docs.payone.com/pcp/checkout-flows/one-step-checkout). For each use case the demo app contains a private method in the top level class `App`. You can run the app to execute the code within in the sandbox API. This is a good way to test, if your setup is correct.

If you're using grald can run it within the demo app directory via:
If you're using gradle can run it within the demo app directory via:

```sh
API_KEY=api_key API_SECRET=api_secret MERCHANT_ID=123 COMMERCE_CASE_ID=234 CHECKOUT_ID=345 ./gradlew :app:run
Expand Down
596 changes: 309 additions & 287 deletions app/src/main/java/com/payone/commerce/platform/app/App.java

Large diffs are not rendered by default.

Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
5 changes: 4 additions & 1 deletion gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
Expand Down Expand Up @@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down
2 changes: 2 additions & 0 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
Expand Down
57 changes: 37 additions & 20 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ buildscript {
gradlePluginPortal()
}
dependencies {
if (JavaVersion.current().majorVersion != "8") {
if (JavaVersion.current().majorVersion != '8') {
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.29.0'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:5.1.0.4882'
}
}
}
Expand All @@ -14,14 +15,14 @@ plugins {
id 'java-library'
id 'jacoco'
id 'checkstyle'
id "io.github.kmbisset89.changelog.plugin" version "1.0.4"
id 'io.github.kmbisset89.changelog.plugin' version '1.0.4'
}

if (JavaVersion.current().majorVersion != "8") {
if (JavaVersion.current().majorVersion != '8') {
apply plugin: 'com.vanniktech.maven.publish'
apply plugin: 'org.sonarqube'
}


version = '0.0.2'

repositories {
Expand All @@ -39,7 +40,7 @@ dependencies {
}

jacoco {
toolVersion = "0.8.8" // Specify the version of JaCoCo you want to use
toolVersion = '0.8.8' // Specify the version of JaCoCo you want to use
}

tasks.test {
Expand All @@ -56,42 +57,58 @@ tasks.jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
"com/payone/**/models/*"
'com/payone/**/models/*'
])
}))
}
}

if (JavaVersion.current().majorVersion != "8") {

if (JavaVersion.current().majorVersion != '8') {
mavenPublishing {
publishToMavenCentral("CENTRAL_PORTAL")
publishToMavenCentral('CENTRAL_PORTAL')

signAllPublications()

coordinates("io.github.payone-gmbh", "pcp-serversdk-java", version)
coordinates('io.github.payone-gmbh', 'pcp-serversdk-java', version)

pom {
name = "PCP-SERVERSDK-JAVA"
description = "The PayOne PCP Java SDK."
inceptionYear = "2024"
url = "https://github.com/PAYONE-GmbH/PCP-ServerSDK-java"
name = 'PCP-SERVERSDK-JAVA'
description = 'The PayOne PCP Java SDK.'
inceptionYear = '2024'
url = 'https://github.com/PAYONE-GmbH/PCP-ServerSDK-java'
licenses {
license {
name = "MIT"
name = 'MIT'
}
}
developers {
developer {
id = "username"
name = "PayOne-GmbH"
url = "https://github.com/PAYONE-GmbH"
id = 'username'
name = 'PayOne-GmbH'
url = 'https://github.com/PAYONE-GmbH'
}
}
scm {
url = "https://github.com/PAYONE-GmbH/PCP-ServerSDK-java"
connection = "scm:git:git://github.com/PAYONE-GmbH/PCP-ServerSDK-java.git"
developerConnection = "scm:git:ssh://[email protected]/PAYONE-GmbH/PCP-ServerSDK-java.git"
url = 'https://github.com/PAYONE-GmbH/PCP-ServerSDK-java'
connection = 'scm:git:git://github.com/PAYONE-GmbH/PCP-ServerSDK-java.git'
developerConnection = 'scm:git:ssh://[email protected]/PAYONE-GmbH/PCP-ServerSDK-java.git'
}
}
}

tasks['sonar'].dependsOn 'jacocoTestReport'

sonar {
properties {
property 'sonar.projectKey', 'PAYONE-GmbH_PCP-ServerSDK-java'
property 'sonar.projectName', 'PCP-ServerSDK-java'
property 'sonar.organization', 'payone-gmbh'
property 'sonar.host.url', 'https://sonarcloud.io'
property 'sonar.sources', 'src/main'
property 'sonar.tests', 'src/test'
property 'sonar.coverage.exclusions', '**/models/*'
property 'sonar.exclusions', '**/models/*'
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ public class CommunicatorConfiguration {
private final String apiKey;
private final String apiSecret;
private final String host;
private final String integrator;

public CommunicatorConfiguration(String apiKey, String apiSecret, String host) {
public CommunicatorConfiguration(String apiKey, String apiSecret, String host, String integrator) {
this.apiKey = apiKey;
this.apiSecret = apiSecret;
this.host = host;
this.integrator = integrator;
}

public String getApiKey() {
Expand All @@ -22,4 +24,8 @@ public String getApiSecret() {
public String getHost() {
return host;
}

public String getIntegrator() {
return integrator;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
import okhttp3.Request;

public class RequestHeaderGenerator {

public static final String SERVER_META_INFO_HEADER_NAME = "X-GCS-ServerMetaInfo";
private static final String AUTHORIZATION_HEADER_NAME = "Authorization";
private static final String CONTENT_TYPE_HEADER_NAME = "Content-Type";
private static final String DATE_HEADER_NAME = "Date";
public static final String CLIENT_META_INFO_HEADER_NAME = "X-GCS-ClientMetaInfo";
public static final String SERVER_META_INFO_HEADER_NAME = "X-GCS-ServerMetaInfo";

private static final String ALGORITHM = "HmacSHA256";
private static final String WHITESPACE_REGEX = "\\r?\\n[\\h]*";
private final String DATE_HEADER_NAME = "Date";
private final String AUTHORIZATION_HEADER_NAME = "Authorization";

private final CommunicatorConfiguration config;
private final Mac mac;
Expand All @@ -38,7 +38,7 @@ public RequestHeaderGenerator(CommunicatorConfiguration config) throws InvalidKe
ALGORITHM);
this.mac.init(secretKeySpec);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("HmacSHA256 must be available to use the PCP Java SDK", e);
throw new AssertionError("HmacSHA256 must be available to use the PCP Java SDK", e);
}
}

Expand Down Expand Up @@ -69,8 +69,8 @@ private String getAuthHeader(Request request, Builder headersBuilder) {
StringBuilder stringToSign = new StringBuilder(request.method());
stringToSign.append("\n");
// 2. Content-Type
if (headersBuilder.get("Content-Type") != null) {
stringToSign.append(headersBuilder.get("Content-Type"));
if (headersBuilder.get(CONTENT_TYPE_HEADER_NAME) != null) {
stringToSign.append(headersBuilder.get(CONTENT_TYPE_HEADER_NAME));
}
stringToSign.append("\n");
// 3. Date
Expand All @@ -90,7 +90,7 @@ private String getAuthHeader(Request request, Builder headersBuilder) {
.append("\n");
}
// 5. Canonicalized Resource (has to include query parameters)
stringToSign.append(request.url().encodedPath().toString());
stringToSign.append(request.url().encodedPath());
if (request.url().encodedQuery() != null) {
stringToSign.append("?")
.append(request.url().encodedQuery());
Expand All @@ -106,14 +106,14 @@ private String sign(String target) {
}

private String getServerMetaInfo() {
ServerMetaInfo meta = new ServerMetaInfo();
ServerMetaInfo meta = new ServerMetaInfo(this.config.getIntegrator());
String jsonString;

try {
jsonString = JsonSerializer.serializeToJson(meta);
return Base64.getEncoder().encodeToString(jsonString.getBytes(StandardCharsets.UTF_8));
} catch (JsonProcessingException e) {
throw new RuntimeException(
throw new AssertionError(
"Server Meta Info must be encodable as JSON, this is likely an internal bug of the java PCP SDK",
e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@
import okhttp3.Response;

public class BaseApiClient {
private static final String JSON_PARSE_ERROR = "Excepted valid JSON response, but failed to parse";
protected static final String MERCHANT_ID_REQUIRED_ERROR = "Merchant ID is required";
protected static final String COMMERCE_CASE_ID_REQUIRED_ERROR = "Commerce Case ID is required";
protected static final String CHECKOUT_ID_REQUIRED_ERROR = "Checkout ID is required";
protected static final String PAYLOAD_REQUIRED_ERROR = "Payload is required";
protected static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
protected static final String CONTENT_TYPE_HEADER_NAME = "Content-Type";

private final OkHttpClient client = new OkHttpClient();
private final String JSON_PARSE_ERROR = "Excepted valid JSON response, but failed to parse";
protected final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

private final RequestHeaderGenerator requestHeaderGenerator;
private final CommunicatorConfiguration config;
Expand Down Expand Up @@ -86,7 +92,7 @@ private void handleError(Response response)
}

String responseBody = response.body().string();
if (responseBody == null || responseBody.isEmpty()) {
if (responseBody.isEmpty()) {
throw new ApiResponseRetrievalException(response.code(), responseBody);
}
try {
Expand Down
Loading