How to retrieve checkout information when using Stripe SDK - asp.net

Here is my Cart and Checkout process in my web application
My purpose is after checkout, I retrieve the payment information like transaction Id or payment reference
In my ASP.NET MVC 5 application, I have following code in Cart View
<div>
#using (Html.BeginForm("", "Cart", FormMethod.Post))
{
... here I show products in cart ...
... NOTE that I don't have any action in my form ...
<input type="submit" id="stripe-checkout-button" value="Checkout" />
}
</div>
<script type="text/javascript">
var stripe = Stripe('#ViewBag.StripePublishKey');
var checkoutButton = document.getElementById('stripe-checkout-button');
checkoutButton.addEventListener('click', function () {
fetch('https://localhost:44323/Cart/CreateCheckoutSession', {
method: 'POST'
})
.then(function(response) {
return response.json();
})
.then(function(session) {
return stripe.redirectToCheckout({ sessionId: session.id });
})
.then(function(result) {
if (result.error) {
alert(result.error.message);
}
})
.catch(function(error) {
console.error('Error:', error);
});
});
</script>
In Cart controller I have following actions
[HttpPost]
public ActionResult CreateCheckoutSession()
{
var cart = (ShoppingCart)Session["cart"];
var options = new SessionCreateOptions
{
PaymentMethodTypes = new List<string> { "card" },
Mode = "payment",
SuccessUrl = Url.Action("CheckoutSuccessful", "Cart", null, Request.Url.Scheme),
CancelUrl = Url.Action("CheckoutCancelled", "Cart", null, Request.Url.Scheme),
PaymentIntentData = new SessionPaymentIntentDataOptions
{
CaptureMethod = "manual"
},
LineItems = new List<SessionLineItemOptions>()
};
foreach (var item in cart.Items)
{
// here I add the purchased product. I remove the code for simplification
}
var service = new SessionService();
Session session = service.Create(options);
ViewBag.SessionId = session.Id;
return Json(new { id = session.Id });
}
public ActionResult CheckoutSuccessful(string sessionId)
{
// sessionId is null here. I'm even not sure if I need this parameter
ShoppingCart cart = (ShoppingCart)Session["cart"];
return RedirectToAction("Index", "Checkout");
}
public ActionResult CheckoutCancelled()
{
return RedirectToAction("Index", "Cart");
}
When I click on Checkout button, the application redirects to Stripe payment page and I can enter email and billing information and click pay. It works well and payment goes through.
Based on my setting, the application redirects to CheckoutSuccessful action after that.
What I am missing here is, in CheckoutSuccessful action, I need to retrieve email address and billing address plus payment or transaction Id. I don't know how to do that.
In CheckoutSuccessful, the parameter sessionId is null. I don't know what I've done wrong here or what I'm missing.
Thanks for help.

You can ensure that the newly created Checkout Session ID is included in your success URL by appending {CHECKOUT_SESSION_ID to the success URL: https://stripe.com/docs/payments/checkout/custom-success-page#modify-success-url
Then on your success URL you can grab the Session ID from the query params and retrieve the Checkout Session.

After a few days research and try out, I figured it out.
After creating session, I need to store the session.Id in Http Session and in CheckoutSuccessful method (which does not need any parameter), I need to call couple of APIs to retrieve session and payment information like below:
var service = new SessionService();
var session = service.Get(the stored session.Id);
var custService = new CustomerService();
var customer = custService.Get(session.CustomerId);
var paymentService = new PaymentIntentService();
var payment = paymentService.Get(session.PaymentIntentId);
Then, I will have all required infromation in session, customer and payment objects.

Related

Scraping an ASP.NET website with NodeJS

i am trying to login to my supplier website programatically and get the resseller price by code. i have my username and password provided by the supplier to use in the website which is powred by ASP.NET. i tried to use the request module but got no luck with it.
this the code i used so far :
var request = require('request');
var j = request.jar();
var request = request.defaults({ jar : j }) //it will make the session default for every request
//...
request({
url:"https://www.XXXXX.com/login.aspx",
method:"POST",
form:{
ctl00$cpholder$txtUserName:"YYYYYYYY",
ctl00$cpholder$txtPassword:"ZZZZZZZZ"
}
},
function(err,response,body){
console.log(err);
// here i try to access the product page like a reseller
request({
url:"https://www.XXXXXX.com/productdetails.aspx?id=20000028&itemno=90NB0CL1-M08420",
method:"GET",
}, function(err, response, body){
console.log(err);
//Some logic
});
});
}
this is the login form code ( in pastebin because it is very long )
https://pastebin.com/kwuRdLX4
please help

AngularJS Get Method Not Work

