開発日記(2024/05/16)App Store Conect APIのsalesReportsが取得できない
<前回までのおさらい>GWを返上してApp Store Conect APIの仕様を理解したにも関わらず、いざリクエストを送ると500エラーが返ってきてしまうという悲しい事態に。。。
1日経っても状況変わらずなので、問い合わせてみる。「開発と技術」から「APIとキー」を選択。
まで開いて、あれ、、ひょっとして呼び出し方に問題があったのでは・・・と思い至る。。もう一回公式ドキュメントに戻ると・・・
ほら、パラメーター必要って書いてあるじゃん。
ぎゃー、、まじか。助けてGPTえもん。で、生成いただいたコードが下記。
const jwt = require('jsonwebtoken');
const fs = require('fs');
const axios = require('axios');
// 秘密鍵の読み込み
const privateKey = fs.readFileSync('ここに秘密鍵のファイル.p8', 'utf8');
// ヘッダ情報
const header = {
alg: 'ES256',
kid: 'ここはkey ID',
typ: 'JWT'
};
// ペイロード情報
const payload = {
iss: 'ここはIssuer ID',
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000 + 20 * 60),
aud: 'appstoreconnect-v1'
};
// JWTトークンの生成
const token = jwt.sign(payload, privateKey, { algorithm: 'ES256', header: header });
// パラメータ
const params = {
'filter[frequency]': 'DAILY',
'filter[reportDate]': '2023-10-22',
'filter[reportSubType]': 'SUMMARY',
'filter[reportType]': 'SALES',
'filter[vendorNumber]': 'ここはベンダー番号'
};
// アクセス先のエンドポイント
const api_url = '<https://api.appstoreconnect.apple.com/v1/salesReports>';
// API リクエストの送信
axios.get(api_url, {
headers: {
Authorization: `Bearer ${token}`,
Accept: '*/*'
},
params: params
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
ぐあ・・・普通に返ってくるじゃん。。ぼくが悪かったです。すみません。。。
そういえば返却値はgzipみたいな話がありましたね・・・
何度か調整して下記に落ちつく。
const jwt = require('jsonwebtoken');
const fs = require('fs');
const axios = require('axios');
const zlib = require('zlib');
// 秘密鍵の読み込み
const privateKey = fs.readFileSync('ここに秘密鍵のファイル.p8', 'utf8');
// ヘッダ情報
const header = {
alg: 'ES256',
kid: 'ここはkey ID',
typ: 'JWT'
};
// ペイロード情報
const payload = {
iss: 'ここはIssuer ID',
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000 + 20 * 60),
aud: 'appstoreconnect-v1'
};
// JWTトークンの生成
const token = jwt.sign(payload, privateKey, { algorithm: 'ES256', header: header });
// パラメータ
const params = {
'filter[frequency]': 'DAILY',
'filter[reportDate]': '2023-10-22',
'filter[reportSubType]': 'SUMMARY',
'filter[reportType]': 'SALES',
'filter[vendorNumber]': 'ここはベンダー番号'
};
// アクセス先のエンドポイント
const api_url = '<https://api.appstoreconnect.apple.com/v1/salesReports>';
// TSVをJSONに変換する関数
function tsvToJson(tsv) {
const lines = tsv.split('\\n');
const headers = lines[0].split('\\t');
return lines.slice(1).map(line => {
const data = line.split('\\t');
return headers.reduce((obj, header, index) => {
obj[header] = data[index];
return obj;
}, {});
});
}
// API リクエストの送信
axios.get(api_url, {
headers: {
Authorization: `Bearer ${token}`,
Accept: '*/*',
'Accept-Encoding': 'gzip' // gzipでの圧縮を受け入れる
},
params: params,
responseType: 'arraybuffer' // バイナリデータとしてレスポンスを受け取る
})
.then(response => {
// gzip解凍
zlib.gunzip(response.data, (err, buffer) => {
if (err) {
console.error('解凍エラー:', err);
return;
}
const tsvData = buffer.toString();
const jsonData = tsvToJson(tsvData);
// JSONデータをコンソールに出力
console.log(JSON.stringify(jsonData, null, 2));
});
})
.catch(error => {
console.error('リクエストエラー:', error.response ? error.response.data : error.message);
});
結果!わ〜返ってきた〜!
パラメーターに指定の日付を動的に変えねばですね。ということで、前日の値を設定して欲しいので、
dconst jwt = require('jsonwebtoken');
const fs = require('fs');
const axios = require('axios');
const zlib = require('zlib');
// 秘密鍵の読み込み
const privateKey = fs.readFileSync('ここに秘密鍵のファイル.p8', 'utf8');
// ヘッダ情報
const header = {
alg: 'ES256',
kid: 'ここはkey ID',
typ: 'JWT'
};
// ペイロード情報
const payload = {
iss: 'ここはIssuer ID',
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000 + 20 * 60),
aud: 'appstoreconnect-v1'
};
// JWTトークンの生成
const token = jwt.sign(payload, privateKey, { algorithm: 'ES256', header: header });
// 前日の日付を取得する関数
function getYesterdayDate() {
const date = new Date();
date.setDate(date.getDate() - 1);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため、+1する
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
// パラメータ
const params = {
'filter[frequency]': 'DAILY',
'filter[reportDate]': getYesterdayDate(),
'filter[reportSubType]': 'SUMMARY',
'filter[reportType]': 'SALES',
'filter[vendorNumber]': 'ここはベンダー番号'
};
// アクセス先のエンドポイント
const api_url = '<https://api.appstoreconnect.apple.com/v1/salesReports>';
// TSVをJSONに変換する関数
function tsvToJson(tsv) {
const lines = tsv.split('\\n');
const headers = lines[0].split('\\t');
return lines.slice(1).map(line => {
const data = line.split('\\t');
return headers.reduce((obj, header, index) => {
obj[header] = data[index];
return obj;
}, {});
});
}
// API リクエストの送信
axios.get(api_url, {
headers: {
Authorization: `Bearer ${token}`,
Accept: '*/*',
'Accept-Encoding': 'gzip' // gzipでの圧縮を受け入れる
},
params: params,
responseType: 'arraybuffer' // バイナリデータとしてレスポンスを受け取る
})
.then(response => {
// gzip解凍
zlib.gunzip(response.data, (err, buffer) => {
if (err) {
console.error('解凍エラー:', err);
return;
}
const tsvData = buffer.toString();
const jsonData = tsvToJson(tsvData);
// JSONデータをコンソールに出力
console.log(JSON.stringify(jsonData, null, 2));
});
})
.catch(error => {
if (error.response && error.response.data) {
const errorMessage = error.response.data.toString('utf8');
console.error('リクエストエラー:', errorMessage);
} else {
console.error('リクエストエラー:', error.message);
}
});
成功!ダウンロード数がゼロの日は404が返るそうなので、挙動としては正常ですね。
ではこれをGCFにアップロードしていただいて、、、あ、でもそれだとテストができないので、、、一旦は日付は固定値でテストしてみる感じかな???
次回で完成させたいなあ・・・
ご覧いただきありがとうございます。とても嬉しいです。