コード例 #1
0
ファイル: views.py プロジェクト: ryanam26/DonkiesAPI
    def post(self, request, *args, **kwargs):
        ser = self.serializer_class(request.user, data=request.data)

        if ser.is_valid():
            user = ser.save()

            request_body = {
                'firstName': user.first_name,
                'lastName': user.last_name,
                'email': user.email,
                'phone': user.phone,
            }

            dw = DwollaApi()

            try:
                id = dw.create_customer(request_body)
            except Exception as e:
                return Response(e, status=400)

            Customer = apps.get_model('bank', 'Customer')

            customer = Customer.objects.create(user=user)
            customer.dwolla_id = id
            customer.save()

            user.signup()
            return Response(sers.UserSerializer(user).data, status=200)

        return Response(ser.errors, status=400)
コード例 #2
0
    def update_dwolla_transfer(self, id, is_test=False):
        """
        If less than 15 minutes from last check, do nothing.
        """
        tds = self.model.objects.get(id=id)
        if not tds.can_update:
            return

        if not is_test:
            now = timezone.now()
            if tds.updated_at + datetime.timedelta(minutes=15) > now:
                return

        dw = DwollaApi()
        d = dw.get_transfer(tds.dwolla_id)
        if d is None:
            logger.error('Can not retrieve transfer: {}'.format(tds.dwolla_id))
            return

        status = d['status']

        if status == self.model.PENDING:
            tds.updated_at = timezone.now()

        elif status == self.model.PROCESSED:
            tds.is_sent = True
            tds.updated_at = timezone.now()
            tds.sent_at = timezone.now()

        else:
            tds.updated_at = timezone.now()
            tds.is_failed = True

        tds.status = status
        tds.save()
コード例 #3
0
ファイル: tasks.py プロジェクト: ryanam26/DonkiesAPI
def process_sandbox_transfers():
    """
    For sandbox transfers.
    They are not processed by default.
    """
    dw = DwollaApi()
    dw.press_sandbox_button()
コード例 #4
0
ファイル: views.py プロジェクト: ryanam26/DonkiesAPI
 def post(self, request, **kwargs):
     customer_id = kwargs['dwolla_customer_id']
     d = DwollaApi()
     token = d.get_iav_token(customer_id)
     if token is None:
         return Response({'message': 'Server error.'}, status=400)
     return Response({'token': token})
コード例 #5
0
ファイル: funding_source.py プロジェクト: ryanam26/DonkiesAPI
 def update_micro_deposits(self, id):
     """
     Updates status of micro-deposits verification.
     """
     fs = self.model.objects.get(id=id)
     if fs.md_status is not None and fs.md_status != self.model.PROCESSED:
         dw = DwollaApi()
         d = dw.get_micro_deposits(fs.dwolla_id)
         fs.md_status = d['status']
         fs.md_created_at = d['created']
         fs.save()
コード例 #6
0
def get_or_create_customer():
    """
    Get or create dwolla customer.
    """
    dw = DwollaApi()
    customer = dw.get_customer_by_email(TEST_EMAIL)
    if customer is not None:
        return customer
    customer = CustomerFactory.get_customer(email=TEST_EMAIL)
    Customer.objects.create_dwolla_customer(customer.id)
    customer.refresh_from_db()
    return dw.get_customer(customer.dwolla_id)
コード例 #7
0
ファイル: customer.py プロジェクト: ryanam26/DonkiesAPI
    def update_customers(self):
        """
        Currently method updates only status.
        """
        dw = DwollaApi()
        for d in dw.get_customers():
            try:
                c = self.model.objects.get(dwolla_id=d['id'])
            except self.model.DoesNotExist:
                continue

            if c.status != d['status']:
                c.status = d['status']
                c.save()
コード例 #8
0
ファイル: customer.py プロジェクト: ryanam26/DonkiesAPI
 def initiate_dwolla_customer(self, id):
     """
     Get data of created, but not initiated yet customer.
     """
     c = self.model.objects.get(id=id)
     if c.dwolla_id is not None and c.created_at is None\
             and not c.user.is_admin:
         dw = DwollaApi()
         d = dw.get_customer(c.dwolla_id)
         if d is not None:
             assert d['id'] == c.dwolla_id
             c.dwolla_type = d['type']
             c.status = d['status']
             c.created_at = d['created']
             c.save()
