Hello,
I am encountering an intermittent TopicDisallowed error while using APNs and would like to ask for your assistance.
Environment:
Authentication: We are using certificate-based authentication with APNs, where the PEM file is stored on the server to authenticate our requests.
API: We are using the HTTP/2 API and calling the /3/device/<device_token> endpoint while passing the apns-topic in the request header.
Issue:
After renewing our APNs certificate, the new certificate mistakenly included an incorrect app bundle ID, resulting in a TopicDisallowed error.
We then issued a new certificate with the correct bundle ID and replaced it on our server before resuming remote push requests.
However, even after replacing the certificate, we are still intermittently receiving the TopicDisallowed error, while other requests successfully return a 200 OK response and deliver notifications to devices.
Over time, the frequency of TopicDisallowed responses has been decreasing, leading us to speculate that APNs might be caching responses and updating this cache over time.
Questions:
Could you provide details on the specific conditions or causes that lead to a TopicDisallowed error?
After replacing the certificate, is there a reason why we might still be intermittently receiving this error? Are there additional certificate or configuration settings we should check?
What might cause some requests to succeed with a 200 OK response, while others result in a TopicDisallowed error with the same setup?
Is it possible that APNs could be caching outdated information from the previous certificate, which might explain the decreasing frequency of the errors?
We have reviewed our certificate and configuration after the renewal, but the issue persists. Any guidance on how to further troubleshoot or resolve this would be greatly appreciated.
Thank you.
User Notifications
RSS for tagPush user-facing notifications to the user's device from a server or generate them locally from your app using User Notifications.
Posts under User Notifications tag
153 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hi Apple Engineers,
Is there an outage of the sandbox API for push notifications?
Since 3:00 AM (CEST) today, I haven’t received any notifications on my test devices.
The app declares support for Voice-over IP (VoIP) in the UIBackgroundModes key in your Info.plist, but we are still unable to locate any VoIP services. Apps that declare support for VoIP in the UIBackgroundModes key in your Info.plist file must have features that require VoIP.
My app rejected for VOIP and the app is totally supported video call or call when app is terminated or in background how can. i solve that rejection issue
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
User Notifications
PushKit
CallKit
Background Assets
Hi,
since at least yesterday api.sandbox.push.apple.com is not available.
It was working before, but now it seems the domain can't be resolved.
I tried nslookup in the terminal.
nslookup api.sandbox.push.apple.com
** server can't find api.sandbox.push.apple.com: NXDOMAIN
Lookup of the production server works:
nslookup api.push.apple.com
Non-authoritative answer:
api.push.apple.com canonical name = api-vs.push-apple.com.akadns.net.
Name: api-vs.push-apple.com.akadns.net
Address: 17.188.180.206
Name: api-vs.push-apple.com.akadns.net
Address: 17.188.180.76
Name: api-vs.push-apple.com.akadns.net
Address: 17.188.180.138
Name: api-vs.push-apple.com.akadns.net
Address: 17.188.182.203
Name: api-vs.push-apple.com.akadns.net
Address: 17.188.180.78
Anyone having the same problem?
Back story: I'm developing an app that communicates with a personal medical device. We use critical alerts when we have hardware issues that could result in harm to the patient. The audio file is a 30 second file to make sure the patient is aware. If the app is open when they occur, we pop up a modal message in the app. When the user dismisses the notice, we call UNNotificationCenter::removeDeliveredNotifications(withIdentifiers:) to remove the critical alert and also to stop the audio file that is playing.
This normally works fine. However we discovered that if the patient leaves critical alert enabled but disables notifications for our app, that we can still post the critical alert and it goes off. However when the user dismisses the message, the removeDeliveredNotifications call does not work. I did some debugging and if call getDeliveredNotifications with this permission combination, it return 0 (normally it would return 1).
Does anyone know of another way to remove the critical alert in this situation? (or should I be submitting this as a bug?)
I have been trying to implement APNS Push Notifications into the iOS App I'm currently developing, and I'm having issues with notifications sent via my custom server not being delivered. I have built and ran the App on my device (iPhone running iOS 17.6.1), requested permission for notifications from UNUserNotificationCenter, and saved the device token for testing purposes.
As a sanity check for the device token and the App entitlements, I used the CloudKit tool for testing Push Notifications. The notifications I send aimed at the "DEVELOPMENT" Environment work properly and arrive on the device.
To configure my custom server, I created the Sandbox Apple Push Notifications certificate in my Developer portal, installed it on my Mac, exported the certificate and key together into a .p12 file, and created the PEM file using this command:
openssl pkcs12 -in Certificates.p12 -out sandbox.pem -nodes -clcerts
When my server attempts to send a notification, it appears to connect to the server and send the payload, but the notification never arrives on the device. I don't get any errors when my server writes the notification's binary payload to the connection.
For clarity, here is the code from my server that sends the "aps" payload to APNS (written in PHP):
public function sendPushNotification($deviceToken, $title, $message)
{
$jsonPayload = $this->composePayload($title, $message);
$msg = $this->buildBinaryNotification($jsonPayload, $deviceToken);
$this->connectToApns();
$result = fwrite($this->mApnsConnectionHandle, $msg, strlen($msg));
if (!$result)
{
$this->writeToLog("Message not delivered?!");
} else {
$this->writeToLog("Message successfully delivered!");
}
$this->disconnectFromApns();
}
And this is the code for constructing the JSON payload, and for converting that JSON into a binary string:
private function composePayload($title, $message)
{
// Create the payload body
$body['aps'] = array(
'alert' => array(
'title'=>$title,
'body'=>$message
)
);
// Encode the payload as JSON
$payload = json_encode($body);
return $payload;
}
private function buildBinaryNotification($payload, $deviceToken)
{
if (strlen($payload) > 0 && strlen($deviceToken) > 0)
{
$msg = chr(0) . pack('n', strlen($deviceToken)) . pack('H*', $deviceToken) . chr(0) . pack('n', strlen($payload)) . $payload;
}
return $msg;
}
Any suggestions or advice would be appreciated.
Hello,
I'm doing some test and I dowload the sample from here https://developer.apple.com/documentation/networkextension/local_push_connectivity/receiving_voice_and_text_communications_on_a_local_network
Everything works correctly and the phones are able to exchange messages without problems and the server sends pushes to the devices.
Now I would like to modify the server so that, when it sends the push to the mobile device, it can change the sound or add other information as is possible when using APN.
Now I would like to modify the server so that, when it sends the push to the mobile device, it can change the sound or add other information as is possible when using APN.
Is there any way to send a payload like for APN?
Thank's
Omar
Please find below a complete app example.
It has a button, when you press it, a local notification is created. However, the UnNotificationCenter.delegate is called twice, and I can't understand why.
I am trying to move my project from Objective-C to Swift, and my similar code there doesn't get called twice, so I'm confused.
Can anybody shine a light on this? Pointers appreciated.
App:
@main
struct NotifTestApp: App {
init() {
UNUserNotificationCenter.current().delegate = NotificationReceiveHandler.shared
configureUserNotifications()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
private func configureUserNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted {
print("Notification permission granted.")
} else if let error = error {
print("Error requesting notification permissions: \(error)")
}
}
}
}
class NotificationReceiveHandler: NSObject, UNUserNotificationCenterDelegate {
static let shared = NotificationReceiveHandler()
//>> THIS IS CALLED TWICE WHEN I PRESS THE BUTTON
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
NSLog(">>> Will present notification!")
completionHandler([.sound])
}
}
///THE UI
struct ContentView: View {
var body: some View {
VStack {
Text("👾")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Notification test!")
Text("When i press the button, will present is called twice!!").font(.footnote)
.padding(10)
Button("Create Notification") {
createNotification(
message: "This is a test notification",
header: "Test Notification",
category: "TEST_CATEGORY",
playSound: true,
dictionary: nil,
imageName: nil)
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
.padding()
}
}
#Preview {
ContentView()
}
private func createNotification(message: String, header: String, category: String, playSound: Bool = true, dictionary: NSDictionary? = nil, imageName: String? = nil) {
let content = UNMutableNotificationContent()
content.title = header
content.body = message
content.categoryIdentifier = category
content.badge = NSNumber(value: 0)
if let imageName = imageName, let imageURL = Bundle.main.url(forResource: imageName, withExtension: "png") {
do {
let attachment = try UNNotificationAttachment(identifier: "image", url: imageURL, options: nil)
content.attachments = [attachment]
} catch {
print("Error creating notification attachment: \(error)")
}
}
content.sound = playSound ? UNNotificationSound(named: UNNotificationSoundName("event.aiff")) : nil
if let infoDict = dictionary {
content.userInfo = infoDict as! [AnyHashable: Any]
}
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
I'm getting really frustrated with emails from my App users who believe they've been charged for a free in-app purchase when they haven't.
My App offers many in-app purchases of digital items and I give 4 of these away for free to let users get comfortable with how it works in-app.
Over the last couple of years I've had a steady increase in angry emails from users who accuse me of fraud by charging them for a free item. I couldn't figure out for a while what this was as they would leave a 1 star rating, delete the app and ignore my emails for more information.
Recently I had someone a bit more patient engage and explain it to me.
The purchase for some reason popped up on my notifications right when I bought the [Free Item in my app]. It was from a movie I bought and the bill was delayed.
The timing of that notification is what is misleading users about the free in-app purchase.
Can someone take note of this please and perhaps delay any payment notifications so they aren't sent when the in-app purchase is for FREE?
Thanks!
Hello everyone,
I have been working on a macOS app that utilizes push notifications for the past year. Up until recently, everything was functioning correctly. However, now I'm experiencing issues where push notifications are either not being delivered at all or are experiencing significant delays, sometimes up to 10 minutes. Setting the priority header to 10 hasn't made any difference. I am currently using development push notifications, but the issue persists when switching to the production environment.
I'm curious if anyone else has encountered similar problems. When checking the push console, it frequently reports that the device is offline, even though it's actually online ("discarded as device was offline"). Occasionally, notifications are delivered promptly, but this is becoming increasingly infrequent.
This issue has been consistently reported by our testers, particularly after they updated to macOS Sonoma. Any insights or assistance you can provide would be greatly appreciated.
I am checking if the user taps on the firebase push notification and get the payload.
override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
os_log("notification tapped %{public}@", log: OSLog.push, type: .info, userInfo)
handleNotificationPayload(userInfo as! [String: AnyObject])
setFlutterLinkClickedVariable()
}
My use case is in app terminated state when push notification is tapped, get the link from payload and navigate to corresponding screen based on the link. This is working when there is only one push notification. When there are multiple push notifications with different links in the payload, only the first notification I tap works. Rest of the notifications just launches the app and does not navigate because the link is not set.
I am getting the link from the payload and invoking flutter code which sets the link in the user defaults (shared preferences) and when the app launches in the home screen it checks for this variable and navigates accordingly.
func handleNotificationPayload(_ payload: [String: AnyObject]) {
if let link = payload["link"] as? String {
setFlutterLinkVariable(link)
}
}
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
os_log("app did receive remote notification %{public}@", log: OSLog.push, type: .info, userInfo)
handleNotificationPayload(userInfo as! [String : AnyObject])
completionHandler(.newData)
}
Currently when there is only one push notification it works because the link is set from the above method. The click delegate is not calling. I did set the delegate in application(:didFinishLaunchingWithOptions).
UNUserNotificationCenter.current().delegate = self
application.registerForRemoteNotifications()
How to solve this issue? Thanks.
I'm currently testing the announce notifications feature and I can't seem to find out how to make Siri read aloud the current currency instead of dollars.
My locale is es-CL (Chile). It uses the currency symbol $ and reads as Pesos locally or Chilean Pesos where the number 5000.1 is represented as 5.000,1
This is the notification content
let content = UNMutableNotificationContent()
content.body = "¡Has recibido un pago por $5.000!"
Siri reads it aloud as "¡Has recibido un pago por 5.000 Dolares!" which translates to "You have received a payment for 5,000 Dollars", instead of the expected "¡Has recibido un pago por 5.000 Pesos!" -> "You have received a payment for 5,000 Pesos"
I've tried changing the development region of the app, interpolating the string with NumberFormatter.localizedString(from: 5000, number: .currency), and with others styles( .currencyAccounting, .currencyISOCode and .currencyPlural) without good results. The last one seems to work buts it's not ideal since it outputs "5.000 pesos chilenos" which gets read as "5 pesos chilenos" which is not the correct amount (bug), it's as is you're not on Chile and I personally prefer it to be a symbol instead of words.
I'm testing with my device which is setup with the region "Chile"
Could someone help me find a solution?
Topic:
Accessibility & Inclusion
SubTopic:
General
Tags:
Localization
User Notifications
Siri and Voice
Hello,
When attempting to assign the UNNotificationResponse to a Published property on the main thread inside UNUserNotificationCenterDelegate's method
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async
both Task { @MainActor in } and await MainActor.run are throwing a NSInternalInconsistencyException: 'Call must be made on main thread'.
I thought both of them were essentially doing the same thing, i.e. call their closure on the main thread. So why is this exception thrown? Is my understanding of the MainActor still incorrect, or is this a bug?
Thank you
Note: Task { await MainActor.run { ... } } and DispatchQueue.main.async don't throw any exception.