コード例 #1
0
ファイル: sales.py プロジェクト: rangsutu88/Tktr
 def payment_stage_view(self):
     if not self.request.matchdict["ref_code"] in self.request.root.payments:
         return HTTPFound(
             location=self.request.route_path("admin_payments"))
     payment = self.request.root.payments[
         self.request.matchdict["ref_code"]]
     stage_index = int(float(self.request.matchdict["stage_index"]))
     if stage_index < 0 or stage_index >= len(payment.history):
         return HTTPFound(location=self.request.route_path(
             "admin_single_payment", ref_code=payment.__name__))
     if "action" in self.request.GET and self.request.GET[
             "action"] == "delete":
         if len(payment.history) <= 1:
             self.request.session.flash(
                 "Must have at least one payment left undeleted", "error")
         else:
             del payment.history[stage_index]
             # Need to work out if still paid?
             if payment.amount_remaining > 0:
                 payment.completed_date = None
                 # Check if the latest stage has been paid into yet?
                 latest = payment.history[-1]
                 if latest.completed:
                     # Add a new payment stage of the same type as the latest
                     new_stage = PaymentStage()
                     new_stage.__parent__ = payment
                     new_stage.method = latest.method
                     new_stage.stage_owner = payment.owner.__name__
                     payment.history.append(new_stage)
             self.request.session.flash(
                 "Removed payment stage successfully", "info")
             return HTTPFound(location=self.request.route_path(
                 "admin_single_payment", ref_code=payment.__name__))
     return {"payment": payment, "stage": payment.history[stage_index]}
コード例 #2
0
ファイル: sales.py プロジェクト: rangsutu88/Tktr
 def change_payment_method_view(self):
     payments = self.request.root.payments
     # Get payment if possible
     if not self.request.matchdict["ref_code"] in self.request.root.payments:
         return HTTPFound(
             location=self.request.route_path("admin_payments"))
     payment = payments[self.request.matchdict["ref_code"]]
     active_stage = (payment.history[len(payment.history) - 1] if
                     (len(payment.history) > 0) else None)
     # Check if already marked as paid
     if payment.paid:
         return HTTPFound(location=self.request.route_path(
             'admin_single_payment', ref_code=payment.__name__))
     # Deal with post request
     if "submit" in self.request.POST:
         if not "method" in self.request.POST:
             self.request.session.flash(
                 "Make sure to select a new payment method.", "error")
         else:
             method = self.request.POST["method"]
             # - First check if the active stage is the current method
             if active_stage.method != method:
                 # Update payment method to match that entered
                 active_stage = PaymentStage()
                 active_stage.__parent__ = payment
                 active_stage.method = method
                 active_stage.stage_owner = payment.owner.__name__
                 active_stage.amount_paid = 0
                 active_stage.processing_charge = 0
                 active_stage.completed = False
                 payment.history.append(active_stage)
             self.request.session.flash(
                 "Payment details have been updated.", "info")
             return HTTPFound(location=self.request.route_path(
                 'admin_single_payment', ref_code=payment.__name__))
     return {
         "payment":
         payment,
         "active_stage":
         active_stage,
         "methods":
         PROP_KEYS.getProperty(self.request, PROP_KEYS.PAYMENT_METHODS)
     }
コード例 #3
0
 def guest_info_edit_pay_view(self):
     # Get the ticket details
     user = self.user
     tick_id = (self.request.matchdict["tick_id"]
                if "tick_id" in self.request.matchdict else None)
     if tick_id == None:
         self.request.session.flash(
             "An error occurred whilst trying to retrieve the ticket details.",
             "error")
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # Check guest details requirement is actually enabled
     if not self.guest_details_required:
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # Try getting the ticket
     try:
         ticket = [x for x in user.tickets if x.__name__ == tick_id][0]
     except Exception:
         self.request.session.flash(
             "An error occurred whilst trying to retrieve the ticket details.",
             "error")
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # Check if this ticket is locked down
     locked_down = ticket.tick_type.locked_down
     if not locked_down:  # Check all addons as well
         for addon in ticket.addons.values():
             if addon.locked_down:
                 locked_down = True
                 break
     if locked_down:
         self.request.session.flash(
             "Editing of guest details for this ticket has been disabled.",
             "info")
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # Check that we haven't already paid for editing of this ticket and that we have to in the first place!
     if (self.details_fee_enabled
             and ticket.change_enabled) or not self.details_fee_enabled:
         return HTTPFound(location=self.request.route_path(
             "ticket_edit_guest", tick_id=tick_id))
     # Check if the user first needs to complete payment
     if not ticket.payment.paid:
         self.request.session.flash(
             "You must complete payment for this ticket before editing guest details.",
             "info")
         return HTTPFound(location=self.request.route_path("ticket_details",
                                                           tick_id=tick_id))
     # If this is the owners ticket then don't allow them to change the details
     if ticket.guest_info == ticket.owner.profile:
         return HTTPFound(
             location=self.request.route_path("user_profile_edit"))
     # If we receive a payment then deal with it
     if "stripeToken" in self.request.POST:
         # Run Stripe payment to authorise
         organisation_name = self.get_payment_method('stripe').settings[
             PROP_KEYS.ORGANISATION_NAME].value
         details_fee = PROP_KEYS.getProperty(self.request,
                                             PROP_KEYS.DETAILS_FEE)
         token = self.request.POST["stripeToken"]
         stripe.api_key = self.get_payment_method('stripe').settings[
             PROP_KEYS.STRIPE_API_KEY].value
         charge = None
         error = None
         try:
             charge = stripe.Charge.create(amount=details_fee,
                                           currency="gbp",
                                           source=token,
                                           description=organisation_name)
             if "paid" in charge and charge["paid"] == True:
                 # Update the ticket that a guest alteration is allowed and then forward to the editing form
                 ticket.change_enabled = True
                 # Append a payment stage covering the detail change charge
                 charge_stage = PaymentStage()
                 charge_stage.__parent__ = ticket.payment
                 charge_stage.method_properties["last_four"] = charge[
                     "source"]["last4"]
                 charge_stage.method_properties["ref_code"] = charge["id"]
                 charge_stage.amount_paid = details_fee
                 charge_stage.processing_charge = details_fee
                 charge_stage.completed = charge_stage.received = charge_stage.cashed = True
                 charge_stage.stage_owner = self.user.__name__
                 charge_stage.date = datetime.now()
                 charge_stage.method = "stripe"
                 charge_stage.transfer = True
                 ticket.payment.history.append(charge_stage)
                 # Forward to the page to actually edit details
                 return HTTPFound(location=self.request.route_path(
                     "ticket_edit_guest", tick_id=tick_id))
             else:
                 error = "The payment failed, please check your details and try again!"
                 if "failure_message" in charge and charge[
                         "failure_message"] != None:
                     error = charge["failure_message"]
         except stripe.error.CardError, e:
             logging.error(self.user.username +
                           ": Stripe invalid card error occurred: %s" % e)
             error = e
         except stripe.error.InvalidRequestError, e:
             logging.error(self.user.username +
                           ": Stripe invalid card request occurred: %s" % e)
             error = e
