Example #1
0
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')
Example #2
0
def send_gold_code(buyer, months, days,
                   trans_id=None, payer_email='', pennies=0):
    code = create_gold_code(trans_id, payer_email,
                            buyer._id, pennies, days, c.start_time)
    # format the code so it's easier to read (XXXXX-XXXXX)
    split_at = len(code) / 2
    code = code[:split_at] + '-' + code[split_at:]

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    subject = _('Your gold gift code has been generated!')
    message = _('Here is your gift code for %(amount)s of reddit gold:\n\n'
                '**%(code)s**\n\nThe recipient (or you!) can enter it at '
                'http://www.reddit.com/gold or go directly to '
                'http://www.reddit.com/thanks/%(code)s to claim it.'
              ) % {'amount': amount, 'code': code}
    message = append_random_bottlecap_phrase(message)

    send_system_message(buyer, subject, message, distinguished='gold-auto')

    g.log.info("%s bought a gold code for %s" % (buyer.name, amount))
    return code
Example #3
0
    def POST_goldcharge(self, form, jquery, token, passthrough, pennies, months,
                        period):
        """
        Submit charge to stripe.

        Called by GoldPayment form. This submits the charge to stripe, and gold
        will be applied once we receive a webhook from stripe.

        """

        try:
            payment_blob = validate_blob(passthrough)
        except GoldException as e:
            # This should never happen. All fields in the payment_blob
            # are validated on creation
            form.set_html('.status',
                          _('something bad happened, try again later'))
            g.log.debug('POST_goldcharge: %s' % e.message)
            return

        if period:
            plan_id = (g.STRIPE_MONTHLY_GOLD_PLAN if period == 'monthly'
                       else g.STRIPE_YEARLY_GOLD_PLAN)
            if c.user.has_gold_subscription:
                form.set_html('.status',
                              _('your account already has a gold subscription'))
                return
        else:
            plan_id = None
            penny_months, days = months_and_days_from_pennies(pennies)
            if not months or months != penny_months:
                form.set_html('.status', _('stop trying to trick the form'))
                return

        customer = self.create_customer(form, token, plan=plan_id)
        if not customer:
            return

        if period:
            c.user.gold_subscr_id = customer.id
            c.user._commit()

            status = _('subscription created')
            subject = _('reddit gold subscription')
            body = _('Your subscription is being processed and reddit gold '
                     'will be delivered shortly.')
        else:
            charge = self.charge_customer(form, customer, pennies, passthrough)
            if not charge:
                return

            status = _('payment submitted')
            subject = _('reddit gold payment')
            body = _('Your payment is being processed and reddit gold '
                     'will be delivered shortly.')

        form.set_html('.status', status)
        body = append_random_bottlecap_phrase(body)
        send_system_message(c.user, subject, body, distinguished='gold-auto')
Example #4
0
File: ipn.py Project: siadat/reddit
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')
Example #5
0
    def process_webhook(self, event_type, webhook):
        if event_type == "noop":
            return

        existing = retrieve_gold_transaction(webhook.transaction_id)
        if not existing and webhook.passthrough:
            try:
                webhook.load_blob()
            except GoldException as e:
                g.log.error("%s: payment_blob %s", webhook.transaction_id, e)
                self.abort403()
        msg = None

        if event_type == "cancelled":
            subject = _("reddit gold payment cancelled")
            msg = _("Your reddit gold payment has been cancelled, contact " "%(gold_email)s for details") % {
                "gold_email": g.goldthanks_email
            }
            if existing:
                # note that we don't check status on existing, probably
                # should update gold_table when a cancellation happens
                reverse_gold_purchase(webhook.transaction_id)
        elif event_type == "succeeded":
            if existing and existing.status == "processed":
                g.log.info("POST_goldwebhook skipping %s" % webhook.transaction_id)
                return

            self.complete_gold_purchase(webhook)
        elif event_type == "failed":
            subject = _("reddit gold payment failed")
            msg = _("Your reddit gold payment has failed, contact " "%(gold_email)s for details") % {
                "gold_email": g.goldthanks_email
            }
        elif event_type == "failed_subscription":
            subject = _("reddit gold subscription payment failed")
            msg = _(
                "Your reddit gold subscription payment has failed. "
                "Please go to http://www.reddit.com/subscription to "
                "make sure your information is correct, or contact "
                "%(gold_email)s for details"
            ) % {"gold_email": g.goldthanks_email}
        elif event_type == "refunded":
            if not (existing and existing.status == "processed"):
                return

            subject = _("reddit gold refund")
            msg = _("Your reddit gold payment has been refunded, contact " "%(gold_email)s for details") % {
                "gold_email": g.goldthanks_email
            }
            reverse_gold_purchase(webhook.transaction_id)

        if msg:
            if existing:
                buyer = Account._byID(int(existing.account_id), data=True)
            elif webhook.buyer:
                buyer = webhook.buyer
            else:
                return
            send_system_message(buyer, subject, msg)
Example #6
0
    def POST_authorize(self, authorize, client, redirect_uri, scope, state,
                       duration, response_type):
        """Endpoint for OAuth2 authorization."""

        self._check_employee_grants(client, scope)

        self._check_redirect_uri(client, redirect_uri)

        self._check_response_type_and_scope(response_type, scope)

        self._check_client_type_and_duration(response_type, client, duration)

        if c.errors:
            return self._error_response(state, redirect_uri,
                                        as_fragment=(response_type == "token"))

        if response_type == "code":
            code = OAuth2AuthorizationCode._new(client._id, redirect_uri,
                                            c.user._id36, scope,
                                            duration == "permanent")
            resp = {"code": code._id, "state": state}
            final_redirect = _update_redirect_uri(redirect_uri, resp)
            g.stats.simple_event('oauth2.POST_authorize.authorization_code_create')
        elif response_type == "token":
            token = OAuth2AccessToken._new(client._id, c.user._id36, scope)
            token_data = OAuth2AccessController._make_token_dict(token)
            token_data["state"] = state
            final_redirect = _update_redirect_uri(redirect_uri, token_data, as_fragment=True)
            g.stats.simple_event('oauth2.POST_authorize.access_token_create')

        # If this is the first time the user is logging in with an official
        # mobile app, gild them
        if (g.live_config.get('mobile_gild_first_login') and
                not c.user.has_used_mobile_app and
                client._id in g.mobile_auth_gild_clients):
            buyer = Account.system_user()
            admintools.adjust_gold_expiration(
                c.user, days=g.mobile_auth_gild_time)
            create_gift_gold(
                buyer._id, c.user._id, g.mobile_auth_gild_time,
                datetime.now(g.tz), signed=True, note='first_mobile_auth')
            subject = 'Let there be gold! Reddit just sent you Reddit gold!'
            message = (
                "Thank you for using the Reddit mobile app!  As a thank you "
                "for logging in during launch week, you've been gifted %s of "
                "Reddit Gold.\n\n"
                "Reddit Gold is Reddit's premium membership program, which "
                "grants you: \n"
                "An ads-free experience in Reddit's mobile apps, and\n"
                "Extra site features on desktop\n\n"
                "Discuss and get help on the features and perks at "
                "r/goldbenefits."
            ) % g.mobile_auth_gild_message
            message += '\n\n' + strings.gold_benefits_msg
            send_system_message(c.user, subject, message, add_to_sent=False)
            c.user.has_used_mobile_app = True
            c.user._commit()

        return self.redirect(final_redirect, code=302)
