回答編集履歴
7
test
CHANGED
@@ -106,7 +106,7 @@
|
|
106
106
|
|
107
107
|
inputValue は 前2つ(jws_header, jws_payload)をピリオドで連結した文字列に一致しています。
|
108
108
|
|
109
|
-
したがって calculatedSignature の後ろ部分に連結している `signature` は、pythonサンプルコードの `encoded_signature` に該当することになるので、
|
109
|
+
したがって calculatedSignature の後ろ部分に連結している `signature` は、pythonサンプルコードの `encoded_signature` [=上記 (2) の行] に該当することになるので、
|
110
110
|
上記のように、
|
111
111
|
```js
|
112
112
|
function hmacSha256(text, key) {
|
6
test
CHANGED
@@ -115,4 +115,6 @@
|
|
115
115
|
};
|
116
116
|
```
|
117
117
|
というコードにすればよいのではないでしょうか。
|
118
|
+
|
119
|
+
つまり元の GAS コードでは、HMAC_SHA_256 で得られたバイト列を Hex 文字列に変えていますが、そうではなくて、得られたバイト列を BASE64 エンコードするのが正解かと思います。
|
118
120
|
|
5
test
CHANGED
@@ -104,7 +104,9 @@
|
|
104
104
|
```
|
105
105
|
に該当しています。
|
106
106
|
|
107
|
+
inputValue は 前2つ(jws_header, jws_payload)をピリオドで連結した文字列に一致しています。
|
108
|
+
|
107
|
-
したがって calculatedSignature の後ろ部分に連結している `signature` は、pythonサンプルコードの `encoded_signature` に該当するので、
|
109
|
+
したがって calculatedSignature の後ろ部分に連結している `signature` は、pythonサンプルコードの `encoded_signature` に該当することになるので、
|
108
110
|
上記のように、
|
109
111
|
```js
|
110
112
|
function hmacSha256(text, key) {
|
@@ -112,5 +114,5 @@
|
|
112
114
|
return Utilities.base64Encode(rowHash);
|
113
115
|
};
|
114
116
|
```
|
115
|
-
というコードにすればよいのではないか
|
117
|
+
というコードにすればよいのではないでしょうか。
|
116
118
|
|
4
test
CHANGED
@@ -86,7 +86,7 @@
|
|
86
86
|
|
87
87
|
+ hmacSha256 関数 → バイト列をBASE64エンコードしたものを返すように修正。
|
88
88
|
|
89
|
-
こちらは、
|
89
|
+
こちらは、途中途中で GAS のデバッグ出力と、サンプルの python コードでのデバッグ出力とを比較して検証してみました。
|
90
90
|
```python
|
91
91
|
signature = hmac.new(
|
92
92
|
secret_key.encode(),
|
3
test
CHANGED
@@ -104,7 +104,7 @@
|
|
104
104
|
```
|
105
105
|
に該当しています。
|
106
106
|
|
107
|
-
したがって calculatedSignature の後ろ部分に連結している `signature` は、pythonサンプルコードの encoded_signature に該当するので、
|
107
|
+
したがって calculatedSignature の後ろ部分に連結している `signature` は、pythonサンプルコードの `encoded_signature` に該当するので、
|
108
108
|
上記のように、
|
109
109
|
```js
|
110
110
|
function hmacSha256(text, key) {
|
2
test
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
const secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
7
7
|
const accountId = "xxxxxxxxxxx";
|
8
8
|
|
9
|
-
const header = `{"alg":"HS256",
|
9
|
+
const header = `{"alg":"HS256","kid":"${access_key}","typ":"text/plain"}`;
|
10
10
|
|
11
11
|
const hex_digest = sha256("");
|
12
12
|
const content_type = "";
|
@@ -77,7 +77,11 @@
|
|
77
77
|
---
|
78
78
|
|
79
79
|
# 変えたところ
|
80
|
-
+
|
80
|
+
+ header の半角スペースを削除(こちらは関係ないかもしれません。ただドキュメントのサンプルは、JSON文字列の半角スペースが削除された文字列をBASE64エンコードしたものになっていました。)
|
81
|
+
```diff
|
82
|
+
- const header = `{"alg": "HS256", "kid": "${access_key}", "typ": "text/plain"}`;
|
83
|
+
+ const header = `{"alg":"HS256","kid":"${access_key}","typ":"text/plain"}`;
|
84
|
+
```
|
81
85
|
|
82
86
|
|
83
87
|
+ hmacSha256 関数 → バイト列をBASE64エンコードしたものを返すように修正。
|
1
修正
test
CHANGED
@@ -1,7 +1,112 @@
|
|
1
|
+
下記ではいかがでしょうか。
|
1
2
|
```js
|
3
|
+
function importAdsReport() {
|
4
|
+
const today = new Date();
|
5
|
+
const access_key = "xxxxxxxxxxxx";
|
6
|
+
const secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
7
|
+
const accountId = "xxxxxxxxxxx";
|
8
|
+
|
9
|
+
const header = `{"alg":"HS256", "kid":"${access_key}","typ":"text/plain"}`;
|
10
|
+
|
11
|
+
const hex_digest = sha256("");
|
12
|
+
const content_type = "";
|
13
|
+
const payload_date = Utilities.formatDate(today, 'GMT', 'yyyyMMdd');
|
14
|
+
const canonical_url = `/api/v3/adaccounts/${accountId}/campaigns`;
|
15
|
+
const payload = `${hex_digest}\n${content_type}\n${payload_date}\n${canonical_url}`;
|
16
|
+
|
17
|
+
const inputValue = `${base64(header)}.${base64(payload)}`;
|
2
|
-
const signature =
|
18
|
+
const signature = hmacSha256(inputValue, secretKey);
|
19
|
+
const calculatedSignature = `${inputValue}.${signature}`;
|
20
|
+
|
21
|
+
const request_headers = {
|
22
|
+
"Date": Utilities.formatDate(today, 'GMT', 'E, dd MMM yyyy HH:mm:ss z'),
|
23
|
+
"Authorization": `Bearer ${calculatedSignature}`
|
24
|
+
}
|
25
|
+
|
26
|
+
const options = {
|
27
|
+
"method": "GET",
|
28
|
+
"headers": request_headers,
|
29
|
+
"muteHttpExceptions": true
|
30
|
+
};
|
31
|
+
|
32
|
+
const response = UrlFetchApp.fetch('https://ads.line.me' + canonical_url, options);
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* base64エンコード
|
37
|
+
* @param {string} input - エンコードしたい文字列
|
38
|
+
* @return {string} - base64エンコードされた文字列
|
39
|
+
*/
|
40
|
+
function base64(input) {
|
41
|
+
return Utilities.base64Encode(input, Utilities.Charset.UTF_8)
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* HMAC SHA 256でハッシュ化
|
46
|
+
* @param {string} text - ハッシュ化する文字列
|
47
|
+
* @param {string} key - ハッシュ化するシークレットキー
|
48
|
+
* @return {string} - ハッシュ値
|
49
|
+
*/
|
50
|
+
function hmacSha256(text, key) {
|
3
|
-
|
51
|
+
const rowHash = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_256, text, key);
|
4
|
-
inputValue,
|
5
|
-
|
52
|
+
return Utilities.base64Encode(rowHash);
|
53
|
+
};
|
54
|
+
|
55
|
+
/**
|
56
|
+
* SHA 256でハッシュ化
|
57
|
+
* @param {string} input - ハッシュ化する文字列
|
58
|
+
* @return {string} - ハッシュ値
|
59
|
+
*/
|
60
|
+
function sha256(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
|
+
}
|
6
75
|
```
|
76
|
+
|
77
|
+
---
|
78
|
+
|
79
|
+
# 変えたところ
|
80
|
+
+ const header の半角スペースを削除(こちらは関係ないかもしれません。ただドキュメントのサンプルは、JSON文字列の半角スペースが削除された文字列をBASE64エンコードしたものになっていました。)
|
81
|
+
|
82
|
+
|
83
|
+
+ hmacSha256 関数 → バイト列をBASE64エンコードしたものを返すように修正。
|
84
|
+
|
85
|
+
こちらは、もとのpython コードでの結果を比較してみると
|
86
|
+
```python
|
87
|
+
signature = hmac.new(
|
88
|
+
secret_key.encode(),
|
89
|
+
signing_input.encode(),
|
90
|
+
hashlib.sha256
|
91
|
+
).digest() # ---(1)
|
92
|
+
encoded_signature = encode_with_base64(signature) # ---(2)
|
93
|
+
token = "%s.%s.%s" % (jws_header, jws_payload, encoded_signature) # ---(3)
|
94
|
+
|
95
|
+
```
|
96
|
+
(1) は `Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_256, text, key);` の結果に一致しています。
|
97
|
+
また(3)は、質問者さんのGASコードを最初から読んでいくと、
|
98
|
+
```js
|
99
|
+
const calculatedSignature = `${inputValue}.${signature}`;
|
100
|
+
```
|
101
|
+
に該当しています。
|
102
|
+
|
103
|
+
したがって calculatedSignature の後ろ部分に連結している `signature` は、pythonサンプルコードの encoded_signature に該当するので、
|
104
|
+
上記のように、
|
105
|
+
```js
|
106
|
+
function hmacSha256(text, key) {
|
107
|
+
const rowHash = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_256, text, key);
|
108
|
+
return Utilities.base64Encode(rowHash);
|
109
|
+
};
|
110
|
+
```
|
7
|
-
と
|
111
|
+
というコードにすればよいのではないかと思いました。
|
112
|
+
|