コード例 #4
0
ファイル: pay_stripe.py プロジェクト: rangsutu88/Tktr
    def alter_pay_stripe_completion_do(self):
        # Check that we have a stripe charge object
        stripe_charge = self.request.session[
            "stripe_charge"] if "stripe_charge" in self.request.session else None
        if stripe_charge == None:
            logging.exception(
                self.user.username +
                ": Stripe charge object was not found in session")
            return self.alter_pay_stripe_view(
                error=
                "During processing the Stripe transaction has been lost, please contact the ticketing officer."
            )

        # Clear the charge object from the session
        self.request.session.pop("stripe_charge", None)

        # Retrieve the payment
        payment_id = self.request.matchdict[
            "payment_id"] if "payment_id" in self.request.matchdict else None
        payment = self.request.root.payments[
            payment_id] if payment_id != None else None
        if payment == None:
            logging.exception(
                self.user.username +
                ": Payment could not be located whilst trying to update payment with Stripe charge %s"
                % stripe_charge["id"])
            self.refund_stripe_charge(stripe_charge["id"])
            return self.alter_pay_stripe_view(
                error=
                "During processing a critical error occurred, please contact the ticketing officer immediately."
            )

        # Pickup the stripe method (regardless of if disabled as we now have made a charge!)
        all_methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
        method = [x for x in all_methods if x.__name__ == "stripe"]
        method = method[0] if len(method) > 0 else None
        if method == None:
            logging.exception(
                self.user.username +
                ": Method could not be found whilst trying to update payment %s with Stripe charge %s"
                % (payment_id, stripe_charge["id"]))
            self.refund_stripe_charge(stripe_charge["id"])
            return self.alter_pay_stripe_view(
                error=
                "During processing a critical error occurred, please contact the ticketing officer immediately."
            )

        # Retrieve stripe processing values
        process_percentage = method.settings[
            PROP.PAYMENT_PROCESSING_PERCENTAGE].value
        process_fee = method.settings[PROP.PAYMENT_PROCESSING_FEE].value

        # Calculate the amount to pay
        subtotal = payment.amount_remaining
        processing = int(ceil(subtotal * process_percentage) + process_fee)
        total = int(ceil(subtotal + processing))

        try:
            # Acquire the source information
            charge_id = stripe_charge[
                "id"] if "source" in stripe_charge else None
            source = stripe_charge[
                "source"] if "source" in stripe_charge else None
            last_four = source[
                "last4"] if source != None and "last4" in source else None
            logging.info(self.user.username +
                         ": Constructing payment from Stripe charge %s" %
                         charge_id)

            # Attach new payment stage to the payment
            stage = PaymentStage()
            stage.__parent__ = payment
            stage.method = "stripe"
            stage.method_properties["last_four"] = last_four
            stage.method_properties["ref_code"] = charge_id
            stage.amount_paid = total
            stage.processing_charge = processing
            stage.completed = True
            stage.received = stage.cashed = True
            stage.stage_owner = self.user.__name__
            payment.history.append(stage)
            payment.completed_date = datetime.now()
            self.request.session["payment_id"] = payment.ref_code
            logging.info(
                self.user.username +
                ": Successfully updated payment %s with Stripe charge %s" %
                (payment.ref_code, charge_id))
            return HTTPFound(location=self.request.route_path(
                "alter_confirm", payment_id=payment_id))

        except Exception as e:
            logging.exception(self.user.username +
                              ": Exception thrown in Stripe checkout: %s" % e)
            # We need to refund immediately as this is an error
            charge_id = stripe_charge[
                "id"] if "source" in stripe_charge else None
            if not self.refund_stripe_charge(charge_id):
                return self.alter_pay_stripe_view(
                    error=
                    "An error occurred during Stripe checkout and the system could not refund you automatically: %s"
                    % e)
            else:
                return self.alter_pay_stripe_view(
                    error=
                    "An error occurred during Stripe checkout but you have been automatically refunded the full amount: %s"
                    % e)
        # We should never get here!
        logging.exception(self.user.username +
                          ": Stripe payment completion escaped expected block")
        return self.alter_pay_stripe_view(
            error=
            "An unexpected error occurred during checkout, please contact the ticketing officer."
        )