コード例 #9
0
ファイル: serializers.py プロジェクト: ryanam26/DonkiesAPI
    def save(self):

        data = self.validated_data

        request_body = {
            'firstName': data['first_name'],
            'lastName': data['last_name'],
            'email': data['email'],
            'type': data['type'],
            'address1': data['address1'],
            'city': data['city'],
            'state': data['state'],
            'postalCode': data['postal_code'],
            'dateOfBirth': str(data['date_of_birth']),
            'ssn': data['ssn'],
            'phone': data['phone'],
        }

        dw = DwollaApi()

        try:
            id = dw.create_customer(request_body)
        except Exception as e:
            raise Exception(e)

        if id is not None:
            user = User.objects.create_user(data['email'], data['password'])
            user.first_name = data['first_name']
            user.last_name = data['last_name']
            user.address1 = data['address1']
            user.postal_code = data['postal_code']
            user.city = data['city']
            user.state = data['state']
            user.date_of_birth = data['date_of_birth']
            user.phone = data['phone']

            user.save()

            Customer = apps.get_model('bank', 'Customer')
            customer = Customer.objects.create(user=user)
            customer.dwolla_id = id

            customer.save()

            # Post save operations, send email e.t.c
            user.signup()

        return None
コード例 #10
0
ファイル: funding_source.py プロジェクト: ryanam26/DonkiesAPI
 def init_dwolla_funding_source(self, id):
     """
     Currently not used.
     Init funding source in Dwolla from manually
     created account.
     """
     fs = self.model.objects.get(id=id)
     if fs.dwolla_id is not None and fs.created_at is None:
         dw = DwollaApi()
         d = dw.get_funding_source(fs.dwolla_id)
         fs.dwolla_id = d['id']
         fs.created_at = d['created']
         fs.status = d['status']
         fs.is_removed = d['removed']
         fs.typeb = d['type']
         fs.save()
コード例 #11
0
ファイル: tasks.py プロジェクト: ryanam26/DonkiesAPI
def transfer_money(amount, funding_source):
    TransferCalculation = apps.get_model('finance', 'TransferCalculation')
    FundingSource = apps.get_model('finance', 'FundingSource')

    dw = DwollaApi()

    destination = settings.DWOLLA_TEMP_BUSINESS_ACCOUNT

    request_body = {
        '_links': {
            'source': {
                'href': funding_source
            },
            'destination': {
                'href': destination
            }
        },
        'amount': {
            'currency': 'USD',
            'value': amount
        }
    }
    try:
        transfer = dw.token.post('transfers', request_body)
        print(transfer.headers['location'])
        trans_calc = TransferCalculation.objects.get(
            user=FundingSource.objects.get(
                funding_sources_url=funding_source).user)
        trans_calc.applied_funds = Decimal(amount)
        trans_calc.save()
    except Exception as error:
        logger.info(error)
コード例 #12
0
ファイル: funding_source.py プロジェクト: ryanam26/DonkiesAPI
    def create_funding_source_iav(self, account_id, dwolla_id, test_dic=None):
        """
        User creates funding source via dwolla.js script in iframe
        using username and password on frontend.
        At first the funding source is created in Dwolla,
        then calling this function from API funding source created in database.

        test_dic - used for tests not calling Dwolla API.

        If Dwolla API fail, we can run this method later.
        FundingSourceIAVLog will contain failed data.

        If this is first FundingSource, set it as active funding source
        for user.
        """
        Account = apps.get_model('finance', 'Account')
        FundingSourceIAVLog = apps.get_model('bank', 'FundingSourceIAVLog')

        fs_log = FundingSourceIAVLog.objects.create(account_id, dwolla_id)
        account = Account.objects.get(id=account_id)

        if test_dic:
            d = test_dic
        else:
            dw = DwollaApi()
            d = dw.get_funding_source(dwolla_id)

        fs = self.model(account=account)
        fs.dwolla_id = d['id']
        fs.created_at = d['created']
        fs.status = d['status']
        fs.is_removed = d['removed']
        fs.typeb = d['type']
        fs.name = d['name']
        fs.verification_type = self.model.IAV
        fs.save()

        fs_log.is_processed = True
        fs_log.save()

        count = self.model.objects.filter(
            account__item__user=account.item.user).count()
        if count == 1:
            Account.objects.set_funding_source(account.id)

        return fs
