def complete_payment(self, pay_response: Dict): """Complete payment.""" response_url = pay_response.get('response_url') current_app.logger.debug('response_url : %s', response_url) if self.payment.status == 'PAID' or not response_url: raise BusinessException(Error.INVALID_INPUT) self.payment.response_url = response_url self.payment.commit() parsed_args = HashService.parse_url_params(response_url) # Validate transaction number if self.payment.transaction_number != parsed_args.get('pbcTxnNumber'): raise BusinessException(Error.INVALID_INPUT) # Check if trnApproved is 1=Success, 0=Declined trn_approved: bool = parsed_args.get('trnApproved') == '1' if trn_approved: self._validate_hash(parsed_args, response_url) # Add paybc api call to verify # handle duplicate payment response. paybc_status = None if trn_approved or parsed_args.get('trnNumber', '').upper() == 'DUPLICATE PAYMENT': paybc_status = self._validate_with_paybc(trn_approved) self.payment.order_id = parsed_args.get('trnOrderId') self.payment.completed_on = datetime.now() self.payment.status = 'PAID' if paybc_status == 'PAID' else parsed_args.get( 'messageText').upper() self.payment.commit() return self._dump()
def upload_template(self, template_file_path: str = receipt_template_path): headers = { "Authorization": f'Bearer {self.access_token}' } url = f"{current_app.config['CDOGS_BASE_URL']}/api/v2/template" template = {'template':('template', open(template_file_path, 'rb'), "multipart/form-data")} current_app.logger.info('Uploading template %s', template_file_path) print('Uploading template %s', template_file_path) response = self._post_upload_template(headers, url, template) if response.status_code == 200: if response.headers.get("X-Template-Hash") is None: raise BusinessException(Error.DATA_NOT_FOUND) current_app.logger.info('Returning new hash %s', response.headers['X-Template-Hash']) print('Returning new hash %s', response.headers['X-Template-Hash']) return response.headers['X-Template-Hash']; response_json = json.loads(response.content) if response.status_code == 405 and response_json['detail'] is not None: match = re.findall(r"Hash '(.*?)'", response_json['detail']); if match: current_app.logger.info('Template already hashed with code %s', match[0]) print('Template already hashed with code %s', match[0]) return match[0] raise BusinessException(Error.DATA_NOT_FOUND)
def __init__(self): self.cdgos_api_service = CdogsApiService() receipt_document_type: DocumentType = DocumentType.get_document_type_by_name( 'receipt') if receipt_document_type is None: raise BusinessException(Error.DATA_NOT_FOUND) self.receipt_template : DocumentTemplate = DocumentTemplate \ .get_template_by_type(document_type_id = receipt_document_type.document_type_id) if self.receipt_template is None: raise BusinessException(Error.DATA_NOT_FOUND)
def doesrequirepayment(requestdatajson): if 'requestType' not in requestdatajson or 'requestType' not in requestdatajson['requestType']: raise BusinessException(Error.DATA_NOT_FOUND) if requestdatajson['requestType']['requestType'] == "personal": return False if 'contactInfo' in requestdatajson: if requestdatajson['requestType']['requestType'] == "general": if 'IGE' in requestdatajson['contactInfo'] and requestdatajson['contactInfo']['IGE']: return False return True elif requestdatajson['requestType']['requestType'] == "personal": return False else: if 'requiresPayment' not in requestdatajson: raise BusinessException(Error.DATA_NOT_FOUND) return requestdatajson['requiresPayment'] raise BusinessException(Error.DATA_NOT_FOUND)
def _validate_hash(self, parsed_args, response_url): # validate if hashValue matches with rest of the values hashed hash_value = parsed_args.pop('hashValue', None) pay_response_url_without_hash = urlencode(parsed_args) if not HashService.is_valid_checksum(pay_response_url_without_hash, hash_value): current_app.logger.warning( f'Transaction is approved, but hash is not matching : {response_url}' ) raise BusinessException(Error.INVALID_INPUT)
def get_fee(code: str, quantity: int, valid_date: date): """Return fee details.""" fee_code: FeeCode = FeeCode.get_fee(code=code, valid_date=valid_date) if not fee_code: raise BusinessException(Error.DATA_NOT_FOUND) fee_response = dict(fee_code=code, fee=fee_code.fee, quantity=quantity, total=quantity * fee_code.fee, description=fee_code.description) return fee_response
def init_payment(self, pay_request: Dict): """Initialize payment request.""" fee = FeeCode.get_fee(code=pay_request.get('fee_code'), valid_date=date.today()) if not fee: raise BusinessException(Error.INVALID_INPUT) return_route = pay_request.get('return_route') quantity = int(pay_request.get('quantity', 1)) self.payment = Payment(fee_code_id=fee.fee_code_id, quantity=quantity, total=quantity * fee.fee, status='PENDING', request_id=self.request_id).flush() self.payment.paybc_url = self._get_paybc_url(fee, return_route) self.payment.transaction_number = self._get_transaction_number() self.payment.commit() pay_response = self._dump() return pay_response
def __init__(self, request_id: int, payment_id=None): self.request_id = request_id if FOIRawRequest.get_request(request_id) is None: raise BusinessException(Error.INVALID_INPUT) self.payment: Payment = Payment.find_by_id( payment_id) if payment_id else None
class FeeService: """ FOI Fee management service This service class manages all CRUD operations related to Fee """ def __init__(self, request_id: int, payment_id=None): self.request_id = request_id if FOIRawRequest.get_request(request_id) is None: raise BusinessException(Error.INVALID_INPUT) self.payment: Payment = Payment.find_by_id( payment_id) if payment_id else None @staticmethod def get_fee(code: str, quantity: int, valid_date: date): """Return fee details.""" fee_code: FeeCode = FeeCode.get_fee(code=code, valid_date=valid_date) if not fee_code: raise BusinessException(Error.DATA_NOT_FOUND) fee_response = dict(fee_code=code, fee=fee_code.fee, quantity=quantity, total=quantity * fee_code.fee, description=fee_code.description) return fee_response def init_payment(self, pay_request: Dict): """Initialize payment request.""" fee = FeeCode.get_fee(code=pay_request.get('fee_code'), valid_date=date.today()) if not fee: raise BusinessException(Error.INVALID_INPUT) return_route = pay_request.get('return_route') quantity = int(pay_request.get('quantity', 1)) self.payment = Payment(fee_code_id=fee.fee_code_id, quantity=quantity, total=quantity * fee.fee, status='PENDING', request_id=self.request_id).flush() self.payment.paybc_url = self._get_paybc_url(fee, return_route) self.payment.transaction_number = self._get_transaction_number() self.payment.commit() pay_response = self._dump() return pay_response def complete_payment(self, pay_response: Dict): """Complete payment.""" response_url = pay_response.get('response_url') current_app.logger.debug('response_url : %s', response_url) if self.payment.status == 'PAID' or not response_url: raise BusinessException(Error.INVALID_INPUT) self.payment.response_url = response_url self.payment.commit() parsed_args = HashService.parse_url_params(response_url) # Validate transaction number if self.payment.transaction_number != parsed_args.get('pbcTxnNumber'): raise BusinessException(Error.INVALID_INPUT) # Check if trnApproved is 1=Success, 0=Declined trn_approved: bool = parsed_args.get('trnApproved') == '1' if trn_approved: self._validate_hash(parsed_args, response_url) # Add paybc api call to verify # handle duplicate payment response. paybc_status = None if trn_approved or parsed_args.get('trnNumber', '').upper() == 'DUPLICATE PAYMENT': paybc_status = self._validate_with_paybc(trn_approved) self.payment.order_id = parsed_args.get('trnOrderId') self.payment.completed_on = datetime.now() self.payment.status = 'PAID' if paybc_status == 'PAID' else parsed_args.get( 'messageText').upper() self.payment.commit() return self._dump() def check_if_paid(self): """Check payment.""" return self.payment.status == 'PAID' def _validate_with_paybc(self, trn_approved): paybc_status = None paybc_response = self.get_paybc_transaction_details() if trn_approved and (paybc_status := paybc_response.get('paymentstatus')) != 'PAID': raise BusinessException(Error.INVALID_INPUT) if paybc_status == 'PAID' and self.payment.total != float( paybc_response.get('trnamount')): raise BusinessException(Error.INVALID_INPUT) return paybc_status
def _validate_with_paybc(self, trn_approved): paybc_status = None paybc_response = self.get_paybc_transaction_details() if trn_approved and (paybc_status := paybc_response.get('paymentstatus')) != 'PAID': raise BusinessException(Error.INVALID_INPUT)