コード例 #5
0
    def make_transfer(self, old_user, new_user, ticket, transfer_fee, stripe_charge=None):
        payment = ticket.payment
        
        # Open a new payment for the new owner, deduct the value of money associated
        # with this ticket from the original payment and add it to this payment, then
        # open a transfer payment stage and move the ticket across. If the original payment
        # was gifted then need to treat specially
        
        new_payment = Payment()
        new_payment.__parent__ = new_user
        new_payment.owner = new_user
        
        # Find out if it was gifted
        gifted = (len([x for x in payment.history if x.method == "gifted"]) > 0)
        
        # Open the finance stage
        finance_stage = PaymentStage()
        finance_stage.__parent__ = new_payment
        finance_stage.completed = finance_stage.received = finance_stage.cashed = True
        finance_stage.stage_owner = old_user.__name__
        finance_stage.date = datetime.now()
        if gifted:
            finance_stage.method = "gifted"
        else:
            finance_stage.method = "banktransfer"
        finance_stage.amount_paid = ticket.total_cost
        new_payment.history.append(finance_stage)
        
        # Open the ticket transfer stage
        transfer_stage = PaymentStage()
        transfer_stage.__parent__ = new_payment
        transfer_stage.amount_paid = transfer_fee
        transfer_stage.processing_charge = transfer_fee
        transfer_stage.completed = transfer_stage.received = transfer_stage.cashed = True
        transfer_stage.stage_owner = new_user.__name__
        transfer_stage.date = datetime.now()
        if stripe_charge != None:
            transfer_stage.method = "stripe"
            transfer_stage.method_properties["last_four"] = stripe_charge["source"]["last4"]
            transfer_stage.method_properties["ref_code"] = stripe_charge["id"]
        else:
            transfer_stage.method = "gifted"
        transfer_stage.transfer = True
        new_payment.history.append(transfer_stage)
        
        # Open the outgoing ticket transfer stage for the original owner
        out_trans_stage = PaymentStage()
        out_trans_stage.__parent__ = payment
        if not gifted:
            out_trans_stage.amount_paid = -ticket.total_cost # To make sure books balance!
        out_trans_stage.completed = out_trans_stage.received = out_trans_stage.cashed = True
        out_trans_stage.stage_owner = new_user.__name__
        out_trans_stage.date = datetime.now()
        if stripe_charge != None:
            out_trans_stage.method = "stripe"
            out_trans_stage.method_properties["last_four"] = stripe_charge["source"]["last4"]
            out_trans_stage.method_properties["ref_code"] = stripe_charge["id"]
        else:
            out_trans_stage.method = "gifted"
        out_trans_stage.transfer = True
        payment.history.append(out_trans_stage)
        
        # Mark new payment as having been completed today
        new_payment.completed_date = datetime.now()

        # Move the ticket over to the new payment
        new_payment.tickets.append(ticket)
        payment.tickets.remove(ticket)
        
        # Move the ticket over to the new user (different to above)
        new_user.tickets.append(ticket)
        new_user.total_tickets += 1 # We increment, but don't decrement (stop scalpers)
        old_user.tickets.remove(ticket)
        ticket.__parent__ = new_user
        ticket.payment = new_payment
        ticket.owner = new_user
        
        # Register payment
        new_user.payments.append(new_payment)
        self.request.root.payments[new_payment.__name__] = new_payment
        
        # If the receiver only has one ticket, then make this their main ticket
        if len(new_user.tickets) == 1:
            ticket.guest_info = new_user.profile
        # Else gift one free guest detail alteration and clear existing details
        else:
            ticket.guest_info = None
            ticket.change_enabled = True
            
        # Transfer complete - notify
        GenericEmail(self.request).compose_and_send(
            "Ticket Transfer Complete",
            "The ticket %s has been successfully transferred to %s. If you did not request this change, please get in touch with us by email or phone (details at the bottom of this message)."
            % (ticket.__name__, new_user.profile.fullname),
            old_user.__name__
        )
        GenericEmail(self.request).compose_and_send(
            "Ticket Transfer from %s" % old_user.profile.fullname,
            "You have been transferred a ticket (%s) from %s. If you think this is a mistake, please get in touch with us by email or phone (details at the bottom of this message)."
            % (ticket.__name__, old_user.profile.fullname),
            new_user.__name__
        )
        self.request.session.flash("Ticket transfer successful!", "info")
        return HTTPFound(location=self.request.route_path("user_profile"))
