Beispiel #1
0
    def setError(self, errCode, errMsg, consumerMsg):
        """ setError
			Creates a new ErrorResponse object and populates it with the arguments

			@param unknown_type errCode		The error code to return. This is either a code from the platform or an internal code.
			@param unknown_type errMsg		The error message. This is not meant for display to the consumer.
			@param unknown_type consumerMsg	The consumer message. The error message to be shown to the user.
		"""
        self.error = ErrorResponse()
        self.error.setErrorCode(errCode)
        self.error.setErrorMessage(errCode)
        if len(consumerMsg):
            self.error.setConsumerMessage(consumerMsg)
        else:
            self.error.setConsumerMessage(IDEAL_PRV_GENERIC_ERRORMESSAGE)
Beispiel #2
0
    def GetIssuerList(self):
        self.clearError()
        configCheck = self.CheckConfig(self.config)

        if configCheck <> unicode('OK'):
            errorResponse = ErrorResponse()
            errorResponse.setErrorCode('001')
            errorResponse.setErrorMessage('Config error: %s' % configCheck)
            errorResponse.setConsumerMessage('')

            return errorResponse

        # Build up the XML header for this request
        xmlMsg = self.getXMLHeader('DirectoryReq', '', '', '', '')
        if not xmlMsg:
            return False

        xmlMsg += u"</DirectoryReq>\n"

        # Post the XML to the server.
        response = self.PostXMLData(xmlMsg)

        # If the response did not work out, return an ErrorResponse object.
        if not self.parseFromXml('errorCode', response) in ['', False]:
            errorResponse = ErrorResponse()

            errorResponse.setErrorCode(self.parseFromXml(
                'errorCode', response))
            errorResponse.setErrorMessage(
                self.parseFromXml('errorMessage', response))
            errorResponse.setConsumerMessage(
                self.parseFromXml('consumerMessage', response))

            return errorResponse

        if self.parseFromXml('acquirerID', response) == '':
            errorResponse = ErrorResponse()

            errorResponse.setErrorCode('ING1001')
            errorResponse.setErrorMessage('DirectoryList service probleem')
            errorResponse.setConsumerMessage('')

            return errorResponse

        # Create a new DirectoryResponse object with the required information
        res = DirectoryResponse()
        res.setAcquirerID(self.parseFromXml('acquirerID', response))
        res.setDirectoryDateTimeStamp(
            self.parseFromXml('directoryDateTimeStamp', response))

        # While there are issuers to be read from the stream
        while response.find('<issuerID>') is not -1:

            # Read the information for the next issuer.
            issuerID = self.parseFromXml('issuerID', response)
            issuerName = self.parseFromXml('issuerName', response)
            issuerList = self.parseFromXml('issuerList', response)

            # Create a new entry and add it to the list
            issuerEntry = IssuerEntry()
            issuerEntry.setIssuerID(issuerID)
            issuerEntry.setIssuerName(issuerName)
            issuerEntry.setIssuerListType(issuerList)
            res.addIssuer(issuerEntry)

            # Find the next issuer.
            response = response[response.find('</issuerList>') + 13:]

        return res