Example #7
0
def send_gift(buyer, recipient, months, days, signed, giftmessage,
              thing_fullname):
    admintools.engolden(recipient, days)

    if thing_fullname:
        thing = Thing._by_fullname(thing_fullname, data=True)
        thing._gild(buyer)
    else:
        thing = None

    if signed:
        sender = buyer.name
        md_sender = "[%s](/user/%s)" % (sender, sender)
    else:
        sender = _("An anonymous redditor")
        md_sender = _("An anonymous redditor")

    create_gift_gold(buyer._id, recipient._id, days, c.start_time, signed)

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    if not thing:
        subject = _(
            'Let there be gold! %s just sent you reddit gold!') % sender
        message = strings.youve_got_gold % dict(sender=md_sender,
                                                amount=amount)

        if giftmessage and giftmessage.strip():
            message += "\n\n" + strings.giftgold_note + giftmessage + '\n\n----'
    else:
        url = thing.make_permalink_slow()
        if isinstance(thing, Comment):
            subject = _('Your comment has been gilded!')
            message = strings.youve_been_gilded_comment % {'url': url}
        else:
            subject = _('Your submission has been gilded!')
            message = strings.youve_been_gilded_link % {'url': url}

    message += '\n\n' + strings.gold_benefits_msg
    if g.lounge_reddit:
        message += '\n* ' + strings.lounge_msg
    message = append_random_bottlecap_phrase(message)

    try:
        send_system_message(recipient,
                            subject,
                            message,
                            distinguished='gold-auto')
    except MessageError:
        g.log.error('send_gift: could not send system message')

    g.log.info("%s gifted %s to %s" % (buyer.name, amount, recipient.name))
    return thing
Example #8
0
def send_gift(buyer, recipient, months, days, signed, giftmessage,
              thing_fullname):
    admintools.engolden(recipient, days)

    if thing_fullname:
        thing = Thing._by_fullname(thing_fullname, data=True)
        thing._gild(buyer)
    else:
        thing = None

    if signed:
        sender = buyer.name
        md_sender = "[%s](/user/%s)" % (sender, sender)
    else:
        sender = _("An anonymous redditor")
        md_sender = _("An anonymous redditor")

    create_gift_gold(buyer._id, recipient._id, days, c.start_time, signed)

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    if not thing:
        subject = _(
            'Let there be gold! %s just sent you reddit gold!') % sender
        message = strings.youve_got_gold % dict(
            sender=md_sender, amount=amount)

        if giftmessage and giftmessage.strip():
            message += "\n\n" + strings.giftgold_note + giftmessage + '\n\n----'
    else:
        url = thing.make_permalink_slow()
        if isinstance(thing, Comment):
            subject = _('Your comment has been gilded!')
            message = strings.youve_been_gilded_comment % {'url': url}
        else:
            subject = _('Your submission has been gilded!')
            message = strings.youve_been_gilded_link % {'url': url}

    message += '\n\n' + strings.gold_benefits_msg
    if g.lounge_reddit:
        message += '\n* ' + strings.lounge_msg
    message = append_random_bottlecap_phrase(message)

    try:
        send_system_message(
            recipient, subject, message, distinguished='gold-auto')
    except MessageError:
        g.log.error('send_gift: could not send system message')

    g.log.info("%s gifted %s to %s" % (buyer.name, amount, recipient.name))
    return thing
Example #9
0
    def POST_authorize(self, authorize, client, redirect_uri, scope, state,
                       duration, response_type):
        """Endpoint for OAuth2 authorization."""

        self._check_employee_grants(client, scope)

        if response_type == "token" and client.is_confidential():
            # Prevent "confidential" clients from distributing tokens
            # in a non-confidential manner
            c.errors.add((errors.OAUTH2_INVALID_CLIENT, "client_id"))
        if response_type == "token" and duration != "temporary":
            # implicit grant -> No refresh tokens allowed
            c.errors.add((errors.INVALID_OPTION, "duration"))
        self._check_redirect_uri(client, redirect_uri)

        if c.errors:
            return self._error_response(state, redirect_uri,
                                        as_fragment=(response_type == "token"))

        if response_type == "code":
            code = OAuth2AuthorizationCode._new(client._id, redirect_uri,
                                            c.user._id36, scope,
                                            duration == "permanent")
            resp = {"code": code._id, "state": state}
            final_redirect = _update_redirect_uri(redirect_uri, resp)
        elif response_type == "token":
            token = OAuth2AccessToken._new(client._id, c.user._id36, scope)
            token_data = OAuth2AccessController._make_token_dict(token)
            token_data["state"] = state
            final_redirect = _update_redirect_uri(redirect_uri, token_data, as_fragment=True)

        # If this is the first time the user is logging in with an official
        # mobile app, gild them
        if (g.live_config.get('mobile_gild_first_login') and
                not c.user.has_used_mobile_app and
                client._id in g.mobile_auth_gild_clients):
            buyer = Account.system_user()
            admintools.adjust_gold_expiration(
                c.user, days=g.mobile_auth_gild_time)
            create_gift_gold(
                buyer._id, c.user._id, g.mobile_auth_gild_time,
                datetime.now(g.tz), signed=True, note='first_mobile_auth')
            subject = 'Let there be gold! %s just sent you reddit gold!' % (
                buyer.name)
            message = "Thank you for using the reddit mobile app!  For your "\
                "participation, you've been gifted %s of reddit gold." % (
                    g.mobile_auth_gild_message)
            message += '\n\n' + strings.gold_benefits_msg
            send_system_message(c.user, subject, message, add_to_sent=False)
            c.user.has_used_mobile_app = True
            c.user._commit()

        return self.redirect(final_redirect, code=302)
Example #10
0
File: ipn.py Project: AD42/reddit
    def cancel_subscription(cls, form, user):
        if not user.has_stripe_subscription:
            return

        customer = stripe.Customer.retrieve(user.gold_subscr_id)
        customer.delete()

        user.gold_subscr_id = None
        user._commit()
        subject = _('your gold subscription has been cancelled')
        message = _('if you have any questions please email %(email)s')
        message %= {'email': g.goldthanks_email}
        send_system_message(user, subject, message)
        return customer
Example #11
0
    def cancel_subscription(user):
        if not getattr(user, "stripe_customer_id", None):
            return

        customer = stripe.Customer.retrieve(user.stripe_customer_id)
        customer.delete()

        user.stripe_customer_id = None
        user._commit()
        subject = _("your gold subscription has been cancelled")
        message = _("if you have any questions please email %(email)s")
        message %= {"email": g.goldthanks_email}
        send_system_message(user, subject, message)
        return customer
Example #12
0
    def cancel_subscription(cls, form, user):
        if not user.has_stripe_subscription:
            return

        customer = stripe.Customer.retrieve(user.gold_subscr_id)
        customer.delete()

        user.gold_subscr_id = None
        user._commit()
        subject = _('your gold subscription has been cancelled')
        message = _('if you have any questions please email %(email)s')
        message %= {'email': g.goldthanks_email}
        send_system_message(user, subject, message)
        return customer