コード例 #6
0
    def banktransfer_view(self):
        # Detect a payment alteration
        payment_id = None
        payment = None
        if "payment_id" in self.request.matchdict:
            payment_id = self.request.matchdict["payment_id"]
        # Check we can be here
        methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
        method = [x for x in methods if x.__name__ == "banktransfer" and x.enabled == True]
        # - First check queue/active status
        if payment_id == None and Queue(self.request).timed_out():
            return HTTPFound(self.request.route_path("purchase_timeout"))
        # - Now details
        elif payment_id == None and not self.details_complete:
            self.request.session.flash("You must complete all of your guest's details before continuing.", "error")
            return HTTPFound(location=self.request.route_path("order_details"))
        # - Check that the payment method is enabled?
        elif len(method) <= 0:
            self.request.session.flash("There was an error with the payment method you selected, please try again.", "error")
            return HTTPFound(location=self.request.route_path("pay_for_tickets"))
        # - Now run some checks that this person actually should be able to pay this
        elif payment_id != None:
            if not payment_id in self.request.root.payments:
                self.request.session.flash("The requested payment does not exist.", "error")
                return HTTPFound(location=self.request.route_path("user_profile"))
            else:
                payment = self.request.root.payments[payment_id]
                if payment.owner != self.user:
                    self.request.session.flash("The requested payment could not be found on your account.", "error")
                    return HTTPFound(location=self.request.route_path("user_profile"))
                elif payment.paid:
                    self.request.session.flash("The requested payment has already been completed, no need to alter the payment.", "error")
                    return HTTPFound(location=self.request.route_path("user_profile"))
        # Get method, processing fee & other parameters
        method = method[0]
        process_fee = method.settings[PROP.PAYMENT_PROCESSING_FEE].value
        org_name = method.get_value(PROP.ORGANISATION_NAME)
        account_number = method.get_value(PROP.BANK_ACCOUNT)
        sort_code = method.get_value(PROP.BANK_SORT_CODE)
        
        if payment_id == None:
            tickets = [x for x in self.user.tickets if x.payment == None]
            if len(tickets) == 0:
                return HTTPFound(location=self.request.route_path("buy_tickets"))

            subtotal = 0
            for tick in tickets:
                subtotal += tick.total_cost
            processing = process_fee
            total = subtotal + processing

            if "action" in self.request.GET and self.request.GET["action"] == "pay":
                if "payment_id" in self.request.session:
                    ref_code = self.request.session["payment_id"]
                    payment = Issuer(self.request.root).constructPayment(
                        user_id=self.user.__name__,
                        paid=False,
                        ref_code=ref_code
                    )
                    stage = PaymentStage()
                    stage.__parent__ = payment
                    stage.method = "banktransfer"
                    stage.processing_charge = processing
                    stage.stage_owner = self.user.__name__
                    payment.history.append(stage)
                    return HTTPFound(location=self.request.route_path("pay_confirm"))

            if not "payment_id" in self.request.session: # NEED TO CHECK FOR UNIQUENESS
                self.request.session["payment_id"] = Coding().generateUniqueCode(short=True,withdash=False)
        
            return {
                "method":           method,
                "subtotal":         self.format_price(subtotal),
                "processing":       self.format_price(processing),
                "total":            self.format_price(total),
                "org_name":         org_name,
                "alteration":       False,
                "account_number":   account_number,
                "sort_code":        sort_code,
                "payment_id":       self.request.session["payment_id"],
                "payment":          None,
                "due_date":         (datetime.now() + timedelta(days=self.payment_window)).strftime("%d/%m/%Y"),
            }
        else:
            subtotal = payment.amount_remaining
            processing = process_fee
            total = subtotal + processing
            if payment.current_method == "banktransfer":
                subtotal = payment.current_stage.amount_remaining
                processing = payment.current_stage.processing_charge
                total = subtotal + processing
            if "action" in self.request.GET and self.request.GET["action"] == "pay":
                # Don't bother adding a payment stage if we are already paying this way!
                if payment.current_method != "banktransfer":
                    # Add a new stage to the payment
                    new_stage = PaymentStage()
                    new_stage.__parent__ = payment
                    new_stage.method = "banktransfer"
                    new_stage.method_change = True
                    new_stage.processing_charge = processing
                    new_stage.stage_owner = self.user.__name__
                    payment.history.append(new_stage)
                # Forward on to the correct place
                return HTTPFound(location=self.request.route_path("alter_confirm", payment_id=payment_id))

            return {
                "method":           method,
                "subtotal":         self.format_price(subtotal),
                "processing":       self.format_price(processing),
                "total":            self.format_price(total),
                "org_name":         org_name,
                "alteration":       True,
                "account_number":   account_number,
                "sort_code":        sort_code,
                "payment_id":       payment_id,
                "payment":          payment,
                "due_date":         (datetime.now() + timedelta(days=self.payment_window)).strftime("%d/%m/%Y"),
            }
