質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JWT(JSON Web Token)

JWT(JSON Web Token)とは、JSONをベースとしたアクセストークンの仕様。電子署名付きのURL safeなJSONのことを指します。電子署名が付いているため、改ざんをチェックできる点がメリットです。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

0回答

360閲覧

GASからLINE Ads APIを使用してLINEの広告成果をスプレッドシートに取得したい

tororo_mmm

総合スコア0

JWT(JSON Web Token)

JWT(JSON Web Token)とは、JSONをベースとしたアクセストークンの仕様。電子署名付きのURL safeなJSONのことを指します。電子署名が付いているため、改ざんをチェックできる点がメリットです。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2023/05/25 12:59

解決したいこと

  • LINEから毎日表示回数などの広告指標をスプレッドシートに自動連携したい
  • そのためにGASからLINE Ads APIを使用して、データの取得がしたい

発生しているエラー

Exception: Request failed for https://ads.line.me returned code 404. Truncated server response: {"errors":[{"reason":"Not Found"}]} (use muteHttpExceptions option to examine full response)

試したこと

ドキュメントの例題にある、条件で計算し、Signatureが一致することまでは確かめることができているのでハッシュの計算は間違えていないかと思います。

ドキュメント:
https://ads.line.me/public-docs/pages/v3/3.9.5/certificated-ad-tech-general-partner/#_without_request_body

手元のPythonでは同じような実装をしており、データの取得が問題なくできています。

エラーの原因かと思っているところ

tokenの値などPythonと一致していることは確認できているので、
GASから送ることが問題なのではないかと疑っているのですが、解決できず。。。
もし何かご存知のかたいらっしゃればご教授いただけると大変助かります。。。。
よろしくお願いいたします。。。!

GASのコード

JavaScript

1function main() { 2 const today = new Date(); 3 4 const access_key = "XXXXXXX"; 5 const secret_key = "XXXXXXX"; 6 const method_type = "GET"; 7 const reportLevel ="adgroup"; 8 const accountId="XXXXXXXX"; 9 const canonical_url = `/api/v3/adaccounts/${accountId}/reports/online/${reportLevel}`; 10 const url_parameters = "?since=2023-04-28&until=2023-04-29"; 11 const request_body = ""; 12 13 14 const endpoint = "https://ads.line.me" + canonical_url + url_parameters; 15 16 const request_body_json = JSON.stringify(request_body).replace(/:/g, ': ').replace(/,/g, ', '); 17 const header = `{"alg":"HS256","kid":"${access_key}","typ":"text/plain"}` 18 const jws_header = encode_with_base64(header); 19 20 // make payload 21 const hex_digest = calc_sha256_digest(request_body_json); 22 console.log("hex") 23 console.log(request_body_json) 24 const content_type = ""; 25 const payload_date = Utilities.formatDate(today, 'GMT', 'yyyyMMdd'); 26 const payload = `${hex_digest}\n${content_type}\n${payload_date}\n${canonical_url}`; 27 console.log(payload) 28 29 const jws_payload = encode_with_base64(payload); 30 const signing_input = `${jws_header}.${jws_payload}`; 31 const encoded_signature = hmacSha256(secret_key, signing_input); 32 const token = `${jws_header}.${jws_payload}.${encoded_signature}`; 33 34 console.log(token); 35 console.log(endpoint); 36 37 const http_headers = { 38 "Content-Type":"", 39 "Date": Utilities.formatDate(today, 'GMT', 'E, dd MMM yyyy HH:mm:ss z'), 40 "Authorization": `Bearer ${token}` 41 } 42 console.log(http_headers); 43 44 const resp = UrlFetchApp.fetch(endpoint, { 45 "Accept-Encoding": "identity", 46 "payload": request_body_json, 47 headers: http_headers, 48 method: method_type 49 }); 50 51 console.log(resp) 52 console.log(resp.getContentText()); 53} 54 55/** 56 * SHA 256でハッシュ化 57 * @param {string} input - ハッシュ化する文字列 58 * @return {string} - ハッシュ値 59 */ 60function calc_sha256_digest(input) { 61 const rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, input, Utilities.Charset.UTF_8); 62 let txtHash = ''; 63 for (i = 0; i < rawHash.length; i++) { 64 let hashVal = rawHash[i]; 65 if (hashVal < 0) { 66 hashVal += 256; 67 } 68 if (hashVal.toString(16).length == 1) { 69 txtHash += '0'; 70 } 71 txtHash += hashVal.toString(16); 72 } 73 return txtHash 74} 75 76/** 77 * base64エンコード 78 * @param {string} input - エンコードしたい文字列 79 * @return {string} - base64エンコードされた文字列 80 */ 81function encode_with_base64(input) { 82 return Utilities.base64Encode(input, Utilities.Charset.UTF_8) 83} 84 85/** 86 * HMAC SHA 256でハッシュ化 87 * @param {string} key - ハッシュ化するシークレットキー 88 * @param {string} text - ハッシュ化する文字列 89 * @return {string} - ハッシュ値 90 */ 91function hmacSha256(key, text) { 92 const rowHash = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_256, text, key); 93 return Utilities.base64Encode(rowHash); 94}; 95

Pythonのコード

Python

1from datetime import datetime as dt 2from datetime import timedelta 3 4import base64 5import datetime 6import hashlib 7import hmac 8import json 9import urllib.request 10 11def calc_sha256_digest(content: str) -> str: 12 sha256 = hashlib.new('sha256') 13 sha256.update(content.encode()) 14 return sha256.hexdigest() 15 16 17def encode_with_base64(value: bytes) -> str: 18 return base64.urlsafe_b64encode(value).decode() 19 20 21access_key = "XXXXXX" 22secret_key = "XXXXXX" 23accountId="XXXXXX" 24reportLevel ="adgroup" 25canonical_url = "/api/v3/adaccounts/"+accountId+"/reports/online/"+reportLevel 26url_parameters = "?since=2023-04-28&until=2023-04-29" 27 28 29endpoint = 'https://ads.line.me' + canonical_url + url_parameters 30method = "GET" 31 32 33request_body_json = "" 34content_type = "" 35 36jws_header = encode_with_base64( 37 json.dumps({ 38 "alg": "HS256", 39 "kid": access_key, 40 "typ": "text/plain", 41 }).encode() 42) 43 44hex_digest = calc_sha256_digest(request_body_json) 45payload_date = datetime.datetime.utcnow().strftime('%Y%m%d') 46payload = "%s\n%s\n%s\n%s" % (hex_digest, content_type, payload_date, canonical_url) 47jws_payload = encode_with_base64(payload.encode()) 48 49datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') 50 51signing_input = "%s.%s" % (jws_header, jws_payload) 52 53signature = hmac.new( 54 secret_key.encode(), 55 signing_input.encode(), 56 hashlib.sha256 57).digest() 58 59encoded_signature = encode_with_base64(signature) 60 61token = "%s.%s.%s" % (jws_header, jws_payload, encoded_signature) 62UAEmdDd8N5axfqpR0EkkRVheoeyAyPEDCX0g)" 63http_headers = { 64 "Date": datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'), 65 "Authorization": "Bearer %s" % token, 66} 67 68req = urllib.request.Request(endpoint, headers=http_headers, method=method) 69 70with urllib.request.urlopen(req) as res: 71 resp = res.read() 72print(resp.decode()) 73 74resp

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

CHERRY

2023/05/26 21:59 編集

> returned code 404. なので、アクセスしているURL に問題がないでしょうか。 生成しているURL を確認するとどのようなURL になっていますか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問