def post(self): logger = sms_api_logger_tool.GeneralLogger() logger.info(message='received change billing email request', data={ 'account_id': self.current_user.account_id, 'new email': self.get_argument('new_email', None), 'old_email': self.current_user.billing_email }) success_message = '' default_error_message = 'unable to save billing email. Please try again' error_message = '' final_result = False try: result = change_billing_email(self.current_user, self.get_argument('new_email', None)) if result: logger.info(message='successful change') success_message = 'billing email updated' final_result = True else: logger.error(message='invalid email format') error_message = 'invalid email' except AccountSaveException, e: error_message = default_error_message logger.error(message='could not save data', data=e)
def validate_rsa_signature(account_suffix, message, signature): gen_logger = sms_api_logger.GeneralLogger() response = {'error': False, 'message': SPIELS['success2']} content_provider = ContentProviders.get(account_suffix) # if not content_provider or content_provider == ' ': # response['error'] = True # response['message'] = SPIELS['error5'] # return response if not content_provider or 'PUBLIC_KEY' not in content_provider or \ content_provider['PUBLIC_KEY'] == ' ': response['error'] = True response['message'] = SPIELS['error5'] return response public_key = content_provider['PUBLIC_KEY'] if not validate_signature(public_key, signature, message): gen_logger.error('RSA signature invalid', { 'suffix': account_suffix, 'signature': signature }) response['error'] = True response['message'] = SPIELS['error4'] return response gen_logger.info('SUCCESS RSA signature validation', { 'suffix': account_suffix, 'signature': signature }) return response
def process_testmin_code_resend(account_id, testmin=None, ver_id=None): ''' @description: - handles the resending of verification code ''' # if not testmin and ver_id: # testmin = __get_min(account_id, ver_id) gen_logger = sms_api_logger.GeneralLogger() if testmin: testmin = '639%s' % str(testmin[-9:]) if __has_reached_max_code_request(account_id, testmin): gen_logger.error('testmin enrollment -- max pincode resends', { 'account_id': account_id, 'mobile': testmin }) raise MaxCodeRequestsException(account_id, testmin) correct_code = __get_vercode(account_id, testmin)['code'] send_pincode(account_id, testmin, str(correct_code)) gen_logger.info('testmin enrollment -- resending pincode (using API)', { 'account_id': account_id, 'mobile': testmin }) __save_code(account_id=account_id, ver_id=ver_id) # updates expiry date return testmin
def has_reached_max_wrong_code_tries(account_id, testmin): ''' @description: - returns True if user has inputted wrong codes more than allowed, else False - uses redis incr ''' testmin = '639%s' % str(testmin[-9:]) code_tries = Verification.incr_code_tries(account_id=account_id, testmin=testmin) # if code_tries and int(code_tries) > MAX_CODE_TRIES: gen_logger = sms_api_logger.GeneralLogger() gen_logger.info('testmin enrollment -- max pincode retries', { 'account_id': account_id, 'mobile': testmin }) # return True # return False if code_tries: return int(code_tries) return None
def add_to_signup_email_queue(self, verification_id, email, v_type): ''' verification id = id of verification table record email = email address to send to v_type = type of verification pushes the email value to the end of the queue ''' l = sms_api_logger.GeneralLogger() l.debug('adding email to signup queue', { 'email': email, 'key': self.signup_email_queue_key }) queue_item = self.__build_email_queue_item(verification_id, email, v_type) result = self.__append_to_email_queue(queue_item) l.debug('added email to queue result', { 'email': email, 'result': result }) return
def post(self): logger = sms_api_logger_tool.GeneralLogger() new_email = self.get_argument('new_email', None) logger.info('received request to change email', { 'account_id': self.current_user.account_id, 'new_email': new_email }) error_message = '' success = False success_message = '' try: change_email_tool.change_email(account_object=self.current_user, new_email=new_email) success = True success_message = 'We sent a verification request to your email.' except PendingAccountAlreadyExisting, e: if e.verification_object: error_message = 'The email address has a pending verification request. <a href="/signup/resend/%s">Click here</a> to resend verification request' % e.verification_object.code else: error_message = 'The email address has a pending verification request.' success = False
def get(self, code): logger = sms_api_logger_tool.GeneralLogger() error_message = '' # step 1 # verify change email error = False error_message = '' success_message = '' try: logger.info('received change email verify from web', data=code) change_email_tool.verify_change_email(code=code) except VerificationExpired, e: main_spiel = 'The confirmation link has already expired' logger.error('attempted to use expired verification code', data=code) error_message = '%s. <a href="/changeemail/verify/resend/%s">Click here</a> to resend verification request.' % ( main_spiel, code)
def set_api_trial_credits(self, suffix): ''' @description: - called when user buys a shortcode - sets api_trial settings to TRIAL_CREDITS in INFRA's redis ''' gen_logger = sms_api_logger.GeneralLogger() KEY = REDIS_CONTENT_PROVIDERS % str(suffix) try: self.redisconn.hset(KEY, TRIAL_CREDITS_KEY, str(CREDITS_COUNT)) self.redisconn.hset(KEY, 'ACTIVE', str(2)) # self.redisconn.hset(KEY, 'TEST_MIN', # str(('639%s' %kwargs['testmin'][-9:]))) # self.redisconn.expire(KEY, # REDIS_CONTENT_PROVIDERS_TRIAL_EXPIRATION) gen_logger.info('updating TRIAL CREDITS', {'suffix': suffix}) except Exception, e: gen_logger.error('error updating TRIAL CREDITS', { 'suffix': suffix, 'error': str(e) }) print e
def send_mt_message(account_id, suffix, testmin, mt_message, client_id, secret_key): ''' uses API to send MT message to user ''' gen_logger = sms_api_logger.GeneralLogger() if not mt_message: message_id = send_trial_mt(suffix, testmin, SENT_TRIAL_MESSAGE % DEFAULT_MESSAGE, client_id, secret_key) elif len(mt_message) > MESSAGE_LEN: message_id = None else: message_id = send_trial_mt(suffix, testmin, SENT_TRIAL_MESSAGE % mt_message, client_id, secret_key) gen_logger.info('Hitting API to sending MT message', {'account_id': account_id, 'mobile': testmin, 'suffix': suffix, 'message_id': message_id}) Verification.set_message_sent_to_pending( testmin[-12:], message_id) return message_id
def post(self): ''' handles request to update balance threshold value all errors are thrown as an exception and result=False is returned iin JSON format if successful result=True is returned ''' new_threshold = self.get_argument('new_threshold', None) logger = sms_api_logger_tool.GeneralLogger() user = self.current_user try: old_threshold = user.balance_notif_threshold update_balance_threshold(account_object=user, threshold=new_threshold) logger.info( 'updated balance threshold', { 'account_id': user.account_id, 'old_threshold': old_threshold, 'new_threshold': new_threshold }) except Exception, e: logger.error('update balance threshold. unexpected error: %s' % e, {'account_id': user.account_id}) self.write(json.dumps({'result': False}))
def get(self, code): try: change_email_tool.resend_change_email_verify(code) except Exception, e: logger = sms_api_logger_tool.GeneralLogger() logger.info('change email resend verification failed', data={'code': code})
def process_code_list_generation(account_id, starts_with): ''' @description: - encapsulates the whole shortcode generation process. - this will be the only function called by the handlers if they need a shortcode list ''' gen_logger = sms_api_logger.GeneralLogger() # is shortcode valid format? if not match(ALLOWED_CODE, starts_with): gen_logger.error('Invalid shortcode', { 'account_id': account_id, 'shortcode_tried': starts_with }) raise ShortcodeFormatInvalidException(account_id, starts_with) starts_with = alpha_to_numeric(starts_with) code_list = __generate_shortcode_list(account_id, starts_with) tries = 0 # the code list generated may contain less than 10 # shortcodes (i.e. the generated shortcode was already # taken). These loop ensures that the system tried # atleast MAX_CODE_GEN_TRIES before returning a # code list with less than 10 shortcodes while tries < MAX_CODE_GEN_TRIES and \ type(code_list) == list and \ len(code_list) < 10: if tries > 0: gen_logger.info( 'shortcode generated less than 10. Trying to regenerate MORE codes', { 'account_id': account_id, 'tries': tries, 'shortcode_tried': starts_with }) if len(code_list) > 0: code_list.extend( __generate_shortcode_list(account_id, starts_with, code_list)) tries += 1 if not code_list: gen_logger.error('No shortcode match', { 'account_id': account_id, 'shortcode_tried': starts_with }) raise NoShortcodeMatchException(account_id, starts_with) return __trim_code_list(code_list)
def set_message_sent_to_success(mobile, message_id): gen_logger = sms_api_logger.GeneralLogger() try: return Verification.set_message_sent_to_success( mobile, message_id) except Exception, e: gen_logger.error('TEST MT sent status to SUCCESS', {'mobile': mobile, 'message_id': message_id})
def __init__(self, values): l = chikka_sms_api_logger.GeneralLogger() l.info('starting chikka sms api storefront web') # check necessary connections all_connected = check_connections(values) # do not load application if connections are down if all_connected: self.load_handlers() handlers = route.get_routes() settings = dict( # this is the salt used to build cookies cookie_secret='thesecretcookie', # this is required by tornado to determine the login page login_url='/signin', # this is to tell tornado where the templates are (absolute path) template_path=os.path.join( os.path.dirname(__file__), "%s/templates" % self.app_relative_path), # this is to tell tornado where the static files are (js, css etc) static_path=os.path.join(os.path.dirname(__file__), "%s/static" % self.app_relative_path), config=values, debug=True, log_method=values['log_method'], dragonapi_url=values['dragonpay']['payment_url']) # add special static file directory with custom handler for SVG files # we set the route as static-svg/(.*) # see ChikkaApiStaticFileHandler class definition below static_svg_path = os.path.join( os.path.dirname(__file__), "%s/static_with_svg" % self.app_relative_path) handlers.append((r"/static-svg/(.*)", ChikkaApiStaticFileHandler, { "path": static_svg_path })) l.info('running web app') tornado.web.Application.__init__(self, handlers=handlers, reload_func=self.terminator, **settings) else: l.error('not all connections loaded, exiting app') raise KeyboardInterrupt()
def main(): try: parse_command_line() Configuration.initialize() import features.logging as chikka_sms_api_logger l = chikka_sms_api_logger.GeneralLogger() app_type = options.app port = options.port debug = True if debug: print "[!!!DEBUG MODE!!!]" bind_to_cpu = -2 log_method='file' scribe_host=None scribe_port = 1234 category = 'smsapi_access' server_ip = '10.11.2.225' app = application_factory[app_type] ghttp_args = { "port": port, "bind_to_cpu": int(bind_to_cpu) } l.info('running gtornado at %s/%s' % ( os.path.dirname(os.path.realpath(__file__)), __file__ ), { 'settings': ghttp_args} ) if options.config != 'prod': ghttp_args['log_method'] = 'file' http_server = GHTTPServer(app, **ghttp_args ) #start the server http_server.start() GIOLoop.instance().start() except KeyboardInterrupt: pass
def process_testmin_code_verification(suffix, account_id, testmin, code): ''' @description: - handles testmin code verificition ''' gen_logger = sms_api_logger.GeneralLogger() testmin = '639%s' % str(testmin[-9:]) correct_code = __get_vercode(account_id, testmin) if not __is_code_correct(correct_code, code): gen_logger.error( 'testmin enrollment -- incorrect pincode', { 'account_id': account_id, 'mobile': testmin, 'code': code, 'suffix': suffix }) raise WrongCodeException(account_id, testmin, code) if __is_code_expired (correct_code) and \ __has_reached_max_code_request(account_id, testmin): gen_logger.error( 'testmin enrollment -- expired pincode, max code requests', { 'account_id': account_id, 'mobile': testmin, 'code': code, 'suffix': suffix }) raise ExpiredCodeMaxCodeRequestException(account_id, testmin, code) if __is_code_expired(correct_code): gen_logger.error( 'testmin enrollment -- expired pincode', { 'account_id': account_id, 'mobile': testmin, 'code': code, 'suffix': suffix }) raise ExpiredCodeException(account_id, testmin, code) __save_testmin(account_id, testmin) ContentProviders.update_cached_api_min(suffix, testmin) Verification.delete_mobile_code(account_id, testmin)
def save_mo_message(account_id, mo_message): ''' saves MO message in Account table ''' if len(mo_message) > MESSAGE_LEN: return None gen_logger = sms_api_logger.GeneralLogger() gen_logger.info('testmin MO -- saving MO reply', {'account_id': account_id, 'mo_message': mo_message}) return Account.update(account_id=account_id, test_mo_reply=(SENT_TRIAL_MESSAGE % mo_message))
def __save_code(account_id, code=None, testmin=None, ver_id=None): ''' saves the code generated in the Verification table ''' if testmin: testmin = '639%s' % str(testmin[-9:]) gen_logger = sms_api_logger.GeneralLogger() try: ver_obj = Verification.get_mobile_code(account_id=account_id, testmin=testmin) if ver_obj or ver_id: if not ver_id: ver_id = ver_obj['id'] if code: Verification.update_mobile_code(account_id=account_id, code=code, mobile=testmin, ver_id=ver_id) else: Verification.update_mobile_code(account_id=account_id, mobile=testmin, ver_id=ver_id) gen_logger.info('testmin enrollment -- updating pincode', {'account_id': account_id}) return ver_obj['id'] if not ver_id else ver_id else: gen_logger.info('testmin enrollment -- saving pincode', { 'account_id': account_id, 'pincode': code }) return Verification.save_mobile_code(account_id=account_id, code=code, mobile=testmin) except DuplicateVerificationCodeException, e: gen_logger.info('testmin enrollment -- pincode not unique', { 'account_id': account_id, 'error': str(e) }) save_code(account_id, code, testmin)
def update_cached_api_settings(self, suffix, **kwargs): ''' @description: - inserts to INFRA's redis for API usage ''' data = {} if 'client_id' in kwargs: data['CLIENT_ID'] = kwargs['client_id'] if 'secret_key' in kwargs: data['SECRET_KEY'] = kwargs['secret_key'] if 'public_key' in kwargs: data['PUBLIC_KEY'] = kwargs['public_key'] if 'mo_url' in kwargs: data['MO_ENDPOINT'] = kwargs['mo_url'] if 'callback_url' in kwargs: data['DN_ENDPOINT'] = kwargs['callback_url'] if 'active' in kwargs: data['ACTIVE'] = kwargs['active'] """ data = { 'PUBLIC_KEY' : kwargs['public_key'], # 'TEST_MIN' : str(('639%s' %kwargs['testmin'][-9:])), 'MO_ENDPOINT' : kwargs['mo_url'], 'DN_ENDPOINT' : kwargs['callback_url'] # 'ACTIVE': str(2) # 2 for TRIAL # 'TRIAL_CREDITS' : 20 # to consult } """ gen_logger = sms_api_logger.GeneralLogger() KEY = REDIS_CONTENT_PROVIDERS % str(suffix) try: for key in data: self.redisconn.hset(KEY, key, data[key]) gen_logger.info('updating API settings', {'suffix': suffix}) except Exception, e: gen_logger.error('error updating API settings', { 'suffix': suffix, 'error': str(e) }) print e
def get(self): logger = sms_api_logger.GeneralLogger() checkout_id = self.get_argument( 'checkout_id', None ) response = {'result' : False, 'error_message':''} default_log_data = {'checkout_id' : checkout_id, 'current_account_id' : self.current_user.account_id } try : logger.info( 'requesting resend sms', default_log_data ) resend_pin_code.resend_sms( checkout_id=checkout_id ) response['result'] = True response['success_message'] = "A PIN code has been sent. You may request to resend PIN code up to 3x per transaction only. Your PIN is valid for 30 minutes." logger.info( 'resend sms request success', default_log_data ) except resend_pin_code.MaxResendReachedError ,e: logger.error( 'max resends reached' , default_log_data ) response['error_message'] = 'You have reached the maximum number of PIN code requests per transaction. Please wait for your PIN code to arrive.'
def update_cached_api_min(self, suffix, min): gen_logger = sms_api_logger.GeneralLogger() try: KEY = REDIS_CONTENT_PROVIDERS % str(suffix) self.redisconn.hset(KEY, 'TEST_MIN', str(('639%s' % min[-9:]))) gen_logger.info('updating TESTMIN in API', { 'suffix': suffix, 'testmin': min }) except Exception, e: gen_logger.error('error updating TESTMIN in API', { 'suffix': suffix, 'testmin': min }) print e
def get(self): logger = sms_api_logger.GeneralLogger() checkout_id = self.get_argument('cid', None) current_user = self.current_user try : logger.info('attempting to pay via smart payment', {'current_account_id':current_user.account_id, 'checkout_id' :checkout_id }) checkout_id = int(checkout_id) checkout_object = get_checkout_for_enter_code( account_id=current_user.account_id, checkout_id=checkout_id ) except CheckoutExpiredError, e : logger.error('enter pin code screen: EXPIRED ; %s' %e , {'current_account_id':current_user.account_id, 'checkout_id' :checkout_id }) self.redirect('/cart?notif-type=code-expired')
def post(self): logger = sms_api_logger.GeneralLogger() logger.info('received shopping cart payment request') ''' allowed payment_type: [ smart, credit_card, seven_eleven, dragonplay, globe_cashformat( 300000, ',.2f') ] ''' account_id = self.get_current_user().account_id try: cart_items_count = get_cart_items_count(account_id) if cart_items_count == 0: self.redirect('/cart') except NoSuffixException, e: self.redirect('/shortcode')
def post(self): logger = sms_api_logger.GeneralLogger() data = json.loads(self.request.body) # logger.info('start :: CheckoutHookSuccessHandler :: request_body =' % data) print '==============' print type(data) print '==============' params = { 'receipt_number' : data['receiptNumber'] or "", 'transaction_reference_number' : data['transactionReferenceNumber'] or "", 'status' : data['status'] or "", 'payment_status' : data['paymentStatus'] or "" } #get checkout_id in paymaya_checkout checkout_id = None checkout_id = paymaya_main.get_checkout_id_by_paymaya_checkout(data['id']); _checkout_id = checkout_id['checkout_id'] params.update({'checkout_id': _checkout_id}) print _checkout_id #update paymaya_checkout to success paymaya_main.update_paymaya_checkout_details(_checkout_id, params) if data['status'] == "COMPLETED" and data['paymentStatus'] == "PAYMENT_SUCCESS" : print "update purchase history" #get account_id in purchase_history account_id = None account_id = paymaya_main.get_account_id_by_checkout(_checkout_id) params.update({'id': account_id}) print account_id #update purchase history to success paymaya_main.on_payment_webhook_success(_checkout_id, account_id) # logger.info('end :: CheckoutHookSuccessHandler') print "end of webhooks success" self.write(json.dumps(params)) self.finish()
def get(self): logger = sms_api_logger.GeneralLogger() checkout_id = self.get_argument('checkout_id') #check if transaction is already successfull then redirect to dashboard if paymaya_main.is_already_successful( checkout_id ) : self.redirect("/dashboard"); paymaya_checkout_details = paymaya_main.get_payamaya_checkout_details( checkout_id ) #call Paymaya checkout information if paymaya_checkout_details['paymaya_checkout_id']: try : paymaya_checkout_url = paymaya_main.get_paymaya_checkout_url() + "/" + paymaya_checkout_details['paymaya_checkout_id'] #build headers paymaya_request_headers = paymaya_main.get_request_headers('secret_key') # #build params request = Request(paymaya_checkout_url, headers=paymaya_request_headers) response_body = loads(urlopen(request).read()) #update checkout details update_params = { 'receipt_number' : response_body['receiptNumber'] or "", 'transaction_reference_number' : response_body['transactionReferenceNumber'] or "", 'status' : response_body['status'], 'payment_status' : response_body['paymentStatus'] } paymaya_main.update_paymaya_checkout_details( checkout_id, update_params ) if response_body['status'] == "COMPLETED" and response_body['paymentStatus'] == "PAYMENT_SUCCESS" : paymaya_main.on_payment_success( checkout_id, self.get_current_user().account_id ) self.redirect("/dashboard") except Exception, e: logger.error( 'unable to get paymaya express checkout. try again: %s' % e, {'checkout_id': checkout_id } )
def post(self, enable_disable): logger = sms_api_logger_tool.GeneralLogger() user = self.current_user try: if 'enable' == enable_disable: user.enable_balance_notification() logger.info('enable balance threshold notification', {'account_id': user.account_id}) elif 'disable' == enable_disable: user.disable_balance_notification() logger.info('disable balance threshold notification', {'account_id': user.account_id}) else: print 'invalid input' except Exception, e: logger.error( 'enable/disable balance notif unexpected error: %s' % e, { 'type': enable_disable, 'account_id': user.account_id }) self.write(json.dumps({'result': False}))
def post(self): l = sms_api_logger.GeneralLogger() l.info('attempted signup wia web', {'email':self.get_argument('email', '')}) email = self.get_argument('email', '') password = self.get_argument('password', '') password_again = self.get_argument('password_again', '') response = {} # check if passwordds are the same error_message = '' error = False first_name = None last_name = None company_name = None address = None try : response = reg_tool.register_user( first_name=first_name, last_name=last_name, email=email, company_name=company_name, address=address, password=password, password_again=password_again) # except password_tool.InvalidPasswordFormat, e : # error = True # error_message = 'Your password must be 8 to 32 characters with no special characters. Please check and try again.' except ActiveAccountAlreadyExisting, e : error = True error_message = 'The account already exists. To reset your password, click <a href="/forgotmypassword/">here.</a>'
def post(self): mobile = self.get_argument('mobile_number', None) message_id = self.get_argument('message_id', None) status = self.get_argument('status', None) gen_logger = sms_api_logger.GeneralLogger() gen_logger.info('MT text CALLBACK HIT', {'message_id': message_id, 'mobile': mobile}) if not mobile or not message_id or not status: response = 'Error' elif status.lower() == 'sent': set_message_sent_to_success(mobile, message_id) response = 'Accepted' else: response = 'Error' # self.write(response) self.finish(response)
def notif_process(): # recover items from queue # loop each item in bckup queue print 'start flush' while True: print 'step' # flushes out backup queue until empty popped_value = BalanceNotification.pop_balance_backup_notif() if not popped_value: break # start regular loop while True: l = chikka_sms_api_logger.GeneralLogger() popped_value = BalanceNotification.pop_balance_notif() l.info('received item for notification', {'suffix': popped_value}) process_suffix_balance_notification(popped_value, l) # remove popped value from backup queue BalanceNotification.pop_out_backup_queue() gevent.sleep(5)
def post(self): ''' receives name from subited form and saves it to database ''' logger = sms_api_logger_tool.GeneralLogger() name = self.get_argument('new_name', None) logger.info( 'received ajax request to change complete name / company name', data={ 'account_id': self.current_user.account_id, 'original_name': self.current_user.name, 'new_name': name }) try: update_name(account_object=self.current_user, name=name) response = {'result': True} except Exception, e: print 'unable to update name' response = {'result': False} logger.error('error in changing name', data=e)