From fa424b889bdf8294cd2615d79dfb0d7d3bff09f6 Mon Sep 17 00:00:00 2001
From: Oleksandr Mandryk <2678920+omandryk@users.noreply.github.com>
Date: Tue, 11 Aug 2026 10:46:04 -0400
Subject: [PATCH 1/4] Revive 1.5 maintenance baseline
---
.github/dependabot.yml | 12 +++
.github/workflows/ci.yml | 24 ++++++
.travis.yml | 9 ---
CHANGELOG.md | 15 ++++
CONTRIBUTING.md | 13 +++
README.md | 81 +++++++++++--------
SECURITY.md | 5 ++
pom.xml | 58 ++++---------
.../woocommerce/oauth/OAuthConfig.java | 2 +-
.../woocommerce/oauth/OAuthSignature.java | 18 +++--
.../integration/WooCommerceClientTest.java | 6 +-
.../woocommerce/oauth/OAuthConfigTest.java | 26 ++++++
.../woocommerce/oauth/OAuthSignatureTest.java | 62 ++++++++++++++
13 files changed, 234 insertions(+), 97 deletions(-)
create mode 100644 .github/dependabot.yml
create mode 100644 .github/workflows/ci.yml
delete mode 100644 .travis.yml
create mode 100644 CHANGELOG.md
create mode 100644 CONTRIBUTING.md
create mode 100644 SECURITY.md
create mode 100644 src/test/java/com/icoderman/woocommerce/oauth/OAuthConfigTest.java
create mode 100644 src/test/java/com/icoderman/woocommerce/oauth/OAuthSignatureTest.java
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..542edcf
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+version: 2
+updates:
+ - package-ecosystem: maven
+ directory: /
+ schedule:
+ interval: monthly
+ open-pull-requests-limit: 5
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: monthly
+ open-pull-requests-limit: 5
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..601b227
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,24 @@
+name: CI
+
+on:
+ push:
+ branches: [master]
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ java: ['8', '11', '17', '21']
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: ${{ matrix.java }}
+ cache: maven
+ - run: mvn --batch-mode --no-transfer-progress verify -Dgpg.skip=true
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 2022698..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-language: java
-jdk: oraclejdk8
-dist: trusty
-
-install: mvn install -Dgpg.skip
-
-cache:
- directories:
- - $HOME/.m2
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..da2adb1
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,15 @@
+# Changelog
+
+## Unreleased
+
+- Restored continuous integration across supported Java versions.
+- Removed embedded WooCommerce credentials from integration tests.
+- Updated maintained dependencies and build plugins.
+- Added unit coverage for OAuth configuration and signing behavior.
+- Corrected OAuth query and ISO-8601 date encoding, informed by community pull requests #37 and #49.
+- Accepted store URLs with a trailing slash, based on community pull request #32.
+- Updated project ownership, security, and contribution documentation.
+
+## 1.4 - 2019-11-05
+
+- Latest historical Maven Central release before the project revival.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..04fa502
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,13 @@
+# Contributing
+
+Issues and focused pull requests are welcome. Before proposing a substantial API change, open an issue so the design and compatibility impact can be discussed.
+
+## Development
+
+Requirements: JDK 8 or newer and Maven 3.8 or newer.
+
+```bash
+mvn verify -Dgpg.skip=true
+```
+
+Integration tests require a disposable WooCommerce store and credentials supplied through `WC_URL`, `WC_CONSUMER_KEY`, and `WC_CONSUMER_SECRET`. Never commit real credentials.
diff --git a/README.md b/README.md
index db19f97..8e9f3ea 100644
--- a/README.md
+++ b/README.md
@@ -1,45 +1,56 @@
# WooCommerce API Java Wrapper
-[](https://travis-ci.org/icoderman/wc-api-java)
-Java wrapper for WooCommerce REST API. The library supports the latest versions of WooCommerce REST API only
-with the OAuth 1.0a authentication over the HTTP protocol.
+[](https://github.com/omandryk/wc-api-java/actions/workflows/ci.yml)
+[](https://central.sonatype.com/artifact/com.icoderman/wc-api-java)
+[](LICENSE)
+
+A small Java wrapper for the WooCommerce REST API, originally released in 2016 and distributed through Maven Central.
+
+> **Project revival:** version 1.4 is the latest published release. The 1.5 line restores maintenance, testing, and modern release infrastructure while preserving the existing API. Do not use unreleased snapshots in production.
+
+## Installation
-## Setup
-wc-api-java is available on maven central:
```xml
-
- com.icoderman
- wc-api-java
- 1.4
-
+
+ com.icoderman
+ wc-api-java
+ 1.4
+
```
## Usage
```java
- public static void main(String[] args) {
- // Setup client
- OAuthConfig config = new OAuthConfig("http://woocommerce.com", "consumerKey", "consumerSecret");
- WooCommerce wooCommerce = new WooCommerceAPI(config, ApiVersionType.V3);
-
- // Prepare object for request
- Map productInfo = new HashMap<>();
- productInfo.put("name", "Premium Quality");
- productInfo.put("type", "simple");
- productInfo.put("regular_price", "21.99");
- productInfo.put("description", "Pellentesque habitant morbi tristique senectus et netus");
-
- // Make request and retrieve result
- Map product = wooCommerce.create(EndpointBaseType.PRODUCTS.getValue(), productInfo);
-
- System.out.println(product.get("id"));
-
- // Get all with request parameters
- Map params = new HashMap<>();
- params.put("per_page","100");
- params.put("offset","0");
- List products = wooCommerce.getAll(EndpointBaseType.PRODUCTS.getValue(), params);
-
- System.out.println(products.size());
- }
+OAuthConfig config = new OAuthConfig(
+ "https://store.example.com",
+ System.getenv("WC_CONSUMER_KEY"),
+ System.getenv("WC_CONSUMER_SECRET")
+);
+WooCommerce wooCommerce = new WooCommerceAPI(config, ApiVersionType.V3);
+
+Map params = new HashMap<>();
+params.put("per_page", "100");
+List products = wooCommerce.getAll(EndpointBaseType.PRODUCTS.getValue(), params);
```
+
+Never commit WooCommerce credentials. Supply them through a secret manager or environment variables.
+
+## Compatibility
+
+- Java 8 or newer
+- WooCommerce REST API v2/v3 endpoints
+- OAuth 1.0a request signing used by the historical 1.x API
+
+The compatibility matrix will be expanded as part of the 1.5 revival. HTTPS-first authentication and a modernized API are being evaluated separately for a future major release.
+
+## Development
+
+```bash
+mvn verify -Dgpg.skip=true
+```
+
+See [CONTRIBUTING.md](CONTRIBUTING.md) and [SECURITY.md](SECURITY.md) before opening an issue or pull request.
+
+## License
+
+MIT © Oleksandr Mandryk
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..f14d595
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,5 @@
+# Security policy
+
+The latest release is the only supported version. Please report suspected vulnerabilities privately through GitHub Security Advisories instead of opening a public issue.
+
+Never include WooCommerce consumer keys, consumer secrets, access tokens, or customer data in a report. Use redacted requests and a minimal reproduction whenever possible.
diff --git a/pom.xml b/pom.xml
index 9444510..b3e15f5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
WooCommerce API Java Wrapper
Java wrapper for WooCommerce REST API
- https://github.com/icoderman/wc-api-java
+ https://github.com/omandryk/wc-api-java
@@ -23,32 +23,24 @@
icoderman
Oleksandr Mandryk
icoderman@gmail.com
- https://github.com/icoderman
+ https://github.com/omandryk
- scm:git:git@github.com:icoderman/wc-api-java.git
- scm:git:git@github.com:icoderman/wc-api-java.git
- git@github.com/icoderman/wc-api-java.git
+ scm:git:https://github.com/omandryk/wc-api-java.git
+ scm:git:ssh://git@github.com/omandryk/wc-api-java.git
+ https://github.com/omandryk/wc-api-java
HEAD
-
-
- ossrh
- https://oss.sonatype.org/content/repositories/snapshots
-
-
- ossrh
- https://oss.sonatype.org/service/local/staging/deploy/maven2/
-
-
-
- 2.10.0
- 4.5.10
- 4.12
+ UTF-8
+ 8
+ 8
+ 2.18.6
+ 4.5.14
+ 4.13.2
@@ -84,17 +76,13 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.0
-
- 1.8
- 1.8
-
+ 3.14.1
org.apache.maven.plugins
maven-source-plugin
- 3.0.1
+ 3.3.1
attach-sources
@@ -108,7 +96,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.0.1
+ 3.11.3
attach-javadocs
@@ -122,7 +110,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.6
+ 3.2.8
true
@@ -140,22 +128,10 @@
org.apache.maven.plugins
maven-release-plugin
- 2.5.3
-
-
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.8
- true
-
- ossrh
- https://oss.sonatype.org/
- true
-
+ 3.1.1
-
\ No newline at end of file
+
diff --git a/src/main/java/com/icoderman/woocommerce/oauth/OAuthConfig.java b/src/main/java/com/icoderman/woocommerce/oauth/OAuthConfig.java
index 5d9dd77..198f573 100644
--- a/src/main/java/com/icoderman/woocommerce/oauth/OAuthConfig.java
+++ b/src/main/java/com/icoderman/woocommerce/oauth/OAuthConfig.java
@@ -12,7 +12,7 @@ public OAuthConfig(String url, String consumerKey, String consumerSecret) {
consumerSecret == null || consumerSecret.isEmpty()) {
throw new IllegalArgumentException("All arguments are required");
}
- this.url = url;
+ this.url = url.endsWith("/") ? url.substring(0, url.length() - 1) : url;
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
}
diff --git a/src/main/java/com/icoderman/woocommerce/oauth/OAuthSignature.java b/src/main/java/com/icoderman/woocommerce/oauth/OAuthSignature.java
index 1cb5997..ecfd5d8 100644
--- a/src/main/java/com/icoderman/woocommerce/oauth/OAuthSignature.java
+++ b/src/main/java/com/icoderman/woocommerce/oauth/OAuthSignature.java
@@ -58,10 +58,9 @@ public static String getAsQueryString(OAuthConfig config, String endpoint, HttpM
return "";
}
Map oauthParameters = getAsMap(config, endpoint, httpMethod, params);
- String encodedSignature = oauthParameters.get(OAuthHeader.OAUTH_SIGNATURE.getValue())
- .replace(SpecialSymbol.PLUS.getPlain(), SpecialSymbol.PLUS.getEncoded());
- oauthParameters.put(OAuthHeader.OAUTH_SIGNATURE.getValue(), encodedSignature);
- return mapToString(oauthParameters, SpecialSymbol.EQUAL.getPlain(), SpecialSymbol.AMP.getPlain());
+ Map encodedParameters = percentEncodeParameters(oauthParameters);
+ return mapToString(getSortedParameters(encodedParameters),
+ SpecialSymbol.EQUAL.getPlain(), SpecialSymbol.AMP.getPlain());
}
public static String getAsQueryString(OAuthConfig config, String endpoint, HttpMethod httpMethod) {
@@ -95,15 +94,18 @@ private static String urlEncode(String s) {
}
}
- private static String getSignatureBaseString(String url, String method, Map parameters) {
+ static String getSignatureBaseString(String url, String method, Map parameters) {
String requestURL = urlEncode(url);
// 1. Percent encode every key and value that will be signed.
Map encodedParameters = percentEncodeParameters(parameters);
// 2. Sort the list of parameters alphabetically by encoded key.
encodedParameters = getSortedParameters(encodedParameters);
- String paramsString = mapToString(encodedParameters, SpecialSymbol.EQUAL.getEncoded(), SpecialSymbol.AMP.getEncoded());
- return String.format(BASE_SIGNATURE_FORMAT, method, requestURL, paramsString);
+ String normalizedParameters = mapToString(encodedParameters,
+ SpecialSymbol.EQUAL.getPlain(), SpecialSymbol.AMP.getPlain());
+
+ // 3. Percent encode the complete normalized parameter string for the signature base string.
+ return String.format(BASE_SIGNATURE_FORMAT, method, requestURL, percentEncode(normalizedParameters));
}
private static String mapToString(Map paramsMap, String keyValueDelimiter, String paramsDelimiter) {
@@ -128,7 +130,7 @@ private static String percentEncode(String s) {
try {
return URLEncoder.encode(s, UTF_8)
// OAuth encodes some characters differently:
- .replace(SpecialSymbol.PLUS.getPlain(), SpecialSymbol.PLUS.getEncoded())
+ .replace(SpecialSymbol.PLUS.getPlain(), "%20")
.replace(SpecialSymbol.STAR.getPlain(), SpecialSymbol.STAR.getEncoded())
.replace(SpecialSymbol.TILDE.getEncoded(), SpecialSymbol.TILDE.getPlain());
} catch (UnsupportedEncodingException e) {
diff --git a/src/test/java/com/icoderman/woocommerce/integration/WooCommerceClientTest.java b/src/test/java/com/icoderman/woocommerce/integration/WooCommerceClientTest.java
index be37195..5b450ad 100644
--- a/src/test/java/com/icoderman/woocommerce/integration/WooCommerceClientTest.java
+++ b/src/test/java/com/icoderman/woocommerce/integration/WooCommerceClientTest.java
@@ -18,9 +18,9 @@
public class WooCommerceClientTest {
- private static final String CONSUMER_KEY = "ck_d35e7be7cc695d87f23490729dd80e173f88c8f5";
- private static final String CONSUMER_SECRET = "cs_53a835760712ebf0c8bcf2a21197af4b2323a052";
- private static final String WC_URL = "http://localhost/index.php";
+ private static final String CONSUMER_KEY = System.getenv("WC_CONSUMER_KEY");
+ private static final String CONSUMER_SECRET = System.getenv("WC_CONSUMER_SECRET");
+ private static final String WC_URL = System.getenv("WC_URL");
private WooCommerce wooCommerce;
diff --git a/src/test/java/com/icoderman/woocommerce/oauth/OAuthConfigTest.java b/src/test/java/com/icoderman/woocommerce/oauth/OAuthConfigTest.java
new file mode 100644
index 0000000..f0bf27a
--- /dev/null
+++ b/src/test/java/com/icoderman/woocommerce/oauth/OAuthConfigTest.java
@@ -0,0 +1,26 @@
+package com.icoderman.woocommerce.oauth;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class OAuthConfigTest {
+ @Test(expected = IllegalArgumentException.class)
+ public void rejectsMissingConsumerSecret() {
+ new OAuthConfig("https://example.com", "consumer-key", "");
+ }
+
+ @Test
+ public void retainsConfigurationValues() {
+ OAuthConfig config = new OAuthConfig("https://example.com", "consumer-key", "consumer-secret");
+ assertEquals("https://example.com", config.getUrl());
+ assertEquals("consumer-key", config.getConsumerKey());
+ assertEquals("consumer-secret", config.getConsumerSecret());
+ }
+
+ @Test
+ public void removesTrailingSlashFromStoreUrl() {
+ OAuthConfig config = new OAuthConfig("https://example.com/", "consumer-key", "consumer-secret");
+ assertEquals("https://example.com", config.getUrl());
+ }
+}
diff --git a/src/test/java/com/icoderman/woocommerce/oauth/OAuthSignatureTest.java b/src/test/java/com/icoderman/woocommerce/oauth/OAuthSignatureTest.java
new file mode 100644
index 0000000..417b5f5
--- /dev/null
+++ b/src/test/java/com/icoderman/woocommerce/oauth/OAuthSignatureTest.java
@@ -0,0 +1,62 @@
+package com.icoderman.woocommerce.oauth;
+
+import com.icoderman.woocommerce.HttpMethod;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class OAuthSignatureTest {
+ private final OAuthConfig config = new OAuthConfig("https://example.com", "consumer key", "consumer-secret");
+
+ @Test
+ public void returnsEmptyValuesForIncompleteInput() {
+ assertTrue(OAuthSignature.getAsMap(null, "https://example.com", HttpMethod.GET).isEmpty());
+ assertEquals("", OAuthSignature.getAsQueryString(config, null, HttpMethod.GET));
+ }
+
+ @Test
+ public void includesRequiredOAuthParameters() {
+ Map values = OAuthSignature.getAsMap(
+ config, "https://example.com/wp-json/wc/v3/products", HttpMethod.GET);
+ assertEquals("consumer key", values.get("oauth_consumer_key"));
+ assertEquals("HMAC-SHA256", values.get("oauth_signature_method"));
+ assertTrue(values.containsKey("oauth_nonce"));
+ assertTrue(values.containsKey("oauth_timestamp"));
+ assertTrue(values.containsKey("oauth_signature"));
+ }
+
+ @Test
+ public void percentEncodesQueryValues() {
+ Map params = new HashMap<>();
+ params.put("search", "coffee & tea");
+ String query = OAuthSignature.getAsQueryString(
+ config, "https://example.com/wp-json/wc/v3/products", HttpMethod.GET, params);
+ assertTrue(query.contains("search=coffee%20%26%20tea"));
+ assertFalse(query.contains("coffee+%26+tea"));
+ }
+
+ @Test
+ public void deleteAddsWooCommerceForceParameter() {
+ Map values = OAuthSignature.getAsMap(
+ config, "https://example.com/wp-json/wc/v3/products/1", HttpMethod.DELETE,
+ Collections.emptyMap());
+ assertEquals("true", values.get("force"));
+ }
+
+ @Test
+ public void doubleEncodesIsoDateInsideSignatureBaseString() {
+ Map params = new HashMap<>();
+ params.put("after", "2023-02-21T13:00:23");
+
+ String baseString = OAuthSignature.getSignatureBaseString(
+ "https://example.com/wp-json/wc/v3/orders", "GET", params);
+
+ assertTrue(baseString.contains("after%3D2023-02-21T13%253A00%253A23"));
+ }
+}
From b5fd21ebb1ef45dc5f7f52416878ef11834362b0 Mon Sep 17 00:00:00 2001
From: Oleksandr Mandryk <2678920+omandryk@users.noreply.github.com>
Date: Tue, 11 Aug 2026 10:56:00 -0400
Subject: [PATCH 2/4] Use branded project contact email
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index b3e15f5..0ba8999 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
icoderman
Oleksandr Mandryk
- icoderman@gmail.com
+ hello@omandryk.com
https://github.com/omandryk
From 77c263c853cda24ef5ecfa99f20cd1e54c3d2c09 Mon Sep 17 00:00:00 2001
From: Oleksandr Mandryk <2678920+omandryk@users.noreply.github.com>
Date: Tue, 11 Aug 2026 11:04:23 -0400
Subject: [PATCH 3/4] Keep revival changes outside core behavior
---
CHANGELOG.md | 3 -
CONTRIBUTING.md | 2 +-
README.md | 6 +-
.../woocommerce/oauth/OAuthConfig.java | 2 +-
.../woocommerce/oauth/OAuthSignature.java | 18 +++---
.../woocommerce/oauth/OAuthConfigTest.java | 26 --------
.../woocommerce/oauth/OAuthSignatureTest.java | 62 -------------------
7 files changed, 13 insertions(+), 106 deletions(-)
delete mode 100644 src/test/java/com/icoderman/woocommerce/oauth/OAuthConfigTest.java
delete mode 100644 src/test/java/com/icoderman/woocommerce/oauth/OAuthSignatureTest.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index da2adb1..01c0b72 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,9 +5,6 @@
- Restored continuous integration across supported Java versions.
- Removed embedded WooCommerce credentials from integration tests.
- Updated maintained dependencies and build plugins.
-- Added unit coverage for OAuth configuration and signing behavior.
-- Corrected OAuth query and ISO-8601 date encoding, informed by community pull requests #37 and #49.
-- Accepted store URLs with a trailing slash, based on community pull request #32.
- Updated project ownership, security, and contribution documentation.
## 1.4 - 2019-11-05
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 04fa502..f459180 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -10,4 +10,4 @@ Requirements: JDK 8 or newer and Maven 3.8 or newer.
mvn verify -Dgpg.skip=true
```
-Integration tests require a disposable WooCommerce store and credentials supplied through `WC_URL`, `WC_CONSUMER_KEY`, and `WC_CONSUMER_SECRET`. Never commit real credentials.
+The legacy live-store integration tests are currently disabled with JUnit's `@Ignore`. For manual testing, use a disposable WooCommerce store and supply `WC_URL`, `WC_CONSUMER_KEY`, and `WC_CONSUMER_SECRET` through environment variables. Never commit real credentials.
diff --git a/README.md b/README.md
index 8e9f3ea..2bb05b9 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ A small Java wrapper for the WooCommerce REST API, originally released in 2016 a
```java
OAuthConfig config = new OAuthConfig(
- "https://store.example.com",
+ "http://localhost",
System.getenv("WC_CONSUMER_KEY"),
System.getenv("WC_CONSUMER_SECRET")
);
@@ -39,9 +39,9 @@ Never commit WooCommerce credentials. Supply them through a secret manager or en
- Java 8 or newer
- WooCommerce REST API v2/v3 endpoints
-- OAuth 1.0a request signing used by the historical 1.x API
+- Legacy OAuth 1.0a request signing over HTTP
-The compatibility matrix will be expanded as part of the 1.5 revival. HTTPS-first authentication and a modernized API are being evaluated separately for a future major release.
+The 1.x client does not implement WooCommerce HTTPS Basic Authentication. Use it only in a controlled environment until HTTPS-first authentication is available in a future major release.
## Development
diff --git a/src/main/java/com/icoderman/woocommerce/oauth/OAuthConfig.java b/src/main/java/com/icoderman/woocommerce/oauth/OAuthConfig.java
index 198f573..5d9dd77 100644
--- a/src/main/java/com/icoderman/woocommerce/oauth/OAuthConfig.java
+++ b/src/main/java/com/icoderman/woocommerce/oauth/OAuthConfig.java
@@ -12,7 +12,7 @@ public OAuthConfig(String url, String consumerKey, String consumerSecret) {
consumerSecret == null || consumerSecret.isEmpty()) {
throw new IllegalArgumentException("All arguments are required");
}
- this.url = url.endsWith("/") ? url.substring(0, url.length() - 1) : url;
+ this.url = url;
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
}
diff --git a/src/main/java/com/icoderman/woocommerce/oauth/OAuthSignature.java b/src/main/java/com/icoderman/woocommerce/oauth/OAuthSignature.java
index ecfd5d8..1cb5997 100644
--- a/src/main/java/com/icoderman/woocommerce/oauth/OAuthSignature.java
+++ b/src/main/java/com/icoderman/woocommerce/oauth/OAuthSignature.java
@@ -58,9 +58,10 @@ public static String getAsQueryString(OAuthConfig config, String endpoint, HttpM
return "";
}
Map oauthParameters = getAsMap(config, endpoint, httpMethod, params);
- Map encodedParameters = percentEncodeParameters(oauthParameters);
- return mapToString(getSortedParameters(encodedParameters),
- SpecialSymbol.EQUAL.getPlain(), SpecialSymbol.AMP.getPlain());
+ String encodedSignature = oauthParameters.get(OAuthHeader.OAUTH_SIGNATURE.getValue())
+ .replace(SpecialSymbol.PLUS.getPlain(), SpecialSymbol.PLUS.getEncoded());
+ oauthParameters.put(OAuthHeader.OAUTH_SIGNATURE.getValue(), encodedSignature);
+ return mapToString(oauthParameters, SpecialSymbol.EQUAL.getPlain(), SpecialSymbol.AMP.getPlain());
}
public static String getAsQueryString(OAuthConfig config, String endpoint, HttpMethod httpMethod) {
@@ -94,18 +95,15 @@ private static String urlEncode(String s) {
}
}
- static String getSignatureBaseString(String url, String method, Map parameters) {
+ private static String getSignatureBaseString(String url, String method, Map parameters) {
String requestURL = urlEncode(url);
// 1. Percent encode every key and value that will be signed.
Map encodedParameters = percentEncodeParameters(parameters);
// 2. Sort the list of parameters alphabetically by encoded key.
encodedParameters = getSortedParameters(encodedParameters);
- String normalizedParameters = mapToString(encodedParameters,
- SpecialSymbol.EQUAL.getPlain(), SpecialSymbol.AMP.getPlain());
-
- // 3. Percent encode the complete normalized parameter string for the signature base string.
- return String.format(BASE_SIGNATURE_FORMAT, method, requestURL, percentEncode(normalizedParameters));
+ String paramsString = mapToString(encodedParameters, SpecialSymbol.EQUAL.getEncoded(), SpecialSymbol.AMP.getEncoded());
+ return String.format(BASE_SIGNATURE_FORMAT, method, requestURL, paramsString);
}
private static String mapToString(Map paramsMap, String keyValueDelimiter, String paramsDelimiter) {
@@ -130,7 +128,7 @@ private static String percentEncode(String s) {
try {
return URLEncoder.encode(s, UTF_8)
// OAuth encodes some characters differently:
- .replace(SpecialSymbol.PLUS.getPlain(), "%20")
+ .replace(SpecialSymbol.PLUS.getPlain(), SpecialSymbol.PLUS.getEncoded())
.replace(SpecialSymbol.STAR.getPlain(), SpecialSymbol.STAR.getEncoded())
.replace(SpecialSymbol.TILDE.getEncoded(), SpecialSymbol.TILDE.getPlain());
} catch (UnsupportedEncodingException e) {
diff --git a/src/test/java/com/icoderman/woocommerce/oauth/OAuthConfigTest.java b/src/test/java/com/icoderman/woocommerce/oauth/OAuthConfigTest.java
deleted file mode 100644
index f0bf27a..0000000
--- a/src/test/java/com/icoderman/woocommerce/oauth/OAuthConfigTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.icoderman.woocommerce.oauth;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class OAuthConfigTest {
- @Test(expected = IllegalArgumentException.class)
- public void rejectsMissingConsumerSecret() {
- new OAuthConfig("https://example.com", "consumer-key", "");
- }
-
- @Test
- public void retainsConfigurationValues() {
- OAuthConfig config = new OAuthConfig("https://example.com", "consumer-key", "consumer-secret");
- assertEquals("https://example.com", config.getUrl());
- assertEquals("consumer-key", config.getConsumerKey());
- assertEquals("consumer-secret", config.getConsumerSecret());
- }
-
- @Test
- public void removesTrailingSlashFromStoreUrl() {
- OAuthConfig config = new OAuthConfig("https://example.com/", "consumer-key", "consumer-secret");
- assertEquals("https://example.com", config.getUrl());
- }
-}
diff --git a/src/test/java/com/icoderman/woocommerce/oauth/OAuthSignatureTest.java b/src/test/java/com/icoderman/woocommerce/oauth/OAuthSignatureTest.java
deleted file mode 100644
index 417b5f5..0000000
--- a/src/test/java/com/icoderman/woocommerce/oauth/OAuthSignatureTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.icoderman.woocommerce.oauth;
-
-import com.icoderman.woocommerce.HttpMethod;
-import org.junit.Test;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class OAuthSignatureTest {
- private final OAuthConfig config = new OAuthConfig("https://example.com", "consumer key", "consumer-secret");
-
- @Test
- public void returnsEmptyValuesForIncompleteInput() {
- assertTrue(OAuthSignature.getAsMap(null, "https://example.com", HttpMethod.GET).isEmpty());
- assertEquals("", OAuthSignature.getAsQueryString(config, null, HttpMethod.GET));
- }
-
- @Test
- public void includesRequiredOAuthParameters() {
- Map values = OAuthSignature.getAsMap(
- config, "https://example.com/wp-json/wc/v3/products", HttpMethod.GET);
- assertEquals("consumer key", values.get("oauth_consumer_key"));
- assertEquals("HMAC-SHA256", values.get("oauth_signature_method"));
- assertTrue(values.containsKey("oauth_nonce"));
- assertTrue(values.containsKey("oauth_timestamp"));
- assertTrue(values.containsKey("oauth_signature"));
- }
-
- @Test
- public void percentEncodesQueryValues() {
- Map params = new HashMap<>();
- params.put("search", "coffee & tea");
- String query = OAuthSignature.getAsQueryString(
- config, "https://example.com/wp-json/wc/v3/products", HttpMethod.GET, params);
- assertTrue(query.contains("search=coffee%20%26%20tea"));
- assertFalse(query.contains("coffee+%26+tea"));
- }
-
- @Test
- public void deleteAddsWooCommerceForceParameter() {
- Map values = OAuthSignature.getAsMap(
- config, "https://example.com/wp-json/wc/v3/products/1", HttpMethod.DELETE,
- Collections.emptyMap());
- assertEquals("true", values.get("force"));
- }
-
- @Test
- public void doubleEncodesIsoDateInsideSignatureBaseString() {
- Map params = new HashMap<>();
- params.put("after", "2023-02-21T13:00:23");
-
- String baseString = OAuthSignature.getSignatureBaseString(
- "https://example.com/wp-json/wc/v3/orders", "GET", params);
-
- assertTrue(baseString.contains("after%3D2023-02-21T13%253A00%253A23"));
- }
-}
From 8afe0355137ada04b8a6399ffd3e6fa84eed2386 Mon Sep 17 00:00:00 2001
From: Oleksandr Mandryk <2678920+omandryk@users.noreply.github.com>
Date: Tue, 11 Aug 2026 11:05:32 -0400
Subject: [PATCH 4/4] Use current GitHub Actions runtimes
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 601b227..deb2e18 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,8 +15,8 @@ jobs:
matrix:
java: ['8', '11', '17', '21']
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-java@v4
+ - uses: actions/checkout@v5
+ - uses: actions/setup-java@v5
with:
distribution: temurin
java-version: ${{ matrix.java }}