Beispiel #3
0
    def RequestTransactionStatus(self, transactionId):
        """ RequestTransactionStatus
			This public function makes a transaction status request

			@param string $transactionId	The transaction ID to query. (as returned from the TX request)
			@return An instance of AcquirerStatusResponse or FALSE on failure.
		"""
        self.clearError()
        configCheck = self.CheckConfig(self.config)

        if configCheck <> unicode('OK'):
            errorResponse = ErrorResponse()
            errorResponse.setErrorCode('001')
            errorResponse.setErrorMessage('Config error: %s' % configCheck)
            errorResponse.setConsumerMessage('')

            return errorResponse

        # check TransactionId length
        if not self.LengthCheck('TransactionID', transactionId,
                                16).lower() == 'ok'.lower():
            return self.getError()
        if not self.verifyNotNull(transactionId, 'transactionId'):
            return self.getError()

        # Build the status request XML.
        xmlMsg = self.getXMLHeader('AcquirerStatusReq', '', '', transactionId,
                                   '')
        if not xmlMsg:
            return False

        # Add transaction information.
        xmlMsg += u"<Transaction>\n<transactionID>%s</transactionID></Transaction>\n" % transactionId
        xmlMsg += u"</AcquirerStatusReq>\n"

        # Post the request to the server.
        response = self.PostXMLData(xmlMsg)
        # If the response did not work out, return an ErrorResponse object.
        if not self.parseFromXml('errorCode', response) in ['', False]:
            errorResponse = ErrorResponse()

            errorResponse.setErrorCode(self.parseFromXml(
                'errorCode', response))
            errorResponse.setErrorMessage(
                self.parseFromXml('errorMessage', response))
            errorResponse.setConsumerMessage(
                self.parseFromXml('consumerMessage', response))

            return errorResponse

        if self.parseFromXml('acquirerID', response) in ['', False]:
            errorResponse = ErrorResponse()

            errorResponse.setErrorCode('ING1001')
            errorResponse.setErrorMessage(
                'Status lookup mislukt (aquirer side)')
            errorResponse.setConsumerMessage('')

            return errorResponse

        # Build the status response object and pass the data into it.
        res = AcquirerStatusResponse()
        creationTime = self.parseFromXml('createDateTimeStamp', response)
        res.setAcquirerID(self.parseFromXml('acquirerID', response))
        res.setConsumerName(self.parseFromXml('consumerName', response))
        res.setConsumerAccountNumber(
            self.parseFromXml('consumerAccountNumber', response))
        res.setConsumerCity(self.parseFromXml('consumerCity', response))
        res.setTransactionID(self.parseFromXml('transactionID', response))

        # The initial status is INVALID, so that future modifications to
        # this or remote code will yield alarming conditions.
        res.setStatus(IDEAL_TX_STATUS_INVALID)
        status = self.parseFromXml('status', response)

        # Determine status identifier (case-insensitive).
        dStatus = {
            'Success': IDEAL_TX_STATUS_SUCCESS,
            'Cancelled': IDEAL_TX_STATUS_CANCELLED,
            'Expired': IDEAL_TX_STATUS_EXPIRED,
            'Failure': IDEAL_TX_STATUS_FAILURE,
            'Open': IDEAL_TX_STATUS_OPEN
        }

        for statuscode in dStatus.keys():
            if status.lower() == statuscode.lower():
                res.setStatus(dStatus[statuscode])
        # The verification of the response starts here.
        # The message as per the reference guide instructions.
        consumerAccountNumber = res.getConsumerAccountNumber()
        if consumerAccountNumber == False:
            consumerAccountNumber = ''
        message = self.strip('%s%s%s%s' %
                             (creationTime, res.getTransactionID(), status,
                              consumerAccountNumber))
        # The signature value in the response contains the signed hash
        # (signed by the signing key on the server)
        signature64 = self.parseFromXml('signatureValue', response)

        # The signed hash is base64 encoded and inserted into the XML as such
        sig = base64.b64decode(signature64)

        # The fingerprint is used as the identifier of the public key certificate.
        # It is sent as part of the response XML.
        fingerprint = self.parseFromXml('fingerprint', response)

        # The merchant should have the public certificate stored locally.
        certfile = self.getCertificateFileName(fingerprint)
        if certfile in ['', False]:
            return False

        # Verify the message signature
        valid = self.Security.verifyMessage(certfile, str(message), str(sig))
        if not valid:
            return False

        if not res:
            return response

        return res
