public bool ProcessPayPalSubscription(byte[] ipnBytes, PayPalVariables variables)
        {
            switch (variables.txn_type)
            {
                case "subscr_payment":
                    return this.ProcessPayPalDonation(ipnBytes, variables);

                case "subscr_signup":
                    return this.HandleSignup(ipnBytes, variables);                
            }
            if (variables.payment_status.Equals("refunded", StringComparison.OrdinalIgnoreCase))
            {
                return this.HandleRefunded(ipnBytes, variables);
            }
            return false;
        }
 public bool ProcessPayPalDonation(byte[] ipnBytes, PayPalVariables variables)
 {
     if (variables.payment_status.Equals("refunded", StringComparison.OrdinalIgnoreCase))
     {
         return this.HandleRefunded(ipnBytes, variables);
     }
     if (!this.ValidateDonation(variables))
     {
         return false;
     }
     try
     {
         var donation = Mapper.Map(variables, new Donation());
         if (variables.txn_type.Equals("subscr_payment", StringComparison.OrdinalIgnoreCase))
         {
             var subscription = _donationRepository.GetDonationSubscription(variables.subscr_id);
             donation.DonationSubscriptionId = subscription.DonationSubscriptionId;
         }
         donation = _donationRepository.CreateDonation(donation);
         string response;
         if (_paypalService.TryReplyToIpn(ipnBytes, out response))
         {
             donation.ExternalStatus = variables.payment_status;
             if (response.Equals("verified", StringComparison.OrdinalIgnoreCase))
             {
                 return this.HandleVerified(variables, donation);
             }
             else
             {
                 this.LogFailure(ipnBytes, response);
                 _donationRepository.CompleteTransaction(donation);
             }
         }
     }
     catch (Exception ex)
     {
         Log.Error("Error while processing PayPal donation IPN.", ex);
     }
     return false;
 }
 public bool TryGetGeoLocation(PayPalVariables source, out GeoLocation location)
 {
     location = null;
     return false;
 }
        private bool HandleVerified(PayPalVariables variables, Donation donation) 
        {
            Log.InfoFormat("{0} - {1}, {2} - OK", variables.txn_id, variables.mc_gross, variables.mc_currency);

            if (variables.payment_status.Equals("completed", StringComparison.OrdinalIgnoreCase))
            {
                donation.IsCompleted = true;
                donation.ExternalStatus = variables.payment_status;
                try
                {
                    GeoLocation location;
                    if (_geocodeService.TryGetGeoLocation(variables, out location))
                    {
                        donation.CityId = location.City.CityId;
                        donation.StateId = location.State.StateId;
                        donation.CountryId = location.Country.CountryId;
                    }
                    var custom = JsonConvert.DeserializeObject<PayPalCustom>(variables.custom);
                    _donationRepository.CompleteTransaction(donation);
                    if (location != null && location.Address != null)
                    {
                        _accountRepository.UpdateUserProfileAddress(custom.UserId, location.Address);
                    }
                    //var contactInfo = _accountRepository.GetUserContactInfo(custom.UserId);
                    //if (contactInfo != null)
                    //{
                    //    _emailService.SendEmail(variables.ReplyEmail, contactInfo.Email, variables.EmailSubject, variables.EmailMessage);
                    //}
                    return true;
                }
                catch (Exception ex)
                {
                    Log.Error("Manual investigation required.", ex);
                }
            }
            return false;
        }
 public bool ValidateSubscription(PayPalVariables variables)
 {
     if (!_donationRepository.SubscriptionCompleted(variables.subscr_id))
     {
         if (!variables.receiver_email.Equals(_paypalEmail, StringComparison.OrdinalIgnoreCase))
         {
             Log.WarnFormat("Email 'receiver_email' value '{0}' does not match our email '{1}'.", variables.receiver_email, _paypalEmail);
             return false;
         }
         if (string.IsNullOrWhiteSpace(variables.subscr_id))
         {
             Log.Warn("Parameter 'txn_id' is empty.");
             return false;
         }
         if (string.IsNullOrWhiteSpace(variables.custom))
         {
             Log.Warn("Parameter 'custom' is empty.");
             return false;
         }
         return true;
     }
     return false;
 }
 private bool HandleRefunded(byte[] ipnBytes, PayPalVariables variables) 
 {
     string response;
     if (_paypalService.TryReplyToIpn(ipnBytes, out response))
     {
         if (response.Equals("verified", StringComparison.OrdinalIgnoreCase))
         {
             _donationRepository.RefundDonation(variables.parent_txn_id, variables.payment_status);
             return true;
         }
         else
         {
             this.LogFailure(ipnBytes, response);
         }
     }
     return false;
 }
 private bool HandleSignup(byte[] ipnBytes, PayPalVariables variables)
 {
     if (!this.ValidateSubscription(variables))
     {
         return false;
     }
     try
     {
         var subscription = Mapper.Map(variables, new DonationSubscription());
         subscription.EndDate = subscription.StartDate.AddMonths(subscription.RecurrenceTimes);
         _donationRepository.CreateDonationSubscription(subscription);
         string response;
         if (_paypalService.TryReplyToIpn(ipnBytes, out response))
         {
             if (response.Equals("verified", StringComparison.OrdinalIgnoreCase))
             {
                 return true;
             }
             else
             {
                 this.LogFailure(ipnBytes, response);
             }
         }
     }
     catch (Exception ex)
     {
         Log.Error("Manual investigation required.", ex);
     }
     return false;
 }
        public bool TryGetGeoLocation(PayPalVariables source, out GeoLocation location)
        {
            location = new GeoLocation();
            try
            {
                var geoCountry = GetCountry(source.address_country, source.address_country_code);
                var geoCity = GetCity(source.address_city, source.address_state, source.address_zip, source.address_country, source.address_country_code);
                var geoState = GetState(geoCity.State, source.address_country, source.address_country_code);

                City city;
                State state;
                Country country;
                var isCity = _metadataRepository.TryGetCity(geoCity.Name, geoState.Name, geoCity.PostalCode, geoCountry.FullName, out city);
                var isState = _metadataRepository.TryGetState(geoState.Name, geoCountry.FullName, out state);   
                var isCountry = _metadataRepository.TryGetCountry(geoCountry.FullName, out country);                                          

                if (!isCountry)
                {                    
                    country = _metadataRepository.CreateCountry(geoCountry);
                }
                if (!isState)
                {                    
                    geoState.CountryId = country.CountryId;
                    state = _metadataRepository.CreateState(geoState);
                }
                if (!isCity)
                {
                    geoCity.StateId = state.StateId;
                    geoCity.PostalCode = geoCity.PostalCode;
                    city = _metadataRepository.CreateCity(geoCity);
                }
                var address = GetAddress(source.address_street, city.Name, state.FullName, city.PostalCode, country.FullName, country.Name);
                if (address != null)
                {
                    address.CityId = city.CityId;
                    address.StateId = state.StateId;
                    address.CountryId = country.CountryId;
                    location.Address = address;
                }                
                location.City = city;
                location.State = state;
                location.Country = country;
                location.IsGeocoded = true;
                return true;
            }
            catch (Exception ex)
            {
                Log.Error("Error while Geocoding.", ex);
            }
            return false;
        }
 public ActionResult PayPalSubscriptionIpn(PayPalVariables model)
 {
     Response.ContentType = "text/html";
     if (_donationService.ProcessPayPalSubscription(Request.BinaryRead(Request.ContentLength), model))
     {
         return new HttpStatusCodeResult(HttpStatusCode.OK);
     }
     return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
 }