Example #13
0
def send_claim_message(username, postcard_url):
    # this is ripped off from the gold-record.py code in reddit-private
    timestamp = int(time.time())
    now = datetime.datetime.now(g.tz)
    transaction_id = "M%d" % timestamp
    secret = "p_%d%s" % (timestamp, randstr(5))
    create_unclaimed_gold(transaction_id, "", "manual-unclaimed",
                          0, REWARD, secret, now, None)

    claim_url = "http://www.reddit.com/thanks/" + secret
    user = Account._by_name(username)
    message = TEMPLATE % dict(postcard_url=postcard_url,
                              claim_url=claim_url,
                              gold_support_email=g.goldthanks_email)
    send_system_message(user, "we got that postcard you sent us!", message)
Example #14
0
def send_gift(buyer, recipient, months, days, signed, giftmessage, comment_id):
    admintools.engolden(recipient, days)

    if comment_id:
        comment = Thing._by_fullname(comment_id, data=True)
        comment._gild(buyer)
    else:
        comment = None

    if signed:
        sender = buyer.name
        md_sender = "[%s](/user/%s)" % (sender, sender)
    else:
        sender = _("An anonymous redditor")
        md_sender = _("An anonymous redditor")

    create_gift_gold(buyer._id, recipient._id, days, c.start_time, signed)

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    if not comment:
        subject = _(
            'Let there be gold! %s just sent you reddit gold!') % sender
        message = strings.youve_got_gold % dict(sender=md_sender,
                                                amount=amount)

        if giftmessage and giftmessage.strip():
            message += "\n\n" + strings.giftgold_note + giftmessage + '\n\n----'
    else:
        subject = _('Your comment has been gilded.')
        message = strings.youve_got_comment_gold % dict(
            url=comment.make_permalink_slow(), )

    message += '\n\n' + strings.gold_benefits_msg
    message += '\n\n' + strings.lounge_msg

    try:
        send_system_message(recipient, subject, message)
    except MessageError:
        g.log.error('send_gift: could not send system message')

    g.log.info("%s gifted %s to %s" % (buyer.name, amount, recipient.name))
    return comment
Example #15
0
File: ipn.py Project: rolmos/reddit
def send_gift(buyer, recipient, months, days, signed, giftmessage, comment_id):
    admintools.engolden(recipient, days)

    if comment_id:
        comment = Thing._by_fullname(comment_id, data=True)
        comment._gild(buyer)
    else:
        comment = None

    if signed:
        sender = buyer.name
        md_sender = "[%s](/user/%s)" % (sender, sender)
    else:
        sender = _("An anonymous redditor")
        md_sender = _("An anonymous redditor")

    create_gift_gold (buyer._id, recipient._id, days, c.start_time, signed)

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    if not comment:
        subject = _('Let there be gold! %s just sent you reddit gold!') % sender
        message = strings.youve_got_gold % dict(sender=md_sender, amount=amount)

        if giftmessage and giftmessage.strip():
            message += "\n\n" + strings.giftgold_note + giftmessage + '\n\n----'
    else:
        subject = _('Your comment has been gilded.')
        message = strings.youve_got_comment_gold % dict(
            url=comment.make_permalink_slow(),
        )

    message += '\n\n' + strings.gold_benefits_msg
    message += '\n\n' + strings.lounge_msg

    try:
        send_system_message(recipient, subject, message)
    except MessageError:
        g.log.error('send_gift: could not send system message')

    g.log.info("%s gifted %s to %s" % (buyer.name, amount, recipient.name))
    return comment
Example #16
0
def send_gold_code(buyer,
                   months,
                   days,
                   trans_id=None,
                   payer_email='',
                   pennies=0,
                   buyer_email=None):
    if buyer:
        paying_id = buyer._id
        buyer_name = buyer.name
    else:
        paying_id = buyer_email
        buyer_name = buyer_email
    code = create_gold_code(trans_id, payer_email, paying_id, pennies, days,
                            c.start_time)
    # format the code so it's easier to read (XXXXX-XXXXX)
    split_at = len(code) / 2
    code = code[:split_at] + '-' + code[split_at:]

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    subject = _('Your gold gift code has been generated!')
    message = _('Here is your gift code for %(amount)s of reddit gold:\n\n'
                '%(code)s\n\nThe recipient (or you!) can enter it at '
                'http://www.reddit.com/gold or go directly to '
                'http://www.reddit.com/thanks/%(code)s to claim it.') % {
                    'amount': amount,
                    'code': code
                }

    if buyer:
        # bought by a logged-in user, send a reddit PM
        message = append_random_bottlecap_phrase(message)
        send_system_message(buyer, subject, message, distinguished='gold-auto')
    else:
        # bought by a logged-out user, send an email
        contents = GoldGiftCodeEmail(message=message).render(style='email')
        _system_email(buyer_email, contents, Email.Kind.GOLD_GIFT_CODE)

    g.log.info("%s bought a gold code for %s", buyer_name, amount)
    return code
Example #17
0
def send_gift(buyer, recipient, months, days, signed, giftmessage, comment_id):
    admintools.engolden(recipient, days)

    if comment_id:
        comment = Thing._by_fullname(comment_id, data=True)
        comment._gild(buyer)
    else:
        comment = None

    if signed:
        sender = buyer.name
        md_sender = "[%s](/user/%s)" % (sender, sender)
    else:
        sender = "someone"
        md_sender = "An anonymous lightnet user"

    create_gift_gold(buyer._id, recipient._id, days, c.start_time, signed)

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    if not comment:
        message = strings.youve_got_gold % dict(sender=md_sender, amount=amount)

        if giftmessage and giftmessage.strip():
            message += "\n\n" + strings.giftgold_note + giftmessage + "\n\n----"
    else:
        message = strings.youve_got_comment_gold % dict(url=comment.make_permalink_slow())

    message += "\n\n" + strings.gold_benefits_msg
    message += "\n\n" + strings.lounge_msg % {"link": "/space/" + g.lounge_reddit}

    subject = sender + " just sent you reddit gold!"

    try:
        send_system_message(recipient, subject, message)
    except MessageError:
        g.log.error("send_gift: could not send system message")

    g.log.info("%s gifted %s to %s" % (buyer.name, amount, recipient.name))
    return comment
Example #18
0
def reverse_gold_purchase(transaction_id, goldtype, buyer, pennies,
                          recipient=None):
    gold_recipient = recipient or buyer
    with gold_lock(gold_recipient):
        gold_recipient._sync_latest()
        months, days = months_and_days_from_pennies(pennies)

        if goldtype in ('onetime', 'autorenew'):
            subtract_gold_days(buyer, days)

        elif goldtype == 'creddits':
            subtract_gold_creddits(buyer, months)

        elif goldtype == 'gift':
            subtract_gold_days(recipient, days)
            subject = 'your gifted gold has been reversed'
            message = 'sorry, but the payment was reversed'
            send_system_message(recipient, subject, message)
    update_gold_transaction(transaction_id, 'reversed')
