neonua666

paypal_utils.py

May 8th, 2017
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.36 KB | None | 0 0
  1. import logging
  2. import requests
  3. import time
  4. from django.utils import timezone
  5. from django.conf import settings
  6. from .models import PayPalExtraPayment, PaypalToken
  7.  
  8.  
  9. SUCCESS_STATUS = requests.codes.ok  # 200
  10. UNAUTHORIZED_STATUS = requests.codes.unauthorized  # 401
  11. APPROVED = 'approved'
  12. env_paypal_param = {
  13.         True: 'sandbox',
  14.         False: 'production'
  15.         }
  16.  
  17. logger = logging.getLogger(__name__)
  18.  
  19.  
  20. def create_access_token():
  21.     """ Creating paypal access token.
  22.    Request:
  23.        Url is 'https://api.sandbox.paypal.com/v1/oauth2/token' for sandbox.
  24.        Auth are paypal client id and client secret.
  25.    Response:
  26.        Status and token.
  27.        If status not 200 - write to the 'err' status and error description.
  28.    Return:
  29.        Paypal token and errors.
  30.    More: 'https://developer.paypal.com/docs/integration/direct/make-your-first-call/#get-an-access-token'
  31.    """
  32.     logger.info("Start creating paypal access token")
  33.  
  34.     paypaltoken = None
  35.     err = None
  36.  
  37.     # request data
  38.     url = settings.PAYPAL_URL_TOKEN
  39.     auth = (settings.PAYPAL_CLIENT_ID, settings.PAYPAL_SECRET)
  40.     headers = {'Accept': 'application/json', 'Accept-Language': 'en_US'}
  41.     data = "grant_type=client_credentials"
  42.  
  43.     # get response data
  44.     response = requests.post(url, auth=auth, headers=headers, data=data, timeout=10)
  45.     response_data = response.json()
  46.  
  47.     # Check response status
  48.     if response.status_code == SUCCESS_STATUS:
  49.         logger.info("Status 200. Start creating paypal access token")
  50.  
  51.         # Save token to db
  52.         paypaltoken = PaypalToken.objects.create(
  53.             access_token=response_data['access_token'],
  54.             access_token_exp=response_data['expires_in'],
  55.             access_token_type=response_data['token_type'],
  56.         )
  57.     else:
  58.         err = {response_data['error']: response_data['error_description']}
  59.     return paypaltoken, err
  60.  
  61.  
  62. def get_access_token():
  63.     """ Receiving paypal access token(AT). If AT not in DB or AT is expired
  64.    or difference in time is 5 sec - create a request to receive new access token.
  65.    Return:
  66.        Token and errors.
  67.    """
  68.     logger.info("Starting get access paypal token")
  69.     err = None
  70.  
  71.     # Get last token from db
  72.     token = PaypalToken.objects.last()
  73.  
  74.     if token is not None:
  75.         logger.debug("Paypal token founded in DB")
  76.  
  77.         # difference time
  78.         token_created_sec = time.mktime(token.created.timetuple())
  79.         token_total_sec = token_created_sec+token.access_token_exp
  80.         now_sec = time.mktime(timezone.now().timetuple())
  81.         diff_sec = token_total_sec - now_sec
  82.         logger.debug('diff_sec: {}'.format(diff_sec))
  83.  
  84.         if int(diff_sec) <= 0:
  85.             token, err = create_access_token()
  86.     else:
  87.         token, err = create_access_token()
  88.     return token, err
  89.  
  90.  
  91. def get_payment_response(payment, token):
  92.     """ Check paypal payment from payment id and access token.
  93.        Requests:
  94.            url - 'https://api.sandbox.paypal.com/v1/payments/payment/{payment_id}' from sandbox.
  95.            headers - 'Authorization: <token_type> <access_token>'.
  96.        Response:
  97.            response status and payment data.
  98.        Return:
  99.            response data and errors.
  100.        More: 'https://developer.paypal.com/docs/api/payments/#payment_get'
  101.        """
  102.  
  103.     url = settings.PAYPAL_URL_PAYMENT + payment.payment_id
  104.     headers = {
  105.         'Content-Type': 'application/json',
  106.         'Authorization': '{0} {1}'.format(token.access_token_type, token.access_token)
  107.     }
  108.  
  109.     # get response data
  110.     response = requests.get(url, headers=headers, timeout=10)
  111.     return response
  112.  
  113.  
  114. def get_payment_data(payment, token):
  115.     """Get payment data
  116.    """
  117.     response_data = None
  118.     err = None
  119.  
  120.     # request data
  121.     for i in range(3):
  122.         err = None
  123.         response = get_payment_response(payment, token)
  124.  
  125.         if response.status_code == SUCCESS_STATUS:
  126.             response_data = response.json()
  127.             break
  128.  
  129.         elif response.status_code == UNAUTHORIZED_STATUS:
  130.             err = {response_data['error']: response_data['error_description']}
  131.     return response_data, err
  132.  
  133.  
  134. def check_payment(payment_state, transactions, order_id):
  135.     """Check validated payment
  136.    Return:
  137.        errors
  138.    """
  139.     err = None
  140.     if payment_state != APPROVED:
  141.         err = {'Check status': 'not approved!'}
  142.     elif int(order_id) != int(transactions['invoice_number']):
  143.         logger.debug('order id not eq transacrion order id!')
  144.         err = {'Check status': 'order id not eq transacrion order id!'}
  145.     return err
  146.  
  147.  
  148. def process_express(request, order):
  149.     """ Payment process through paypal.
  150.    Saving payment to the database.
  151.    Return:
  152.        paypal extra payment and errors
  153.    """
  154.     logger.info('Start process extrapaypall expert')
  155.  
  156.     err = None
  157.     paypal_extra_payment = None
  158.  
  159.     data = request.POST
  160.  
  161.     # Get access token
  162.     token, token_err = get_access_token()
  163.     if token_err:
  164.         logger.info("Get access token has some errors: {}".format(token_err))
  165.         return paypal_extra_payment, token_err
  166.  
  167.     logger.debug('Token is {}'.format(token))
  168.  
  169.     # Begin creating a record in the table PayPalExtraPayment
  170.     paypal_extra_payment = PayPalExtraPayment(
  171.         payment_id=data['paymentID'],
  172.         payer_id=data['payerID'],
  173.         payment_token=data['paymentToken'],
  174.         return_url=data['returnUrl'],
  175.         access_token=token,
  176.         payer_ip=request.META.get('HTTP_X_FORWARDED_FOR')
  177.     )
  178.  
  179.     # Get payment details
  180.     payment_data, payment_err = get_payment_data(paypal_extra_payment, token)
  181.     if payment_err:
  182.         logger.info("Valid has some errors: {}".format(payment_err))
  183.         return paypal_extra_payment, payment_err
  184.  
  185.     transactions = payment_data['transactions'][0]
  186.  
  187.     # Check paypal payment
  188.     check_error = check_payment(payment_data['state'], transactions, order.id)
  189.     if check_error:
  190.  
  191.         logger.info("Valid has some errors: {}".format(payment_err))
  192.         return paypal_extra_payment, check_error
  193.  
  194.     payer = payment_data['payer']
  195.     related_resources = transactions['related_resources'][0]['sale']
  196.  
  197.     # Data to DB
  198.     paypal_extra_payment.order = order
  199.  
  200.     paypal_extra_payment.raw_data = payment_data
  201.     paypal_extra_payment.payment_date = payment_data['create_time']
  202.     paypal_extra_payment.status = payment_data['state']
  203.  
  204.     paypal_extra_payment.merchant_id = transactions['payee']['merchant_id']
  205.     paypal_extra_payment.invoice_number = transactions['invoice_number']
  206.     paypal_extra_payment.items = transactions['description']
  207.     paypal_extra_payment.currency = transactions['amount']['currency']
  208.     paypal_extra_payment.price_total = transactions['amount']['total']
  209.     paypal_extra_payment.price_subtotal = transactions['amount']['details']['subtotal']
  210.     paypal_extra_payment.price_fee = related_resources['transaction_fee']['value']
  211.     paypal_extra_payment.payer_info = payer['payer_info']
  212.     paypal_extra_payment.payer_first_name = payer['payer_info']['first_name']
  213.     paypal_extra_payment.payer_last_name = payer['payer_info']['last_name']
  214.     paypal_extra_payment.payer_email = payer['payer_info']['email']
  215.  
  216.     paypal_extra_payment.save()
  217.     logger.info('Paypal extra payment created: {}'.format(paypal_extra_payment))
  218.  
  219.     return paypal_extra_payment, err
Add Comment
Please, Sign In to add comment