Java SDK for Shopify APIs, including:
- Shopify Store & Shopify APP
- GraphQL Admin Schema
- GraphQL Admin API
- GraphQL Storefront Schema
- GraphQL Storefront API
- GraphQL Partner Schema
- GraphQL Partner API
- [INCOMPLETE] REST Admin API Models
- [INCOMPLETE] REST Admin API
- ...
Shopify Core & APP
implementation("xyz.codemeans.shopify4j:shopify4j-core:$shopify4jVersion")
GraphQL Admin
// api
implementation("xyz.codemeans.shopify4j:graphql-admin-api:$shopify4jVersion")
// schema
implementation("xyz.codemeans.shopify4j:graphql-admin-schema:$shopify4jVersion")
GraphQL Storefront
// api
implementation("xyz.codemeans.shopify4j:graphql-storefront-api:$shopify4jVersion")
// schema
implementation("xyz.codemeans.shopify4j:graphql-storefront-schema:$shopify4jVersion")
GraphQL Partner
// api
implementation("xyz.codemeans.shopify4j:graphql-partner-api:$shopify4jVersion")
// schema
implementation("xyz.codemeans.shopify4j:graphql-partner-schema:$shopify4jVersion")
REST Admin
// api
implementation("xyz.codemeans.shopify4j:rest-admin-api:$shopify4jVersion")
// model
implementation("xyz.codemeans.shopify4j:rest-admin-model:$shopify4jVersion")
Requirements:
- JDK 8
- gradle >= 5.6
- ruby >= 2.3
- graphql_java_gen
Configure nexus repository in build.gradle: $HOME/.gradle/gradle.properties
OR gradle.properteis
nexus.repo.url=http://your.nexus.host/repository/maven-public/
nexus.repo.public=http://your.nexus.host/repository/maven-public/
nexus.repo.release=http://your.nexus.host/repository/maven-releases/
nexus.repo.snapshot=http://your.nexus.host/repository/maven-snapshots/
nexus.username=your-nexus-username
nexus.password=your-nexus-password
Then run
gradle publish -Prelease -Ppub=nexus
Shopify Oauth flow: https://shopify.dev/tutorials/authenticate-with-oauth
// step1: Get client credentials
PublicApp app = new PublicApp()
.setClientId("<client-id>")
.setClientSecret("<client-secret>")
.setScopes(...);
// step2: Ask for permission
AuthorizationReq req = new AuthorizationReq();
...
String authorizationUrl = oauthFlow.authorizationUrl(app, req);
redirectTo(authorizationUrl);
// step3: Confirm installation
ConfirmRedirection redirection = new ConfirmRedirection()
.setCode("<code>")
.setShop("<shop>");
OauthAccessToken accessToken = oauthFlow.exchangeAccessToken(app, redirection);
...
// step4: Making authenticated requests
...
HMAC Verification
boolean verified = HmacVerification.verifyQueryString(app.getClientSecret(), queryString);
If you are integrating with multiple shopify stores in one sysmtem, just like we do, ClientFactory
will be very helpful.
If information of your stores is saved in some persistent database, you can just implement a StoreSettingStorage
to retrieve data and build out a StoreSetting
.
Here is an example for REST & GraphQL API:
StoreSettingStorage settingStorage = ...;
GraphqlInvoker invoker = new OkHttpGraphqlInvoker(new PrivateAppAdminAccessTokenProvider(settingStorage));
ClientFactory<GraphqlAdmin> clientFactory = new DefaultGraphqlAdminFactory(settingStorage, invoker);
clientFactory = CachedClientFactory.of(clientFactory); // cache created stores, avoiding duplicated creation
GraphqlAdmin store1 = clientFactory.getClient(domain1);
Please see release notes: https://github.com/YuanWenqing/shopify4j/releases
StoreSetting setting = ...;
GraphqlInvoker invoker = new OkHttpGraphqlInvoker(AccessTokenProvider.constant(setting.getPrivateApp().getAdminApiPassword()));
GraphqlAdmin admin = new DefaultGraphqlAdmin(setting, invoker);
// get a product with: title, handle ...
QueryRootQuery queryRootQuery = Operations.query(query -> query
.product(id, product -> product
.title()
.handle()
...
)
);
Product product = admin.query(queryRootQuery).getData().getProduct();
GraphqlInvoker
is a simple interface to invoke GraphQL http request.
OkHttpGraphqlInvoker
is the basic implementation based on okhttp3.
You can customize your implementation on any http library you like.
- GraphQL Admin API Documentation: https://shopify.dev/docs/admin-api/graphql/
- GraphQL Storefront API Documentation: https://shopify.dev/docs/storefront-api/
- GraphQL Partner API Documentation: https://shopify.dev/docs/partner-api/
- Starter Tutorial: https://www.shopify.com/partners/blog/getting-started-with-graphql
- Codegen: https://github.com/Shopify/graphql_java_gen/
- Find GraphQL schema: https://community.shopify.com/c/Shopify-APIs-SDKs/Admin-API-Graphql-shema-endpoint/m-p/837807
- Useful Documenation: https://2fd.github.io/graphdoc/shopify/
StoreSetting setting = ...;
RestInvoker invoker = new OkHttpRestInvoker(AccessTokenProvider.constant(setting.getPrivateApp().getAdminApiPassword()));
RestAdmin store = new DefaultRestAdmin(setting, invoker);
// get a product
Product product = store.products.get(pid).object();
For now, supported apis can be checked in RestAdmin
store.collects()
store.collections()
store.customCollections()
store.smartCollections()
store.products()
store.productImages()
store.productVariants()
- ...
Sometimes, it's necessary to invoke multiple requests to complete one business operation.
For example, creation of a product with different images in some varaints needs steps below:
- invoke product creation request
- set imageId of varaints according to the response of product creation
- invoke product update request to bind variant and its image
Pipeline
is designed to simplify invocation of these requests:
store.products().pipeline(ProductModifyPipeline.create(product));
More general, if requests cross multiple apis, do pipeline via store
class StorePipeline implements Pipeline<RestAdmin, Product> {
public StorePipeline(...) {
...
}
@Override
public Class<Product> typeOfR() {
return Product.class;
}
@Override
public Product runWith(RestAdmin store) throws ShopifyServerException {
...
}
}
store.pipeline(new StorePipeline(...));
RestInvoker
is a simple interface to invoke REST http request.
OkHttpRestInvoker
is the basic implementation based on okhttp3.
You can customize your implementation on any http library you like.
Jackson is the default json serialization library. Since it is not easy to configure root-wrapping for specific classes by Jackson until the future version 3.0, we adopt a convention for model definication: @JsonRootName
is used as a signal to explicitly indicate whether root-wrapping is enabled.
shopify4j
is a third-party sdk of Shopify, thus it's impossible to track changes of Shopify API exactly in time. For compatibility and flexiblity, we don't use enums in Shopify model directly. But for convenience, we define almost all of the enums described in Shopify documentation and every enum type implements the interface ShopifyEnum
. It's very simple to use pre-defined enums when requesting Shopify like this:
ProductApi.ListReq listReq = new ProductApi.ListReq()
.setStatus(ProductStatus.active.shopifyValue())
.setPublishedStatus(PublishedStatus.any.shopifyValue());
If you want to cast a string value in response to an enum value, do like this:
ProductStatus status = ShopifyEnum.asEnum("active", ProductStatus.class);
- API Documentation: https://shopify.dev/docs/admin-api/rest/reference