fps_integration.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. """ Amazon FPS integration,
  2. currently not used. due to issues with Taxes """
  3. import urlparse
  4. import urllib
  5. import datetime
  6. import time
  7. import logging
  8. from django.utils.decorators import method_decorator
  9. from django.views.decorators.csrf import csrf_exempt
  10. from django.views.decorators.http import require_POST
  11. from django.core.urlresolvers import reverse
  12. from django.http import HttpResponseForbidden, HttpResponseRedirect, HttpResponse
  13. from billing.integrations.amazon_fps_integration import (
  14. AmazonFpsIntegration as Integration,
  15. )
  16. from billing.models import AmazonFPSResponse
  17. from billing.signals import transaction_was_successful, transaction_was_unsuccessful
  18. from store_order.models import Order, OrderPayment
  19. from cart import cart
  20. csrf_exempt_m = method_decorator(csrf_exempt)
  21. require_POST_m = method_decorator(require_POST)
  22. LOGGER = logging.getLogger("fps_integration")
  23. class FpsIntegration(Integration):
  24. @csrf_exempt_m
  25. @require_POST_m
  26. def fps_ipn_handler(self, request):
  27. LOGGER.debug("In fps_ipn_handler")
  28. uri = request.build_absolute_uri()
  29. parsed_url = urlparse.urlparse(uri)
  30. LOGGER.debug("[fps_ipn_handler] verify signiture")
  31. v_resp = self.fps_connection.verify_signature(
  32. UrlEndPoint="%s://%s%s"
  33. % (parsed_url.scheme, parsed_url.netloc, parsed_url.path),
  34. HttpParameters=request.raw_post_data,
  35. )
  36. LOGGER.debug("[fps_ipn_handler] v_resp = ".format(v_resp))
  37. LOGGER.debug(
  38. "[fps_ipn_handler] v_resp.VerifySignatureResult = ".format(
  39. v_resp.VerifySignatureResult
  40. )
  41. )
  42. LOGGER.debug(
  43. "[fps_ipn_handler] v_resp.VerifySignatureResult.VerificationStatus = ".format(
  44. v_resp.VerifySignatureResult.VerificationStatus
  45. )
  46. )
  47. if not v_resp.VerifySignatureResult.VerificationStatus == "Success":
  48. LOGGER.debug("[fps_ipn_handler] Signature bad")
  49. return HttpResponseForbidden()
  50. LOGGER.debug("[fps_ipn_handler] Signature good")
  51. data = dict(map(lambda x: x.split("="), request.raw_post_data.split("&")))
  52. LOGGER.debug("[fps_ipn_handler] data: {0}".format(data))
  53. for (key, val) in data.iteritems():
  54. data[key] = urllib.unquote_plus(val)
  55. if AmazonFPSResponse.objects.filter(
  56. transactionId=data["transactionId"]
  57. ).count():
  58. LOGGER.debug("[fps_ipn_handler] have an object already")
  59. resp = AmazonFPSResponse.objects.get(transactionId=data["transactionId"])
  60. else:
  61. LOGGER.debug("[fps_ipn_handler] no object create one")
  62. resp = AmazonFPSResponse()
  63. for (key, val) in data.iteritems():
  64. attr_exists = hasattr(resp, key)
  65. if attr_exists and not callable(getattr(resp, key, None)):
  66. if key == "transactionDate":
  67. # TODO: add timezone info .gets this RuntimeWarning: DateTimeField received a naive datetime (2013-02-03 10:58:51) while time zone support is active.
  68. val = datetime.datetime(*time.localtime(float(val))[:6])
  69. setattr(resp, key, val)
  70. resp.save()
  71. LOGGER.debug("[fps_ipn_handler] saved object")
  72. if resp.statusCode == "Success":
  73. LOGGER.debug("[fps_ipn_handler] success")
  74. transaction_was_successful.send(
  75. sender=self.__class__, type=data["operation"], response=resp
  76. )
  77. else:
  78. LOGGER.debug(
  79. "[fps_ipn_handler] not success it is {0}".format(resp.statusCode)
  80. )
  81. if not "Pending" in resp.statusCode:
  82. LOGGER.debug("[fps_ipn_handler] send unsuccessful signal")
  83. transaction_was_unsuccessful.send(
  84. sender=self.__class__, type=data["operation"], response=resp
  85. )
  86. # Associate the amazon payment with our order from before.
  87. # TODO: this needs to be fully tested.. all scenerios
  88. # new payments and updates.
  89. LOGGER.debug("[fps_ipn_handler] add info to Order ")
  90. try:
  91. LOGGER.debug("Cart_id = {0}".format(resp.callerReference))
  92. order = Order.objects.get(cart_id=resp.callerReference)
  93. try:
  94. order_payment = order.orderpayment
  95. except OrderPayment.DoesNotExist:
  96. LOGGER.debug("Order_payment does't exist add one")
  97. order_payment = OrderPayment()
  98. order.orderpayment = order_payment
  99. LOGGER.debug("order_payment = {0}".format(order_payment))
  100. try:
  101. amazon_payment = order_payment.amazon_payment
  102. LOGGER.debug(
  103. "There is an amazon_payment already {0}".format(amazon_payment)
  104. )
  105. if not amazon_payment:
  106. LOGGER.debug("Amazon payment is null, need to set it.")
  107. order_payment.amazon_payment = resp
  108. except AmazonFPSResponse.DoesNotExist:
  109. LOGGER.debug("amazon_payment does't exist add one")
  110. order_payment.amazon_payment = resp
  111. LOGGER.debug("Save order payment")
  112. order_payment.save()
  113. LOGGER.debug("Set order status to submitted")
  114. order.status = Order.SUBMITTED
  115. # TODO: Make sure status is set correctly.
  116. order.save()
  117. except Exception as e:
  118. # TODO log error, send email.
  119. LOGGER.debug("Error = {0}".format(e))
  120. # Return a HttpResponse to prevent django from complaining
  121. LOGGER.debug("[fps_ipn_handler] Done")
  122. return HttpResponse(resp.statusCode)
  123. def transaction(self, request):
  124. """Ideally at this method, you will check the
  125. caller reference against a user id or uniquely
  126. identifiable attribute (if you are already not
  127. using it as the caller reference) and the type
  128. of transaction (either pay, reserve etc). For
  129. the sake of the example, we assume all the users
  130. get charged $100"""
  131. """
  132. {'status': 'SC',
  133. 'city': 'Dallas',
  134. 'signatureVersion': '2',
  135. 'zip': '73933',
  136. 'tokenID': 'F3B8EXIKM4RMLDLRDIHH3LGPTSLAMHTPJMQBEUBCFH24HAAZ339CSD2S8RR9LNPF',
  137. 'country': 'United+States',
  138. 'signature': 'Wc038ij3U0ZmUmKgiFq455WQPz0q7D9TTfUsxNx8WC6Rk%2FGBpGEiFb4gSnQBxY437oAKqEgoaVMF%0AVoWaKw%2Fmp0b88N%2BQpW048l%2FFbgaWr%2FSz3Vs5AamL0JrDfJ7nd3iF3%2BtPU3gmG4D2qfTwBHu%2FQlLk%0A3bHukecNPRpcmPo1jJQ%3D',
  139. 'state': 'TX',
  140. 'certificateUrl': 'https%3A%2F%2Ffps.sandbox.amazonaws.com%2Fcerts%2F090911%2FPKICert.pem%3FrequestId%3D1mmly3b6mqxve2fuq5vof9sb27gj2nbgt4e0ipj3ff5sxbmo1j',
  141. 'expiry': '01%2F2015',
  142. 'signatureMethod': 'RSA-SHA1',
  143. 'callerReference': '366dcf11-6111-4efb-ac1a-0d0f906cbc62',
  144. 'addressLine2': 'Apt.+2B+-+92+DfkR',
  145. 'addressLine1': '123+Main+St%2C+200+EduFeG',
  146. 'phoneNumber': '5551234567',
  147. 'addressName': 'Ken+Cochrane'}
  148. """
  149. request_url = request.build_absolute_uri()
  150. LOGGER.debug("request_url = {0}".format(request_url))
  151. parsed_url = urlparse.urlparse(request_url)
  152. LOGGER.debug("parsed_url = {0}".format(parsed_url))
  153. query = parsed_url.query
  154. LOGGER.debug(query)
  155. # resp = self.purchase(100, data)
  156. LOGGER.debug("---")
  157. data = dict(map(lambda x: x.split("="), query.split("&")))
  158. LOGGER.debug(data)
  159. LOGGER.debug("---")
  160. for (key, val) in data.iteritems():
  161. data[key] = urllib.unquote_plus(val)
  162. # if AmazonFPSResponse.objects.filter(transactionId=data["transactionId"]).count():
  163. # resp = AmazonFPSResponse.objects.get(transactionId=data["transactionId"])
  164. # else:
  165. # resp = AmazonFPSResponse()
  166. # data['TransactionAmount'] = '100'
  167. # data['TransactionAmount.Value'] = 1
  168. LOGGER.debug(data)
  169. LOGGER.debug("session_key = {0}".format(request.session.session_key))
  170. shopping_cart = cart.get_cart(request)
  171. LOGGER.debug("Cart = {0}".format(shopping_cart))
  172. order = Order.objects.get(cart_id=shopping_cart.cart_id)
  173. LOGGER.debug("Order = {0}".format(order))
  174. order.phone = data.get("phoneNumber", None)
  175. order.shipping_name = data.get("addressName", None)
  176. order.shipping_address_1 = data.get("addressLine1", None)
  177. order.shipping_address_2 = data.get("addressLine2", None)
  178. order.shipping_city = data.get("city", None)
  179. order.shipping_state = data.get("state", None)
  180. order.shipping_country = data.get("country", None)
  181. order.shipping_zip = data.get("zip", None)
  182. order.billing_name = data.get("addressName", None)
  183. order.billing_address_1 = data.get("addressLine1", None)
  184. order.billing_address_2 = data.get("addressLine2", None)
  185. order.billing_city = data.get("city", None)
  186. order.billing_state = data.get("state", None)
  187. order.billing_country = data.get("country", None)
  188. order.billing_zip = data.get("zip", None)
  189. order.save()
  190. # TODO: order.total needs to be more then 0.0 if not, problem.
  191. resp = self.purchase(order.total, data)
  192. LOGGER.debug(resp["status"])
  193. return HttpResponseRedirect(
  194. "%s?status=%s" % (reverse("checkout_receipt"), resp["status"])
  195. )