Handling Notification Responses from APNs

Panther·2021년 8월 17일
0

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/handling_notification_responses_from_apns

"Respond to the status codes that the APNs servers return."

APNs 서버가 반환한 상태 코드에 응답합니다.

Overview

애플 푸시 노티피케이션 서비스(APNs)는 서버가 전송하는 각 POST 요청에 응답을 제공합니다. 각 응답은 응답의 상태를 나타내는 필드를 갖는 헤더를 포함합니다. 요청이 성공적이었다면 응답의 바디는 비어있습니다. 에러가 발생하면 바디는 에러에 대한 추가적인 정보를 갖는 JSON 딕셔너리를 포함합니다.

기기가 노티피케이션을 받는 데 문제를 갖고 있다면, Troubleshoot Problems with Receiving Notifications에서 리스트로 나타나 있는 일반적인 문제들을 보시기 바랍니다.

Troubleshoot Problems with Receiving Notifications는 이 글의 아래에 나옵니다.

Interpret Header Responses

Table 1은 헤더 응답에서 키의 의미를 설명하고 있습니다.

Table 1 Header keys

Header nameValue
apns-id요청 헤드의 apns-id 필드에서 발견되는 같은 값입니다. 노티피케이션을 식별하기 위해 이 값을 사용하시기 바랍니다. 요청에서 apns-id 필드를 구체화하지 않으면 APNs는 새로운 UUID를 생성하고 이 헤더에 UUID를 반환합니다.
:statusHTTP 상태코드입니다.

Table 2는 응답의 :status 헤더에서 가능한 값을 리스트로 보여줍니다.

Table 2 HTTP status codes

Status codeDescription
200Success.
400Bad request.
403인증서 혹은 제공자의 인증 토큰에 에러가 있습니다.
404요청이 유효하지 않은 :path 값을 포함하고 있습니다.
405요청이 유효하지 않은 :method 값을 사용했습니다. POST 요청만 지원됩니다.
410기기 토큰이 더 이상 주제에서 활성화되지 않습니다.
413노티피케이션 페이로드가 너무 큽니다.
429서버가 같은 기기 토큰에 대한 너무 많은 요청을 받았습니다.
500내부 서버 에러입니다.
503서버가 닫혀있고 사용이 불가능합니다.

Understand Error Codes

Table 3은 요청 실패의 경우에 대해 JSON 딕셔너리에서 찾을 수 있는 키를 리스트로 보여주고 있습니다. JSON 데이터는 연결이 종료될 때 GOAWAY 프레임에 포함될 것입니다.

Table 3 Response keys

KeyDescription
reason실패 이유를 나타내는 에러 코드(스트링으로 구체화된)입니다.
timestamp에포크로부터 밀리세컨드로 나타나는 시간으로, APNs가 주제에 대해 더 이상 유효하지 않은 토큰이라고 확인한 시점입니다. 이 키는 에러가 :status 필드에서 410일 때만 포함됩니다.

Table 4는 응답의 JSON 페이로드 원인 키에 포함된 가능한 에러 코드를 리스트로 보여줍니다.

Table 4 Response error strings

