lib/veritrans/client.rb in veritrans-1.2.6 vs lib/veritrans/client.rb in veritrans-2.0.0beta
- old
+ new
@@ -1,241 +1,109 @@
-# :nodoc:
-module Veritrans
+# Veritrans HTTP Client
- # :nodoc:
- class Client
- include Config
+require "base64"
+require 'uri'
+require 'excon'
- # constructor to create instance of Veritrans::Client
- def initialize(&block)
- class <<self
- self
- end.class_eval do
- attr_accessor(:commodity, *PostData::PostParam)
- end
-
- # return-back to merchant-web
- self.customer_specification_flag = Config::CUSTOMER_SPECIFICATION_FLAG
- self.settlement_type = Config::SETTLEMENT_TYPE_CARD
+module Veritrans
+ module Client
+ extend self
- # if block_given?
- # yield(self) #self.instance_eval(&block)
- # return self.get_keys
- # end
+ # Failback for activesupport
+ def _json_encode(params)
+ if defined?(ActiveSupport) && defined?(ActiveSupport::JSON)
+ ActiveSupport::JSON.encode(params)
+ else
+ require 'json' unless defined?(JSON)
+ JSON.generate(params)
+ end
end
- #
- # Example:
- #
- # client = Veritrans::Client.new
- # client.order_id = "dummy#{(0...12).map{65.+(rand(25))}.join}"
- # client.session_id = "session#{(0...12).map{65.+(rand(25))}.join}"
- # client.gross_amount = "10"
- # client.commodity = [{
- # "COMMODITY_ID" => "IDxx1",
- # "COMMODITY_UNIT" => "10",
- # "COMMODITY_NUM" => "1",
- # "COMMODITY_NAME1" => "Waterbotle",
- # "COMMODITY_NAME2" => "Waterbottle in Indonesian"}]
- # client.get_keys
- #
- def get_keys
- init_instance
-
- if customer_specification_flag == "0" && shipping_flag == "0"
- raise "required_shipping_address must be '1'"
+ def _json_decode(params)
+ if defined?(ActiveSupport) && defined?(ActiveSupport::JSON)
+ ActiveSupport::JSON.decode(params)
+ else
+ require 'json' unless defined?(JSON)
+ JSON.parse(params)
end
+ end
- params = prepare_params(PostData::ServerParam,PostData::PostParam)
+ # This is proxy method for make_request to save request and response to logfile
+ def request_with_logging(method, url, params)
+ short_url = url.sub(config.api_host, '')
+ file_logger.info("Perform #{short_url} \nSending: " + _json_encode(params))
- if !params[:promo_bins].blank?
- params.merge!({ "promo_bins[]" => params[:promo_bins]})
- params.delete :promo_bins
- end
+ result = make_request(method, url, params)
- if !params[:point_banks].blank?
- params.merge!({ "point_banks[]" => params[:point_banks]})
- params.delete :point_banks
+ if result.status_code < 300
+ file_logger.info("Success #{short_url} \nGot: " + _json_encode(result.data) + "\n")
+ else
+ file_logger.warn("Failed #{short_url} \nGot: " + _json_encode(result.data) + "\n")
end
- if !params[:installment_banks].blank?
- params.merge!({ "installment_banks[]" => params[:installment_banks]})
- params.delete :installment_banks
- end
-
- if !params[:installment_terms].blank?
- params.merge!({ "installment_terms" => params[:installment_terms].to_json })
- params.delete :installment_terms
- end
-
- if !params[:payment_methods].blank?
- params.merge!({ "payment_methods[]" => params[:payment_methods]})
- params.delete :payment_methods
- end
-
- commodity = @commodity.collect do |data|
- data.keys.map do |key|
- if key.downcase == "commodity_id"
- data["item_id[]"] = data[key]
- end
-
- if key.downcase == "commodity_unit"
- data["price[]"] = data[key]
- end
-
- if key.downcase == "commodity_num"
- data["quantity[]"] = data[key]
- end
-
- if key.downcase == "commodity_name1"
- data["item_name1[]"] = data[key]
- end
-
- if key.downcase == "commodity_name2"
- data["item_name2[]"] = data[key]
- end
-
- data.delete key
- end
-
- # construct commodity
- orders_uri = Addressable::URI.new
- orders_uri.query_values = data
- # return list of commodity as query string format
- orders_uri.query
- end
-
- uri = Addressable::URI.new
- uri.query_values = params
- query_string = "#{uri.query}&repeat_line=#{commodity.length}&#{commodity.join('&')}"
-
- conn = Faraday.new(:url => server_host)
- @resp = conn.post do |req|
- req.url(Config::REQUEST_KEY_URL)
- req.body = query_string
- end.env
-
- delete_keys
- @resp[:url] = @resp[:url].to_s
-
- if version.to_i == 1
- @token = JSON.parse(@resp[:body])
- else
- @token = parse_body(@resp[:body])
- end
+ result
end
- # :nodoc:
- def server_host
- return Client.config["server_host"] ? Client.config["server_host"] : Config::SERVER_HOST
- end
+ private
- def redirect_url
- "#{server_host}/web1/paymentStart.action"
+ def basic_auth_header(server_key = SERVER_KEY)
+ key = Base64.strict_encode64(server_key + ":")
+ "Basic #{key}"
end
- # :nodoc:
- def merchant_id
- return Client.config["merchant_id"]
+ def get(url, params = {})
+ make_request(:get, url, params)
end
- # :nodoc:
- def merchant_id= new_merchant_id
- Client.config["merchant_id"] = new_merchant_id
+ def delete(url, params)
+ make_request(:delete, url, params)
end
- # :nodoc:
- def merchant_hash_key
- return Client.config["merchant_hash_key"]
+ def post(url, params)
+ make_request(:post, url, params)
end
- # :nodoc:
- def merchant_hash_key= new_merchant_hash_key
- Client.config["merchant_hash_key"] = new_merchant_hash_key
- end
+ def make_request(method, url, params, auth_header = nil)
+ if !config.server_key || config.server_key == ''
+ raise "Please add server_key to config/veritrans.yml"
+ end
- # :nodoc:
- def error_payment_return_url
- return Client.config["error_payment_return_url"]
- end
+ method = method.to_s.upcase
+ logger.info "Veritrans: #{method} #{url} #{_json_encode(params)}"
- # :nodoc:
- def finish_payment_return_url
- return Client.config["finish_payment_return_url"]
- end
+ # Add authentication and content type
+ # Docs http://docs.veritrans.co.id/sandbox/introduction.html
+ options = {
+ :body => _json_encode(params),
+ :headers => {
+ :Authorization => auth_header || basic_auth_header(config.server_key),
+ :Accept => "application/json",
+ :"Content-Type" => "application/json",
+ :"User-Agent" => "Veritrans ruby gem #{Veritrans::VERSION}"
+ }
+ }
- # :nodoc:
- def unfinish_payment_return_url
- return Client.config["unfinish_payment_return_url"]
- end
+ if method == "GET"
+ options.delete(:body)
+ options[:query] = URI.encode_www_form(params)
+ end
- # :nodoc:
- def token
- return @token
- end
+ s_time = Time.now
+ request = Excon.new(url, read_timeout: 40, write_timeout: 40, connect_timeout: 40)
- # :nodoc:
- def billing_address_different_with_shipping_address
- @customer_specification_flag
- end
+ response = request.send(method.downcase.to_sym, options.merge(path: URI.parse(url).path))
- # :nodoc:
- def billing_address_different_with_shipping_address=(flag)
- @customer_specification_flag = customer_specification_flag
- end
+ logger.info "Veritrans: got #{(Time.now - s_time).round(3)} sec #{response.status} #{response.body}"
- # :nodoc:
- def required_shipping_address
- @shipping_flag
- end
+ Result.new(response, url, options, Time.now - s_time)
- # :nodoc:
- def required_shipping_address=(flag)
- @shipping_flag = flag
- end
-
- def new_api
- return true
- end
-
- private
- # Generate merchant hash code
- def merchanthash
- if version.to_i == 1
- return HashGenerator::generate(merchant_hash_key, merchant_id, order_id);
- else
- return Digest::SHA512.hexdigest("#{merchant_hash_key},#{merchant_id},01,#{order_id},#{gross_amount}")
- end
- end
-
- # deprecated
- def parse_body(body)
- arrs = body.split("\r\n")
- arrs = arrs[-2,2] if arrs.length > 1
- return Hash[arrs.collect{|x|x.split("=")}]
- end
-
- def init_instance
- @token = nil
- end
-
- def prepare_params(*arg)
- params = {}
- # extract keys from post data
- arg.flatten.each do |key|
- # retrieve value from client configuration
- value = self.send(key)
- params[key.downcase] = value if value
- end
- return params
- end
-
- def delete_keys
- @resp.delete(:ssl)
- @resp.delete(:request)
- @resp.delete(:response)
- @resp.delete(:request_headers)
- @resp.delete(:parallel_manager)
+ rescue Excon::Errors::SocketError => error
+ logger.info "PAPI: socket error, can not connect"
+ error_response = Excon::Response.new(
+ body: '{"status_code": "500", "status_message": "Internal server error, no response from backend. Try again later"}',
+ status: '500'
+ )
+ Veritrans::Result.new(error_response, url, options, Time.now - s_time)
end
end
end