def complete_gold_purchase(secret, transaction_id, payer_email, payer_id, subscription_id, pennies, months, goldtype, buyer, recipient, signed, giftmessage, comment): """After receiving a message from a payment processor, apply gold. Shared endpoint for all payment processing systems. Validation of gold purchase (sender, recipient, etc.) should happen before hitting this. """ gold_recipient = recipient or buyer with gold_lock(gold_recipient): gold_recipient._sync_latest() days = days_from_months(months) if goldtype in ('onetime', 'autorenew'): admintools.engolden(buyer, days) if goldtype == 'onetime': subject = "thanks for buying reddit gold!" if g.lounge_reddit: message = strings.lounge_msg else: message = ":)" else: subject = "your reddit gold has been renewed!" message = ("see the details of your subscription on " "[your userpage](/u/%s)" % buyer.name) elif goldtype == 'creddits': buyer._incr('gold_creddits', months) subject = "thanks for buying creddits!" message = ("To spend them, visit http://%s/gold or your favorite " "person's userpage." % (g.domain)) elif goldtype == 'gift': send_gift(buyer, recipient, months, days, signed, giftmessage, comment) subject = "thanks for giving reddit gold!" message = "Your gift to %s has been delivered." % recipient.name status = 'processed' secret_pieces = [goldtype] if goldtype == 'gift': secret_pieces.append(recipient.name) secret_pieces.append(secret) secret = '-'.join(secret_pieces) try: create_claimed_gold(transaction_id, payer_email, payer_id, pennies, days, secret, buyer._id, c.start_time, subscr_id=subscription_id, status=status) except IntegrityError: g.log.error('gold: got duplicate gold transaction') try: message = append_random_bottlecap_phrase(message) send_system_message(buyer, subject, message, distinguished='gold-auto') except MessageError: g.log.error('complete_gold_purchase: could not send system message')
def complete_gold_purchase(secret, transaction_id, payer_email, payer_id, subscription_id, pennies, months, goldtype, buyer, recipient, signed, giftmessage, comment): """After receiving a message from a payment processor, apply gold. Shared endpoint for all payment processing systems. Validation of gold purchase (sender, recipient, etc.) should happen before hitting this. """ gold_recipient = recipient or buyer with gold_lock(gold_recipient): gold_recipient._sync_latest() days = days_from_months(months) if goldtype in ('onetime', 'autorenew'): admintools.engolden(buyer, days) if goldtype == 'onetime': subject = "thanks for buying reddit gold!" if g.lounge_reddit: lounge_url = "/r/" + g.lounge_reddit message = strings.lounge_msg % dict(link=lounge_url) else: message = ":)" else: subject = "your reddit gold has been renewed!" message = ("see the details of your subscription on " "[your userpage](/u/%s)" % buyer.name) elif goldtype == 'creddits': buyer._incr('gold_creddits', months) subject = "thanks for buying creddits!" message = ("To spend them, visit http://%s/gold or your favorite " "person's userpage." % (g.domain)) elif goldtype == 'gift': send_gift(buyer, recipient, months, days, signed, giftmessage, comment) subject = "thanks for giving reddit gold!" message = "Your gift to %s has been delivered." % recipient.name status = 'processed' secret_pieces = [goldtype] if goldtype == 'gift': secret_pieces.append(recipient.name) secret_pieces.append(secret) secret = '-'.join(secret_pieces) try: create_claimed_gold(transaction_id, payer_email, payer_id, pennies, days, secret, buyer._id, c.start_time, subscr_id=subscription_id, status=status) except IntegrityError: g.log.error('gold: got duplicate gold transaction') try: send_system_message(buyer, subject, message) except MessageError: g.log.error('complete_gold_purchase: could not send system message')
def finish(self, parameters, txn_id, payer_email, paying_id, subscr_id, custom, pennies, months, days): blob_key, payment_blob = get_blob(custom) buyer_id = payment_blob.get('account_id', None) if not buyer_id: dump_parameters(parameters) raise ValueError("No buyer_id in IPN with custom='%s'" % custom) try: buyer = Account._byID(buyer_id) except NotFound: dump_parameters(parameters) raise ValueError("Invalid buyer_id %d in IPN with custom='%s'" % (buyer_id, custom)) if subscr_id: buyer.gold_subscr_id = subscr_id instagift = False if payment_blob['goldtype'] in ('autorenew', 'onetime'): admintools.engolden(buyer, days) subject = _("Eureka! Thank you for investing in reddit gold!") message = _("Thank you for buying reddit gold. Your patronage " "supports the site and makes future development " "possible. For example, one month of reddit gold " "pays for 5 instance hours of reddit's servers.") message += "\n\n" + strings.gold_benefits_msg if g.lounge_reddit: message += "\n* " + strings.lounge_msg elif payment_blob['goldtype'] == 'creddits': buyer._incr("gold_creddits", months) buyer._commit() subject = _("Eureka! Thank you for investing in reddit gold " "creddits!") message = _("Thank you for buying creddits. Your patronage " "supports the site and makes future development " "possible. To spend your creddits and spread reddit " "gold, visit [/gold](/gold) or your favorite " "person's user page.") message += "\n\n" + strings.gold_benefits_msg + "\n\n" message += _("Thank you again for your support, and have fun " "spreading gold!") elif payment_blob['goldtype'] == 'gift': recipient_name = payment_blob.get('recipient', None) try: recipient = Account._by_name(recipient_name) except NotFound: dump_parameters(parameters) raise ValueError("Invalid recipient_name %s in IPN/GC with custom='%s'" % (recipient_name, custom)) signed = payment_blob.get("signed", False) giftmessage = _force_unicode(payment_blob.get("giftmessage", "")) comment_id = payment_blob.get("comment") send_gift(buyer, recipient, months, days, signed, giftmessage, comment_id) instagift = True subject = _("Thanks for giving the gift of reddit gold!") message = _("Your classy gift to %s has been delivered.\n\n" "Thank you for gifting reddit gold. Your patronage " "supports the site and makes future development " "possible.") % recipient.name message += "\n\n" + strings.gold_benefits_msg + "\n\n" message += _("Thank you again for your support, and have fun " "spreading gold!") else: dump_parameters(parameters) raise ValueError("Got status '%s' in IPN/GC" % payment_blob['status']) # Reuse the old "secret" column as a place to record the goldtype # and "custom", just in case we need to debug it later or something secret = payment_blob['goldtype'] + "-" + custom if instagift: status="instagift" else: status="processed" create_claimed_gold(txn_id, payer_email, paying_id, pennies, days, secret, buyer_id, c.start_time, subscr_id, status=status) message = append_random_bottlecap_phrase(message) send_system_message(buyer, subject, message, distinguished='gold-auto') payment_blob["status"] = "processed" g.hardcache.set(blob_key, payment_blob, 86400 * 30)
def POST_ipn(self, paypal_secret, payment_status, txn_id, paying_id, payer_email, mc_currency, mc_gross, custom): parameters = request.POST.copy() # Make sure it's really PayPal if paypal_secret != g.PAYPAL_SECRET: log_text("invalid IPN secret", "%s guessed the wrong IPN secret" % request.ip, "warning") raise ValueError # Return early if it's an IPN class we don't care about response, psl = check_payment_status(payment_status) if response: return response # Return early if it's a txn_type we don't care about response, subscription = check_txn_type(parameters['txn_type'], psl) if subscription is None: subscr_id = None elif subscription == "new": subscr_id = parameters['subscr_id'] elif subscription == "cancel": cancel_subscription(parameters['subscr_id']) else: raise ValueError("Weird subscription: %r" % subscription) if response: return response # Check for the debug flag, and if so, dump the IPN dict if g.cache.get("ipn-debug"): g.cache.delete("ipn-debug") dump_parameters(parameters) if mc_currency != 'USD': raise ValueError("Somehow got non-USD IPN %r" % mc_currency) if not (txn_id and paying_id and payer_email and mc_gross): dump_parameters(parameters) raise ValueError("Got incomplete IPN") pennies = int(mc_gross * 100) months, days = months_and_days_from_pennies(pennies) # Special case: autorenewal payment existing = existing_subscription(subscr_id, paying_id, custom) if existing: if existing != "deleted account": create_claimed_gold ("P" + txn_id, payer_email, paying_id, pennies, days, None, existing._id, c.start_time, subscr_id) admintools.engolden(existing, days) g.log.info("Just applied IPN renewal for %s, %d days" % (existing.name, days)) return "Ok" # More sanity checks that all non-autorenewals should pass: if not custom: dump_parameters(parameters) raise ValueError("Got IPN with txn_id=%s and no custom" % txn_id) self.finish(parameters, "P" + txn_id, payer_email, paying_id, subscr_id, custom, pennies, months, days)
def finish(self, parameters, txn_id, payer_email, paying_id, subscr_id, custom, pennies, months, days): blob_key, payment_blob = get_blob(custom) buyer_id = payment_blob.get('account_id', None) if not buyer_id: dump_parameters(parameters) raise ValueError("No buyer_id in IPN/GC with custom='%s'" % custom) try: buyer = Account._byID(buyer_id) except NotFound: dump_parameters(parameters) raise ValueError("Invalid buyer_id %d in IPN/GC with custom='%s'" % (buyer_id, custom)) if subscr_id: buyer.gold_subscr_id = subscr_id instagift = False if payment_blob['goldtype'] in ('autorenew', 'onetime'): admintools.engolden(buyer, days) subject = _("thanks for buying reddit gold!") if g.lounge_reddit: lounge_url = "/r/" + g.lounge_reddit message = strings.lounge_msg % dict(link=lounge_url) else: message = ":)" elif payment_blob['goldtype'] == 'creddits': buyer._incr("gold_creddits", months) buyer._commit() subject = _("thanks for buying creddits!") message = _("To spend them, visit [/gold](/gold) or your favorite person's userpage.") elif payment_blob['goldtype'] == 'gift': recipient_name = payment_blob.get('recipient', None) try: recipient = Account._by_name(recipient_name) except NotFound: dump_parameters(parameters) raise ValueError("Invalid recipient_name %s in IPN/GC with custom='%s'" % (recipient_name, custom)) signed = payment_blob.get("signed", False) giftmessage = _force_unicode(payment_blob.get("giftmessage", "")) comment_id = payment_blob.get("comment") send_gift(buyer, recipient, months, days, signed, giftmessage, comment_id) instagift = True subject = _("thanks for giving reddit gold!") message = _("Your gift to %s has been delivered." % recipient.name) else: dump_parameters(parameters) raise ValueError("Got status '%s' in IPN/GC" % payment_blob['status']) # Reuse the old "secret" column as a place to record the goldtype # and "custom", just in case we need to debug it later or something secret = payment_blob['goldtype'] + "-" + custom if instagift: status="instagift" else: status="processed" create_claimed_gold(txn_id, payer_email, paying_id, pennies, days, secret, buyer_id, c.start_time, subscr_id, status=status) send_system_message(buyer, subject, message) payment_blob["status"] = "processed" g.hardcache.set(blob_key, payment_blob, 86400 * 30)
def complete_gold_purchase(cls, webhook): """After receiving a message from a payment processor, apply gold. Shared endpoint for all payment processing systems. Validation of gold purchase (sender, recipient, etc.) should happen before hitting this. """ secret = webhook.passthrough transaction_id = webhook.transaction_id payer_email = webhook.payer_email payer_id = webhook.payer_id subscr_id = webhook.subscr_id pennies = webhook.pennies months = webhook.months goldtype = webhook.goldtype buyer = webhook.buyer recipient = webhook.recipient signed = webhook.signed giftmessage = webhook.giftmessage comment = webhook.comment gold_recipient = recipient or buyer with gold_lock(gold_recipient): gold_recipient._sync_latest() days = days_from_months(months) if goldtype in ("onetime", "autorenew"): admintools.engolden(buyer, days) if goldtype == "onetime": subject = "thanks for buying reddit gold!" if g.lounge_reddit: message = strings.lounge_msg else: message = ":)" else: subject = "your reddit gold has been renewed!" message = "see the details of your subscription on " "[your userpage](/u/%s)" % buyer.name elif goldtype == "creddits": buyer._incr("gold_creddits", months) subject = "thanks for buying creddits!" message = "To spend them, visit http://%s/gold or your " "favorite person's userpage." % (g.domain) elif goldtype == "gift": send_gift(buyer, recipient, months, days, signed, giftmessage, comment) subject = "thanks for giving reddit gold!" message = "Your gift to %s has been delivered." % recipient.name status = "processed" secret_pieces = [goldtype] if goldtype == "gift": secret_pieces.append(recipient.name) secret_pieces.append(secret or "") secret = "-".join(secret_pieces) try: create_claimed_gold( transaction_id, payer_email, payer_id, pennies, days, secret, buyer._id, c.start_time, subscr_id=subscr_id, status=status, ) except IntegrityError: g.log.error("gold: got duplicate gold transaction") try: message = append_random_bottlecap_phrase(message) send_system_message(buyer, subject, message, distinguished="gold-auto") except MessageError: g.log.error("complete_gold_purchase: send_system_message error")
def complete_gold_purchase(cls, webhook): """After receiving a message from a payment processor, apply gold. Shared endpoint for all payment processing systems. Validation of gold purchase (sender, recipient, etc.) should happen before hitting this. """ secret = webhook.passthrough transaction_id = webhook.transaction_id payer_email = webhook.payer_email payer_id = webhook.payer_id subscr_id = webhook.subscr_id pennies = webhook.pennies months = webhook.months goldtype = webhook.goldtype buyer = webhook.buyer recipient = webhook.recipient signed = webhook.signed giftmessage = webhook.giftmessage comment = webhook.comment gold_recipient = recipient or buyer with gold_lock(gold_recipient): gold_recipient._sync_latest() days = days_from_months(months) if goldtype in ('onetime', 'autorenew'): admintools.engolden(buyer, days) if goldtype == 'onetime': subject = "thanks for buying reddit gold!" if g.lounge_reddit: message = strings.lounge_msg else: message = ":)" else: subject = "your reddit gold has been renewed!" message = ("see the details of your subscription on " "[your userpage](/u/%s)" % buyer.name) elif goldtype == 'creddits': buyer._incr('gold_creddits', months) subject = "thanks for buying creddits!" message = ("To spend them, visit http://%s/gold or your " "favorite person's userpage." % (g.domain)) elif goldtype == 'gift': send_gift(buyer, recipient, months, days, signed, giftmessage, comment) subject = "thanks for giving reddit gold!" message = "Your gift to %s has been delivered." % recipient.name status = 'processed' secret_pieces = [goldtype] if goldtype == 'gift': secret_pieces.append(recipient.name) secret_pieces.append(secret or transaction_id) secret = '-'.join(secret_pieces) try: create_claimed_gold(transaction_id, payer_email, payer_id, pennies, days, secret, buyer._id, c.start_time, subscr_id=subscr_id, status=status) except IntegrityError: g.log.error('gold: got duplicate gold transaction') try: message = append_random_bottlecap_phrase(message) send_system_message(buyer, subject, message, distinguished='gold-auto') except MessageError: g.log.error( 'complete_gold_purchase: send_system_message error')
def finish(self, parameters, txn_id, payer_email, paying_id, subscr_id, custom, pennies, months, days): blob_key, payment_blob = get_blob(custom) buyer_id = payment_blob.get('account_id', None) if not buyer_id: dump_parameters(parameters) raise ValueError("No buyer_id in IPN with custom='%s'" % custom) try: buyer = Account._byID(buyer_id) except NotFound: dump_parameters(parameters) raise ValueError("Invalid buyer_id %d in IPN with custom='%s'" % (buyer_id, custom)) if subscr_id: buyer.gold_subscr_id = subscr_id instagift = False if payment_blob['goldtype'] in ('autorenew', 'onetime'): admintools.engolden(buyer, days) subject = _("Eureka! Thank you for investing in reddit gold!") message = _("Thank you for buying reddit gold. Your patronage " "supports the site and makes future development " "possible. For example, one month of reddit gold " "pays for 5 instance hours of reddit's servers.") message += "\n\n" + strings.gold_benefits_msg if g.lounge_reddit: message += "\n* " + strings.lounge_msg elif payment_blob['goldtype'] == 'creddits': buyer._incr("gold_creddits", months) buyer._commit() subject = _("Eureka! Thank you for investing in reddit gold " "creddits!") message = _("Thank you for buying creddits. Your patronage " "supports the site and makes future development " "possible. To spend your creddits and spread reddit " "gold, visit [/gold](/gold) or your favorite " "person's user page.") message += "\n\n" + strings.gold_benefits_msg + "\n\n" message += _("Thank you again for your support, and have fun " "spreading gold!") elif payment_blob['goldtype'] == 'gift': recipient_name = payment_blob.get('recipient', None) try: recipient = Account._by_name(recipient_name) except NotFound: dump_parameters(parameters) raise ValueError( "Invalid recipient_name %s in IPN/GC with custom='%s'" % (recipient_name, custom)) signed = payment_blob.get("signed", False) giftmessage = _force_unicode(payment_blob.get("giftmessage", "")) comment_id = payment_blob.get("comment") send_gift(buyer, recipient, months, days, signed, giftmessage, comment_id) instagift = True subject = _("Thanks for giving the gift of reddit gold!") message = _("Your classy gift to %s has been delivered.\n\n" "Thank you for gifting reddit gold. Your patronage " "supports the site and makes future development " "possible.") % recipient.name message += "\n\n" + strings.gold_benefits_msg + "\n\n" message += _("Thank you again for your support, and have fun " "spreading gold!") else: dump_parameters(parameters) raise ValueError("Got status '%s' in IPN/GC" % payment_blob['status']) # Reuse the old "secret" column as a place to record the goldtype # and "custom", just in case we need to debug it later or something secret = payment_blob['goldtype'] + "-" + custom if instagift: status = "instagift" else: status = "processed" create_claimed_gold(txn_id, payer_email, paying_id, pennies, days, secret, buyer_id, c.start_time, subscr_id, status=status) message = append_random_bottlecap_phrase(message) send_system_message(buyer, subject, message, distinguished='gold-auto') payment_blob["status"] = "processed" g.hardcache.set(blob_key, payment_blob, 86400 * 30)
def complete_gold_purchase( secret, transaction_id, payer_email, payer_id, subscription_id, pennies, months, goldtype, buyer, recipient, signed, giftmessage, comment, ): """After receiving a message from a payment processor, apply gold. Shared endpoint for all payment processing systems. Validation of gold purchase (sender, recipient, etc.) should happen before hitting this. """ gold_recipient = recipient or buyer with gold_lock(gold_recipient): gold_recipient._sync_latest() days = days_from_months(months) if goldtype in ("onetime", "autorenew"): admintools.engolden(buyer, days) if goldtype == "onetime": subject = "thanks for buying reddit gold!" if g.lounge_reddit: lounge_url = "/space/" + g.lounge_reddit message = strings.lounge_msg % dict(link=lounge_url) else: message = ":)" else: subject = "your reddit gold has been renewed!" message = "see the details of your subscription on " "[your userpage](/u/%s)" % buyer.name elif goldtype == "creddits": buyer._incr("gold_creddits", months) subject = "thanks for buying creddits!" message = "To spend them, visit http://%s/gold or your favorite " "person's userpage." % (g.domain) elif goldtype == "gift": send_gift(buyer, recipient, months, days, signed, giftmessage, comment) subject = "thanks for giving reddit gold!" message = "Your gift to %s has been delivered." % recipient.name status = "processed" secret_pieces = [goldtype] if goldtype == "gift": secret_pieces.append(recipient.name) secret_pieces.append(secret) secret = "-".join(secret_pieces) try: create_claimed_gold( transaction_id, payer_email, payer_id, pennies, days, secret, buyer._id, c.start_time, subscr_id=subscription_id, status=status, ) except IntegrityError: g.log.error("gold: got duplicate gold transaction") try: send_system_message(buyer, subject, message) except MessageError: g.log.error("complete_gold_purchase: could not send system message")