コード例 #13
0
ファイル: customer.py プロジェクト: ryanam26/DonkiesAPI
    def create_dwolla_customer(self, id):
        """
        Celery task POST call to dwolla to create customer.
        """
        customer = self.model.objects.get(id=id)
        if customer.dwolla_id is not None\
                or not customer.user.is_profile_completed\
                or customer.user.is_admin:
            return

        dic = self.get_customer_data_for_create_request(customer)

        dw = DwollaApi()
        id = dw.create_customer(dic)
        if id is not None:
            customer.dwolla_id = id
            customer.save()
コード例 #14
0
    def initiate_dwolla_transfer(self, id):
        tds = self.model.objects.get(id=id)
        if not tds.can_initiate:
            return

        fs = tds.account.funding_source

        dw = DwollaApi()
        id = dw.initiate_transfer(fs.dwolla_id, str(tds.amount))
        if id is None:
            logger.error('Can not initiate transfer: {}'.format(tds.dwolla_id))
            return

        tds.dwolla_id = id
        tds.is_initiated = True
        tds.initiated_at = timezone.now()
        tds.updated_at = timezone.now()
        tds.save()
コード例 #15
0
    def update_dwolla_failure_code(self, id):
        tds = self.model.objects.get(id=id)
        if not tds.is_failed or tds.failure_code is not None:
            return

        dw = DwollaApi()
        code = dw.get_transfer_failure_code(tds.dwolla_id)

        if code is None:
            logger.error('Can not get failure code for: {}'.format(
                tds.dwolla_id))
            return

        tds.failure_code = code
        tds.updated_at = timezone.now()
        tds.save()

        if code != 'R01':
            self.move_failed(tds.id)
コード例 #16
0
ファイル: funding_source.py プロジェクト: ryanam26/DonkiesAPI
    def create_dwolla_funding_source(self, id):
        """
        Currently not used.
        Create funding source in Dwolla from manually
        created account.
        """
        fs = self.model.objects.get(id=id)
        if fs.dwolla_id is not None:
            return

        data = {
            'routingNumber': fs.routing_number,
            'accountNumber': fs.account_number,
            'type': fs.type,
            'name': fs.name
        }
        dw = DwollaApi()
        id = dw.create_funding_source(fs.customer.dwolla_id, data)
        if id is not None:
            fs.dwolla_id = id
            fs.save()
コード例 #17
0
ファイル: tasks.py プロジェクト: ryanam26/DonkiesAPI
def take_monthly_fee():
    dwa = DwollaApi()
    root = dwa.token.get(url='/')
    dwolla_account = root.body['_links']['account']['href']
    Customer = apps.get_model('bank', 'Customer')
    account_token = dwa.client.Token(access_token=dwa.token.access_token,
                                     refresh_token=dwa.token.access_token)
    for customer in Customer.objects.exclude(user__is_paused=True).exclude(
            user__is_closed_account=True).exclude(user__active_days=30):
        customer.user.active_days += 1
        customer.user.save()
    for customer in Customer.objects.exclude(user__is_paused=True).exclude(
            user__is_closed_account=True).filter(user__active_days=30):
        result = dwa.get_funding_sources(customer.dwolla_id)[0]
        customer_source_url = result['_links']['self']['href']
        customer_balance_id = result[0]['id']
        customer_balance = dwa.get_funding_source_balance(
            customer_balance_id)['balance']['value']
        if float(customer_balance) < 1.99:
            request_body = {
                '_links': {
                    'source': {
                        'href': customer_source_url
                    },
                    'destination': {
                        'href': dwolla_account
                    }
                },
                'amount': {
                    'currency': 'USD',
                    'value': '1.99'
                }
            }
            transfer = account_token.post('transfers', request_body)
            customer.user.active_days = 0
            customer.user.save()
        else:
            logger.info("Not enough money to fee")
        logger.info("Got fee from customer{}".format(customer.dwolla_id))
