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)