-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
160 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class PaymentsConfig(AppConfig): | ||
default_auto_field = 'django.db.models.BigAutoField' | ||
name = 'payments' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Generated by Django 4.1.7 on 2024-11-06 16:50 | ||
|
||
from django.conf import settings | ||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
import phonenumber_field.modelfields | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='PaymentProfile', | ||
fields=[ | ||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region=None)), | ||
('telecom_provider', models.CharField(max_length=50,blank=True, null=True)), | ||
('is_verified', models.BooleanField(default=False)), | ||
('is_validated', models.BooleanField(default=False)), | ||
('created_at', models.DateTimeField(auto_now_add=True)), | ||
('updated_at', models.DateTimeField(auto_now=True)), | ||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='payment_profile', to=settings.AUTH_USER_MODEL)), | ||
], | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from django.db import models | ||
|
||
from phonenumber_field.modelfields import PhoneNumberField | ||
from users.models import ConnectUser | ||
|
||
|
||
class PaymentProfile(models.Model): | ||
user = models.OneToOneField( | ||
ConnectUser, | ||
on_delete=models.CASCADE, | ||
related_name='payment_profile' | ||
) | ||
phone_number = PhoneNumberField() | ||
telecom_provider = models.CharField(max_length=50, blank=True, null=True) | ||
# whether the number is verified using OTP | ||
is_verified = models.BooleanField(default=False) | ||
# whether the number is a valid payment receiver | ||
is_validated = models.BooleanField(default=False) | ||
|
||
created_at = models.DateTimeField(auto_now_add=True) | ||
updated_at = models.DateTimeField(auto_now=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from django.http import JsonResponse, HttpResponse, Http404 | ||
from django.views.decorators.http import require_POST | ||
from oauth2_provider.decorators import protected_resource | ||
from utils.rest_framework import ClientProtectedResourceAuth | ||
from rest_framework.decorators import api_view | ||
from rest_framework.views import APIView | ||
from users.models import ConnectUser, PhoneDevice | ||
from utils.twilio import lookup_telecom_provider | ||
from .models import PaymentProfile | ||
|
||
|
||
@api_view(['POST']) | ||
def update_payment_profile_phone(request): | ||
user = request.user | ||
phone_number = request.data.get('phone_number') | ||
telecom_provider = lookup_telecom_provider(phone_number) | ||
payment_profile, created = PaymentProfile.objects.update_or_create( | ||
user=user, | ||
defaults={ | ||
'phone_number': phone_number, | ||
'telecom_provider': telecom_provider, | ||
'is_verified': False, | ||
'is_validated': False | ||
} | ||
) | ||
return PhoneDevice.send_otp_httpresponse(phone_number=payment_profile.phone_number, user=payment_profile.user) | ||
|
||
|
||
@api_view(['POST']) | ||
def confirm_payment_profile_otp(request): | ||
PaymentProfile.objects.get(user=request.user) | ||
payment_profile = request.user.payment_profile | ||
device = PhoneDevice.objects.get(phone_number=payment_profile.phone_number, user=payment_profile.user) | ||
if not device.verify_token(request.data.get('token')): | ||
return JsonResponse({"error": "OTP token is incorrect"}, status=401) | ||
|
||
payment_profile.is_verified = True | ||
payment_profile.save() | ||
return JsonResponse({"success": True}) | ||
|
||
|
||
@require_POST | ||
@protected_resource(scopes=[]) | ||
def validate_payment_phone_number(request): | ||
username = request.data["username"] | ||
phone_number = request.data["phone_number"] | ||
user = ConnectUser.objects.get(username=username) | ||
profile = getattr(user, "payment_profile") | ||
|
||
if not profile or profile.phone_number != phone_number: | ||
raise Http404("Payment number not found") | ||
|
||
profile.is_validated = True | ||
return HttpResponse() | ||
|
||
|
||
class ValidatePhoneNumber(APIView): | ||
authentication_classes = [ClientProtectedResourceAuth] | ||
|
||
def post(self, request, *args, **kwargs): | ||
username = request.data["username"] | ||
phone_number = request.data["phone_number"] | ||
user = ConnectUser.objects.get(username=username) | ||
profile = getattr(user, "payment_profile") | ||
|
||
if not profile or profile.phone_number != phone_number: | ||
raise Http404("Payment number not found") | ||
|
||
profile.is_validated = True | ||
profile.save() | ||
return HttpResponse() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters