diff --git a/apps/pg/admin.py b/apps/pg/admin.py index 650555c..1af6777 100644 --- a/apps/pg/admin.py +++ b/apps/pg/admin.py @@ -1,3 +1,4 @@ +import logging import io import jdatetime @@ -7,13 +8,13 @@ from django.db.models import Sum from django.http import HttpResponse from django.utils import timezone from django.utils.html import format_html -from django.shortcuts import redirect +from django.shortcuts import redirect, get_object_or_404 from django.urls import path -from utils.wallet_client import deposit_to_user_wallet_verify from .constans import StateChoices from .models import PaymentRequest, PNA, Fake +logger = logging.getLogger(__name__) class PNAAdmin(admin.ModelAdmin): list_display = ['pna_status_code', 'pna_status_message', 'jajali_datetime', 'payment_request'] @@ -83,7 +84,7 @@ class PaymentRequestAdmin(admin.ModelAdmin): return super().changelist_view(request, extra_context=extra_context) def check_success_again(self, obj): - if obj.state == StateChoices.WALLET_SUBMIT_SUCCESS: + if obj.state in [StateChoices.IPG_SUCCESS, StateChoices.WALLET_SUBMIT_PENDING, StateChoices.WALLET_SUBMIT_SUCCESS]: return format_html( 'بررسی دوباره موفقیت', f'{obj.uuid}/check_success_again/' @@ -96,27 +97,19 @@ class PaymentRequestAdmin(admin.ModelAdmin): path('/check_success_again/', self.admin_site.admin_view(self.check_success_again_view)) ] return custom_urls + urls - def check_success_again_view(self, request, payment_request_uuid): - verify_response = deposit_to_user_wallet_verify(payment_request_uuid) - if not verify_response: - self.message_user(request, "خطای استعلام", level=messages.ERROR) - else: - if not verify_response.uuid or verify_response.state != 5: - to_pay_failed = PaymentRequest.objects.filter( - pk=payment_request_uuid, - state=StateChoices.WALLET_SUBMIT_SUCCESS.value - ).update( - state=StateChoices.FAILED.value, - ) - else: - to_pay_success = PaymentRequest.objects.filter( - pk=payment_request_uuid, - state=StateChoices.WALLET_SUBMIT_SUCCESS.value - ).update( - state=StateChoices.SUCCESS.value, - ) - self.message_user(request, f"درخواست {payment_request_uuid} بررسی شد ✅") + logger.info(f"[Admin panel] Check success again for payment_request_uuid={payment_request_uuid}") + payment_request: PaymentRequest = get_object_or_404(PaymentRequest, uuid=payment_request_uuid) + logger.info(f"[Admin panel] initial payment_request state={payment_request.state}") + if payment_request.state == StateChoices.IPG_SUCCESS: + payment_request.charge_wallet_balance() + elif payment_request.state == StateChoices.WALLET_SUBMIT_PENDING: + payment_request.deposit_submit() + elif payment_request.state == StateChoices.WALLET_SUBMIT_SUCCESS: + payment_request.deposit_verify() + payment_request.refresh_from_db() + logger.info(f"[Admin panel] final payment_request state={payment_request.state}") + self.message_user(request, f"درخواست {payment_request_uuid} بررسی شد ✅") return redirect(request.META.get("HTTP_REFERER", "..")) diff --git a/apps/pg/models.py b/apps/pg/models.py index 68589c6..76f2e3f 100644 --- a/apps/pg/models.py +++ b/apps/pg/models.py @@ -1,5 +1,6 @@ +import logging + import urllib.parse -from mimetypes import guess_all_extensions import jdatetime from django.conf import settings @@ -18,7 +19,7 @@ from utils.wallet_client import deposit_to_user_wallet_submit, withdraw_from_use from utils.pna import PNAClient from django.utils.translation import gettext_lazy as _ - +logger = logging.getLogger(__name__) class GatewayChoise(TextChoices): FAKE = "fake", _("fake") @@ -114,7 +115,67 @@ class PaymentRequest(models.Model): else: raise Exception(error_message) + def deposit_submit(self): + data = { + "uuid": str(self.uuid), + "payee_id": str(self.user.uuid), + "payee_type": 1, + "amount": self.amount, + "details": { + 'description': str(_("charge via ipg")), + 'reference_id': str(self.uuid), + 'application_details_url': '' + }, + } + submit_response = deposit_to_user_wallet_submit(settings.WALLET_CATEGORY_UUID, data) + + if not submit_response or not submit_response.uuid: + logger.error(f"[Deposit Submit] Wallet submission failed | payment_id={self.pk}") + raise Exception('Failed to submit payment in wallet') + + to_success = PaymentRequest.objects.filter( + pk=self.pk, + state=StateChoices.WALLET_SUBMIT_PENDING.value, + ).update( + state=StateChoices.WALLET_SUBMIT_SUCCESS.value) + + if not to_success: + logger.error(f"[Deposit Submit] Failed to update state to WALLET_SUBMIT_SUCCESS | payment_id={self.pk}") + raise Exception('Cannot charge balance because state') + return to_success + + def deposit_verify(self): + verify_response = deposit_to_user_wallet_verify(settings.WALLET_CATEGORY_UUID, self.uuid) + + if not verify_response: + logger.error(f"[Deposit Verify] Failed to get response from wallet service | payment_id={self.pk}") + raise Exception('Failed to get response from wallet service') + + if not verify_response.uuid or verify_response.state != 5: + logger.error(f"[Deposit Verify] Wallet verification failed | payment_id={self.pk}, response={verify_response}") + to_pay_failed = PaymentRequest.objects.filter( + pk=self.pk, + state=StateChoices.WALLET_SUBMIT_SUCCESS.value + ).update( + state=StateChoices.FAILED.value, + ) + raise Exception('Failed to verify payment in wallet') + + to_pay_success = PaymentRequest.objects.filter( + pk=self.pk, + state=StateChoices.WALLET_SUBMIT_SUCCESS.value + ).update( + state=StateChoices.SUCCESS.value, + ) + + if not to_pay_success: + logger.error(f"[Deposit Verify] Failed to update state to SUCCESS | payment_id={self.pk}") + raise Exception('Failed to update state payment') + + return to_pay_success + def charge_wallet_balance(self): + logger.info(f"[Charge Wallet] Starting wallet charge process | payment_id={self.pk}") if self.state in [StateChoices.IPG_SUCCESS]: to_pending = PaymentRequest.objects.filter( pk=self.pk, @@ -122,54 +183,15 @@ class PaymentRequest(models.Model): ).update( state=StateChoices.WALLET_SUBMIT_PENDING.value) if not to_pending: + logger.error(f"[Charge Wallet] Failed to update state to WALLET_SUBMIT_PENDING | payment_id={self.pk}") raise Exception('Cannot charge balance because state') - - data = { - "uuid": str(self.uuid), - "payee_id": str(self.user.uuid), - "payee_type": 1, - "amount": self.amount, - "details": { - 'description': str(_("charge via ipg")), - 'reference_id': str(self.uuid), - 'application_details_url': '' - }, - } - submit_response = deposit_to_user_wallet_submit(data) - - if not submit_response.uuid: - raise Exception('Failed to submit payment in wallet') - - to_success = PaymentRequest.objects.filter( - pk=self.pk, - state=StateChoices.WALLET_SUBMIT_PENDING.value, - ).update( - state=StateChoices.WALLET_SUBMIT_SUCCESS.value) - - if not to_success: - raise Exception('Cannot charge balance because state') - - verify_response = deposit_to_user_wallet_verify(self.uuid) - - if not verify_response.uuid or verify_response.state != 5: - to_pay_failed = PaymentRequest.objects.filter( - pk=self.pk, - state=StateChoices.WALLET_SUBMIT_SUCCESS.value - ).update( - state=StateChoices.FAILED.value, - ) - raise Exception('Failed to verify payment in wallet') - - to_pay_success = PaymentRequest.objects.filter( - pk=self.pk, - state=StateChoices.WALLET_SUBMIT_SUCCESS.value - ).update( - state=StateChoices.SUCCESS.value, - ) - - if not to_pay_success: - raise Exception('Failed to update state payment') - + logger.info(f"[Charge Wallet] State updated to WALLET_SUBMIT_PENDING | payment_id={self.pk}") + self.deposit_submit() + to_pay_success = self.deposit_verify() + if to_pay_success: + logger.info(f"[Charge Wallet] Wallet charged successfully | payment_id={self.pk}") + else: + logger.warning(f"[Charge Wallet] Wallet charge verification failed | payment_id={self.pk}") return bool(to_pay_success) diff --git a/main/settings.py b/main/settings.py index 4a5e9a1..16c1f02 100644 --- a/main/settings.py +++ b/main/settings.py @@ -255,4 +255,5 @@ CACHES = { PNA_CORPORATION_PIN = config('PNA_CORPORATION_PIN') WALLET_BASE_PUBLIC_URL = config('WALLET_BASE_PUBLIC_URL') +WALLET_CATEGORY_UUID = config('WALLET_CATEGORY_UUID') IPG_BASE_PUBLIC_URL = config('IPG_BASE_PUBLIC_URL') diff --git a/utils/wallet_client.py b/utils/wallet_client.py index 0762eaa..729ae4b 100644 --- a/utils/wallet_client.py +++ b/utils/wallet_client.py @@ -8,8 +8,8 @@ from httpx import Request from gooyal_wallet_client import AuthenticatedClient from gooyal_wallet_client.models import MyWallet, UserTransaction, ApplicationDeposit, ApplicationWithdraw -from gooyal_wallet_client.api.wallet import (wallet_api_application_deposit_create, - wallet_api_application_deposit_verify_retrieve, +from gooyal_wallet_client.api.wallet import (wallet_api_application_deposit_create_2, + wallet_api_application_deposit_verify_retrieve_2, wallet_api_application_withdraw_create, wallet_api_application_withdraw_verify_retrieve) from gooyal_wallet_client.types import Response @@ -73,22 +73,24 @@ def get_client(): return client -def deposit_to_user_wallet_submit(data): +def deposit_to_user_wallet_submit(category_uuid, data): class Tmp(): def to_dict(self): return data deposit_data = Tmp() client = get_client() - response: ApplicationDeposit = wallet_api_application_deposit_create.sync(client=client, body=deposit_data) + response: ApplicationDeposit = wallet_api_application_deposit_create_2.sync(category_uuid= category_uuid, + client=client, + body=deposit_data) print(response) return response -def deposit_to_user_wallet_verify(uuid): +def deposit_to_user_wallet_verify(category_uuid, uuid): client = get_client() - response: ApplicationDeposit = wallet_api_application_deposit_verify_retrieve.sync(uuid=uuid, client=client) + response: ApplicationDeposit = wallet_api_application_deposit_verify_retrieve_2.sync(category_uuid=category_uuid, uuid=uuid, client=client) print(response) return response