fps_integration.py 9.5 KB

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