I have an angular application, and I am trying to get a list of users from the server. I ran into an issue. I have page call CurrentUsers. If CurrentUsers method returns a Json Object, the entire object is display on the page regardless of what I do in the app controller and html page. If the method return a view, it does not display anything. However, I can hard code the json object in the cotroller, and it will work fine.
As a result, I created another method to return the json object. I made a call to that method, but it never reached the server. Your help will be very much appreciated.
The CurrentUsers Method returning a JSON Object, the entire json object display on the screen regardless
[HttpGet]
public JsonResult CurrentUsers()
{
List<Users> currentUser = new List<Users>()
{
new Users{ UserName = "JDoe", Professor="SSmith", Course = "English1"},
new Users{ UserName = "ADan", Professor="SDhor", Course = "Science"},
new Users{ UserName = "ADes", Professor="SCarry", Course = "Religion101"},
new Users{ UserName = "DJay", Professor="SCrowe", Course = "Teaching101"},
new Users{ UserName = "MAnne", Professor="TRow", Course = "PreCalc"},
};
return Json(new { Ok = true, data= currentUser });
// return View();
}
If the above method return a View, I can modify the controller as
shown below, and I will see the appropriate Information
Registration.controller('CurrentUsersController', function ($scope, $http) {
$scope.currentUsers = [{ "Professor": "SSmith", "UserName": "JDoe", "Course": "English1" }, { "Professor": "SDhor", "UserName": "ADan", "Course": "Science" }, { "Professor": "SCarry", "UserName": "ADes", "Course": "Religion101" }]
});
I modified the controller to use a service and created the method below to read the Current Users so that the view can simply return a View(). However, I have not been able to get the 'GET'to work.
[HttpGet]
public JsonResult GetUsers()
{
List<Users> currentUser = new List<Users>()
{
new Users{ UserName = "JDoe", Professor="SSmith", Course = "English1"},
new Users{ UserName = "ADan", Professor="SDhor", Course = "Science"},
new Users{ UserName = "ADes", Professor="SCarry", Course = "Religion101"},
new Users{ UserName = "DJay", Professor="SCrowe", Course = "Teaching101"},
new Users{ UserName = "MAnne", Professor="TRow", Course = "PreCalc"},
};
return Json(new { Ok = true, data = currentUser , message =
"Success"}, JsonRequestBehavior.AllowGet);
}
the modify CurrentUsers Method to return a view
public ActionResult CurrentUsers()
{
return View();
}
My modify controller
Registration.controller('CurrentUsersController', function ($scope, GetUSerService) {
$scope.message = 'this is the Current User controller';
$scope.currentUsers = [];
var result = GetUSerService.getData()
.then(function (result) {
console.log('the result');
console.log(result.data);
});
});
my service
Registration.service('GetUSerService', function ($http,$q) {
this.getData = function () {
var deferredObject = $q.defer();
$http.get('/Home/GetUsers').
success(function (data) {
console.log('service call data');
console.log(data);
deferredObject.resolve({ success: true, data : data.data });
}).
error(function () {
deferredObject.resolve({ success: false, data : '' });
});
return deferredObject.promise;
};
});
Updated 10/6 #5:50
#FernandoPinheiro answer works for me. The only thing is that the GetUsers action is being called twice.
Updated 10/7
I figured out why the post was being done twice. On my template, I had ng-app="Registration", and I had ng-controller= "CurrentUsersController". Because I specified the controller name in the route provider, I did not need it to add it to the partial view. As soon as I removed it from the view, it worked as expected.
Your GetUserService is calling $http.post('/Home/GetUsers') instead of $http.get('/Home/GetUsers').
Besides, shouldnt you set the Route attribute for the action ?

MailChimp API 3.0 Subscribe

I am having trouble sorting out the new MailChimp API (V3.0). It does not seem like there is a way to call a subscribe method. It seems like I have to use their Sign Up Form. Am I correct?
If by "subscribe" you mean that your application will add someone to a mailing list, you may want to take a look at the List Members Collection portion of their documentation.
http://kb.mailchimp.com/api/resources/lists/members/lists-members-collection
Adding/editing a subscriber via MailChimp v3.0 REST API.
// node/javascript specific, but pretty basic PUT request to MailChimp API endpoint
// dependencies (npm)
var request = require('request'),
url = require('url'),
crypto = require('crypto');
// variables
var datacenter = "yourMailChimpDatacenter", // something like 'us11' (after '-' in api key)
listId = "yourMailChimpListId",
email = "subscriberEmailAddress",
apiKey = "yourMailChimpApiKey";
// mailchimp options
var options = {
url: url.parse('https://'+datacenter+'.api.mailchimp.com/3.0/lists/'+listId+'/members/'+crypto.createHash('md5').update(email).digest('hex')),
headers: {
'Authorization': 'authId '+apiKey // any string works for auth id
},
json: true,
body: {
email_address: email,
status_if_new: 'pending', // pending if new subscriber -> sends 'confirm your subscription' email
status: 'subscribed',
merge_fields: {
FNAME: "subscriberFirstName",
LNAME: "subscriberLastName"
},
interests: {
MailChimpListGroupId: true // if you're using groups within your list
}
}
};
// perform update
request.put(options, function(err, response, body) {
if (err) {
// handle error
} else {
console.log('subscriber added to mailchimp list');
}
});

