I used to received the notification after receiving a new mail after making a subscription. However, since I accidently spammed my own mail box (create an event that make it so that each time there is a new message, a new draft message was created (and draft message count as new message), each time I create a subscription, I got the answer that everything is fine, but no new subscription is created. What should I do to have a functionnal subscription ?
Annex:
the post call which ask to call a ws each times a new message is received
https://graph.microsoft.com/post/subscriptions
with those params
{
changeType: 'created',
notificationUrl: 'the adresse of the webservice',
resource: 'me/messages',
expirationDateTime: '2018-10-23T17:46:08Z',
clientState: 'Message Created'
}
the answer (I also got a log indicating that the webservice got the notification token and answer it with a plain/text with statut 200 message containing the notification token.
{
changeType: 'created',
notificationUrl: 'the adresse of the webservice',
resource: 'me/messages',
expirationDateTime: '2018-10-22T17:37:21Z',
clientState: 'Message Created'
}
A few things to check:
The results returned by the list subscriptions API varies depending on the permissions (the linked article explains that). Make sure that when you check for the existence of the sub, you have the right permissions for the subscription you are looking for. Best, test with the same app and identity.
You mentioned you did receive a notification from the subscription? If so, the notification contains the ID of the subscription that generated it. That in itself is proof that the subscription was indeed created. Are you able to do a GET on that subscription?
Related
After a user visits the payments page and successfully makes a payment, Stripe will redirect the customer to whatever url is provided to success_url
Stripe.api_key = 'sk_test_51HYHSFGtUKse83O9J4QeAib3cp8sHzGaOQRrn7sba92Hd8dCHE3AIHe5ModevMK7TVAUCyJU0ADSwIUoX00qxZmBI9r'
session = Stripe::Checkout::Session.create({
payment_method_types: ['card'],
line_items: [{
name: 'Kavholm rental',
amount: 1000,
currency: 'aud',
quantity: 1,
}],
payment_intent_data: {
application_fee_amount: 123,
transfer_data: {
destination: '{{CONNECTED_STRIPE_ACCOUNT_ID}}',
},
},
success_url: 'https://example.com/success',
cancel_url: 'https://example.com/failure',
})
Now the app/platform must arrange 'fulfillment':
After the payment is completed, you’ll need to handle any fulfillment necessary on your end. A home-rental company that requires payment upfront, for instance, would connect the homeowner with the renter after a successful payment.
Also (bold from me):
Do not rely on the redirect to the success_url param alone for fulfilling purchases as:
Malicious users could directly access the success_url without paying and gain access to your goods or services.
Customers may not always reach the success_url after a successful payment. It is possible they close their browser tab before the redirect occurs.
Up to this point, everything is very well explained in the stripe docs and very understandable.
But I want to know: what is the best thing to do next, noting that:
a payment may not go through immediately, so simply loading the success_url might be premature
a webhook can be (easily) configured to listen for events, however if the success_url is loaded even 1 second before the webhook receives a success message, then it won't know that the payment went through successfully (so, for example, displaying "Congrats, your product will be shipped!" message could be presumptuous
Question
So, finally, the question: what is best practice for the flow on from success_url? I am just confused as to what is the best pattern..
Ideas
Here are some things I've considered:
Upon routing to success_url, simply use sleep(5) and then check the webhook in the controller for the success_url so it takes 5 extra seconds to load giving the webhook a chance to receive incoming events, so you can display either "Congrats your product will be shipped!" or "Oh, no, something went wrong with your payment, please try again or contact your bank".
Routing directly to success_url, but then having a message saying "please refresh in a moment" (then listening for a webhook indicating the payment was successful, and then conditionally showing the "Congrats your product will be shipped!" message)
The documentation for fulfilling orders has this in an info box under the code snippet:
Your webhook endpoint redirects your customer to the success_url when you acknowledge you received the event. In scenarios where your endpoint is down or the event isn’t acknowledged properly, your handler redirects the customer to the success_url 10 seconds after a successful payment.
The event referenced above is the checkout.session.completed event sent to your webhook endpoint. The delay is designed to let you confirm the payment is successful and customize the success page based on the result of the Checkout Session's outcome.
In other words, Checkout won't send someone to your success_url until you've responded to the checkout.session.completed event request from your webhook endpoint with a successful (2xx) response, giving you time to customize the success page based on the outcome.
You can, for example, default to a "your payment is being processed" success page, but if you confirm the Checkout Session and payment succeeded after receiving the checkout.session.completed event, you can instead change the page to read "congrats your product will be shipped".
This approach means you can reliably present a success page that always has displays accurate information.
I'm making this addons that have to send to the raid my interrupt cooldown.
The problem is that whenever i send a message to the raid i am the only one that receive it.
This is the code that send the message:
C_ChatInfo.SendAddonMessage("KickRotation",string.format( "%0.2f",remainingCd ), "RAID")
This is the event handler:
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("CHAT_MSG_ADDON")
frame:SetScript("OnEvent", function(self, event, ...)
local prefix, msg, msgType, sender = ...;
if event == "CHAT_MSG_ADDON" then
if prefix == "KickRotation" then
print("[KickRotation]" ..tostring(sender) .." potrà interrompere tra: " ..msg);
end
end
if event == "PLAYER_ENTERING_WORLD" then
print("[KickRotation] v0.1 by Galfrad")
end
end)
Basically when the message is sended it is printed only to me.
Network messages are handled and transferred to the recipient channel (in this case, Raid Group) by the server. The reason that you are seeing the message locally, but the other people do not see it is that the message will be handled on the local system (sender) to reduce the repetition of data transmit.
Server however, only accepts and sends messages that are registered to it.
Therefore, you must first register your add-on messages to the server so the other players in the requested channel be able to receive it.
First, register your add-on messages with the name you have given already (But be sure to call the registration method only once per client):
local success = C_ChatInfo.RegisterAddonMessagePrefix("KickRotation") -- Addon name.
Next, check if your message was accepted and registered to the server. In case success is set to false (failure), you may want to handle proper warning messages and notifications to the user. The case of failure means that either server has disabled add-on messages or you have reached the limit of add-on message registrations.
Finally, send your message again check if it did not fail.
if not C_ChatInfo.SendAddonMessage("KickRotation",string.format( "%0.2f",remainingCd ), "RAID") then
print("[KickRotation] Failed to send add-on message, message rejected by the server.")
end
I have a multi-tenant application that has webhooks setup to monitor for new emails arriving in the SentItems folder. Sometimes I get a notification for a random tenant, that a new email has arrived, but I can't find it in the user's mailbox through Microsoft Graph or EWS.
I get a notification that this ID has arrived:
AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK3wAAAA==
but the only messages in the SentItems folder are these:
[0]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK6wAAAA=="
[1]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK6gAAAA=="
[2]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK6QAAAA=="
[3]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK6AAAAA=="
[4]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK5wAAAA=="
[5]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK5AAAAA=="
[6]: "AAMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAAAAAAnaThn6c3YR6wA5CaaALt2BwD45xsfmmj8TKVOa3R-3Ss0AAAAAAEJAAD45xsfmmj8TKVOa3R-3Ss0AAA9xTdMAAA="
[7]: "AAMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAAAAAAnaThn6c3YR6wA5CaaALt2BwD45xsfmmj8TKVOa3R-3Ss0AAAAAAEJAAD45xsfmmj8TKVOa3R-3Ss0AAAHDRc_AAA="
[8]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK1wAAAA=="
and the email is not to be found anywhere in the mailbox. I actually think it's strange that two of the IDs don't match the parent folder's ID, but the rest do.
UPDATE 04/07:
Mark requested the complete notification, but I don't have it for this ID. Hovever I got a new one, where the item does not exist. The notification was part of multiple, but the one that I can't find is this one:
{
"subscriptionId":"70f45211-1096-4282-b34a-b37219ff7756",
"subscriptionExpirationDateTime":"2018-07-04T23:00:02.7089152+00:00",
"changeType":"created",
"resource":"Users/2e1b31b1-9ba8-43b0-92e2-d7e7eb740017/Messages/AAMkADZhMWJhNjQ3LTJkZGQtNGViYS05MTBlLWExYzg1YWU4YjU1OABGAAAAAAC0KduT98_pQLvg9lqbswvNBwCXszCEea-1T5Fvw2GeYIEvAAAAAAEJAACXszCEea-1T5Fvw2GeYIEvAAAAH3cQAAA=",
"resourceData":{
"#odata.type":"#Microsoft.Graph.Message",
"#odata.id":"Users/2e1b31b1-9ba8-43b0-92e2-d7e7eb740017/Messages/AAMkADZhMWJhNjQ3LTJkZGQtNGViYS05MTBlLWExYzg1YWU4YjU1OABGAAAAAAC0KduT98_pQLvg9lqbswvNBwCXszCEea-1T5Fvw2GeYIEvAAAAAAEJAACXszCEea-1T5Fvw2GeYIEvAAAAH3cQAAA=",
"#odata.etag":"W/\"CQAAABYAAACXszCEea/1T5Fvw2GeYIEvAABTkl6J\"",
"id":"AAMkADZhMWJhNjQ3LTJkZGQtNGViYS05MTBlLWExYzg1YWU4YjU1OABGAAAAAAC0KduT98_pQLvg9lqbswvNBwCXszCEea-1T5Fvw2GeYIEvAAAAAAEJAACXszCEea-1T5Fvw2GeYIEvAAAAH3cQAAA="
},
"clientState":"e698cb6b-03f6-4ecb-847d-aa142a21176d"
},
UPDATE 05-07:
Another one:
{
"subscriptionId":"3f7f0518-1e1c-4126-b046-ead9251692e8",
"subscriptionExpirationDateTime":"2018-07-06T19:00:11.8955691+00:00",
"changeType":"created",
"resource":"Users/dcfcac62-511b-425c-93ad-e7f786f67f90/Messages/AAMkADdjMzk2ZmE5LWFhZTgtNDY4MC04NTQ3LWQ1NTc1N2FhYWU5OQBGAAAAAADHkc19ugpQQYziYaUQfoyOBwB4OcB73fiVTK3E3hTiQwPfAAAAAAEJAAB4OcB73fiVTK3E3hTiQwPfAAMSo0tHAAA=",
"resourceData":{
"#odata.type":"#Microsoft.Graph.Message",
"#odata.id":"Users/dcfcac62-511b-425c-93ad-e7f786f67f90/Messages/AAMkADdjMzk2ZmE5LWFhZTgtNDY4MC04NTQ3LWQ1NTc1N2FhYWU5OQBGAAAAAADHkc19ugpQQYziYaUQfoyOBwB4OcB73fiVTK3E3hTiQwPfAAAAAAEJAAB4OcB73fiVTK3E3hTiQwPfAAMSo0tHAAA=",
"#odata.etag":"W/\"CQAAABYAAAB4OcB73fiVTK3E3hTiQwPfAAMTQCkA\"",
"id":"AAMkADdjMzk2ZmE5LWFhZTgtNDY4MC04NTQ3LWQ1NTc1N2FhYWU5OQBGAAAAAADHkc19ugpQQYziYaUQfoyOBwB4OcB73fiVTK3E3hTiQwPfAAAAAAEJAAB4OcB73fiVTK3E3hTiQwPfAAMSo0tHAAA="
},
"clientState":"59f393b1-6200-4c4e-9ce3-7d70a009359c"
}
It's seems you were right Marc. It was due to messages being moved from the sentItems folder. The user archived the email manually in my system, and moved the email to another folder, to indicate that it was archived. Strange behavior :)
I'm developing a Rails application, and I'd like to send web push notifications to specific users when certain actions happen, e.g:
A user started tracking a timer, but the timer has been running for more than 6 hours. Then the app sends that user a web notification.
I've been doing research and found this tutorial, the author implements push notifications for Rails, however there's no insight on how to identify the users.
From what I understood, the users needs to subscribe from their browser to be able to get push notifications, however, considering each user can use the application from multiple browsers, how can I automatically subscribe/unsubscribe a user for notifications in all browsers they use the app from?
So, what I did was adding a notification_subscription model to my User model.
On my javascript, I check if there's a current browser subscription present:
this.serviceWorkerReady()
.then((serviceWorkerRegistration) => {
serviceWorkerRegistration.pushManager.getSubscription()
.then((pushSubscription) => {
if (pushSubscription && _.includes(subscriptionEndpoints, pushSubscription.endpoint)) {
return;
}
this.subscribe();
});
});
I check if the current subscription is already present in the user stored endpoints, and subscribe if it isn't.
On subscription I send the new endpoint to the backend, which adds the new subscription to the user:
$.post(Routes.users_subscriptions_path({ format: 'json' }), {
subscription: subscription.toJSON()
});
Then I can send notifications to users to every endpoint:
def push_notifications_to_user(user)
message = {
title: "A message!",
tag: 'notification-tag'
}
user.notification_subscriptions.each do |subscription|
begin
Webpush.payload_send(
message: JSON.generate(message),
endpoint: endpoint,
p256dh: p256dh,
auth: auth,
api_key: public_key
)
rescue Webpush::InvalidSubscription => exception
subscription.destroy
end
end
end
The webpush gem raises an InvalidSubscription exception if the endpoint is invalid, we can destroy that endpoint to keep only the valid endpoints from the user.
The endpoint is unique by browser so you need an additional authentication scheme on the top of your app to send user's information along with the new endpoint.
You need to attach metadata (i.e. the user ID) to the endpoint when you store it on your server:
#subscription = Subscriptions.new endpoint: params[:endpoint]
#subscription.user = current_user
// or if you send with AJAX the user id together with the endpoint
#subscription.user = User.find params[:user_id]
In the second case I suggest to sign the user ID or use a secret token, otherwise anyone would be able to subscribe to push notifications as if it was another user.
Then you can delete from the database all the endpoints that belong to that user ID to unsubscribe all his devices.
However I don't think it's a good practice: a user may want to receive notifications on a device and not on another one.
Remote iOS client successfully connects to me, send subscribe command (it works fine), but on "unsubscribe" command I get next error:
Unsubscribing from channel: {"channel":"Assessor::StationChannel", "station_id": 1}
Could not execute command from {"command"=>"unsubscribe", "identifier"=>"{\"channel\":\"Assessor::StationChannel\", \"station_id\": 1}"}) [NoMethodError - undefined method `unsubscribe_from_channel' for nil:NilClass]: /app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/connection/subscriptions.rb:44:in `remove_subscription' | /app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/connection/subscriptions.rb:40:in `remove' | /app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/connection/subscriptions.rb:16:in `execute_command' | /app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/connection/base.rb:88:in `dispatch_websocket_message' | /app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/server/worker.rb:58:in `block in invoke'
Subscribe message format:
{"command": "subscribe", "identifier": "{\"channel\":\"Assessor::StationChannel\", \"station_id\": 1}"}
Unsubscribe message format:
{"command": "unsubscribe", "identifier": "{\"channel\":\"Assessor::StationChannel\", \"station_id\": 1}"}
I cannot reproduce this problem on localhost, so maybe somebody can help me?
I saw a similar error. I was trying to unsubscribe via the client (JS). I eventually figured out it was because the javascript to .remove(subscription) takes the subscription and not the subscription identifier.
This is how I got it to work without error. Perhaps it will help you find out why you are getting the error from the server side.
subscription = App.cable.subscriptions.subscriptions[0]
App.cable.subscriptions.remove(subscription);
(Note, I'm just pulling the first subscription from the array, TODO: Search for the subscription I want to remove)
Here is the bug I was seeing and how I eventually found the source code/answer. I ran these from the webclient console:
App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2})
That line works and I get a "... is transmitting the subscription confirmation" on stdout for rails s
App.cable.subscriptions.remove({channel: "RoomChannel", room_id: 2})
That line blows up, yells at my kids, and insults my wife which looks like:
[NoMethodError - undefined method `unsubscribe_from_channel' for nil:NilClass]: /usr/local/lib64/ruby/gems/2.3.0/gems/actioncable-5.0.0.1/lib/action_cable/connection/subscriptions.rb:44:in `remove_subscription'
I also noted the following line before the crash.
Unsubscribing from channel:
The code to produce that is: logger.info "Unsubscribing from channel: #{data['identifier']}". Which means it wasn't finding the data['identifier']. So I started debugging and I see that line 88 of base.rb in actioncable only gets {"command":"unsubscribe"} and not something like {"command":"unsubscribe", "identifier":" (channel name here)}
Which brought me to action_cable.js. (I would have started here, but I hate JS.). Here was my problem: function(subscription). I was sending the identifier and not the subscription object.
Subscriptions.prototype.remove = function(subscription) {
this.forget(subscription);
if (!this.findAll(subscription.identifier).length) {
this.sendCommand(subscription, "unsubscribe");
}
return subscription;
};
App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2}) returns a subscription object you have to pass that into the remove function
var subscription = App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2});
Then later
App.cable.subscriptions.remove(subscription);
After several tries I eventually figured it out. Late reply but this worked for me hope it does for you.
App["identifier"].disconnected() #e.g App["chat_4"].disconnect()
=> YourChannel stopped streaming from chat_4 #rails terminal
Above is the line to stop the streaming and below is how you subscribe to the channel
App['chat' + id] = App.cable.subscriptions.create({channel:
'YourChannel', chat_id: id}, {
disconnected: function () {
App.cable.subscriptions.remove(this)
},
)}
I know this is an old question, but I suffered from the same issue. None of the answers above worked for me and in fact, at least in Rails 5.0.1, they are incorrect. It is a frontend issue all right, but here's why it doesn't matter whether you call App.yourChannelName.unsubscribe() or App.yourChannelName.remove(App.yourChannelName)
Eg. if you have something like this (example code is in coffeescript, so ignore the lack of vars and other stuff from vanilla JS):
App.yourChannel = App.cable.subscriptions.create({channel: 'YourChannel', id: id})
...
// do stuff, execute callbacks, whatnot
...
// try to execute unsubscribe
App.yourChannel.unsubscribe()
The .unsubscribe() is a method on Subscription prototype which only does return this.consumer.subscriptions.remove(this)
The this.consumer.subscriptions returns the instance of your subscription, in example above, it would be App.yourChannel and calls .remove method with the instance of Subscription - ie. with App.yourChannel
So App.yourChannel.unsubscribe() is the same as calling App.cable.subscriptions.remove(App.yourChannel) (or whichever variable you choose to store the instance of Subscription in.
I have also been seeing the same error as OP, except that in my case, it was caused by App.yourChannel.unsubscribe() being called two times - the first time it was called immediately after I received specific data via the channel and the second time was due to a custom cleanup being run in a specific scenario before the App.yourChannel was re-subscribed.
So if you see a similar error, I suggest you look at the server logs.
You'll probably see something like
Registered connection (some-id) <-- initial subscription
YourChannel is transmitting the subscription confirmation
...
// other stuff while user is subscribed to the channel
...
Unsubscribing from channel: {"channel":"YourChannel","id":"some-id"} <-- initial unsubscribe call
YourChannel stopped streaming from your_channel_some-id
// some other requests potentially, perhaps some DB queries
...
// there are no requests to subscribe to the channel with the some-id, eg. you won't see this
// Registered connection (some-id)
// YourChannel is transmitting the subscription confirmation
Unsubscribing from channel: {"channel":"YourChannel","id":"some-id"} <-- duplicated unsubscribe call
Could not execute command from {"command"=>"unsubscribe", "identifier"=>"{\"channel\":\"YourChannel\",\"id\":\"some-id\"}"}) [NoMethodError - undefined method `unsubscribe_from_channel' for nil:NilClass]:
Basically, the user subscribes, unsubscribes, then tries to unsubscribe again (even though they are not subscribed to that channel anymore)