103103
104104public class ShopifySdk {
105105
106+ static final String API_VERSION_PREFIX = "api" ;
106107 private static final long TWO_HUNDRED_MILLISECONDS = 200L ;
107108 private static final String EQUALS = "=" ;
108109 private static final String AMPERSAND = "&" ;
@@ -122,7 +123,6 @@ public class ShopifySdk {
122123 static final String OAUTH = "oauth" ;
123124 static final String REVOKE = "revoke" ;
124125 static final String ACCESS_TOKEN = "access_token" ;
125- static final String VERSION_2020_01 = "api/2020-01" ;
126126 static final String PRODUCTS = "products" ;
127127 static final String VARIANTS = "variants" ;
128128 static final String CUSTOM_COLLECTIONS = "custom_collections" ;
@@ -181,6 +181,7 @@ public class ShopifySdk {
181181
182182 private String shopSubdomain ;
183183 private String apiUrl ;
184+ private String apiVersion ;
184185 private String clientId ;
185186 private String clientSecret ;
186187 private String authorizationToken ;
@@ -253,6 +254,18 @@ public static interface OptionalsStep {
253254 */
254255 OptionalsStep withReadTimeout (int duration , TimeUnit timeUnit );
255256
257+ /**
258+ * String representation of the version you want to use. If not populated, this
259+ * will use shopify oldest stable version. Although this is not recommended so
260+ * you can target a set of shopify features. Ex: '2020-10' '2020-07' '2020-04'.
261+ * If you are specifying the API URL ensure you leave off the version if you are
262+ * using this.
263+ *
264+ * @param apiVersion
265+ * @return
266+ */
267+ OptionalsStep withApiVersion (final String apiVersion );
268+
256269 ShopifySdk build ();
257270
258271 }
@@ -291,6 +304,7 @@ protected ShopifySdk(final Steps steps) {
291304 this .clientSecret = steps .clientSecret ;
292305 this .authorizationToken = steps .authorizationToken ;
293306 this .apiUrl = steps .apiUrl ;
307+ this .apiVersion = steps .apiVersion ;
294308 this .minimumRequestRetryRandomDelayMilliseconds = steps .minimumRequestRetryRandomDelayMilliseconds ;
295309 this .maximumRequestRetryRandomDelayMilliseconds = steps .maximumRequestRetryRandomDelayMilliseconds ;
296310 this .maximumRequestRetryTimeoutMilliseconds = steps .maximumRequestRetryTimeoutMilliseconds ;
@@ -321,6 +335,7 @@ protected static class Steps
321335 private String clientSecret ;
322336 private String authorizationToken ;
323337 private String apiUrl ;
338+ private String apiVersion ;
324339 private long minimumRequestRetryRandomDelayMilliseconds = DEFAULT_MINIMUM_REQUEST_RETRY_RANDOM_DELAY_IN_MILLISECONDS ;
325340 private long maximumRequestRetryRandomDelayMilliseconds = DEFAULT_MAXIMUM_REQUEST_RETRY_RANDOM_DELAY_IN_MILLISECONDS ;
326341 private long maximumRequestRetryTimeoutMilliseconds = DEFAULT_MAXIMUM_REQUEST_RETRY_TIMEOUT_IN_MILLISECONDS ;
@@ -398,11 +413,17 @@ public OptionalsStep withReadTimeout(final int duration, final TimeUnit timeUnit
398413 return this ;
399414 }
400415
416+ @ Override
417+ public OptionalsStep withApiVersion (final String apiVersion ) {
418+ this .apiVersion = apiVersion ;
419+ return this ;
420+ }
421+
401422 }
402423
403424 public boolean revokeOAuthToken () {
404425 try {
405- final Response response = delete (getWebTarget ().path (OAUTH ).path (REVOKE ));
426+ final Response response = delete (getUnversionedWebTarget ().path (OAUTH ).path (REVOKE ));
406427 return Status .OK .getStatusCode () == response .getStatus ();
407428 } catch (final ShopifyErrorResponseException e ) {
408429 return false ;
@@ -426,8 +447,8 @@ public ShopifyPage<ShopifyProduct> getProducts(final int pageSize) {
426447 }
427448
428449 public ShopifyPage <ShopifyProduct > getProducts (final String pageInfo , final int pageSize ) {
429- final Response response = get (getWebTarget ().path (VERSION_2020_01 ). path ( PRODUCTS )
430- .queryParam (LIMIT_QUERY_PARAMETER , pageSize ). queryParam ( PAGE_INFO_QUERY_PARAMETER , pageInfo ));
450+ final Response response = get (getWebTarget ().path (PRODUCTS ). queryParam ( LIMIT_QUERY_PARAMETER , pageSize )
451+ .queryParam (PAGE_INFO_QUERY_PARAMETER , pageInfo ));
431452 final ShopifyProductsRoot shopifyProductsRoot = response .readEntity (ShopifyProductsRoot .class );
432453 return mapPagedResponse (shopifyProductsRoot .getProducts (), response );
433454 }
@@ -723,7 +744,7 @@ public ShopifyCustomer getCustomer(final String customerId) {
723744 }
724745
725746 public ShopifyPage <ShopifyCustomer > getCustomers (final ShopifyGetCustomersRequest shopifyGetCustomersRequest ) {
726- WebTarget target = getWebTarget ().path (VERSION_2020_01 ). path ( CUSTOMERS );
747+ WebTarget target = getWebTarget ().path (CUSTOMERS );
727748 if (shopifyGetCustomersRequest .getPageInfo () != null ) {
728749 target = target .queryParam (PAGE_INFO_QUERY_PARAMETER , shopifyGetCustomersRequest .getPageInfo ());
729750 }
@@ -749,14 +770,15 @@ public ShopifyPage<ShopifyCustomer> getCustomers(final ShopifyGetCustomersReques
749770 }
750771
751772 public ShopifyPage <ShopifyCustomer > searchCustomers (final String query ) {
752- final Response response = get (getWebTarget ().path (VERSION_2020_01 ). path ( CUSTOMERS ).path (SEARCH )
773+ final Response response = get (getWebTarget ().path (CUSTOMERS ).path (SEARCH )
753774 .queryParam (QUERY_QUERY_PARAMETER , query ).queryParam (LIMIT_QUERY_PARAMETER , DEFAULT_REQUEST_LIMIT ));
754775 return getCustomers (response );
755776 }
756777
757778 public ShopifyFulfillment cancelFulfillment (final String orderId , final String fulfillmentId ) {
779+ final WebTarget buildOrdersEndpoint = buildOrdersEndpoint ();
758780 final Response response = post (
759- buildOrdersEndpoint () .path (orderId ).path (FULFILLMENTS ).path (fulfillmentId ).path (CANCEL ),
781+ buildOrdersEndpoint .path (orderId ).path (FULFILLMENTS ).path (fulfillmentId ).path (CANCEL ),
760782 new ShopifyFulfillment ());
761783 final ShopifyFulfillmentRoot shopifyFulfillmentRootResponse = response .readEntity (ShopifyFulfillmentRoot .class );
762784 return shopifyFulfillmentRootResponse .getFulfillment ();
@@ -1009,8 +1031,8 @@ private String generateToken() {
10091031 try {
10101032
10111033 final Entity <String > entity = Entity .entity (EMPTY_STRING , MediaType .APPLICATION_JSON );
1012- final Response response = this .webTarget .path (OAUTH ).path (ACCESS_TOKEN ). queryParam ( CLIENT_ID , this . clientId )
1013- .queryParam (CLIENT_SECRET , this .clientSecret )
1034+ final Response response = this .getUnversionedWebTarget () .path (OAUTH ).path (ACCESS_TOKEN )
1035+ .queryParam (CLIENT_ID , this . clientId ). queryParam ( CLIENT_SECRET , this .clientSecret )
10141036 .queryParam (AUTHORIZATION_CODE , this .authorizationToken ).request (MediaType .APPLICATION_JSON )
10151037 .post (entity );
10161038
@@ -1027,6 +1049,14 @@ private String generateToken() {
10271049 }
10281050 }
10291051
1052+ private WebTarget getUnversionedWebTarget () {
1053+ if (StringUtils .isNotBlank (this .shopSubdomain )) {
1054+ return CLIENT
1055+ .target (new StringBuilder ().append (HTTPS ).append (this .shopSubdomain ).append (API_TARGET ).toString ());
1056+ }
1057+ return CLIENT .target (this .apiUrl );
1058+ }
1059+
10301060 private WebTarget getWebTarget () {
10311061 if (this .webTarget == null ) {
10321062
@@ -1037,9 +1067,13 @@ private WebTarget getWebTarget() {
10371067 } else {
10381068 this .webTarget = CLIENT .target (this .apiUrl );
10391069 }
1070+ if (StringUtils .isNotBlank (this .apiVersion )) {
1071+ this .webTarget = this .webTarget .path (API_VERSION_PREFIX ).path (this .apiVersion );
1072+ }
10401073 if (this .accessToken == null ) {
10411074 this .accessToken = generateToken ();
10421075 }
1076+
10431077 final Shop shop = this .getShop ().getShop ();
10441078 LOGGER .info (SHOP_RETRIEVED_MESSAGE , shop .getId (), shop .getName ());
10451079 }
@@ -1120,6 +1154,6 @@ private String getQueryParam(final URI uri, final String key) {
11201154 }
11211155
11221156 private WebTarget buildOrdersEndpoint () {
1123- return getWebTarget ().path (VERSION_2020_01 ). path ( ORDERS );
1157+ return getWebTarget ().path (ORDERS );
11241158 }
11251159}
0 commit comments