def update(self, name, email, mc_use, mc_apikey, mc_donorlist, paypal_id, impressions, donate_parent, amount1, amount2, amount3, amount4, use_custom, confirmation_header, confirmation_info, confirmation_footer, confirmation_text, donor_report_text): s = self if name != s.name: s.name = name if email != s.email: s.email = email if email in tools.getAccountEmails(): raise Exception("Cannot have the same email as another organization.") if mc_use != s.mc_use: s.mc_use = mc_use if mc_apikey != s.mc_apikey: s.mc_apikey = mc_apikey if mc_donorlist != s.mc_donorlist: s.mc_donorlist = mc_donorlist if paypal_id != s.paypal_id: s.paypal_id = paypal_id if impressions != s.impressions: s.impressions = impressions if donate_parent != s.donate_parent: s.donate_parent = donate_parent if int(amount1) != s.amount1: s.amount1 = int(amount1) if int(amount2) != s.amount2: s.amount2 = int(amount2) if int(amount3) != s.amount3: s.amount3 = int(amount3) if int(amount4) != s.amount4: s.amount4 = int(amount4) if use_custom != s.use_custom: s.use_custom = use_custom if confirmation_header != s.confirmation_header: s.confirmation_header = confirmation_header if confirmation_info != s.confirmation_info: s.confirmation_info = confirmation_info if confirmation_footer != s.confirmation_footer: s.confirmation_footer = confirmation_footer if confirmation_text != s.confirmation_text: s.confirmation_text = confirmation_text if donor_report_text != s.donor_report_text: s.donor_report_text = donor_report_text s.put()
def post(self): # Below URL used for the live version. PP_URL = "https://www.paypal.com/cgi-bin/webscr" # Below URL used for testing with the sandbox - if this is uncommented, all real # donations will not be authenticated. ONLY use with dev versions. # PP_URL = "https://www.sandbox.paypal.com/cgi-bin/webscr" # Gets all account emails from Settings data models # to authenticate PayPal (don't accept payment from unknown) all_account_emails = tools.getAccountEmails() parameters = None if self.request.POST: parameters = self.request.POST.copy() if self.request.GET: parameters = self.request.GET.copy() payment_status = self.request.get("payment_status") logging.info("Payment status: " + payment_status) # Check payment is completed, not Pending or Failed. if payment_status == "Failed" or payment_status == "Pending": logging.error("Payment status is " + payment_status + ", so not continuing.") else: logging.info("All parameters: " + str(parameters)) # Check the IPN POST request came from real PayPal, not from a fraudster. if parameters: parameters['cmd'] = '_notify-validate' # Encode the parameters in UTF-8 out of Unicode str_parameters = {} for k, v in parameters.iteritems(): str_parameters[k] = unicode(v).encode('utf-8') params = urllib.urlencode(str_parameters) status = urlfetch.fetch( url=PP_URL, method=urlfetch.POST, payload=params, ).content if not status == "VERIFIED": logging.debug("PayPal returned status:" + str(status)) logging.debug('Error. The request could not be verified, check for fraud.') parameters['homemadeParameterValidity'] = False # Comparing receiver email to list of allowed email addresses try: receiver_email = parameters['receiver_email'] authenticated = False settings = None # If the receiver_email isn't in the database, this will fail settings = all_account_emails[receiver_email] authenticated = True logging.info("Getting payment to account: " + receiver_email + ", #: " + settings) except: authenticated = False logging.info("No match for incoming payment email address. Not continuing.") # Make sure money is going to the correct account - otherwise fraudulent if authenticated == True: # Currency of the donation # currency = parameters['mc_currency'] s = tools.getKey(settings).get() ipn_data = str(parameters) # Email and payer ID numbers try: email = parameters['payer_email'] except: email = None try: name = parameters['first_name'] + " " + parameters['last_name'] except: name = "Anonymous Donor" # Check if an address was given by the donor try: # Stich all the address stuff together address = [parameters['address_street'], parameters['address_city'], parameters['address_state'], parameters['address_zip']] except: address = None # Reading designation and notes values encoded in JSON from # donate form decoded_custom = None try: decoded_custom = json.loads(parameters["custom"]) team_key = tools.getKeyIfExists(decoded_custom[0]) individual_key = tools.getKeyIfExists(decoded_custom[1]) special_notes = decoded_custom[2] if s.exists.entity(team_key) == False: team_key = None if s.exists.entity(individual_key) == False: individual_key = None except: logging.error("Excepted on designation.") team_key = None individual_key = None special_notes = None try: cover_trans = decoded_custom[3] email_subscr = decoded_custom[4] except: cover_trans = False email_subscr = False try: phone = parameters['contact_phone'] if len(phone) > 10: special_notes += "\nContact phone: " + phone phone = None except: logging.info("Excepted on phone number.") phone = None confirmation_amount = tools.toDecimal(0) amount_donated = tools.toDecimal(0) try: confirmation_amount = parameters['mc_gross'] amount_donated = float(parameters['mc_gross']) - float(parameters['mc_fee']) except: pass # Find out what kind of payment this was - recurring, one-time, etc. try: payment_type = parameters['txn_type'] except: logging.info("Txn_type not available, so continuing with payment status") payment_type = payment_status if payment_type == "recurring_payment_profile_created" or payment_type == "subscr_signup": logging.info("This is the start of a recurring payment. Create info object.") payment_id = parameters['subscr_id'] # Duration between payments duration = "recurring" # s.create.recurring_donation(payment_id, duration, ipn_data) elif payment_type == "recurring_payment" or payment_type == "subscr_payment": logging.info("This is a recurring donation payment.") payment_id = parameters['subscr_id'] payment_type = "recurring" # Create a new donation s.create.donation(name, email, amount_donated, payment_type, confirmation_amount=confirmation_amount, phone=phone, address=address, team_key=team_key, individual_key=individual_key, payment_id=payment_id, special_notes=special_notes, email_subscr=email_subscr, ipn_data=ipn_data) elif payment_type == "web_accept": logging.info("This is a one-time donation.") if payment_status == "Completed": payment_id = parameters['txn_id'] # Create a new donation s.create.donation(name, email, amount_donated, "one-time", confirmation_amount=confirmation_amount, address=address, team_key=team_key, individual_key=individual_key, payment_id=payment_id, special_notes=special_notes, email_subscr=email_subscr, ipn_data=ipn_data) else: logging.info("Payment status not complete. Not logging the donation.") elif payment_type == "subscr_cancel": logging.info("A subscriber has cancelled.") amount_donated = "N/A" elif payment_type == "subscr_failed": logging.info("A subscriber payment has failed.") amount_donated = "N/A" elif payment_type == "Refunded": try: donation = models.Donation.gql("WHERE payment_id = :t", t=parameters["txn_id"]) donation_key = donation[0].key() donation_key.delete() logging.info("Refund detected and donation deleted. (" + donation_key.urlsafe() + ")") except: logging.info("Donation tried to be deleted, but failed. Most likely already deleted.") try: logging.info("Recording IPN") logging.info("Payment type: " + payment_type) logging.info("Name: " + name) logging.info("Email: " + email) logging.info("Amount donated: " + str(amount_donated)) except: logging.error("Failed somewhere in the logs.")