Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Update] repo #2

Merged
merged 2 commits into from
Jun 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Cardman API

A one-stop solution for managing all your Credit Card needs with an option to realtime track your Credit Card transactions.

## Features

- Realtime transaction tracking based on alert email auto-forward rules on your mailbox
- Consolidated card balances

## Getting started

- Step 1: Create a Railway.app account and project

- Visit the Railway.app website (https://railway.app/) and sign up for an account if you don't have one already.
- Create a new project in Railway.app by connecting your Git repository containing this Django project.

- Step 2: Set up environment variables in Railway.app

- In your Railway.app project, navigate to the "Environment Variables" section.
- Click on the "Add Variable" button.
- Set the variable name as SNS_ENDPOINT_SECRET and provide a random secure UUID as the value. You can generate a UUID using an online UUID generator or use a programming language to generate one.
- Click on the "Add Variable" button again.
- Set the variable name as ENDPOINT_URI_WITH_SCHEMA and provide your app URL with the appropriate schema (HTTP or HTTPS).
- Example: https://your-domain.com or http://your-domain.com
- Save the environment variables.

- Step 3: Deploy your Django project on Railway.app

- Once your environment variables are set, click the "Deploy" button in Railway.app to deploy your Django project.
- Railway.app will automatically build and deploy your project based on this Git repository's configuration.
- That's it! Your Django project will be deployed on Railway.app, and the environment variables SNS_ENDPOINT_SECRET and ENDPOINT_URI_WITH_SCHEMA will be set. You can now use these variables to configure the SNS integration and use the provided endpoint URL.

- Step 4: Set up an AWS account

- Create an AWS account if you don't have one already.
- Go to the AWS Management Console and navigate the Simple Email Service (SES) dashboard.
- Follow the instructions to verify your email domain
- Forward your MX Entry to AWS SES

- Step 5: Configure SNS to handle email receiving

- Go to the AWS Management Console and navigate to the SNS dashboard.
- Click on "Create topic" to create a new topic.
- Provide a name for the topic and click "Create topic" to create it.
- Select the newly created topic from the list and click "Create subscription".
- Choose the protocol as HTTPS/HTTP.
- In the "Endpoint" field, enter the endpoint URL of your Django app where you want to receive the email payload, for example, https://your-domain.com/emails/inbound/SNS_ENDPOINT_SECRET/ (replace your-domain.com and SNS_ENDPOINT_SECRET with your actual values).

- Step 6: Configure Django user:
- Clone this repository and change database credentials to one from the railway app
- Run `python manage.py createsuperuser` to create a user
- Navigate to https://your-domain.com/admin and log in using the credentials generated.
- Add a bank with an alert email used to receive emails (in lowercase) and parser name, i.e. `AxisCCParser` for Axis Bank.
- Add a registered email used to forward emails to the server.

## Usage

Navigate to `/cards` to view all the cards info
Navigate to `/cards/add` to add a card
Navigate to `/transactions` to view all the transactions info
Navigate to `/transactions/add` to add a transaction
Navigate to `/banks` to view all the bank info

## Additional information

Feel free to open a PR with new parsers in `/emails/email_parsers`
This is still a work in progress. Any feedback and bug reports are welcomed.
2 changes: 1 addition & 1 deletion cardman/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
SECRET_KEY = os.environ.get('SECRET_KEY', 'django-insecure-(x&dc^khsyq$t6jxl27mtty*-dnqet$7iet=&f9x$#$of0s*=i')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
DEBUG = (os.environ.get('ENVIRONMENT', 'production') != 'production')

ALLOWED_HOSTS = ["*"]

Expand Down
2 changes: 0 additions & 2 deletions cardman/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
"""
from django.contrib import admin
from django.urls import path, include
from rest_framework.authtoken import views

urlpatterns = [
path('admin/', admin.site.urls),
path('token-auth/', views.obtain_auth_token),
path('auth/', include('rest_framework.urls')),
path('cards/', include('cards.urls')),
path('banks/', include('banks.urls')),
Expand Down
16 changes: 8 additions & 8 deletions emails/email_parsers/AxisCCParser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
from django.db.models import QuerySet

from cards.models import Card
from emails.email_parsers.BaseEmailParser import BaseEmailParser
Expand All @@ -7,11 +8,7 @@

class AxisCCParser(BaseEmailParser):

def __init__(self):
super().__init__()

@staticmethod
def parse(email, user, bank):
def __init__(self, email: str, cards: QuerySet(Card), transaction: Transaction):
if 'Transaction alert on Axis Bank Credit Card no. ' not in email:
return

Expand All @@ -23,7 +20,10 @@ def parse(email, user, bank):
card_number = card_number.replace('X', '')

amount = int(float(result[0][1]) * 100)
store = result[0][2]
merchant = result[0][2]

transaction.card = cards.filter(card_number__endswith=card_number).first()
transaction.amount_in_paise = amount
transaction.merchant = merchant

card = Card.objects.get(card_number__endswith=card_number, bank=bank, user=user)
Transaction.objects.create(card=card, amount_in_paise=amount, merchant=store)
super().__init__(transaction)
10 changes: 3 additions & 7 deletions emails/email_parsers/BaseEmailParser.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from django.contrib.auth.models import User
from banks.models import Bank
from transactions.models import Transaction


class BaseEmailParser:
def __init__(self):
pass

@staticmethod
def parse(email: str, user: User, bank: Bank):
raise NotImplementedError("You must implement parse() method in your parser class")
def __init__(self, transaction: Transaction):
transaction.save()
11 changes: 8 additions & 3 deletions emails/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

from banks.models import Bank
from cardman import request_parsers
from transactions.models import Transaction
from cards.models import Card
from .models import RegisteredEmail


Expand Down Expand Up @@ -52,12 +54,15 @@ def post(request):
importlib.import_module('emails.email_parsers.' + bank.cc_transaction_email_parser),
bank.cc_transaction_email_parser
)
parser.parse(strip_non_ascii(decoded_message).replace('\r\n', '').replace('=', '').replace('>', ''),
user, bank)
transaction = Transaction()
parser(
strip_non_ascii(decoded_message).replace('\r\n', '').replace('=', '').replace('>', ''),
Card.objects.filter(user=user, bank=bank),
transaction
)
return Response({"success": True}, status=status.HTTP_200_OK)

return Response({"success": True}, status=status.HTTP_200_OK)
except Exception as e:
print(e)
pass
return Response({"success": True}, status=status.HTTP_200_OK)