コード例 #7
0
    def transfer_ticket_payment_view(self):
        # Check agreements
        if not self.user.purchase_agreement:
            return HTTPFound(
                location=self.request.route_path("purchase_agreement_act"))
        elif not self.user.privacy_agreement:
            return HTTPFound(
                location=self.request.route_path("privacy_policy_act"))

        tick_id = self.request.matchdict["tick_id"]
        ticket = None
        # Find ticket
        for tick in self.user.tickets:
            if tick.__name__ == tick_id:
                ticket = tick
                break
        # Safety
        if ticket == None:
            self.request.session.flash("Ticket does not exist.", "error")
            return HTTPFound(location=self.request.route_path("user_profile"))
        # Check that ticket is paid for
        elif not ticket.payment.paid:
            self.request.session.flash(
                "The payment has not been completed for this ticket, therefore you cannot transfer it.",
                "error")
            return HTTPFound(location=self.request.route_path("user_profile"))
        # Also check that if they are exchanging their own ticket that they don't have guests
        elif ticket.guest_info == ticket.owner.profile and len(
                self.user.tickets) > 1:
            self.request.session.flash(
                "You may not exchange your own ticket while you still have guest tickets.",
                "error")
            return HTTPFound(location=self.request.route_path("user_profile"))
        # Now check we have received a valid posted username
        if not "transfer_to" in self.request.session:
            self.request.session.flash(
                "You must enter a username to transfer the ticket to!",
                "error")
            return HTTPFound(location=self.request.route_path(
                "transfer_ticket", tick_id=tick_id))
        elif not self.request.session["transfer_to"].lower(
        ) in self.request.root.users or self.request.session[
                "transfer_to"].lower() == self.user.__name__:
            self.request.session.flash(
                "You must enter a valid username (someone with an account) to transfer the ticket to!",
                "error")
            return HTTPFound(location=self.request.route_path(
                "transfer_ticket", tick_id=tick_id))
        recipient = self.request.session["transfer_to"].lower()
        # OK, now if we have a payment deal with it
        if "stripeToken" in self.request.POST:
            # Double check the username
            username = self.request.POST["username"].lower().replace(" ", "")
            if len(username) <= 2:
                self.request.session.flash(
                    "You must enter a valid username to transfer the ticket to. You have not been charged.",
                    "error")
                return HTTPFound(location=self.request.route_path(
                    "transfer_ticket", tick_id=tick_id))
            if not username in self.request.root.users:
                self.request.session.flash(
                    "The username \"%s\" does not exist within the system, please check again. You have not been charged."
                    % username, "error")
                return HTTPFound(location=self.request.route_path(
                    "transfer_ticket", tick_id=tick_id))
            elif self.request.root.users[
                    username].profile == None or not self.request.root.users[
                        username].profile.complete:
                self.request.session.flash(
                    "The username \"%s\" does not have a complete profile, please complete it before transferring. You have not been charged."
                    % username, "error")
                return HTTPFound(location=self.request.route_path(
                    "transfer_ticket", tick_id=tick_id))
            # Run Stripe payment to authorise
            organisation_name = self.get_payment_method('stripe').settings[
                PROP_KEYS.ORGANISATION_NAME].value
            transfer_fee = PROP_KEYS.getProperty(self.request,
                                                 PROP_KEYS.TRANSFER_FEE)
            token = self.request.POST["stripeToken"]
            stripe.api_key = self.get_payment_method('stripe').settings[
                PROP_KEYS.STRIPE_API_KEY].value
            charge = None
            error = None
            try:
                charge = stripe.Charge.create(
                    amount=transfer_fee,
                    currency="gbp",
                    source=token,
                    description=organisation_name,
                )
                if "paid" in charge and charge["paid"] == True:
                    # Ok, now exchange
                    new_user = self.request.root.users[username]
                    payment = ticket.payment
                    old_user = ticket.owner

                    # Open a new payment for the new owner, deduct the value of money associated
                    # with this ticket from the original payment and add it to this payment, then
                    # open a transfer payment stage and move the ticket across. If the original payment
                    # was gifted then need to treat specially

                    new_payment = Payment()
                    new_payment.__parent__ = new_user
                    new_payment.owner = new_user

                    # Find out if it was gifted
                    gifted = (len([
                        x for x in payment.history if x.method == "gifted"
                    ]) > 0)

                    # Open the finance stage
                    finance_stage = PaymentStage()
                    finance_stage.__parent__ = new_payment
                    finance_stage.completed = finance_stage.received = finance_stage.cashed = True
                    finance_stage.stage_owner = old_user.__name__
                    finance_stage.date = datetime.now()
                    if gifted:
                        finance_stage.method = "gifted"
                    else:
                        finance_stage.method = "banktransfer"
                    finance_stage.amount_paid = ticket.total_cost
                    new_payment.history.append(finance_stage)

                    # Open the ticket transfer stage
                    transfer_stage = PaymentStage()
                    transfer_stage.__parent__ = new_payment
                    transfer_stage.method_properties["last_four"] = charge[
                        "source"]["last4"]
                    transfer_stage.method_properties["ref_code"] = charge["id"]
                    transfer_stage.amount_paid = transfer_fee
                    transfer_stage.processing_charge = transfer_fee
                    transfer_stage.completed = transfer_stage.received = transfer_stage.cashed = True
                    transfer_stage.stage_owner = new_user.__name__
                    transfer_stage.date = datetime.now()
                    transfer_stage.method = "stripe"
                    transfer_stage.transfer = True
                    new_payment.history.append(transfer_stage)

                    # Open the outgoing ticket transfer stage for the original owner
                    out_trans_stage = PaymentStage()
                    out_trans_stage.__parent__ = payment
                    if not gifted:
                        out_trans_stage.amount_paid = -ticket.total_cost  # To make sure books balance!
                    out_trans_stage.completed = out_trans_stage.received = out_trans_stage.cashed = True
                    out_trans_stage.stage_owner = new_user.__name__
                    out_trans_stage.date = datetime.now()
                    out_trans_stage.method = "stripe"
                    out_trans_stage.method_properties["last_four"] = charge[
                        "source"]["last4"]
                    out_trans_stage.method_properties["ref_code"] = charge[
                        "id"]
                    out_trans_stage.transfer = True
                    payment.history.append(out_trans_stage)

                    # Mark new payment as having been completed today
                    new_payment.completed_date = datetime.now()

                    # Move the ticket over to the new payment
                    new_payment.tickets.append(ticket)
                    payment.tickets.remove(ticket)

                    # Move the ticket over to the new user (different to above)
                    new_user.tickets.append(ticket)
                    new_user.total_tickets += 1  # We increment, but don't decrement (stop scalpers)
                    old_user.tickets.remove(ticket)
                    ticket.__parent__ = new_user
                    ticket.payment = new_payment
                    ticket.owner = new_user

                    # Register payment
                    new_user.payments.append(new_payment)
                    self.request.root.payments[
                        new_payment.__name__] = new_payment

                    # If the receiver only has one ticket, then make this their main ticket
                    if len(new_user.tickets) == 1:
                        ticket.guest_info = new_user.profile
                    # Else gift one free guest detail alteration and clear existing details
                    else:
                        ticket.guest_info = None
                        ticket.change_enabled = True

                    # Transfer complete - notify
                    GenericEmail(self.request).compose_and_send(
                        "Ticket Transfer Complete",
                        "The ticket %s has been successfully transferred to %s. If you did not request this change, please get in touch with us by email or phone (details at the bottom of this message)."
                        % (ticket.__name__, new_user.profile.fullname),
                        old_user.__name__)
                    GenericEmail(self.request).compose_and_send(
                        "Ticket Transfer from %s" % old_user.profile.fullname,
                        "You have been transferred a ticket (%s) from %s. If you think this is a mistake, please get in touch with us by email or phone (details at the bottom of this message)."
                        % (ticket.__name__, old_user.profile.fullname),
                        new_user.__name__)
                    self.request.session.flash("Ticket transfer successful!",
                                               "info")
                    return HTTPFound(
                        location=self.request.route_path("user_profile"))
                else:
                    error = "The payment failed, please check your details and try again!"
                    if "failure_message" in charge and charge[
                            "failure_message"] != None:
                        error = charge["failure_message"]
            except stripe.error.CardError, e:
                logging.error(self.user.username +
                              ": Stripe invalid card error occurred: %s" % e)
                error = e
            except stripe.error.InvalidRequestError, e:
                logging.error(self.user.username +
                              ": Stripe invalid card request occurred: %s" % e)
                error = e
