diff --git a/src/hope_payment_gateway/apps/fsp/western_union/api/client.py b/src/hope_payment_gateway/apps/fsp/western_union/api/client.py index 5bc517c3..48452b50 100644 --- a/src/hope_payment_gateway/apps/fsp/western_union/api/client.py +++ b/src/hope_payment_gateway/apps/fsp/western_union/api/client.py @@ -52,6 +52,10 @@ def __init__(self) -> None: self.quote_client = Client(quote_wsdl, transport=transport, settings=settings) self.quote_client.set_ns_prefix("xrsi", "http://www.westernunion.com/schema/xrsi") + status_wsdl = str(Path(__file__).parent / "wsdl" / "PayStatus_Service_H2HService.wsdl") + self.status_client = Client(status_wsdl, transport=transport, settings=settings) + self.status_client.set_ns_prefix("xrsi", "http://www.westernunion.com/schema/xrsi") + transaction_wsdl = str(Path(__file__).parent / "wsdl" / "SendMoneyStore_Service_H2HService.wsdl") self.transaction_client = Client(transaction_wsdl, transport=transport, settings=settings) self.transaction_client.set_ns_prefix("xrsi", "http://www.westernunion.com/schema/xrsi") @@ -314,8 +318,30 @@ def create_transaction(self, base_payload, update=True): return pr def query_status(self, transaction_id, update): - # western union does not have an API to address this - pass + pr = PaymentRecord.objects.get( + fsp_code=transaction_id, parent__fsp__vendor_number=config.WESTERN_UNION_VENDOR_NUMBER + ) + wu_env = config.WESTERN_UNION_WHITELISTED_ENV + frm = pr.extra_data.get("foreign_remote_system", None) + mtcn = pr.extra_data.get("mtcn", None) + payload = { + "channel": {"type": "H2H", "name": "CHANNEL", "version": "9500"}, + "mtcn": mtcn, + "foreign_remote_system": frm, + } + response = self.response_context(self.status_client, "PayStatus", payload, f"SOAP_HTTP_Port_{wu_env}") + if update: + wu_status = response["content"]["payment_transactions"]["payment_transaction"][0]["pay_status_description"] + flow = PaymentRecordFlow(pr) + status = {"PAID": PaymentRecordState.TRANSFERRED_TO_BENEFICIARY}.get(wu_status, None) + if pr.status != status: + if status in [PaymentRecordState.TRANSFERRED_TO_BENEFICIARY]: + pr.message = "Payment Record update by manual sync" + pr.success = True + flow.confirm() + pr.save() + + return response def search_request(self, frm, mtcn): payload = FinancialServiceProvider.objects.get( diff --git a/src/hope_payment_gateway/apps/fsp/western_union/api/wsdl/PayStatus_Service_H2HService.wsdl b/src/hope_payment_gateway/apps/fsp/western_union/api/wsdl/PayStatus_Service_H2HService.wsdl new file mode 100644 index 00000000..59cc8282 --- /dev/null +++ b/src/hope_payment_gateway/apps/fsp/western_union/api/wsdl/PayStatus_Service_H2HService.wsdl @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/hope_payment_gateway/apps/gateway/admin.py b/src/hope_payment_gateway/apps/gateway/admin.py index d198aea8..5d2ce72a 100644 --- a/src/hope_payment_gateway/apps/gateway/admin.py +++ b/src/hope_payment_gateway/apps/gateway/admin.py @@ -79,6 +79,8 @@ def western_union(self, button): self.wu_prepare_payload, self.wu_send_money_validation, self.wu_send_money, + self.wu_status, + self.wu_status_update, self.wu_search_request, self.wu_cancel, ] @@ -127,6 +129,26 @@ def wu_send_money(self, request, pk) -> TemplateResponse: loglevel = messages.SUCCESS if log.success else messages.ERROR messages.add_message(request, loglevel, log.message) + @view(html_attrs={"style": "background-color:yellow;color:blue"}, label="Check Status") + def wu_status(self, request, pk) -> TemplateResponse: + context = self.get_common_context(request, pk) + obj = PaymentRecord.objects.get(pk=pk) + if mtcn := obj.extra_data.get("mtcn", None): + context["msg"] = f"Search request through MTCN \n" f"PARAM: mtcn {mtcn}" + context.update(WesternUnionClient().query_status(obj.fsp_code, False)) + return TemplateResponse(request, "request.html", context) + messages.warning(request, "Missing MTCN") + + @view(html_attrs={"style": "background-color:yellow;color:blue"}, label="Status Update") + def wu_status_update(self, request, pk) -> TemplateResponse: + context = self.get_common_context(request, pk) + obj = PaymentRecord.objects.get(pk=pk) + if mtcn := obj.extra_data.get("mtcn", None): + context["msg"] = f"Search request through MTCN \n" f"PARAM: mtcn {mtcn}" + context.update(WesternUnionClient().query_status(obj.fsp_code, True)) + return TemplateResponse(request, "request.html", context) + messages.warning(request, "Missing MTCN") + @view(html_attrs={"style": "background-color:yellow;color:blue"}, label="Search Request") def wu_search_request(self, request, pk) -> TemplateResponse: context = self.get_common_context(request, pk) diff --git a/tests/western_union/endpoints/status.yaml b/tests/western_union/endpoints/status.yaml new file mode 100644 index 00000000..b4fd36fd --- /dev/null +++ b/tests/western_union/endpoints/status.yaml @@ -0,0 +1,25 @@ +responses: +- response: + auto_calculate_content_length: false + body: ' + + UNICEFCONTEALBERTO100000SDSDG12/18/24 + 04:41:181048645159PAIDIDENTIFIERREFNOCOUNTER111' + content_type: text/plain + headers: + Content-Security-Policy: 'frame-ancestors *;script-src ''self'' ''unsafe-inline'' + ''unsafe-eval'' ; style-src ''self'' ''unsafe-inline'' ; img-src ''self'' + data: ; connect-src ''self'' wss:;' + Transfer-Encoding: chunked + X-Backside-Transport: OK OK + X-Content-Type-Options: nosniff + X-Frame-Options: SAMEORIGIN + X-Global-Transaction-ID: 4bc148eb6762b637012641b4 + X-XSS-Protection: 1; mode=block + method: POST + status: 200 + url: https://wugateway2pi.westernunion.com/PayStatus_Service_H2H diff --git a/tests/western_union/endpoints/test_status.py b/tests/western_union/endpoints/test_status.py new file mode 100644 index 00000000..26f6573c --- /dev/null +++ b/tests/western_union/endpoints/test_status.py @@ -0,0 +1,38 @@ +import responses +from constance.test import override_config +from factories import PaymentRecordFactory + +from hope_payment_gateway.apps.fsp.western_union.api.client import WesternUnionClient +from hope_payment_gateway.apps.gateway.models import PaymentRecordState + + +# @_recorder.record(file_path="tests/western_union/endpoints/status.yaml") +@responses.activate +@override_config(WESTERN_UNION_VENDOR_NUMBER="12345") +def test_status(django_app, admin_user, wu): + responses.patch("https://wugateway2pi.westernunion.com/Search_Service_H2H") + responses._add_from_file(file_path="tests/western_union/endpoints/status.yaml") + ref_no, mtcn, frm = ( + "Y3snz233UkGt1Gw4", + "8560724095", + { + "identifier": "IDENTIFIER", + "reference_no": "REFNO", + "counter_id": "COUNTER", + }, + ) + pr = PaymentRecordFactory( + fsp_code=mtcn, + record_code=ref_no, + extra_data={ + "mtcn": mtcn, + "foreign_remote_system": frm, + "channel": {"type": "H2H", "name": "TEST", "version": "9500"}, + }, + parent__fsp=wu, + status=PaymentRecordState.TRANSFERRED_TO_FSP, + ) + resp = WesternUnionClient().query_status(pr.fsp_code, True) + pr.refresh_from_db() + assert pr.status == PaymentRecordState.TRANSFERRED_TO_BENEFICIARY + assert (resp["title"], resp["code"]) == ("PayStatus", 200)