didww_ups 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format documentation
3
+ --require spec_helper
@@ -0,0 +1,8 @@
1
+ nguage: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.5
6
+ - 2.2.0
7
+ - jruby-19mode # JRuby in 1.9 mode
8
+ - rbx-2.2.10
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ group :test do
3
+ gem 'coveralls', require: false # Test coverage website. Go to https://coveralls.io
4
+ end
5
+ # Specify your gem's dependencies in didww_ups.gemspec
6
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Igor Fedoronchuk
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ # DidwwUps
2
+
3
+ [![Build Status](http://img.shields.io/travis/didww/didww_ups.svg)](https://travis-ci.org/didww/didww_ups)
4
+ [![Coverage Status](http://img.shields.io/coveralls/didww/didww_ups.svg)](https://coveralls.io/r/didww/didww_ups)
5
+ [![Dependency Status](http://img.shields.io/gemnasium/didww/didww_ups.svg)](https://gemnasium.com/didww/didww_ups)
6
+ [![Code Climate](http://img.shields.io/codeclimate/github/didww/didww_ups.svg)](https://codeclimate.com/github/didww/didww_ups)
7
+ [![Gem Version](http://img.shields.io/gem/v/didww_ups.svg)](https://rubygems.org/gems/didww_ups)
8
+ [![License](http://img.shields.io/:license-mit-blue.svg)](http://didww.mit-license.org)
9
+
10
+
11
+ API Client for DIDWW UPS payment gateway
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ gem 'didww_ups'
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install didww_ups
26
+
27
+
28
+ ## Contributing
29
+
30
+ 1. Fork it
31
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
32
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
33
+ 4. Push to the branch (`git push origin my-new-feature`)
34
+ 5. Create new Pull Request
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ # If you want to make this the default task
7
+ task :default => :spec
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'didww_ups/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "didww_ups"
8
+ spec.version = DidwwUps::VERSION
9
+ spec.authors = ["Igor Fedoronchuk"]
10
+ spec.email = ["igor.f@didww.com"]
11
+ spec.description = %q{API client library for DIDWW payment gateway (UPS)}
12
+ spec.summary = %q{API client library for DIDWW payment gateway (UPS)}
13
+ spec.homepage = "https://www.didww.com"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency('activeresource-response', "~> 1.1.1")
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rack"
26
+ spec.add_development_dependency "rspec", "~> 3"
27
+ spec.add_development_dependency "webmock"
28
+ end
@@ -0,0 +1,118 @@
1
+ require "didww_ups/version"
2
+ require "logger"
3
+ require "activeresource-response"
4
+ require 'active_support/core_ext/module'
5
+
6
+ module DidwwUps
7
+
8
+ SANDBOX_HOST = 'dev-payments.didww.com'
9
+
10
+ PRODUCTION_HOST = 'ups.didww.com'
11
+
12
+ mattr_accessor :service_host
13
+ mattr_accessor :config
14
+ mattr_accessor :logger
15
+ mattr_accessor :global_store
16
+ self.logger = ::Logger.new($stdout)
17
+
18
+ def self.configure(env)
19
+ @configuration_env = env
20
+ all_configs = load_configuration
21
+
22
+
23
+ if all_configs.any?
24
+ self.config = all_configs[env].symbolize_keys
25
+ if config[:ups_host].present?
26
+ self.service_host = config[:ups_host]
27
+ else
28
+ self.environment = config[:ups_env]
29
+ end
30
+ DidwwUps::Base.site = 'https://' + self.service_host
31
+ store = DidwwUps::Store.new(api_public_key: config[:store_public_key], api_secret_key: config[:store_secret_key])
32
+ DidwwUps.global_store = store
33
+ DidwwUps.store = store
34
+ end
35
+ end
36
+
37
+
38
+ def self.environment=(env)
39
+ env = env.to_sym
40
+ if [:live, :production].include? env
41
+ self.service_host = PRODUCTION_HOST
42
+ elsif [:test, :development, :sandbox].include? env
43
+ self.service_host = SANDBOX_HOST
44
+ else
45
+ raise ArgumentError.new("environment= #{env} accepts any of :live, :production, :test, :sandbox")
46
+ end
47
+ end
48
+
49
+ def self.current_store
50
+ Thread.current['didww_ups.active_store'] || DidwwUps.global_store
51
+ end
52
+
53
+ def self.profile
54
+ current_store.class.profile
55
+ end
56
+
57
+ #
58
+ def self.store=(store)
59
+ Thread.current['didww_ups.active_store'] = store
60
+ end
61
+
62
+ def self.with_configuration(new_env)
63
+ old_env = @configuration_env
64
+ begin
65
+ self.configure(new_env)
66
+ yield if block_given?
67
+ ensure
68
+ self.configure(old_env)
69
+ end
70
+ end
71
+
72
+ def self.with_store(new_store)
73
+ old_store = current_store
74
+ begin
75
+ self.store = new_store
76
+ yield if block_given?
77
+ ensure
78
+ self.store=old_store
79
+ end
80
+ end
81
+
82
+ def self.load_configuration
83
+ config_file = ENV['DIDWW_UPS_CONFIG_FILE'] || 'config/didww_ups.yml'
84
+ if File.exist?(config_file)
85
+ YAML.load_file(config_file)
86
+ else
87
+ raise StandardError.new("File #{config_file} doesn't exist") if ENV['DIDWW_UPS_CONFIG_FILE'].present?
88
+ logger.warn "Can't find #{config_file}"
89
+ {}
90
+ end
91
+ end
92
+
93
+
94
+ end
95
+
96
+
97
+ require "didww_ups/connection"
98
+ require "didww_ups/collection"
99
+ require "didww_ups/base"
100
+ require "didww_ups/store"
101
+ require "didww_ups/credit_card"
102
+ require "didww_ups/payment"
103
+ require "didww_ups/refund"
104
+ require "didww_ups/modules_base"
105
+ require "didww_ups/modules_token"
106
+ require "didww_ups/modules_payment"
107
+ require "didww_ups/modules_refund"
108
+ require 'yaml'
109
+ if defined? Rails
110
+ require 'didww_ups/railtie'
111
+ require 'generators/config'
112
+ else
113
+ DidwwUps.configure(ENV['RACK_ENV'])
114
+ end
115
+
116
+
117
+
118
+
@@ -0,0 +1,43 @@
1
+ # DidwwUps::Base class base class for API resources
2
+ module DidwwUps
3
+ class Base < ActiveResource::Base
4
+
5
+ self.include_format_in_path = false
6
+ self.prefix = "/api/rest/v1/"
7
+ add_response_method :http
8
+
9
+ self.collection_parser = DidwwUps::Collection
10
+
11
+ delegate :[], to: :@attributes
12
+
13
+ def remote_errors_response
14
+ instance_variable_get(:@remote_errors).try(:response)
15
+ end
16
+
17
+ class << self
18
+
19
+ def site=(site)
20
+ site_uri = create_site_uri_from(site)
21
+ @site = site_uri
22
+ Thread.current['didww_ups.site'] = site_uri
23
+ end
24
+
25
+ def site
26
+ Thread.current['didww_ups.site'] || @site
27
+ end
28
+
29
+ #no headers
30
+ def headers
31
+ {}
32
+ end
33
+
34
+ #override with needed Connection class
35
+ def connection(refresh = false)
36
+ @connection = DidwwUps::Connection.new(DidwwUps::Base.site, format) if refresh || @connection.nil?
37
+ @connection.timeout = timeout if timeout
38
+ @connection.ssl_options = ssl_options if ssl_options
39
+ @connection
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,17 @@
1
+ # DidwwUps::Collection class with ability to handle :total_count, :offset_value, :limit_value
2
+ module DidwwUps
3
+ class Collection < ActiveResource::Collection
4
+
5
+ attr_reader :total_count, :offset_value, :limit_value
6
+
7
+ def resource_class=(rc)
8
+ super rc
9
+ response = rc.connection.http_response
10
+ @total_count = response['X-Total-Count'].to_i
11
+ @offset_value = response['X-Offset-Value'].to_i
12
+ @limit_value = response['X-Limit-Value'].to_i
13
+ end
14
+ end
15
+
16
+
17
+ end
@@ -0,0 +1,14 @@
1
+ # DidwwUps::Connection class with overridden authorization_header method
2
+ module DidwwUps
3
+ class Connection < ActiveResource::Connection
4
+
5
+
6
+ # Adding Auth header
7
+ # Example
8
+ # Token token=dGVzdC1wdWJsaWM0OmNlNTM0M2NiNTY1ZDM3ZmFiZjExZjhkODAzMTA4YmQwMTBkYzc2ZGE=, date=2012-12-03 14:55:57,type=v1
9
+ def authorization_header(http_method, uri)
10
+ {'Authorization' => 'Token token=' + DidwwUps.current_store.request_token(URI(uri).request_uri, http_method)}
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,155 @@
1
+ # DidwwUps::CreditCard class to handle Credit Cards
2
+ #
3
+ # Routes:
4
+ # GET /api/rest/v1/credit_cards/:id/modules(.:format)
5
+ # GET /api/rest/v1/credit_cards/:credit_card_id/properties(.:format)
6
+ # GET /api/rest/v1/credit_cards/:credit_card_id/billing_address(.:format)
7
+ # GET /api/rest/v1/credit_cards(.:format)
8
+ # GET /api/rest/v1/credit_cards/:id(.:format)
9
+ # DELETE /api/rest/v1/credit_cards/:id(.:format)
10
+ #
11
+ # Filter Examples
12
+ # credit_cards = DidwwUps::CreditCard.all(params: { page:1, per_page:10 , q:{token_ref_is_present: true, cc_expired_gte: '2014-06-01'}})
13
+ # # => GET "/api/rest/v1/credit_cards?page=1&per_page=10&q%5Bcc_number_contains%5D=37"
14
+ #
15
+ # Possible filter keys for q hash
16
+ # * +created_at_gte+
17
+ # * +created_at_lte+
18
+ # * +cc_expired_gte+
19
+ # * +cc_expired_lte+
20
+ # * +store_id_eq+
21
+ # * +cc_number_contains+
22
+ # * +token_ref_contains+
23
+ # * +token_ref_is_present+ (true)
24
+ # * +token_ref_is_blank+ (true)
25
+ # * +customer_id_eq+
26
+ # * +customer_id_starts_with+
27
+ #
28
+ # Methods for pagination
29
+ # # credit_cards.total_count
30
+ # # credit_cards.limit_value
31
+ # # credit_cards.offset_value
32
+ #
33
+ # Find by token example
34
+ # DidwwUps::CreditCard.find("ToTXNnMAUika3o0sS0sqMw")
35
+ # # => GET "/api/rest/v1/credit_cards/ToTXNnMAUika3o0sS0sqMw"
36
+ #
37
+ # Remove example
38
+ # DidwwUps::CreditCard.new({token_ref:"ToTXNnMAUika3o0sS0sqMw"}, true).destroy
39
+ # # => DELETE "/api/rest/v1/credit_cards/ToTXNnMAUika3o0sS0sqMw"
40
+ #
41
+ #
42
+ module DidwwUps
43
+ class CreditCard < DidwwUps::Base
44
+
45
+ self.prefix = "/api/rest/v1/"
46
+
47
+ validate do
48
+ unless persisted? # was initialized by DidwwUps::Store#retrieve_credit_card
49
+ self.errors[:base] << "Invalid callback hash" unless self["secure_hash"].to_s == valid_callback_hash
50
+ self.errors[:base] << self["error"] if self["error"].present?
51
+ end
52
+ end
53
+
54
+ schema do
55
+ attribute :credit_card_number, :string
56
+ attribute :credit_card_type, :string
57
+ attribute :credit_card_expired, :string
58
+ attribute :unique_id, :string
59
+ attribute :store_id, :integer
60
+ attribute :token_ref, :string
61
+ attribute :updated_at, :datetime
62
+ attribute :customer_id, :string
63
+ attribute :card_id, :string
64
+
65
+ end
66
+
67
+
68
+ def updated_at
69
+ Time.parse(self[:updated_at])
70
+ end
71
+
72
+ def initialize(attributes = {}, persisted = false)
73
+ super attributes, persisted #check attributes keys
74
+ if self['success'].to_i == 1
75
+ @attributes['token_ref'] = self['result']
76
+ else
77
+ @attributes['error'] = self['result']
78
+ end
79
+ end
80
+
81
+ # Properties
82
+ # DidwwUps::CreditCard.new({:token_ref => "LQ8IQ4Av6hM3tgX_WLJp9w"}, true).get(:properties)
83
+ # DidwwUps::CreditCard.find("LQ8IQ4Av6hM3tgX_WLJp9w").properties
84
+ # # => GET "/api/rest/v1/credit_cards/LQ8IQ4Av6hM3tgX_WLJp9w/properties"
85
+ # # => {"bin"=>"510510", "bank"=>"BANK OF HAWAII", "country"=>"UNITED STATES", "card_brand"=>"MASTERCARD", "card_type"=>"CREDIT", "bank_phone"=>"1-888-643-3888 OR 1-888-643-9888", "customer_ip"=>"195.138.65.189", "fraud_level"=>nil}
86
+ #
87
+ def properties
88
+ attribute_or_get! :properties
89
+ end
90
+
91
+ # Payment Modules
92
+ # DidwwUps::CreditCard.find("LQ8IQ4Av6hM3tgX_WLJp9w").get(:modules)
93
+ # DidwwUps::CreditCard.find("LQ8IQ4Av6hM3tgX_WLJp9w").modules
94
+ # # => GET "/api/rest/v1/credit_cards/LQ8IQ4Av6hM3tgX_WLJp9w/modules"
95
+ # # => ["WorldnetTps"]
96
+ def modules
97
+ self[:modules] ||= self[:modules_tokens].present? ?
98
+ self[:modules_tokens].collect { |t| t.module_name } :
99
+ get(:modules)
100
+ end
101
+
102
+ # Billing Address
103
+ # DidwwUps::CreditCard.new({:token_ref => "LQ8IQ4Av6hM3tgX_WLJp9w"}, true).get(:billing_address)
104
+ # DidwwUps::CreditCard.find("LQ8IQ4Av6hM3tgX_WLJp9w").billing_address
105
+ # # => GET "/api/rest/v1/credit_cards/LQ8IQ4Av6hM3tgX_WLJp9w/modules"
106
+ # # => "{\"bill_first_name\":\"FirstName\",\"bill_last_name\":\"SecondName\",\"city\":\"Odessa\",\"company\":\"\",\"country\":\"UA\",\"created_at\":\"2014-03-27T12:29:43Z\",\"email\":\"olga@gmail.com\",\"fax_number\":\"\",\"first_address_line\":\"Address line1\",\"id\":1070,\"phone_number\":\"3806600000000\",\"second_address_line\":\"Address line2\",\"state\":null,\"updated_at\":\"2014-03-27T12:29:43Z\",\"zip\":\"65007\",\"avs_result\":null}"
107
+ def billing_address
108
+ attribute_or_get! :billing_address
109
+ end
110
+
111
+ # create Payment ,
112
+ # * *See* : DidwwUps::Payment#create
113
+ # * *Returns* : DidwwUps::Payment
114
+ def create_payment(params={})
115
+ DidwwUps::Payment.create(params.merge({token_ref: self['token_ref']}))
116
+ end
117
+
118
+ def to_param
119
+ token_ref
120
+ end
121
+
122
+ alias :id :to_param
123
+
124
+ def brand
125
+ self[:credit_card_type]
126
+ end
127
+
128
+ def display_name
129
+ "#{self.brand} #{self[:credit_card_number]}"
130
+ end
131
+
132
+ def expired_this_month?
133
+ self[:credit_card_expired] == DateTime.now.utc.strftime("%Y-%d")
134
+ end
135
+
136
+ def expired?
137
+ self[:credit_card_expired] < DateTime.now.utc.strftime("%Y-%d")
138
+ end
139
+
140
+ protected
141
+ def valid_callback_hash
142
+ Digest::SHA1.hexdigest "#{self['result']}#{self['success']}#{self['customer_id']}#{self['card_id']}#{self['date_time']}#{DidwwUps.current_store['api_secret_key']}"
143
+ end
144
+
145
+ def attribute_or_get!(name)
146
+ if self.attributes.has_key? name
147
+ return {} if self[name].nil?
148
+ self[name].is_a?(Hash) ? self[name] : self[name].try(:attributes)
149
+ else
150
+ self[name] = get(name)
151
+ end
152
+ end
153
+
154
+ end
155
+ end