def arbitrary_charge(self, session, id, amount, description, email, return_to='arbitrary_charge_form'): charge = Charge(amount=100 * int(amount), description=description, receipt_email=email) stripe_intent = charge.create_stripe_intent(session) message = stripe_intent if isinstance(stripe_intent, string_types) else '' if message: return {'error': message} else: session.add( ArbitraryCharge( amount=charge.dollar_amount, what=charge.description, reg_station=cherrypy.session.get('reg_station'))) return { 'stripe_intent': stripe_intent, 'success_url': '{}?message={}'.format(return_to, 'Charge successfully processed'), 'cancel_url': 'cancel_arbitrary_charge' }
def purchases_charge(self, session, id, amount, receipt_id): receipt = session.art_show_receipt(receipt_id) attendee = session.attendee(id) charge = Charge( attendee, amount=amount, description='{}ayment for {}\'s art show purchases'.format( 'P' if int(amount) == receipt.total else 'Partial p', attendee.full_name)) stripe_intent = charge.create_stripe_intent(session) message = stripe_intent if isinstance(stripe_intent, string_types) else '' if message: return {'error': message} else: session.add( ArtShowPayment( receipt=receipt, amount=charge.amount, type=c.STRIPE, )) session.commit() return { 'stripe_intent': stripe_intent, 'success_url': 'pieces_bought?id={}&message={}'.format( attendee.id, 'Charge successfully processed') }
def process_art_show_payment(self, session, id): attendee = session.attendee(id) charge = Charge(attendee, description="Art show application payment") stripe_intent = charge.create_stripe_intent(session) message = stripe_intent if isinstance(stripe_intent, string_types) else '' if message: return {'error': message} else: for app in attendee.art_show_applications: app.status = c.PAID # This needs to accommodate payment cancellations send_email.delay( c.ADMIN_EMAIL, c.ART_SHOW_EMAIL, 'Art Show Payment Received', render('emails/art_show/payment_notification.txt', {'app': app}, encoding=None), model=app.to_dict('id')) send_email.delay( c.ART_SHOW_EMAIL, app.email, 'Art Show Payment Received', render('emails/art_show/payment_confirmation.txt', {'app': app}, encoding=None), model=app.to_dict('id')) if attendee.paid == c.NOT_PAID: attendee.paid = c.HAS_PAID session.add(session.create_receipt_item(attendee, charge.amount, "Art show payment", charge.stripe_transaction)) session.add(attendee) session.commit() return {'stripe_intent': stripe_intent, 'success_url': 'edit?id={}&message={}'.format(attendee.art_show_applications[0].id, 'Your payment has been accepted')}
def stripe_webhook_handler(request=None): if not request or not request.body: return "Request required" sig_header = cherrypy.request.headers['HTTP_STRIPE_SIGNATURE'] payload = request.body event = None try: event = stripe.Webhook.construct_event( payload, sig_header, c.STRIPE_ENDPOINT_SECRET ) except ValueError as e: # Invalid payload cherrypy.response.status = 400 except stripe.error.SignatureVerificationError as e: # Invalid signature return HttpResponse(status=400) if event['type'] == 'payment_intent.succeeded': payment_intent = event.data.object Charge.mark_paid_from_stripe(payment_intent) else: cherrypy.response.status = 400 cherrypy.response.status = 200 return "Success!"
def take_payment(self, session, id): attendee = session.attendee(id) charge = Charge(attendee, amount=attendee.amount_unpaid * 100) stripe_intent = charge.create_stripe_intent(session) message = stripe_intent if isinstance(stripe_intent, string_types) else '' if message: return {'error': message} else: db_attendee = session.query(Attendee).filter_by( id=attendee.id).first() if db_attendee: attendee = db_attendee session.add( session.create_receipt_item(attendee, charge.amount, "At-door kiosk payment", charge.stripe_transaction)) session.add(attendee) session.commit() return { 'stripe_intent': stripe_intent, 'success_url': 'register?message={}'.format(c.AT_DOOR_PREPAID_MSG) }
def test_charge_log_transaction(self, monkeypatch): attendee = Attendee() monkeypatch.setattr(Attendee, 'amount_unpaid', 10) charge = Charge(targets=[attendee], amount=1000, description="Test charge") charge.response = stripe.Charge(id=10) result = charge.stripe_transaction_from_charge() assert result.stripe_id == 10 assert result.amount == 1000 assert result.desc == "Test charge" assert result.type == c.PAYMENT assert result.who == 'non-admin'
def process_marketplace_payment(self, session, id): attendee = session.attendee(id) charge = Charge( attendee, description="Marketplace application payment for {}".format( attendee.full_name)) stripe_intent = charge.create_stripe_intent(session) message = stripe_intent if isinstance(stripe_intent, string_types) else '' if message: return {'error': message} else: if attendee.marketplace_cost: for app in attendee.marketplace_applications: cancel_amt = app.amount_unpaid app.amount_paid += app.amount_unpaid send_email.delay( c.ADMIN_EMAIL, c.MARKETPLACE_APP_EMAIL, 'Marketplace Payment Received', render('emails/marketplace/payment_notification.txt', {'app': app}, encoding=None), model=app.to_dict('id')) send_email.delay( c.MARKETPLACE_APP_EMAIL, app.email_to_address, 'Marketplace Payment Received', render('emails/marketplace/payment_confirmation.txt', {'app': app}, encoding=None), model=app.to_dict('id')) if attendee.paid == c.NOT_PAID: attendee.paid = c.HAS_PAID session.add( session.create_receipt_item(attendee, charge.amount, "Marketplace payment", charge.stripe_transaction)) session.add(attendee) session.commit() return { 'stripe_intent': stripe_intent, 'success_url': 'edit?id={}&message={}'.format( attendee.marketplace_applications[0].id, 'Your payment has been accepted'), 'cancel_url': '../preregistration/cancel_payment?model_id={}&cancel_amt={}'. format(attendee.marketplace_applications[0].id, cancel_amt) }
def test_charge_log_transaction_no_unpaid(self, monkeypatch): group = Group() monkeypatch.setattr(Group, 'amount_unpaid', 0) charge = Charge(targets=[group], amount=1000, description="Test charge") charge.response = stripe.Charge(id=10) txn = charge.stripe_transaction_from_charge() result = charge.stripe_transaction_for_model(group, txn) assert result.group_id == group.id assert result.txn_id == txn.id assert result.share == 1000
def test_charge_log_transaction_attendee(self, monkeypatch): attendee = Attendee() monkeypatch.setattr(Attendee, 'amount_unpaid', 10) charge = Charge(targets=[attendee], description="Test charge") charge.response = stripe.Charge(id=10) txn = charge.stripe_transaction_from_charge() result = charge.stripe_transaction_for_model(attendee, txn) assert result.attendee_id == attendee.id assert result.txn_id == txn.id assert result.share == 1000
def test_charge_log_transaction(self): attendee = Attendee() charge = Charge(targets=[attendee], amount=1000, description="Test charge") charge.response = stripe.Charge(id=10) result = charge.stripe_transaction_from_charge() assert result.stripe_id == 10 assert result.amount == 1000 assert result.desc == "Test charge" assert result.type == c.PAYMENT assert result.who == 'non-admin' assert result.fk_id == attendee.id assert result.fk_model == attendee.__class__.__name__
def hotel(self, session, message='', id=None, edit_id=None, requested_hotel_info=False): id = edit_id or id if not id: raise HTTPRedirect('form') if not c.PREREG_REQUEST_HOTEL_INFO_OPEN: if cherrypy.request.method == 'POST': raise HTTPRedirect('index?message={}', 'Requests for hotel booking info have already been closed') else: raise HTTPRedirect('form?edit_id={}', id) attendee = self._get_unsaved( id, if_not_found=HTTPRedirect('form?message={}', 'Could not find the given preregistration')) is_group_leader = not attendee.is_unassigned and attendee.promo_code_groups > 0 if cherrypy.request.method == 'POST': attendee.requested_hotel_info = requested_hotel_info target = attendee track_type = c.EDITED_PREREG if target.id in Charge.unpaid_preregs else c.UNPAID_PREREG Charge.unpaid_preregs[target.id] = Charge.to_sessionized(attendee) Tracking.track(track_type, attendee) raise HTTPRedirect('index') return { 'message': message, 'id': id, 'edit_id': edit_id, 'is_group_leader': is_group_leader, 'requested_hotel_info': attendee.requested_hotel_info if edit_id else True }
def stripe_webhook_handler(self): if not cherrypy.request or not cherrypy.request.body: cherrypy.response.status = 400 return "Request required" sig_header = cherrypy.request.headers.get('Stripe-Signature', '') payload = cherrypy.request.body.read() event = None try: event = stripe.Webhook.construct_event(payload, sig_header, c.STRIPE_ENDPOINT_SECRET) except ValueError as e: cherrypy.response.status = 400 return "Invalid payload: " + payload except stripe.error.SignatureVerificationError as e: cherrypy.response.status = 400 return "Invalid signature: " + sig_header if not event: cherrypy.response.status = 400 return "No event" if event and event['type'] == 'payment_intent.succeeded': payment_intent = event['data']['object'] matching_txns = Charge.mark_paid_from_stripe_id( payment_intent['id']) if not matching_txns: cherrypy.response.status = 400 return "No matching Stripe transaction" cherrypy.response.status = 200 return "Payment marked complete for payment intent ID " + payment_intent[ 'id']
def pay_for_extra_members(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [group] = charge.groups group_badge_price = c.DEALER_BADGE_PRICE if group.tables else c.GROUP_PRICE badges_to_add = charge.dollar_amount // group_badge_price if charge.dollar_amount % group_badge_price: message = 'Our preregistration price has gone up since you tried to add the badges; please try again' else: message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('group_members?id={}&message={}', group.id, message) else: session.assign_badges(group, group.badges + badges_to_add) group.amount_paid += charge.dollar_amount session.merge(group) if group.is_dealer: send_email.delay( c.MARKETPLACE_EMAIL, c.MARKETPLACE_EMAIL, 'Dealer Paid for Extra Members', render('emails/dealers/payment_notification.txt', {'group': group}, encoding=None), model=group.to_dict('id')) raise HTTPRedirect( 'group_members?id={}&message={}', group.id, 'You payment has been accepted and the badges have been added to your group')
def manual_reg_charge(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [attendee] = charge.attendees message = charge.charge_cc(session, stripeToken) if message: return { 'success': False, 'message': 'Error processing card: {}'.format(message) } else: attendee.paid = c.HAS_PAID attendee.payment_method = c.MANUAL session.add( session.create_receipt_item(attendee, attendee.total_cost * 100, "At-door desk payment", charge.stripe_transaction)) attendee.amount_paid_override = attendee.total_cost session.merge(attendee) session.commit() return { 'success': True, 'message': 'Payment accepted.', 'id': attendee.id }
def process_art_show_payment(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [attendee] = charge.attendees attendee = session.merge(attendee) apps = attendee.art_show_applications for app in apps: message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('edit?id={}&message={}', app.id, message) else: attendee.amount_paid += charge.dollar_amount app.status = c.PAID if attendee.paid == c.NOT_PAID: attendee.paid = c.HAS_PAID session.add(attendee) send_email.delay(c.ADMIN_EMAIL, c.ART_SHOW_EMAIL, 'Art Show Payment Received', render('emails/art_show/payment_notification.txt', {'app': app}, encoding=None), model=app.to_dict('id')) send_email.delay(c.ART_SHOW_EMAIL, app.email, 'Art Show Payment Received', render('emails/art_show/payment_confirmation.txt', {'app': app}, encoding=None), model=app.to_dict('id')) raise HTTPRedirect('edit?id={}&message={}', app.id, 'Your payment has been accepted!')
def pay_for_extra_codes(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [attendee] = charge.attendees attendee = session.attendee(attendee.id) group = attendee.promo_code_groups[0] badges_to_add = charge.dollar_amount // c.GROUP_PRICE if charge.dollar_amount % c.GROUP_PRICE: message = 'Our preregistration price has gone up since you tried to add more codes; please try again' else: message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('group_promo_codes?id={}&message={}', group.id, message) else: session.add(session.create_receipt_item( attendee, charge.amount, "Adding {} badge{} to promo code group {} (${} each)".format( badges_to_add, "s" if badges_to_add > 1 else "", group.name, c.GROUP_PRICE), charge.stripe_transaction, c.PROMO_CODE), ) session.add_codes_to_pc_group(group, badges_to_add) attendee.amount_paid_override += charge.dollar_amount raise HTTPRedirect( 'group_promo_codes?id={}&message={}', group.id, 'You payment has been accepted and the codes have been added to your group')
def pay_for_extra_members(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [group] = charge.groups group_badge_price = c.DEALER_BADGE_PRICE if group.tables else c.GROUP_PRICE badges_to_add = charge.dollar_amount // group_badge_price if charge.dollar_amount % group_badge_price: message = 'Our preregistration price has gone up since you tried to add the badges; please try again' else: message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('group_members?id={}&message={}', group.id, message) else: session.assign_badges(group, group.badges + badges_to_add) group.amount_paid_override += charge.dollar_amount session.add(session.create_receipt_item( group, charge.amount, "{} badge{} (${} each)".format( badges_to_add, "s" if badges_to_add > 1 else "", group.new_badge_cost), charge.stripe_transaction, c.BADGE), ) session.merge(group) if group.is_dealer: send_email.delay( c.MARKETPLACE_EMAIL, c.MARKETPLACE_EMAIL, '{} Paid for Extra Members'.format(c.DEALER_TERM.title()), render('emails/dealers/payment_notification.txt', {'group': group}, encoding=None), model=group.to_dict('id')) raise HTTPRedirect( 'group_members?id={}&message={}', group.id, 'You payment has been accepted and the badges have been added to your group')
def process_marketplace_payment(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [attendee] = charge.attendees attendee = session.merge(attendee) apps = attendee.marketplace_applications message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('edit?id={}&message={}', apps[0].id, message) else: attendee_payment = charge.dollar_amount if attendee.marketplace_cost: for app in attendee.marketplace_applications: attendee_payment -= app.amount_unpaid app.amount_paid += app.amount_unpaid attendee.amount_paid += attendee_payment if attendee.paid == c.NOT_PAID: attendee.paid = c.HAS_PAID session.add(attendee) send_email.delay(c.ADMIN_EMAIL, c.MARKETPLACE_APP_EMAIL, 'Marketplace Payment Received', render('emails/marketplace/payment_notification.txt', {'app': app}, encoding=None), model=app.to_dict('id')) send_email.delay(c.MARKETPLACE_APP_EMAIL, app.email, 'Marketplace Payment Received', render('emails/marketplace/payment_confirmation.txt', {'app': app}, encoding=None), model=app.to_dict('id')) raise HTTPRedirect('edit?id={}&message={}', app.id, 'Your payment has been accepted!')
def process_group_payment(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [group] = charge.groups message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('group_members?id={}&message={}', group.id, message) else: group.amount_paid += charge.dollar_amount session.merge(group) if group.is_dealer: try: send_email.delay( c.MARKETPLACE_EMAIL, c.MARKETPLACE_EMAIL, 'Dealer Payment Completed', render('emails/dealers/payment_notification.txt', {'group': group}, encoding=None), model=group.to_dict('id')) except Exception: log.error( 'unable to send dealer payment confirmation email', exc_info=True) raise HTTPRedirect('group_members?id={}&message={}', group.id, 'Your payment has been accepted!')
def pay_for_extra_members(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [group] = charge.groups badges_to_add = charge.dollar_amount // c.GROUP_PRICE if charge.dollar_amount % c.GROUP_PRICE: message = 'Our preregistration price has gone up since you tried to add the badges; please try again' else: message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('group_members?id={}&message={}', group.id, message) else: session.assign_badges(group, group.badges + badges_to_add) group.amount_paid += charge.dollar_amount session.merge(group) if group.is_dealer: send_email.delay( c.MARKETPLACE_EMAIL, c.MARKETPLACE_EMAIL, 'Dealer Paid for Extra Members', render('emails/dealers/payment_notification.txt', {'group': group}, encoding=None), model=group.to_dict('id')) raise HTTPRedirect( 'group_members?id={}&message={}', group.id, 'You payment has been accepted and the badges have been added to your group' )
def index(self, message=''): if not Charge.unpaid_preregs: raise HTTPRedirect('form?message={}', message) if message else HTTPRedirect('form') else: return { 'message': message, 'charge': Charge(listify(Charge.unpaid_preregs.values())) }
def _get_unsaved(self, id, if_not_found=None): """ if_not_found: pass in an HTTPRedirect() class to raise if the unsaved attendee is not found. by default we will redirect to the index page """ if id in Charge.unpaid_preregs: return Charge.from_sessionized(Charge.unpaid_preregs[id]) else: raise HTTPRedirect('index') if if_not_found is None else if_not_found
def manual_reg_charge(self, session, id): attendee = session.attendee(id) charge = Charge(attendee, amount=attendee.amount_unpaid * 100) stripe_intent = charge.create_stripe_intent(session) message = stripe_intent if isinstance(stripe_intent, string_types) else '' if message: return {'error': message} else: attendee.payment_method = c.MANUAL session.add( session.create_receipt_item(attendee, charge.amount, "At-door desk payment", charge.stripe_transaction)) session.merge(attendee) session.commit() return {'stripe_intent': stripe_intent, 'success_url': ''}
def pay(self, session, id, message=''): attendee = session.attendee(id) if attendee.paid != c.NOT_PAID: raise HTTPRedirect('register?message={}', c.AT_DOOR_NOPAY_MSG) else: return { 'message': message, 'attendee': attendee, 'charge': Charge(attendee, description=attendee.full_name) }
def repurchase(self, session, id, **params): if 'csrf_token' in params: old_attendee = session.attendee(id).to_dict(c.UNTRANSFERABLE_ATTRS) del old_attendee['id'] new_attendee = Attendee(**old_attendee) Charge.unpaid_preregs[new_attendee.id] = Charge.to_sessionized( new_attendee) Tracking.track(c.UNPAID_PREREG, new_attendee) raise HTTPRedirect("form?edit_id={}", new_attendee.id) return {'id': id}
def sales_charge(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('sales_charge_form?message={}', message) else: session.add( ArbitraryCharge(amount=charge.dollar_amount, what=charge.description)) raise HTTPRedirect('sales_charge_form?message={}', 'Charge successfully processed')
def index(self, session, message=''): if not Charge.unpaid_preregs: raise HTTPRedirect('form?message={}', message) if message else HTTPRedirect('form') else: charge = Charge(listify(Charge.unpaid_preregs.values())) for attendee in charge.attendees: if attendee.promo_code and attendee.promo_code.group: attendee.group_name = session.query(PromoCode).filter_by( code=attendee.promo_code.code).first().group.name return {'message': message, 'charge': charge}
def repurchase(self, session, id, **params): if 'csrf_token' in params: old_attendee = session.attendee(id).to_dict(c.UNTRANSFERABLE_ATTRS) del old_attendee['id'] new_attendee = Attendee(**old_attendee) Charge.unpaid_preregs[new_attendee.id] = Charge.to_sessionized(new_attendee) Tracking.track(c.UNPAID_PREREG, new_attendee) raise HTTPRedirect("form?edit_id={}", new_attendee.id) return { 'id': id }
def check_missed_stripe_payments(): pending_ids = [] with Session() as session: pending_payments = session.query(StripeTransaction).filter_by( type=c.PENDING) for payment in pending_payments: pending_ids.append(payment.stripe_id) events = stripe.Event.list( type='payment_intent.succeeded', created={ # Check for events created in the last hour. 'gte': int(time.time() - 60 * 60), }) for event in events.auto_paging_iter(): payment_intent = event.data.object log.debug('Processing Payment Intent ID {}', payment_intent.id) if payment_intent.id in pending_ids: log.debug('Charge is pending, intent ID is {}', payment_intent.id) Charge.mark_paid_from_stripe_id(payment_intent.id)
def arbitrary_charge(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('arbitrary_charge_form?message={}', message) else: session.add(ArbitraryCharge( amount=charge.dollar_amount, what=charge.description, reg_station=cherrypy.session.get('reg_station') )) raise HTTPRedirect('{}?message={}', return_to, 'Charge successfully processed')
def prereg_payment(self, session, payment_id=None, stripeToken=None): if not payment_id or not stripeToken or c.HTTP_METHOD != 'POST': message = 'The payment was interrupted. Please check below to ensure you received your badge.' raise HTTPRedirect('paid_preregistrations?message={}', message) charge = Charge.get(payment_id) if not charge.total_cost: message = 'Your total cost was $0. Your credit card has not been charged.' elif charge.amount != charge.total_cost: message = 'Our preregistration price has gone up; ' \ 'please fill out the payment form again at the higher price' else: message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('index?message={}', message) # from this point on, the credit card has actually been charged but we haven't marked anything as charged yet. # be ultra-careful until the attendees/groups are marked paid and written to the DB or we could end up in a # situation where we took the payment, but didn't mark the cards charged for attendee in charge.attendees: attendee.paid = c.HAS_PAID attendee.amount_paid = attendee.total_cost attendee_name = 'PLACEHOLDER' if attendee.is_unassigned else attendee.full_name log.info("PAYMENT: marked attendee id={} ({}) as paid", attendee.id, attendee_name) session.add(attendee) for group in charge.groups: group.amount_paid = group.default_cost log.info("PAYMENT: marked group id={} ({}) as paid", group.id, group.name) for attendee in group.attendees: attendee.amount_paid = attendee.total_cost - attendee.badge_cost attendee_name = 'UNASSIGNED PLACEHOLDER' if attendee.is_unassigned else attendee.full_name log.info("PAYMENT: marked group member id={} ({}) as paid", attendee.id, attendee_name) session.add(group) session.commit( ) # paranoia: really make sure we lock in marking taking payments in the database Charge.unpaid_preregs.clear() Charge.paid_preregs.extend(charge.targets) log.debug( 'PAYMENT: prereg payment actual charging process FINISHED for stripeToken={}', stripeToken) raise HTTPRedirect('paid_preregistrations?payment_received={}', charge.dollar_amount)
def sales_charge(self, session, id, amount, description): charge = Charge(amount=100 * float(amount), description=description) stripe_intent = charge.create_stripe_intent(session) message = stripe_intent if isinstance(stripe_intent, string_types) else '' if message: return {'error': message} else: session.add( ArbitraryCharge( amount=charge.dollar_amount, what=charge.description, )) return { 'stripe_intent': stripe_intent, 'success_url': 'sales_charge_form?message={}'.format( 'Charge successfully processed'), 'cancel_url': '../merch_admin/cancel_arbitrary_charge' }
def manual_reg_charge(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [attendee] = charge.attendees message = charge.charge_cc(session, stripeToken) if message: return {'success': False, 'message': 'Error processing card: {}'.format(message)} else: attendee.paid = c.HAS_PAID attendee.payment_method = c.MANUAL attendee.amount_paid = attendee.total_cost session.merge(attendee) session.commit() return {'success': True, 'message': 'Payment accepted.', 'id': attendee.id}
def paid_preregistrations(self, session, payment_received=None, message=''): if not Charge.paid_preregs: raise HTTPRedirect('index') else: preregs = [session.merge(Charge.from_sessionized(d)) for d in Charge.paid_preregs] for prereg in preregs: try: session.refresh(prereg) except Exception: pass # this badge must have subsequently been transferred or deleted return { 'preregs': preregs, 'total_cost': payment_received, 'message': message }
def take_payment(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [attendee] = charge.attendees message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('pay?id={}&message={}', attendee.id, message) else: db_attendee = session.query(Attendee).filter_by(id=attendee.id).first() if db_attendee: attendee = db_attendee attendee.paid = c.HAS_PAID attendee.amount_paid = attendee.total_cost session.add(attendee) raise HTTPRedirect( 'register?message={}', c.AT_DOOR_PREPAID_MSG)
def process_attendee_donation(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [attendee] = charge.attendees message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('attendee_donation_form?id=' + attendee.id + '&message={}', message) else: # It's safe to assume the attendee exists in the database already. # The only path to reach this method requires the attendee to have # already paid for their registration, thus the attendee has been # saved to the database. attendee = session.query(Attendee).get(attendee.id) attendee.amount_paid += charge.dollar_amount if attendee.paid == c.NOT_PAID and attendee.amount_paid == attendee.total_cost: attendee.paid = c.HAS_PAID raise HTTPRedirect('badge_updated?id={}&message={}', attendee.id, 'Your payment has been accepted')
def pay_for_extra_codes(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [attendee] = charge.attendees group = session.attendee(attendee.id).promo_code_groups[0] badges_to_add = charge.dollar_amount // c.GROUP_PRICE if charge.dollar_amount % c.GROUP_PRICE: message = 'Our preregistration price has gone up since you tried to add more codes; please try again' else: message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('group_promo_codes?id={}&message={}', group.id, message) else: session.add_codes_to_pc_group(group, badges_to_add) attendee.amount_paid += charge.dollar_amount session.merge(attendee) raise HTTPRedirect( 'group_promo_codes?id={}&message={}', group.id, 'You payment has been accepted and the codes have been added to your group')
def process_group_payment(self, session, payment_id, stripeToken): charge = Charge.get(payment_id) [group] = charge.groups message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('group_members?id={}&message={}', group.id, message) else: group.amount_paid += charge.dollar_amount session.merge(group) if group.is_dealer: try: send_email.delay( c.MARKETPLACE_EMAIL, c.MARKETPLACE_EMAIL, 'Dealer Payment Completed', render('emails/dealers/payment_notification.txt', {'group': group}, encoding=None), model=group.to_dict('id')) except Exception: log.error('unable to send dealer payment confirmation email', exc_info=True) raise HTTPRedirect('group_members?id={}&message={}', group.id, 'Your payment has been accepted!')
def prereg_payment(self, session, payment_id=None, stripeToken=None): if not payment_id or not stripeToken or c.HTTP_METHOD != 'POST': message = 'The payment was interrupted. Please check below to ensure you received your badge.' raise HTTPRedirect('paid_preregistrations?message={}', message) charge = Charge.get(payment_id) if not charge.total_cost: message = 'Your total cost was $0. Your credit card has not been charged.' elif charge.amount != charge.total_cost: message = 'Our preregistration price has gone up; ' \ 'please fill out the payment form again at the higher price' else: message = charge.charge_cc(session, stripeToken) if message: raise HTTPRedirect('index?message={}', message) # from this point on, the credit card has actually been charged but we haven't marked anything as charged yet. # be ultra-careful until the attendees/groups are marked paid and written to the DB or we could end up in a # situation where we took the payment, but didn't mark the cards charged for attendee in charge.attendees: attendee.paid = c.HAS_PAID attendee_name = 'PLACEHOLDER' if attendee.is_unassigned else attendee.full_name log.info("PAYMENT: marked attendee id={} ({}) as paid", attendee.id, attendee_name) session.add(attendee) if attendee.badges: pc_group = session.create_promo_code_group(attendee, attendee.name, int(attendee.badges) - 1) session.add(pc_group) session.commit() attendee.amount_paid = attendee.total_cost session.commit() # paranoia: really make sure we lock in marking taking payments in the database Charge.unpaid_preregs.clear() Charge.paid_preregs.extend(charge.targets) log.debug('PAYMENT: prereg payment actual charging process FINISHED for stripeToken={}', stripeToken) raise HTTPRedirect('paid_preregistrations?payment_received={}', charge.dollar_amount)
def test_charge_log_transaction_no_model(self): stripe.Charge.create = Mock(return_value=1) Charge.stripe_transaction_from_charge = Mock() charge = Charge(amount=1000, description="Test charge") Charge.charge_cc(charge, Mock(), 1) assert not Charge.stripe_transaction_from_charge.called
def form(self, session, message='', edit_id=None, **params): """ Our production NGINX config caches the page at /preregistration/form. Since it's cached, we CAN'T return a session cookie with the page. We must POST to a different URL in order to bypass the cache and get a valid session cookie. Thus, this page is also exposed as "post_form". """ params['id'] = 'None' # security! group = Group() if edit_id is not None: attendee = self._get_unsaved( edit_id, if_not_found=HTTPRedirect('form?message={}', 'That preregistration has already been finalized')) attendee.apply(params, restricted=True) params.setdefault('pii_consent', True) else: attendee = session.attendee(params, ignore_csrf=True, restricted=True) if attendee.badge_type == c.PSEUDO_DEALER_BADGE: if not c.DEALER_REG_OPEN: return render('static_views/dealer_reg_closed.html') if c.AFTER_DEALER_REG_START \ else render('static_views/dealer_reg_not_open.html') # Both the Attendee class and Group class have identically named # address fields. In order to distinguish the two sets of address # fields in the params, the Group fields are prefixed with "group_" # when the form is submitted. To prevent instantiating the Group object # with the Attendee's address fields, we must clone the params and # rename all the "group_" fields. group_params = dict(params) for field_name in ['country', 'region', 'zip_code', 'address1', 'address2', 'city']: group_params[field_name] = params.get('group_{}'.format(field_name), '') if params.get('copy_address'): params[field_name] = group_params[field_name] group = session.group(group_params, ignore_csrf=True, restricted=True) if c.PAGE == 'post_dealer': attendee.badge_type = c.PSEUDO_DEALER_BADGE elif not attendee.badge_type: attendee.badge_type = c.ATTENDEE_BADGE if cherrypy.request.method == 'POST' or edit_id is not None: message = check_pii_consent(params, attendee) or message if not message and attendee.badge_type not in c.PREREG_BADGE_TYPES: message = 'Invalid badge type!' if not message and c.BADGE_PROMO_CODES_ENABLED and params.get('promo_code'): message = session.add_promo_code_to_attendee(attendee, params.get('promo_code')) if message: return { 'message': message, 'attendee': attendee, 'group': group, 'edit_id': edit_id, 'affiliates': session.affiliates(), 'cart_not_empty': Charge.unpaid_preregs, 'copy_address': params.get('copy_address'), 'promo_code': params.get('promo_code', ''), 'pii_consent': params.get('pii_consent'), } if 'first_name' in params: message = check(attendee, prereg=True) if not message and attendee.badge_type == c.PSEUDO_DEALER_BADGE: message = check(group, prereg=True) if attendee.badge_type in [c.PSEUDO_GROUP_BADGE, c.PSEUDO_DEALER_BADGE]: message = "Please enter a group name" if not params.get('name') else '' else: params['badges'] = 0 params['name'] = '' if not message: if attendee.badge_type == c.PSEUDO_DEALER_BADGE: attendee.paid = c.PAID_BY_GROUP group.attendees = [attendee] session.assign_badges(group, params['badges']) group.status = c.WAITLISTED if c.DEALER_REG_SOFT_CLOSED else c.UNAPPROVED attendee.ribbon = add_opt(attendee.ribbon_ints, c.DEALER_RIBBON) attendee.badge_type = c.ATTENDEE_BADGE session.add_all([attendee, group]) session.commit() try: send_email.delay( c.MARKETPLACE_EMAIL, c.MARKETPLACE_EMAIL, 'Dealer Application Received', render('emails/dealers/reg_notification.txt', {'group': group}, encoding=None), model=group.to_dict('id')) send_email.delay( c.MARKETPLACE_EMAIL, attendee.email, 'Dealer Application Received', render('emails/dealers/application.html', {'group': group}, encoding=None), 'html', model=group.to_dict('id')) except Exception: log.error('unable to send marketplace application confirmation email', exc_info=True) raise HTTPRedirect('dealer_confirmation?id={}', group.id) else: track_type = c.UNPAID_PREREG if attendee.id in Charge.unpaid_preregs: track_type = c.EDITED_PREREG # Clear out any previously cached targets, in case the unpaid badge # has been edited and changed from a single to a group or vice versa. del Charge.unpaid_preregs[attendee.id] Charge.unpaid_preregs[attendee.id] = Charge.to_sessionized(attendee, params.get('name'), params.get('badges')) Tracking.track(track_type, attendee) if session.attendees_with_badges().filter_by( first_name=attendee.first_name, last_name=attendee.last_name, email=attendee.email).count(): raise HTTPRedirect('duplicate?id={}', group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) if attendee.banned: raise HTTPRedirect('banned?id={}', group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) if c.PREREG_REQUEST_HOTEL_INFO_OPEN: hotel_page = 'hotel?edit_id={}' if edit_id else 'hotel?id={}' raise HTTPRedirect(hotel_page, group.id if attendee.paid == c.PAID_BY_GROUP else attendee.id) else: raise HTTPRedirect('index') else: if edit_id is None: if attendee.badge_type == c.PSEUDO_DEALER_BADGE: # All new dealer signups should default to receiving the # hotel info email, even if the deadline has passed. # There's a good chance some dealers will apply for a table # AFTER the hotel booking deadline, but BEFORE the hotel # booking is sent out. This ensures they'll still receive # the email, as requested by the Marketplace Department. attendee.requested_hotel_info = True if attendee.badge_type == c.PSEUDO_DEALER_BADGE and c.DEALER_REG_SOFT_CLOSED: message = 'Dealer registration is closed, but you can ' \ 'fill out this form to add yourself to our waitlist' promo_code_group = None if attendee.promo_code: promo_code_group = session.query(PromoCode).filter_by(code=attendee.promo_code.code).first().group return { 'message': message, 'attendee': attendee, 'group': group, 'promo_code_group': promo_code_group, 'edit_id': edit_id, 'affiliates': session.affiliates(), 'cart_not_empty': Charge.unpaid_preregs, 'copy_address': params.get('copy_address'), 'promo_code': params.get('promo_code', ''), 'pii_consent': params.get('pii_consent'), }