def post(nr_num): try: # TODO: Validate NR string format # if not RequestDAO.validNRFormat(nr_num): # return jsonify(message='NR number is not in a valid format \'NR 9999999\''), 400 nr_draft = RequestDAO.find_by_nr(nr_num) if not nr_draft: # Should this be a 400 or 404... hmmm return jsonify(message='{nr_num} not found'.format(nr_num=nr_num)), 400 json_input = request.get_json() if not json_input: return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400 elif isinstance(json_input, str): json_input = json.loads(json_input) # Grab the info we need off the request payment_info = json_input.get('paymentInfo') filing_info = json_input.get('filingInfo') business_info = json_input.get('businessInfo') # Create our payment request req = PaymentRequest( payment_info=payment_info, filing_info=filing_info, business_info=business_info ) payment_response = create_payment(req) if not payment_response: raise PaymentServiceError(message=MSG_ERROR_CREATING_RESOURCE) if payment_response and payment_response.status_code == PaymentStatusCode.CREATED.value: # Save the payment info to Postgres payment = PaymentDAO() payment.nrId = nr_draft.id payment.payment_token = str(payment_response.id) payment.payment_completion_date = payment_response.created_on payment.payment_status_code = PaymentState.CREATED.value payment.save_to_db() data = jsonify(payment_response.to_dict()) response = make_response(data, 200) return response except PaymentServiceError as err: return handle_exception(err, err.message, 500) except SBCPaymentException as err: return handle_exception(err, err.message, 500) except SBCPaymentError as err: return handle_exception(err, err.message, 500) except Exception as err: return handle_exception(err, err, 500)
def post(self, nr_id, payment_action=NameRequestActions.COMPLETE.value): """ At this point, the Name Request will still be using a TEMPORARY NR number. Confirming the payment on the frontend triggers this endpoint. Here, we: - Save the request to NRO which gives us a real NR. - Create the payment via SBC Pay. - If payment creation is successful, create a corresponding payment record in our system. :param nr_id: :param payment_action: :return: """ try: # Find the existing name request nr_model = RequestDAO.query.get(nr_id) if not nr_model: # Should this be a 400 or 404... hmmm return jsonify(message='Name Request {nr_id} not found'.format( nr_id=nr_id)), 400 if not payment_action: return jsonify( message='Invalid payment action, {action} not found'. format(action=payment_action)), 400 valid_payment_action = payment_action in [ NameRequestActions.COMPLETE.value, NameRequestActions.UPGRADE.value, NameRequestActions.REAPPLY.value ] if not valid_payment_action: return jsonify( message='Invalid payment action [{action}]'.format( action=payment_action)), 400 # We only handle payments if the NR is in the following states valid_payment_states = [ State.DRAFT, State.COND_RESERVE, State.RESERVED, State.CONDITIONAL, State.APPROVED ] valid_nr_state = nr_model.stateCd in valid_payment_states if not valid_nr_state: return jsonify(message='Invalid NR state'.format( action=payment_action)), 400 if valid_payment_action and valid_nr_state: if payment_action in [NameRequestActions.COMPLETE.value]: # Save the record to NRO, which swaps the NR-L Number for a real NR update_solr = True nr_model = self.add_records_to_network_services( nr_model, update_solr) json_input = request.get_json() payment_request = {} if not json_input: # return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400 # Grab the data from the NR, if it exists payment_request = build_payment_request(nr_model) elif isinstance(json_input, dict): payment_request = merge_payment_request(nr_model, json_input) elif isinstance(json_input, str): payment_request = merge_payment_request( nr_model, json.loads(json_input)) # Grab the info we need off the request payment_info = payment_request.get('paymentInfo') filing_info = payment_request.get('filingInfo') business_info = payment_request.get('businessInfo') # Create our payment request req = PaymentRequest(payment_info=payment_info, filing_info=filing_info, business_info=business_info) payment_response = create_payment(req) if not payment_response: raise PaymentServiceError(message=MSG_ERROR_CREATING_RESOURCE) if payment_response and payment_response.status_code == PaymentStatusCode.CREATED.value: # Save the payment info to Postgres payment = PaymentDAO() payment.nrId = nr_model.id payment.payment_token = str(payment_response.id) payment.payment_completion_date = payment_response.created_on payment.payment_status_code = PaymentState.CREATED.value payment.save_to_db() # Wrap the response, providing info from both the SBC Pay response and the payment we created data = jsonify({ 'id': payment.id, 'nrId': payment.nrId, 'token': payment.payment_token, 'statusCode': payment.payment_status_code, 'completionDate': payment.payment_completion_date, 'payment': payment.as_dict(), 'sbcPayment': payment_response.to_dict() }) # Record the event nr_svc = self.nr_service # EventRecorder.record(nr_svc.user, Event.PATCH + ' [payment ID: {id}]'.format(id=payment.id), nr_model, data) response = make_response(data, 201) return response except PaymentServiceError as err: return handle_exception(err, err.message, 500) except SBCPaymentException as err: return handle_exception(err, err.message, err.status_code) except SBCPaymentError as err: return handle_exception(err, err.message, 500) except Exception as err: return handle_exception(err, err, 500)
filing_info.get('filingTypes')[0]['waiveFees'] = waive_fees if 'waiveFees' in headers: del headers['waiveFees'] # This is to support staff-payment-enabled switch to false in Launch Darkly if not account_info and not waive_fees: headers = {} # Create our payment request req = PaymentRequest(paymentInfo=payment_info, filingInfo=filing_info, businessInfo=business_info, accountInfo=account_info, details=details) payment_response = create_payment(req.as_dict(), headers) try: successful_status_list = [ PaymentStatusCode.APPROVED.value, PaymentStatusCode.CREATED.value, PaymentStatusCode.COMPLETED.value ] if payment_response.statusCode in successful_status_list: # Save the payment info to Postgres payment = PaymentDAO() payment.nrId = nr_model.id payment.payment_token = str(payment_response.id) # namex-pay will set payment_status_code to completed state after actioning it on the queue payment.payment_status_code = payment_response.statusCode payment.payment_action = payment_action payment.save_to_db()
def post(self, nr_id, payment_action=NameRequestActions.CREATE.value): """ At this point, the Name Request will still be using a TEMPORARY NR number. Confirming the payment on the frontend triggers this endpoint. Here, we: - Save the request to NRO which gives us a real NR. - Create the payment via SBC Pay. - If payment creation is successful, create a corresponding payment record in our system. :param nr_id: :param payment_action: :return: """ try: # Find the existing name request nr_model = RequestDAO.query.get(nr_id) if not nr_model: # Should this be a 400 or 404... hmmm return jsonify(message='Name Request {nr_id} not found'.format(nr_id=nr_id)), 400 if not payment_action: return jsonify(message='Invalid payment action, {action} not found'.format(action=payment_action)), 400 valid_payment_action = payment_action in [ NameRequestActions.CREATE.value, NameRequestActions.UPGRADE.value, NameRequestActions.REAPPLY.value ] if not valid_payment_action: return jsonify(message='Invalid payment action [{action}]'.format(action=payment_action)), 400 # We only handle payments if the NR is in the following states valid_payment_states = [State.DRAFT, State.COND_RESERVE, State.RESERVED, State.CONDITIONAL, State.APPROVED, State.PENDING_PAYMENT] valid_nr_state = nr_model.stateCd in valid_payment_states if not valid_nr_state: return jsonify(message='Invalid NR state'.format(action=payment_action)), 400 if valid_payment_action and valid_nr_state: if payment_action in [NameRequestActions.CREATE.value]: # Save the record to NRO, which swaps the NR-L Number for a real NR update_solr = True nr_model = self.add_records_to_network_services(nr_model, update_solr) json_input = request.get_json() payment_request = {} if not json_input: # return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400 # Grab the data from the NR, if it exists payment_request = build_payment_request(nr_model) elif isinstance(json_input, dict): payment_request = merge_payment_request(nr_model, json_input) elif isinstance(json_input, str): payment_request = merge_payment_request(nr_model, json.loads(json_input)) # Grab the info we need off the request payment_info = payment_request.get('paymentInfo', {}) filing_info = payment_request.get('filingInfo') business_info = payment_request.get('businessInfo') # Create our payment request req = PaymentRequest( paymentInfo=payment_info, filingInfo=filing_info, businessInfo=business_info ) payment_response = create_payment(req.as_dict(), json_input.get('headers')) try: successful_status_list = [ PaymentStatusCode.APPROVED.value, PaymentStatusCode.CREATED.value, PaymentStatusCode.COMPLETED.value ] if payment_response.statusCode in successful_status_list: # Save the payment info to Postgres payment = PaymentDAO() payment.nrId = nr_model.id payment.payment_token = str(payment_response.id) # namex-pay will set payment_status_code to completed state after actioning it on the queue payment.payment_status_code = payment_response.statusCode payment.payment_action = payment_action payment.save_to_db() # happens for PAD. If completed/approved right away queue will have err'd so apply changes here # TODO: send email / furnish payment for these if payment_response.statusCode in [PaymentStatusCode.APPROVED.value, PaymentStatusCode.COMPLETED.value]: if payment_action == PaymentDAO.PaymentActions.CREATE.value: # pylint: disable=R1705 if nr_model.stateCd == State.PENDING_PAYMENT: nr_model.stateCd = State.DRAFT payment.payment_completion_date = datetime.utcnow() elif payment_action == PaymentDAO.PaymentActions.UPGRADE.value: # TODO: handle this (refund payment and prevent action?) if nr_model.stateCd == State.PENDING_PAYMENT: msg = f'Upgrading a non-DRAFT NR for payment.id={payment.id}' current_app.logger.debug(msg) nr_model.priorityCd = 'Y' nr_model.priorityDate = datetime.utcnow() payment.payment_completion_date = datetime.utcnow() elif payment_action == PaymentDAO.PaymentActions.REAPPLY.value: # TODO: handle this (refund payment and prevent action?) if nr_model.stateCd != State.APPROVED \ and nr_model.expirationDate + timedelta(hours=NAME_REQUEST_EXTENSION_PAD_HOURS) < datetime.utcnow(): msg = f'Extend NR for payment.id={payment.id} nr_model.state{nr_model.stateCd}, nr_model.expires:{nr_model.expirationDate}' current_app.logger.debug(msg) nr_model.expirationDate = nr_model.expirationDate + timedelta(days=NAME_REQUEST_LIFESPAN_DAYS) payment.payment_completion_date = datetime.utcnow() nr_model.save_to_db() payment.save_to_db() # Wrap the response, providing info from both the SBC Pay response and the payment we created data = jsonify({ 'id': payment.id, 'nrId': payment.nrId, 'nrNum': nr_model.nrNum, 'token': payment.payment_token, 'statusCode': payment.payment_status_code, 'action': payment.payment_action, 'completionDate': payment.payment_completion_date, 'payment': payment.as_dict(), 'sbcPayment': payment_response.as_dict() }) # Record the event # nr_svc = self.nr_service # EventRecorder.record(nr_svc.user, Event.POST + ' [payment created]', json_input) response = make_response(data, 201) return response # something went wrong with status code above else: # log actual status code current_app.logger.debug('Error with status code. Actual status code: ' + payment_response.statusCode) # return generic error status to the front end return jsonify(message='Name Request {nr_id} encountered an error'.format(nr_id=nr_id)), 402 except Exception as err: current_app.logger.error(err.with_traceback(None)) return jsonify(message='Name Request {nr_id} encountered an error'.format(nr_id=nr_id)), 500 except PaymentServiceError as err: return handle_exception(err, err.message, 500) except SBCPaymentException as err: return handle_exception(err, err.message, err.status_code) except SBCPaymentError as err: return handle_exception(err, err.message, 500) except Exception as err: return handle_exception(err, err, 500)