Example #19
0
File: ipn.py Project: siadat/reddit
    def process_webhook(self, event_type, passthrough, transaction_id, pennies,
                        months):
        if event_type == 'noop':
            return

        try:
            payment_blob = validate_blob(passthrough)
        except GoldError as e:
            g.log.error('%s %s: bad payment_blob %s' % (self.name,
                                                        transaction_id,
                                                        e))
            self.abort403()

        goldtype = payment_blob['goldtype']
        buyer = payment_blob['buyer']
        recipient = payment_blob.get('recipient', None)
        signed = payment_blob.get('signed', False)
        giftmessage = payment_blob.get('giftmessage', None)
        comment = payment_blob.get('comment', None)
        comment = comment._fullname if comment else None
        existing = retrieve_gold_transaction(transaction_id)

        if event_type == 'cancelled':
            subject = 'gold payment cancelled'
            msg = ('your gold payment has been cancelled, contact '
                   '%(gold_email)s for details' % {'gold_email':
                                                   g.goldthanks_email})
            send_system_message(buyer, subject, msg)
            if existing:
                # note that we don't check status on existing, probably
                # should update gold_table when a cancellation happens
                reverse_gold_purchase(transaction_id)
        elif event_type == 'succeeded':
            if existing and existing.status == 'processed':
                g.log.info('POST_goldwebhook skipping %s' % transaction_id)
                return

            payer_email = ''
            payer_id = ''
            subscription_id = None
            complete_gold_purchase(passthrough, transaction_id, payer_email,
                                   payer_id, subscription_id, pennies, months,
                                   goldtype, buyer, recipient, signed,
                                   giftmessage, comment)
        elif event_type == 'failed':
            subject = 'gold payment failed'
            msg = ('your gold payment has failed, contact %(gold_email)s for '
                   'details' % {'gold_email': g.goldthanks_email})
            send_system_message(buyer, subject, msg)
            # probably want to update gold_table here
        elif event_type == 'refunded':
            if not (existing and existing.status == 'processed'):
                return

            subject = 'gold refund'
            msg = ('your gold payment has been refunded, contact '
                   '%(gold_email)s for details' % {'gold_email':
                                                   g.goldthanks_email})
            send_system_message(buyer, subject, msg)
            reverse_gold_purchase(transaction_id)
Example #20
0
    def process_webhook(self, event_type, passthrough, transaction_id, pennies,
                        months):
        if event_type == 'noop':
            return

        try:
            payment_blob = validate_blob(passthrough)
        except GoldException as e:
            g.log.error('%s %s: bad payment_blob %s' % (self.name,
                                                        transaction_id,
                                                        e))
            self.abort403()

        goldtype = payment_blob['goldtype']
        buyer = payment_blob['buyer']
        recipient = payment_blob.get('recipient', None)
        signed = payment_blob.get('signed', False)
        giftmessage = payment_blob.get('giftmessage', None)
        comment = payment_blob.get('comment', None)
        comment = comment._fullname if comment else None
        existing = retrieve_gold_transaction(transaction_id)

        if event_type == 'cancelled':
            subject = 'gold payment cancelled'
            msg = ('your gold payment has been cancelled, contact '
                   '%(gold_email)s for details' % {'gold_email':
                                                   g.goldthanks_email})
            send_system_message(buyer, subject, msg)
            if existing:
                # note that we don't check status on existing, probably
                # should update gold_table when a cancellation happens
                reverse_gold_purchase(transaction_id)
        elif event_type == 'succeeded':
            if existing and existing.status == 'processed':
                g.log.info('POST_goldwebhook skipping %s' % transaction_id)
                return

            payer_email = ''
            payer_id = ''
            subscription_id = None
            complete_gold_purchase(passthrough, transaction_id, payer_email,
                                   payer_id, subscription_id, pennies, months,
                                   goldtype, buyer, recipient, signed,
                                   giftmessage, comment)
        elif event_type == 'failed':
            subject = 'gold payment failed'
            msg = ('your gold payment has failed, contact %(gold_email)s for '
                   'details' % {'gold_email': g.goldthanks_email})
            send_system_message(buyer, subject, msg)
            # probably want to update gold_table here
        elif event_type == 'refunded':
            if not (existing and existing.status == 'processed'):
                return

            subject = 'gold refund'
            msg = ('your gold payment has been refunded, contact '
                   '%(gold_email)s for details' % {'gold_email':
                                                   g.goldthanks_email})
            send_system_message(buyer, subject, msg)
            reverse_gold_purchase(transaction_id)
Example #21
0
File: ipn.py Project: siadat/reddit
def reverse_gold_purchase(transaction_id):
    transaction = retrieve_gold_transaction(transaction_id)

    if not transaction:
        raise GoldException('gold_table %s not found' % transaction_id)

    buyer = Account._byID(int(transaction.account_id), data=True)
    recipient = None
    days = transaction.days
    months = days / 31

    secret = transaction.secret
    if '{' in secret:
        secret.strip('{}') # I goofed
        pieces = secret.split(',')
    else:
        pieces = secret.split('-')
    goldtype = pieces[0]
    if goldtype == 'gift':
        recipient_name, secret = pieces[1:]
        recipient = Account._by_name(recipient_name)

    gold_recipient = recipient or buyer
    with gold_lock(gold_recipient):
        gold_recipient._sync_latest()

        if goldtype in ('onetime', 'autorenew'):
            subtract_gold_days(buyer, days)

        elif goldtype == 'creddits':
            subtract_gold_creddits(buyer, months)

        elif goldtype == 'gift':
            subtract_gold_days(recipient, days)
            subject = 'your gifted gold has been reversed'
            message = 'sorry, but the payment was reversed'
            send_system_message(recipient, subject, message)
    update_gold_transaction(transaction_id, 'reversed')
Example #22
0
def reverse_gold_purchase(transaction_id):
    transaction = retrieve_gold_transaction(transaction_id)

    if not transaction:
        raise GoldException("gold_table %s not found" % transaction_id)

    buyer = Account._byID(int(transaction.account_id), data=True)
    recipient = None
    days = transaction.days
    months = days / 31

    secret = transaction.secret
    if "{" in secret:
        secret.strip("{}")  # I goofed
        pieces = secret.split(",")
    else:
        pieces = secret.split("-")
    goldtype = pieces[0]
    if goldtype == "gift":
        recipient_name, secret = pieces[1:]
        recipient = Account._by_name(recipient_name)

    gold_recipient = recipient or buyer
    with gold_lock(gold_recipient):
        gold_recipient._sync_latest()

        if goldtype in ("onetime", "autorenew"):
            subtract_gold_days(buyer, days)

        elif goldtype == "creddits":
            subtract_gold_creddits(buyer, months)

        elif goldtype == "gift":
            subtract_gold_days(recipient, days)
            subject = "your gifted gold has been reversed"
            message = "sorry, but the payment was reversed"
            send_system_message(recipient, subject, message)
    update_gold_transaction(transaction_id, "reversed")
Example #23
0
File: ipn.py Project: AD42/reddit
def reverse_gold_purchase(transaction_id):
    transaction = retrieve_gold_transaction(transaction_id)

    if not transaction:
        raise GoldException('gold_table %s not found' % transaction_id)

    buyer = Account._byID(int(transaction.account_id), data=True)
    recipient = None
    days = transaction.days
    months = days / 31

    secret = transaction.secret
    if '{' in secret:
        secret.strip('{}') # I goofed
        pieces = secret.split(',')
    else:
        pieces = secret.split('-')
    goldtype = pieces[0]
    if goldtype == 'gift':
        recipient_name, secret = pieces[1:]
        recipient = Account._by_name(recipient_name)

    gold_recipient = recipient or buyer
    with gold_lock(gold_recipient):
        gold_recipient._sync_latest()

        if goldtype in ('onetime', 'autorenew'):
            subtract_gold_days(buyer, days)

        elif goldtype == 'creddits':
            subtract_gold_creddits(buyer, months)

        elif goldtype == 'gift':
            subtract_gold_days(recipient, days)
            subject = 'your gifted gold has been reversed'
            message = 'sorry, but the payment was reversed'
            send_system_message(recipient, subject, message)
    update_gold_transaction(transaction_id, 'reversed')