Getting a username from ID without autopublish

I just got done with the rough draft of my app, and thought it was time to remove autopublish and insecure mode. I started transfering all the stray update and insert methods I had been calling on the client to methods. But now I'm having trouble returning a username from an ID.
My function before: (that worked, until I removed autopublish)
challenger: function() {
var postId = Session.get('activePost');
var post = Posts.findOne(postId);
if (post.challenger !== null) {
var challenger = Meteor.users.findOne(post.challenger);
return challenger.username;
}
return false;
}
Now what I'm trying:
Template.lobby.helpers({
challenger: function() {
var postId = Session.get('activePost');
var post = Posts.findOne(postId);
if (post.challenger !== null) {
var userId = post.challenger;
Meteor.call('getUsername', userId, function (err, result) {
if (err) {
console.log(err);
}
return result;
});
}
return false;
},
Using:
Meteor.methods({
getUsername: function(userId) {
var user = Meteor.users.findOne({_id: userId});
var username = user.username;
return username;
},
...
})
I have tried blocking the code, returning values only once they're defined, and console.logging in the call-callback (which returned the correct username to console, but the view remained unchanged)
Hoping someone can find the obvious mistake I'm making, because I've tried for 3 hours now and I can't figure out why the value would be returned in console but not returned to the template.
Helpers need to run synchronously and should not have any side effects. Instead of calling a method to retrieve the user, you should ensure the user(s) you need for that route/template are published. For example your router could wait on subscriptions for both the active post and the post's challenger. Once the client has the necessary documents, you can revert to your original code.

Custom Meteor enroll template

In my application I want to seed the database with users and send them an enrollment link to activate their account (and choose a password). I also want them to verify/change some profile data.
On the server I seed the database like this:
Meteor.startup(function () {
if(Meteor.users.find().count() === 0) {
var user_id = Accounts.createUser({ email: 'some#email.com', profile: { some: 'profile' } });
Accounts.sendEnrollmentEmail(user_id);
}
})
The enrollment link is sent as expected, but I want to create a custom template for when the url in the email is clicked. Preferably handled by iron-router. (Not using the accounts-ui package).
I tried things like redirecting the user to a custom route like this:
var doneCallback, token;
Accounts.onEnrollmentLink(function (token, done) {
doneCallback = done;
token = token;
Router.go('MemberEnroll')
});
which is not working (it changes the url but not rendering my template)
I also tried to change the enroll URL on the server like this:
Accounts.urls.enrollAccount = function (token) {
return Meteor.absoluteUrl('members/enroll/' + token);
};
But when I do this, the Accounts.onEnrollmentLink callback does not fire.
Also, changing the URL is not documented so I'm not sure its a good practice at all.
Any help is appreciated.
In my application I'm doing like this
this.route('enroll', {
path: '/enroll-account/:token',
template: 'enroll_page',
onBeforeAction: function() {
Meteor.logout();
Session.set('_resetPasswordToken', this.params.token);
this.subscribe('enrolledUser', this.params.token).wait();
},
data: function() {
if(this.ready()){
return {
enrolledUser: Meteor.users.findOne()
}
}
}
})
As enrollment url is like this
http://www.yoursite.com/enroll-account/hkhk32434kh42hjkhk43
when users click on the link they will redirect to this template and you can render your template
In my publication
Meteor.publish('enrolledUser', function(token) {
return Meteor.users.find({"services.password.reset.token": token});
});
After taking the password from the user
Accounts.resetPassword(token, creds.password,function(e,r){
if(e){
alert("Sorry we could not reset your password. Please try again.");
}else{
alert("Logged In");
Router.go('/');
}
})
enroll link
Accounts.urls.enrollAccount = function (token) {
return Meteor.absoluteUrl('enroll-account/' + token);
};
Im afraid now isnt possible, what i did is changing the html and css using "rendered" function but it has some probs with delay
Meteor.startup(function(){
Template["_enrollAccountDialog"].rendered = function(){
document.getElementById('enroll-account-password-label').innerHTML = 'Escolha sua senha';
$('.accounts-dialog').css('background-color','#f4f5f5');
$('.accounts-dialog').css('text-align','center');
$('.accounts-dialog').removeAttr('width');
document.getElementById('login-buttons-enroll-account-button').className = ' create-account-button';
document.getElementById('login-buttons-enroll-account-button').innerHTML = 'Criar conta';
}
});

Resources