1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【iOS】App Store Connect API アプリのダウンロード数をLINEへ通知する

Last updated at Posted at 2024-09-20

自己紹介

個人開発でいくつかアプリをリリースしている者です。

LINE通知までの経緯

ダウンロード数のチェックでApp Store Connectに頻繁にアクセスするのですが、都度チェックしに行くのは面倒!

よし、LINEに通知してくれるようなアプリを作ってみようということで、作りました。

使用技術、言語

  • Google Cloud Functions
  • Python
  • LINE Notify

(2024/10/25追加)
LINE Notifyはサービス提供が2025年3月31日に終了します。
https://notify-bot.line.me/closing-announce
よく確認してから、お使いください。
私はこの記事投稿後にSlackへ通知するように修正しました。

構成図

スクリーンショット 2024-09-20 11.21.30.png

CloudFunctions

ここで情報の取得〜LINE通知まで全て行います。
大まかな流れです。

  • JWTトークンの作成
  • App Store Connect APIへリクエスト
  • レスポンス情報の加工
  • LINE Notify経由でLINEへ通知

基本的なApp Store Connect APIの使い方は調べたら出てくるので注意点のみ記載します。

利用ライブラリ

requirements.txt
functions-framework==3.*
pyjwt==2.8.0
requests==2.31.0
cryptography==41.0.5
pandas==2.2.2

App Store Connect APIへリクエスト

リクエスト先
https://api.appstoreconnect.apple.com/v1/salesReports
リファレンス

毎日実行して、昨日のデータを取得する方針だったのですが、ここで問題が。

昨日のデータを取得しようとすると、404エラーになる!

Daily reports are available the following day.
Reports are generally available by 8 a.m. Pacific Time (PT).

(日本語訳)
日次レポートは翌日からご利用いただけます。
レポートは通常、太平洋標準時 (PT) の午前 8 時までに利用可能になります。

太平洋標準時と日本時間で時差が17時間あるため、レポートは2日後の午前1時以降に取得する必要があります。
9月18日のレポート情報が欲しければ、9月21日の午前1時以降ということです。

前日のレポートが取得できないのは、辛いですが、しゃーなしということで、2日前のデータを取得するようにしています。

App Store Connect APIへリクエストするときのヘッダーはこんな感じです。

  two_days_ago = (datetime.now() - timedelta(2)).strftime('%Y-%m-%d')
  params = {
  'filter[frequency]': 'DAILY',
  'filter[reportSubType]': 'SUMMARY',
  'filter[reportType]': 'SALES',
  'filter[reportDate]': two_days_ago,
  'filter[vendorNumber]': vender_no # App Store Connectから取得
  }

レスポンス情報の加工

コンテンツの形式が application/a-gzipGZIP形式 になっています。

なので、解凍して、LINEで通知して欲しい文字列に加工します。
参考にコードを載せてますが、コードは全てChatGPTさんにお願して作りました。
参考程度に。

# AppStoreConnectAPIからのレスポンス
response = requests.get(url, headers=headers, params=params)

# レスポンスの解凍
compressed_data = BytesIO(response.content)
with gzip.GzipFile(fileobj=compressed_data) as decompressed_file:
  # 解凍されたデータを読み込む
  decompressed_data = decompressed_file.read()

# 解凍されたデータを加工
tsv_data = decompressed_data.decode('utf-8')
df = pd.read_csv(StringIO(tsv_data), sep='\t')

# データの集計用の辞書
results = {}
# DataFrameをループしてデータを集計
for _, row in df.iterrows():
  title = row['Title']
  product_type = row['Product Type Identifier']
  units = row['Units']
  
  # タイプを取得
  product_type_desc = product_type_map.get(product_type, '未知のタイプ')

  # タイトルのキーが存在しない場合は追加
  if title not in results:
      results[title] = {'ダウンロード': 0, 'アップデート': 0, 'App 内課金': 0, '再ダウンロード': 0}

  # 集計
  if product_type_desc == '再ダウンロード':
      results[title]['再ダウンロード'] += units
  elif product_type_desc == 'アップデート':
      results[title]['アップデート'] += units
  elif product_type_desc == 'App 内課金':
      results[title]['App 内課金'] += units
  else:  # デフォルトはダウンロード
      results[title]['ダウンロード'] += units

# 結果を文字列に整形
result_str = f"{two_days_ago}"
for title, metrics in results.items():
  result_str += f"\n{title}"
  for metric, value in metrics.items():
      if value > 0:
          result_str += f"\n {metric}{value}"


データの中にあるプロダクトIDは下記のタイプに紐づいてます。
product_type_mapはここの情報を元に変換してます。
https://developer.apple.com/jp/help/app-store-connect/reference/product-type-identifiers/

LINE Notify経由でLINEへ通知

ここは単純にLINE NotifyのAPIを呼び出すだけです。

LINEのメッセージのイメージはこんな感じです。

現状は、毎朝9時30分にCloud SchedulerとCloud Pub/Subで定期実行するようにしています。

最後に

実際に通知が来ると、モチベアップになりますね!
引き続き個人開発とか頑張っていきます〜。

参考

https://zenn.dev/yamazaking/articles/eedf5e9179d46a
https://dev.classmethod.jp/articles/try-cloud-functions-scheduler-pubsub/

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?