didww_ups 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.travis.yml +8 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +34 -0
- data/Rakefile +7 -0
- data/didww_ups.gemspec +28 -0
- data/lib/didww_ups.rb +118 -0
- data/lib/didww_ups/base.rb +43 -0
- data/lib/didww_ups/collection.rb +17 -0
- data/lib/didww_ups/connection.rb +14 -0
- data/lib/didww_ups/credit_card.rb +155 -0
- data/lib/didww_ups/modules_base.rb +27 -0
- data/lib/didww_ups/modules_payment.rb +18 -0
- data/lib/didww_ups/modules_refund.rb +17 -0
- data/lib/didww_ups/modules_token.rb +14 -0
- data/lib/didww_ups/payment.rb +80 -0
- data/lib/didww_ups/railtie.rb +7 -0
- data/lib/didww_ups/refund.rb +65 -0
- data/lib/didww_ups/store.rb +119 -0
- data/lib/didww_ups/version.rb +3 -0
- data/lib/generators/config.rb +15 -0
- data/lib/generators/templates/didww_ups.yml +14 -0
- data/spec/credit_card_spec.rb +100 -0
- data/spec/didww_ups.yml +5 -0
- data/spec/payment_spec.rb +127 -0
- data/spec/refund_spec.rb +112 -0
- data/spec/spec_helper.rb +98 -0
- data/spec/store_spec.rb +109 -0
- metadata +178 -0
data/spec/didww_ups.yml
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe DidwwUps::Payment do
|
3
|
+
before do
|
4
|
+
@path = DidwwUps::Payment.site.to_s + DidwwUps::Payment.prefix.to_s
|
5
|
+
end
|
6
|
+
context "Read Collection" do
|
7
|
+
before do
|
8
|
+
|
9
|
+
|
10
|
+
@collection = [
|
11
|
+
{id: 1967, token_ref: "DwyRv3iGrrrGvNtNJGHPUA", cc_type: "MASTERCARD", cc_number: "540400******0001", success: true, error: nil, amount: "20.5", order_id: "8", store_id: 6, module: "Stripe", operator: "Admin", description: "Payment for order # 8", customer_id: "143620"},
|
12
|
+
{id: 1968, token_ref: "DwyRv3iGrrrGvNtNJGHPUA", cc_type: "MASTERCARD", cc_number: "540400******0001", success: true, error: nil, amount: "20.5", order_id: "9", store_id: 6, module: "Stripe", operator: "Admin", description: "Payment for order # 9", customer_id: "143620"}
|
13
|
+
]
|
14
|
+
@collection_headers = {'X-Total-Count' => '10', 'X-Offset-Value' => '0', 'X-Limit-Value' => '2'}
|
15
|
+
stub_request(:get, @path + 'payments?page=1&per_page=2').to_return(body: @collection.to_json, headers: @collection_headers)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be success" do
|
19
|
+
payments = DidwwUps::Payment.all(params: {page: 1, per_page: 2})
|
20
|
+
expect(payments.count).to eq(2)
|
21
|
+
expect(payments.total_count).to eq(@collection_headers['X-Total-Count'].to_i)
|
22
|
+
expect(payments.offset_value).to eq(@collection_headers['X-Offset-Value'].to_i)
|
23
|
+
expect(payments.limit_value).to eq(@collection_headers['X-Limit-Value'].to_i)
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "Create Payment" do
|
29
|
+
|
30
|
+
before do
|
31
|
+
|
32
|
+
@credit_card = DidwwUps::CreditCard.new({
|
33
|
+
token_ref: 'LQ8IQ4Av6hM3tgX_WLJp9w'
|
34
|
+
}, true)
|
35
|
+
stub_request(:post, @path + 'payments').to_return(body: response.to_json, status: status)
|
36
|
+
|
37
|
+
@payment = DidwwUps::Payment.create({token_ref: "LQ8IQ4Av6hM3tgX_WLJp9w", order_id: 7, amount: 20.5, operator: 'Admin', description: 'Payment for order # 7'})
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:status) { 200 }
|
42
|
+
|
43
|
+
|
44
|
+
context "Transaction failed" do
|
45
|
+
let(:response) {
|
46
|
+
{
|
47
|
+
id: 1967,
|
48
|
+
token_ref: "LQ8IQ4Av6hM3tgX_WLJp9w",
|
49
|
+
cc_type: "MASTERCARD",
|
50
|
+
cc_number: "540400******0001",
|
51
|
+
success: false,
|
52
|
+
error: "Declined",
|
53
|
+
amount: 20.5,
|
54
|
+
order_id: 7,
|
55
|
+
description: "Payment for order # 7",
|
56
|
+
operator: "Admin",
|
57
|
+
type: "Stripe"
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
it "should be created" do
|
62
|
+
expect(@payment).to be_persisted
|
63
|
+
|
64
|
+
end
|
65
|
+
it "should be valid" do
|
66
|
+
expect(@payment).to be_valid
|
67
|
+
end
|
68
|
+
it "should be failed" do
|
69
|
+
expect(@payment).not_to be_success
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "Invalid request" do
|
74
|
+
let(:response) {
|
75
|
+
{errors: {base: ["Order was already processed"]}}
|
76
|
+
}
|
77
|
+
let(:status) { 422 }
|
78
|
+
it "should not be created" do
|
79
|
+
expect(@payment).not_to be_persisted
|
80
|
+
|
81
|
+
end
|
82
|
+
it "should not be valid" do
|
83
|
+
expect(@payment).not_to be_valid
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not be success" do
|
87
|
+
expect(@payment).not_to be_success
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
context "Transaction succeed" do
|
94
|
+
|
95
|
+
let(:response) {
|
96
|
+
{
|
97
|
+
id: 1968,
|
98
|
+
token_ref: "LQ8IQ4Av6hM3tgX_WLJp9w",
|
99
|
+
cc_type: "MASTERCARD",
|
100
|
+
cc_number: "540400******0001",
|
101
|
+
success: true,
|
102
|
+
error: nil,
|
103
|
+
amount: 20.5,
|
104
|
+
order_id: 7,
|
105
|
+
description: "Payment for order # 7",
|
106
|
+
operator: "Admin",
|
107
|
+
type: "Stripe"}
|
108
|
+
}
|
109
|
+
|
110
|
+
|
111
|
+
it "should be created" do
|
112
|
+
expect(@payment).to be_persisted
|
113
|
+
|
114
|
+
end
|
115
|
+
it "should be valid" do
|
116
|
+
expect(@payment).to be_valid
|
117
|
+
end
|
118
|
+
it "should be success" do
|
119
|
+
expect(@payment).to be_success
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
end
|
data/spec/refund_spec.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe DidwwUps::Refund do
|
3
|
+
before do
|
4
|
+
@path = DidwwUps::Refund.site.to_s + DidwwUps::Refund.prefix
|
5
|
+
end
|
6
|
+
context "Create Refund" do
|
7
|
+
before do
|
8
|
+
|
9
|
+
stub_request(:post, @path + 'refunds').to_return(body: response.to_json, status: status)
|
10
|
+
|
11
|
+
@refund = DidwwUps::Refund.create(order_id: "8", amount: 12.00, operator: "Bob", description: "Stolen Card")
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:status) { 200 }
|
16
|
+
|
17
|
+
|
18
|
+
context "Transaction failed" do
|
19
|
+
let(:response) {
|
20
|
+
{
|
21
|
+
id: 466,
|
22
|
+
success: false,
|
23
|
+
error: "Credit Card is expired",
|
24
|
+
amount: 12.0,
|
25
|
+
order_id: 8,
|
26
|
+
description: "Stolen Card",
|
27
|
+
operator: "Bob"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
it "should be created" do
|
32
|
+
expect(@refund).to be_persisted
|
33
|
+
|
34
|
+
end
|
35
|
+
it "should be valid" do
|
36
|
+
expect(@refund).to be_valid
|
37
|
+
end
|
38
|
+
it "should be failed" do
|
39
|
+
expect(@refund).not_to be_success
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "Invalid request" do
|
44
|
+
let(:response) {
|
45
|
+
{errors: {amount: ["must be less or equal to 10.0"]}}
|
46
|
+
}
|
47
|
+
let(:status) { 422 }
|
48
|
+
it "should not be created" do
|
49
|
+
expect(@refund).not_to be_persisted
|
50
|
+
|
51
|
+
end
|
52
|
+
it "should not be valid" do
|
53
|
+
expect(@refund).not_to be_valid
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should not be success" do
|
57
|
+
expect(@refund).not_to be_success
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
context "Transaction succeed" do
|
64
|
+
|
65
|
+
let(:response) {
|
66
|
+
{
|
67
|
+
id: 466,
|
68
|
+
success: true,
|
69
|
+
error: nil,
|
70
|
+
amount: 12.0,
|
71
|
+
order_id: 8,
|
72
|
+
description: "Stolen Card",
|
73
|
+
operator: "Bob"
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
|
78
|
+
it "should be created" do
|
79
|
+
expect(@refund).to be_persisted
|
80
|
+
|
81
|
+
end
|
82
|
+
it "should be valid" do
|
83
|
+
expect(@refund).to be_valid
|
84
|
+
end
|
85
|
+
it "should be success" do
|
86
|
+
expect(@refund).to be_success
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
context "Read Collection" do
|
91
|
+
before do
|
92
|
+
@collection = [
|
93
|
+
{id: 2, success: true, error: nil, amount: 10.01, order_id: 6, store_id: 1, description: 'Refund for order # 34', operator: 'Steve'},
|
94
|
+
{id: 2, success: true, error: nil, amount: 10.02, order_id: 7, store_id: 1, description: 'Refund for order # 35', operator: 'Steve'}
|
95
|
+
|
96
|
+
]
|
97
|
+
@collection_headers = {'X-Total-Count' => '10', 'X-Offset-Value' => '0', 'X-Limit-Value' => '2'}
|
98
|
+
stub_request(:get, @path + 'refunds?page=1&per_page=2').to_return(body: @collection.to_json, headers: @collection_headers)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be success" do
|
102
|
+
credit_cards = DidwwUps::Refund.all(params: {page: 1, per_page: 2})
|
103
|
+
expect(credit_cards.count).to eq(2)
|
104
|
+
expect(credit_cards.total_count).to eq(@collection_headers['X-Total-Count'].to_i)
|
105
|
+
expect(credit_cards.offset_value).to eq(@collection_headers['X-Offset-Value'].to_i)
|
106
|
+
expect(credit_cards.limit_value).to eq(@collection_headers['X-Limit-Value'].to_i)
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'coveralls'
|
2
|
+
Coveralls.wear!
|
3
|
+
|
4
|
+
ENV['RACK_ENV'] ||= 'test'
|
5
|
+
ENV['DIDWW_UPS_CONFIG_FILE'] = File.expand_path(File.join(File.dirname(__FILE__), 'didww_ups.yml'))
|
6
|
+
|
7
|
+
lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
|
8
|
+
specs = File.expand_path("#{File.dirname(__FILE__)}/../spec")
|
9
|
+
$:.unshift(lib)
|
10
|
+
$:.unshift(specs)
|
11
|
+
|
12
|
+
require 'rack'
|
13
|
+
require 'webmock/rspec'
|
14
|
+
require 'didww_ups'
|
15
|
+
|
16
|
+
|
17
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
18
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
19
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
20
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
21
|
+
#
|
22
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
23
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
24
|
+
# (such as loading up an entire rails app) will add to the boot time of your
|
25
|
+
# test suite on EVERY test run, even for an individual file that may not need
|
26
|
+
# all of that loaded.
|
27
|
+
#
|
28
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
29
|
+
# users commonly want.
|
30
|
+
#
|
31
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
32
|
+
RSpec.configure do |config|
|
33
|
+
# The settings below are suggested to provide a good initial experience
|
34
|
+
# with RSpec, but feel free to customize to your heart's content.
|
35
|
+
=begin
|
36
|
+
# These two settings work together to allow you to limit a spec run
|
37
|
+
# to individual examples or groups you care about by tagging them with
|
38
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
39
|
+
# get run.
|
40
|
+
config.filter_run :focus
|
41
|
+
config.run_all_when_everything_filtered = true
|
42
|
+
|
43
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
44
|
+
# file, and it's useful to allow more verbose output when running an
|
45
|
+
# individual spec file.
|
46
|
+
if config.files_to_run.one?
|
47
|
+
# RSpec filters the backtrace by default so as not to be so noisy.
|
48
|
+
# This causes the full backtrace to be printed when running a single
|
49
|
+
# spec file (e.g. to troubleshoot a particular spec failure).
|
50
|
+
config.full_backtrace = true
|
51
|
+
|
52
|
+
# Use the documentation formatter for detailed output,
|
53
|
+
# unless a formatter has already been configured
|
54
|
+
# (e.g. via a command-line flag).
|
55
|
+
config.formatter = 'doc' if config.formatters.none?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Print the 10 slowest examples and example groups at the
|
59
|
+
# end of the spec run, to help surface which specs are running
|
60
|
+
# particularly slow.
|
61
|
+
config.profile_examples = 10
|
62
|
+
|
63
|
+
# Run specs in random order to surface order dependencies. If you find an
|
64
|
+
# order dependency and want to debug it, you can fix the order by providing
|
65
|
+
# the seed, which is printed after each run.
|
66
|
+
# --seed 1234
|
67
|
+
config.order = :random
|
68
|
+
|
69
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
70
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
71
|
+
# test failures related to randomization by passing the same `--seed` value
|
72
|
+
# as the one that triggered the failure.
|
73
|
+
Kernel.srand config.seed
|
74
|
+
|
75
|
+
# rspec-expectations config goes here. You can use an alternate
|
76
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
77
|
+
# assertions if you prefer.
|
78
|
+
config.expect_with :rspec do |expectations|
|
79
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
80
|
+
# For more details, see:
|
81
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
82
|
+
expectations.syntax = :expect
|
83
|
+
end
|
84
|
+
|
85
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
86
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
87
|
+
config.mock_with :rspec do |mocks|
|
88
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
89
|
+
# For more details, see:
|
90
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
91
|
+
mocks.syntax = :expect
|
92
|
+
|
93
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
94
|
+
# a real object. This is generally recommended.
|
95
|
+
mocks.verify_partial_doubles = true
|
96
|
+
end
|
97
|
+
=end
|
98
|
+
end
|
data/spec/store_spec.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe DidwwUps::Store do
|
3
|
+
before do
|
4
|
+
|
5
|
+
@store = DidwwUps.current_store
|
6
|
+
|
7
|
+
@valid_params = callback_params.merge('secure_hash' => DidwwUps::CreditCard.new(callback_params).send(:valid_callback_hash))
|
8
|
+
end
|
9
|
+
#
|
10
|
+
# ==== params
|
11
|
+
# * +success+ - 0/1 (1 - YES)
|
12
|
+
# * +credit_card_expired+ - (credit card expiration YEAR-month)
|
13
|
+
# * +credit_card_number+ - (masked card number)
|
14
|
+
# * +credit_card_type+ - (credit card type upcased)
|
15
|
+
# * +customer_id+ - (customer id, that opened the iframe - check if currently logged in )
|
16
|
+
# * +date_time+ - UTC datetime ()
|
17
|
+
# * +result+ - =error string if success equal to 0 , credit card ups token other-way.
|
18
|
+
# * +secure_hash+ - SHA1 of result + success + customer_id + date_time + api_secret_key
|
19
|
+
let(:callback_params) {
|
20
|
+
{
|
21
|
+
'success' => '1',
|
22
|
+
'result' => '4UHSmRkBMhWtHloKQfkjVQ',
|
23
|
+
'customer_id' => 'john@doe.com',
|
24
|
+
'credit_card_expired' => '2020-12',
|
25
|
+
'credit_card_type' => 'MASTERCARD',
|
26
|
+
'credit_card_number' => '540400******0001',
|
27
|
+
'date_time' => '2014-06-06:09:19:16:000',
|
28
|
+
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
|
33
|
+
context "Has no token" do
|
34
|
+
|
35
|
+
let(:callback_params) {
|
36
|
+
{
|
37
|
+
'success' => '0',
|
38
|
+
'result' => 'Some error',
|
39
|
+
'customer_id' => 'john@doe.com',
|
40
|
+
'credit_card_expired' => '',
|
41
|
+
'credit_card_type' => '',
|
42
|
+
'credit_card_number' => '',
|
43
|
+
'date_time' => '2014-06-06:09:19:16:000',
|
44
|
+
|
45
|
+
}
|
46
|
+
}
|
47
|
+
it "should retrieve invalid credit card" do
|
48
|
+
|
49
|
+
credit_card = @store.retrieve_credit_card(@valid_params)
|
50
|
+
expect(credit_card).not_to be_valid
|
51
|
+
expect(credit_card.errors.full_messages).to eq([callback_params['result']])
|
52
|
+
end
|
53
|
+
|
54
|
+
context "Calling #retrieve_credit_card" do
|
55
|
+
it "should raise InvalidRequest error" do
|
56
|
+
expect { @store.retrieve_credit_card!(@valid_params) }.to raise_error(DidwwUps::Store::InvalidRequest, callback_params['result'])
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
context "Has success token" do
|
65
|
+
|
66
|
+
|
67
|
+
context "Secure hash is valid" do
|
68
|
+
it "should retrieve credit card" do
|
69
|
+
credit_card = @store.retrieve_credit_card(@valid_params)
|
70
|
+
expect(credit_card).to be_valid
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
context "Secure hash is invalid" do
|
76
|
+
it "should retrieve invalid credit card" do
|
77
|
+
params = @valid_params.merge('secure_hash' => "invalid")
|
78
|
+
credit_card = @store.retrieve_credit_card(params)
|
79
|
+
expect(credit_card).not_to be_valid
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
context "Build new credit card request" do
|
87
|
+
before do
|
88
|
+
@date_time = '2014-06-12 01:12:55'
|
89
|
+
allow(@store).to receive(:formatted_date_time) { @date_time }
|
90
|
+
|
91
|
+
|
92
|
+
end
|
93
|
+
it "should build valid uri" do
|
94
|
+
customer_id = 'some-unique_customer'
|
95
|
+
card_id = "12"
|
96
|
+
uri = @store.new_credit_card_uri(customer_id, {card_id: card_id})
|
97
|
+
query = Rack::Utils.parse_nested_query(uri.query)
|
98
|
+
expect(uri.host).to eq(DidwwUps::SANDBOX_HOST)
|
99
|
+
expect(query['customer_id']).to eq(customer_id)
|
100
|
+
expect(query['public_key']).to eq(@store['api_public_key'])
|
101
|
+
expect(query['date_time']).to eq(@date_time)
|
102
|
+
expect(query['hash']).to eq(@store.new_credit_card_uri_hash(customer_id, card_id, @date_time))
|
103
|
+
expect(uri.path).to eq(DidwwUps::Store::NEW_CREDIT_CARD_PATH)
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|