I am using Stripes payment gateway with C# .Net. I started with creating a checkout which redirects the user to Stripe's payment gateway (I didnt want the hassle of maintaining the card numbers etc so this way it forwards to Stripe to ask for the card details, process the payment etc) https://stripe.com/docs/payments/checkout/one-time - this was done in code-behind.
I set my success URL as www.example.com/myHandler.ashx (Generic Handler)- this URL sets the order id as successful. My handler code is similar to https://stripe.com/docs/webhooks/build (since im using a Generic Handler i'm using forms and not MVC)
After a successful payment, the payment is recorded to my database.
Considering this is a webhook, how do i display/redirect to a thank you page?
You have more than one way to solve this.
Option 1:
Combine the success page with your webhook. This means it will display the page to the user and update the state of the transaction on the backend.
your url would look like this
SuccessUrl = "https://example.com/success?session_id={CHECKOUT_SESSION_ID}"
Then use the session ID to handle the state change like you would with your webhook but return the html page to the user (Technically this wouldn't be a webhook).
Based on your question it could be that the SuccessUrl gives a session object as body because otherwise your current code shouldn't be working but I'm not sure.
To get the session object based on the Id you can make another call to stripe see:
https://stripe.com/docs/api/checkout/sessions/retrieve#retrieve_checkout_session
Once payment is successful, the Checkout Session will contain a reference to the Customer, and either the successful PaymentIntent or an active Subscription.
Option 2:
Create a webhook separately from your thank you page. This means that the SuccessUrl would be your thank you page.
The webhook needs to be defined separately and globally with stripe. You can look here on how this is done: https://stripe.com/docs/webhooks/configure
Related
Using Identity Serve 4 with .Net Core 3.1, razor pages. Also using Cookie Authentication
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
Problem -
In a web application John logged-in 2 times
1st Login on Chrome
2nd Login on edge
So, if John again trying to logged-in on 3rd time on Firefox without logout from previous browsers, then I want to logout John from 1st Login on Chrome forcefully.
I can keep the track of logins in a Session table including Session Id, User Id etc.
But I don’t know how logout user from a particular session using Session Id.
Please help.
Thanks
ASP.NET Core provides an ITicketStore interface which allows you to get control of storing user sessions. Once you provide a class implementing this interface and register it, it will call your class when sessions are being created or verified which you can then store in a database however you like, including attaching arbitrary metadata like browser ID etc.
Now that you have user sessions in your database, you can separately query them and revoke as needed in other logic, including during logins. Since you now provide the session data, simply deleting the record effectively logs the user out from that session. Note that if you use any caching layer to reduce the store requests, you'd need to remove any cached copies as well.
Note that this is separate from IdentityServer and happens with ASP.NET Core itself.
This is a good tutorial that helped me implementing this in my app.
A sample of how it looks to register in Startup, where PersistentTicketStore is my implementation:
// Persistent ticket/cookie store to provide durable user sessions
services.AddSingleton<IUserSessionRepository, UserSessionRepository>();
services.AddSingleton<ITicketStore, PersistentTicketStore>();
services.AddOptions<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme)
.Configure<ITicketStore>((options, store) => options.SessionStore = store);
Use the End Session Endpoint
The end session endpoint can be used to end a session and trigger a log out
In the log in process you will need to capture the id_token received from authentication and what user it belongs and store it on some dbo.table. You can use this same table to also keep track if a user has logged in more than once.
To log out a user or end a session you will need to pass the ID you saved as a query string parameter called id_token_hint in a GET call as shown below into:
GET /connect/endsession?id_token_hint={id_token}
For reference see the documentation here https://identityserver4.readthedocs.io/en/latest/endpoints/endsession.html#end-session-endpoint
Since you're saying you can keep track of logins, perhaps you should keep track of each session and assign a number somewhere indicating when it was logged in (1 for Chrome, 2 for edge, 3 for Firefox).
Then each time a request is made, you check in your table what the lowest number is (1,2,3 etc), and if the session matches that number, you sign the user out from that session.
await
HttpContext.SignOutAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);
Since each browser will have their own cookie, you can use the above method.
After signing someone out, the next login can be assigned 4, and if 2 makes a request you log that client out.....
Also see this: https://github.com/IdentityServer/IdentityServer4/issues/736
I have implemented this.
When a user logs in, the session id (IUserSession.GetSessionIdAsync) is manually stored in our database. The previous value of this database field is used to create a logout_token which I send to my clients. You can have look at IdentityServer4.Infrastructure.BackChannelLogoutClient to figure out how to create the token and post.
All this assumes you have backchannel logout implemented ofcourse.
In my application I plan to use SignalR in order for the backend code to send messages to the logged in user based on the conditions that arise on the server.
In particular I want the SignalR to call methods on the JS client whenever something happens on the backend. This could be periodic calculations happening on the backend that suddenly pass a threshold and I need to invoke something on the JS client for a particular User. The particular User is the key element here. Only the User that should know about this.
I'm assuming this should be very simple with SignalR but I have some problem understanding the way to implement this. My solution is as follow;
Each time a user logs in, I create a SignalR Group and add that user to that group.
Each time a user logs out, I remove them from the Group. (I don't know if I can also delete the Group itself)
Now each time something happens on the back end, I use SignalR to push information to a particular User that needs to know about that event by calling a JS client method and sending to the group with the name equal to the Name Identifier of the user of interest.
So to apply this solution, I need to get the information about the User that just logged in inside the C# Hub in order to create the group and join him.
Now my problem is, how to access the information that I need from the User that logs in to the application in the C# Hub . I'm interested in the User Name Identifier of course. I have been thinking that the Context Property in the Hub should give me the information that I need (This is my understanding of the MS Docs) but I cannot make it to work. Please study below code.
// As soon as a User logs in, below method fires. I try to get the information
// in here but no success
public override async Task OnConnectedAsync()
{
var CID = Context.ConnectionId; // this gives a unique connection ID
var user = Context.User; // This returns nothing
var userID = Context.UserIdentifier; // This returns nothing
var httpContextObject = Context.GetHttpContext(); // This returns nothing
await base.OnConnectedAsync();
}
When I call other methods in the C# Hub from JS the method is fired and
information is passed but I still have no access to the information the
Context Property should provide.
Please help me first by confirming or correcting my overall approach and if there are well known best practices available. Secondly please let me know how can I get information that the Context Property provides in the Hub and generally where this information is available and how to access and use them.
Many thanks in advance.
'User' is a claims principle (normally stored in the asp cookie), to get the User form your Identity database use:
var user = await _userManager.GetUserAsync(User);
For future reference, your question is very long, you will get more help if you keep questions brief and to the point.
I've solved my problem by using Authentication with SignalR. I don't need to add a user to any groups to push massages to them. In the Startup class I add Authentication above SignalR service and then the user object is passed to the Hub in the Context property. I can also push to any user by injecting the IHubContext to any class constructor I need.
When I send to PayPal the data the client wants to buy from my store I get an approval link. After the client check out I execute the payment.
I want to add my client username to the payment. After it will execute I will get the payment information and also the username and I will know which username paid me.
Is that possible to add another information to payments?
I actually don't think thats possible.
I remember we tried to add customerID to the call without succeeding.
What we did was to save the userdata we wanted to add to the request along with a session ID and then took the payment/order ID that you receive after making the call to Paypal and match the session ID with the one you saved before the request.
Something like that anyway, was a while ago :)
I am making my first subscription based website in MVC4 / C# / Razor and have created an Authorize.net "Card Not Present" sandbox account for testing.
I have implemented the subscription and it works like a charm. I am redirecting the new subscriber to the "Registration" page using the built in Visual Studio 2013 site that is created by default.
I have saved the SubscriptionId that was returned from Authorize.net and put it into a session variable. I then look at that session on the Registration page to see if it has a value or not.
If there is a value then I allow the user to create an account, otherwise I redirect them to an error page.
Is there anything you think I should add / best practices? I also planned on storing the SubscriptionId with the account when it gets created so I have a way to link up the user to a subscription on Auth.net's website.
Second question: Is there a way to ping Auth.net every time a user logs in so I can check to see if they still have an Active subscription? I would imagine that storing the SubscriptionId would be helpful so that is why I am saving it. I checked the documentation from Authorize.net and didn't see anything... I want to make sure people aren't getting a free ride out of the site...
Thanks in advance for your help / suggestions...
For your second question, if you've stored the subscriptionId in your database, you can use ARBGetSubscriptionStatusRequest to determine if they have an active subscription.
http://developer.authorize.net/api/reference/#recurring-billing-get-subscription-status
I'm trying to use AdaptivePayments to send funds from one user to another user via my site, so I can check whether or not they've actually gone through with the payment. The payment goes through, but they're not returned to my site so I can't track the payment.
I'm redirecting to `https://www.sandbox.paypal.com/webscr&cmd=_ap-payment&paykey=MYKEY
But I jsut get takn to 'My Account' and see the payment is successful, but not redirected.
I've also tried redirecting to https://sandbox.paypal.com/webapps/adaptivepayment/flow/pay?&paykey=MYKEY but I get:
This transaction has already been approved. Please visit your PayPal
Account Overview to see the details.
I'm redirecting by setting is NVPRequest["returnUrl"] = "http://mysite.com/APReturn.aspx but this is seemingly ignored. Is there a way to do this or a better method of achieving what I need?
Late, but for those who come across this on Google:
You should redirect to https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_ap-payment&paykey=MYKEY (note the addition of cgi-bin and change of & to ?).
In addition, I would strongly discourage you of using the return page as a means to track a buyer. Buyers can (and will) close their browser as soon as a payment has been completed.
Instead, I'd highly suggest looking into using PayPal Instant Payment Notifications (IPN).
PayPal IPN allows you to (asynchronously) process order information while not having to depend on the buyer to return to your website to complete the order.
You can use IPN by setting up a script which receives this (POST) data from PayPal. In addition, you must include the following code in your button and/or API call(s):
For Website Payments Standard (where "xxxxxxxx" is the full URL to your IPN script):
For Express Checkout:
Include NOTIFYURL=xxxxxxxx in your SetExpressCheckout and DoExpressCheckoutPayment API call
For Website Payments Pro
Include NOTIFYURL=xxxxxxxx in your DoDirectPayment API call
For Adaptive Payments
Include ipnNotificationUrl in your Pay request.
You can find sample code, documentation and further information on PayPal IPN at https://www.paypal.com/ipn
Not sure but have you tried this https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_AdaptivePayments.pdf ? Try to run serch through the documenet with keyword='returnurl' or keyword='retrun url'
Turns out that setting the email of the sender pre-approves the transaction.
The reason for the "This transaction has already been approved" may be that you're using an incorrect test account as the "sender" in the call to the PAY api.
Here's how to create the correct test account: http://www.pashabitz.com/2011/12/18/Adaptive+Payments+Error+This+Transaction+Has+Already+Been+Approved.aspx