コード例 #8
0
ファイル: sales.py プロジェクト: rangsutu88/Tktr
    def enter_payment_view(self):
        payments = self.request.root.payments
        # Get payment if possible
        if not self.request.matchdict["ref_code"] in self.request.root.payments:
            return HTTPFound(
                location=self.request.route_path("admin_payments"))
        payment = payments[self.request.matchdict["ref_code"]]
        active_stage = (payment.history[len(payment.history) - 1] if
                        (len(payment.history) > 0) else None)
        # Check if already marked as paid
        if payment.paid:
            return HTTPFound(location=self.request.route_path(
                'admin_single_payment', ref_code=payment.__name__))
        # Process form
        error = None
        if "submit" in self.request.POST:
            try:
                if not "amount" in self.request.POST or float(
                        self.request.POST['amount']) <= 0:
                    error = "An amount of money greater than zero must be specified"
                elif not "method" in self.request.POST or self.get_payment_method(
                        self.request.POST["method"]) == None:
                    error = "A valid payment method must be specified"
                elif not "year" in self.request.POST or not "month" in self.request.POST or not "day" in self.request.POST:
                    error = "A valid date must be entered"
                elif int(self.request.POST["year"]) < 2000 or int(
                        self.request.POST["month"]) < 1 or int(
                            self.request.POST["month"]) > 12 or int(
                                self.request.POST["day"]) < 1 or int(
                                    self.request.POST["day"]) > 31:
                    error = "A valid date must be entered"
                # elif not "status" in self.request.POST or self.request.POST["status"] not in ["cashed", "received"]: error = "You must select a valid payment status"
                if not error:
                    # Process this payment stage through
                    amount = floor(float(self.request.POST["amount"]) * 100.0)
                    method = self.request.POST["method"]
                    year = int(self.request.POST["year"])
                    month = int(self.request.POST["month"])
                    day = int(self.request.POST["day"])
                    transaction_date = datetime(year=year,
                                                month=month,
                                                day=day)
                    # - First check if the active stage is the current method
                    if active_stage.method != method:
                        # Update payment method to match that entered
                        active_stage = PaymentStage()
                        active_stage.__parent__ = payment
                        active_stage.method = method
                        active_stage.stage_owner = payment.owner.__name__
                        payment.history.append(active_stage)
                    # Update amount paid
                    active_stage.amount_paid = amount
                    active_stage.completed = True  # Doesn't mean 'fully paid' just something has happened at this stage

                    # Check for a complete sale
                    if active_stage.amount_remaining <= active_stage.amount_paid:
                        payment.completed_date = transaction_date
                        # Send payment confirmation email
                        emailer = GenericEmail(self.request)
                        emailer.compose_and_send(
                            "Ticket Payment Completed",
                            """Your ticket purchase (reference code %s) has now been confirmed as a result of your complete payment being received on %s and there is no 
                            further action required.""" %
                            (payment.ref_code,
                             payment.completed_date.strftime("%d/%m/%Y")),
                            payment.owner.__name__)
                    else:
                        # We need to open up a new stage with the same type as the previous
                        new_stage = PaymentStage()
                        new_stage.__parent__ = payment
                        new_stage.method = method
                        new_stage.stage_owner = payment.owner.__name__
                        payment.history.append(new_stage)
                        # Send partial payment confirmation email
                        emailer = GenericEmail(self.request)
                        emailer.compose_and_send(
                            "Partial Ticket Payment Received",
                            """A payment of %s for your tickets with reference code %s has now been received on %s. Please remember to complete the remainder of your
                            payment (%s) in order for your tickets to the event to be confirmed."""
                            % (self.format_price(amount), payment.ref_code,
                               transaction_date.strftime("%d/%m/%Y"),
                               self.format_price(payment.amount_remaining)),
                            payment.owner.__name__)
                    logging.info(
                        "%s: Created a new payment stage for payment %s for user %s"
                        % (self.user.username, payment.__name__,
                           payment.owner.username))
                    self.request.session.flash("Payment entered successfully",
                                               "info")
                    return HTTPFound(location=self.request.route_path(
                        "admin_single_payment", ref_code=payment.__name__))
            except Exception:
                logging.exception(
                    "%s: An error occurred adding a payment stage to payment %s"
                    % (self.user.username, payment.__name__))
                error = "An unknown error has occurred"
        return {
            "payment": payment,
            "date": datetime.now(),
            "active_stage": active_stage,
            "error": error
        }