Beispiel #4
0
    def RequestTransaction(self,
                           issuerId,
                           purchaseId,
                           amount,
                           description,
                           entranceCode,
                           optExpirationPeriod='',
                           optMerchantReturnURL=''):
        """
			This function submits a transaction request to the server.

			@param string $issuerId			The issuer Id to send the request to
			@param string $purchaseId		The purchase Id that the merchant generates
			@param integer $amount			The amount in cents for the purchase
			@param string $description		The description of the transaction
			@param string $entranceCode		The entrance code for the visitor of the merchant site. Determined by merchant
			@param string $optExpirationPeriod		Expiration period in specific format. See reference guide. Can be configured in config.
			@param string $optMerchantReturnURL		The return URL (optional) for the visitor. Optional. Can be configured in config.
			@return An instance of AcquirerTransactionResponse or "false" on failure.
		"""
        self.clearError()
        configCheck = self.CheckConfig(self.config)

        if configCheck <> unicode('OK'):
            self.setError(ING_ERROR_MISSING_CONFIG,
                          'Config error: %s' % configCheck,
                          IDEAL_PRV_GENERIC_ERROR)
            return self.getError()

        if not self.verifyNotNull( issuerId, 'issuerId' ) or \
         not self.verifyNotNull( purchaseId, 'purchaseId' ) or \
         not self.verifyNotNull( amount, 'amount' ) or \
         not self.verifyNotNull( description, 'description' ) or \
         not self.verifyNotNull( entranceCode, 'entranceCode' ):
            errorResponse = self.getError()
            return errorResponse

        # check amount length
        amountOK = self.LengthCheck('Amount', amount, 12)
        if amountOK != "ok":
            return self.getError()

        # check for diacritical characters
        amountOK = self.CheckDiacritical('Amount', amount)
        if amountOK != "ok":
            return self.getError()

        # check entrancecode length
        entranceCodeOK = self.LengthCheck('Entrancecode', entranceCode, 40)
        if entranceCodeOK != "ok":
            return self.getError()
        # check for diacritical characters
        entranceCodeOK = self.CheckDiacritical('Entrancecode', entranceCode)
        if entranceCodeOK != "ok":
            return self.getError()

        # check purchaseid length
        purchaseIDOK = self.LengthCheck('PurchaseID', purchaseId, 16)
        if purchaseIDOK != "ok":
            return self.getError()
        # check for diacritical characters
        purchaseIDOK = self.CheckDiacritical('PurchaseID', purchaseId)
        if purchaseIDOK != "ok":
            return self.getError()

        # According to the specification, these values should be hardcoded.
        currency = 'EUR'
        language = 'nl'

        # Retrieve these values from the configuration file.
        cfgExpirationPeriod, result1 = self.getConfiguration(
            'EXPIRATIONPERIOD', True)
        cfgMerchantReturnURL, result2 = self.getConfiguration(
            'MERCHANTRETURNURL', True)

        if len(optExpirationPeriod):
            # If a (valid?) optional setting was specified for the expiration period, use it.
            expirationPeriod = optExpirationPeriod
        else:
            expirationPeriod = cfgExpirationPeriod

        if len(optMerchantReturnURL):
            # If a (valid?) optional setting was specified for the merchantReturnURL, use it.
            merchantReturnURL = optMerchantReturnURL
        else:
            merchantReturnURL = cfgMerchantReturnURL

        if not self.verifyNotNull( expirationPeriod, 'expirationPeriod' ) or \
         not self.verifyNotNull( merchantReturnURL, 'merchantReturnURL' ):
            return False

        # Build the XML header for the transaction request
        xmlMsg = self.getXMLHeader(
            'AcquirerTrxReq', issuerId,
            "<Issuer>\n<issuerID>%s</issuerID>\n</Issuer>\n" % issuerId,
            "%s%s%s%s%s%s%s" % (merchantReturnURL, purchaseId, amount,
                                currency, language, description, entranceCode),
            "<merchantReturnURL>%s</merchantReturnURL>\n" % merchantReturnURL)

        if xmlMsg in [False, '']:
            return False

        # Add transaction information to the request.
        xmlMsg += "<Transaction>\n<purchaseID>%s</purchaseID>\n" % purchaseId
        xmlMsg += "<amount>%s</amount>\n" % amount
        xmlMsg += "<currency>%s</currency>\n" % currency
        xmlMsg += "<expirationPeriod>%s</expirationPeriod>\n" % expirationPeriod
        xmlMsg += "<language>%s</language>\n" % language
        xmlMsg += "<description>%s</description>\n" % description
        xmlMsg += "<entranceCode>%s</entranceCode>\n" % entranceCode
        xmlMsg += "</Transaction>\n"
        xmlMsg += "</AcquirerTrxReq>\n"

        # Post the request to the server.
        response = self.PostXMLData(xmlMsg)

        # If the response did not work out, return an ErrorResponse object.
        if not self.parseFromXml('errorCode', response) in ['', False]:
            errorResponse = ErrorResponse()

            errorResponse.setErrorCode(self.parseFromXml(
                'errorCode', response))
            errorResponse.setErrorMessage(
                self.parseFromXml('errorMessage', response))
            errorResponse.setConsumerMessage(
                self.parseFromXml('consumerMessage', response))

            return errorResponse

        if self.parseFromXml('acquirerID', response) in ['', False]:
            errorResponse = ErrorResponse()

            errorResponse.setErrorCode('ING1001')
            errorResponse.setErrorMessage('Transactie mislukt (aquirer side)')
            errorResponse.setConsumerMessage('')

            return errorResponse

        html_decode_table = {
            "&amp;": "&",
            "&quot;": '"',
            "&apos;": "'",
            "&gt;": ">",
            "&lt;": "<",
        }

        def html_decode(text):
            """Produce entities within text."""
            L = []
            for c in text:
                L.append(html_decode_table.get(c, c))
            return "".join(L)

        # Build the transaction response object and pass in the data.
        res = AcquirerTransactionResponse()
        res.setAcquirerID(self.parseFromXml('acquirerID', response))
        res.setIssuerAuthenticationURL(
            html_decode(self.parseFromXml('issuerAuthenticationURL',
                                          response)))
        res.setTransactionID(self.parseFromXml('transactionID', response))
        res.setPurchaseID(self.parseFromXml('purchaseID', response))

        if not res:
            return response

        return res