예제 #1
0
    def __init__(self, request, form_template="django_paypal_centinel/centinel_form.html/", error_template=""):
        """ Initialise the wrapper """

        self.request = request
        self.client = CentinelClient()
        #grab urls users have setup to redirect result of the transaction to.
        self.success_view = reverse(conf.SUCCESS_VIEW)
        self.error_view = reverse(conf.ERROR_VIEW)
        self.error_template = error_template
        self.form_template = form_template

        #Get the Centinel required values from settings.
        self.url = conf.URL
        self.return_url = conf.RETURN_URL
        #Add the retrieved values to the centinel client data.
        self.client.add_many({
            'ProcessorId': conf.PROCESSOR_ID,
            'MerchantId': conf.MERCHANT_ID,
            'TransactionPwd': conf.PASSWORD
        })
예제 #2
0
class Centinel(object):
    """ Wrapper for handling Centinel Authorisation """
    form_template = ""
    error_template = ""
    success_view = None
    return_url = ""
    request = None
    url = ""

    def __init__(self, request, form_template="django_paypal_centinel/centinel_form.html/", error_template=""):
        """ Initialise the wrapper """

        self.request = request
        self.client = CentinelClient()
        #grab urls users have setup to redirect result of the transaction to.
        self.success_view = reverse(conf.SUCCESS_VIEW)
        self.error_view = reverse(conf.ERROR_VIEW)
        self.error_template = error_template
        self.form_template = form_template

        #Get the Centinel required values from settings.
        self.url = conf.URL
        self.return_url = conf.RETURN_URL
        #Add the retrieved values to the centinel client data.
        self.client.add_many({
            'ProcessorId': conf.PROCESSOR_ID,
            'MerchantId': conf.MERCHANT_ID,
            'TransactionPwd': conf.PASSWORD
        })

    def create_centinel_request(self, data_dict, card_details):
        """ Create centinel request """

        data_required_keys = (
                "Amount", "CurrencyCode",
                "OrderNumber"
                )

        card_required_keys = (
                "CardNumber", "CardExpDate"
                )

        #Check all the required names are present otherwise raise an error.
        for name in data_required_keys:
            if name not in data_dict.keys():
                raise ImproperlyConfigured("{0} is required".format(name))

        for name in card_required_keys:
            if name not in card_details.keys():
                raise ImproperlyConfigured("{0} is required".format(name))

        self.client.add_many({
            "CardExpMonth": card_details['CardExpDate'].strftime('%m'),
            "CardExpYear": card_details['CardExpDate'].year,
            "CardNumber": card_details['CardNumber'],
            "Version": "1.7",
            "TransactionType": "C"
            })

        self.order_id = data_dict['OrderNumber']

        for key, value in data_dict.iteritems():
            self.client.add(key, value)

    def centinel_lookup(self, data_dict, card_details):
        """ Create and do lookup request for centinel """
        self.card_details = card_details

        self.client.add("MsgType", "cmpi_lookup")
        self.create_centinel_request(data_dict, card_details)
        result = self.client.send_request(self.url)

        logger.debug(self.client.response)
        logger.debug(result)
        return self.centinel_lookup_response(result)

    def centinel_lookup_response(self, result):
        """ Response from centinel handler """

        if result == True:
            self.update_centinel_response_object()
            if (self.client.response['Enrolled'] == "N" or
                self.client.response['ACSUrl'] == ("U" or "N")):
                return self.return_success_view(self.client.response['TransactionId'])
            else:
                #Display the form view
                return self.return_card_form_view()
        else:
            #display the Error view
            return self.return_error_view(self)

    def return_card_form_view(self):
        """ Create and send request to merchant """
        import logging
        logger = logging.getLogger('informed.worldpay')
        logger.debug("creating form")
        logger.debug("payload: %s", self.client.response['Payload'])
        logger.debug("return url: %s", self.return_url + "%s/" % self.client.response['TransactionId'])

        forms = {}
        forms['centinel'] = CentinelForm(
                initial={
                    "PaReq": self.client.response['Payload'],
                    "TermUrl": self.return_url,
                    "MD": ""
                    }
                )

        logger.debug(self.request)
        logger

        forms['card_details'] = self.create_temp_form()
        return centinel_iframe(self.request, forms, self.client.response['ACSUrl'], self.form_template)

    def return_error_view(self, error=None):
        """ Return an error view """

        if error == None:
            error = self.client.response['ErrorDesc']

        logger.debug("returning error view")
        return self.error_view(self.request, error)

    def return_success_view(self, transaction_id):
        """ return the success view """
        cent_resp = CentinelResponse.objects.get(transaction_id=transaction_id)
        order_id = cent_resp.order_id

        ds_fields = {
                "AUTHSTATUS3DS": self.client.response.get('PAResStatus', None),
                "CAVV": self.client.response.get('Cavv', None),
                "ECI3DS": self.client.response['EciFlag'],
                "XID": self.client.response.get('Xid', None),
                }

        if self.client.response.get('Enrolled'):
            ds_fields["MPIVENDOR3DS"] = self.client.response['Enrolled']
        else:
            ds_fields["MPIVENDOR3DS"] = "N"
        return self.success_view(self.request, order_id, ds_fields, self.card_details)

    def centinel_authenticate(self, payload, transaction_id):
        """ Send authenticate request """

        self.client.add_many({
            "MsgType": "cmpi_authenticate",
            "Version": "1.7",
            "TransactionType": "C",
            "PAResPayload": payload,
            "TransactionId": transaction_id
        })
        result = self.client.send_request(self.url)
        logger.debug(self.client.response)

        self.retrieve_card_details()
        return self.centinel_authenticate_response(result, transaction_id)

    def update_centinel_response_object(self, transaction_id=None):
        """ Create or Update the centinel object associated with the order """
        enrolled = self.client.response.get('Enrolled', None)
        acs_url = self.client.response.get('ACSUrl', None)
        if transaction_id == None:
            transaction_id = self.client.response.get('TransactionId', None)

        logger.debug(self.client.response)
        logger.debug("trans_id: %s" % transaction_id)

        cent_resp, created = CentinelResponse.objects.get_or_create(pk=transaction_id)
        cent_resp.cavv = self.client.response.get('Cavv', None)
        cent_resp.xid = self.client.response.get('Xid', None)

        order_id = getattr(self, "order_id", None)
        if order_id:
            cent_resp.order_id = order_id

        if acs_url != ("U" or "N" or None):
            cent_resp.result = "waiting"
            cent_resp.eci3ds = enrolled
        else:
            if (self.client.response['SignatureVerification'] == "Y" or
                    enrolled == "N" or acs_url == ("U" or "N")):
                cent_resp.result = "passed"
            else:
                cent_resp.result = "rejected"
        cent_resp.save()

    def centinel_authenticate_response(self, result, transaction_id):
        """ Response from centinel authenticate request """
        self.update_centinel_response_object(transaction_id)
        if result == True:
            if (self.client.response['SignatureVerification'] == "Y" and
                self.client.response['PAResStatus'] != "N"):

                return self.return_success_view(transaction_id)
            else:
                return self.return_error_view(error="Sorry you are not eligible for authentication")
        else:
            return self.return_error_view("Error Authenticating")

    def create_temp_form(self):
        """ create form from card details and check validity"""

        card_details = {
                'card_no': self.card_details['CardNumber'],
                'start_date': self.card_details['CardStartDate'],
                'expiry_date': self.card_details['CardExpDate'],
                'sec_code': self.card_details['CardSecCode'],
                'issue_number': self.card_details['CardIssue'],
                'transaction_id': self.client.response['TransactionId']
                }

        form = CardDetailsForm(card_details)
        # make sure it's valid or let it raise a Validation Exception
        if form.is_valid():
            logger.debug("valid")
        else:
            logger.debug(form.errors)
        return form

    def retrieve_card_details(self):
        """ retrieve card details from instance """

        form = CardDetailsForm(self.request.POST)

        if form.is_valid():
            self.card_details = {
                'CardNumber': form.cleaned_data['card_no'],
                'CardStartDate': form.cleaned_data['start_date'],
                'CardExpDate': form.cleaned_data['expiry_date'],
                'CardSecCode': form.cleaned_data['sec_code'],
                'CardIssue': form.cleaned_data['issue_number'],
                }
            return True
        else:
            logger.debug(form.errors)
            return False