import gocardless_pro import braintree import logging from django.conf import settings payment_providers = settings.PAYMENT_PROVIDERS logger = logging.getLogger(__name__) # import paypalrestsdk as paypal PROVIDER_ID = {'gocardless': 1, 'braintree': 2} PROVIDER_NAME = {1: 'gocardless', 2: 'braintree'} def select_provider(type): if type == "gocardless": return gocardless_provider() if type == "braintree": return braintree_provider() # if type == "paypal": return paypal_provider() logger.exception('[scaffold] - "No Provider for ' + type) assert 0, "No Provider for " + type class gocardless_provider: """ gocardless test account details 20-00-00, 55779911 """ form_remote = True client = None def __init__(self): # gocardless are changing there api, not sure if we can switch yet self.client = gocardless_pro.Client( access_token=payment_providers['gocardless']['credentials']['access_token'], environment=payment_providers['gocardless']['environment']) def fetch_customers(self): """Fetch list of customers payments""" for customer in self.client.customers.list().records: for payment in self.client.payments.list(params={"customer": customer.id}).records: yield { 'user_reference': customer.id, 'email': customer.email, 'status': payment.status, 'payment_id': payment.links.subscription, 'payment_type': 'subscription' if payment.links.subscription else 'payment', 'payment_date': payment.charge_date, 'amount': payment.amount } def fetch_subscriptions(self): # for paying_member in self.client.mandates.list().records: for paying_member in self.client.subscriptions.list().records: mandate = self.client.mandates.get(paying_member.links.mandate) customer = self.client.customers.get(mandate.links.customer) # TODO get the last couple of months not all time payments payments = self.client.payments.list(params={"customer": customer.id}).records last_payments = None if len(payments): last_payment = payments[0].charge_date # gocardless does not have a reference so we use the id instead yield { 'status': paying_member.status, 'email': customer.email, 'start_date': paying_member.created_at, 'reference': paying_member.id, 'last_payment': last_payment, 'amount': paying_member.amount * 0.01} def get_redirect_url(self): return payment_providers['gocardless']['redirect_url'] def get_token(self): return 'N/A' def cancel_subscription(self, user, reference): try: subscription = self.client.subscriptions.get(reference) response = self.client.subscriptions.cancel(reference) except gocardless_pro.errors.InvalidApiUsageError as e: if e.code is 404: logger.info('Cancel subscription failed user not found %s %s' % (e.code, e)) return { 'success': False } except Exception as e: logger.info('Cancel subscription failed unknown reason code %s %s' % (e.code, e)) return { 'success': False } return { 'amount': subscription.amount, 'start_date': subscription.created_at, 'reference': subscription.id, 'success': True if response.status == 'cancelled' else False } def create_subscription(self, user, session, amount, name, redirect_success, redirect_failure, interval_unit='monthly', interval_length='1'): return self.client.redirect_flows.create(params={ "description": name, "session_token": session, "success_redirect_url": redirect_success, "prefilled_customer": { "given_name": user.first_name, "family_name": user.last_name, "email": user.email } }) def confirm_subscription(self, membership, session, provider_response, name, interval_unit='monthly', interval_length='1'): r = provider_response.get('redirect_flow_id') response = self.client.redirect_flows.complete(r, params={'session_token': session}) user_id = response.links.customer mandate_id = response.links.mandate user = self.client.customers.get(response.links.customer) mandate = self.client.mandates.get(response.links.mandate) # for some reason go cardless is in pence, so 20.00 needs to be sent as 2000 # what genious decided that was a good idea, now looks like i am charging £2000 :p # the return is the same so you need to convert on send and receive subscription_response = self.client.subscriptions.create( params={ 'amount': str(membership.payment).replace('.', ''), 'currency': 'GBP', 'interval_unit': interval_unit, 'name': name, # 'metadata': {'reference': }, 'links': {'mandate': mandate_id} }) return { 'amount': membership.payment, 'email': user.email, 'start_date': subscription_response.created_at, 'reference': subscription_response.id, 'status': subscription_response.status, 'success': subscription_response.api_response.status_code } class braintree_provider: form_remote = False def __init__(self): braintree.Configuration.configure( environment=braintree.Environment.Sandbox, merchant_id=payment_providers['braintree']['credentials']['merchant_id'], public_key=payment_providers['braintree']['credentials']['public_key'], private_key=payment_providers['braintree']['credentials']['private_key']) def get_token(self): return braintree.ClientToken.generate() def create_subscription(self, amount, name, redirect_success, redirect_failure, interval_unit='month', interval_length='1'): result = braintree.Customer.create({ "first_name": "test", "last_name": "user", "payment_method_nonce": nonce_from_the_client }) return braintree.Subscription.create({ "payment_method_token": "the_token", "plan_id": "membership", "merchant_account_id": "gbp_sandbox" #"price": "20.00" #'name': name }) def confirm_subscription(self, args): if self.provider == 'gocardless': response = gocardless_pro.client.confirm_resource(args) subscription = gocardless_pro.client.subscription(args.get('resource_id')) return { 'amount': subscription.amount, 'start_date': subscription.created_at, 'reference': subscription.id } def fetch_subscriptions(self): for paying_member in braintree.Subscription.search(braintree.SubscriptionSearch.status == braintree.Subscription.Status.Active): user=paying_member.user() yield { 'status': paying_member.status, 'email': user.email, 'start_date': paying_member.created_at, 'reference': paying_member.reference, 'amount': paying_member.amount}