require 'cgi' require 'net/http' require 'adyen/rest/errors' require 'adyen/rest/request' require 'adyen/rest/response' require 'adyen/rest/authorise_payment' require 'adyen/rest/authorise_recurring_payment' require 'adyen/rest/modify_payment' module Adyen module REST # The Client class acts as a client to Adyen's REST webservice. # # @!attribute environment [r] # The adyen environment to interact with. Either 'live' or 'test'. # @return [String] class Client include AuthorisePayment include ModifyPayment attr_reader :environment # @param environment [String] The Adyen environment to interface with. Either # 'live' or 'test'. # @param username [String] The webservice username, e.g. ws@Company.Account # @param password [String] The password associated with the username def initialize(environment, username, password) @environment, @username, @password = environment, username, password end # Closes the client. # # - This will terminate the HTTP connection. # - After calling this method, the behavior of any further method calls against # this client instance is undefined. # # @return [void] def close @http.finish if @http && @http.started? @http = nil end # Runs a client session against the Adyen REST service for the duration of the block, # and closes the connection afterwards. # # @yield The provided block will be called in which you can interact with the API using # the provided client. The client will be closed after the block returns. # @return [void] def session yield(self) ensure close end # The underlying Net::HTTP instance that is used to execute HTTP # request against the API. # # You can use this to set options on the Net::HTTP instance, like read_timeout. # Many of these options will only work if you set them before the HTTP connection is # opened, i.e. before doing the first API call. # # @return [Net::HTTP] The underlying Net::HTTP instance the client uses to perform HTTP request. def http @http ||= Net::HTTP.new(endpoint.host, endpoint.port).tap do |http| http.use_ssl = endpoint.scheme == 'https' end end # Executes an API request, and returns a reponse of the given type. # # @param request [Adyen::REST::Request] The API request to execute. # validate! will be called on the this object before the # request is made. # @param response_type [Class] The response type to use. Use either # Adyen::REST::Response or a subclass. # @return [Adyen::REST::Response] A response instance of the provided type # @see execute_http_request The execute_http_request takes care # of executing the underlying HTTP request. def execute_request(request) request.validate! http_response = execute_http_request(request) request.build_response(http_response) end protected # Executes a HTTP request against Adyen's REST webservice. # @param request [Adyen::REST::Request] The request to execute. # @return [Net::HTTPResponse] The response from the server. # @raise [Adyen::REST::Error] if the HTTP response code was not 200. # @see #http Use the http method to set options on the underlying # Net::HTTP object, like timeouts. def execute_http_request(request) http_request = Net::HTTP::Post.new(endpoint.path) http_request.basic_auth(@username, @password) http_request.set_form_data(request.form_data) case response = http.request(http_request) when Net::HTTPOK return response when Net::HTTPInternalServerError raise Adyen::REST::ResponseError.new(response.body) when Net::HTTPUnauthorized raise Adyen::REST::Error.new("Webservice credentials are incorrect") else raise Adyen::REST::Error.new("Unexpected HTTP response: #{response.code}") end end # The endpoint URI for this client. # @return [URI] The endpoint to use for the environment. def endpoint @endpoint ||= URI(ENDPOINT % [environment]) end # @see Adyen::REST::Client#endpoint ENDPOINT = 'https://pal-%s.adyen.com/pal/adapter/httppost' private_constant :ENDPOINT end end end