Example #24
0
def send_gift(buyer, recipient, months, days, signed, giftmessage, comment_id):
    admintools.engolden(recipient, days)

    if comment_id:
        comment = Thing._by_fullname(comment_id, data=True)
        comment._gild(buyer)
    else:
        comment = None

    if signed:
        sender = buyer.name
        md_sender = "[%s](/user/%s)" % (sender, sender)
    else:
        sender = "someone"
        md_sender = "An anonymous redditor"

    create_gift_gold (buyer._id, recipient._id, days, c.start_time, signed)

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    if not comment:
        message = strings.youve_got_gold % dict(sender=md_sender, amount=amount)

        if giftmessage and giftmessage.strip():
            message += "\n\n" + strings.giftgold_note + giftmessage
    else:
        message = strings.youve_got_comment_gold % dict(
            url=comment.make_permalink_slow(),
        )

    subject = sender + " just sent you reddit gold!"
    send_system_message(recipient, subject, message)

    g.log.info("%s gifted %s to %s" % (buyer.name, amount, recipient.name))
    return comment
Example #25
0
def send_gold_code(buyer, months, days,
                   trans_id=None, payer_email='', pennies=0, buyer_email=None):
    if buyer:
        paying_id = buyer._id
        buyer_name = buyer.name
    else:
        paying_id = buyer_email
        buyer_name = buyer_email
    code = create_gold_code(trans_id, payer_email,
                            paying_id, pennies, days, c.start_time)
    # format the code so it's easier to read (XXXXX-XXXXX)
    split_at = len(code) / 2
    code = code[:split_at] + '-' + code[split_at:]

    if months == 1:
        amount = "a month"
    else:
        amount = "%d months" % months

    subject = _('Your gold gift code has been generated!')
    message = _('Here is your gift code for %(amount)s of reddit gold:\n\n'
                '%(code)s\n\nThe recipient (or you!) can enter it at '
                'http://www.reddit.com/gold or go directly to '
                'http://www.reddit.com/thanks/%(code)s to claim it.'
              ) % {'amount': amount, 'code': code}

    if buyer:
        # bought by a logged-in user, send a reddit PM
        message = append_random_bottlecap_phrase(message)
        send_system_message(buyer, subject, message, distinguished='gold-auto')
    else:
        # bought by a logged-out user, send an email
        contents = GoldGiftCodeEmail(message=message).render(style='email')
        _system_email(buyer_email, contents, Email.Kind.GOLD_GIFT_CODE)
                      
    g.log.info("%s bought a gold code for %s", buyer_name, amount)
    return code
Example #26
0
    def process_webhook(self, event_type, webhook):
        if event_type == 'noop':
            return

        existing = retrieve_gold_transaction(webhook.transaction_id)
        if not existing and webhook.passthrough:
            try:
                webhook.load_blob()
            except GoldException as e:
                g.log.error('%s: payment_blob %s', webhook.transaction_id, e)
                self.abort403()
        msg = None

        if event_type == 'cancelled':
            subject = _('reddit gold payment cancelled')
            msg = _('Your reddit gold payment has been cancelled, contact '
                    '%(gold_email)s for details') % {'gold_email':
                                                     g.goldthanks_email}
            if existing:
                # note that we don't check status on existing, probably
                # should update gold_table when a cancellation happens
                reverse_gold_purchase(webhook.transaction_id)
        elif event_type == 'succeeded':
            if (existing and
                    existing.status in ('processed', 'unclaimed', 'claimed')):
                g.log.info('POST_goldwebhook skipping %s' % webhook.transaction_id)
                return

            self.complete_gold_purchase(webhook)
        elif event_type == 'failed':
            subject = _('reddit gold payment failed')
            msg = _('Your reddit gold payment has failed, contact '
                    '%(gold_email)s for details') % {'gold_email':
                                                     g.goldthanks_email}
        elif event_type == 'deleted_subscription':
            # the subscription may have been deleted directly by the user using
            # POST_delete_subscription, in which case gold_subscr_id is already
            # unset and we don't need to message them
            if webhook.buyer and webhook.buyer.gold_subscr_id:
                subject = _('reddit gold subscription cancelled')
                msg = _('Your reddit gold subscription has been cancelled '
                        'because your credit card could not be charged. '
                        'Contact %(gold_email)s for details')
                msg %= {'gold_email': g.goldthanks_email}
                webhook.buyer.gold_subscr_id = None
                webhook.buyer._commit()
        elif event_type == 'refunded':
            if not (existing and existing.status == 'processed'):
                return

            subject = _('reddit gold refund')
            msg = _('Your reddit gold payment has been refunded, contact '
                   '%(gold_email)s for details') % {'gold_email':
                                                    g.goldthanks_email}
            reverse_gold_purchase(webhook.transaction_id)

        if msg:
            if existing:
                buyer = Account._byID(int(existing.account_id), data=True)
            elif webhook.buyer:
                buyer = webhook.buyer
            else:
                return

            try:
                send_system_message(buyer, subject, msg)
            except MessageError:
                g.log.error('process_webhook: send_system_message error')
Example #27
0
    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)
Example #28
0
    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')
Example #29
0
File: ipn.py Project: 6r3nt/reddit
    def process_webhook(self, event_type, webhook):
        if event_type == 'noop':
            return

        existing = retrieve_gold_transaction(webhook.transaction_id)
        if not existing and webhook.passthrough:
            try:
                webhook.load_blob()
            except GoldException as e:
                g.log.error('%s: payment_blob %s', webhook.transaction_id, e)
                if self.abort_on_error:
                    self.abort403()
                else:
                    return
        msg = None

        if event_type == 'cancelled':
            subject = _('reddit gold payment cancelled')
            msg = _('Your reddit gold payment has been cancelled, contact '
                    '%(gold_email)s for details') % {'gold_email':
                                                     g.goldthanks_email}
            if existing:
                # note that we don't check status on existing, probably
                # should update gold_table when a cancellation happens
                reverse_gold_purchase(webhook.transaction_id)
        elif event_type == 'succeeded':
            if (existing and
                    existing.status in ('processed', 'unclaimed', 'claimed')):
                g.log.info('POST_goldwebhook skipping %s' % webhook.transaction_id)
                return

            self.complete_gold_purchase(webhook)
        elif event_type == 'failed':
            subject = _('reddit gold payment failed')
            msg = _('Your reddit gold payment has failed, contact '
                    '%(gold_email)s for details') % {'gold_email':
                                                     g.goldthanks_email}
        elif event_type == 'deleted_subscription':
            # the subscription may have been deleted directly by the user using
            # POST_delete_subscription, in which case gold_subscr_id is already
            # unset and we don't need to message them
            if webhook.buyer and webhook.buyer.gold_subscr_id:
                subject = _('reddit gold subscription cancelled')
                msg = _('Your reddit gold subscription has been cancelled '
                        'because your credit card could not be charged. '
                        'Contact %(gold_email)s for details')
                msg %= {'gold_email': g.goldthanks_email}
                webhook.buyer.gold_subscr_id = None
                webhook.buyer._commit()
        elif event_type == 'refunded':
            if not (existing and existing.status == 'processed'):
                return

            subject = _('reddit gold refund')
            msg = _('Your reddit gold payment has been refunded, contact '
                   '%(gold_email)s for details') % {'gold_email':
                                                    g.goldthanks_email}
            reverse_gold_purchase(webhook.transaction_id)

        if msg:
            if existing:
                buyer = Account._byID(int(existing.account_id), data=True)
            elif webhook.buyer:
                buyer = webhook.buyer
            else:
                return

            try:
                send_system_message(buyer, subject, msg)
            except MessageError:
                g.log.error('process_webhook: send_system_message error')
