Reditect url from the method of notify_url of paypal in mvc - asp.net-mvc-4

i am using paypal for payment. in paypal i found two type url -
return_url
notify_url
i wan to check the validity after transaction, save some data and then redirect buyer to receipt page with a unique value that is saved in db. that is why i m not using redirect_url
here is my code
[HttpPost]
public ActionResult TestPaypalIpn()
{
var response = new StreamReader(Request.InputStream, System.Text.Encoding.UTF8).ReadToEnd();
var webClient = new WebClient();
string address = "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_notify-validate&" + response;
System.IO.File.WriteAllText(#"D:\Streamstech\Content\requestAddress.txt", address);
try
{
string result = webClient.DownloadString(address);
System.IO.File.WriteAllText(#"D:\Streamstech\Content\response.txt", result);
if (result == "VERIFIED")
{
if (Request.Params["payment_status"] == "Completed" && Request.Params["business"] == Request.Params["receiver_email"])
{
var lisenceKey = Request.Params["transaction_subject"];
var userProductLisence = UserProductLisenceRepository.GetConditional(
l => l.LisenceKey == lisenceKey).FirstOrDefault();
if (userProductLisence != null)
{
if (userProductLisence.PaypalTransactionId == null)
{
userProductLisence.PaypalTransactionId = Request.Params["txn_id"];
userProductLisence.PayerEmailForPaypalTransaction = Uri.EscapeUriString(Request.Params["payer_email"]);
UserProductLisenceRepository.Edit(userProductLisence);
return RedirectToAction("Receipt", "Transaction", new { requestId = userProductLisence.LisenceKey });
}
}
}
return RedirectToAction("ShowError", "Transaction", new { errorname = "", errorMessage = "something went wrong, try again later" });
}
return RedirectToAction("ShowError", "Transaction", new { errorname = "verification Problem", errorMessage = "Transaction not verified" });
}
catch (Exception e)
{
System.IO.File.WriteAllText(#"D:\Streamstech\Content\error.txt", e.Message);
return RedirectToAction("ShowError", "Transaction", new { errorname = "Error..!!!", errorMessage = "something went wrong, try again later" });
throw;
}
return null;
}
here i can compare, save data to database.. but it is not redirecting to receipt page.. what is the problem here in code...??
or any suggestion how can i do it.. ?
Thank You..

Based on your requirement, you need to use return_url instead of notify_url. For notify_url, it's used for receiving message in system back end and you maybe can't receive it immediately after payment is done. refer to https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNPDTAnAlternativetoIPN/

Related

Using MQTT ManagedClient with ASP NET API, how to?

I'm currently working on a project that has to rely heavily on MQTT - one of the parts that needs to utilize MQTT is a ASP Net API, but I'm having difficulties receiving messages.
Here is my MQTTHandler:
public MQTTHandler()
{
_mqttUrl = Properties.Resources.mqttURL ?? "";
_mqttPort = Properties.Resources.mqttPort ?? "";
_mqttUsername = Properties.Resources.mqttUsername ?? "";
_mqttPassword = Properties.Resources.mqttUsername ?? "";
_mqttFactory = new MqttFactory();
_tls = false;
}
public async Task<IManagedMqttClient> ConnectClientAsync()
{
var clientID = Guid.NewGuid().ToString();
var messageBuilder = new MqttClientOptionsBuilder()
.WithClientId(clientID)
.WithCredentials(_mqttUsername, _mqttPassword)
.WithTcpServer(_mqttUrl, Convert.ToInt32(_mqttPort));
var options = _tls ? messageBuilder.WithTls().Build() : messageBuilder.Build();
var managedOptions = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
.WithClientOptions(options)
.Build();
_mqttClient = new MqttFactory().CreateManagedMqttClient();
await _mqttClient.StartAsync(managedOptions);
Console.WriteLine("Klient startet");
return _mqttClient;
}
public async Task PublishAsync(string topic, string payload, bool retainFlag = true, int qos = 1)
{
await _mqttClient.EnqueueAsync(new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(payload)
.WithQualityOfServiceLevel((MQTTnet.Protocol.MqttQualityOfServiceLevel)qos)
.WithRetainFlag(retainFlag)
.Build());
Console.WriteLine("Besked published");
}
public async Task SubscribeAsync(string topic, int qos = 1)
{
var topicFilters = new List<MQTTnet.Packets.MqttTopicFilter>
{
new MqttTopicFilterBuilder()
.WithTopic(topic)
.WithQualityOfServiceLevel((MQTTnet.Protocol.MqttQualityOfServiceLevel)(qos))
.Build()
};
await _mqttClient.SubscribeAsync(topicFilters);
}
public Status GetSystemStatus(MqttApplicationMessageReceivedEventArgs e)
{
try
{
var json = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
var status = JsonSerializer.Deserialize<Status>(json);
if (status != null)
{
return status;
}
else
{
return null;
}
}
catch (Exception)
{
throw;
}
}
The above has been tested with a console app and works as it should.
The reason I need MQTT in the APi is that a POST method has to act on the value of a topic;
In particular I need to check a systems status before allowing the post;
[HttpPost]
public async Task<ActionResult<Order>> PostOrder(Order order)
{
if (_lastStatus != null)
{
if (_lastStatus.OpStatus)
{
return StatusCode(400, "System is busy!");
}
else
{
var response = await _orderManager.AddOrder(order);
return StatusCode(response.StatusCode, response.Message);
}
}
return StatusCode(400, "Something went wrong");
}
So I will need to set up a subscriber for this controller, and set the value of _lastStatus on received messages:
private readonly MQTTHandler _mqttHandler;
private IManagedMqttClient _mqttClient;
private Status _lastStatus;
public OrdersController(OrderManager orderManager)
{
_orderManager = orderManager;
_mqttHandler = new MQTTHandler();
_mqttClient = _mqttHandler.ConnectClientAsync().Result;
_mqttHandler.SubscribeAsync("JSON/Status");
_mqttClient.ApplicationMessageReceivedAsync += e =>
{
_lastStatus = _mqttHandler.GetSystemStatus(e);
return Task.CompletedTask;
};
}
However, it's behaving a little odd and I'm not experienced enough to know why.
The first time I make a POST request, _lastStatus is null - every following POST request seem to have the last retained message.
I'm guessing that I am struggling due to stuff being asynchronous, but not sure, and every attempt I've attempted to make it synchronous have failed.
Anyone have a clue about what I'm doing wrong?

change phone number in asp identity

I have problem with updating of phone number in my ASP net core application.
All fields except phone number are saving in DB. I tried 3 different ways to update phone:
set manualy
use UserManager.SetPhoneNumberAsync()
use UserManager.ChangePhoneNumberAsync() with token generation
All of them are not working. And there are no any errors. Help me please
[HttpPost][AllowAnonymous]
public async Task UpdateLogin(UpdateAccountRequest request)
{
try {
var user = await UserService.FindExistingUserAsync(request.CurrentEmail, request.CurrentPhoneNumber);
var account = user.Accounts.SingleOrDefault(x = > x.AccountId == request.AccountId);
account.FirstName = request.PatientFirstName;
account.LastName = request.PatientLastName;
var changePhoneNumberToken = await UserManager.GenerateChangePhoneNumberTokenAsync(user, request.UpdatedPhoneNumber);
var changePhoneResult = await UserManager.ChangePhoneNumberAsync(user, request.UpdatedPhoneNumber, changePhoneNumberToken);
if (!changePhoneResult.Succeeded) {
return StatusCode(StatusCodes.Status500InternalServerError, changePhoneResult.Errors);
}
var updateResult = await UserManager.UpdateAsync(user);
if (!result.Succeeded) {
return StatusCode(StatusCodes.Status500InternalServerError);
}
return Ok("User updated");
}
catch (Exception ex) {
return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
}
}
Problem disappeared. Loks like DB was not updated

Invalid token in reset password of Asp.Net web api

I'm working on a project using Asp.NET web api, and my authentication system is based on identity 2.0. When user sends the ResetPassword form, he gets "Invalid token"
this is my forgotpassword method
public async Task<HttpResponseMessage> ForgotPassword(ForgotPasswordViewModel model)
{
if (!ModelState.IsValid)
{
HttpError error = new HttpError(ModelState, false);
error.Message = Resource.No_Item_Found_Message;
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, error);
}
var user = await UserManager.FindByEmailAsync(model.Email);
if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
{
// Don't reveal that the user does not exist or is not confirmed
HttpError error = new HttpError();
error.Message = Resource.Process_Failed;
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, error);
}
var provider = new DpapiDataProtectionProvider("ECommerceWebApp");
UserManager.UserTokenProvider = new DataProtectorTokenProvider<ECommerceUser, string>(provider.Create("UserToken"));
var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
code = HttpUtility.UrlEncode(code);
try
{
// var callbackUrl = new Uri(Url.Link("ResetPasswordRoute", new { userId = user.Id, code = code, newPassword = model.Password }));
var callbackUrl = Url.Link("Default", new { Controller = "Account", action = "ResetPassword", userId = user.Id, code = code });
await UserManager.SendEmailAsync(user.Id, "تغییر رمز عبور در IRI1", "<div style='font-family:tahoma;direction:rtl;text-align:right;font-size:12px;'>" + "<h3>اولین و بزرگترین مرکز دادوستد بدون واسطه در ایران و کشورهای همسایه</h3>لطفاً با کلیک بر روی گزینۀ تغییر رمز به صفحۀ مربوطه بروید : <br/><br/>تغییر رمز عبور <br/><br/><br/><a href='iri1.com'>Iri1 Web Sites</a>" + "</div>");
}
catch (Exception ex)
{
HttpError error = new HttpError();
error.Message = ex.Message;
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, error);
}
return Request.CreateResponse(Resource.Reset_Password_Message_Client);
}
and this is my ResetPassword method
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await UserManager.FindByEmailAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
var code = HttpUtility.UrlDecode(model.Code);
var result = await UserManager.ResetPasswordAsync(user.Id, code, model.Password);
if (result.Succeeded)
{
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
AddErrors(result);
return View();
}
I still get invalid token error
I've just begun learning Identity Authentication and have no way to run samples from the Internet(I've got no visual studio). But I've noticed this method from GidHub samples, which seems to me to be wrong:
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPassword(string code = null)
{
return code == null ? View("Error") : View();
}
In my humble opinion this method should do this:
return code == null ? View("Error") : View(new ResetPasswordViewModel{Code = code});
And thus the hidden field in ResetPassword view contains the Code. When the user clicks the submit button this code will be posted with the email and password to the httppost ResetPassword action where you can access the code thus: model.Code
Now I hope you've got a valid token

