Example #1
0
def order_pay():
    """
        Page to pay an order
    """
    from openstudio.os_customer import Customer
    coID = request.vars['coID']

    order = Order(coID)
    os_customer = Customer(auth.user.id)
    mollie_customer_id = None
    invoice_id = ''
    mollie_payment_id = ''

    # check if the order belongs to the currently logged in customer
    if not order.order.auth_customer_id == auth.user.id:
        session.flash = T("Unable to show order")
        redirect(URL('profile', 'index'))

    # Check if the order contains a class that's been fully booked in the main time
    if order.contains_class():
        cls = order.get_class_object_order_item()
        if cls.get_full() or cls.get_full_bookings_shop():
            redirect(
                URL("shop",
                    "class_full",
                    vars={
                        "clsID": cls.clsID,
                        "date": cls.date.strftime(DATE_FORMAT)
                    }))

    mollie = Client()
    mollie_api_key = get_sys_property('mollie_website_profile')
    mollie.set_api_key(mollie_api_key)

    amounts = order.get_amounts()

    # Go to Mollie for payment
    amount = format(amounts.TotalPriceVAT, '.2f')
    description = T('Order') + ' #' + str(coID)

    if os_customer.row.mollie_customer_id:
        # yep
        mollie_customer_id = os_customer.row.mollie_customer_id
        try:
            mollie_customer = mollie.customers.get(mollie_customer_id)
            # print "we've got one!"
            # print mollie_customer
            # print mollie.customers.all()
        except Exception as e:
            # print e.__class__.__name__
            # print str(e)
            # print 'customer id invalid, create new customer'
            if 'The customer id is invalid' in str(e):
                create_mollie_customer(auth.user.id, mollie)
                os_customer = Customer(auth.user.id)  # refresh
                mollie_customer_id = os_customer.row.mollie_customer_id
    else:
        create_mollie_customer(auth.user.id, mollie)
        os_customer = Customer(auth.user.id)  # refresh
        mollie_customer_id = os_customer.row.mollie_customer_id

    contains_subscription = order.contains_subscription()
    recurring_type = None
    if contains_subscription:
        mandates = os_customer.get_mollie_mandates()
        # set default recurring type, change to recurring if a valid mandate is found.
        recurring_type = 'first'
        if mandates['count'] > 0:
            # background payment
            valid_mandate = False
            for mandate in mandates['_embedded']['mandates']:
                if mandate['status'] == 'valid':
                    valid_mandate = True
                    break

            if valid_mandate:
                # Do a normal payment, probably an automatic payment failed somewhere in the process
                # and customer should pay manually now
                recurring_type = None

    try:
        redirect_url = 'https://' + request.env.http_host + '/shop/complete?coID=' + str(
            coID)

        payment = mollie.payments.create({
            'amount': {
                'currency': CURRENCY,
                'value': amount
            },
            'description':
            description,
            'sequenceType':
            recurring_type,
            'customerId':
            mollie_customer_id,
            'redirectUrl':
            redirect_url,
            'webhookUrl':
            'https://' + request.env.http_host + '/mollie/webhook',
            'metadata': {
                'customers_orders_id': coID
            }
        })

        db.customers_orders_mollie_payment_ids.insert(
            customers_orders_id=coID,
            mollie_payment_id=payment['id'],
            RecurringType=recurring_type)

        # Send the customer off to complete the payment.
        redirect(payment.checkout_url)

    except MollieError as e:
        return 'API call failed: ' + e.message
Example #2
0
def invoice_pay():
    """
        Link to mollie payment page from invoice payment
    """
    from openstudio.os_customer import Customer

    #response.title = T("Pay invoice")
    iID = request.vars['iID']

    invoice = Invoice(iID)
    invoice_amounts = invoice.get_amounts()

    if not invoice.get_linked_customer_id() == auth.user.id:
        return 'Not authorized'

    mollie = Mollie.API.Client()
    mollie_api_key = get_sys_property('mollie_website_profile')
    mollie.setApiKey(mollie_api_key)

    description = invoice.invoice.Description + ' - ' + invoice.invoice.InvoiceID
    recurring_type = None
    mollie_customer_id = None

    # Subscription invoice?
    if invoice.get_linked_customer_subscription_id():
        # subscription invoice
        # customer = Customer(auth.user.id)
        # mollie_customer_id = customer.row.mollie_customer_id
        # check if we have a mollie customer id
        os_customer = Customer(auth.user.id)
        if os_customer.row.mollie_customer_id:
            # yep
            mollie_customer_id = os_customer.row.mollie_customer_id
            try:
                mollie_customer = mollie.customers.get(mollie_customer_id)
                # print "we've got one!"
                # print mollie_customer
                # print mollie.customers.all()
            except Exception as e:
                # print e.__class__.__name__
                # print str(e)
                # print 'customer id invalid, create new customer'
                if 'The customer id is invalid' in str(e):
                    create_mollie_customer(auth.user.id, mollie)
                    os_customer = Customer(auth.user.id) # refresh
        else:
            create_mollie_customer(auth.user.id, mollie)
            os_customer = Customer(auth.user.id) # refresh

        mandates = os_customer.get_mollie_mandates()
        # set default recurring type, change to recurring if a valid mandate is found.
        recurring_type = 'first'
        if mandates['count'] > 0:
            # background payment
            valid_mandate = False
            for mandate in mandates:
                if mandate['status'] == 'valid':
                    valid_mandate = True
                    break

            if valid_mandate:
                # Do a normal payment, probably an automatic payment failed somewhere in the process
                # and customer should pay manually now
                recurring_type = None

    # Do a regular payment or first recurring payment
    try:
        webhook_url = 'https://' + request.env.http_host + '/mollie/webhook'
        payment = mollie.payments.create({
            'amount':      invoice_amounts.TotalPriceVAT,
            'description': description,
            'recurringType': recurring_type,
            'customerId': mollie_customer_id,
            'redirectUrl': 'https://' + request.env.http_host + '/shop/complete?iID=' + unicode(iID),
            'webhookUrl': webhook_url,
            'metadata': {
                'invoice_id': invoice.invoice.id,
                'customers_orders_id': 'invoice' # This lets the webhook function know it's dealing with an invoice
            }
        })

        db.invoices_mollie_payment_ids.insert(
            invoices_id=iID,
            mollie_payment_id=payment['id'],
            RecurringType=recurring_type,
            WebhookURL=webhook_url
        )

        # Send the customer off to complete the payment.
        redirect(payment.getPaymentUrl())

    except Mollie.API.Error as e:
        return 'API call failed: ' + e.message
