recently I'm struggling with adding APNs feature to my Ruby on Rails(7) project using RPush. I made some wrong config before and that lead to a failed launch of rails s
, then I found and fixed it so I think all config is correct and service is running. Then I tried on heroku where my server is and I didn't get the APNs, then I tried it locally on my laptop, it shows me some error message which I cannot find a solution with Google or ChatGPT. Here is some error log below and I did work on it for a month as a beginner. Please let me know to correct it, thanks:
Started POST "/notifications/send_notifications" for ::1 at 2024-07-10 00:27:31 +0800
Processing by NotificationsController#send_notifications as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]"}
Rpush::Client::ActiveRecord::Apnsp8::App Load (0.5ms) SELECT "rpush_apps".* FROM "rpush_apps" WHERE "rpush_apps"."type" = $1 AND "rpush_apps"."name" = $2 LIMIT $3 [["type", "Rpush::Client::ActiveRecord::Apnsp8::App"], ["name", "MyProjectName"], ["LIMIT", 1]]
↳ app/controllers/notifications_controller.rb:34:in `send_apns'
TRANSACTION (0.4ms) BEGIN
↳ app/controllers/notifications_controller.rb:38:in `send_apns'
Rpush::Client::ActiveRecord::Apnsp8::Notification Create (2.2ms) INSERT INTO "rpush_notifications" ("badge", "device_token", "sound", "alert", "data", "expiry", "delivered", "delivered_at", "failed", "failed_at", "error_code", "error_description", "deliver_after", "created_at", "updated_at", "alert_is_json", "type", "collapse_key", "delay_while_idle", "registration_ids", "app_id", "retries", "uri", "fail_after", "processing", "priority", "url_args", "category", "content_available", "notification", "mutable_content", "external_device_id", "thread_id", "dry_run", "sound_is_json") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35) RETURNING "id" [["badge", nil], ["device_token", "[FILTERED]"], ["sound", nil], ["alert", "Your custom message"], ["data", "{\"foo\":\"bar\"}"], ["expiry", 86400], ["delivered", false], ["delivered_at", nil], ["failed", false], ["failed_at", nil], ["error_code", nil], ["error_description", nil], ["deliver_after", nil], ["created_at", "2024-07-09 16:27:31.439547"], ["updated_at", "2024-07-09 16:27:31.439547"], ["alert_is_json", false], ["type", "Rpush::Client::ActiveRecord::Apnsp8::Notification"], ["collapse_key", "[FILTERED]"], ["delay_while_idle", false], ["registration_ids", nil], ["app_id", 1], ["retries", 0], ["uri", nil], ["fail_after", nil], ["processing", false], ["priority", nil], ["url_args", nil], ["category", nil], ["content_available", false], ["notification", nil], ["mutable_content", false], ["external_device_id", nil], ["thread_id", nil], ["dry_run", false], ["sound_is_json", false]]
↳ app/controllers/notifications_controller.rb:38:in `send_apns'
TRANSACTION (0.8ms) COMMIT
↳ app/controllers/notifications_controller.rb:38:in `send_apns'
[2024-07-10 00:27:32][ERROR] [MyProjectName] Notification 11 failed, 403/InvalidProviderToken
Notification failed: 11
Redirected to http://localhost:3000/notifications
Completed 302 Found in 839ms (ActiveRecord: 21.2ms | Allocations: 78151)
Here is the config in rpush.rb
require 'jwt'
Rpush.configure do |config|
config.client = :active_record
config.push_poll = 2
config.batch_size = 100
config.pid_file = 'tmp/rpush.pid'
config.log_file = 'log/rpush.log'
config.log_level = (defined?(Rails) && Rails.logger) ? Rails.logger.level : ::Logger::Severity::INFO
end
Rpush.reflect do |on|
on.notification_delivered do |notification|
Rails.logger.info("Notification delivered: #{notification.id}")
end
on.notification_failed do |notification|
Rails.logger.error("Notification failed: #{notification.id}")
end
end
if Rpush::Apnsp8::App.where(name: 'RaceCal').empty?
app = Rpush::Apnsp8::App.new
app.name = 'RaceCal'
apn_key_path = Rails.root.join('config', 'keys', 'AuthKey_xxx.p8')
app.apn_key = File.read(apn_key_path)
key_file = File.read(apn_key_path)
app.environment = 'development' #'development' # or 'production'
app.team_id = 'team id'
app.apn_key_id = 'apn key'
app.bundle_id = 'bundle_id'
app.connections = 1
app.save!
token = JWT.encode({
iss: team_id,
iat: Time.now.to_i
}, key_file, 'ES256', {
kid: key_id
})
puts token
end
The code to trigger APNs in notifications_controller.rb
require 'jwt'
class NotificationsController < ApplicationController
before_action :require_login, except: [:new, :create]
def index
# TODO
end
def send_notifications
send_apns("my debug device token", "Your custom message")
redirect_to notifications_path, notice: "Notifications sent successfully"
end
private
def send_apns(device_token, message)
n = Rpush::Apnsp8::Notification.new
n.app = Rpush::Apnsp8::App.find_by_name("MyProjectName")
n.device_token = device_token
n.alert = message
n.data = { foo: :bar }
n.save!
Rpush.push
Rpush.apns_feedback
end
def admin_only
unless current_user.admin?
redirect_to root_path, alert: "You are not authorized to perform this action."
end
end
def require_login
redirect_to login_url unless session[:user_id]
end
end
Then I click the send_notifications button, it shows the error log above.
team_id
andkey_id
are not defined andtoken
is unused. Otherwise the error is fairly clear that the provider token in invalid