didww_ups 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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