コード例 #18
0
ファイル: views.py プロジェクト: ryanam26/DonkiesAPI
    def post(self, request, *args, **kwargs):
        ser = self.serializer_class(request.user, data=request.data)

        if ser.is_valid():
            user = ser.save()

            request_body = {
                'firstName': user.first_name,
                'lastName': user.last_name,
                'email': user.email,
                'type': user.type,
                'address1': user.address1,
                'city': user.city,
                'state': user.state,
                'postalCode': user.postal_code,
                'dateOfBirth': str(user.date_of_birth),
                'ssn': user.ssn,
                'phone': user.phone,
            }

            dw = DwollaApi()

            try:
                id = dw.create_customer(request_body)
            except Exception as e:
                return Response(e, status=400)

            Customer = apps.get_model('bank', 'Customer')

            customer = Customer.objects.create(user=user)
            customer.dwolla_id = id
            customer.save()

            user.signup()

            return Response(ser.data, status=200)

        return Response(ser.errors, status=400)
コード例 #19
0
class TestTransferDonkiesDwolla(base.Mixin):
    """
    Tests that use Dwolla API.
    Run from US server.
    """
    def setup(self):
        self.dw = DwollaApi()

    @pytest.mark.django_db
    def notest01(self, dwolla):
        """
        Do not run each time, because too many customers
        will be created in Dwolla.

        Test create customer.
        """
        customer = CustomerFactory.get_customer()
        Customer.objects.create_dwolla_customer(customer.id)
        customer.refresh_from_db()
        assert customer.dwolla_id is not None

    @pytest.mark.django_db
    def notest02(self):
        """
        Do not run each time, because too many customers
        will be created in Dwolla.

        Test create and initiate customer.
        """
        customer = CustomerFactory.get_customer()
        Customer.objects.create_dwolla_customer(customer.id)
        customer.refresh_from_db()
        assert customer.dwolla_id is not None

        Customer.objects.initiate_dwolla_customer(customer.id)
        customer.refresh_from_db()
        assert customer.dwolla_type is not None
        assert customer.created_at is not None
        assert customer.status is not None

    @pytest.mark.django_db
    def notest03(self):
        """
        Do not run each time, because too many customers
        will be created in Dwolla.

        Test create customer, then create the same customer again.
        Instead of error, should get the same customer.
        """
        customer = CustomerFactory.get_customer()
        data = Customer.objects.get_customer_data_for_create_request(customer)
        c1 = self.dw.create_customer(data)
        c2 = self.dw.create_customer(data)
        assert c1 == c2

    @pytest.mark.django_db
    def test04(self, dwolla):
        """
        Test initiate transfer.
        """
        funding_source = dwolla['funding_source']

        e = Emulator(num_debit_accounts=1)
        e.init()
        e.make_transfer_prepare_condition()

        Emulator.run_transfer_prepare()
        Emulator.run_transfer_donkies_prepare()

        # Exchange dwolla_id for mock debit account with
        # real funding source dwolla_id
        account = e.debit_accounts[0]
        fs = account.funding_source
        fs.dwolla_id = funding_source['id']
        fs.save()

        tds = TransferDonkies.objects.first()
        tds.save()

        TransferDonkies.objects.initiate_dwolla_transfer(tds.id)
        tds.refresh_from_db()

        assert tds.is_initiated is True
        assert tds.initiated_at is not None
        assert tds.updated_at is not None
        assert tds.dwolla_id is not None

    @pytest.mark.django_db
    def test05(self, dwolla):
        """
        Test initiate and update transfer with success status.
        """
        funding_source = dwolla['funding_source']

        e = Emulator(num_debit_accounts=1)
        e.init()
        e.make_transfer_prepare_condition()

        Emulator.run_transfer_prepare()
        Emulator.run_transfer_donkies_prepare()

        # Exchange dwolla_id for mock debit account with
        # real funding source dwolla_id from API
        account = e.debit_accounts[0]
        fs = account.funding_source
        fs.dwolla_id = funding_source['id']
        fs.save()

        tds = TransferDonkies.objects.first()
        tds.save()

        TransferDonkies.objects.initiate_dwolla_transfer(tds.id)

        for _ in range(20):
            TransferDonkies.objects.update_dwolla_transfer(
                tds.id, is_test=True)
            tds.refresh_from_db()

            print('Transfer status: ', tds.status)

            # Process sandbox transfers
            self.dw.press_sandbox_button()

            if tds.status and tds.status != TransferDonkies.PENDING:
                break
            time.sleep(5)

        assert tds.status == TransferDonkies.PROCESSED
        assert tds.is_sent is True
        assert tds.sent_at is not None
        assert tds.updated_at is not None

    @pytest.mark.django_db
    def test06(self, dwolla):
        """
        Should be last test as it changes fixture's funding_source to R01.

        Test initiate and update transfer with insufficient funds.
        1) Should get failed status.
        2) Update failure_code.
        3) Failure code should be "R01"
        """
        customer = dwolla['customer']
        funding_source = get_or_create_funding_source(customer, name='R01')

        e = Emulator(num_debit_accounts=1)
        e.init()
        e.make_transfer_prepare_condition()

        Emulator.run_transfer_prepare()
        Emulator.run_transfer_donkies_prepare()

        # Exchange dwolla_id for mock debit account with
        # real funding source dwolla_id from API
        account = e.debit_accounts[0]
        fs = account.funding_source
        fs.dwolla_id = funding_source['id']
        fs.save()

        tds = TransferDonkies.objects.first()
        tds.save()

        TransferDonkies.objects.initiate_dwolla_transfer(tds.id)

        for _ in range(20):
            TransferDonkies.objects.update_dwolla_transfer(
                tds.id, is_test=True)
            tds.refresh_from_db()

            print('Transfer status: ', tds.status)

            # Process sandbox transfers
            self.dw.press_sandbox_button()

            if tds.status and tds.status != TransferDonkies.PENDING:
                break
            time.sleep(5)

        assert tds.status == TransferDonkies.FAILED
        assert tds.is_failed is True
        assert tds.failure_code is None

        TransferDonkies.objects.update_dwolla_failure_code(tds.id)
        tds.refresh_from_db()
        assert tds.failure_code == 'R01'
