I made a shopify app @java

Recently, I decided to make a shopify application that I often hear the name of in Japan, so I will keep what I remembered at that time. I handed over the explanation of shopify itself to other people, and this time I will focus on application development. I posted an article on Qiita for the first time this time. I had a hard time because there wasn't much commentary in Japanese, so I hope it helps similar people. It will be an explanation for those who want to develop an application. (Please point out the parts that are difficult to understand because I omit the parts in the first place)

First of all, there are three types of apps. There are three types: private apps, closed apps, and open apps.

[Private app]

Create from the store screen. Basic authentication is performed using the API key and password on the store screen. The resources that can be accessed are set on the store screen. You don't have to make an Oath, so it's a good place to get started quickly. However, since this app cannot be opened, it is limited to the case where the operator = developer or once created, it is a one-off app. I think it's perfect for those who want to touch it for a moment and see what it looks like.

[Close app]

Install from the partner screen. Get a token with Oath authentication and authenticate with token. It can only be installed on sites under your control. It feels like it's for development before it's open.

Flow until token acquisition

1. Create an app on the partner screen

Set the redirect destination when installing the application in Whitelisted redirection.

2. Install by specifying the store

After performing hmac authentication, the URL specified for the created application will be accessed. "https://"+shop+"/admin/oauth/authorize?client_id="+api_key+"&scope="+scope+"&redirect_uri="+redirect_uri+"&state="+state+"&grant_options[]="+grant_options; I'll redirect you to. If hmac authentication does not pass, refuse it. For api_key, specify the API key in the application on the partner screen. Enter permissions such as write_orders, read_orders, write_customers, read_customers, etc. in scope separated by commas. In state, put a character string to be checked after redirecting later.

3. If the parameters are correct after redirect, it will be called back to redirect_uri.

Please note that you will not be able to proceed to the store screen ⇒ redirect unless you enter the URL of the callback destination in Whitelisted redirection. The get parameter when called back contains state and code. Check if the state matches the one set in 2 above. If not, refuse it. code is the code required to get the token.

4. Obtaining a token (this is the most difficult battle)

Obtain the token using the code obtained earlier and the API key and API secret key in the application on the partner screen. Even if you send each code with json, it will be played, so let's put it in the request body and post it. CloseableHttpClient client = HttpClients.createDefault(); HttpPost httpPost= new HttpPost(”URL”); // shop +"/admin/oauth/access_token" ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair(”client_secret”, <API secret key>)); params.add(new BasicNameValuePair(”code”, <code>)); params.add(new BasicNameValuePair(”client_id”, <API key>)); httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); The other thing that was annoying was the http header. httpPost.setHeader("content-type", "application/x-www-form-urlencoded"); httpPost.setHeader("accept", "*/*"); httpPost.removeHeaders ("user-agent"); // Maybe it doesn't make sense httpPost.removeHeaders ("accept-encoding"); // Maybe it doesn't make sense httpPost.removeHeaders ("connection"); // Maybe it doesn't make sense response = client.execute(httpPost); If you send with, token will be returned as json. (The belief that if you return with json, you should send it with json is a step to the swamp)

5. Authenticate using token (Please get or post to your favorite API. APIs that use permissions that were not included in scope will be played)

The token will be specified in the http header. (It seems that the get parameter can be used, but it is not recommended) http.setHeader("X-Shopify-Access-Token", token); The other header specifications are like ↓. http.setHeader("accept-encoding", "gzip, deflate"); http.setHeader("accept", "*/*"); http.setHeader("Content-type","application/json; charset=UTF-8"); token doesn't seem to expire.

[Open app]

Install it from the app store and use it. If you ask shopify to review what you made with the close app, it will be opened (it seems that you have not done it yet) If you open it, you can sell the app.

[Common to all apps]

There is an access limit. If you do not make it with this in mind, it will be quite inefficient. Check the leaky bucket for the detailed mechanism. Roughly speaking ... ・ It can process 2 requests per second (in the normal plan) -Requests that could not be processed are stacked for 40 requests (in the normal plan) and processed sequentially. The current number of processing stacks is in the response header HTTP_X_SHOPIFY_SHOP_API_CALL_LIMIT An error will occur if the amount is exceeded. In other words, if you process in series, the API will only accept it twice a second. It will be a considerable bottleneck, so it will be a little better if you parallelize your own processing and API request, perform your own processing while executing the API, and try not to make the timing when you do not hit the API as much as possible. Specifically, we parallelized it with Callable and started to perform our own processing in order from the one that returned from the API. However, no matter how much parallelization is done, the response from the API is only twice a second, so increasing the stack does not mean that the entire process will be faster. Therefore, by adjusting the number of threads, we have tried not to carry a useless processing stack. If you keep using it until LIMIT, it will get in the way for other apps, so I think it's better to stack at most 2 or 3. It's a feeling of always stacking a little and minimizing the timing when the API is resting. On the other hand, unless the API is resting, stacking it any further will not speed it up. It is better to incorporate a mechanism that delays and suppresses the next CALL when the limit is about to be reached. If the stack increases unexpectedly and the limit is exceeded, an error will occur, so if you have a limiter yourself, you can avoid unnecessary access.

