forked from edly-io/ecommerce
-
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
umer farooq
committed
Jan 12, 2021
1 parent
f812f58
commit 9aa82a0
Showing
9 changed files
with
413 additions
and
2 deletions.
There are no files selected for viewing
33 changes: 33 additions & 0 deletions
33
ecommerce/extensions/basket/migrations/0012_basketchallanvoucher.py
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,33 @@ | ||
# -*- coding: utf-8 -*- | ||
# Generated by Django 1.11.29 on 2021-01-04 16:01 | ||
from __future__ import unicode_literals | ||
|
||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
import django_extensions.db.fields | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('basket', '0011_add_email_basket_attribute_type'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='BasketChallanVoucher', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name='created')), | ||
('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')), | ||
('voucher_number', models.CharField(max_length=32, unique=True)), | ||
('is_paid', models.BooleanField(default=False)), | ||
('basket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='basket.Basket', verbose_name='Basket')), | ||
], | ||
options={ | ||
'ordering': ('-modified', '-created'), | ||
'abstract': False, | ||
'get_latest_by': 'modified', | ||
}, | ||
), | ||
] |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
""" Paystack payment processor. """ | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
import logging | ||
|
||
import waffle | ||
from django.conf import settings | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Lumsxpay(): | ||
""" | ||
Just a bare structure of processor to register its name, no legacy methods added or will be used as LUMSX | ||
payment method is thirdparty and cannot be integerated | ||
""" | ||
NAME = 'lumsxpay' | ||
|
||
def __init__(self, site): | ||
self.site = site | ||
|
||
@property | ||
def payment_processor(self): | ||
return Lumsxpay(self.request.site) | ||
|
||
@classmethod | ||
def is_enabled(cls): | ||
""" | ||
Returns True if this payment processor is enabled, and False otherwise. | ||
""" | ||
return waffle.switch_is_active(settings.PAYMENT_PROCESSOR_SWITCH_PREFIX + cls.NAME) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
""" View for interacting with the LumsxPay payment processor. """ | ||
|
||
from __future__ import unicode_literals | ||
|
||
import json | ||
import logging | ||
|
||
import requests | ||
from django.db import transaction | ||
from django.http import HttpResponseNotFound | ||
from django.shortcuts import redirect, render_to_response | ||
from django.utils.decorators import method_decorator | ||
from django.views.generic import View | ||
from oscar.core.loading import get_class, get_model | ||
|
||
from ecommerce.extensions.checkout.mixins import EdxOrderPlacementMixin | ||
from ecommerce.extensions.payment.processors.lumsxpay import Lumsxpay | ||
from ecommerce.extensions.analytics.utils import translate_basket_line_for_segment | ||
from ecommerce.extensions.basket.models import BasketChallanVoucher | ||
from ecommerce.core.url_utils import get_lms_dashboard_url | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
Applicator = get_class('offer.applicator', 'Applicator') | ||
Basket = get_model('basket', 'Basket') | ||
Product = get_model('catalogue', 'Product') | ||
OrderTotalCalculator = get_class('checkout.calculators', 'OrderTotalCalculator') | ||
NoShippingRequired = get_class('shipping.methods', 'NoShippingRequired') | ||
|
||
|
||
class LumsxpayExecutionView(EdxOrderPlacementMixin, View): | ||
@property | ||
def payment_processor(self): | ||
return Lumsxpay(self.request.site) | ||
|
||
@method_decorator(transaction.non_atomic_requests) | ||
def dispatch(self, request, *args, **kwargs): | ||
return super(LumsxpayExecutionView, self).dispatch(request, *args, **kwargs) | ||
|
||
def voucher_payment(self, request): | ||
configuration_helpers = request.site.siteconfiguration.edly_client_theme_branding_settings | ||
url = configuration_helpers.get('LUMSXPAY_VOUCHER_API_URL') | ||
|
||
if not (url and request.basket): | ||
return None | ||
|
||
products_basket = [translate_basket_line_for_segment(line) for line in request.basket.all_lines()] | ||
|
||
shipping_method = NoShippingRequired() | ||
shipping_charge = shipping_method.calculate(request.basket) | ||
order_total = OrderTotalCalculator().calculate(request.basket, shipping_charge) | ||
|
||
user = request.basket.owner | ||
|
||
billing_address = None | ||
order = self.handle_order_placement( | ||
order_number=request.basket.order_number, | ||
user=user, | ||
basket=request.basket, | ||
shipping_address=None, | ||
shipping_method=shipping_method, | ||
shipping_charge=shipping_charge, | ||
billing_address=billing_address, | ||
order_total=order_total, | ||
request=None | ||
) | ||
self.handle_post_order(order) | ||
|
||
return order | ||
|
||
def extract_items_from_basket(self, basket): | ||
return [ | ||
{ | ||
"title": l.product.title, | ||
"amount": str(l.line_price_incl_tax), | ||
"id": l.product.course_id} | ||
for l in basket.all_lines() | ||
] | ||
|
||
def is_basket_and_challan_exists(self, request): | ||
courses = [i['id'] for i in self.extract_items_from_basket(request.basket)] | ||
course_ids = [] | ||
|
||
for course in courses: | ||
product = Product.objects.filter(structure='child', course_id=course).first() | ||
if product: | ||
course_ids.append(product.id) | ||
|
||
basket = Basket.objects.filter(owner_id=request.user, lines__product_id__in=course_ids).first() | ||
if BasketChallanVoucher.objects.filter(basket=basket).exists(): | ||
return True | ||
|
||
def create_challan_voucher(self, basket, voucher_number): | ||
try: | ||
return BasketChallanVoucher.objects.create(basket=basket, voucher_number=voucher_number, is_paid=False) | ||
except: | ||
return logger.exception('could not create the challan voucher entry in DB') | ||
|
||
def fetch_challan_details(self, request): | ||
courses = [i['id'] for i in self.extract_items_from_basket(request.basket)] | ||
course_ids = [] | ||
|
||
for course in courses: | ||
product = Product.objects.filter(structure='child', course_id=course).first() | ||
if product: | ||
course_ids.append(product.id) | ||
|
||
basket = Basket.objects.filter(owner_id=request.user, lines__product_id__in=course_ids).first() | ||
challan_basket = BasketChallanVoucher.objects.filter(basket=basket).first() | ||
voucher_number = challan_basket.voucher_number | ||
|
||
configuration_helpers = request.site.siteconfiguration.edly_client_theme_branding_settings | ||
url = configuration_helpers.get('LUMSXPAY_VOUCHER_API_URL') + '/' + voucher_number | ||
headers = { | ||
"Authorization": "Bearer b55a65baa0fb0f586ea9170298c20a3fe3d64460add0bf00e43d191aba9fd0a7", | ||
"Content-Type": "application/json" | ||
} | ||
|
||
response = requests.get(url, headers=headers) | ||
if response.status_code == 200: | ||
voucher_details = response.json() | ||
voucher_data = voucher_details.get('data', {}) | ||
url_for_online_payment = voucher_data.get("url_for_online_payment") | ||
url_for_download_voucher = voucher_data.get("url_for_download_voucher") | ||
return { | ||
'configuration_helpers': configuration_helpers, | ||
'url_for_online_payment': url_for_online_payment, | ||
'url_for_download_voucher': url_for_download_voucher, | ||
'items_list': voucher_data.get('items'), | ||
"name": request.user.username, | ||
"email": request.user.email, | ||
"order_id": request.basket.order_number, | ||
"user": request.user, | ||
"lms_dashboard_url": get_lms_dashboard_url, | ||
"is_paid": False, | ||
} | ||
|
||
return HttpResponseNotFound() | ||
|
||
def get(self, request): | ||
configuration_helpers = request.site.siteconfiguration.edly_client_theme_branding_settings | ||
url = configuration_helpers.get('LUMSXPAY_VOUCHER_API_URL') | ||
|
||
if request.user.is_anonymous or not (url and request.basket): # change it to login redirect | ||
return HttpResponseNotFound() | ||
|
||
try: | ||
if self.is_basket_and_challan_exists(request): | ||
context = self.fetch_challan_details(request) | ||
|
||
return render_to_response('payment/lumsxpay.html', context) | ||
else: | ||
items = self.extract_items_from_basket(request.basket) | ||
payload = { | ||
"name": request.user.username, | ||
"email": request.user.email, | ||
"order_id": request.basket.order_number, | ||
"items": items | ||
} | ||
|
||
headers = { | ||
"Authorization": "Bearer b55a65baa0fb0f586ea9170298c20a3fe3d64460add0bf00e43d191aba9fd0a7", | ||
"Content-Type": "application/json"} | ||
|
||
response = requests.post(url, data=json.dumps(payload), headers=headers) | ||
if response.status_code == 200: | ||
voucher_details = response.json() | ||
url_for_online_payment = voucher_details.get('data', {}).get("url_for_online_payment") | ||
url_for_download_voucher = voucher_details.get('data', {}).get("url_for_download_voucher") | ||
|
||
context = { | ||
'configuration_helpers': configuration_helpers, | ||
'url_for_online_payment': url_for_online_payment, | ||
'url_for_download_voucher': url_for_download_voucher, | ||
'items_list': items, | ||
"name": request.user.username, | ||
"email": request.user.email, | ||
"order_id": request.basket.order_number, | ||
"user": request.user, | ||
"lms_dashboard_url": get_lms_dashboard_url, | ||
"is_paid": False | ||
} | ||
|
||
voucher_number = voucher_details['data']['voucher_id'] | ||
self.create_challan_voucher(request.basket, voucher_number) | ||
|
||
return render_to_response('payment/lumsxpay.html', context) | ||
|
||
return HttpResponseNotFound() | ||
|
||
except: # pylint: disable=bare-except | ||
logger.exception('could not make the connection with %s for basket %s' % (url, request.basket.id)) | ||
return HttpResponseNotFound() |
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
Oops, something went wrong.