コード例 #9
0
    def stripe_view(self):
        # Detect a payment alteration
        payment_id = None
        payment = None
        if "payment_id" in self.request.matchdict:
            payment_id = self.request.matchdict["payment_id"]
        # Check we can be here
        methods = PROP.getProperty(self.request, PROP.PAYMENT_METHODS)
        method = [
            x for x in methods if x.__name__ == "stripe" and x.enabled == True
        ]
        # - First check queue/active status
        if payment_id == None and Queue(self.request).timed_out():
            return HTTPFound(self.request.route_path("purchase_timeout"))
        # - Now details
        elif payment_id == None and not self.details_complete:
            self.request.session.flash(
                "You must complete all of your guest's details before continuing.",
                "error")
            return HTTPFound(location=self.request.route_path("order_details"))
        # - Check that the payment method is enabled?
        elif len(method) <= 0:
            self.request.session.flash(
                "There was an error with the payment method you selected, please try again.",
                "error")
            return HTTPFound(
                location=self.request.route_path("pay_for_tickets"))
        # - Now run some checks that this person actually should be able to pay this
        elif payment_id != None:
            if not payment_id in self.request.root.payments:
                self.request.session.flash(
                    "The requested payment does not exist.", "error")
                return HTTPFound(
                    location=self.request.route_path("user_profile"))
            else:
                payment = self.request.root.payments[payment_id]
                if payment.owner != self.user:
                    self.request.session.flash(
                        "The requested payment could not be found on your account.",
                        "error")
                    return HTTPFound(
                        location=self.request.route_path("user_profile"))
                elif payment.paid:
                    self.request.session.flash(
                        "The requested payment has already been completed, no need to alter the payment.",
                        "error")
                    return HTTPFound(
                        location=self.request.route_path("user_profile"))

        method = method[0]
        # Get some property values
        process_percentage = method.settings[
            PROP.PAYMENT_PROCESSING_PERCENTAGE].value
        process_fee = method.settings[PROP.PAYMENT_PROCESSING_FEE].value
        pub_api_key = method.settings[PROP.STRIPE_PUBLIC_KEY].value
        organisation_name = method.settings[PROP.ORGANISATION_NAME].value
        contact_email = method.settings[PROP.STRIPE_CONTACT_EMAIL].value

        # Ok, all good
        user = self.request.root.users[self.request.session["user_id"]]
        tickets = [x for x in user.tickets if x.payment == None]
        if payment_id == None and len(tickets) == 0:
            return HTTPFound(location=self.request.route_path("buy_tickets"))
        subtotal = 0
        for tick in tickets:
            subtotal += tick.total_cost

        # If we have submitted a Stripe purchase
        error = None
        if "stripeToken" in self.request.POST:
            stripe.api_key = method.settings[PROP.STRIPE_API_KEY].value
            token = self.request.POST["stripeToken"]
            if payment_id == None:
                # Create the holder Stripe payment first, but don't store
                payment = None
                try:
                    payment = Issuer(self.request.root).constructPayment(
                        user_id=self.request.session["user_id"]
                        # ref_code is auto generated
                    )
                    # Try running purchase
                    charge = None
                    try:
                        processing = int(
                            ceil(subtotal * process_percentage) + process_fee)
                        total = int(subtotal + processing)
                        # Create the Stripe charge
                        charge = stripe.Charge.create(
                            amount=total,
                            currency="gbp",
                            source=token,
                            description=organisation_name,
                        )
                        if "paid" in charge and charge["paid"] == True:
                            stage = PaymentStage()
                            stage.__parent__ = payment
                            stage.method = "stripe"
                            stage.method_properties["last_four"] = charge[
                                "source"]["last4"]
                            stage.method_properties["ref_code"] = charge["id"]
                            stage.amount_paid = total
                            stage.processing_charge = processing
                            stage.completed = True
                            stage.stage_owner = user.__name__
                            payment.history.append(stage)
                            payment.completed_date = datetime.now()
                            self.request.session[
                                "payment_id"] = payment.ref_code
                            logging.info(
                                self.user.username +
                                ": Stripe charge %s succeeded for payment %s" %
                                (charge["id"], payment.__name__))
                            return HTTPFound(location=self.request.route_path(
                                "pay_confirm"))
                        else:
                            if "failure_message" in charge and charge[
                                    "failure_message"] != None:
                                error = charge["failure_message"]
                                logging.error(self.user.username +
                                              ": Stripe refused charge: %s" %
                                              error)
                            else:
                                logging.error(self.user.username +
                                              ": Stripe refused charge")
                                error = "Charge was not accepted by Stripe"
                    except stripe.error.CardError, e:
                        logging.error(
                            self.user.username +
                            ": Stripe invalid card error occurred: %s" % e)
                        error = e
                    except stripe.error.InvalidRequestError, e:
                        logging.error(
                            self.user.username +
                            ": Stripe invalid card request occurred: %s" % e)
                        error = e
                    except stripe.error.RateLimitError, e:
                        logging.error(self.user.username +
                                      ": Stripe rate limit error: %s" % e)
                        error = "Too many people are trying to pay right now, please try again in a moment"
                    except stripe.error.AuthenticationError, e:
                        logging.error(self.user.username +
                                      ": Stripe authentication error: %s" % e)
                        error = "An authentication error occurred trying to connect to Stripe, please contact the committee"
コード例 #10
0
 else:
     # Try running payment alteration
     charge = None
     try:
         subtotal = payment.amount_remaining
         processing = int(
             ceil(subtotal * process_percentage) + process_fee)
         total = int(ceil(subtotal + processing))
         charge = stripe.Charge.create(
             amount=total,
             currency="gbp",
             source=token,
             description=organisation_name,
         )
         if "paid" in charge and charge["paid"] == True:
             new_stage = PaymentStage()
             new_stage.__parent__ = payment
             new_stage.method = "stripe"
             new_stage.method_properties["last_four"] = charge[
                 "source"]["last4"]
             new_stage.method_properties["ref_code"] = charge["id"]
             new_stage.amount_paid = total
             new_stage.processing_charge = processing
             new_stage.received = new_stage.cashed = True
             new_stage.completed = True
             new_stage.stage_owner = user.__name__
             payment.history.append(new_stage)
             payment.completed_date = datetime.now()
             logging.info(
                 self.user.username +
                 ": Stripe charge %s succeeded for payment %s" %
コード例 #11
0
 def allocate_tickets_view(self):
     if "submit" in self.request.POST:
         username = self.request.POST["username"].lower()
         if not username in self.request.root.users:
             self.request.session.flash(
                 "The user you specified does not exist, ticket allocation failed.",
                 "error")
             return {}
         user = self.request.root.users[username]
         num_tickets = int(float(self.request.POST["numtickets"]))
         if num_tickets <= 0:
             self.request.session.flash(
                 "You must specify a number of tickets to issue, allocation failed.",
                 "error")
         # Build the list of requested tickets and addons
         tick_types = {}
         for i in range(0, num_tickets):
             type_code = self.request.POST["ticket-%i-type" % i]
             addon_code = self.request.POST["ticket-%i-addon" % i]
             if type_code in tick_types:
                 tick_types[type_code]["count"] += 1
                 if addon_code in tick_types[type_code]["addons"]:
                     tick_types[type_code]["addons"][addon_code] += 1
                 else:
                     tick_types[type_code]["addons"][addon_code] = 1
             else:
                 tick_types[type_code] = {
                     "count": 1,
                     "addons": {
                         addon_code: 1
                     }
                 }
         # Check stock of tickets and addons
         for type_key in tick_types:
             number = tick_types[type_key]["count"]
             addons = tick_types[type_key]["addons"]
             if not type_key in self.request.root.ticket_pools:
                 self.request.session.flash(
                     "Invalid ticket type was specified.", "error")
                 return {}
             pool = self.request.root.ticket_pools[type_key]
             if len(pool.tickets) < number:
                 self.request.session.flash(
                     "There is not enough stock of '%s' to allocate the requested tickets."
                     % pool.tick_type.name, "error")
                 return {}
             #if not user.__parent__.__name__ in pool.groups:
             #    self.request.session.flash("The user is not permitted to have tickets of the type '%s'." % pool.tick_type.name, "error")
             #    return {}
             # Now check addons
             for addon_key in addons:
                 if addon_key == "none":
                     continue
                 if not addon_key in pool.tick_type.addons:
                     self.request.session.flash(
                         "Invalid addon type was specified.", "error")
                     return {}
                 addon = pool.tick_type.addons[addon_key]
                 num_addons = addons[addon_key]
                 if addon.remaining < num_addons:
                     self.request.session.flash(
                         "There is not enough stock of the addon '%s' to allocate the requested tickets."
                         % addon.name, "error")
                     return {}
         # Issue the tickets and attach all addons requested
         has_ticket = (user.tickets != None and len(user.tickets) > 0
                       )  # Whether we need to set a ticket to be theirs
         all_tickets = []
         for type_key in tick_types:
             number = tick_types[type_key]["count"]
             addons = tick_types[type_key]["addons"]
             pool = self.request.root.ticket_pools[type_key]
             for i in range(0, number):
                 ticket = pool.tickets[0]
                 user.tickets.append(ticket)
                 pool.tickets.remove(ticket)
                 ticket.__parent__ = user
                 ticket.owner = user
                 ticket.issue_date = datetime.now()
                 ticket.change_enabled = True  # Allow user to update guest details once
                 if not has_ticket:
                     ticket.guest_info = user.profile
                     has_ticket = True
                 else:
                     blank_profile = UserProfile()
                     blank_profile.__parent__ = ticket
                     ticket.guest_info = blank_profile
                 all_tickets.append(ticket)
                 # Attach an addon if available
                 for addon_key in addons:
                     if addon_key == "none" or addons[addon_key] <= 0:
                         continue
                     addon = pool.tick_type.addons[addon_key]
                     ticket.addons[addon.__name__] = addon
                     addon.allocated.append(ticket)
                     addons[addon_key] -= 1
                     break
         # Open a payment and attach all of the tickets into it
         gift = ("gift" in self.request.POST
                 and self.request.POST["gift"] == "gift")
         payment = Payment()
         payment.owner = user
         payment.__parent__ = user
         payment.opened_date = datetime.now()
         for ticket in all_tickets:
             ticket.payment = payment
             payment.tickets.append(ticket)
         if gift:
             new_stage = PaymentStage()
             new_stage.__parent__ = payment
             new_stage.method = "gifted"
             new_stage.amount_paid = int(payment.amount_remaining)
             new_stage.processing_charge = 0
             new_stage.received = new_stage.cashed = True
             new_stage.completed = True
             new_stage.stage_owner = user.__name__
             payment.history.append(new_stage)
             payment.completed_date = datetime.now()
         else:
             new_stage = PaymentStage()
             new_stage.__parent__ = payment
             new_stage.method = "cheque"
             new_stage.method_change = True
             new_stage.stage_owner = user.__name__
             payment.history.append(new_stage)
         # Attach the payment to the user
         user.payments.append(payment)
         user.total_tickets += len(payment.tickets)
         self.request.root.payments[payment.__name__] = payment
         # Send a information email
         if user.profile != None:
             emailer = GenericEmail(self.request)
             if gift:
                 emailer.compose_and_send(
                     "Tickets Allocated",
                     """This is to notify you that %i ticket(s) have been allocated to your account, they have been transferred as a gift and
                     hence no further action is required. If you want to get in touch, your ticket allocation reference is %s."""
                     % (len(payment.tickets), payment.ref_code),
                     payment.owner.__name__)
             else:
                 emailer.compose_and_send(
                     "Tickets Allocated",
                     """This is to notify you that %i ticket(s) have been allocated to your account. You are required to complete payment for
                     your tickets, currently they are set as a default of cheque payment, however you may change this by logging into your ticket
                     account. Your purchase reference is %s and your owed total is %s."""
                     % (len(payment.tickets), payment.ref_code,
                        self.format_price(payment.total)),
                     payment.owner.__name__)
         # Report all good
         self.request.session.flash("Ticket allocation successful!", "info")
         return HTTPFound(location=self.request.route_path("admin_tickets"))
     return {}
コード例 #12
0
    def setup_payments_test(self):
        counting = 0
        for key in self.request.root.ticket_pools:
            pool = self.request.root.ticket_pools[key]
            ticks_left = len(pool.tickets)
            while (ticks_left > 0):
                # Whilst tickets are left, purchase random quantities of tickets
                payment = Payment()
                payment.owner = self.user
                payment.__parent__ = self.user

                stage = PaymentStage()
                stage.__parent__ = payment
                stage.stage_owner = self.user.__name__
                stage.date = datetime.now()
                stage.method = [
                    "banktransfer", "cheque", "stripe", "collegebill"
                ][counting % 4]
                if stage.method == "stripe":
                    stage.method_properties["last_four"] = "1234"
                    stage.method_properties[
                        "ref_code"] = "TESTINGSTRIPEREFCODE"
                counting += 1
                payment.history.append(stage)

                # To issue
                total_to_issue = randint(1, 10)
                if total_to_issue > ticks_left:
                    total_to_issue = ticks_left
                ticks_left -= total_to_issue
                for i in range(0, total_to_issue):
                    tick = pool.tickets[0]
                    payment.tickets.append(tick)
                    self.user.tickets.append(tick)
                    pool.tickets.remove(tick)
                    tick.__parent__ = tick.owner = self.user
                    tick.guest_info = self.user.profile
                    tick.issue_date = datetime.now()
                    tick.payment = payment
                    self.user.total_tickets += 1

                # Enter a certain amount of payment
                stage.amount_paid = (counting % 3) * 0.5 * payment.total
                if stage.amount_paid > 0:
                    stage.received = stage.cashed = stage.completed = True

                # If the payment calculates it has been paid then add date
                if payment.paid:
                    payment.completed_date = datetime.now()
                elif stage.amount_paid > 0:
                    # Append a second blank payment stage on
                    stage_2 = PaymentStage()
                    stage_2.__parent__ = payment
                    stage_2.stage_owner = self.user.__name__
                    stage_2.date = datetime.now()
                    stage_2.method = ["banktransfer", "cheque",
                                      "collegebill"][counting % 3]
                    payment.history.append(stage_2)

                self.user.payments.append(payment)
                self.request.root.payments[payment.__name__] = payment
        self.request.session.flash("Test payments setup successfully!", "info")
        return HTTPFound(location=self.request.route_path('tests_page'))