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.
Related
We are trying to implement a chatbot on our website.
My code successfully triggers the Flow. The Conversations log on Twilio shows that my code sent a message of "Hi" and the Flow triggered and sent the expected greeting.
The problem is that I'm not seeing anyplace where the Flow output is being sent to my website callback and so I'm not able to output the Flow messages to my website user.
When the Flow sends a message, where is the configuration that makes a callback to my website so I can output the message to the user?
onMessageAdded DOES get called on my website callback, but only for messages sent by the website code - not the Flow.
At this point I think the problem is a Twilio configuration for Conversations, Messages or the Flow, but it could be a configuration problem in my code.
Here is my rough initial code:
TwilioClient.Init(_twilioAccountSid, _twilioAuthToken);
//
// Create Conversation
var conversation = ConversationResource.Create(
friendlyName: "Test conversation",
messagingServiceSid: _twilioMessagingServiceSid,
attributes: null,
xTwilioWebhookEnabled: ConversationResource.WebhookEnabledTypeEnum.True
);
_log.Info("Conversation.Create: " + conversation.Sid);
//
// Attach Flow to Conversation
var webhook = WebhookResource.Create(
configurationMethod: WebhookResource.MethodEnum.Post,
configurationFlowSid: _twilioStudioFlowSid,
target: WebhookResource.TargetEnum.Studio,
configurationFilters: new List<string> {
"onMessageAdded",
"onMessageUpdated",
"onMessageRemoved",
"onConversationUpdated",
"onConversationRemoved",
"onParticipantAdded",
"onParticipantUpdated",
"onParticipantRemoved"
},
pathConversationSid: conversation.Sid
);
_log.Info("WebhookResource.Create: " + webhook.Sid);
//
// Create a Participant
var participant = ParticipantResource.Create(
identity: _identity,
pathConversationSid: conversation.Sid
);
_log.Info("Participant.Create: " + participant.Sid);
//
// Send Message
var message = MessageResource.Create(
author: _identity,
body: "Hi!",
xTwilioWebhookEnabled: MessageResource.WebhookEnabledTypeEnum.True,
pathConversationSid: conversation.Sid
);
_log.Info("Message.Create: " + message.Sid);
Is there a reason you decided to not use the Twilio Conversations SDK for JavaScript?
The architecture you are using may require this additional configuration.
Triggering Webhooks for REST API Events
Upon configuration, only actions from SDK-driven clients (like mobile phones or browsers) or SMS-based Participants will cause webhooks without further action on your part. This includes both Service-level webhooks and Conversation-Scoped Webhooks. This is a default behavior to help avoid infinite feedback loops.
Your Post-Event Webhook target, however, may be an important tool for archiving. In this case, you may also want to enable webhook "echoes" from actions you take on the REST API. To do so, you can add a header X-Twilio-Webhook-Enabled=true to any such request. Requests bearing this header will yield webhooks to the configured Post-Event webhook target.
Troubleshooting Webhook Delivery for Conversations or Chat
I don’t think there is a way to set this header when using Twilio Studio widgets.
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?
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.
I am currently integrating into the twilio rest api and need to perform a check on a users phone number to determine if that user has blacklisted themselves or not. I have little experience with this api and scouring through the documentation and google has turned up nothing.
In our application we are going to have a notification center and if the user has blacklisted themselves I do not want to give them the ability to turn on their SMS notifications. Potentially a user could have SMS notifications on but twilio would block any messages. I know there is the ability to get a status code back from twilio when an SMS is queued that shows the user is blacklisted (https://www.twilio.com/docs/api/rest/message). However, I will not be sending messages on the notifications screen and need a direct way (if at all possible) to check twilio to determine if a number is blacklisted. Any help is much appreciated. Let me know if anymore information will be of help.
Megan from Twilio.
I'd be curious to see if you ever tried your own workaround. But I wanted to note for others in a similar situation how you could grab the blacklist error and then do whatever you may want with it.
In Ruby it would look something like this:
require 'rubygems'
require 'twilio-ruby'
account_sid = 'YOUR_ACCOUNT_SID'
auth_token = 'YOUR_AUTH_TOKEN'
#client = Twilio::REST::Client.new account_sid, auth_token
begin
#message = #client.messages.create(
from: 'TWILIO_NUMBER',
to: 'USER_NUMBER',
body: 'Howdy!'
)
rescue Twilio::REST::RestError => e
if e.code == 21610
# User is blacklisted
# Store info however you choose
puts e.message
end
end
We check for blacklisting specifically using the code '21610'. For more information about errors you can visit the reference page.
Hope this helps!
Twilio recommends developers to store the opt-out/in statuses in their side. I have stored it in DB. There are 2 ways to collect the unsubscribed users list.
1) Use SMS webhooks. You can find how to configure your Twilio number to receive webhook events here
#PostMapping(value = "/twilio", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_ATOM_XML_VALUE)
public String twilioConsumer(TwilioEventDTO twilioEventDTO) {
// twilioEventDTO.getBody() => returns the body of the SMS user replied.
twilioService.consume(twilioEventDTO);
return new MessagingResponse.Builder().build().toXml();
}
2) Since I implemented webhooks later, I had to collect already unsubscribed users. When you send sms to the number that has been opted-out, Twilio API throws an exception with the status number of 21610. You can catch it and store the number in DB.
try {
Message result = Message.creator(
new PhoneNumber(toPhoneNumber),
new PhoneNumber(fromPhoneNumber),
messageBody)
.create();
response = result.getStatus().name();
} catch (ApiException e) {
if (e.getCode().equals(21610))
updateSubscription(toPhoneNumber, false);
logger.warn("Error on sending SMS: {}", e.getMessage());
}
P.S.: examples written in Java - Spring Boot framework.
I'm stuck with getting activemerchants paypal express ipn notification to work.
My workflow looks like this:
# authorize the payment user gets redirected..
def auth
...
gateway.setup_authorization(total_as_cents, setup_authorization_params)
...
end
# purchase the authorized sum
def purchase
...
purchase_params = {
token: #order.payment_params[:token],
payer_id: #order.payment_params[:payer_id],
currency: current_tenant.currency.unit,
notify_url: paypal_ipn_callback_url
}
response = gateway.purchase(total_as_cents, purchase_params)
...
end
In the paypal docs it says notify_url is deprecated they use PAYMENTREQUEST_n_NOTIFYURL instead. But I have no clue how to tell this my paypal express gateway.
My ipn callback doesn't get called so I assume the notifyurl param doesn't work anymore.
Paypal is in sandbox mode but that should make no difference right?
Any hints?
I believe that if you are using Paypal Express that means you are doing a deep integration with your system, and you don't need the IPN, you can get the response from
response = gateway.purchase(total_as_cents, purchase_params)
and get all information from it, and that response is an object
ActiveMerchant::Billing::PaypalExpressResponse
The IPN is used for the basic Paypal integration, with no API calls from your app, only Paypal URL redirect with params.