Skip to content

Commit

Permalink
feat: working code
Browse files Browse the repository at this point in the history
  • Loading branch information
syedsajjadkazmii committed Dec 17, 2024
1 parent 3063f3b commit 86b61a5
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,15 @@ def get_edx_is_sanctioned(order: CTOrder) -> bool:
return get_edx_order_workflow_state_key(order) == TwoUKeys.SDN_SANCTIONED_ORDER_STATE


def get_edx_refund_amount(order: CTOrder) -> decimal:
def get_edx_refund_info(payment: CTPayment) -> decimal:
refund_amount = decimal.Decimal(0.00)
pmt, _ = get_edx_successful_payment_info(order)
for transaction in pmt.transactions:
interaction_id = None
for transaction in payment.transactions:
print('\n\n\n\n\n\nget_edx_refund_amount transaction.type = ', transaction.type)
if transaction.type == TransactionType.CHARGE: # pragma no cover
print('\n\n\n\n\n\nget_edx_refund_amount transaction.amount = ', transaction.amount)
refund_amount += decimal.Decimal(typed_money_to_string(transaction.amount, money_as_decimal_string=True))
return refund_amount
interaction_id = transaction.interaction_id
return refund_amount, interaction_id
return refund_amount, interaction_id

2 changes: 1 addition & 1 deletion commerce_coordinator/apps/commercetools/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ def _preprocess_refund_object(self, refund: Refund, psp: str) -> Refund:
else:
refund["created"] = datetime.datetime.utcfromtimestamp(refund["created"])

refund["status"] = translate_refund_status_to_transaction_status(refund["status"])
refund["status"] = translate_refund_status_to_transaction_status(refund["status"].lower())
refund["currency"] = refund["currency"].upper()
return refund

Expand Down
17 changes: 14 additions & 3 deletions commerce_coordinator/apps/commercetools/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
EDX_PAYPAL_PAYMENT_INTERFACE_NAME
)
from commerce_coordinator.apps.commercetools.catalog_info.edx_utils import (
get_edx_refund_amount,
get_edx_refund_info,
get_edx_successful_payment_info
)
from commerce_coordinator.apps.commercetools.clients import CommercetoolsAPIClient
Expand Down Expand Up @@ -169,11 +169,14 @@ def run_filter(self, active_order_management_system, order_id, **kwargs): # pyl

if payment:
ct_payment = ct_api_client.get_payment_by_key(payment.interface_id)
ret_val['amount_in_cents'] = get_edx_refund_amount(ct_order)
refund_amount, ct_transaction_interaction_id = get_edx_refund_info(ct_payment)
ret_val['amount_in_cents'] = refund_amount
ret_val['ct_transaction_interaction_id'] = ct_transaction_interaction_id
ret_val['has_been_refunded'] = has_refund_transaction(ct_payment)
ret_val['payment_data'] = ct_payment
else:
ret_val['amount_in_cents'] = decimal.Decimal(0.00)
ret_val['ct_transaction_interaction_id'] = None
ret_val['has_been_refunded'] = False
ret_val['payment_data'] = None