Status codeError stringDescription
400BadCollapseIDcollapse 아이덴티파이어가 허용된 최대 크기를 초과합니다.
400BadDeviceToken구체화된 기기 토큰이 유효하지 않습니다. 요청이 유효한 토큰을 포함하는지 검증해야 하고, 토큰이 환경과 일치하는지 확인해야 합니다.
400BadExpirationDateapns-expiration 값이 유효하지 않습니다.
400BadMessageIdapn-id 값이 유효하지 않습니다.
400BadPriorityapns-priority 값이 유효하지 않습니다.
400BadTopicapns-topic 값이 유효하지 않습니다.
400DeviceTokenNotForTopic기기 토큰이 구체화된 주제와 일치하지 않습니다.
400DuplicateHeaders하나 혹은 하나 이상의 헤더가 반복됩니다.
400IdleTimeoutidle 타임아웃입니다.
400InvalidPushTypeapns-push-type 값이 유효하지 않습니다.
400MissingDeviceToken기기 토큰이 요청 :path에서 구체화되지 않습니다. :path 헤더가 기기 토큰을 포함하는지 검증해야 합니다.
400MissingTopic요청의 apns-topic 헤더가 구체화되지 않고 요구되지 않습니다. apns-topic 헤더는 클라이언트가 여러 주제를 지원하는 인증을 사용해서 연결될 때 필수입니다.
400PayloadEmpty메시지 페이로드가 비어있습니다.
400TopicDisallowed이 주제를 푸시하는 것이 허용되지 않습니다.
403BadCertificate인증서가 유효하지 않습니다.
403BadCertificateEnvironment클라이언트 인증서가 잘못된 환경을 위한 것입니다.
403ExpiredProviderToken제공자 토큰이 오래되어 새 토큰을 생성해야 합니다.
403Forbidden구체화된 액션이 허용되지 않습니다.
403InvalidProviderToken제공자 토큰이 유효하지 않거나 토큰 시그니처가 검증될 숭수 없습니다.
403MissingProviderTokenAPNs에 연결하기 위해 제공자 인증서가 사용되지 않았으며, 인증 헤더를 잃어버렸거나 제공자 토큰이 구체화되지 않았습니다.
404BadPath요청이 유효하지 않은 :path 값을 포함합니다.
405MethodNotAllowed구체화된 :method 값이 POST가 아닙니다.
410unregistered기기 토큰이 특정 주제에서 비활성화입니다. 애플리케이션이 같은 기기 토큰을 가져오지 않는 한 같은 기기 토큰에 푸시를 보낼 필요가 없습니다. Registering Your App with APNs를 보시기 바랍니다.
413PayloadTooLarge메시지 페이로드가 너무 큽니다. 허용된 페이로드 크기에 대한 정보는 Create and Send a POST Request to APNs를 보시기 바랍니다.
429TooManyProviderTokenUpdates제공자의 인증 토큰이 지나치게 자주 업데이트되고 있습니다. 20분 안에 한 번 이상의 인증 토큰 업데이트를 하지 않아야 합니다.
429TooManyRequests같은 기기 토큰에 너무 많은 요청이 연속적으로 만들어졌습니다.
500InternalServerError내부 서버 에러가 발생했습니다.
503ServiceUnavailable서비스가 사용 불가능합니다.
503ShutdownAPNs 서버가 닫혀있습니다.

Registering Your App with APNs
https://developer.apple.com/documentation/usernotifications/registering_your_app_with_apns
https://velog.io/@panther222128/Registering-Your-App-with-APNs

Create and Send a POST Request to APNs
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns#2947607
https://velog.io/@panther222128/Sending-Notification-Requests-to-APNs

Listing 1은 성공적인 푸시 요청에 대한 샘플 응답을 보여주고 있습니다.

Listing 1 A successful response

HEADERS
  + END_STREAM
  + END_HEADERS
  apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
  :status = 200

Listing 2는 에러가 발생했을 때 샘플 응답을 보여주고 있습니다.

Listing 2 An error response

HEADERS
  - END_STREAM
  + END_HEADERS
  :status = 400
  content-type = application/json
  apns-id: <a_UUID>
DATA
  + END_STREAM
  { "reason" : "BadDeviceToken" }

Troubleshoot Problems with Receiving Notifications

