예제 #1
0
    def test_pay_to_alias(self):
        """ Test the logic of making a payment to an alias.
        """
        # Create a source account and give it some funds.

        src_user = self.create_random_user()

        src_account = Account()
        src_account.user_id = src_user.user_id
        src_account.suffix  = "source account"
        src_account.save()

        transaction = Transaction()
        transaction.account = src_account
        transaction.timestamp = datetime.datetime.now()
        transaction.type      = Transaction.TYPE_DEPOSIT
        transaction.amount    = decimal.Decimal("100.00")
        transaction.save()

        # Create a user to make a payment to, and set up an alias for that
        # user.  Note that we store the user ID and alias in global variables,
        # so our testing alias resolver can resolve the alias.

        dst_user = self.create_random_user()

        global _test_alias_id, _test_user_id

        _test_user_id  = dst_user.user_id
        _test_alias_id = utils.random_letters()

        # Open a session as the source user, so we can make a payment from that
        # account.

        err_msg = self.open_session(src_user.user_id, src_user.password)
        self.assertEqual(err_msg, None)

        # Define our source and destination accounts, using the alias for the
        # destination account.

        src_account_id = {'user_id' : src_user.user_id,
                          'suffix'  : "source account"}

        dst_account_id = {'user_alias' : _test_alias_id}

        # Make a payment from the source to the destination account.

        resolver_path = "tahua.tests.test_payments.test_alias_resolver"
        with self.settings(TAHUA_USER_ALIAS_RESOLVER=resolver_path):
            success,response = self.call_api("tahua.api.pay.pay",
                                             include_session_key=True,
                                             from_account_id=src_account_id,
                                             to_account_id=dst_account_id,
                                             amount="10.00",
                                             pin_number=src_user.pin_number,
                                             meta_data={})
        if not success: self.fail(response)

        # Finally, check that the payment went to the right account.

        account_id = {'user_id' : dst_user.user_id}

        balance = account_helper.get_account_balance(account_id)
        self.assertEqual(balance, decimal.Decimal("10.00"))
예제 #2
0
파일: pay.py 프로젝트: 3taps/Tahua
def pay(request):
    """ Respond to the "/pay" API call.
    """
    try:
        # Extract our payload from the request parameters.

        request_payload = api_helper.process_request(request)
        if "error" in request_payload:
            return request_payload["error"]

        # Check that the required fields have all been supplied.

        error = api_helper.check_fields(
            request_payload,
            required_fields=["session_key", "from_account_id", "to_account_id", "amount"],
            optional_fields=["pin_number", "meta_data"],
        )
        if error != None:
            return error

        # Get the values we need from the payload.

        session = request_payload["session"]
        from_account_id = request_payload["fields"]["from_account_id"]
        to_account_id = request_payload["fields"]["to_account_id"]
        amount = decimal.Decimal(request_payload["fields"]["amount"])
        pin_number = request_payload["fields"].get("pin_number")
        meta_data = request_payload["fields"].get("meta_data")

        # If the "to" account refers to a user alias, call the user alias
        # resolver to translate from the user alias to the underlying user ID.

        if isinstance(to_account_id, dict):
            if "user_alias" in to_account_id:
                user_id = alias_resolver.resolve(to_account_id["user_alias"])
                if user_id == None:
                    return api_helper.error(request_payload, api_errors.UNKNOWN_ACCOUNT_ALIAS)
                to_account_id["user_id"] = user_id
                del to_account_id["user_alias"]

        # Check that the "from" and "to" accounts are both valid.

        if not account_helper.is_valid_account_id(from_account_id):
            return api_helper.error(request_payload, api_errors.INVALID_ACCOUNT_ID)

        if not account_helper.is_valid_account_id(to_account_id):
            return api_helper.error(request_payload, api_errors.INVALID_ACCOUNT_ID)

        # Make sure the user is allowed to access the "from" account.

        if session.user.user_id != from_account_id.get("user_id"):
            return api_helper.error(request_payload, api_errors.UNAUTHORIZED)

        # If this transaction requires a PIN number, ensure that the correct
        # PIN has been supplied.

        max_payment_without_pin = account_helper.get_account_policy(from_account_id, "max_payment_without_pin")
        if max_payment_without_pin != None:
            if amount >= max_payment_without_pin:
                # We need a PIN number for this payment -> check that the
                # correct PIN has been supplied.
                if pin_number == None:
                    return api_helper.error(request_payload, api_errors.PIN_NUMBER_REQUIRED)

                if pin_number != session.user.pin_number:
                    return api_helper.error(request_payload, api_errors.INVALID_PIN_NUMBER)

        # Check that the amount isn't too high, or doesn't exceed the daily
        # transaction limit...eventually.

        # Check that the account has enough funds to cover the desired
        # transaction.

        min_account_balance = account_helper.get_account_policy(from_account_id, "min_account_balance")
        if min_account_balance == None:
            min_account_balance = decimal.Decimal("0.00")

        account_balance = account_helper.get_account_balance(from_account_id)
        if account_balance - amount < min_account_balance:
            return api_helper.error(request_payload, api_errors.INSUFFICIENT_FUNDS)

        # If necessary, create the Account record(s) for the from and to
        # accounts.

        from_account = account_helper.get_or_create_account(from_account_id)
        to_account = account_helper.get_or_create_account(to_account_id)

        # If we get here, we're ready to make this payment.  Create appropriate
        # Transaction records to transfer the funds from one account to the
        # other.

        timestamp = datetime.datetime.now()

        transaction = Transaction()
        transaction.account = from_account
        transaction.other_account = to_account
        transaction.timestamp = timestamp
        transaction.type = Transaction.TYPE_PAYMENT
        transaction.amount = -amount
        transaction.set_metadata(meta_data)
        transaction.save()

        transaction = Transaction()
        transaction.account = to_account
        transaction.other_account = from_account
        transaction.timestamp = timestamp
        transaction.type = Transaction.TYPE_PAYMENT
        transaction.amount = amount
        transaction.set_metadata(meta_data)
        transaction.save()

        # Update the 'update_id' values for both accounts, so that the various
        # clients will know that the accounts have been updated.

        account_helper.increment_update_id(from_account.id)
        account_helper.increment_update_id(to_account.id)

        # Finally, return an empty response payload back to the caller.  We
        # return an empty response (as opposed to an error response) when the
        # payment was successful.

        response_payload = {}
        return api_helper.response(request_payload, response_payload)
    except:
        traceback.print_exc()
        return HttpResponseServerError()