Ejemplo n.º 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')
Ejemplo n.º 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
Ejemplo n.º 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')
Ejemplo n.º 4
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
Ejemplo n.º 5
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
Ejemplo n.º 6
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
    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 comment
Ejemplo n.º 7
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
Ejemplo n.º 8
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
Ejemplo n.º 9
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)
        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(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 = _('reddit gold payment failed')
            msg = _('Your reddit gold payment has failed, contact '
                    '%(gold_email)s for details') % {'gold_email':
                                                     g.goldthanks_email}
            # probably want to update gold_table here
        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(transaction_id)

        if msg:
            msg = append_random_bottlecap_phrase(msg)
            send_system_message(buyer, subject, msg, distinguished='gold-auto')
Ejemplo n.º 10
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')
Ejemplo n.º 11
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')
Ejemplo n.º 12
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)
Ejemplo n.º 13
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)
        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(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 = _('reddit gold payment failed')
            msg = _('Your reddit gold payment has failed, contact '
                    '%(gold_email)s for details') % {
                        'gold_email': g.goldthanks_email
                    }
            # probably want to update gold_table here
        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(transaction_id)

        if msg:
            msg = append_random_bottlecap_phrase(msg)
            send_system_message(buyer, subject, msg, distinguished='gold-auto')
Ejemplo n.º 14
0
    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.')
            msg = append_random_bottlecap_phrase(msg)

            send_system_message(c.user,
                                subject,
                                msg,
                                distinguished='gold-auto')
Ejemplo n.º 15
0
    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.')
            msg = append_random_bottlecap_phrase(msg)

            send_system_message(c.user, subject, msg,
                                distinguished='gold-auto')
Ejemplo n.º 16
0
    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.')
                        msg = append_random_bottlecap_phrase(msg)

                        try:
                            send_system_message(buyer,
                                                subject,
                                                msg,
                                                distinguished='gold-auto')
                        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)
Ejemplo n.º 17
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")
Ejemplo n.º 18
0
Archivo: ipn.py Proyecto: 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)
Ejemplo n.º 19
0
    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.')
                        msg = append_random_bottlecap_phrase(msg)

                        try:
                            send_system_message(buyer, subject, msg,
                                                distinguished='gold-auto')
                        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)