테스트를 하는 동안 테스트 기기가 제공자 서버에서 전송된 푸시 노티피케이션을 받지 못하고 있다면 아래 가능한 원인을 생각해보시기 바랍니다.

  • 제공자 서버가 테스트 기기에 대한 최신 기기 토큰을 가지고 있는지 확인해야 합니다. 앱이 launch될 때마다 현재 토큰을 요청해야 하고 해당 토큰을 제공자 서버에 전달해야 합니다. APNs가 에러를 알려주고 있는지 확인하기 위해 적합한 실패 핸들러 메소드를 구현해야 합니다. Registering Your App with APNs를 보시기 바랍니다.
  • APNs에 의해 반환된 에러를 확인합니다. 실패가 발생하면 APNs는 제공자 서버로 적합한 에러를 알려줍니다. 적합한 액션을 결정하기 위해 에러 코드를 사용하시기 바랍니다.
  • 요청 헤더에 apns-push-type 키를 포함시켰는지 화인해야 합니다. 이 키는 watchOS 6에서부터 요구됩니다. 이 키의 부재는 노티피케이션의 전달을 지연시키거나 전달을 방지합니다. Table 1을 보시기 바랍니다.
  • 같은 기기에 너무 빠르게 요청을 보내고 있는지 확인해야 합니다. APNs는 각 기기에 한 노티피케이션만 큐에 넣으며, 기기는 APNs가 큐에서 빼기 전에 노티피케이션의 수용을 허용해야 합니다. 짧은 시간 안에 여러 노티피케이션 요청을 보내면 각각의 새로운 요청은 이전 요청을 덮어 씁니다.
  • 조용한 노티피케이션이 조절되고 있는지 확인해야 합니다. APNs는 제한된 수의 조용한 노티피케이션(컨텐트를 갖는) 키를 보냅니다. 더불어 기기가 이미 하루의 전력 예산을 초과한 경우 조용한 노티피케이션은 전원 예산이 재설정(하루에 한 번 발생하는)되기까지 다시 보내지지 않습니다. 이러한 제한은 Xcode에서 앱을 테스트할 때는 비활성화됩니다. Pushing Background Updates to Your App을 보시기 바랍니다.
  • 서버 및 기기의 방화벽 설정을 확인하시기 바랍니다. 노티피케이션을 보내려면 바이너리 인터페이스를 사용하는 경우 제공자 서버는 인바운드 및 아웃바운드 TCP 패킷을 HTTP/2 연결에 대한 포트 443에 허용해야 하거나, 포트 2195에 허용해야 합니다. 와이파이를 거쳐 APNs에 연결하는 기기는 포트 5223에 인바운드 및 아웃바운드 TCP 패킷을 허용할 필요가 있으며, 5223 포트를 사용할 수 없는 경우 포트 443에 폴백합니다.
  • 기기를 스패밍하지 않고 있다는 것을 검증해야 합니다. 짧은 시간 안에 너무 많은 노티피케이션을 같은 기기에 보내면 APNs는 이를 denial-of-service로 처리하고 일시적으로 노티피케이션 전송으로부터 서버를 막습니다.

Pushing Background Updates to Your App
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns
https://velog.io/@panther222128/Pushing-Background-Updates-to-Your-App

제공자 서버가 APNs에 연결할 수 없다면, 아래 가능한 원인을 생각해보시기 바랍니다.

  • 제공자 서버에 설치된 필요한 인증서를 갖고 있는지 확인해야 합니다. 제공자 서버가 TLS/SSL 유효성에 적합한 인증서를 갖고 있지 않다면 APNs에 연결할 수 없습니다. 인증서 기반 연결의 경우 제공자 서버는 애플로부터 가져온 인증서도 가지고 있어야 합니다. Establishing a Certificate-Based Connection to APNs를 보시기 바랍니다.
  • 제공자 서버가 APNs에 얼마나 자주 연결하고 있는지 확인해야 합니다. 제공자 서버가 APNs 연결을 반복적으로 열고 닫으면, APNs는 이를 denial-of-service 공격으로 처리하고 일시적으로 연결로부터 서버를 막습니다.

서버로부터 OpenSSL s_client 명령을 실행시켜 제공자 서버와 APNs 사이의 TLS handshake를 검증할 수 있습니다. Listing 3에서 보여주고 있습니다. 또한, 이 명령은 TLS/SSL 인증서가 만료되었는지 혹은 취소되었는지를 보여주기도 합니다.

Listing 3 Verifying the TLS handshake

$ openssl s_client -connect api.development.push.apple.com:443 -cert YourSSLCertAndPrivateKey.pem -debug 
-showcerts -CAfile server-ca-cert.pem

See Also


Server Tasks

Generating a Remote Notification

JSON 페이로드로 사용자의 기기에 노티피케이션을 전송합니다.

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
https://velog.io/@panther222128/Generating-a-Remote-Notification

Sending Notification Requests to APNs

애플 푸시 노티피케이션 서비스(APNs)에 원격 노티피케이션 페이로드 및 기기 토큰 정보를 전송합니다.

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns
https://velog.io/@panther222128/Sending-Notification-Requests-to-APNs

Pushing Background Updates to Your App

앱을 깨우고 백그라운드에서 업데이트하는 노티피케이션을 전달합니다.

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app
https://velog.io/@panther222128/Pushing-Background-Updates-to-Your-App


0개의 댓글