How to send 1 million of push notification (APNS) within few second using PushSharp as webservice?

to do that i made a web service to send push (by referencing PushSharp library). I request web service through my web application. i retrieve list of device token from database(using web application) send to web service using for loop to send push. and get result/exception for each one. This process is very slow and take long long time to send notification. If anybody suggest me to what should i do i will be grateful to you.
public ActionResult SendNowToken(int certificateInfoId, string message, string certificate, int badgeNo, int pushtype, string password, string countryJsonString)
{
if (IsPushParameterValid(certificateInfoId, message, certificate, badgeNo, pushtype, password, countryJsonString))
{
var countryObject = new JavaScriptSerializer().Deserialize<Country>(countryJsonString);
var errorList = new List<ErrorList>();
byte[] certificatePath = System.IO.File.ReadAllBytes(HttpContext.Server.MapPath("~/Content/certificate/" + certificate));
foreach (var aDeviceToken in countryObject.DeviceTokens)
{
try
{
var serviceClient = new PushServiceSoapClient();
string serviceResult = serviceClient.SendPushNotification(message, badgeNo, pushtype, aDeviceToken.Token, certificatePath, password);
if (serviceResult != "Sent Notification")
{
var delimiters = new[] { ' ' };
string[] errorResult = serviceResult.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
string errorMessage = ConvertErrorCodeToErrorMessage(errorResult[0]);
var error = new ErrorList
{
CountryName = countryObject.CountryName,
ErrorTime = DateTime.Now,
ErrorMessage = errorMessage,
Token = aDeviceToken.Token
};
errorList.Add(error);
}
}
catch (Exception ex)
{
var error = new ErrorList
{
CountryName = countryObject.CountryName,
ErrorTime = DateTime.Now,
ErrorMessage = ex.Message,
Token = aDeviceToken.Token
};
errorList.Add(error);
}
}
if (errorList.Count != 0)
{
ViewBag.Message = "Push Notification does not send to country... ";
return PartialView("_SendAllError", errorList.ToList());
}
errorList.Clear();
}
return View();
}