Example #30
0
    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)
Example #31
0
File: ipn.py Project: rolmos/reddit
    def POST_gcheckout(self, full_sn):
        if full_sn:
            short_sn = full_sn.split('-')[0]
            g.log.error( "GOOGLE CHECKOUT: %s" % short_sn)
            trans = _google_ordernum_request(short_sn)

            # get the financial details
            auth = trans.find("authorization-amount-notification")

            custom = None
            cart = trans.find("shopping-cart")
            if cart:
                private_item_data = cart.find("merchant-private-item-data")
                if private_item_data:
                    custom = str(private_item_data.contents[0])

            if not auth:
                # see if the payment was declinded
                status = trans.findAll('financial-order-state')
                if 'PAYMENT_DECLINED' in [x.contents[0] for x in status]:
                    g.log.error("google declined transaction found: '%s'" %
                                short_sn)
                elif 'REVIEWING' not in [x.contents[0] for x in status]:
                    g.log.error(("google transaction not found: " +
                                 "'%s', status: %s")
                                % (short_sn, [x.contents[0] for x in status]))
                else:
                    g.log.error(("google transaction status: " +
                                 "'%s', status: %s")
                                % (short_sn, [x.contents[0] for x in status]))
                    if custom:
                        payment_blob = validate_blob(custom)
                        buyer = payment_blob['buyer']
                        subject = _('Your gold order has been received')
                        msg = _('Your order for reddit gold has been '
                                'received, and will be delivered shortly. '
                                'Please bear with us as Google Wallet '
                                'payments can take up to an hour to '
                                'complete.')
                        try:
                            send_system_message(buyer, subject, msg)
                        except MessageError:
                            g.log.error('gcheckout send_system_message failed')
            elif auth.find("financial-order-state"
                           ).contents[0] == "CHARGEABLE":
                email = str(auth.find("email").contents[0])
                payer_id = str(auth.find('buyer-id').contents[0])
                if custom:
                    days = None
                    try:
                        pennies = int(float(trans.find("order-total"
                                                      ).contents[0])*100)
                        months, days = months_and_days_from_pennies(pennies)
                        if not months:
                            raise ValueError("Bad pennies for %s" % short_sn)
                        charged = trans.find("charge-amount-notification")
                        if not charged:
                            _google_charge_and_ship(short_sn)

                        parameters = request.POST.copy()
                        self.finish(parameters, "g%s" % short_sn,
                                    email, payer_id, None,
                                    custom, pennies, months, days)
                    except ValueError, e:
                        g.log.error(e)
                else:
                    raise ValueError("Got no custom blob for %s" % short_sn)

            return (('<notification-acknowledgment ' +
                     'xmlns="http://checkout.google.com/schema/2" ' +
                     'serial-number="%s" />') % full_sn)
Example #32
0
    def POST_authorize(self, authorize, client, redirect_uri, scope, state,
                       duration, response_type):
        """Endpoint for OAuth2 authorization."""

        self._check_employee_grants(client, scope)

        self._check_redirect_uri(client, redirect_uri)

        self._check_response_type_and_scope(response_type, scope)

        self._check_client_type_and_duration(response_type, client, duration)

        if c.errors:
            return self._error_response(state, redirect_uri,
                                        as_fragment=(response_type == "token"))

        if response_type == "code":
            code = OAuth2AuthorizationCode._new(client._id, redirect_uri,
                                            c.user._id36, scope,
                                            duration == "permanent")
            resp = {"code": code._id, "state": state}
            final_redirect = _update_redirect_uri(redirect_uri, resp)
            g.stats.simple_event('oauth2.POST_authorize.authorization_code_create')
        elif response_type == "token":
            device_id = get_device_id(client)
            token = OAuth2AccessToken._new(
                client_id=client._id,
                user_id=c.user._id36,
                scope=scope,
                device_id=device_id,
            )
            resp = OAuth2AccessController._make_new_token_response(token)
            resp["state"] = state
            final_redirect = _update_redirect_uri(redirect_uri, resp, as_fragment=True)
            g.stats.simple_event('oauth2.POST_authorize.access_token_create')

        # If this is the first time the user is logging in with an official
        # mobile app, gild them
        if (g.live_config.get('mobile_gild_first_login') and
                not c.user.has_used_mobile_app and
                client._id in g.mobile_auth_gild_clients):
            buyer = Account.system_user()
            admintools.adjust_gold_expiration(
                c.user, days=g.mobile_auth_gild_time)
            create_gift_gold(
                buyer._id, c.user._id, g.mobile_auth_gild_time,
                datetime.now(g.tz), signed=True, note='first_mobile_auth')
            subject = 'Let there be gold! Reddit just sent you Reddit gold!'
            message = (
                "Thank you for using the Reddit mobile app!  As a thank you "
                "for logging in during launch week, you've been gifted %s of "
                "Reddit Gold.\n\n"
                "Reddit Gold is Reddit's premium membership program, which "
                "grants you: \n"
                "An ads-free experience in Reddit's mobile apps, and\n"
                "Extra site features on desktop\n\n"
                "Discuss and get help on the features and perks at "
                "r/goldbenefits."
            ) % g.mobile_auth_gild_message
            message += '\n\n' + strings.gold_benefits_msg
            send_system_message(c.user, subject, message, add_to_sent=False)
            c.user.has_used_mobile_app = True
            c.user._commit()

        return self.redirect(final_redirect, code=302)
Example #33
0
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")
Example #34
0
    def process_webhook(self, event_type, webhook):
        if event_type == 'noop':
            return

        existing = retrieve_gold_transaction(webhook.transaction_id)
        if not existing and webhook.passthrough:
            try:
                webhook.load_blob()
            except GoldException as e:
                g.log.error('%s: payment_blob %s', webhook.transaction_id, e)
                self.abort403()
        msg = None

        if event_type == 'cancelled':
            subject = _('reddit gold payment cancelled')
            msg = _('Your reddit gold payment has been cancelled, contact '
                    '%(gold_email)s for details') % {
                        'gold_email': g.goldthanks_email
                    }
            if existing:
                # note that we don't check status on existing, probably
                # should update gold_table when a cancellation happens
                reverse_gold_purchase(webhook.transaction_id)
        elif event_type == 'succeeded':
            if existing and existing.status == 'processed':
                g.log.info('POST_goldwebhook skipping %s' %
                           webhook.transaction_id)
                return

            self.complete_gold_purchase(webhook)
        elif event_type == 'failed':
            subject = _('reddit gold payment failed')
            msg = _('Your reddit gold payment has failed, contact '
                    '%(gold_email)s for details') % {
                        'gold_email': g.goldthanks_email
                    }
        elif event_type == 'failed_subscription':
            subject = _('reddit gold subscription payment failed')
            msg = _('Your reddit gold subscription payment has failed. '
                    'Please go to http://www.reddit.com/subscription to '
                    'make sure your information is correct, or contact '
                    '%(gold_email)s for details') % {
                        'gold_email': g.goldthanks_email
                    }
        elif event_type == 'refunded':
            if not (existing and existing.status == 'processed'):
                return

            subject = _('reddit gold refund')
            msg = _('Your reddit gold payment has been refunded, contact '
                    '%(gold_email)s for details') % {
                        'gold_email': g.goldthanks_email
                    }
            reverse_gold_purchase(webhook.transaction_id)

        if msg:
            if existing:
                buyer = Account._byID(int(existing.account_id), data=True)
            elif webhook.buyer:
                buyer = webhook.buyer
            else:
                return
            send_system_message(buyer, subject, msg)
