forked from braintree/braintree_python
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtransparent_redirect_gateway.py
More file actions
81 lines (67 loc) · 3.21 KB
/
transparent_redirect_gateway.py
File metadata and controls
81 lines (67 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import cgi
from datetime import datetime
import urllib
import braintree
from braintree.util.crypto import Crypto
from braintree.error_result import ErrorResult
from braintree.exceptions.forged_query_string_error import ForgedQueryStringError
from braintree.util.http import Http
from braintree.successful_result import SuccessfulResult
from braintree.transparent_redirect import TransparentRedirect
class TransparentRedirectGateway(object):
def __init__(self, gateway):
self.gateway = gateway
self.config = gateway.config
def confirm(self, query_string):
"""
Confirms a transparent redirect request. It expects the query string from the
redirect request. The query string should _not_ include the leading "?" character. ::
result = braintree.TransparentRedirect.confirm("foo=bar&id=12345")
"""
parsed_query_string = self._parse_and_validate_query_string(query_string)
confirmation_gateway = {
TransparentRedirect.Kind.CreateCustomer: "customer",
TransparentRedirect.Kind.UpdateCustomer: "customer",
TransparentRedirect.Kind.CreatePaymentMethod: "credit_card",
TransparentRedirect.Kind.UpdatePaymentMethod: "credit_card",
TransparentRedirect.Kind.CreateTransaction: "transaction"
}[parsed_query_string["kind"][0]]
return getattr(self.gateway, confirmation_gateway)._post("/transparent_redirect_requests/" + parsed_query_string["id"][0] + "/confirm")
def tr_data(self, data, redirect_url):
data = self.__flatten_dictionary(data)
date_string = datetime.utcnow().strftime("%Y%m%d%H%M%S")
data["time"] = date_string
data["redirect_url"] = redirect_url
data["public_key"] = self.config.public_key
data["api_version"] = self.config.api_version()
tr_content = urllib.urlencode(data)
tr_hash = Crypto.hmac_hash(self.config.private_key, tr_content)
return tr_hash + "|" + tr_content
def url(self):
"""
Returns the url for POSTing Transparent Redirect HTML forms
"""
return self.config.base_merchant_url() + "/transparent_redirect_requests"
def _parse_and_validate_query_string(self, query_string):
query_params = cgi.parse_qs(query_string)
http_status = int(query_params["http_status"][0])
message = query_params.get("bt_message")
if message != None:
message = message[0]
if Http.is_error_status(http_status):
Http.raise_exception_from_status(http_status, message)
if not self._is_valid_tr_query_string(query_string):
raise ForgedQueryStringError
return query_params
def _is_valid_tr_query_string(self, query_string):
content, hash = query_string.split("&hash=")
return hash == Crypto.hmac_hash(self.config.private_key, content)
def __flatten_dictionary(self, params, parent=None):
data = {}
for key, val in params.iteritems():
full_key = parent + "[" + key + "]" if parent else key
if isinstance(val, dict):
data.update(self.__flatten_dictionary(val, full_key))
else:
data[full_key] = val
return data