Skip to content

Commit

Permalink
upgrades
Browse files Browse the repository at this point in the history
  • Loading branch information
domdinicola committed Oct 4, 2024
1 parent dc6cccc commit a5420d3
Show file tree
Hide file tree
Showing 16 changed files with 576 additions and 440 deletions.
578 changes: 307 additions & 271 deletions pdm.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ includes = []
dev = [
"argh",
"black",
"django-regex",
"django-webtest",
"drf-api-checker",
"faker",
Expand All @@ -54,6 +55,7 @@ dev = [
"pytest-cov",
"pytest-django",
"pytest-echo",
"pytest-factoryboy",
"pytest-xdist",
"requests-mock",
"responses",
Expand Down Expand Up @@ -102,6 +104,7 @@ dependencies = [
"dj-static",
"drf-spectacular[sidecar]",
"factory-boy",
"flower",
"gunicorn",
"newrelic",
"natural-keys",
Expand All @@ -119,7 +122,6 @@ dependencies = [
"wheel",
"uwsgi",
"zeep",
"flower>=2.0.1",
]
name = "hope_payment_gateway"
version = "0.1"
Expand Down
2 changes: 2 additions & 0 deletions src/hope_payment_gateway/apps/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from hope_payment_gateway.apps.core.models import System, User

admin.site.site_header = "Payment Gateway"


@admin.register(User)
class UserAdminPlus(UserAdminPlus):
Expand Down
19 changes: 19 additions & 0 deletions src/hope_payment_gateway/apps/core/templates/request.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% extends "admin_extra_buttons/action_page.html" %}
{% load static %}

{% block content %}

<i>{% autoescape on %}
{{ msg | linebreaksbr }}
{% endautoescape %}
</i>

<pre>
{% if format == "json" %}
{{ content | pprint }}
{% else %}
{{ content }}
{% endif %}
</pre>

{% endblock %}
112 changes: 0 additions & 112 deletions src/hope_payment_gateway/apps/fsp/moneygram/auth.py

This file was deleted.

181 changes: 181 additions & 0 deletions src/hope_payment_gateway/apps/fsp/moneygram/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import base64
import json
import logging

from django.conf import settings

import phonenumbers
import requests
from phonenumbers import NumberParseException
from urllib3.connectionpool import HTTPSConnectionPool

from hope_payment_gateway.apps.core.models import Singleton
from hope_payment_gateway.apps.gateway.flows import PaymentRecordFlow
from hope_payment_gateway.apps.gateway.models import PaymentRecord

logger = logging.getLogger(__name__)


MONEYGRAM_DM_MAPPING = {
"WILL_CALL": "WILL_CALL",
"DIRECT_TO_ACCT": "DIRECT_TO_ACCT",
"BANK_DEPOSIT": "DIRECT_TO_ACCT",
}


class PayloadMissingKey(Exception):
pass


class MoneyGramClient(metaclass=Singleton):
token = ""
expires_in = None
token_response = None

def __init__(self):
self.get_token()

def get_token(self):
url = settings.MONEYGRAM_HOST + "/oauth/accesstoken?grant_type=client_credentials"
credentials = f"{settings.MONEYGRAM_CLIENT_ID}:{settings.MONEYGRAM_CLIENT_SECRET}"
encoded_credentials = base64.b64encode(credentials.encode("utf-8")).decode("utf-8")
headers = {"Content-Type": "application/json", "Authorization": "Basic " + encoded_credentials}

try:
response = requests.get(url, headers=headers)
except HTTPSConnectionPool:
self.token = None
self.token_response = None
else:
if response.status_code == 200:
parsed_response = json.loads(response.text)
self.token = parsed_response["access_token"]
self.expires_in = parsed_response["expires_in"]
else:
logger.warning("Invalid token")
self.token = None
self.token_response = response

def prepare_transaction(self, hope_payload):

raw_phone_no = hope_payload.get("phone_no", "N/A")
try:
phone_no = phonenumbers.parse(raw_phone_no, None)
phone_number = phone_no.national_number
country_code = phone_no.country_code
except NumberParseException:
phone_number = raw_phone_no
country_code = None

for key in [
"first_name",
"last_name",
"amount",
"destination_country",
"destination_currency",
"payment_record_code",
]:
if not (key in hope_payload.keys() and hope_payload[key]):
raise PayloadMissingKey("InvalidPayload: {} is missing in the payload".format(key))

return {
"targetAudience": "AGENT_FACING",
"agentPartnerId": settings.MONEYGRAM_PARTNER_ID,
"userLanguage": "en-US",
"destinationCountryCode": hope_payload["destination_country"],
# "destinationCountrySubdivisionCode": "US-NY",
"receiveCurrencyCode": hope_payload["destination_currency"],
"serviceOptionCode": hope_payload.get("delivery_services_code", "WILL_CALL"),
# "serviceOptionRoutingCode": "74261037", # TODO
"autoCommit": "true",
"sendAmount": {"currencyCode": hope_payload["origination_currency"], "value": hope_payload["amount"]},
"sender": {
"business": {
"businessName": "UNICEF",
"legalEntityName": "UNICEF",
"businessType": "ACCOMMODATION_HOTELS",
"businessRegistrationNumber": settings.MONEYGRAM_REGISTRATION_NUMBER,
"businessIssueDate": "2024-04-29",
"businessCountryOfRegistration": "USA",
"address": {
"line1": "3 United Nations Plaza",
"city": "NEW YORK",
"countrySubdivisionCode": "US-NY",
"countryCode": "USA",
"postalCode": 10017,
},
"contactDetails": {"phone": {"number": 2123267000, "countryDialCode": 1}},
}
},
"beneficiary": {
"consumer": {
"name": {
"firstName": hope_payload["first_name"],
"middleName": hope_payload.get("middle_name", ""),
"lastName": hope_payload["last_name"],
},
"address": {
"line1": hope_payload.get("address", "Via di Acilia"),
"city": hope_payload.get("city", "Roma"),
"countryCode": hope_payload["destination_country"],
"postalCode": 55442,
},
"mobilePhone": {"number": phone_number, "countryDialCode": country_code},
}
},
}

def create_transaction(self, hope_payload):

if self.token:

url = settings.MONEYGRAM_HOST + "/disbursement/v1/transactions"
payload = self.prepare_transaction(hope_payload)
headers = {
"Content-Type": "application/json",
"X-MG-ClientRequestId": hope_payload["payment_record_code"],
"Authorization": "Bearer " + self.token,
}

response = self.perform_request(url, headers, payload)
self.transaction_callback(hope_payload, response.json())
return response

else:
return self.token_response

def perform_request(self, url, headers, payload=None):
try:
response = requests.post(url, json=payload, headers=headers)

if response.status_code == 200:
parsed_response = json.dumps(json.loads(response.text), indent=2)
print(parsed_response)
else:
print("Request failed with status code:", response.status_code)
print(json.dumps(json.loads(response.text), indent=2))

except (requests.exceptions.RequestException, requests.exceptions.MissingSchema) as e:
print("An error occurred:", e)
response = dict

return response

def transaction_callback(self, hope_payload, response):
record_code = hope_payload["payment_record_code"]
pr = PaymentRecord.objects.get(record_code=record_code)
pr.fsp_code = response["referenceNumber"]
pr.success = True
pr.payout_amount = response["receiveAmount"]["amount"]["value"]
pr.extra_data.update(
{
"fee": response["receiveAmount"]["fees"]["value"],
"fee_currency": response["receiveAmount"]["fees"]["currencyCode"],
"taxes": response["receiveAmount"]["taxes"]["value"],
"taxes_currency": response["receiveAmount"]["taxes"]["currencyCode"],
"expectedPayoutDate": response["expectedPayoutDate"],
"transactionId": response["transactionId"],
}
)
flow = PaymentRecordFlow(pr)
flow.store()
2 changes: 1 addition & 1 deletion src/hope_payment_gateway/apps/fsp/moneygram/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from constance import config

from hope_payment_gateway.apps.fsp.moneygram.auth import MoneyGramClient
from hope_payment_gateway.apps.fsp.moneygram.client import MoneyGramClient
from hope_payment_gateway.apps.gateway.models import (
FinancialServiceProvider,
PaymentInstruction,
Expand Down
Loading

0 comments on commit a5420d3

Please sign in to comment.