Example #35
0
File: ipn.py Project: AD42/reddit
    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)
Example #36
0
File: ipn.py Project: siadat/reddit
    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)
Example #37
0
File: ipn.py Project: siadat/reddit
    def POST_gcheckout(self, full_sn):
        if full_sn:
            short_sn = full_sn.split('-')[0]
            g.log.error( "GOOGLE CHECKOUT: %s" % short_sn)
            trans = _google_ordernum_request(short_sn)

            # get the financial details
            auth = trans.find("authorization-amount-notification")

            custom = None
            cart = trans.find("shopping-cart")
            if cart:
                private_item_data = cart.find("merchant-private-item-data")
                if private_item_data:
                    custom = str(private_item_data.contents[0])

            if not auth:
                # see if the payment was declinded
                status = trans.findAll('financial-order-state')
                if 'PAYMENT_DECLINED' in [x.contents[0] for x in status]:
                    g.log.error("google declined transaction found: '%s'" %
                                short_sn)
                elif 'REVIEWING' not in [x.contents[0] for x in status]:
                    g.log.error(("google transaction not found: " +
                                 "'%s', status: %s")
                                % (short_sn, [x.contents[0] for x in status]))
                else:
                    g.log.error(("google transaction status: " +
                                 "'%s', status: %s")
                                % (short_sn, [x.contents[0] for x in status]))
                    if custom:
                        payment_blob = validate_blob(custom)
                        buyer = payment_blob['buyer']
                        subject = _('gold order')
                        msg = _('your order has been received and gold will'
                                ' be delivered shortly. please bear with us'
                                ' as google wallet payments can take up to an'
                                ' hour to complete')
                        try:
                            send_system_message(buyer, subject, msg)
                        except MessageError:
                            g.log.error('gcheckout send_system_message failed')
            elif auth.find("financial-order-state"
                           ).contents[0] == "CHARGEABLE":
                email = str(auth.find("email").contents[0])
                payer_id = str(auth.find('buyer-id').contents[0])
                if custom:
                    days = None
                    try:
                        pennies = int(float(trans.find("order-total"
                                                      ).contents[0])*100)
                        months, days = months_and_days_from_pennies(pennies)
                        if not months:
                            raise ValueError("Bad pennies for %s" % short_sn)
                        charged = trans.find("charge-amount-notification")
                        if not charged:
                            _google_charge_and_ship(short_sn)

                        parameters = request.POST.copy()
                        self.finish(parameters, "g%s" % short_sn,
                                    email, payer_id, None,
                                    custom, pennies, months, days)
                    except ValueError, e:
                        g.log.error(e)
                else:
                    raise ValueError("Got no custom blob for %s" % short_sn)

            return (('<notification-acknowledgment ' +
                     'xmlns="http://checkout.google.com/schema/2" ' +
                     'serial-number="%s" />') % full_sn)
Example #38
0
File: ipn.py Project: rolmos/reddit
    def POST_goldcharge(self, form, jquery, token, passthrough, pennies, months):
        """
        Submit charge to stripe.

        Called by GoldPayment form. This submits the charge to stripe, and gold
        will be applied once we receive a webhook from stripe.

        """

        try:
            payment_blob = validate_blob(passthrough)
        except GoldException as e:
            # This should never happen. All fields in the payment_blob
            # are validated on creation
            form.set_html('.status',
                          _('something bad happened, try again later'))
            g.log.debug('POST_goldcharge: %s' % e.message)
            return

        penny_months, days = months_and_days_from_pennies(pennies)
        if not months or months != penny_months:
            form.set_html('.status', _('stop trying to trick the form'))
            return

        stripe.api_key = g.STRIPE_SECRET_KEY

        try:
            customer = stripe.Customer.create(card=token)

            if (customer['active_card']['address_line1_check'] == 'fail' or
                customer['active_card']['address_zip_check'] == 'fail'):
                form.set_html('.status',
                              _('error: address verification failed'))
                form.find('.stripe-submit').removeAttr('disabled').end()
                return

            if customer['active_card']['cvc_check'] == 'fail':
                form.set_html('.status', _('error: cvc check failed'))
                form.find('.stripe-submit').removeAttr('disabled').end()
                return

            charge = stripe.Charge.create(
                amount=pennies,
                currency="usd",
                customer=customer['id'],
                description='%s-%s' % (passthrough, c.user.name)
            )
        except stripe.CardError as e:
            form.set_html('.status', 'error: %s' % e.message)
            form.find('.stripe-submit').removeAttr('disabled').end()
        except stripe.InvalidRequestError as e:
            form.set_html('.status', _('invalid request'))
        except stripe.APIConnectionError as e:
            form.set_html('.status', _('api error'))
        except stripe.AuthenticationError as e:
            form.set_html('.status', _('connection error'))
        except stripe.StripeError as e:
            form.set_html('.status', _('error'))
            g.log.error('stripe error: %s' % e)
        else:
            form.set_html('.status', _('payment submitted'))

            # webhook usually sends near instantly, send a message in case
            subject = _('reddit gold payment')
            msg = _('Your payment is being processed and reddit gold will be '
                    'delivered shortly.')
            send_system_message(c.user, subject, msg)
Example #39
0
    def process_webhook(self, event_type, passthrough, transaction_id, pennies, months):
        if event_type == "noop":
            return

        try:
            payment_blob = validate_blob(passthrough)
        except GoldError as e:
            g.log.error("%s %s: bad payment_blob %s" % (self.name, transaction_id, e))
            self.abort403()

        goldtype = payment_blob["goldtype"]
        buyer = payment_blob["buyer"]
        recipient = payment_blob.get("recipient", None)
        signed = payment_blob.get("signed", False)
        giftmessage = payment_blob.get("giftmessage", None)
        comment = payment_blob.get("comment", None)
        comment = comment._fullname if comment else None
        existing = retrieve_gold_transaction(transaction_id)

        if event_type == "cancelled":
            subject = "gold payment cancelled"
            msg = "your gold payment has been cancelled, contact " "%(gold_email)s for details" % {
                "gold_email": g.goldthanks_email
            }
            send_system_message(buyer, subject, msg)
            if existing:
                # note that we don't check status on existing, probably
                # should update gold_table when a cancellation happens
                reverse_gold_purchase(transaction_id)
        elif event_type == "succeeded":
            if existing and existing.status == "processed":
                g.log.info("POST_goldwebhook skipping %s" % transaction_id)
                return

            payer_email = ""
            payer_id = ""
            subscription_id = None
            complete_gold_purchase(
                passthrough,
                transaction_id,
                payer_email,
                payer_id,
                subscription_id,
                pennies,
                months,
                goldtype,
                buyer,
                recipient,
                signed,
                giftmessage,
                comment,
            )
        elif event_type == "failed":
            subject = "gold payment failed"
            msg = "your gold payment has failed, contact %(gold_email)s for " "details" % {
                "gold_email": g.goldthanks_email
            }
            send_system_message(buyer, subject, msg)
            # probably want to update gold_table here
        elif event_type == "refunded":
            if not (existing and existing.status == "processed"):
                return

            subject = "gold refund"
            msg = "your gold payment has been refunded, contact " "%(gold_email)s for details" % {
                "gold_email": g.goldthanks_email
            }
            send_system_message(buyer, subject, msg)
            reverse_gold_purchase(transaction_id)
