/// <summary> /// Saves on database the updated information for a payment account with the notified information that /// means an change on the payment gateway for that object. /// Braintree sends notifications through Webhooks to a configured URL, our page at that address /// manage it and call this when matched the Kind of notification related to the creation request /// for a Sub-merchant or Merchant account (aka provider payment account). /// </summary> /// <param name="notification"></param> public static void RegisterProviderPaymentAccountCreationNotification(WebhookNotification notification, string signature, string payload) { // If is not a SubMerchant creation, skip (maybe a new main merchant account was created) if (!notification.MerchantAccount.IsSubMerchant) { return; } var providerID = LcUtils.ExtractInt(notification.MerchantAccount.Id, 0); // Is not valid user if (providerID == 0) { using (var logger = new LcLogger("PaymentGatewayWebhook")) { logger.Log("SubMerchantAccount:: Impossible to get the provider UserID from next MerchantAccountID: {0}", notification.MerchantAccount.Id); logger.Log("SubMerchantAccount:: Follows signature and payload"); logger.LogData(signature); logger.LogData(payload); logger.Save(); } return; } LcData.SetProviderPaymentAccount( providerID, notification.MerchantAccount.Id, notification.MerchantAccount.Status.ToString(), notification.Message, signature, payload ); }
/// <summary> /// Create or update the payment account for the provider at the payment gateway (Braintree) given /// that user information. /// On Braintree Marketplace, this is called 'Create a Sub Merchant' /// </summary> /// <param name="user"></param> /// <param name="address"></param> /// <param name="bank"></param> /// <param name="gateway"></param> /// <returns>It returns the result of the Braintree transaction (check for IsSuccess to know the result), /// or null when there Braintree doesn't authorize the operation (AuthorizationException catched), /// it means the details are not complete or malformed.</returns> public static dynamic CreateProviderPaymentAccount(dynamic user, LcData.Address address, dynamic bank, DateTime BirthDate, string Ssn, BraintreeGateway gateway = null) { gateway = NewBraintreeGateway(gateway); // We need to detect what FundingDestination notify depending on the provided // information // Analizing source bank information: asterisks means 'not to set -- preseve previous value', other value is send being // null or empty to clear/remove previous value // Next variables will have null for 'not to set' or any other to be udpated. string routingNumber = null; string accountNumber = null; FundingDestination fundingDest = FundingDestination.EMAIL; if (bank != null) { // Null and asterisks values are not set if (bank.RoutingNumber != null && !bank.RoutingNumber.Contains("*")) { routingNumber = bank.RoutingNumber; } if (bank.AccountNumber != null && !bank.AccountNumber.Contains("*")) { accountNumber = bank.AccountNumber; } // We check against the bank object because has the original values. // Here, we allow an asterisks value as valid, because is a previous one // that will be preserved, or any new value to be set just different // from empty or null if (!String.IsNullOrEmpty(bank.AccountNumber) && !String.IsNullOrEmpty(bank.RoutingNumber)) { fundingDest = FundingDestination.BANK; } else if (!String.IsNullOrWhiteSpace(user.MobilePhone)) { fundingDest = FundingDestination.MOBILE_PHONE; } } var updateBankInfo = bank != null; var btAccount = GetProviderPaymentAccount((int)user.UserID); MerchantAccountRequest request = new MerchantAccountRequest { Individual = new IndividualRequest { FirstName = user.FirstName, LastName = user.LastName, Email = user.Email, Phone = user.MobilePhone, Address = new AddressRequest { StreetAddress = address.AddressLine1, // NOTE: We set the ExtendedAddress, but was communicated by Braintree on 2014-03-12 // that field is not being stored (support messages copies at #454). // On the interface, we rely on our db for the copied version of that address part as fallback. ExtendedAddress = address.AddressLine2, PostalCode = address.PostalCode, Locality = address.City, Region = address.StateProvinceCode, //CountryCodeAlpha2 = address.CountryCodeAlpha2 }, DateOfBirth = BirthDate.ToString("yyyy-MM-dd") }, TosAccepted = true, MasterMerchantAccountId = BraintreeMerchantAccountId, Id = LcPayment.GetProviderPaymentAccountId((int)user.UserID) }; if (btAccount == null || String.IsNullOrWhiteSpace(Ssn) || !Ssn.Contains("*")) { // Braintree require pass an empty string to remove the value of SSN in case of // user remove it from the form field: request.Individual.Ssn = String.IsNullOrWhiteSpace(Ssn) ? "" : Ssn; } // Set payment/funding information only on creation or explicitely // asked for update of its data if (btAccount == null || updateBankInfo) { request.Funding = new FundingRequest { Destination = fundingDest, Email = user.Email, MobilePhone = user.MobilePhone }; // On null, we don't set the values, empty to remove or value to set if (routingNumber != null) { request.Funding.RoutingNumber = routingNumber; } if (accountNumber != null) { request.Funding.AccountNumber = accountNumber; } } try{ Result <MerchantAccount> ret = null; if (btAccount == null) { ret = gateway.MerchantAccount.Create(request); } else { ret = gateway.MerchantAccount.Update(request.Id, request); } // All Ok, register on database if (ret.IsSuccess()) { LcData.SetProviderPaymentAccount( user.UserID, request.Id, btAccount == null ? "pending" : null, null, null, null ); } return(ret); } catch (Braintree.Exceptions.AuthorizationException ex) { throw ex; //return null; } }
public static void Set(PaymentAccount data) { // Gathering state and postal IDs and verifying they match var add = new LcRest.Address { postalCode = data.postalCode, countryCode = data.countryCode }; if (!LcRest.Address.AutosetByCountryPostalCode(add)) { throw new ValidationException("[[[Postal Code is not valid.]]]", "postalCode"); } else { data.city = add.city; data.stateProvinceCode = add.stateProvinceCode; } var emulateBraintree = ASP.LcHelpers.Channel == "localdev"; if (emulateBraintree) { LcData.SetProviderPaymentAccount( data.userID, "FAIK REQUEST ID: " + Guid.NewGuid(), "pending", null, null, null ); } else { var email = LcRest.UserProfile.GetEmail(data.userID); var result = LcPayment.CreateProviderPaymentAccount( new LcData.UserInfo { UserID = data.userID, FirstName = data.firstName, LastName = data.lastName, Email = email, MobilePhone = data.phone }, new LcData.Address { AddressLine1 = data.streetAddress, PostalCode = data.postalCode, City = data.city, StateProvinceCode = data.stateProvinceCode, CountryID = add.countryID }, new LcPayment.BankInfo { RoutingNumber = data.routingNumber, AccountNumber = data.accountNumber }, data.birthDate.Value, data.ssn ); if (result == null) { throw new ValidationException("[[[It looks like you already have an account set up with Braintree. Please contact us, and we can help.]]]"); } else if (!result.IsSuccess()) { throw new ValidationException(result.Message); //foreach (var err in result.Errors.All()) { } } } }