Expand Down Expand Up @@ -299,6 +302,7 @@ def run_filter(
active_order_management_system,
payment_data,
has_been_refunded,
payment_intent_id,
psp,
**kwargs
): # pylint: disable=arguments-differ
Expand Down Expand Up @@ -332,7 +336,8 @@ def run_filter(
payment_key = refund_response['payment_intent']
payment_on_order = ct_api_client.get_payment_by_key(payment_key)
elif psp == EDX_PAYPAL_PAYMENT_INTERFACE_NAME:
payment_on_order = ct_api_client.get_payment_by_transaction_interaction_id(refund_response['paypal_capture_id'])
payment_on_order = ct_api_client.get_payment_by_key(payment_intent_id)
print('\n\n\n paypal payment_on_order = ', payment_on_order)

updated_payment = ct_api_client.create_return_payment_transaction(
payment_id=payment_on_order.id,
Expand All @@ -345,6 +350,7 @@ def run_filter(
'returned_payment': updated_payment
}
except CommercetoolsError as err: # pragma no cover
error_message = "unknown"
if psp == EDX_STRIPE_PAYMENT_INTERFACE_NAME:
error_message = f"[payment_intent_id: {refund_response['payment_intent']}, "
elif psp == EDX_PAYPAL_PAYMENT_INTERFACE_NAME:
Expand All @@ -356,6 +362,11 @@ def run_filter(
log.exception(f"[{tag}] Commercetools Error: {err}, {err.errors}")
return PipelineCommand.CONTINUE.value
except HTTPError as err: # pragma no cover
error_message = "unknown"
if psp == EDX_STRIPE_PAYMENT_INTERFACE_NAME:
error_message = f"[payment_intent_id: {refund_response['payment_intent']}, "
elif psp == EDX_PAYPAL_PAYMENT_INTERFACE_NAME:
error_message = f"[paypal_capture_id: {refund_response['paypal_capture_id']}, "
log.info(f"[{tag}] Unsuccessful attempt to create refund payment transaction with details: "
f"psp: {psp}, "
f"{error_message}"
Expand Down
2 changes: 2 additions & 0 deletions commerce_coordinator/apps/commercetools/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ def post(self, request):
**request.data
}

print('\n\n\n\n\n\nrequest.data', request.data)

logger.debug(f'[CT-{tag}] Message received from commercetools with details: {input_data}')

message_details = OrderReturnedViewMessageInputSerializer(data=input_data)
Expand Down
47 changes: 16 additions & 31 deletions commerce_coordinator/apps/paypal/clients.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,38 @@
import logging
import json

from django.conf import settings
from paypalserversdk.http.auth.o_auth_2 import ClientCredentialsAuthCredentials
from paypalserversdk.logging.configuration.api_logging_configuration import (
LoggingConfiguration,
RequestLoggingConfiguration,
ResponseLoggingConfiguration,
)
from paypalserversdk.paypalserversdk_client import PaypalserversdkClient
from paypalserversdk.controllers.orders_controller import OrdersController
from paypalserversdk.controllers.payments_controller import PaymentsController
from paypalserversdk.api_helper import ApiHelper


class PayPalClient:
def __init__(self):
self.paypal_client: PaypalserversdkClient = PaypalserversdkClient(
client_credentials_auth_credentials=ClientCredentialsAuthCredentials(
o_auth_client_id=settings.PAYMENT_PROCESSOR_CONFIG['edx']['paypal']['client_id'],
o_auth_client_secret=settings.PAYMENT_PROCESSOR_CONFIG['edx']['paypal']['client_secret'],
),
logging_configuration=LoggingConfiguration(
log_level=logging.INFO,
# Disable masking of sensitive headers for Sandbox testing.
# This should be set to True (the default if unset)in production.
mask_sensitive_headers=False,
request_logging_config=RequestLoggingConfiguration(
log_headers=True, log_body=True
),
response_logging_config=ResponseLoggingConfiguration(
log_headers=True, log_body=True
),
),
)


def refund_order(self, order_id):
def refund_order(self, capture_id):
paypal_client = self.paypal_client
orders_controller: OrdersController = paypal_client.orders
payments_controller: PaymentsController = paypal_client.payments

order = orders_controller.orders_get({"id": order_id})

capture_id = order.body.purchase_units[0].payments.captures[0].id

collect = {"capture_id": capture_id, "prefer": "return=minimal"}
result = payments_controller.captures_refund(collect)
collect = {"capture_id": capture_id, "prefer": "return=representation"}
refund_response = payments_controller.captures_refund(collect)
print('\n\n\n\n\n refund_response.body = ', refund_response.body)
if refund_response.body:
response = json.loads(ApiHelper.json_serialize(refund_response.body))
print('\n\n\n\n\n refund_order response serialized = ', response)

return {
"id": response.get("id"),
"created": response.get("create_time"),
"status": response.get("status"),
"amount": response.get("amount").get("value"),
"currency": response.get("amount").get("currency_code"),
}

if result.body:
return {"paypal_capture_id": capture_id}

return None
21 changes: 13 additions & 8 deletions commerce_coordinator/apps/paypal/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from commerce_coordinator.apps.paypal.clients import PayPalClient
from commerce_coordinator.apps.core.constants import PipelineCommand
from openedx_filters import PipelineStep
from requests import RequestException

from commerce_coordinator.apps.commercetools.catalog_info.constants import EDX_PAYPAL_PAYMENT_INTERFACE_NAME

Expand Down Expand Up @@ -43,6 +44,7 @@ def run_filter(
order_id,
amount_in_cents,
has_been_refunded,
ct_transaction_interaction_id,
psp,
**kwargs
): # pylint: disable=arguments-differ
Expand All @@ -57,7 +59,7 @@ def run_filter(

tag = type(self).__name__

if psp != EDX_PAYPAL_PAYMENT_INTERFACE_NAME and not amount_in_cents:
if psp != EDX_PAYPAL_PAYMENT_INTERFACE_NAME or not amount_in_cents or not ct_transaction_interaction_id:
return PipelineCommand.CONTINUE.value

if has_been_refunded:
Expand All @@ -66,16 +68,19 @@ def run_filter(
'refund_response': "charge_already_refunded"
}

paypal_client = PayPalClient()
try:
paypal_refund_response = paypal_client.refund_order(order_id=order_id)
paypal_client = PayPalClient()
paypal_refund_response = paypal_client.refund_order(capture_id=ct_transaction_interaction_id)
print('\n\n\n\n\n paypal_refund_response = ', paypal_refund_response)
return {
'refund_response': paypal_refund_response
'refund_response': paypal_refund_response,
}
except Exception as ex:
logger.info(f'[CT-{tag}] Unsuccessful PayPal refund with details:'
f'[order_id: {order_id}'
f'message_id: {kwargs["message_id"]}')
raise Exception from ex
logger.error(f'[CT-{tag}] Unsuccessful PayPal refund with details: '
f'[order_id: {order_id} '
f'message_id: {kwargs["message_id"]} '
f'exception: {ex}')

raise RequestException(str(ex))


5 changes: 4 additions & 1 deletion commerce_coordinator/apps/stripe/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,11 @@ def run_filter(
"""

tag = type(self).__name__
print('\n\n\n\n\n\nRefundPaymentIntent psp = ', psp)
print('\n\n\n\n\n\nRefundPaymentIntent payment_intent_id = ', payment_intent_id)
print('\n\n\n\n\n\nRefundPaymentIntent amount_in_cents = ', amount_in_cents)

if psp != EDX_STRIPE_PAYMENT_INTERFACE_NAME and not payment_intent_id or not amount_in_cents: # pragma: no cover
if psp != EDX_STRIPE_PAYMENT_INTERFACE_NAME or not payment_intent_id or not amount_in_cents: # pragma: no cover
logger.info(f'[{tag}] payment_intent_id or amount_in_cents not set, skipping.')
return PipelineCommand.CONTINUE.value

Expand Down
4 changes: 2 additions & 2 deletions commerce_coordinator/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,8 @@ def root(*path_fragments):
'paypal': {
'user_activity_page_url': '',
'paypal_webhook_id': PAYPAL_WEBHOOK_ID,
'client_id': '',
'client_secret': '',
'client_id': 'ASoOt8z1BmLEzJGLV-N_gWP083ghlpWaj9eOj4BxQ9k8rQ-jDoSO5e_5-gRR3uzwp-hOt_YmfzKsnrFV',
'client_secret': 'EL_StzjNHS0lUbtVLPOUxC-fa27E4x12WIAN4XRHjYNNYM3kkUNxXoaFd_XextoDC1h3TvF9vuC74J1Z',
},
},
}
Expand Down
4 changes: 2 additions & 2 deletions commerce_coordinator/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@
'paypal': {
'user_activity_page_url': 'https://sandbox.paypal.com/myaccount/activities/',
'paypal_webhook_id': 'SET-ME-PLEASE',
'client_id': '',
'client_secret': '',
'client_id': 'ASoOt8z1BmLEzJGLV-N_gWP083ghlpWaj9eOj4BxQ9k8rQ-jDoSO5e_5-gRR3uzwp-hOt_YmfzKsnrFV',
'client_secret': 'EL_StzjNHS0lUbtVLPOUxC-fa27E4x12WIAN4XRHjYNNYM3kkUNxXoaFd_XextoDC1h3TvF9vuC74J1Z',
},
},
}
Expand Down
6 changes: 6 additions & 0 deletions commerce_coordinator/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
from commerce_coordinator.apps.titan import urls as titan_urls
from commerce_coordinator.settings.base import FAVICON_URL

from commerce_coordinator.apps.paypal.clients import PayPalClient

paypal_client = PayPalClient()

admin.autodiscover()

urlpatterns = oauth2_urlpatterns + [
Expand Down Expand Up @@ -70,6 +74,7 @@
re_path(r'^$', lambda r: JsonResponse(data=[
"Welcome to Commerce Coordinator",
"This is an API app that provides a backend for Commerce.",
str(paypal_client),
], status=status.HTTP_200_OK, safe=False), name='root'),

path('favicon.ico', RedirectView.as_view(url=FAVICON_URL), name='favicon'),
Expand All @@ -84,3 +89,4 @@
import debug_toolbar

urlpatterns.append(re_path(r'^__debug__/', include(debug_toolbar.urls)))

0 comments on commit 86b61a5

Please sign in to comment.