Example #40
0
    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")
Example #41
0
    def POST_goldcharge(self, form, jquery, token, passthrough, pennies,
                        months, period):
        """
        Submit charge to stripe.

        Called by GoldPayment form. This submits the charge to stripe, and gold
        will be applied once we receive a webhook from stripe.

        """

        try:
            payment_blob = validate_blob(passthrough)
        except GoldException as e:
            # This should never happen. All fields in the payment_blob
            # are validated on creation
            form.set_html('.status',
                          _('something bad happened, try again later'))
            g.log.debug('POST_goldcharge: %s' % e.message)
            return

        if period:
            plan_id = (g.STRIPE_MONTHLY_GOLD_PLAN
                       if period == 'monthly' else g.STRIPE_YEARLY_GOLD_PLAN)
            if c.user.has_gold_subscription:
                form.set_html(
                    '.status',
                    _('your account already has a gold subscription'))
                return
        else:
            plan_id = None
            penny_months, days = months_and_days_from_pennies(pennies)
            if not months or months != penny_months:
                form.set_html('.status', _('stop trying to trick the form'))
                return

        customer = self.create_customer(form, token)
        if not customer:
            return

        if period:
            subscription = self.set_subscription(form, customer, plan_id)
            if not subscription:
                return

            c.user.gold_subscr_id = customer.id
            c.user._commit()

            status = _('subscription created')
            subject = _('reddit gold subscription')
            body = _('Your subscription is being processed and reddit gold '
                     'will be delivered shortly.')
        else:
            charge = self.charge_customer(form, customer, pennies, passthrough)
            if not charge:
                return

            status = _('payment submitted')
            subject = _('reddit gold payment')
            body = _('Your payment is being processed and reddit gold '
                     'will be delivered shortly.')

        form.set_html('.status', status)
        body = append_random_bottlecap_phrase(body)
        send_system_message(c.user, subject, body, distinguished='gold-auto')
Example #42
0
File: ipn.py Project: dinxx/reddit
    def process_webhook(self, event_type, webhook):
        if event_type == 'noop':
            return

        existing = retrieve_gold_transaction(webhook.transaction_id)
        if not existing and webhook.passthrough:
            try:
                webhook.load_blob()
            except GoldException as e:
                g.log.error('%s: payment_blob %s', webhook.transaction_id, e)
                self.abort403()
        msg = None

        if event_type == 'cancelled':
            subject = _('reddit gold payment cancelled')
            msg = _('Your reddit gold payment has been cancelled, contact '
                    '%(gold_email)s for details') % {'gold_email':
                                                     g.goldthanks_email}
            if existing:
                # note that we don't check status on existing, probably
                # should update gold_table when a cancellation happens
                reverse_gold_purchase(webhook.transaction_id)
        elif event_type == 'succeeded':
            if (existing and
                    existing.status in ('processed', 'unclaimed', 'claimed')):
                g.log.info('POST_goldwebhook skipping %s' % webhook.transaction_id)
                return

            self.complete_gold_purchase(webhook)
        elif event_type == 'failed':
            subject = _('reddit gold payment failed')
            msg = _('Your reddit gold payment has failed, contact '
                    '%(gold_email)s for details') % {'gold_email':
                                                     g.goldthanks_email}
        elif event_type == 'failed_subscription':
            subject = _('reddit gold subscription payment failed')
            msg = _('Your reddit gold subscription payment has failed. Please '
                    'go to [your gold subscription page](%(gold_subscription)s) '
                    'to make sure your information is correct, or contact '
                    '%(gold_email)s for details')
            msg %= {'gold_subscription': '/gold/subscription',
                    'gold_email': g.goldthanks_email}
        elif event_type == 'refunded':
            if not (existing and existing.status == 'processed'):
                return

            subject = _('reddit gold refund')
            msg = _('Your reddit gold payment has been refunded, contact '
                   '%(gold_email)s for details') % {'gold_email':
                                                    g.goldthanks_email}
            reverse_gold_purchase(webhook.transaction_id)

        if msg:
            if existing:
                buyer = Account._byID(int(existing.account_id), data=True)
            elif webhook.buyer:
                buyer = webhook.buyer
            else:
                return

            try:
                send_system_message(buyer, subject, msg)
            except MessageError:
                g.log.error('process_webhook: send_system_message error')
Example #43
0
File: ipn.py Project: siadat/reddit
    def POST_goldcharge(self, form, jquery, token, passthrough, pennies, months):
        """
        Submit charge to stripe.

        Called by GoldPayment form. This submits the charge to stripe, and gold
        will be applied once we receive a webhook from stripe.

        """

        try:
            payment_blob = validate_blob(passthrough)
        except GoldException as e:
            # This should never happen. All fields in the payment_blob
            # are validated on creation
            form.set_html('.status',
                          _('something bad happened, try again later'))
            g.log.debug('POST_goldcharge: %s' % e.message)
            return

        penny_months, days = months_and_days_from_pennies(pennies)
        if not months or months != penny_months:
            form.set_html('.status', _('stop trying to trick the form'))
            return

        stripe.api_key = g.STRIPE_SECRET_KEY

        try:
            customer = stripe.Customer.create(card=token)

            if (customer['active_card']['address_line1_check'] == 'fail' or
                customer['active_card']['address_zip_check'] == 'fail'):
                form.set_html('.status',
                              _('error: address verification failed'))
                form.find('.stripe-submit').removeAttr('disabled').end()
                return

            if customer['active_card']['cvc_check'] == 'fail':
                form.set_html('.status', _('error: cvc check failed'))
                form.find('.stripe-submit').removeAttr('disabled').end()
                return

            charge = stripe.Charge.create(
                amount=pennies,
                currency="usd",
                customer=customer['id'],
                description='%s-%s' % (passthrough, c.user.name)
            )
        except stripe.CardError as e:
            form.set_html('.status', 'error: %s' % e.message)
            form.find('.stripe-submit').removeAttr('disabled').end()
        except stripe.InvalidRequestError as e:
            form.set_html('.status', _('invalid request'))
        except stripe.APIConnectionError as e:
            form.set_html('.status', _('api error'))
        except stripe.AuthenticationError as e:
            form.set_html('.status', _('connection error'))
        except stripe.StripeError as e:
            form.set_html('.status', _('error'))
            g.log.error('stripe error: %s' % e)
        else:
            form.set_html('.status', _('payment submitted'))

            # webhook usually sends near instantly, send a message in case
            subject = _('gold payment')
            msg = _('your payment is being processed and gold will be'
                    ' delivered shortly')
            send_system_message(c.user, subject, msg)