[Summary]

The APIs that can be used are the same, although there are differences between basic authentication and Oath authentication, whether private or closed. If you have an environment where you can use ruby or nodejs, I think it is faster to use the public library that is open to the public. For that reason, I decided to make it with java, but I hope that those who are addicted to the same swamp can get out of it in this article. By the way, old java has a high possibility of being able to use ssl authentication, so it is better to add a certificate first. (It's best to give the version obediently) It seems that there is a library called Shopify4J, but I didn't have the courage to use it because the update stopped a long time ago. Also, since the official shopify community is a mixture of boulders, there are times when you can clear it easily, and there are times when you get stuck in the depths, so let's make the choices around that. It's not that complicated when I look back at it after it's completed, but when I look it up in the official English documents and the community and make trial and error, I feel like I'm going back and forth. Obviously, everyone uses the library, so you probably wouldn't bother to make this area. I came across specifications and interesting mechanisms that I rarely see in Japan when I made them, but it depends on the response ...

[Materials useful for the survey]

https://www.shopify.com/partners/blog/17056443-how-to-generate-a-shopify-api-token I have a php sample, so I used it to authenticate. I checked and reproduced the same request for my development environment by checking the header and transmission parameter configuration. It is a remnant that the source contains a wasteful spell.

Recommended Posts

I made a shopify app @java
I made a chat app.
I made a matching app (Android app)
[Android] I made a pedometer app.
I made a rock-paper-scissors app with kotlin
I made a calculator app on Android
I made a new Java deployment tool
I made a rock-paper-scissors app with android
I made a Diff tool for Java files
I made a rock-paper-scissors game in Java (CLI)
I made a viewer app that displays a PDF
I made roulette in Java.
I made a simple calculation problem game in Java
I made a Wrapper that calls KNP from Java
Ruby: I made a FizzBuzz program!
I created a PDF in Java.
I made a GUI with Swing
[Beginner] I made a program to sell cakes in Java
I made a simple recommendation function.
I made an annotation in Java.
I made a package.xml generation tool.
I made a Dockerfile to start Glassfish 5 using Oracle Java
[Rails] I made a simple calendar mini app with customized specifications.
I recently made a js app in the rumored Dart language
I made a method to ask for Premium Friday (Java 8 version)
Create a TODO app in Java 7 Create Header
I made a risky die with Ruby
I made a plugin for IntelliJ IDEA
Try making a calculator app in Java
Deploy a Java web app on Heroku
I made a bulletin board using Docker 1
I made StringUtils.isBlank
I made an app to scribble with PencilKit on a PDF file
I made a class that can use JUMAN and KNP from Java
[LINE BOT] I made a ramen BOT with Java (Maven) + Heroku + Spring Boot (1)
04. I made a front end with SpringBoot + Thymeleaf
I made a mosaic art with Pokemon images
java I tried to break a simple block
I did Java to make (a == 1 && a == 2 && a == 3) always true
I made an app for myself! (Reading management app)
I made a gender selection column with enum
I tried hitting a Java method from ABCL
I made an Android app for MiRm service
I wanted to make (a == 1 && a == 2 && a == 3) true in Java
I wrote a primality test program in Java
I tried to create a LINE clone app
I made a Docker container to run Maven
I made a Ruby extension library in C
[Rails] I made a draft function using enum
CICS-Run Java application-(1) Run a simple sample app
I made a LINE bot with Rails + heroku
I wrote a prime factorization program in Java
I tried to break a block with java (1)
I tried running Java on a Mac terminal
Ssh connect using SSHJ from a Java 6 app
I made a portfolio with Ruby On Rails
I want to play a GIF image on the Andorid app (Java, Kotlin)
Learn Java with Progate → I will explain because I made a basic game myself
[Azure] I tried to create a Java application for free-Web App creation- [Beginner]
I made a Docker image of SDAPS for Japanese
Create a portfolio app using Java and Spring Boot