naver / searchad-apidoc

http://naver.github.io/searchad-apidoc/
103 stars 74 forks source link

Invalid Signature 문의 #997

Closed jhn153228THM closed 1 month ago

jhn153228THM commented 1 month ago

안녕하세요 파이썬으로 masterAPI를 사용하고 있는데요. 개발 소스에서post함수와 get 함수가 같은 방식으로 시그니처를 만드는데 get 함수에서만 Invalid에러가 떠서 이유를 알수가 없어서 문의 남깁니다...

main.py

from naver_test_doc.master_api import MasterAPI
def main():
    master_api = MasterAPI(secret_manager=SecretManager())
    rep_post = master_api.post()                                     ### 성공
    master_report_id = rep_post["id"]
    master_report_status = rep_post["status"]
    print(f"master_report_id : {master_report_id}")
    print(f"master_report_status : {master_report_status}")

    while master_report_status in ("REGIST", "RUNNING"):
        print("report waiting")
        rep_get = master_api.get(master_report_id)          ### 실패
        master_report_status = rep_get["status"]
        print(f"check : id = {master_report_id}, status = {master_report_status}")
        time.sleep(5)

master_api.py

class MasterAPI:
    def __init__(self, secret_manager: SecretManager):
        self.secret_manager = secret_manager
        self.uri = "/master-reports"

    def post(self):
        method = "POST"
        req_header = self.secret_manager.get_header(method=method, uri=self.uri)
        req_param_item = {"item": "Campaign"}
        # print((self.secret_manager.base_url() + self.uri))
        # print(req_header)
        # print(req_param_item)
        response = requests.post(
            (self.secret_manager.base_url() + self.uri),
            headers=req_header,
            json=req_param_item,
        )
        if response.status_code != 201:
            print(f"Response Status Code: {response.status_code}")
            print(f"Response Body: {response.text}")
            response.raise_for_status()
        return response.json()

    def get(self, master_report_id):
        method = "GET"
        req_header = self.secret_manager.get_header(method=method, uri=self.uri)
        response = requests.get(
            (self.secret_manager.base_url() + self.uri + f"/{master_report_id}"),
            headers=req_header,
        )
        if response.status_code != 200:
            print(f"Response Status Code: {response.status_code}")
            print(f"Response Body: {response.text}")
            response.raise_for_status()
        return response.json()

SecretManager.py

class SecretManager:
    def get_header(self, method, uri) -> dict:
        timestamp = str(round(time.time() * 1000))
        print(f"timestamp : {timestamp}")
        signature = signaturehelper.Signature.generate(
            timestamp, method, uri, self._secret_key
        )
        return {
            "Content-Type": "application/json; charset=UTF-8",
            "X-Timestamp": timestamp,
            "X-API-KEY": self._api_key,
            "X-Customer": self._customer_id,
            "X-Signature": signature,
        }

signaturehelper.py

class Signature:

    @staticmethod
    def generate(timestamp, method, uri, secret_key):
        message = "{}.{}.{}".format(timestamp, method, uri)
        hash = hmac.new(
            bytes(secret_key, "utf-8"), bytes(message, "utf-8"), hashlib.sha256
        )
        hash.hexdigest()
        return base64.b64encode(hash.digest())

둘 다 같은방식으로 get_header로 API 요청을 하는데 원인을 알수 없네요..

response 내용 : requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://api.searchad.naver.com/master-reports/f2ccc33dd14476b0ba9d691dcc56b22e Response Status Code: 403 Response Body: {"signature":"W3PQRPYRnMDKYQGUN8XGe3XnPS7BzkQfirE8OG2YXhQ=","status":403,"type":"urn:naver:api:problem:invalid-signature","title":"Invalid Signature","detail":"Signature 'W3PQRPYRnMDKYQGUN8XGe3XnPS7BzkQfirE8OG2YXhQ=' is invalid."}

jhn153228THM commented 1 month ago

하핳 헤더 만들 때 리포트 ID도 추가해야 하네요

def get(self, master_report_id):
        method = "GET"
        req_header = self.secret_manager.get_header(
            method=method, uri=self.uri + f"/{master_report_id}"
        ) # 수정 부분
        response = requests.get(
            (self.secret_manager.base_url() + self.uri + f"/{master_report_id}"),
            headers=req_header,
        )
        if response.status_code != 200:
            print(f"Response Status Code: {response.status_code}")
            print(f"Response Body: {response.text}")
            response.raise_for_status()
        return response.json()