fix: Unified scarf setup (#8238)

This commit is contained in:
Shailesh-714
2025-06-09 12:54:29 +05:30
committed by GitHub
parent 5ab769d116
commit 473344e9b3
7 changed files with 430 additions and 346 deletions

2
.gitignore vendored
View File

@@ -120,6 +120,7 @@ fabric.properties
### dotenv ###
.env
.oneclick-setup.env
### Linux ###
*~
@@ -145,7 +146,6 @@ fabric.properties
# Icon must end with two \r
Icon
# Thumbnails
._*

View File

@@ -11,6 +11,8 @@ services:
prestart-hook:
image: curlimages/curl-base:latest
container_name: prestart-hook
environment:
- ONE_CLICK_SETUP=${ONE_CLICK_SETUP:-false}
entrypoint:
[
"/bin/sh",
@@ -29,7 +31,7 @@ services:
networks:
- router_net
volumes:
- pg_data:/VAR/LIB/POSTGRESQL/DATA
- pg_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=db_user
- POSTGRES_PASSWORD=db_pass
@@ -108,23 +110,6 @@ services:
start_period: 5s
timeout: 5s
poststart-hook:
image: curlimages/curl-base:latest
container_name: poststart-hook
depends_on:
hyperswitch-server:
condition: service_healthy # Ensures it only starts when `hyperswitch-server` is healthy
entrypoint:
[
"/bin/sh",
"-c",
"apk add --no-cache bash jq && /bin/bash /poststart_hook.sh",
]
volumes:
- ./scripts/poststart_hook.sh:/poststart_hook.sh
networks:
- router_net
hyperswitch-producer:
image: docker.juspay.io/juspaydotin/hyperswitch-producer:standalone
pull_policy: always
@@ -223,6 +208,49 @@ services:
labels:
logs: "promtail"
create-default-user:
image: curlimages/curl-base:latest
container_name: create-default-user
depends_on:
hyperswitch-server:
condition: service_healthy
hyperswitch-control-center:
condition: service_started
environment:
- HYPERSWITCH_SERVER_URL=http://hyperswitch-server:8080
- HYPERSWITCH_CONTROL_CENTER_URL=http://hyperswitch-control-center:9000
entrypoint:
[
"/bin/sh",
"-c",
"apk add --no-cache bash jq && /bin/bash /create_default_user.sh",
]
volumes:
- ./scripts/create_default_user.sh:/create_default_user.sh
networks:
- router_net
poststart-hook:
image: curlimages/curl-base:latest
container_name: poststart-hook
depends_on:
create-default-user:
condition: service_completed_successfully
hyperswitch-server:
condition: service_healthy # Ensures it only starts when `hyperswitch-server` is healthy
environment:
- ONE_CLICK_SETUP=${ONE_CLICK_SETUP:-false}
entrypoint:
[
"/bin/sh",
"-c",
"apk add --no-cache bash jq && /bin/bash /poststart_hook.sh",
]
volumes:
- ./scripts/poststart_hook.sh:/poststart_hook.sh
networks:
- router_net
### Clustered Redis setup
redis-cluster:
image: redis:7
@@ -476,4 +504,4 @@ services:
- HYPERSWITCH_CLIENT_URL=http://localhost:9050
- HYPERSWITCH_SERVER_URL=http://localhost:8080
labels:
logs: "promtail"
logs: "promtail"

View File

@@ -0,0 +1,138 @@
#! /usr/bin/env bash
EMAIL="demo@hyperswitch.com"
PASSWORD="Hyperswitch@123"
# Initialize merchant_id and profile_id to empty strings
merchant_id=""
profile_id=""
# Test the health endpoint first to ensure the API is responsive
health_response=$(curl -s -w "\\nStatus_Code:%{http_code}" "${HYPERSWITCH_SERVER_URL}/health")
health_status_code=$(echo "${health_response}" | grep "Status_Code:" | cut -d':' -f2)
health_response_body=$(echo "${health_response}" | head -n1)
# Try signin first
signin_payload="{\"email\":\"${EMAIL}\",\"password\":\"${PASSWORD}\"}"
signin_response=$(curl -s -X POST -H "Content-Type: application/json" -H "api-key: hyperswitch" -H "User-Agent: HyperSwitch-Shell-Client/1.0" -H "Referer: ${HYPERSWITCH_CONTROL_CENTER_URL}/" -d "${signin_payload}" "${HYPERSWITCH_SERVER_URL}/user/signin")
# Check if user needs to be created
if [[ $(
echo "${signin_response}" | grep -q "error"
echo $?
) -eq 0 ]]; then
# User doesn't exist or login failed, create new account
signup_payload="{\"email\":\"${EMAIL}\",\"password\":\"${PASSWORD}\",\"country\":\"IN\"}"
# Only try signing up once - using exact headers from browser
# For making signup request without verbose logging
signup_cmd="curl -s -X POST '${HYPERSWITCH_SERVER_URL}/user/signup' \
-H 'Accept: */*' \
-H 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' \
-H 'Content-Type: application/json' \
-H 'Origin: ${HYPERSWITCH_CONTROL_CENTER_URL}' \
-H 'Referer: ${HYPERSWITCH_CONTROL_CENTER_URL}/' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36' \
-H 'api-key: hyperswitch' \
-d '${signup_payload}'"
signup_response=$(eval "${signup_cmd}")
# Extract token from signup response
token=$(echo "${signup_response}" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
token_type=$(echo "${signup_response}" | grep -o '"token_type":"[^"]*"' | cut -d'"' -f4)
is_new_user=true
else
auth_response="${signin_response}"
token=$(echo "${auth_response}" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
token_type=$(echo "${auth_response}" | grep -o '"token_type":"[^"]*"' | cut -d'"' -f4)
is_new_user=false
fi
# Handle 2FA if needed
if [ "${token_type}" = "totp" ]; then
MAX_RETRIES=3
for i in $(seq 1 ${MAX_RETRIES}); do
terminate_response=$(curl -s -X GET -H "Content-Type: application/json" -H "api-key: hyperswitch" -H "authorization: Bearer ${token}" "${HYPERSWITCH_SERVER_URL}/user/2fa/terminate?skip_two_factor_auth=true")
new_token=$(echo "${terminate_response}" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
if [ -n "${new_token}" ]; then
token="${new_token}"
break
else
if [ $i -lt ${MAX_RETRIES} ]; then
sleep 1
fi
fi
done
fi
# Get user info
if [ -n "${token}" ]; then
user_info_cmd="curl -s -X GET -H 'Content-Type: application/json' -H 'api-key: hyperswitch' -H 'authorization: Bearer ${token}' '${HYPERSWITCH_SERVER_URL}/user'"
user_info=$(eval "${user_info_cmd}")
else
user_info="{}"
fi
merchant_id=$(echo "${user_info}" | grep -o '"merchant_id":"[^"]*"' | cut -d'"' -f4 || echo "")
profile_id=$(echo "${user_info}" | grep -o '"profile_id":"[^"]*"' | cut -d'"' -f4 || echo "")
# Configure account for new users
if [ "${is_new_user}" = true ] && [ -n "${merchant_id}" ] && [ -n "${token}" ]; then
# Create merchant account
merchant_payload="{\"merchant_id\":\"${merchant_id}\",\"merchant_name\":\"Test\"}"
merchant_response=$(curl -s -X POST -H "Content-Type: application/json" -H "api-key: hyperswitch" -H "authorization: Bearer ${token}" -d "${merchant_payload}" "${HYPERSWITCH_SERVER_URL}/accounts/${merchant_id}")
# Configure connector
connector_payload=$(
cat <<EOF
{
"connector_type": "payment_processor",
"profile_id": "${profile_id}",
"connector_name": "paypal_test",
"connector_label": "paypal_test_default",
"disabled": false,
"test_mode": true,
"payment_methods_enabled": [
{
"payment_method": "card",
"payment_method_types": [
{
"payment_method_type": "debit",
"card_networks": [
"Mastercard"
],
"minimum_amount": 0,
"maximum_amount": 68607706,
"recurring_enabled": true,
"installment_payment_enabled": false
},
{
"payment_method_type": "credit",
"card_networks": [
"Visa"
],
"minimum_amount": 0,
"maximum_amount": 68607706,
"recurring_enabled": true,
"installment_payment_enabled": false
}
]
}
],
"metadata": {},
"connector_account_details": {
"api_key": "test_key",
"auth_type": "HeaderKey"
},
"status": "active"
}
EOF
)
connector_response=$(curl -s -X POST -H "Content-Type: application/json" -H "api-key: hyperswitch" -H "authorization: Bearer ${token}" -d "${connector_payload}" "${HYPERSWITCH_SERVER_URL}/account/${merchant_id}/connectors")
# Silently check if configuration was successful without printing messages
if [ -z "$(echo "${merchant_response}" | grep -o 'merchant_id')" ] || [ -z "$(echo "${connector_response}" | grep -o 'connector_id')" ]; then
# Only log to debug log if we want to troubleshoot later
: # No-op command
fi
fi

24
scripts/notify_scarf.sh Executable file
View File

@@ -0,0 +1,24 @@
#! /usr/bin/env bash
set -euo pipefail
# Define the URL and parameters
SCARF_URL="https://hyperswitch.gateway.scarf.sh/docker"
VERSION=$1
INSTALLATION_STATUS=$2
CURL_COMMAND=("curl" "--get" "${SCARF_URL}" "--data-urlencode" "${VERSION}" "--data-urlencode" "${INSTALLATION_STATUS}")
# Calculate number of arguments and process remaining args (if any)
if [ $# -gt 2 ]; then
# Starting from the 3rd argument (index 2 in $@)
for param in "${@:3}"; do
CURL_COMMAND+=("--data-urlencode" "${param}")
done
fi
# Execute the curl command
echo "Executing: ${CURL_COMMAND[@]}"
"${CURL_COMMAND[@]}"
# Print confirmation
echo "Request sent to ${SCARF_URL} with ${VERSION} and ${INSTALLATION_STATUS}"

View File

@@ -7,7 +7,13 @@ STATUS=""
SERVER_BASE_URL="http://hyperswitch-server:8080"
HYPERSWITCH_HEALTH_URL="${SERVER_BASE_URL}/health"
HYPERSWITCH_DEEP_HEALTH_URL="${SERVER_BASE_URL}/health/ready"
WEBHOOK_URL="https://hyperswitch.gateway.scarf.sh/docker"
ONE_CLICK_SETUP="${ONE_CLICK_SETUP:-false}"
if [[ "${ONE_CLICK_SETUP}" == "true" ]]; then
SCARF_URL="https://hyperswitch.gateway.scarf.sh/docker"
else
SCARF_URL="https://hyperswitch.gateway.scarf.sh/only-docker"
fi
# Fetch health status
echo "Fetching app server health status..."
@@ -15,12 +21,12 @@ HEALTH_RESPONSE=$(curl --silent --fail "${HYPERSWITCH_HEALTH_URL}") || HEALTH_RE
if [[ "${HEALTH_RESPONSE}" == "connection_error" ]]; then
STATUS="error"
ERROR_MESSAGE="404 response"
ERROR_MESSAGE="500 response"
curl --get "${WEBHOOK_URL}" \
curl --get "${SCARF_URL}" \
--data-urlencode "version=${VERSION}" \
--data-urlencode "status=${STATUS}" \
--data-urlencode "error_message=${ERROR_MESSAGE}"
--data-urlencode "error_message='${ERROR_MESSAGE}'"
echo "Webhook sent with connection error."
exit 0
@@ -33,10 +39,10 @@ echo "Fetching Hyperswitch health status..."
HEALTH_RESPONSE=$(curl --silent "${HYPERSWITCH_DEEP_HEALTH_URL}")
# Prepare curl command
CURL_COMMAND=("curl" "--get" "${WEBHOOK_URL}" "--data-urlencode" "version=${VERSION}")
CURL_COMMAND=("curl" "--get" "${SCARF_URL}" "--data-urlencode" "version=${VERSION}")
# Check if the response contains an error
if [[ "$(echo "${HEALTH_RESPONSE}" | jq --raw-output '.error')" != 'null' ]]; then
if [[ "$(echo "${HEALTH_RESPONSE}" | jq --raw-output '.error')" != "null" ]]; then
STATUS="error"
ERROR_TYPE=$(echo "${HEALTH_RESPONSE}" | jq --raw-output '.error.type')
ERROR_MESSAGE=$(echo "${HEALTH_RESPONSE}" | jq --raw-output '.error.message')
@@ -48,17 +54,19 @@ if [[ "$(echo "${HEALTH_RESPONSE}" | jq --raw-output '.error')" != 'null' ]]; th
"--data-urlencode" "error_message='${ERROR_MESSAGE}'"
"--data-urlencode" "error_code='${ERROR_CODE}'"
)
else
"${CURL_COMMAND[@]}"
echo "Webhook sent with error status."
exit 0
elif [[ "${ONE_CLICK_SETUP}" == "false" ]]; then
STATUS="success"
CURL_COMMAND+=("--data-urlencode" "status=${STATUS}")
for key in $(echo "${HEALTH_RESPONSE}" | jq --raw-output 'keys_unsorted[]'); do
value=$(echo "${HEALTH_RESPONSE}" | jq --raw-output --arg key "${key}" '.[$key]')
CURL_COMMAND+=("--data-urlencode" "'${key}=${value}'")
CURL_COMMAND+=("--data-urlencode" "${key}=${value}")
done
"${CURL_COMMAND[@]}"
echo "Webhook notification sent for success status."
else
echo "ONE_CLICK_SETUP=true and status=success, skipping webhook call."
fi
# Send the webhook request
bash -c "${CURL_COMMAND[*]}"
echo "Webhook notification sent."

View File

@@ -1,13 +1,21 @@
#! /usr/bin/env bash
set -euo pipefail
ONE_CLICK_SETUP="${ONE_CLICK_SETUP:-false}"
# Check if ONE_CLICK_SETUP is set to true; if so, skip execution
if [ "${ONE_CLICK_SETUP}" = "true" ]; then
echo "ONE_CLICK_SETUP is true; skipping script execution."
exit 0
fi
# Define the URL and parameters
WEBHOOK_URL="https://hyperswitch.gateway.scarf.sh/docker"
SCARF_URL="https://hyperswitch.gateway.scarf.sh/only-docker"
VERSION="unknown"
STATUS="initiated"
# Send the GET request
curl --get "${WEBHOOK_URL}" --data-urlencode "version=${VERSION}" --data-urlencode "status=${STATUS}"
curl --get "${SCARF_URL}" --data-urlencode "version=${VERSION}" --data-urlencode "status=${STATUS}"
# Print confirmation
echo "Request sent to ${WEBHOOK_URL} with version=${VERSION} and status=${STATUS}"
echo "Request sent to ${SCARF_URL} with version=${VERSION} and status=${STATUS}"

View File

@@ -1,5 +1,82 @@
#!/usr/bin/env bash
set -euo pipefail
set -Eeuo pipefail
# Set up error logging - redirect stderr to both log file and console
ERROR_LOG="error.log"
exec 2> >(tee -a "${ERROR_LOG}" >&2)
# Set traps for errors and interruptions
trap 'handle_error "$LINENO" "$BASH_COMMAND" "$?"' ERR
trap 'handle_interrupt' INT TERM
# Variables for installation status
VERSION="unknown"
INSTALLATION_STATUS="initiated"
SCARF_PARAMS=()
# Trap and handle any errors that occur during the script execution
handle_error() {
local lineno=$1
local last_command=$2
local exit_code=$3
# Capture recent error log content if available
local log_content=""
if [ -f "${ERROR_LOG}" ] && [ -s "${ERROR_LOG}" ]; then
# Get last 5 lines of error log, escape for URL encoding
log_content=$(tail -n 1 "${ERROR_LOG}" | tr '\n' '|' | sed 's/|$//')
fi
# Set global vars used by scarf_call
INSTALLATION_STATUS="error"
ERROR_MESSAGE="Command '\$ ${last_command}' failed at line ${lineno} with exit code ${exit_code} and error logs: ${log_content:-'not available'}"
SCARF_PARAMS+=(
"error_type=script_error"
"error_message=${ERROR_MESSAGE}"
"error_code=${exit_code}"
)
scarf_call
cleanup
exit $exit_code
}
# Handle user interruptions
handle_interrupt() {
echo ""
echo_warning "Script interrupted by user"
# Set appropriate error information for user abort
INSTALLATION_STATUS="user_interrupt"
# Call scarf to report the interruption
scarf_call
cleanup
exit 130
}
cleanup() {
# Clean up any started containers if we've selected a profile
if [ -n "${PROFILE:-}" ]; then
echo_info "Cleaning up any started containers..."
case $PROFILE in
standalone)
$DOCKER_COMPOSE down >/dev/null 2>&1 || true
;;
standard)
$DOCKER_COMPOSE down >/dev/null 2>&1 || true
;;
full)
$DOCKER_COMPOSE --profile scheduler --profile monitoring --profile olap --profile full_setup down >/dev/null 2>&1 || true
;;
esac
fi
# Optionally remove error log if it's empty or on successful completion
if [ -f "${ERROR_LOG}" ]; then
rm -f "${ERROR_LOG}"
fi
}
# ANSI color codes for pretty output
RED='\033[0;31m'
@@ -9,21 +86,6 @@ BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Global cleanup function to handle error conditions and graceful exit
cleanup() {
# Restore strict error checking
set -e
# Remove any temporary files if needed
# Add any necessary cleanup operations here
# The exit status passed to the function
exit $1
}
# Set up trap to call cleanup function on script exit or interruptions
trap 'cleanup $?' EXIT
trap 'cleanup 1' INT TERM
# Function to print colorful messages
echo_info() {
printf "${BLUE}[INFO]${NC} %s\n" "$1"
@@ -43,7 +105,7 @@ echo_error() {
show_banner() {
printf "${BLUE}${BOLD}\n"
printf "\n"
printf "\n"
printf " # \n"
printf " # # # #### ##### ## # # \n"
printf " # # # # # # # # # # \n"
@@ -51,15 +113,15 @@ show_banner() {
printf " # # # # # ##### ###### # \n"
printf " # # # # # # # # # # \n"
printf " ##### #### #### # # # # \n"
printf "\n"
printf "\n"
printf "\n"
printf "\n"
printf " # # # # ##### ###### ##### #### # # # ##### #### # # \n"
printf " # # # # # # # # # # # # # # # # # # \n"
printf " # # # # # ##### # # #### # # # # # ###### \n"
printf " ####### # ##### # ##### # # ## # # # # # # \n"
printf " # # # # # # # # # ## ## # # # # # # \n"
printf " # # # # ###### # # #### # # # # #### # # \n"
printf "\n"
printf "\n"
sleep 1
printf "${NC}\n"
printf "🚀 ${BLUE}One-Click Docker Setup${NC} 🚀\n"
@@ -68,11 +130,11 @@ show_banner() {
# Detect Docker Compose version
detect_docker_compose() {
# Check Docker or Podman
if command -v docker &> /dev/null; then
if command -v docker &>/dev/null; then
CONTAINER_ENGINE="docker"
echo_success "Docker is installed."
echo ""
elif command -v podman &> /dev/null; then
elif command -v podman &>/dev/null; then
CONTAINER_ENGINE="podman"
echo_success "Podman is installed."
echo ""
@@ -85,17 +147,17 @@ detect_docker_compose() {
fi
# Check Docker Compose or Podman Compose
if $CONTAINER_ENGINE compose version &> /dev/null; then
DOCKER_COMPOSE="$CONTAINER_ENGINE compose"
echo_success "Compose is installed for $CONTAINER_ENGINE."
if $CONTAINER_ENGINE compose version &>/dev/null; then
DOCKER_COMPOSE="${CONTAINER_ENGINE} compose"
echo_success "Compose is installed for ${CONTAINER_ENGINE}."
echo ""
else
echo_error "Compose is not installed for $CONTAINER_ENGINE. Please install $CONTAINER_ENGINE compose to proceed."
echo_error "Compose is not installed for ${CONTAINER_ENGINE}. Please install ${CONTAINER_ENGINE} compose to proceed."
echo ""
if [ "$CONTAINER_ENGINE" = "docker" ]; then
if [ "${CONTAINER_ENGINE}" = "docker" ]; then
echo_info "Visit https://docs.docker.com/compose/install/ for installation instructions."
echo ""
elif [ "$CONTAINER_ENGINE" = "podman" ]; then
echo ""
elif [ "${CONTAINER_ENGINE}" = "podman" ]; then
echo_info "Visit https://podman-desktop.io/docs/compose/setting-up-compose for installation instructions."
echo ""
fi
@@ -107,25 +169,25 @@ detect_docker_compose() {
check_prerequisites() {
# Check curl
if ! command -v curl &> /dev/null; then
if ! command -v curl &>/dev/null; then
echo_error "curl is not installed. Please install curl to proceed."
echo ""
exit 1
fi
echo_success "curl is installed."
echo ""
# Check ports
required_ports=(8080 9000 9050 5432 6379 9060)
unavailable_ports=()
for port in "${required_ports[@]}"; do
if command -v nc &> /dev/null; then
if command -v nc &>/dev/null; then
if nc -z localhost "$port" 2>/dev/null; then
unavailable_ports+=("$port")
fi
elif command -v lsof &> /dev/null; then
if lsof -i :"$port" &> /dev/null; then
elif command -v lsof &>/dev/null; then
if lsof -i :"$port" &>/dev/null; then
unavailable_ports+=("$port")
fi
else
@@ -134,7 +196,7 @@ check_prerequisites() {
break
fi
done
if [ ${#unavailable_ports[@]} -ne 0 ]; then
echo_warning "The following ports are already in use: ${unavailable_ports[*]}"
echo_warning "This might cause conflicts with Hyperswitch services."
@@ -155,10 +217,19 @@ setup_config() {
echo_error "Configuration file 'config/docker_compose.toml' not found. Please ensure the file exists and is correctly configured."
exit 1
fi
# Create an .env file for one-click setup
local env_file=".oneclick-setup.env"
echo "# One-Click Setup configuration" >"${env_file}"
echo "# Generated on $(date)" >>"${env_file}"
echo "" >>"${env_file}"
# Enable one-click setup mode
echo "ONE_CLICK_SETUP=true" >>"${env_file}"
}
select_profile() {
printf "\n"
select_profile() {
printf "\n"
printf "Select a setup option:\n"
printf "1) ${YELLOW}Standard Setup${NC}: ${BLUE}[Recommended]${NC} Ideal for quick trial.\n"
printf " Services included: ${BLUE}App Server, Control Center, PostgreSQL and Redis${NC}\n"
@@ -170,283 +241,82 @@ select_profile() {
printf " Services included: ${BLUE}App Server, PostgreSQL and Redis)${NC}\n"
echo ""
local profile_selected=false
while [ "$profile_selected" = false ]; do
while [ "${profile_selected}" = "false" ]; do
echo -n "Enter your choice (1-3): "
read -n 1 profile_choice
echo
case $profile_choice in
1)
PROFILE="standard"
profile_selected=true
;;
2)
PROFILE="full"
profile_selected=true
;;
3)
PROFILE="standalone"
profile_selected=true
;;
*)
echo_error "Invalid choice. Please enter 1, 2, or 3."
;;
1)
PROFILE="standard"
profile_selected=true
;;
2)
PROFILE="full"
profile_selected=true
;;
3)
PROFILE="standalone"
profile_selected=true
;;
*)
echo_error "Invalid choice. Please enter 1, 2, or 3."
;;
esac
done
echo "Selected setup: $PROFILE"
echo "Selected setup: ${PROFILE}"
}
scarf_call() {
# Call the Scarf webhook endpoint with the provided parameters
chmod +x scripts/notify_scarf.sh
if [ ${#SCARF_PARAMS[@]} -eq 0 ]; then
scripts/notify_scarf.sh "version=${VERSION}" "status=${INSTALLATION_STATUS}" >/dev/null 2>&1
else
scripts/notify_scarf.sh "version=${VERSION}" "status=${INSTALLATION_STATUS}" "${SCARF_PARAMS[@]}" >/dev/null 2>&1
fi
# Reset SCARF_PARAMS for the next call
SCARF_PARAMS=()
}
start_services() {
case $PROFILE in
standalone)
$DOCKER_COMPOSE up -d pg redis-standalone migration_runner hyperswitch-server
;;
standard)
$DOCKER_COMPOSE up -d
;;
full)
$DOCKER_COMPOSE --profile scheduler --profile monitoring --profile olap --profile full_setup up -d
;;
standalone)
$DOCKER_COMPOSE --env-file .oneclick-setup.env up -d pg redis-standalone migration_runner hyperswitch-server
;;
standard)
$DOCKER_COMPOSE --env-file .oneclick-setup.env up -d
;;
full)
$DOCKER_COMPOSE --env-file .oneclick-setup.env --profile scheduler --profile monitoring --profile olap --profile full_setup up -d
;;
esac
}
check_services_health() {
# Wait for the hyperswitch-server to be healthy
MAX_RETRIES=30
RETRY_INTERVAL=5
RETRIES=0
while [ $RETRIES -lt $MAX_RETRIES ]; do
response=$(curl -s -w "\\nStatus_Code:%{http_code}" http://localhost:8080/health)
status_code=$(echo "$response" | grep "Status_Code:" | cut -d':' -f2)
response_body=$(echo "$response" | head -n1)
if [ "$status_code" = "200" ] && [ "$response_body" = "health is good" ]; then
print_access_info
return
fi
RETRIES=$((RETRIES+1))
if [ $RETRIES -eq $MAX_RETRIES ]; then
printf "\n"
echo_error "${RED}${BOLD}Hyperswitch server did not become healthy in the expected time."
printf "Check logs with: $DOCKER_COMPOSE logs hyperswitch-server, Or reach out to us on slack(https://hyperswitch-io.slack.com/) for help.\n"
printf "\n"
else
printf "Waiting for server to become healthy... (%d/%d)\n" $RETRIES $MAX_RETRIES
sleep $RETRY_INTERVAL
fi
done
}
HYPERSWITCH_BASE_URL="http://localhost:8080"
HYPERSWITCH_HEALTH_URL="${HYPERSWITCH_BASE_URL}/health"
HYPERSWITCH_DEEP_HEALTH_URL="${HYPERSWITCH_BASE_URL}/health/ready"
configure_account() {
# Temporarily disable strict error checking to prevent premature exit
set +e
local show_credentials_flag=false
BASE_URL="http://localhost:8080"
EMAIL="demo@hyperswitch.com"
PASSWORD="Hyperswitch@123"
# Initialize merchant_id and profile_id to empty strings
merchant_id=""
profile_id=""
# Function to make API calls with proper headers
make_api_call() {
local method=$1
local endpoint=$2
local data=$3
local auth_header=${4:-}
# Ensure endpoint starts with /user if it doesn't already
if [[ ! $endpoint =~ ^/user && ! $endpoint =~ ^/health && ! $endpoint =~ ^/accounts && ! $endpoint =~ ^/account ]]; then
endpoint="/user$endpoint"
fi
local headers=(-H "Content-Type: application/json" -H "api-key: hyperswitch" -H "User-Agent: HyperSwitch-Shell-Client/1.0" -H "Referer: http://localhost:9000/")
if [ -n "$auth_header" ]; then
headers+=(-H "authorization: Bearer $auth_header")
fi
if [ -n "$merchant_id" ]; then
headers+=(-H "X-Merchant-Id: $merchant_id")
fi
if [ -n "$profile_id" ]; then
headers+=(-H "X-Profile-Id: $profile_id")
fi
local curl_cmd
if [ "$method" = "GET" ]; then
curl_cmd=(curl -s -X "$method" "${headers[@]}" "$BASE_URL$endpoint")
else
curl_cmd=(curl -s -X "$method" "${headers[@]}" -d "$data" "$BASE_URL$endpoint")
fi
local retries=3
local i=0
while [ $i -lt $retries ]; do
response=$("${curl_cmd[@]}")
local response_code=$("${curl_cmd[@]}" -o /dev/null -s -w "%{http_code}")
if [ $response_code -lt 400 ]; then
echo "$response"
return 0
fi
i=$((i+1))
done
return 1
}
# Test the health endpoint first to ensure the API is responsive
health_response=$(curl -s -w "\\nStatus_Code:%{http_code}" "$BASE_URL/health")
health_status_code=$(echo "$health_response" | grep "Status_Code:" | cut -d':' -f2)
health_response_body=$(echo "$health_response" | head -n1)
# Try signin first
signin_payload="{\"email\":\"$EMAIL\",\"password\":\"$PASSWORD\"}"
signin_response=$(make_api_call "POST" "/signin" "$signin_payload")
status_code=$?
# Check if user needs to be created
if [[ $status_code -ne 0 || $(echo "$signin_response" | grep -q "error"; echo $?) -eq 0 ]]; then
# User doesn't exist or login failed, create new account
signup_payload="{\"email\":\"$EMAIL\",\"password\":\"$PASSWORD\",\"country\":\"IN\"}"
# Only try signing up once - using exact headers from browser
# For making signup request without verbose logging
signup_cmd="curl -s -X POST '$BASE_URL/user/signup' \
-H 'Accept: */*' \
-H 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' \
-H 'Content-Type: application/json' \
-H 'Origin: http://localhost:9000' \
-H 'Referer: http://localhost:9000/' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36' \
-H 'api-key: hyperswitch' \
-d '$signup_payload'"
signup_response=$(eval "$signup_cmd")
# Extract token from signup response
token=$(echo "$signup_response" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
token_type=$(echo "$signup_response" | grep -o '"token_type":"[^"]*"' | cut -d'"' -f4)
if [ -n "$token" ]; then
show_credentials_flag=true
fi
is_new_user=true
else
auth_response="$signin_response"
token=$(echo "$auth_response" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
token_type=$(echo "$auth_response" | grep -o '"token_type":"[^"]*"' | cut -d'"' -f4)
if [ -n "$token" ]; then
show_credentials_flag=true
fi
is_new_user=false
# Basic health check
health_response=$(curl --silent --fail "${HYPERSWITCH_HEALTH_URL}") || exit 0
if [ "${health_response}" != "health is good" ]; then
exit 0
fi
# Handle 2FA if needed
if [ "$token_type" = "totp" ]; then
MAX_RETRIES=3
for i in $(seq 1 $MAX_RETRIES); do
terminate_response=$(curl -s -X GET -H "Content-Type: application/json" -H "api-key: hyperswitch" -H "authorization: Bearer $token" "$BASE_URL/user/2fa/terminate?skip_two_factor_auth=true")
new_token=$(echo "$terminate_response" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
if [ -n "$new_token" ]; then
token="$new_token"
break
else
if [ $i -lt $MAX_RETRIES ]; then
sleep 1
fi
fi
done
# Deep health check
deep_health_response=$(curl --silent "${HYPERSWITCH_DEEP_HEALTH_URL}") || exit 0
if [[ "$(echo "${deep_health_response}" | jq --raw-output '.error')" != "null" ]]; then
exit 0
fi
# Get user info
if [ -n "$token" ]; then
user_info_cmd="curl -s -X GET -H 'Content-Type: application/json' -H 'api-key: hyperswitch' -H 'authorization: Bearer $token' '$BASE_URL/user'"
user_info=$(eval "$user_info_cmd")
else
user_info="{}"
fi
merchant_id=$(echo "$user_info" | grep -o '"merchant_id":"[^"]*"' | cut -d'"' -f4 || echo "")
profile_id=$(echo "$user_info" | grep -o '"profile_id":"[^"]*"' | cut -d'"' -f4 || echo "")
# Configure account for new users
if [ "$is_new_user" = true ] && [ -n "$merchant_id" ] && [ -n "$token" ]; then
# Create merchant account
merchant_payload="{\"merchant_id\":\"$merchant_id\",\"merchant_name\":\"Test\"}"
merchant_response=$(curl -s -X POST -H "Content-Type: application/json" -H "api-key: hyperswitch" -H "authorization: Bearer $token" -d "$merchant_payload" "$BASE_URL/accounts/$merchant_id")
# Configure connector
connector_payload=$(cat <<EOF
{
"connector_type": "payment_processor",
"profile_id": "$profile_id",
"connector_name": "paypal_test",
"connector_label": "paypal_test_default",
"disabled": false,
"test_mode": true,
"payment_methods_enabled": [
{
"payment_method": "card",
"payment_method_types": [
{
"payment_method_type": "debit",
"card_networks": [
"Mastercard"
],
"minimum_amount": 0,
"maximum_amount": 68607706,
"recurring_enabled": true,
"installment_payment_enabled": false
},
{
"payment_method_type": "credit",
"card_networks": [
"Visa"
],
"minimum_amount": 0,
"maximum_amount": 68607706,
"recurring_enabled": true,
"installment_payment_enabled": false
}
]
}
],
"metadata": {},
"connector_account_details": {
"api_key": "test_key",
"auth_type": "HeaderKey"
},
"status": "active"
}
EOF
)
connector_response=$(curl -s -X POST -H "Content-Type: application/json" -H "api-key: hyperswitch" -H "authorization: Bearer $token" -d "$connector_payload" "$BASE_URL/account/$merchant_id/connectors")
# Silently check if configuration was successful without printing messages
if [ -z "$(echo "$merchant_response" | grep -o 'merchant_id')" ] || [ -z "$(echo "$connector_response" | grep -o 'connector_id')" ]; then
# Only log to debug log if we want to troubleshoot later
: # No-op command
fi
fi
# Provide helpful information to the user regardless of success/failure
if [ "$show_credentials_flag" = true ]; then
printf " Use the following credentials:\n"
printf " Email: $EMAIL\n"
printf " Password: $PASSWORD\n"
fi
# Restore strict error checking
set -e
# Extract version
VERSION=$(curl --silent --output /dev/null --request GET --write-out '%header{x-hyperswitch-version}' "${HYPERSWITCH_BASE_URL}" | sed 's/-dirty$//')
INSTALLATION_STATUS="success"
print_access_info
scarf_call
}
print_access_info() {
@@ -457,41 +327,49 @@ print_access_info() {
printf "${NC}\n"
printf "${GREEN}${BOLD}Setup complete! You can now access Hyperswitch services at:${NC}\n"
if [ "$PROFILE" != "standalone" ]; then
printf "${GREEN}${BOLD}Control Center${NC}: ${BLUE}${BOLD}http://localhost:9000${NC}\n"
configure_account || true
fi
printf "${GREEN}${BOLD}App Server${NC}: ${BLUE}${BOLD}http://localhost:8080${NC}\n"
if [ "$PROFILE" = "full" ]; then
printf "${GREEN}${BOLD}Monitoring (Grafana)${NC}: ${BLUE}${BOLD}http://localhost:3000${NC}\n"
fi
printf "\n"
# Default user credentials
printf " Use the following credentials:\n"
printf " Email: demo@hyperswitch.com\n"
printf " Password: Hyperswitch@123\n"
printf "\n"
# Provide the stop command based on the selected profile
echo_info "To stop all services, run the following command:"
case $PROFILE in
standalone)
printf "${BLUE}$DOCKER_COMPOSE down${NC}\n"
;;
standard)
printf "${BLUE}$DOCKER_COMPOSE down${NC}\n"
;;
full)
printf "${BLUE}$DOCKER_COMPOSE --profile scheduler --profile monitoring --profile olap --profile full_setup down${NC}\n"
;;
standalone)
printf "${BLUE}$DOCKER_COMPOSE down${NC}\n"
;;
standard)
printf "${BLUE}$DOCKER_COMPOSE down${NC}\n"
;;
full)
printf "${BLUE}$DOCKER_COMPOSE --profile scheduler --profile monitoring --profile olap --profile full_setup down${NC}\n"
;;
esac
printf "\n"
printf "Reach out to us on ${BLUE}https://hyperswitch-io.slack.com${NC} in case you face any issues.\n"
}
# Main execution flow
scarf_call
show_banner
detect_docker_compose
check_prerequisites
source .oneclick-setup.env
setup_config
select_profile
start_services
check_services_health # This will call print_access_info if the server is healthy
check_services_health