def providers(request): donation = json.loads(request.body) _, contribution = save_donor_and_contribution(donation) stamp = uuid.uuid1().hex body = payments_request_body(stamp, contribution.sum, contribution.donor.email) body_json = json.dumps(body) payment_providers_response = requests.post( f"{PAYTRAIL_URL}/payments", headers={ **signed_paytrail_headers(PAYTRAIL_ACCOUNT_ID, PAYTRAIL_ACCOUNT_SECRET, body_json), **{ "Content-Type": "application/json; charset=utf-8" } }, data=body_json) verify_response_headers(payment_providers_response.headers, PAYTRAIL_ACCOUNT_SECRET, payment_providers_response.text) payment_providers = json.loads(payment_providers_response.text) payment = Transaction( checkout_transaction_id=payment_providers["transactionId"], checkout_reference=payment_providers["reference"], status="new", contribution=contribution) logger.info("Creating new payment %", payment) payment.save() response = HttpResponse(content_type="application/json") response.write(payment_providers_response.text) return response
def make_payment(payment: Payment): transaction = Transaction(payment=payment, waiting=True) transaction.save() response = None try: if payment.payment_method == 'M': # save transaction phone number transaction_phone = TransactionPhone( transaction=transaction, phone_number=payment.order.billing_address.phone_number) transaction_phone.save() response = mobile_payments( phone_number=transaction_phone.phone_number, amount=payment.amount, transaction_id=str(transaction.id)) elif payment.payment_method == 'C': # TODO pass else: raise Exception('Incorrect payment method') except Exception as e: transaction_failed(transaction, e) raise Exception(e) else: return save_transaction(transaction=transaction, transaction_resp=response)
def save_transaction(transaction: Transaction, transaction_resp): """ Save the transaction response as a Transaction object to the db :param transaction: Transaction model object :param transaction_resp: Transaction respsonse from africastalking API """ if type(transaction_resp) == dict and transaction_resp['status']: if transaction_resp['description']: transaction.description = transaction_resp['description'] if transaction_resp['transactionId']: transaction.transaction_id = transaction_resp['transactionId'] if transaction_resp['providerChannel']: transaction.provider_channel = transaction_resp['providerChannel'] if transaction_resp['status'] == 'InvalidRequest': transaction.save() transaction_failed( transaction=transaction, error_message= 'InvalidRequest: The request could not be accepted as one of the fields ' 'was invalid. The description field will contain more information.' ) raise Exception('Transaction Failed: InvalidRequest') # Handle phone number not supported elif transaction_resp['status'] == 'NotSupported': # TODO: mark transaction phone number as invalid transaction.save() transaction_failed( transaction=transaction, error_message= 'NotSupported: Checkout to the provided phone number is not supported.' ) raise Exception('Transaction Failed: NotSupported') # Handle unknown fail elif transaction_resp['status'] == 'Failed': transaction.save() transaction_failed(transaction=transaction, error_message='Failed') raise Exception('Transaction Failed: Failed') # Successful transaction. Awaiting confirmation from user elif transaction_resp['status'] == 'PendingConfirmation': transaction.save() return else: transaction.save() transaction_failed(transaction=transaction) else: transaction_failed(transaction=transaction, error_message='No response') raise Exception('Transaction Failed')
def pay_bill(self, request, **kwargs): if request.user.is_authenticated(): data = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) bill = Bill.objects.get(id=data.get('bill_id')) bill.sender = request.user bill.save() transcation = Transaction() transcation.sender = request.user transcation.receiver = bill.store.vendor.user transcation.transaction_type = 2 transcation.amount = bill.total_amount transcation.bill = bill transcation.store = bill.store transcation.transaction_state = 1 mobile = Mobile() mobile.transaction = transcation try: bank = BankAccountDetails.objects.get(user=request.user, account_state=1) mobile.sender_account = bank except BankAccountDetails.DoesNotExist: return self.create_response(request, {"success":False, "status_code":101, "details": "No active bank accounts or please link atleast one bank account"}) if int(bill.total_amount) > int(bank.balance): return self.create_response(request, {"success":False, "status_code":201, "details":"Insufficient Funds"}) else: bank.balance = int(bank.balance)-int(bill.total_amount) bank1 = BankAccountDetails.objects.get(user=transcation.receiver, account_state=1) bank.save() bank1.balance = int(bank1.balance)+int(bill.total_amount) bank1.save() transcation.save() bank = BankAccountDetails.objects.get(user=transcation.receiver, account_state=1) mobile.receiver_account = bank mobile.save() bundle = TransactionResource().build_bundle(obj=transcation) bundle = TransactionResource().full_dehydrate(bundle=bundle) return self.create_response(request, {'success': True, "status_code": 100, 'transaction': bundle}) else: return self.create_response(request, {'success':False, "details":"user not authenticated please login", "status_code": 111})
def checkout(self, user, address, payment_method): order = self.user_cart(user) transaction = Transaction() transaction.transaction_status = 1 transaction.transaction_id = str(uuid.uuid1()) transaction.price = order.total_prices() transaction.order = order transaction.payment_method = payment_method transaction.save() order.status = PLACED_ORDER order.process_status = PENDING order.address = Address.objects.get(id=address) order.save() return order
def transaction_failed(transaction: Transaction, error_message=None): if error_message: if type(error_message) != str: try: error_message = str(error_message) except: print(error_message) error_message = None transaction.paid = False transaction.waiting = False transaction.failed = True transaction.error_message = error_message transaction.save() payment_failed(transaction.payment)
def save_transaction(transaction: Transaction, transaction_resp): if type(transaction_resp) == dict and transaction_resp['status']: if transaction_resp['description']: transaction.description = transaction_resp['description'] if transaction_resp['transactionId']: transaction.transaction_id = transaction_resp['transactionId'] if transaction_resp['providerChannel']: transaction.provider_channel = transaction_resp['providerChannel'] if transaction_resp['status'] == 'InvalidRequest': transaction.save() transaction_failed( transaction=transaction, error_message= 'InvalidRequest: The request could not be accepted as one of the fields ' 'was invalid. The description field will contain more information.' ) raise Exception('Transaction Failed: InvalidRequest') # elif transaction_resp['status'] == 'NotSupported': transaction.save() transaction_failed( transaction=transaction, error_message= 'NotSupported: Checkout to the provided phone number is not supported.' ) raise Exception('Transaction Failed: NotSupported') # elif transaction_resp['status'] == 'Failed': transaction.save() transaction_failed(transaction=transaction, error_message='Failed') raise Exception('Transaction Failed: Failed') # elif transaction_resp['status'] == 'PendingConfirmation': transaction.save() pass else: transaction.save() transaction_failed(transaction=transaction) else: transaction_failed(transaction=transaction, error_message='No response') raise Exception('Transaction Failed')
def transaction_failed(transaction: Transaction, error_message=None): """ Save a failed Transaction :param transaction: Transaction object(model) :param error_message: Error message to be recorded """ if error_message: if type(error_message) != str: try: error_message = str(error_message) except: error_message = None transaction.paid = False transaction.waiting = False transaction.failed = True transaction.error_message = error_message transaction.save() payment_failed(transaction.payment)
def send_money(self, request, **kwargs): if request.user.is_authenticated(): data = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) if data.get('send_money_type') == 0: mobile_number = data.get('mobile') amount = data.get('amount') message = data.get('message') transaction = Transaction() transaction.sender = request.user try: receiver = User.objects.get(mobile=mobile_number) except User.DoesNotExist: return self.create_response(request, {"success": False, "status_code": 102, 'details':"given mobile number is not associated with any account"}) transaction.receiver = receiver transaction.amount = amount transaction.text = message transaction.transaction_type = 2 transaction.transaction_state = 1 mobile = Mobile() mobile.transaction = transaction try: bank = BankAccountDetails.objects.get(user=request.user, account_state=1) mobile.sender_account = bank a=transaction.amount aa=bank.balance s=int(aa)-int(a) if s<0: print(transaction.amount) print(bank.balance) return self.create_response(request, {"success": False, "status_code": 201, "details": "Insufficient Funds"}) else: bank.balance = int(bank.balance)-int(transaction.amount) bank.save() bank = BankAccountDetails.objects.get(user=transaction.receiver, account_state=1) mobile.receiver_account = bank bank.balance = int(bank.balance)+int(transaction.amount) bank.save() except BankAccountDetails.DoesNotExist: return self.create_response(request, {"success": False, "status_code": 101, "details": "No active bank accounts or please link atleast one bank account"}) transaction.save() mobile.save() bundle = TransactionResource().build_bundle(obj=transaction) bundle = TransactionResource().full_dehydrate(bundle=bundle) return self.create_response(request, {'success': True, "status_code": 100, 'transaction': bundle}) elif data.get('send_money_type') == 1: account_no = data.get('account_no') holder_name = data.get('holder_name') ifsc_code = data.get('ifsc_code') amount = data.get('amount') transaction = Transaction() transaction.sender = request.user transaction.amount = amount transaction.transaction_type = 0 transaction.text = data.get('message') transaction.transaction_state = 1 transaction.save() account_details = AccountDetails() account_details.transaction = transaction try: account_details.sender_bank = BankAccountDetails.objects.get(user=request.user,account_state=BankAccountDetails.ACTIVE) account_details.sender_bank.balance = int(account_details.sender_bank.balance)-int(amount) except BankAccountDetails.DoesNotExist: return self.create_response(request, {"success": False, "status_code": 101, "details": "No active bank accounts or please link atleast one bank account"}) account_details.holder_name = holder_name account_details.account_no = account_no account_details.ifsc_code = ifsc_code account_details.save() account_details.save() bundle = TransactionResource().build_bundle(obj=transaction) bundle = TransactionResource().full_dehydrate(bundle=bundle) return self.create_response(request, {'success': True, "status_code": 100, 'transaction': bundle}) else: return self.create_response(request, {'success': False, "details": "service not found", "error_code": 404}) else: return self.create_response(request, {'success': False, "details": "user not authenticated please login", "error_code": 111})