return login success from a web api to an mvc 4 application

my colleague and myself are working on an application form with login functionality the user logs in from the mvc 4 app and there details are submitted to the web api to be checked against the values held in the database once verified the web api returns a loginResult class that contains the error message (if any) and a bool for stating whether it has been successful or not.
at the mvc 4 application level the code below is used to submit the login details to the web api:
Login Action
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(AccountViewModel model)
{
if (!ModelState.IsValid) return View("Login", model);
await _client.PostAsJsonAsync("api/Applicant/CheckApplicant", model)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
var service = DependencyResolver.Current.GetService<IApplyService>();
var loginResult = service.GetLoginResult();
var loginSuccess = loginResult.LoginSuccess;
if (loginSuccess != null && (bool) loginSuccess)
{
FormsAuthentication.SetAuthCookie(model.Email, model.RememberMe);
return RedirectToRoute("Terms And Conditions");
}
return View("Login");
}
the login details are then received at the web api in this method:
Check Applicant Method
public String CheckApplicant(Applicant applicant)
{
Int32 passwordFailureTimeoutMins = Convert.ToInt32(System.Configuration.ConfigurationSettings.AppSettings["PasswordFailureTimeoutMins"]);
Int32 passwordFailureAttempts = Convert.ToInt32(System.Configuration.ConfigurationSettings.AppSettings["PasswordFailureAttempts"]);
ApplicantRepository applicantRepository = new ApplicantRepository();
Applicant applicantDB = applicantRepository.GetById(applicant.Email);
LoginResult loginResult = new LoginResult();
PasswordHelper passwordHelper = new PasswordHelper();
if (applicantDB == null)
{
loginResult.LoginSuccess = false;
loginResult.LoginError = "Your password or login may not be correct.";
}
else
{
bool loginFailureCheck;
if (applicantDB.LoginFailureCount > passwordFailureAttempts)
{
System.TimeSpan diffResult = DateTime.Now.Subtract(Convert.ToDateTime(applicantDB.LastLoginFailure));
if (diffResult.Minutes < passwordFailureTimeoutMins)
{
loginFailureCheck = false;
}
else
{
loginFailureCheck = true;
}
}
else
{
loginFailureCheck = true;
}
if (passwordHelper.CheckPassword(applicant.Password, applicantDB.Password))
{
if(loginFailureCheck)
{
if(applicantDB.AccountActive)
{
loginResult.LoginSuccess = true;
loginResult.LoginError = "Login Successful.";
applicantDB.LastLoginFailure = null;
applicantDB.LastLoginSuccess = DateTime.Now;
applicantDB.LoginFailureCount = 0;
applicantRepository.Update(applicantDB);
}
else
{
loginResult.LoginSuccess = false;
loginResult.LoginError = "This account has been permanently banned.";
}
}
else
{
loginResult.LoginSuccess = false;
loginResult.LoginError = "This account is now temporarily disabled please wait " + passwordFailureTimeoutMins + " minutes before trying again";
applicantDB.LastLoginFailure = DateTime.Now;
applicantDB.LoginFailureCount = applicantDB.LoginFailureCount + 1;
applicantRepository.Update(applicantDB);
}
}
else
{
loginResult.LoginSuccess = false;
loginResult.LoginError = "Your password or login may not be correct.";
applicantDB.LastLoginFailure = DateTime.Now;
applicantDB.LoginFailureCount = applicantDB.LoginFailureCount + 1;
applicantRepository.Update(applicantDB);
}
}
return JsonConvert.SerializeObject(loginResult);
}
as you can see it returns a JsonConvert.SerializeObject(loginResult).
when this is done the process returns to the Login ActionResult as above it then moves to the GetLoginResult() method as shown below:
GetLoginResult
public LoginResult GetLoginResult()
{
const string uri = "http://localhost:55830/api/Applicant/CheckApplicant";
using (var httpClient = new HttpClient())
{
var response = httpClient.GetStringAsync(uri);
return JsonConvert.DeserializeObject<LoginResult>(response.Result);
}
}
when it get to this point it returns an error 405 method not allowed.
How do I consume the loginResult at the mvc 4 app level and what is the best way of sending the loginResult from the web api?
Any advice would be greatly appreciated.
Not sure what exactly you are trying to do but are you making a GET to read the result of the previous POST? You can read the response message of POST to get the result, like this.
public async Task<ActionResult> Login(AccountViewModel model)
{
if (!ModelState.IsValid) return View("Login", model);
var message = await _client.PostAsJsonAsync
("api/Applicant/CheckApplicant", model);
message.EnsureSuccessStatusCode();
LoginResult result = await message.Content.ReadAsAsync<LoginResult>();
// do other stuff here
}
Change the web API action method to return LoginResult directly. The framework will serialize it for you.
public LoginResult CheckApplicant(Applicant applicant)
{
}