def process(self, result): """ Signs result body with a hmac signature. It the compares the resultant signature with the X-Kopo-Kopo signature from the headers of the result. If the signatures are the same, the result is valid. Returns a json formatted str containing content of the HTTP result. :param result: A HTTP result object :type result: requests.models.Response :return: str """ if result is None or result == '': raise exceptions.InvalidArgumentError('Response cannot be empty') # define result body result_body = result.content # define X-KopoKopo-Signature x_kopo_kopo_signature = result.headers.get('X-KopoKopo-Signature') # define hmac signature hmac_signature = generate_hmac_signature( bytes(self._client_secret, 'utf-8'), result_body) # compare signatures if hmac.compare_digest(hmac_signature, x_kopo_kopo_signature) is False: raise exceptions.InvalidArgumentError('Invalid result passed') return result.json
def validate_string_arguments(*args): for arg in args: if arg is None or arg == '': raise exceptions.InvalidArgumentError('Invalid/empty argument') if not isinstance(arg, str): raise exceptions.InvalidArgumentError('Argument must be of type str.') pass
def validate_dictionary_arguments(*args): for arg in args: if arg is None or arg == {}: raise exceptions.InvalidArgumentError('Invalid argument passed.' 'Expects dict object') if not isinstance(arg, dict): raise exceptions.InvalidArgumentError('Argument must be of type dict.')
def create_polling_request(self, kwargs): """ Creates a request for the reception of payments from MPESA users. Returns a request response object < class, 'requests.models.Response'> :param kwargs: The values constitute all user input. :type kwargs: dict :return: requests.models.Response """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'scope' not in kwargs or \ 'scope_reference' not in kwargs or \ 'from_time' not in kwargs or \ 'to_time' not in kwargs or \ 'callback_url' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for creating Polling Request.') # iterate through kwargs if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'scope' in kwargs: scope = kwargs['scope'] if 'scope_reference' in kwargs: scope_reference = kwargs['scope_reference'] if 'from_time' in kwargs: from_time = kwargs['from_time'] if 'to_time' in kwargs: to_time = kwargs['to_time'] if 'callback_url' in kwargs: callback_url = kwargs['callback_url'] # define headers headers = dict(self._headers) # validate bearer_token validation.validate_string_arguments(bearer_token) # add bearer token headers['Authorization'] = 'Bearer ' + bearer_token + '' # build polling request url polling_request_url = self._build_url(POLLING_PATH) # define links JSON object polling_request_links = json_builder.links(callback_url=callback_url) # define MPESA payment request JSON object polling_request_payload = json_builder.polling( scope=scope, scope_reference=scope_reference, from_time=from_time, to_time=to_time, polling_links=polling_request_links) return self._make_requests(headers=headers, method='POST', url=polling_request_url, payload=polling_request_payload)
def validate_url(url): validated_url = urlparse(url) # check url format if validated_url.scheme is "" or validated_url.netloc is "": raise exceptions.InvalidArgumentError('The url format passed is invalid (should be : https://domain.com)') if validated_url.scheme is not "" and not validated_url.scheme == 'https': raise exceptions.InvalidArgumentError('Provide a url with a valid certificate => (https://)') else: return True
def add_mobile_wallet_settlement_account(self, kwargs): """ Creates a verified settlement bank account. Returns a request response object < class, 'requests.models.Response'> :param kwargs: The values constitute all user input. :type kwargs: dict :return: requests.models.Response """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'first_name' not in kwargs or \ 'last_name' not in kwargs or \ 'phone_number' not in kwargs or \ 'network' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for creating Outgoing Pay.') # iterate through kwargs if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'first_name' in kwargs: first_name = kwargs['first_name'] if 'last_name' in kwargs: last_name = kwargs['last_name'] if 'phone_number' in kwargs: phone_number = kwargs['phone_number'] if 'network' in kwargs: network = kwargs['network'] # build url create_mobile_wallet_settlement_account_url = self._build_url( SETTLEMENT_MOBILE_ACCOUNTS_PATH) # define headers headers = dict(self._headers) # validate string arguments validation.validate_string_arguments(bearer_token, first_name, last_name, phone_number, network) validation.validate_phone_number(phone_number) # add authorization to headers headers['Authorization'] = 'Bearer ' + bearer_token + '' # define create mobile settlement account payload create_mobile_settlement_account_payload = json_builder.mobile_settlement_account( first_name=first_name, last_name=last_name, phone_number=phone_number, network=network) return self._make_requests( headers=headers, method='POST', url=create_mobile_wallet_settlement_account_url, payload=create_mobile_settlement_account_payload)
def add_bank_settlement_account(self, kwargs): """ Creates a verified settlement bank account. Returns a request response object < class, 'requests.models.Response'> :return: requests.models.Response """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'settlement_method' not in kwargs or \ 'account_name' not in kwargs or \ 'account_number' not in kwargs or \ 'bank_branch_ref' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for creating Bank Settlement Account.') # iterate through kwargs if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'settlement_method' in kwargs: settlement_method = kwargs['settlement_method'] if 'account_name' in kwargs: account_name = kwargs['account_name'] if 'account_number' in kwargs: account_number = kwargs['account_number'] if 'bank_branch_ref' in kwargs: bank_branch_ref = kwargs['bank_branch_ref'] # build url create_bank_settlement_account_url = self._build_url( SETTLEMENT_BANK_ACCOUNTS_PATH) # define headers headers = dict(self._headers) # validate string arguments validation.validate_string_arguments(bearer_token, settlement_method, account_name, bank_branch_ref, account_number) # add authorization to headers headers['Authorization'] = 'Bearer ' + bearer_token + '' # define create bank settlement account payload create_bank_settlement_account_payload = json_builder.bank_settlement_account( settlement_method=settlement_method, account_name=account_name, account_number=account_number, bank_branch_ref=bank_branch_ref) return self._make_requests( headers=headers, method='POST', url=create_bank_settlement_account_url, payload=create_bank_settlement_account_payload)
def metadata(join=None, **kwargs): """ Returns a json formatted str with a maximum of 5 metadata key-value pairs. :param join: :param kwargs: Metadata information :return: str """ if kwargs is None or kwargs == '': raise exceptions.InvalidArgumentError( 'Invalid argument passed. Expects ' / 'key=word/') if len(kwargs) >= 5: raise exceptions.InvalidArgumentError( 'Should be less than or 5 metadata objects') metadata_object = kwargs return metadata_object
def send_transaction_sms_notification(self, kwargs): """ Creates a transaction sms notification. Returns a request response object < class, 'requests.models.Response'> :return: requests.models.Response """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'webhook_event_reference' not in kwargs or \ 'message' not in kwargs or \ 'callback_url' not in kwargs: raise exceptions.InvalidArgumentError('Invalid arguments for creating Transaction SMS Notification.') # iterate through kwargs if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'webhook_event_reference' in kwargs: webhook_event_reference = kwargs['webhook_event_reference'] if 'message' in kwargs: message = kwargs['message'] if 'callback_url' in kwargs: callback_url = kwargs['callback_url'] # build url create_transaction_sms_notification_url = self._build_url(TRANSACTION_NOTIFICATIONS_PATH) # define headers headers = dict(self._headers) # validate string arguments validation.validate_string_arguments(bearer_token, webhook_event_reference, message, callback_url) notification_links = json_builder.links(callback_url=callback_url) # add authorization to headers headers['Authorization'] = 'Bearer ' + bearer_token + '' # define create bank settlement account payload create_transaction_sms_notification_payload = json_builder.transaction_sms_notification(webhook_event_reference=webhook_event_reference, message=message, notification_links=notification_links) return self._make_requests(headers=headers, method='POST', url=create_transaction_sms_notification_url, payload=create_transaction_sms_notification_payload)
def validate_email(email): """ :param email: An email address :type email: str :return: True """ validated_email = re.search(r'\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b', email, re.I) if validated_email is not None: return True else: raise exceptions.InvalidArgumentError("The email address passed is invalid. (Should be: [email protected])")
def validate_phone_number(phone_number): """ :param phone_number: A phone number :type phone_number: str :return: True """ validated_phone_number = re.search('^\+\d{1,3}\d{3,}$', phone_number) if validated_phone_number is not None: return True else: raise exceptions.InvalidArgumentError('The phone number passed is invalid. (Should be: +254123456789)')
def create_subscription(self, bearer_token, event_type, webhook_endpoint, webhook_secret): """ Creates a subscription to a webhook service. Returns a request response object < class, 'requests.models.Response'> :param bearer_token: Access token to be used to make calls to the Kopo Kopo API :type bearer_token: str :param event_type:Type of subscription event. Should be one of: buygoods_transaction_received, buygoods_transaction_reversed, settlement_transfer_completed, customer_created :type event_type: str :param webhook_endpoint: HTTP end point to send the webhook. :type webhook_endpoint: str :param webhook_secret: Secret used to encrypt the request payload using HMAC. :type webhook_secret: str :return: requests.models.Response """ # event types event_types_to_check = [ 'b2b_transaction_received', 'buygoods_transaction_received', 'buygoods_transaction_reversed', 'merchant_to_merchant_transaction_received', 'settlement_transfer_completed', 'customer_created' ] # build subscription url subscription_url = self._build_url(WEBHOOK_SUBSCRIPTION_PATH) # define headers headers = dict(self.headers) # validate string arguments validation.validate_string_arguments(bearer_token, event_type, webhook_endpoint, webhook_secret) headers['Authorization'] = 'Bearer ' + bearer_token + '' if not any(check in event_type for check in event_types_to_check): raise exceptions.InvalidArgumentError( 'Event type not recognized by k2-connect') # validate webhook endpoint validation.validate_url(webhook_endpoint) # define subscription payload subscription_payload = json_builder.webhook_subscription( event_type=event_type, webhook_endpoint=webhook_endpoint, webhook_secret=webhook_secret) return self._make_requests(headers=headers, method='POST', url=subscription_url, payload=subscription_payload)
def _make_requests(self, headers, method, url, data=None, payload=None, params=None): """ Returns JSON payload. :param headers: Headers for HTTP request :type headers: str (JSON) :param method: Method for HTTP request (GET, POST) :type method str :param url: URL to which HTTP request is sent :type url: str :param data: Dictionary, list of tuples or bytes to send in the body of the :class:`Request`. :param payload: Payload for HTTP request :type payload: str (JSON) :param params: Query parameters for a HTTP request :type params: str (JSON) :return: str (JSON) """ if validation.validate_url(url) is True: if method == 'GET': response = self.__get_request(url=url, headers=headers, params=params) elif method == 'POST': response = self.__post_request(url=url, headers=headers, payload=payload, data=data) else: raise exceptions.InvalidArgumentError('Method not recognized by k2-connect') # define status code to check status_code = response.status_code if 200 <= status_code <= 300: # FIXME: This is a HACK. if urlparse(url).path == '/oauth/token' or method == 'GET': return response.json() response_location = response.headers.get('location') return response_location response_error = { 'error_code': response.status_code, 'error_content': response.text } raise exceptions.K2Error(response_error) return exceptions.K2Error
def add_pay_recipient(self, kwargs): """ Adds external entities that will be the destination of your payments. Returns a request response object < class, 'requests.models.Response'> :param kwargs: The values constitute all user input. :type kwargs: dict :return:'requests.models.Response' """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'recipient_type' not in kwargs: raise exceptions.InvalidArgumentError('Recipient Type not given.') if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'recipient_type' in kwargs: recipient_type = kwargs['recipient_type'] # define headers headers = dict(self._headers) validation.validate_string_arguments(bearer_token) # add bearer token headers['Authorization'] = 'Bearer ' + bearer_token # build url add_pay_url = self._build_url(url_path=ADD_PAY_PATH) if 'email' in kwargs: validation.validate_email(str(kwargs['email'])) if 'phone_number' in kwargs: validation.validate_phone_number(str(kwargs['phone_number'])) # expected parameters for bank account wallet recipient if recipient_type == BANK_ACCOUNT_RECIPIENT_TYPE: if 'account_name' not in kwargs or \ 'account_number' not in kwargs or \ 'settlement_method' not in kwargs or \ 'bank_branch_ref' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for bank account Pay recipient') # build recipient json object recipient_object = json_builder.bank_account( account_name=str(kwargs['account_name']), account_number=str(kwargs['account_number']), settlement_method=str(kwargs['settlement_method']), bank_branch_ref=str(kwargs['bank_branch_ref'])) # build bank payment recipient json object payment_recipient_object = json_builder.pay_recipient( recipient_type=recipient_type, recipient=recipient_object) # expected parameters for mobile wallet recipient # ['first_name', 'last_name', # network','phone_number','email'] elif recipient_type == MOBILE_WALLET_RECIPIENT_TYPE: if 'first_name' not in kwargs or \ 'last_name' not in kwargs or \ 'phone_number' not in kwargs or \ 'email' not in kwargs or \ 'network' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for mobile wallet Pay recipient') # create recipient json object recipient_object = json_builder.mobile_wallet( first_name=str(kwargs['first_name']), last_name=str(kwargs['last_name']), phone_number=str(kwargs['phone_number']), network=str(kwargs['network']), email=str(kwargs['email'])) # create mobile wallet recipient json object payment_recipient_object = json_builder.pay_recipient( recipient_type=recipient_type, recipient=recipient_object) elif recipient_type == TILL_RECIPIENT_TYPE: if 'till_name' not in kwargs or \ 'till_number' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for till Pay recipient') # create recipient json object recipient_object = json_builder.till_pay_recipient( till_name=str(kwargs['till_name']), till_number=str(kwargs['till_number'])) # create mobile wallet recipient json object payment_recipient_object = json_builder.pay_recipient( recipient_type=recipient_type, recipient=recipient_object) # expected parameters for mobile wallet recipient # ['till_name', 'till_number'] elif recipient_type == PAYBILL_RECIPIENT_TYPE: if 'paybill_name' not in kwargs or \ 'paybill_number' not in kwargs or \ 'paybill_account_number' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for paybill Pay recipient') # create recipient json object recipient_object = json_builder.paybill_pay_recipient( paybill_name=str(kwargs['paybill_name']), paybill_number=str(kwargs['paybill_number']), paybill_account_number=str(kwargs['paybill_account_number'])) # create mobile wallet recipient json object payment_recipient_object = json_builder.pay_recipient( recipient_type=recipient_type, recipient=recipient_object) # expected parameters for mobile wallet recipient # ['alias_name', 'till_number'] else: raise exceptions.InvalidArgumentError( 'The recipient type is not recognized by k2connect') return self._make_requests(headers=headers, method='POST', url=add_pay_url, payload=payment_recipient_object)
def send_pay(self, kwargs): """ Creates an outgoing pay to a third party. The result of the pay is provided asynchronously and posted to the callback_url provided. Returns a request response object < class, 'requests.models.Response'> :param kwargs: Provision for optional metadata with maximum of 5 key value pairs. :type kwargs: dict :return:requests.models.Response """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'destination_reference' not in kwargs or \ 'destination_type' not in kwargs or \ 'callback_url' not in kwargs or \ 'description' not in kwargs or \ 'amount' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for creating Outgoing Pay.') if 'currency' not in kwargs: currency = 'KES' if 'metadata' not in kwargs: pay_metadata = '' # iterate through kwargs if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'callback_url' in kwargs: callback_url = kwargs['callback_url'] if 'description' in kwargs: description = kwargs['description'] if 'currency' in kwargs: currency = 'KES' if 'metadata' in kwargs: pay_metadata = json_builder.metadata(kwargs['metadata']) # build send_pay url send_pay_url = self._build_url(SEND_PAY_PATH) # define headers headers = dict(self._headers) # check bearer token validation.validate_string_arguments(bearer_token) # add authorization to headers headers['Authorization'] = 'Bearer ' + bearer_token + '' # create amount json object pay_amount = json_builder.amount(currency=currency, value=kwargs['amount']) # create links json object pay_links = json_builder.links(callback_url=callback_url) # create payment json object pay_json = json_builder.pay(kwargs['destination_reference'], kwargs['destination_type'], pay_amount, description, pay_links, pay_metadata) return self._make_requests(url=send_pay_url, method='POST', payload=pay_json, headers=headers)
def settle_funds(self, kwargs): """ Creates a transfer from merchant account to a different settlement account. Returns a request response object < class, 'requests.models.Response'> :param kwargs: The values constitute all user input. :type kwargs: dict :return: requests.models.Response """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'currency' not in kwargs: currency = 'KES' if 'destination_reference' not in kwargs: destination_reference = '' if 'destination_type' not in kwargs: destination_type = '' if 'callback_url' not in kwargs or \ 'value' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for creating Outgoing Pay.') # iterate through kwargs if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'callback_url' in kwargs: callback_url = kwargs['callback_url'] if 'destination_type' in kwargs: destination_type = kwargs['destination_type'] if 'destination_reference' in kwargs: destination_reference = kwargs['destination_reference'] if 'value' in kwargs: value = kwargs['value'] # build settle funds url settle_funds_url = self._build_url(TRANSFER_PATH) # define headers headers = dict(self._headers) # check bearer token validation.validate_string_arguments(bearer_token, currency, value) # add authorization to headers headers['Authorization'] = 'Bearer ' + bearer_token + '' # define amount transfer_amount = json_builder.amount(currency=currency, value=value) # create links json object transfer_links = json_builder.links(callback_url=callback_url) if destination_reference is None and destination_type is None: settle_funds_payload = json_builder.transfers( transfer_links=transfer_links, transfers_amount=transfer_amount) else: settle_funds_payload = json_builder.transfers( transfer_links=transfer_links, transfers_amount=transfer_amount, destination_type=destination_type, destination_reference=destination_reference) return self._make_requests(headers=headers, method='POST', url=settle_funds_url, payload=settle_funds_payload)
def add_pay_recipient(self, bearer_token, recipient_type, **kwargs): """ Adds external entities that will be the destination of your payments. Returns a request response object < class, 'requests.models.Response'> :param bearer_token: Access token to be used to make calls to the Kopo Kopo API :type bearer_token: str :param recipient_type: The type of wallet to which pay will be sent. Example: recipient_type = BANK_ACCOUNT_RECIPIENT_TYPE :type recipient_type: str :param kwargs: The values thAccess token to be used to make calls to the Kopo Kopo APIat constitute recipient types. :type kwargs: dict :return:'requests.models.Response' """ # define headers headers = dict(self._headers) validation.validate_string_arguments(bearer_token) # add bearer token headers['Authorization'] = 'Bearer ' + bearer_token + '' # build url add_pay_url = self._build_url(url_path=ADD_PAY_PATH) if 'email' in kwargs: validation.validate_email(str(kwargs['email'])) if 'phone' in kwargs: validation.validate_phone_number(str(kwargs['phone'])) # expected parameters for bank account wallet recipient # ['account_name', 'account_number', # 'bank_branch_id','bank_id', name'] if recipient_type == BANK_ACCOUNT_RECIPIENT_TYPE: if 'account_name' not in kwargs or \ 'account_number' not in kwargs or \ 'bank_branch_id' not in kwargs or \ 'bank_id' not in kwargs or \ 'name' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for bank account') # build recipient json object recipient_object = json_builder.bank_account( account_name=str(kwargs['account_name']), account_number=str(kwargs['account_number']), bank_branch_id=str(kwargs['bank_branch_id']), bank_id=str(kwargs['bank_id']), name=str(kwargs['name']), email=None, phone=None) # build bank payment recipient json object payment_recipient_object = json_builder.pay_recipient( recipient_type=recipient_type, recipient=recipient_object) # expected parameters for mobile wallet recipient # ['first_name', 'last_name', # network','phone','email'] elif recipient_type == MOBILE_WALLET_RECIPIENT_TYPE: if 'first_name' not in kwargs or \ 'last_name' not in kwargs or \ 'phone' not in kwargs or \ 'network' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for mobile wallet') # create recipient json object recipient_object = json_builder.mobile_wallet( first_name=str(kwargs['first_name']), last_name=str(kwargs['last_name']), phone=str(kwargs['phone']), network=str(kwargs['network']), email=None) # create mobile wallet recipient json object payment_recipient_object = json_builder.pay_recipient( recipient_type=recipient_type, recipient=recipient_object) else: raise exceptions.InvalidArgumentError( 'The recipient type is not recognized by k2connect') return self._make_requests( headers=headers, method='POST', payload=payment_recipient_object, url=add_pay_url, )
def create_payment_request(self, kwargs): """ Creates a request for the reception of payments from MPESA users. Returns a request response object < class, 'requests.models.Response'> :param kwargs: The values constitute all user input. :type kwargs: dict :return: requests.models.Response """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'first_name' not in kwargs or \ 'last_name' not in kwargs or \ 'callback_url' not in kwargs or \ 'payment_channel' not in kwargs or \ 'phone_number' not in kwargs or \ 'till_number' not in kwargs or \ 'email' not in kwargs or \ 'amount' not in kwargs: raise exceptions.InvalidArgumentError('Invalid arguments for creating Incoming Payment Request.') if 'currency' not in kwargs: currency = 'KES' if 'metadata' not in kwargs: mpesa_payment_metadata = '' # iterate through kwargs if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'phone_number' in kwargs: phone_number = kwargs['phone_number'] if validation.validate_phone_number(phone_number) is False: pass if 'email' in kwargs: email = kwargs['email'] validation.validate_email(email) if 'currency' in kwargs: currency = 'KES' if 'metadata' in kwargs: mpesa_payment_metadata = json_builder.metadata(kwargs['pay_metadata']) # define headers headers = dict(self._headers) # validate bearer_token validation.validate_string_arguments(bearer_token) # add bearer token headers['Authorization'] = 'Bearer ' + bearer_token + '' # build create mpesa payment request url mpesa_payment_request_url = self._build_url(CREATE_RECEIVE_MPESA_PAYMENT_PATH) # define amount JSON object mpesa_payment_request_amount = json_builder.amount(currency=currency, value=kwargs['amount']) # define links JSON object mpesa_payment_request_links = json_builder.links(callback_url=kwargs['callback_url']) # define subscriber JSON object mpesa_payment_subscriber = json_builder.subscriber(first_name=kwargs['first_name'], last_name=kwargs['last_name'], phone_number=phone_number, email=email) # define MPESA payment request JSON object mpesa_payment_request_payload = json_builder.mpesa_payment(mpesa_links=mpesa_payment_request_links, mpesa_payment_amount=mpesa_payment_request_amount, mpesa_payment_subscriber=mpesa_payment_subscriber, metadata=mpesa_payment_metadata, payment_channel=kwargs['payment_channel'], till_number=kwargs['till_number']) return self._make_requests(headers=headers, method='POST', url=mpesa_payment_request_url, payload=mpesa_payment_request_payload)
def create_subscription(self, kwargs): """ Creates a subscription to a webhook service. Returns a request response object < class, 'requests.models.Response'> :param bearer_token: Access token to be used to make calls to the Kopo Kopo API :param kwargs: The values constitute all user input. :type kwargs: dict :return: requests.models.Response """ if 'access_token' not in kwargs: raise exceptions.InvalidArgumentError('Access Token not given.') if 'event_type' not in kwargs: raise exceptions.InvalidArgumentError('Event Type not given.') if 'webhook_endpoint' not in kwargs or \ 'scope' not in kwargs: raise exceptions.InvalidArgumentError( 'Invalid arguments for creating a Webhook Subscription.') if 'access_token' in kwargs: bearer_token = kwargs['access_token'] if 'event_type' in kwargs: event_type = kwargs['event_type'] if 'webhook_endpoint' in kwargs: webhook_endpoint = kwargs['webhook_endpoint'] if 'scope' in kwargs: scope = kwargs['scope'] if 'scope_reference' in kwargs: scope_reference = kwargs['scope_reference'] # event types event_types_to_check = [ 'b2b_transaction_received', 'buygoods_transaction_received', 'buygoods_transaction_reversed', 'm2m_transaction_received', 'settlement_transfer_completed', 'customer_created' ] till_scope_event_types = [ 'b2b_transaction_received', 'buygoods_transaction_received', 'buygoods_transaction_reversed' ] # build subscription url subscription_url = self._build_url(WEBHOOK_SUBSCRIPTION_PATH) # define headers headers = dict(self._headers) # validate string arguments validation.validate_string_arguments(bearer_token, event_type, webhook_endpoint, scope) if 'scope_reference' in kwargs: validation.validate_string_arguments(scope_reference) headers['Authorization'] = 'Bearer ' + bearer_token + '' if not any(check in event_type for check in event_types_to_check): raise exceptions.InvalidArgumentError( 'Event type not recognized by k2-connect') if any(check in event_type for check in till_scope_event_types): if scope != 'till': raise exceptions.InvalidArgumentError( 'Invalid scope for given event type.') if 'scope_reference' not in kwargs or kwargs[ 'scope_reference'] is None: raise exceptions.InvalidArgumentError( 'Scope reference not given.') if not any(check in event_type for check in till_scope_event_types): scope_reference = None if scope != 'company': raise exceptions.InvalidArgumentError( 'Invalid scope for given event type.') if 'scope_reference' in kwargs: raise exceptions.InvalidArgumentError( 'Invalid scope reference for given event type.') # validate webhook endpoint validation.validate_url(webhook_endpoint) # define subscription payload subscription_payload = json_builder.webhook_subscription( event_type=event_type, webhook_endpoint=webhook_endpoint, scope=scope, scope_reference=scope_reference) return self._make_requests(headers=headers, method='POST', url=subscription_url, payload=subscription_payload)