/// <summary> /// Used to set IPN values with date and time information. /// </summary> /// <remarks> /// This method should not be used directly. Instead use /// <see cref="SetIpnTransactionProperties"/>. /// </remarks> /// <param name="key">The key used to find the property.</param> /// <param name="val">The value to set to the property.</param> /// <param name="ipn">The <see cref="IpnTransaction"/> to set to.</param> /// <returns>TRUE if a property was set, otherwise returns FALSE.</returns> private bool SetIpnTransactionProperties_Date(string key, string val, IpnTransaction ipn) { if (key == "payment_date") { ipn.PaymentDate = ConvertIpnDate(val); } else if (key == "auction_closing_date") { ipn.PaymentDate = ConvertIpnDate(val); } else { return false; } return true; }
private bool ProcessTransaction(IpnTransaction ipnTx) { // TODO: Determine what you want todo with the IPN transaction message. // For example, typically an ecommerce site would verify the order details with // the database to verify that the price was not changed and that the order was // actually placed by the original customer. // The following code will check for an existing shopping cart order // and update it's payment information. If the order was not found, // then this IPN is ignored. Also note that "Buy Now" purchases will // not have a corresponding order and thus IPN messages will be ignored. // Verify that the order is valid if (ipnTx.Custom == null || ipnTx.Custom == string.Empty) { return false; } //else //{ // if (!Config.Credits.Required) // { // // Try converting to int, should be an int and convertable if // // original order was placed by PayPalCommerce // try // { // subscriptionID = Int32.Parse(ipnTx.Custom); // } // catch (Exception) // { // throw new Exception(String.Format("Invalid subscription id - {0}", ipnTx.Custom)); // } // } //} //if (Config.Credits.Required) //{ if (ipnTx.TransactionType == TransactionType.Web_Accept) { int packageId; try { packageId = Int32.Parse(ipnTx.Items[0].ItemNumber); } catch (Exception) { throw new Exception(String.Format("Invalid package id - {0}", ipnTx.Items[0].ItemNumber)); } CreditsPackage package = CreditsPackage.Fetch(packageId); if (package == null) { throw new Exception(String.Format("There is no package with id = {0}", packageId)); } if (package.Price != (decimal)ipnTx.McGross) throw new Exception(String.Format("Invalid amount! The amount from the package {0} differs from the value {1} ", package.Price, (decimal)ipnTx.McGross)); User user; try { user = ezFixUp.Classes.User.Load(ipnTx.Custom); } catch (NotFoundException) { throw new Exception(String.Format("There is no user with username {0}", ipnTx.Custom)); } user.Credits += package.Quantity; user.Update(true); #region Apply affiliate commission string description = String.Format("Credits fee ({0}, {1})", package.Price, DateTime.Now); string notes = Config.AdminSettings.Payments.PayPalSandbox ? "SANDBOX" : "LIVEMODE"; int paymentHistoryID = Payments.SavePaymentHistory(user.Username, "PayPal", package.Price, description, notes, 1); AffiliateCommission.ApplyCommission(user.Username, paymentHistoryID, package.Price, notes); #endregion } //} else { int subscriptionID; try { subscriptionID = Int32.Parse(ipnTx.Custom); } catch (Exception) { throw new Exception(String.Format("Invalid subscription id - {0}", ipnTx.Custom)); } if (ipnTx.TransactionType == TransactionType.Subscr_Signup) { float amount = ipnTx.MC_AMOUNT3;//ipnTx.SubscriptionItems[2].Amount; int cycle = ipnTx.SubscriptionItems[2].Period; int cycleUnits = Convert.ToInt32(ipnTx.SubscriptionItems[2].TimeUnits); //some validations BillingPlan plan = BillingPlan.FetchBySubscriptionID(subscriptionID); if (amount != plan.Amount) { return false; } if (cycle != plan.Cycle || cycleUnits != Convert.ToInt32(plan.CycleUnit) ) { return false; } if (Config.AdminSettings.Payments.PayPalEmail.ToLower() != ipnTx.ReceiverEmail.ToLower()) { LogIPN(String.Format("The paypal email in the web.config file '{0}' is different from '{1}' that is configured in the merchant account", Config.AdminSettings.Payments.PayPalEmail.ToLower(), ipnTx.ReceiverEmail.ToLower())); return false; } //activate subscription Subscription subscription = Subscription.Fetch(subscriptionID); subscription.Activate(ipnTx.SubscrDate, plan); string description = String.Format("Subscription fee ({0}, {1})", plan.Amount, DateTime.Now); string notes = Config.AdminSettings.Payments.PayPalSandbox ? "SANDBOX" : "LIVEMODE"; int paymentHistoryID = Payments.SavePaymentHistory(subscription.Username, "PayPal", (decimal)plan.Amount, description, notes, 1); #region Apply affiliate commission AffiliateCommission.ApplyCommission(subscription.Username, paymentHistoryID, (decimal)plan.Amount, notes); #endregion } if (ipnTx.TransactionType == TransactionType.Subscr_Payment && ipnTx.PaymentStatus == PaymentStatus.Completed) { Subscription subscription = Subscription.Fetch(subscriptionID); BillingPlan plan = BillingPlan.FetchBySubscriptionID(subscriptionID); if (!subscription.Confirmed || subscription.RenewDate >= DateTime.Now.AddDays(3)) return true; subscription.Renew(plan); string description = String.Format("Subscription fee ({0}, {1})", plan.Amount, DateTime.Now); string notes = Config.AdminSettings.Payments.PayPalSandbox ? "SANDBOX" : "LIVEMODE"; int paymentHistoryID = Payments.SavePaymentHistory(subscription.Username, "PayPal", (decimal)plan.Amount, description, notes, 1); #region Apply affiliate commission AffiliateCommission.ApplyCommission(subscription.Username, paymentHistoryID, (decimal)plan.Amount, notes); #endregion } if (ipnTx.TransactionType == TransactionType.Subscr_Modify) { float amount = ipnTx.MC_AMOUNT3;//ipnTx.SubscriptionItems[2].Amount; int cycle = ipnTx.SubscriptionItems[2].Period; int cycleUnits = Convert.ToInt32(ipnTx.SubscriptionItems[2].TimeUnits); BillingPlan plan = BillingPlan.FetchByPlanData(amount, cycle, cycleUnits); Subscription subscription = Subscription.Fetch(subscriptionID); subscription.RenewDate = ipnTx.SubscrEffectiveDate; DateTime effectiveDate = ipnTx.SubscrEffectiveDate; switch (plan.CycleUnit) { case CycleUnits.Days: subscription.RenewDate = subscription.RenewDate.AddDays(plan.Cycle); break; case CycleUnits.Weeks: subscription.RenewDate = subscription.RenewDate.AddDays(plan.Cycle * 7); break; case CycleUnits.Months: subscription.RenewDate = subscription.RenewDate.AddMonths(plan.Cycle); break; case CycleUnits.Years: subscription.RenewDate = subscription.RenewDate.AddYears(plan.Cycle); break; } subscription.PlanID = plan.ID; subscription.Update(); } switch (ipnTx.TransactionType) { case TransactionType.Subscr_Cancel: Subscription.RequestCancellation(subscriptionID); break; case TransactionType.Subscr_Eot: //case TransactionType.Subscr_Cancel: //change the user's status to INACTIVE Subscription.Cancel(subscriptionID); ezFixUp.Classes.User.SetAsPaidUser(subscriptionID, false); break; } } return true; }
/// <summary> /// Used to set IPN values related to a product. /// </summary> /// <remarks> /// This method should not be used directly. Instead use /// <see cref="SetIpnTransactionProperties"/>. /// </remarks> /// <param name="key">The key used to find the property.</param> /// <param name="val">The value to set to the property.</param> /// <param name="ipn">The <see cref="IpnTransaction"/> to set to.</param> /// <returns>TRUE if a property was set, otherwise returns FALSE.</returns> private bool SetIpnTransactionProperties_Product(string key, string val, IpnTransaction ipn) { if (key.StartsWith("item_name")) { int itemIndex; try { itemIndex = Int32.Parse(key.Substring(9)); // 9 is itemIndex after "item_name" } catch (Exception) { // If no itemIndex, then just single item itemIndex = 1; } if (ipn.Items.Count < itemIndex) { for (int i = ipn.Items.Count; i < itemIndex; i++) { ipn.Items.Add(new CartItem()); } } ShoppingItem item = ipn.Items[itemIndex - 1]; item.ItemName = val; } else if (key.StartsWith("item_number")) { int itemIndex; try { itemIndex = Int32.Parse(key.Substring(11)); // 11 is itemIndex after "item_number" } catch (Exception) { // If no itemIndex, then just single item itemIndex = 1; } if (ipn.Items.Count < itemIndex) { for (int i = ipn.Items.Count; i < itemIndex; i++) { ipn.Items.Add(new CartItem()); } } ShoppingItem item = ipn.Items[itemIndex - 1]; item.ItemNumber = val; } else if (key.StartsWith("quantity")) { int itemIndex; try { itemIndex = Int32.Parse(key.Substring(8)); // 8 is itemIndex after "quantity" } catch (Exception) { // If no itemIndex, then just single item itemIndex = 1; } if (ipn.Items.Count < itemIndex) { for (int i = ipn.Items.Count; i < itemIndex; i++) { ipn.Items.Add(new CartItem()); } } CartItem item = (CartItem)ipn.Items[itemIndex - 1]; item.Quantity = Int32.Parse(val); } else { return false; } return true; }
/// <summary> /// Used to set IPN values related to a customer. /// </summary> /// <remarks> /// This method should not be used directly. Instead use /// <see cref="SetIpnTransactionProperties"/>. /// </remarks> /// <param name="key">The key used to find the property.</param> /// <param name="val">The value to set to the property.</param> /// <param name="ipn">The <see cref="IpnTransaction"/> to set to.</param> /// <returns>TRUE if a property was set, otherwise returns FALSE.</returns> private bool SetIpnTransactionProperties_Customer(string key, string val, IpnTransaction ipn) { // Only want to set these values switch (key) { case "first_name": ipn.CustomerInfo.FirstName = val; break; case "last_name": ipn.CustomerInfo.LastName = val; break; case "payer_business_name": ipn.CustomerInfo.BusinessName = val; break; case "address_name": ipn.CustomerInfo.AddressName = val; break; case "address_street": ipn.CustomerInfo.Address1 = val; break; case "address_city": ipn.CustomerInfo.City = val; break; case "address_state": ipn.CustomerInfo.State = val; break; case "address_zip": ipn.CustomerInfo.Zip = val; break; case "address_country": ipn.CustomerInfo.Country = val; break; case "address_status": ipn.SetProperty("address_status", val); break; case "payer_email": ipn.CustomerInfo.Email = val; break; case "payer_id": ipn.CustomerInfo.PayerID = val; break; case "payer_status": ipn.SetProperty("payer_status", val); break; default: return false; } return true; }
/// <summary> /// Used to set IPN values related to a subscription. /// </summary> /// <remarks> /// This method should not be used directly. Instead use /// <see cref="SetIpnTransactionProperties"/>. /// </remarks> /// <param name="key">The key used to find the property.</param> /// <param name="val">The value to set to the property.</param> /// <param name="ipn">The <see cref="IpnTransaction"/> to set to.</param> /// <returns>TRUE if a property was set, otherwise returns FALSE.</returns> private bool SetIpnTransactionProperties_SubscriptionItem(string key, string val, IpnTransaction ipn) { // Only want to set these values int nSubItemIndex; switch (key) { case "amount1": case "amount2": case "amount3": nSubItemIndex = Int32.Parse(key.Substring(6)) - 1; ipn.SubscriptionItems[nSubItemIndex].Amount = Convert.ToSingle(val); break; case "period1": case "period2": case "period3": nSubItemIndex = Int32.Parse(key.Substring(6)) - 1; // Parse the period IPN variable into it's parts string strPeriod, strTimeUnit; strPeriod = val.Substring(0, val.IndexOf(' ')); strTimeUnit = val.Substring(val.IndexOf(' ') + 1); // Set corresponding SubscriptionItems properties ipn.SubscriptionItems[nSubItemIndex].Period = Convert.ToInt32(strPeriod); switch (strTimeUnit.ToUpper()) { case "D": ipn.SubscriptionItems[nSubItemIndex].TimeUnits = SubscriptionPeriodUnits.Days; break; case "W": ipn.SubscriptionItems[nSubItemIndex].TimeUnits = SubscriptionPeriodUnits.Weeks; break; case "M": ipn.SubscriptionItems[nSubItemIndex].TimeUnits = SubscriptionPeriodUnits.Months; break; case "Y": ipn.SubscriptionItems[nSubItemIndex].TimeUnits = SubscriptionPeriodUnits.Years; break; } break; default: return false; } return true; }
/// <summary> /// Helper function used to set the property value for an <see cref="IpnTransaction"/> object /// for the given key. /// </summary> /// <param name="key">The key used to find the property.</param> /// <param name="val">The value to set to the property.</param> /// <param name="ipn">The <see cref="IpnTransaction"/> to set to.</param> private void SetIpnTransactionProperties(string key, string val, IpnTransaction ipn) { Debug.Assert(key != null, "Cannot find property with key == null!"); Debug.Assert(val != null, "Cannot set property with val == null!"); Debug.Assert(ipn != null, "Cannot set property with ipn == null!"); // Set Date/Time Properties if (SetIpnTransactionProperties_Date(key, val, ipn)) { return; } // Set Buyer Information Properties else if (SetIpnTransactionProperties_Customer(key, val, ipn)) { return; } // Set Product Information Properties else if (SetIpnTransactionProperties_Product(key, val, ipn)) { return; } // Set Subscriptions Information Properties else if (SetIpnTransactionProperties_SubscriptionItem(key, val, ipn)) { return; } // Set Generically else { ipn.SetProperty(key, val); } }
/// <summary> /// Creates an <see cref="IpnTransaction"/> based on the current instance of the IPN message. /// </summary> /// <remarks> /// This will use the current <see cref="HttpRequest.Form"/> values. /// </remarks> /// <returns>An instance of <see cref="IpnTransaction"/> that represents the current IPN.</returns> private IpnTransaction CreateIpnTransaction() { IpnTransaction ipn = new IpnTransaction(); // Do some preprocessing first if (Request.Form["txn_type"] == "cart") { // Figure out how many items in the cart int cartCount = Int32.Parse(Request.Form["num_cart_items"] ?? "1"); for (int i = 0; i < cartCount; i++) { ipn.Items.Add(new CartItem()); } } // Loop through all the keys in the Form Debug.Assert(Request.Form != null, "Form was null!"); Debug.Assert(Request.Form.Keys != null, "Form Keys was null!"); foreach (string key in Request.Form.Keys) { try { SetIpnTransactionProperties(key, Request.Form[key], ipn); } catch (Exception) { // An error in parsing the key/value will be skipped continue; } } ipn.RawIPN = Request.Form.ToString(); return ipn; }