コード例 #20
0
def get_or_create_funding_source(customer, name='My Bank'):
    """
    Returns funding source (bank) or creates verified
    funding source (bank) in Dwolla for test customer.

    name is used to simulate different test cases.

    name = "R01" Insufficient Funds:
             failing from the source bank account.

    name = "R01-late" Simulate funds failing from the
            source bank account post-settlement.
            Must click "Process bank transfers" twice.
    """
    dw = DwollaApi()
    for fs in dw.get_funding_sources(customer['id']):
        if fs['status'] == 'verified' and fs['type'] == 'bank':
            # Set funding source's name.
            dw.edit_funding_source_name(fs['id'], name)
            return fs

    data = {
        'routingNumber': '222222226',
        'accountNumber': '123456789',
        'type': 'savings',
        'name': name
    }
    print('Creating funding source --------')
    id = dw.create_funding_source(customer['id'], data)
    fs = dw.get_funding_source(id)
    print(fs)

    print('Initiating micro-deposits -------')
    res = dw.initiate_micro_deposits(fs['id'])
    print(res)

    print('Get status of micro-deposits -------')
    res = dw.get_micro_deposits(fs['id'])

    print('Verifying funding source -------')
    res = dw.verify_micro_deposits(
        fs['id'], '0.05', '0.05')
    print(res)

    print('Checking the status of funding source -------')
    fs = dw.get_funding_source(id)
    print(fs['status'])
    return fs
コード例 #21
0
ファイル: funding_source.py プロジェクト: ryanam26/DonkiesAPI
 def init_micro_deposits(self, id):
     fs = self.model.objects.get(id=id)
     if fs.md_status is None:
         dw = DwollaApi()
         dw.init_micro_deposits(fs.dwolla_id)
コード例 #22
0
 def setup(self):
     self.dw = DwollaApi()