Class: CloverSandboxSimulator::Services::Clover::OauthService
- Inherits:
-
BaseService
- Object
- BaseService
- CloverSandboxSimulator::Services::Clover::OauthService
- Defined in:
- lib/clover_sandbox_simulator/services/clover/oauth_service.rb
Overview
Manages Clover OAuth2 authentication Handles token refresh and validation using omniauth-clover-oauth2
Usage:
oauth = OauthService.new
# Check if token needs refresh
if oauth.token_expired?
new_token = oauth.refresh_token
end
# Get authorization URL for initial auth
url = oauth.
Constant Summary collapse
- SANDBOX_AUTH_URL =
Sandbox OAuth endpoints
"https://sandbox.dev.clover.com/oauth/v2/authorize"- SANDBOX_TOKEN_URL =
"https://sandbox.dev.clover.com/oauth/v2/token"- PRODUCTION_AUTH_URL =
Production OAuth endpoints
"https://www.clover.com/oauth/v2/authorize"- PRODUCTION_TOKEN_URL =
"https://www.clover.com/oauth/v2/token"
Instance Attribute Summary collapse
-
#app_id ⇒ Object
readonly
Returns the value of attribute app_id.
-
#app_secret ⇒ Object
readonly
Returns the value of attribute app_secret.
Attributes inherited from BaseService
Instance Method Summary collapse
-
#authorization_url(redirect_uri:, merchant_id: nil) ⇒ String
Get the authorization URL for user consent.
-
#decode_token(token) ⇒ Hash
Get token info from a JWT.
-
#exchange_code(code:, redirect_uri:) ⇒ Hash
Exchange authorization code for tokens.
-
#initialize(config: nil, app_id: nil, app_secret: nil) ⇒ OauthService
constructor
A new instance of OauthService.
-
#oauth_configured? ⇒ Boolean
Check if OAuth credentials are configured.
-
#refresh_current_merchant_token ⇒ Hash?
Refresh the token for the current merchant using stored refresh token Updates both config and .env.json.
-
#refresh_token(refresh_token) ⇒ Hash
Refresh an expired access token.
-
#save_token_to_json(merchant_id, access_token) ⇒ Object
Alias for backwards compatibility.
-
#save_tokens_to_json(merchant_id, access_token: nil, refresh_token: nil) ⇒ Object
Save tokens to .env.json for a specific merchant.
-
#token_expired?(token = nil) ⇒ Boolean
Check if the current API token is expired Clover JWT tokens have an ‘exp’ claim.
-
#update_config_token(access_token) ⇒ Object
Update the configuration with a new token.
Constructor Details
#initialize(config: nil, app_id: nil, app_secret: nil) ⇒ OauthService
Returns a new instance of OauthService.
33 34 35 36 37 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 33 def initialize(config: nil, app_id: nil, app_secret: nil) super(config: config) @app_id = app_id || ENV.fetch("CLOVER_APP_ID", nil) @app_secret = app_secret || ENV.fetch("CLOVER_APP_SECRET", nil) end |
Instance Attribute Details
#app_id ⇒ Object (readonly)
Returns the value of attribute app_id.
31 32 33 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 31 def app_id @app_id end |
#app_secret ⇒ Object (readonly)
Returns the value of attribute app_secret.
31 32 33 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 31 def app_secret @app_secret end |
Instance Method Details
#authorization_url(redirect_uri:, merchant_id: nil) ⇒ String
Get the authorization URL for user consent
50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 50 def (redirect_uri:, merchant_id: nil) validate_oauth_config! params = { client_id: app_id, redirect_uri: redirect_uri, response_type: "code" } params[:merchant_id] = merchant_id if merchant_id "#{auth_endpoint}?#{URI.encode_www_form(params)}" end |
#decode_token(token) ⇒ Hash
Get token info from a JWT
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 148 def decode_token(token) parts = token.split(".") raise ArgumentError, "Invalid JWT format" unless parts.length == 3 payload = JSON.parse(Base64.decode64(parts[1])) { merchant_id: payload["merchant_uuid"], app_id: payload["app_uuid"], issued_at: Time.at(payload["iat"]), expires_at: Time.at(payload["exp"]), permissions: payload["permission_bitmap"] } rescue StandardError => e logger.error "Failed to decode token: #{e.}" {} end |
#exchange_code(code:, redirect_uri:) ⇒ Hash
Exchange authorization code for tokens
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 68 def exchange_code(code:, redirect_uri:) validate_oauth_config! logger.info "Exchanging authorization code for tokens..." response = RestClient.post( token_endpoint, { client_id: app_id, client_secret: app_secret, code: code, redirect_uri: redirect_uri, grant_type: "authorization_code" }, { "Content-Type" => "application/x-www-form-urlencoded" } ) tokens = JSON.parse(response.body) logger.info "Token exchange successful" tokens rescue RestClient::ExceptionWithResponse => e handle_oauth_error(e) end |
#oauth_configured? ⇒ Boolean
Check if OAuth credentials are configured
40 41 42 43 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 40 def oauth_configured? !app_id.nil? && !app_id.empty? && !app_secret.nil? && !app_secret.empty? end |
#refresh_current_merchant_token ⇒ Hash?
Refresh the token for the current merchant using stored refresh token Updates both config and .env.json
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 178 def refresh_current_merchant_token unless config.refresh_token && !config.refresh_token.empty? logger.warn "No refresh token available for current merchant" return nil end tokens = refresh_token(config.refresh_token) return nil unless tokens # Update config update_config_token(tokens["access_token"]) # Save to .env.json save_tokens_to_json( config.merchant_id, access_token: tokens["access_token"], refresh_token: tokens["refresh_token"] ) tokens end |
#refresh_token(refresh_token) ⇒ Hash
Refresh an expired access token
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 96 def refresh_token(refresh_token) validate_oauth_config! logger.info "Refreshing access token..." response = RestClient.post( token_endpoint, { client_id: app_id, client_secret: app_secret, refresh_token: refresh_token, grant_type: "refresh_token" }, { "Content-Type" => "application/x-www-form-urlencoded" } ) tokens = JSON.parse(response.body) logger.info "Token refresh successful" tokens rescue RestClient::ExceptionWithResponse => e handle_oauth_error(e) end |
#save_token_to_json(merchant_id, access_token) ⇒ Object
Alias for backwards compatibility
228 229 230 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 228 def save_token_to_json(merchant_id, access_token) save_tokens_to_json(merchant_id, access_token: access_token) end |
#save_tokens_to_json(merchant_id, access_token: nil, refresh_token: nil) ⇒ Object
Save tokens to .env.json for a specific merchant
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 205 def save_tokens_to_json(merchant_id, access_token: nil, refresh_token: nil) file_path = config.class::MERCHANTS_FILE return unless File.exist?(file_path) merchants = JSON.parse(File.read(file_path)) merchant = merchants.find { |m| m["CLOVER_MERCHANT_ID"] == merchant_id } if merchant merchant["CLOVER_API_TOKEN"] = access_token if access_token merchant["CLOVER_REFRESH_TOKEN"] = refresh_token if refresh_token # Also update config config.refresh_token = refresh_token if refresh_token File.write(file_path, JSON.pretty_generate(merchants)) logger.info "Tokens saved to .env.json for merchant #{merchant_id}" else logger.warn "Merchant #{merchant_id} not found in .env.json" end rescue StandardError => e logger.error "Failed to save tokens: #{e.}" end |
#token_expired?(token = nil) ⇒ Boolean
Check if the current API token is expired Clover JWT tokens have an ‘exp’ claim
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 124 def token_expired?(token = nil) token ||= config.api_token return true if token.nil? || token.empty? || token == "NEEDS_REFRESH" # Decode JWT to check expiration parts = token.split(".") return true unless parts.length == 3 payload = JSON.parse(Base64.decode64(parts[1])) exp = payload["exp"] return true unless exp # Token is expired if exp is in the past (with 60s buffer) Time.now.to_i >= (exp - 60) rescue StandardError => e logger.debug "Could not decode token: #{e.}" true end |
#update_config_token(access_token) ⇒ Object
Update the configuration with a new token
169 170 171 172 |
# File 'lib/clover_sandbox_simulator/services/clover/oauth_service.rb', line 169 def update_config_token(access_token) config.api_token = access_token logger.info "Configuration updated with new token" end |