ZReviewTender — Free Open Source App Reviews Monitoring Bot
Real-time monitoring of the latest app reviews and providing instant feedback to improve collaboration efficiency and consumer satisfaction
ZhgChgLi / ZReviewTender
App Reviews to Slack Channel
ZReviewTender — Automatically monitors the latest user reviews of App Store iOS/macOS apps and Google Play Android apps, and provides continuous integration tools to integrate into team workflows, improving collaboration efficiency and consumer satisfaction.
Key Features
- Retrieve review lists from App Store iOS/macOS apps and Google Play Android apps and filter out the latest reviews that have not been crawled yet
- [Default Feature] Forward the latest crawled reviews to Slack, and click the message timestamp link to quickly enter the backend to reply to reviews
- [Default Feature] Support using Google Translate API to automatically translate reviews from non-specified languages/regions into your language
- [Default Feature] Support automatic recording of reviews to Google Sheets
- Support flexible expansion, in addition to the included default features, you can still develop the required features according to the team workflow and integrate them into the tool e.g. Forward reviews to Discord, Line, Telegram…
- Use timestamps to record crawl positions to prevent duplicate crawling of reviews
- Support filtering features, you can specify to crawl only reviews with certain ratings, containing certain keywords, or from certain regions/languages
- Apple provides a stable and reliable source of App Store app review data based on the new App Store Connect API, no longer relying on unreliable XML data or Fastlane Spaceship sessions that expire and require regular manual maintenance
- Android also uses the official AndroidpublisherV3 API to fetch review data
- Support deployment using Github Repo w/ Github Action, allowing you to quickly and freely set up the ZReviewTender App Reviews bot
- 100% Ruby @ RubyGem
Comparison with Similar Services
App Reviews Workflow Integration Example (in Pinkoi)
Problem:
Reviews in the marketplace are very important for products, but it is a very manual and repetitive task to communicate and refer.
Because you have to manually check for new reviews from time to time, and if there are customer service issues, forward them to customer service for assistance. It’s repetitive and manual.
Through the ZReviewTender review bot, reviews are automatically forwarded to the Slack Channel, allowing everyone to quickly receive the latest review information, and track and discuss in real-time. It also allows the entire team to understand the current user reviews and suggestions for the product.
For more information, refer to: 2021 Pinkoi Tech Career Talk — High-Efficiency Engineering Team Demystified.
Deployment — Using Default Features Only
If you only need the default features of ZReviewTender (to Slack/Google Translate/Filter), you can use the following quick deployment method.
ZReviewTender has been packaged and released on RubyGems, and you can quickly and easily install and use ZReviewTender with RubyGems.
[Recommended] Deploy Directly Using Github Repo Template
- No hosting space required ✅
- No environment requirements ✅
- No need to understand engineering principles ✅
- Complete the Config file configuration to complete the deployment ✅
- Deployment can be completed in 8 steps ✅
- Completely free ✅ Github Action provides each account with 2,000+ minutes/month of execution time. Running ZReviewTender review fetching once only takes about 15-30 seconds. By default, it runs every 6 hours, 4 times a day, consuming only about 60 minutes per month. Github Private Repo can be created without any limit for free.
- Go to the ZReviewTender Template Repo: ZReviewTender-deploy-with-github-action
Click the “Use this template” button at the top right.
- Create Repo
- Repository name: Enter the name of the Repo project you want
- Access: Private
⚠️⚠️ Be sure to create a Private Repo ⚠️⚠️
Because you will upload settings and private keys to the project
Finally, click the “Create repository from template” button at the bottom.
- Confirm that your created Repo is a Private Repo
Confirm that the Repo name at the top right shows “🔒” and the Private label.
If not, it means you created a Public Repo which is very dangerous, please go to the top Tab “Settings” -> “General” -> Bottom “Danger Zone” -> “Change repository visibility” -> “Make private” to change it back to Private Repo.
- Wait for Project init to succeed
You can check the Badge in the Readme on the Repo homepage
If it shows passing, it means init was successful.
Or click the top Tab “Actions” -> wait for the “Init ZReviewTender” Workflow to complete:
Execution status will change to 3 “✅ Init ZReviewTender” -> Project init successful.
- Confirm if the init files and directories are correctly created
Click the “Code” tab above to return to the project directory. If the project init is successful, you will see:
- Directory:
config/
- File:
config/android.yml
- File:
config/apple.yml
- Directory:
latestCheckTimestamp/
- File:
latestCheckTimestamp/.keep
- Complete Configuration for
android.yml
&apple.yml
Enter the config/
directory to complete the configuration of android.yml
& apple.yml
files.
Click to enter the config YML file you want to edit and click the “✏️” in the upper right corner to edit the file.
Refer to the “ Settings “ section below to complete the configuration of android.yml
& apple.yml
.
After editing, you can directly save the settings by clicking “Commit changes” below.
Upload the corresponding Key files to the config/
directory:
In the config/
directory, select “Add file” -> “Upload files” in the upper right corner.
Upload the corresponding Key and external file paths configured in the config yml to the config/
directory, drag the files to the “upper block” -> wait for the files to upload -> directly “Commit changes” below to save.
After uploading, go back to the /config
directory to check if the files are correctly saved & uploaded.
- Initialize ZReviewTender (manually trigger execution once)
Click the “Actions” tab above -> select “ZReviewTender” on the left -> select “Run workflow” on the right -> click the “Run workflow” button to execute ZReviewTender once.
After clicking, refresh the webpage and you will see:
Click “ZReviewTender” to view the execution status.
Expand the “ Run ZreviewTender -r
“ block to view the execution log.
Here you can see an error because I haven’t configured my config yml file properly.
Go back and adjust the android/apple config yml, then return to step 6 and trigger the execution again.
Check the log of the “ ZReviewTender -r
“ block to confirm successful execution!
The Slack channel designated to receive the latest review messages will also show an init success message 🎉
- Done! 🎉 🎉 🎉
Configuration complete! From now on, the latest reviews within the period will be automatically fetched and forwarded to your Slack channel every 6 hours!
You can check the latest execution status at the top of the Readme on the Repo homepage:
If an error occurs, it means there was an execution error. Please go to Actions -> ZReviewTender to view the records; if there is an unexpected error, please create an Issue with the record information, and it will be fixed as soon as possible!
❌❌❌ When an error occurs, Github will also send an email notification, so you don’t have to worry about the bot crashing without anyone noticing!
Github Action Adjustment
You can configure the Github Action execution rules according to your needs.
Click on the “Actions” tab above -> “ZReviewTender” on the left -> “ ZReviewTender.yml
“ on the top right
Click the “✏️” on the top right to edit the file.
There are two parameters that can be adjusted:
cron: Set how often to check for new reviews. The default is 15 */6 * * *
, which means it will run every 6 hours and 15 minutes.
You can refer to crontab.guru to configure it according to your needs.
Please note:
- Github Action uses the UTC time zone
- The higher the execution frequency, the more Github Action execution quota will be consumed
run: Set the command to be executed. You can refer to the “ Execution “ section below. The default is ZReviewTender -r
- Default execution for Android App & Apple (iOS/macOS App):
ZReviewTender -r
- Execute only for Android App:
ZReviewTender -g
- Execute only for Apple (iOS/macOS App) App:
ZReviewTender -a
After editing, click “Start commit” on the top right and select “Commit changes” to save the settings.
Manually Trigger ZReviewTender
Refer to the previous section “6. Initialize ZReviewTender (Manually trigger execution once)”
Install Using Gem
If you are familiar with Gems, you can directly use the following command to install ZReviewTender
1
gem install ZReviewTender
Install Using Gem (Not familiar with Ruby/Gems)
If you are not familiar with Ruby or Gems, you can follow the steps below to install ZReviewTender
step by step
- Although macOS comes with Ruby, it is recommended to use rbenv or rvm to install a new Ruby and manage Ruby versions (I use
2.6.5
) - Use rbenv or rvm to install Ruby 2.6.5, and switch to rbenv/rvm’s Ruby
- Use
which ruby
to confirm that the current Ruby in use is not the system Ruby/usr/bin/ruby
- Once the Ruby environment is OK, use the following command to install
ZReviewTender
1
gem install ZReviewTender
Deployment — Want to Extend Functionality Yourself
Manual
- git clone ZReviewTender Source Code
- Confirm & improve the Ruby environment
- Enter the directory and run
bundle install
to install related dependencies for ZReviewTender
The method for creating a Processor can be referred to in the later content of the article.
Configuration
ZReviewTender — Use a yaml file to configure the Apple/Google review bot.
[Recommendation] Directly use the command at the bottom of the article — “Generate Configuration File”:
1
ZReviewTender -i
Directly generate blank apple.yml
& android.yml
configuration files.
Apple (iOS/macOS App)
Refer to the apple.example.yml file:
⚠️ After downloading
apple.example.yml
, remember to rename the file toapple.yml
apple.yml:
1
2
3
4
5
6
platform: 'apple'
appStoreConnectP8PrivateKeyFilePath: '' # APPLE STORE CONNECT API PRIVATE .p8 KEY File Path
appStoreConnectP8PrivateKeyID: '' # APPLE STORE CONNECT API PRIVATE KEY ID
appStoreConnectIssueID: '' # APPLE STORE CONNECT ISSUE ID
appID: '' # APP ID
...
appStoreConnectIssueID:
- App Store Connect -> Keys -> App Store Connect API
- Issuer ID:
appStoreConnectIssueID
appStoreConnectP8PrivateKeyID & appStoreConnectP8PrivateKeyFilePath:
- Name:
ZReviewTender
- Access:
App Manager
- appStoreConnectP8PrivateKeyID:
Key ID
- appStoreConnectP8PrivateKeyFilePath:
/AuthKey_XXXXXXXXXX.p8
, Download API Key, and place the file in the same directory as the config yml.
appID:
appID: App Store Connect -> App Store -> General -> App Information -> Apple ID
GCP Service Account
The Google API services used by ZReviewTender (fetching store reviews, Google Translate, Google Sheet) all use Service Account authentication.
You can follow the official steps to create GCP & Service Account to download and save the GCP Service Account credentials (*.json
).
- To use the auto-translate feature, make sure GCP has enabled
Cloud Translation API
and the Service Account is added. - To use the record to Google Sheet feature, make sure GCP has enabled
Google Sheets API
,Google Drive API
, and the Service Account is added.
Google Play Console (Android App)
Refer to the android.example.yml file:
⚠️ After downloading
android.example.yml
, remember to rename the file toandroid.yml
android.yml:
1
2
3
4
5
6
platform: 'android'
packageName: '' # Android App Package Name
keyFilePath: '' # Google Android Publisher API Credential .json File Path
playConsoleDeveloperAccountID: '' # Google Console Developer Account ID
playConsoleAppID: '' # Google Console App ID
......
packageName:
packageName: com.XXXXX
can be obtained from Google Play Console -> Dashboard -> App
playConsoleDeveloperAccountID & playConsoleAppID:
Can be obtained from the URL on the Google Play Console -> Dashboard -> App page:
This will be used to generate a review message link, allowing the team to quickly access the backend review reply page by clicking the link.
keyFilePath:
The most important information, GCP Service Account credential key (*.json
)
Follow the steps in the official documentation to create a Google Cloud Project & Service Account, then go to Google Play Console -> Setup -> API Access to enable the Google Play Android Developer API
and link the project. Download the JSON key from GCP.
Example content of the JSON key:
gcp_key.json:
1
2
3
4
5
6
7
8
9
10
11
12
{
"type": "service_account",
"project_id": "XXXX",
"private_key_id": "XXXX",
"private_key": "-----BEGIN PRIVATE KEY-----\nXXXX\n-----END PRIVATE KEY-----\n",
"client_email": "XXXX@XXXX.iam.gserviceaccount.com",
"client_id": "XXXX",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/XXXX.iam.gserviceaccount.com"
}
- keyFilePath:
/gcp_key.json
Key file path, place the file in the same directory as the config yml.
Processors
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
processors:
- FilterProcessor:
class: "FilterProcessor"
enable: true # enable
keywordsInclude: [] # keywords you want to filter out
ratingsInclude: [] # ratings you want to filter out
territoriesInclude: [] # territories you want to filter out
- GoogleTranslateProcessor: # Google Translate Processor, will translate review text to your language, you can remove whole block if you don't needed it.
class: "GoogleTranslateProcessor"
enable: false # enable
googleTranslateAPIKeyFilePath: '' # Google Translate API Credential .json File Path
googleTranslateTargetLang: 'zh-TW' # Translate to what Language
googleTranslateTerritoriesExclude: ["TWN","CHN"] # Review origin Territory (language) that you don't want to translate.
- SlackProcessor: # Slack Processor, resend App Review to Slack.
class: "SlackProcessor"
enable: true # enable
slackTimeZoneOffset: "+08:00" # Review Created Date TimeZone
slackAttachmentGroupByNumber: "1" # 1~100, how many review message in 1 slack message.
slackBotToken: "" # Slack Bot Token, send slack message throught Slack Bot.
slackBotTargetChannel: "" # Slack Bot Token, send slack message throught Slack Bot. (recommended, first priority)
slackInCommingWebHookURL: "" # Slack In-Comming WebHook URL, Send slack message throught In-Comming WebHook, not recommended, deprecated.
...More Processors...
ZReviewTender comes with four processors, and the order affects the data processing flow: FilterProcessor -> GoogleTranslateProcessor -> SlackProcessor -> GoogleSheetProcessor.
FilterProcessor:
Filters the fetched reviews based on specified conditions, only processing reviews that meet the criteria.
- class:
FilterProcessor
No need to adjust, points to lib/Processors/FilterProcessor
.rb - enable:
true
/false
Enable this processor or not - keywordsInclude: [“
keyword1
”,“keyword2
”…] Filters reviews that contain these keywords - ratingsInclude: [
1
,2
…] 1~5 Filters reviews that include these ratings - territoriesInclude: [“
zh-hant
”,”TWN
”…] Filters reviews that include these regions (Apple) or languages (Android)
GoogleTranslateProcessor:
Translate the reviews into the specified language.
- class:
GoogleTranslateProcessor
No adjustment needed, points to lib/Processors/GoogleTranslateProcessor
.rb - enable:
true
/false
Enable this Processor or Not - googleTranslateAPIKeyFilePath:
/gcp_key.json
GCP Service Account credential key File Path*.json
, place the file in the same directory as the config yml, refer to the Google Play Console JSON key example above. (Please ensure that the service account of the JSON key hasCloud Translation API
permissions) - googleTranslateTargetLang:
zh-TW
,en
…target translation language - googleTranslateTerritoriesExclude: [“
zh-hant
”,”TWN
”…] Territories (Apple) or languages (Android) that do not need translation
SlackProcessor:
Forward reviews to Slack.
- class:
SlackProcessor
No adjustment needed, points to lib/Processors/SlackProcessor
.rb - enable:
true
/false
Enable this Processor or Not - slackTimeZoneOffset:
+08:00
Review time display time zone - slackAttachmentGroupByNumber:
1
Set how many Reviews to combine into one message to speed up sending; default is 1 Review per 1 Slack message. - slackBotToken:
xoxb-xxxx-xxxx-xxxx
Slack Bot Token, Slack recommends creating a Slack Bot withpostMessages
Scope and using it to send Slack messages - slackBotTargetChannel:
CXXXXXX
Group ID ( not the group name ), the Slack Bot will send to which Channel group; and you need to add your Slack Bot to that group - slackInCommingWebHookURL:
https://hooks.slack.com/services/XXXXX
Use the old InComming WebHookURL to send messages to Slack, note! Slack does not recommend continuing to use this method to send messages.
Please note, this is a legacy custom integration — an outdated way for teams to integrate with Slack. These integrations lack newer features and they will be deprecated and possibly removed in the future. We do not recommend their use. Instead, we suggest that you check out their replacement: Slack apps.
- slackBotToken and slackInCommingWebHookURL, SlackProcessor will preferentially choose to use slackBotToken
GoogleSheetProcessor
Record reviews to Google Sheet.
- class:
GoogleSheetProcessor
No adjustment needed, points to lib/Processors/SlackProcessor
.rb - enable:
true
/false
Enable this Processor or Not - googleSheetAPIKeyFilePath:
/gcp_key.json
GCP Service Account credential key File Path*.json
, place the file in the same directory as the config yml, refer to the Google Play Console JSON key example above. (Please ensure that the service account of the JSON key hasGoogle Sheets API
,Google Drive API
permissions) - googleSheetTimeZoneOffset:
+08:00
Review time display time zone - googleSheetID:
Google Sheet ID
Can be obtained from the Google Sheet URL: https://docs.google.com/spreadsheets/d/googleSheetID
/ - googleSheetName: Sheet name, e.g.
Sheet1
- keywordsInclude: [“
keyword1
”,“keyword2
”…] Filter reviews that contain these keywords - ratingsInclude: [
1
,2
…] 1~5 Filter reviews that contain these rating scores - territoriesInclude: [“
zh-hant
”,”TWN
”…] Filter reviews that contain these territories (Apple) or languages (Android) - values: [ ] Combination of review information fields
1
2
3
4
5
6
7
8
9
10
%TITLE% Review Title
%BODY% Review Content
%RATING% Review Rating 1~5
%PLATFORM% Review Source Platform Apple or Android
%ID% Review ID
%USERNAME% Review Username
%URL% Review URL
%TERRITORY% Review Territory (Apple) or Review Language (Android)
%APPVERSION% Reviewed App Version
%CREATEDDATE% Review Creation Date
For example, my Google Sheet columns are as follows:
1
Review Rating,Review Title,Review Content,Review Information
Then values can be set as:
1
values: ["%TITLE%","%BODY%","%RATING%","%PLATFORM% - %APPVERSION%"]
Custom Processor to Integrate Your Workflow
If you need a custom Processor, please use manual deployment, as the gem version of ZReviewTender is packaged and cannot be dynamically adjusted.
You can refer to lib/Processors/ProcessorTemplate.rb to create your extension:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$lib = File.expand_path('../lib', File.dirname(__FILE__))
require "Models/Review"
require "Models/Processor"
require "Helper"
require "ZLogger"
# Add to config.yml:
#
# processors:
# - ProcessorTemplate:
# class: "ProcessorTemplate"
# parameter1: "value"
# parameter2: "value"
# parameter3: "value"
# ...
#
class ProcessorTemplate < Processor
def initialize(config, configFilePath, baseExecutePath)
# init Processor
# get parameter from config e.g. config["parameter1"]
# configFilePath: file path of config file (apple.yml/android.yml)
# baseExecutePath: user execute path
end
def processReviews(reviews, platform)
if reviews.length < 1
return reviews
end
## do what you want to do with reviews...
## return result reviews
return reviews
end
end
initialize will provide:
- config Object: Corresponding settings in the config yml
- configFilePath: Path of the used config yml file
- baseExecutePath: Path where the user executes ZReviewTender
processReviews(reviews, platform):
After fetching new reviews, this function will be called to allow the Processor to handle them. Please return the resulting Reviews after processing.
Review data structure is defined in lib/Models/ Review.rb
Notes
XXXterritorXXX
parameter:
- Apple Region: TWM/JPN…
- Android Language: zh-hant/en/…
If a Processor is not needed: You can set enable: false
or directly remove the Processor Config Block.
1
2
3
4
5
6
7
8
9
10
**Processors execution order can be adjusted according to your needs:**
e.g. Execute Filter first, then Translation, then Slack, then Log to Google Sheet...
### Execution
> ⚠️ Use Gem to directly run `ZReviewTender`, if it's a manual deployment project, please use `bundle exec ruby bin/ZReviewTender` to execute.
#### Generate configuration files:
```css
ZReviewTender -i
Generate apple.yml & android.yml from apple.example.yml & android.example.yml to the config/
directory in the current execution directory.
Execute Apple & Android review scraping:
1
ZReviewTender -r
- By default, read the
apple.yml
&android.yml
settings under/config/
Execute Apple & Android review scraping & specify configuration file directory:
1
ZReviewTender --run=configuration file directory
- By default, read the
apple.yml
&android.yml
settings under/config/
Execute only Apple review scraping:
1
ZReviewTender -a
- By default, read the
apple.yml
settings under/config/
Execute only Apple review scraping & specify configuration file location:
1
ZReviewTender --apple=apple.yml configuration file location
Execute only Android review scraping:
1
ZReviewTender -g
- By default, read the
android.yml
settings under/config/
Execute only Android review scraping & specify configuration file location:
1
ZReviewTender --googleAndroid=android.yml configuration file location
Clear execution records and return to initial settings
1
ZReviewTender -d
This will delete the Timestamp record file in /latestCheckTimestamp
, returning to the initial state. Re-executing the scraping will receive the init success message again:
Current ZReviewTender version
1
ZReviewTender -v
Displays the latest version number of ZReviewTender on RubyGem.
Update ZReviewTender to the latest version (rubygem only)
1
ZReviewTender -n
First execution
The first successful execution will send an initialization success message to the specified Slack Channel and generate latestCheckTimestamp/Apple
and latestCheckTimestamp/Android
files in the corresponding execution directory to record the last scraped review Timestamp.
Additionally, an execute.log
will be generated to record execution errors.
Set up a schedule for continuous execution
Set up a schedule (using crontab) to continuously scrape new reviews. ZReviewTender will scrape new reviews from the last scraped review Timestamp recorded in latestCheckTimestamp
to the current scraping time and update the Timestamp record file.
e.g. crontab: 15 */6 * * * ZReviewTender -r
Additionally, note that since the Android API only provides reviews added or edited in the last 7 days, the schedule cycle should not exceed 7 days to avoid missing reviews.
https://developers.google.com/android-publisher/reply-to-reviews#retrieving_a_set_of_reviews
Github Action Deployment
ZReviewTender App Reviews Automatic Bot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
name: ZReviewTender
on:
workflow_dispatch:
schedule:
- cron: "15 */6 * * *" # Runs every six hours, you can refer to the above crontab to change the settings
jobs:
ZReviewTender:
runs-on: ubuntu-latest
steps:
- name: ZReviewTender Automatic Bot
uses: ZhgChgLi/ZReviewTender@main
with:
command: '-r' # Executes Apple & iOS App review check, you can refer to the above to change to other execution commands
⚠️️️️️ Warning Again!
Be sure to ensure that your configuration files and keys cannot be publicly accessed, as the sensitive information within them could lead to App/Slack permissions being stolen; the author is not responsible for any misuse.
If any unexpected errors occur, please create an Issue with the log information, and it will be fixed as soon as possible!
Done
The tutorial ends here, next is the behind-the-scenes development story.
=========================
The War with App Reviews
I thought last year’s summary of AppStore APP’s Reviews Slack Bot and the related technology implementation of ZReviewsBot — Slack App Review Notification Bot would conclude the integration of the latest App reviews into the company’s workflow; unexpectedly, Apple updated the App Store Connect API this year, allowing this matter to continue evolving.
Last year’s solution for fetching Apple iOS/macOS App reviews:
- Public URL API (RSS) ⚠️: Cannot flexibly filter, provides limited information, has a quantity limit, and we occasionally encounter data disorder issues, very unstable; might be deprecated by the official in the future
- Using Fastlane — SpaceShip to encapsulate complex web operations and session management, fetching review data from the App Store Connection backend (equivalent to running a web simulator crawler to fetch data from the backend).
Following last year’s method, only the second method can be used, but the effect is not perfect; the session will expire, requiring manual periodic updates, and cannot be placed on the CI/CD server because the session will expire immediately if the IP changes.
important-note-about-session-duration by Fastlane
After receiving the news that Apple updated the App Store Connect API this year, I immediately started redesigning the new review bot. In addition to using the official API, I also optimized the previous architecture design and became more familiar with Ruby usage.
Issues encountered during the development of App Store Connect API
- The List All Customer Reviews for an App endpoint does not provide App version information.
It’s very strange, so I had to workaround by first hitting this endpoint to filter out the latest reviews, then hitting List All App Store Versions for an App & List All Customer Reviews for an App Store Version to combine the App version information.
Issues encountered during the development of AndroidpublisherV3
- The API does not provide a method to get all reviews, only reviews added/edited in the last 7 days.
- Also uses JWT to connect to Google API (without relying on related libraries e.g. google-apis-androidpublisher_v3)
- Here is an example of generating & using Google API JWT:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require "jwt"
require "time"
payload = {
iss: "client_email field in the GCP API service account key (*.json) file",
sub: "client_email field in the GCP API service account key (*.json) file",
scope: ["https://www.googleapis.com/auth/androidpublisher"].join(' '),
aud: "token_uri field in the GCP API service account key (*.json) file",
iat: Time.now.to_i,
exp: Time.now.to_i + 60*20
}
rsa_private = OpenSSL::PKey::RSA.new("private_key field in the GCP API service account key (*.json) file")
token = JWT.encode payload, rsa_private, 'RS256', header_fields = {kid:"private_key_id field in the GCP API service account key (*.json) file", typ:"JWT"}
uri = URI("token_uri field in the GCP API service account key (*.json) file")
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri)
request.body = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=#{token}"
response = https.request(request).read_body
bearer = result["access_token"]
### use bearer token
uri = URI("https://androidpublisher.googleapis.com/androidpublisher/v3/applications/APP_PACKAGE_NAME/reviews")
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Get.new(uri)
request['Authorization'] = "Bearer #{bearer}";
response = https.request(request).read_body
result = JSON.parse(response)
# success!
If you have any questions or suggestions, feel free to contact me.
===
===
This article was first published in Traditional Chinese on Medium ➡️ View Here