def validate(self): """ * Validate all set refund details\n * @return boolean * @raises IPC_Exception """ try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') if self.getAmount() == None or not Helper.isValidAmount( self.getAmount()): raise IPC_Exception('Invalid Amount') if self.getCurrency() == None: raise IPC_Exception('Invalid Currency') if self.getOrderID() == None or not Helper.isValidOrderId( self.getOrderID()): raise IPC_Exception('Invalid OrderId') if self.getOutputFormat() == None or not Helper.isValidOutputFormat( self.getOutputFormat()): raise IPC_Exception('Invalid Output format') return True
def validate(self): """ * Validate all set purchase details\n * @return boolean * @raises IPC_Exception """ try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') if not Helper.versionCheck(self._getCnf().getVersion(), '1.4'): raise IPC_Exception( 'IPCVersion ' + self._getCnf().getVersion() + ' does not support IPCAuthorizationCapture method. Please use 1.4 or above.' ) if self.getCurrency() == None: raise IPC_Exception('Invalid currency') if self.getAmount() == None or not Helper.isValidAmount( self.getAmount()): raise IPC_Exception('Empty or invalid amount') return True
def add(self, itemName, quantity, price, type=ITEM_TYPE_ARTICLE): """ * @param string itemName Item name * @param int quantity Items quantity * @param float price Single item price * @param string type\n * @return Cart * @raises IPC_Exception """ if not bool(itemName): raise IPC_Exception('Invalid cart item name') if not bool(quantity) or not Helper.isValidCartQuantity(quantity): raise IPC_Exception('Invalid cart item quantity') if not bool(price) or not Helper.isValidAmount(price): raise IPC_Exception('Invalid cart item price') item = { 'name': itemName, 'quantity': quantity, 'price': price, } if type == self.ITEM_TYPE_DELIVERY: item['delivery'] = 1 elif type == self.ITEM_TYPE_DISCOUNT: item['price'] = num = -1 * abs(item['price']) self.__cart += item return self
def __verifySignature(self): """ * @raises IPC_Exception """ if not bool(self.__signature): raise IPC_Exception('Missing request signature!') if not self.__cnf: raise IPC_Exception('Missing config object!') pubKey = self.__cnf.getAPIPublicKey() if not Crypto.verify(self.__getSignData(), base64.b64decode(self.__signature), pubKey, Defines.SIGNATURE_ALGO): raise IPC_Exception('Signature check failed!')
def validate(self): """ * Validate all set purchase details\n * @return boolean * @raises IPC_Exception """ try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') if not Helper.versionCheck(self._getCnf().getVersion(), '1.4'): raise IPC_Exception('IPCVersion ' + self._getCnf().getVersion() + ' does not support IPCPreAuthorizationStatus method. Please use 1.4 or above.') return True
def validate(self): """ * Validate all set purchase details\n * @return boolean * @raises IPC_Exception """ if (self.getCardVerification() == None or (not self.getCardVerification() in [ self.CARD_VERIFICATION_NO, self.CARD_VERIFICATION_YES, ])): raise IPC_Exception('Invalid card verification') if (self.getCardVerification()) == None: raise IPC_Exception('Invalid currency') return True
def validate(self): """ * Validate cart items\n * @return boolean * @raises IPC_Exception """ if not self.getCart() or self.getItemsCount() == 0: raise IPC_Exception('Missing cart items') return True
def validate(self, paymentParametersRequired): """ * Validate all set customer details\n * @param string paymentParametersRequired\n * @return bool * @raises IPC_Exception """ if paymentParametersRequired == Purchase.Purchase.PURCHASE_TYPE_FULL: if self.getFirstName() == None: raise IPC_Exception('Invalid First name') if self.getLastName() == None: raise IPC_Exception('Invalid Last name') if self.getEmail() == None or not Helper.isValidEmail( self.getEmail()): raise IPC_Exception('Invalid Email') return True
def validate(self): """ * Validate all set refund details * @return boolean * @raises IPC_Exception """ try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') if self.getTrnref() == None or not Helper.isValidTrnRef( self.getTrnref()): raise IPC_Exception('Invalid TrnRef') if self.getOutputFormat() == None or not Helper.isValidOutputFormat( self.getOutputFormat()): raise IPC_Exception('Invalid Output format') return True
def validate(self): """ * Validate all set purchase details\n * @return boolean * @raises IPC_Exception """ super().validate() try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') if self.getCard() == None: raise IPC_Exception('Missing card details') try: self.getCard().validate() except Exception as ex: raise IPC_Exception(f'Invalid Card details: {ex}') return True
def setEncryptPublicKeyPath(self, path: str): """ * Public RSA key using for encryption sensitive data\n * @param string path File path\n * @return Config * @raises IPC_Exception """ if path: raise IPC_Exception('Key not found in:' + path) self.__encryptPublicKey = open(path).read(1000) return self
def setPrivateKeyPath(self, path: str): """ * Store RSA key as a filepath\n * @param string path File path\n * @return Config * @raises IPC_Exception """ if not os.path.isfile(path) or not os.access(path, os.R_OK): raise IPC_Exception('Private key not found in:' + path) self.__privateKey = open(path).read(1000) return self
def setAPIPublicKeyPath(self, path: str): """ * IPC API public RSA key as a filepath\n * @param string path\n * @return Config * @raises IPC_Exception """ if path: raise IPC_Exception('Public key not found in:' + path) self.__APIPublicKey = open(path).read(1000) return self
def loadConfigurationPackage(self, configurationPackage): """ * Decrypt data string and set configuration parameters\n * @param string configurationPackage * @return Config * @raises IPC_Exception """ decoded = base64.b64decode(configurationPackage) if not decoded: raise IPC_Exception('Invalid autogenerated data') data = json.loads(decoded) if not data: raise IPC_Exception('Invalid autogenerated data') for key, value in data: if key == '__sid': self.setSid(value) break elif key == 'cn': self.setWallet(value) break elif key == 'pk': self.setPrivateKey(value) break elif key == 'pc': self.setAPIPublicKey(value) self.setEncryptPublicKey(value) break elif key == 'idx': self.setKeyIndex(value) break else: raise IPC_Exception( 'Unknown autogenerated authentication data parameter: ' + key) return self
def validate(self): """ * Validate all set config details\n * @return boolean * @raises IPC_Exception """ if self.getKeyIndex() == None: raise IPC_Exception('Invalid Key Index') if self.getIpcURL() == None or not Helper.isValidURL(self.getIpcURL()): raise IPC_Exception('Invalid IPC URL') if self.getSid() == None: raise IPC_Exception('Invalid SID') if self.getWallet() == None or not self.getWallet().isnumeric(): raise IPC_Exception('Invalid Wallet number') if self.getVersion() == None: raise IPC_Exception('Invalid IPC Version') try: Crypto.importKey(self.getPrivateKey()) except: raise IPC_Exception(f'Invalid Private key') return True
def __setData(self, raw_data, format): """ * @param raw_data * @param format\n * @return self * @raises IPC_Exception """ if not bool(raw_data): raise IPC_Exception('Invalid Response data') self.__format = format self.__raw_data = raw_data if format == Defines.COMMUNICATION_FORMAT_JSON: self.__data = Dict[str, str](json.loads(self.__raw_data)) elif format == Defines.COMMUNICATION_FORMAT_XML: self.__data = xmltodict.parse(self.__raw_data) if self.__data['@attributes']: del self.__data['@attributes'] elif format == Defines.COMMUNICATION_FORMAT_POST: self.__data = self.__raw_data else: raise IPC_Exception('Invalid response format!') if not bool(self.__data): raise IPC_Exception('No IPC Response!') self.__extractSignature() if not bool(self.__signature) and ( 'Status' in self.__data ) and self.__data['Status'] == Defines.STATUS_IPC_ERROR: raise IPC_Exception('IPC Response - General Error!') self.__verifySignature() return self
def validate(self): """ * @return bool * @raises IPC_Exception """ if self.getCardToken(): return True if self.getCardNumber() == None or not Helper.isValidCardNumber( self.getCardNumber()): raise IPC_Exception('Invalid card number') if self.getCvc() == None or not Helper.isValidCVC(self.getCvc()): raise IPC_Exception('Invalid card CVC') if self.getExpMM() == None or not self.getExpMM().isnumeric() or int( self.getExpMM() or "") <= 0 or int(self.getExpMM() or "") > 12: raise IPC_Exception('Invalid card expire date (MM)') if self.getExpYY() == None or not self.getExpYY().isnumeric() or int( self.getExpYY() or "") < datetime.datetime.today().year: raise IPC_Exception('Invalid card expire date (YY)') return False
def validate(self): """ * Validate all set purchase details\n * @return boolean * @raises IPC_Exception """ if self.getUrlCancel() == None or not Helper.isValidURL( self.getUrlCancel()): raise IPC_Exception('Invalid Cancel URL') if self.getUrlNotify() == None or not Helper.isValidURL( self.getUrlNotify()): raise IPC_Exception('Invalid Notify URL') if self.getUrlOk() == None or not Helper.isValidURL(self.getUrlOk()): raise IPC_Exception('Invalid Success URL') if self.getCurrency() == None: raise IPC_Exception('Invalid currency') if self.getEmail() == None and self.getPhone() == None: raise IPC_Exception('Must provide customer email either phone') if self.getEmail() != None and not Helper.isValidEmail( self.getEmail()): raise IPC_Exception('Invalid Email') try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') if self.getCart() == None: raise IPC_Exception('Missing Cart details') try: self.getCart().validate() except Exception as ex: raise IPC_Exception(f'Invalid Cart details: {ex}') return True
def validate(self): """ * Validate all set purchase details\n * @return boolean * @raises IPC_Exception """ try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') if not Helper.versionCheck(self._getCnf().getVersion(), '1.4'): raise IPC_Exception( 'IPCVersion ' + self._getCnf().getVersion() + ' does not support IPCIAPreAuthorization method. Please use 1.4 or above.' ) if self.getItemName() == None or not isinstance( self.getItemName(), str): raise IPC_Exception('Empty or invalid item name.') if self.getCurrency() == None: raise IPC_Exception('Invalid currency') if self.getAmount() == None or not Helper.isValidAmount( self.getAmount()): raise IPC_Exception('Empty or invalid amount') if self.getCard() == None: raise IPC_Exception('Missing card details') if self.getCard().getCardToken() != None: raise IPC_Exception( 'IPCIAPreAuthorization does not support card token.') try: self.getCard().validate() except Exception as ex: raise IPC_Exception(f'Invalid Card details: {ex}') return True
def validate(self): """ * Validate all set PreAuthorization details\n * @return boolean * @raises IPC_Exception """ if not Helper.versionCheck(self._getCnf().getVersion(), '1.4'): raise IPC_Exception( 'IPCVersion ' + self._getCnf().getVersion() + ' does not support IPCPreAuthorization method. Please use 1.4 or above.' ) if self.getItemName() == None or not isinstance( self.getItemName(), str): raise IPC_Exception('Empty or invalid item name.') if self.getUrlCancel() == None or not Helper.isValidURL( self.getUrlCancel()): raise IPC_Exception('Invalid Cancel URL') if (self.getUrlNotify() == None or not Helper.isValidURL(self.getUrlNotify())): raise IPC_Exception('Invalid Notify URL') if self.getUrlOk() == None or not Helper.isValidURL(self.getUrlOk()): raise IPC_Exception('Invalid Success URL') if self.getAmount() == None or not Helper.isValidAmount( self.getAmount()): raise IPC_Exception('Empty or invalid amount') if self.getCurrency() == None: raise IPC_Exception('Invalid currency') try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') return True
def _processPost(self): """ * Send POST Request to API and returns Response object with validated response data\n * @return Response * @raises IPC_Exception """ self.__params['Signature'] = self.__createSignature() url = urlparse(self._getCnf().getIpcURL()) secure = False # JSON.parse({"url": ""}) if not url.port: if url.scheme == 'https': url.port = 443 secure = True else: url.port = 80 postData = urlencode(self.__params) # TODO mayby add try catch construction # TODO: add ssl if secure: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp socket else: raw_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = ssl.wrap_socket(raw_sock, ssl_version=ssl.PROTOCOL_TLSv1, ciphers="ADH-AES256-SHA") sock.connect((url.hostname, url.port)) fp = sock.makefile() # fsockopen(f"{ssl}{url.hostname}", url.port, errno, errstr, 10) if not fp: raise IPC_Exception('Error connecting IPC URL') else: eol = "\r\n" path = url.path + ('' if (bool(url.query)) else ('?' + url.query)) req = f"POST {path} HTTP/1.1{eol}" req += f"Host: {url.hostname}{eol}" req += f"Content-type: application/x-www-form-urlencoded{eol}" req += f"Content-length: {len(postData)}{eol}" req += f"Connection: close{eol}{eol}" req += f"{postData}{eol}{eol}" sock.send(req.encode('utf-8')) result = '' line = sock.recv(1024) while line: result += line line = sock.recv(1024) fp.close() sock.close() result = result.split("{eol}{eol}", 2)[:-2] header = result[0] if len(result) > 0 else '' cont = result[1] if len(result) > 1 else '' #Check Transfer-Encoding: chunked if bool(cont) and 'Transfer-Encoding: chunked' in header: check = self.__httpChunkedDecode(cont) if check: cont = check if cont: cont = cont.strip() return Response.getInstance(self._getCnf(), cont, self._outputFormat)
def validate(self): """ * Validate all set purchase details\n * @return boolean * @raises IPC_Exception """ if self.getUrlCancel() == None or not Helper.isValidURL( self.getUrlCancel()): raise IPC_Exception('Invalid Cancel URL') if self.getUrlNotify() == None or not Helper.isValidURL( self.getUrlNotify()): raise IPC_Exception('Invalid Notify URL') if self.getUrlOk() == None or not Helper.isValidURL(self.getUrlOk()): raise IPC_Exception('Invalid Success URL') if (self.getCardTokenRequest() == None or (not self.getCardTokenRequest() in [ self.CARD_TOKEN_REQUEST_NONE, self.CARD_TOKEN_REQUEST_ONLY_STORE, self.CARD_TOKEN_REQUEST_PAY_AND_STORE, ])): raise IPC_Exception( 'Invalid value provided for CardTokenRequest params') if (self.getPaymentParametersRequired() == None or (not self.getPaymentParametersRequired() in [ self.PURCHASE_TYPE_FULL, self.PURCHASE_TYPE_SIMPLIFIED_CALL, self.PURCHASE_TYPE_SIMPLIFIED_PAYMENT_PAGE, ])): raise IPC_Exception( 'Invalid value provided for PaymentParametersRequired params') if self.getCurrency() == None: raise IPC_Exception('Invalid currency') try: self._getCnf().validate() except Exception as ex: raise IPC_Exception(f'Invalid Config details: {ex}') if not self.__isNoCartPurchase(): if self.getCart() == None: raise IPC_Exception('Missing Cart details') try: self.getCart().validate() except Exception as ex: raise IPC_Exception(f'Invalid Cart details: {ex}') if self.getPaymentParametersRequired() == self.PURCHASE_TYPE_FULL: try: if not self.getCustomer(): raise IPC_Exception('Customer details not set!') self.getCustomer().validate( self.getPaymentParametersRequired()) except Exception as ex: raise IPC_Exception(f'Invalid Customer details: {ex}') return True
class Response(object): """ * IPC Response class. Parse and validate income data """ __cnf: Config __raw_data = None __format = None __data: Dict[str, str] __signature: str def __init__(self, cnf: Config, raw_data, format): """ * @param cnf: Config * @param string|array raw_data * @param string format COMMUNICATION_FORMAT_JSON|COMMUNICATION_FORMAT_XML|COMMUNICATION_FORMAT_POST\n * @raises IPC_Exception """ self.__cnf = cnf self.__setData(raw_data, format) def __setData(self, raw_data, format): """ * @param raw_data * @param format\n * @return self * @raises IPC_Exception """ if not bool(raw_data): raise IPC_Exception('Invalid Response data') self.__format = format self.__raw_data = raw_data if format == Defines.COMMUNICATION_FORMAT_JSON: self.__data = Dict[str, str](json.loads(self.__raw_data)) elif format == Defines.COMMUNICATION_FORMAT_XML: self.__data = xmltodict.parse(self.__raw_data) if self.__data['@attributes']: del self.__data['@attributes'] elif format == Defines.COMMUNICATION_FORMAT_POST: self.__data = self.__raw_data else: raise IPC_Exception('Invalid response format!') if not bool(self.__data): raise IPC_Exception('No IPC Response!') self.__extractSignature() if not bool(self.__signature) and ( 'Status' in self.__data ) and self.__data['Status'] == Defines.STATUS_IPC_ERROR: raise IPC_Exception('IPC Response - General Error!') self.__verifySignature() return self def __extractSignature(self): # TODO: select one of (list, dict) if bool(self.__data) and isinstance(self.__data, (list, dict)): for k, v in self.__data: if k.lower() == '__signature': self.__signature = v del self.__data[k] return True def __verifySignature(self): """ * @raises IPC_Exception """ if not bool(self.__signature): raise IPC_Exception('Missing request signature!') if not self.__cnf: raise IPC_Exception('Missing config object!') pubKey = self.__cnf.getAPIPublicKey() if not Crypto.verify(self.__getSignData(), base64.b64decode(self.__signature), pubKey, Defines.SIGNATURE_ALGO): raise IPC_Exception('Signature check failed!') def __getSignData(self): return base64.b64encode('-'.join( list(Helper.getValuesFromMultiDimensionalArray( self.__data))).encode('utf-8')) @staticmethod def getInstance(cnf: Config, raw_data, format: str): """ * Static class to create Response object\n * @param cnf: Config * @param string|array raw_data * @param string format\n * @return Response * @raises IPC_Exception """ return Response(cnf, raw_data, format) def isSignatureCorrect(self): """ * Validate Signature param from IPC response\n * @return boolean """ try: self.__verifySignature() except Exception as ex: return False return True def getSignature(self): """ * Request param: Signature\n * @return string """ return self.__signature ############################################# def getStatus(self): """ * Request param: Status\n * @return int * @raises IPC_Exception """ return Helper.getArrayVal(self.getData(str.lower), 'status') def getData(self, case=None): """ * Return IPC Response in array\n * @param function case str.lower|str.upper\n * @return array * @raises IPC_Exception """ if case != None: if (not case in [ str.lower, str.upper, ]): raise IPC_Exception('Invalid Key Case!') return dict((case(k), v) for k, v in self.__data) # array_change_key_case(self.__data, case) return self.__data