def task_mollie_subscription_invoices_and_payments():
    """
        Create subscription invoices for subscriptions with payment method 100
        Collect payment for these invoices
    """
    def send_mail_failed(cuID):
        """
            When a recurring payment fails, mail customer with request to pay manually
        """
        os_mail = OsMail()
        msgID = os_mail.render_email_template('payment_recurring_failed')
        os_mail.send_and_archive(msgID, cuID)

    from openstudio.os_customer import Customer

    # hostname
    sys_hostname = get_sys_property('sys_hostname')
    # set up Mollie
    mollie = Client()
    mollie_api_key = get_sys_property('mollie_website_profile')
    mollie.set_api_key(mollie_api_key)
    # set dates
    today = datetime.date.today()
    firstdaythismonth = datetime.date(today.year, today.month, 1)
    lastdaythismonth = get_last_day_month(firstdaythismonth)

    # call some function to do stuff

    # find all active subscriptions with payment method 100 (Mollie)
    query = (db.customers_subscriptions.payment_methods_id == 100) & \
            (db.customers_subscriptions.Startdate <= lastdaythismonth) & \
            ((db.customers_subscriptions.Enddate >= firstdaythismonth) |
             (db.customers_subscriptions.Enddate == None))
    rows = db(query).select(db.customers_subscriptions.ALL)

    success = 0
    failed = 0

    # create invoices
    for i, row in enumerate(rows):
        cs = CustomerSubscription(row.id)
        # This function returns the invoice id if it already exists
        iID = cs.create_invoice_for_month(TODAY_LOCAL.year, TODAY_LOCAL.month)

        #print 'invoice created'
        #print iID

        # Do we have an invoice?
        if not iID:
            continue

        invoice = Invoice(iID)
        # Only do something if the invoice status is sent
        if not invoice.invoice.Status == 'sent':
            continue

        # We're good, continue processing
        invoice_amounts = invoice.get_amounts()
        #print invoice.invoice.InvoiceID
        description = invoice.invoice.Description + ' - ' + invoice.invoice.InvoiceID
        db.commit()

        #create recurring payments using mandates
        #subscription invoice
        customer = Customer(row.auth_customer_id)
        mollie_customer_id = customer.row.mollie_customer_id
        mandates = customer.get_mollie_mandates()
        valid_mandate = False
        # set default recurring type, change to recurring if a valid mandate is found.
        if mandates['count'] > 0:
            # background payment
            for mandate in mandates['_embedded']['mandates']:
                if mandate['status'] == 'valid':
                    valid_mandate = True
                    break

            if valid_mandate:
                # Create recurring payment
                try:
                    webhook_url = URL('mollie',
                                      'webhook',
                                      scheme='https',
                                      host=sys_hostname)
                    payment = mollie.payments.create({
                        'amount': {
                            'currency': CURRENCY,
                            'value': str(invoice_amounts.TotalPriceVAT)
                        },
                        'customerId': mollie_customer_id,
                        'sequenceType': 'recurring',  # important
                        'description': description,
                        'webhookUrl': webhook_url,
                        'metadata': {
                            'invoice_id': invoice.invoice.id,
                            'customers_orders_id':
                            'invoice'  # This lets the webhook function know it's dealing with an invoice
                        }
                    })

                    # link invoice to mollie_payment_id
                    db.invoices_mollie_payment_ids.insert(
                        invoices_id=invoice.invoice.id,
                        mollie_payment_id=payment['id'],
                        RecurringType='recurring',
                        WebhookURL=webhook_url)

                    success += 1

                except MollieError as e:
                    print(e)
                    # send mail to ask customer to pay manually
                    send_mail_failed(cs.auth_customer_id)

                    failed += 1
                    # return error
                    # return 'API call failed: ' + e.message
        else:
            # send mail to ask customer to pay manually
            send_mail_failed(cs.auth_customer_id)

            failed += 1

    # For scheduled tasks, db has to be committed manually
    db.commit()

    return T("Payments collected") + ': ' + str(success) + '<br>' + \
        T("Payments failed to collect") + ': ' + str(failed)