adyen-cse-ruby 0.1.5 → 1.1.3
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.
- checksums.yaml +5 -5
- data/.gitignore +0 -1
- data/.travis.yml +6 -2
- data/DEVELOPMENT.md +15 -0
- data/Gemfile.lock +31 -0
- data/README.md +86 -7
- data/adyen-cse-ruby.gemspec +4 -4
- data/lib/adyen_cse/encrypter.rb +28 -28
- data/lib/adyen_cse/version.rb +1 -1
- metadata +21 -21
- data/development.md +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1dc6b42606f020de53d9548fe9018476fb4292c5c4ef71cf158dc2d1c1b02c84
|
4
|
+
data.tar.gz: 6ea9ce274d8837186e3db4190541c3a6ab1310743e29794e1dfbeaf353507a15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65c0720f6cd58a0be9949f2c545f4857feb106af6fe8c52779c5f651ab2d270dce2cf1fddec64371e4cc1f3de209c5478531ceca9a649356efdd820a27f00ca3
|
7
|
+
data.tar.gz: 2f6197596e8a06eba8508fbfb8d006b7169777cb636c8c9d37eb2030a47960053dafe35487ec9be4545d64814f6dc3baba25b2774f63074e059f224a23d9e606
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/DEVELOPMENT.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Note to self.
|
2
|
+
|
3
|
+
## Developing
|
4
|
+
|
5
|
+
1. Run `bin/setup` to install dependencies
|
6
|
+
2. Run `bundle exec rake test` to run the tests
|
7
|
+
3. Run `bin/console` for an interactive prompt (optional, for debugging)
|
8
|
+
|
9
|
+
## Releasing New Version
|
10
|
+
|
11
|
+
1. Update version number in `version.rb`
|
12
|
+
2. Run `bundle exec rake release`. This will:
|
13
|
+
1. Create a git tag with the version number
|
14
|
+
2. Push git commits and tags to remote
|
15
|
+
3. Push the `.gem` file to [rubygems.org](https://rubygems.org)
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
adyen-cse-ruby (1.1.3)
|
5
|
+
openssl-ccm
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
coderay (1.1.3)
|
11
|
+
method_source (1.0.0)
|
12
|
+
minitest (5.14.1)
|
13
|
+
openssl-ccm (1.2.2)
|
14
|
+
pry (0.13.1)
|
15
|
+
coderay (~> 1.1)
|
16
|
+
method_source (~> 1.0)
|
17
|
+
rake (13.0.1)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
adyen-cse-ruby!
|
24
|
+
bundler
|
25
|
+
minitest
|
26
|
+
openssl-ccm
|
27
|
+
pry
|
28
|
+
rake
|
29
|
+
|
30
|
+
BUNDLED WITH
|
31
|
+
2.1.2
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
[](https://badge.fury.io/rb/adyen-cse-ruby)
|
1
2
|
[](https://travis-ci.org/jooeycheng/adyen-cse-ruby)
|
3
|
+
[](https://codeclimate.com/github/jooeycheng/adyen-cse-ruby/maintainability)
|
2
4
|
|
3
5
|
# Adyen CSE for Ruby
|
4
6
|
|
@@ -29,13 +31,90 @@ Or install it yourself as:
|
|
29
31
|
```ruby
|
30
32
|
require 'adyen_cse'
|
31
33
|
|
32
|
-
cse = AdyenCse::Encrypter.new(public_key)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
cse = AdyenCse::Encrypter.new(public_key)
|
35
|
+
|
36
|
+
encrypted_card = cse.encrypt!(
|
37
|
+
holder_name: "Adyen Shopper",
|
38
|
+
number: 4111_1111_1111_1111.to_s,
|
39
|
+
expiry_month: "08",
|
40
|
+
expiry_year: "2018",
|
41
|
+
cvc: "737"
|
42
|
+
)
|
43
|
+
```
|
44
|
+
|
45
|
+
Optionally, you may pass a custom `generation_time` to mock expired data.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
encrypted_card = cse.encrypt!(
|
49
|
+
...,
|
50
|
+
generation_time: Time.new(2015, 10, 21)
|
51
|
+
)
|
52
|
+
```
|
53
|
+
|
54
|
+
## factory_bot integration
|
55
|
+
Example of an `:adyen_test_card` factory with [factory_bot](https://github.com/thoughtbot/factory_bot).
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
# ./spec/factories/adyen_test_card.rb
|
59
|
+
|
60
|
+
require 'adyen_cse'
|
61
|
+
|
62
|
+
class AdyenTestCard
|
63
|
+
attr_reader :holder_name, :number, :expiry_month, :expiry_year, :cvc
|
64
|
+
|
65
|
+
PUBLIC_KEY = "your_public_key_here"
|
66
|
+
|
67
|
+
def initialize(params = {})
|
68
|
+
@holder_name = params[:holder_name]
|
69
|
+
@number = params[:number]
|
70
|
+
@expiry_month = params[:expiry_month]
|
71
|
+
@expiry_year = params[:expiry_year]
|
72
|
+
@cvc = params[:cvc]
|
73
|
+
end
|
74
|
+
|
75
|
+
def nonce
|
76
|
+
AdyenCse::Encrypter.new(PUBLIC_KEY).encrypt!(
|
77
|
+
holder_name: holder_name,
|
78
|
+
number: number,
|
79
|
+
expiry_month: expiry_month,
|
80
|
+
expiry_year: expiry_year,
|
81
|
+
cvc: cvc
|
82
|
+
)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
FactoryBot.define do
|
87
|
+
factory :adyen_test_card do
|
88
|
+
sequence(:holder_name) { |n| "Shopper #{n}" }
|
89
|
+
expiry_month { '08' }
|
90
|
+
expiry_year { '2018' }
|
91
|
+
cvc { '737' }
|
92
|
+
|
93
|
+
visa
|
94
|
+
|
95
|
+
trait :visa do
|
96
|
+
number { 4111_1111_1111_1111.to_s }
|
97
|
+
end
|
98
|
+
|
99
|
+
trait :mastercard do
|
100
|
+
number { 5555_5555_5555_4444.to_s }
|
101
|
+
end
|
102
|
+
|
103
|
+
trait :amex do
|
104
|
+
number { 3451_779254_88348.to_s }
|
105
|
+
cvc { '7373' }
|
106
|
+
end
|
107
|
+
|
108
|
+
skip_create
|
109
|
+
initialize_with { new(attributes) }
|
110
|
+
end
|
38
111
|
end
|
112
|
+
```
|
39
113
|
|
40
|
-
|
114
|
+
Example usage:
|
115
|
+
```ruby
|
116
|
+
RSpec.describe ExamplePaymentService do
|
117
|
+
let(:credit_card) { FactoryBot.build(:adyen_test_card) }
|
118
|
+
...
|
119
|
+
end
|
41
120
|
```
|
data/adyen-cse-ruby.gemspec
CHANGED
@@ -21,9 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
-
spec.add_runtime_dependency "openssl-ccm"
|
24
|
+
spec.add_runtime_dependency "openssl-ccm"
|
25
25
|
|
26
|
-
spec.add_development_dependency "bundler"
|
27
|
-
spec.add_development_dependency "rake"
|
28
|
-
spec.add_development_dependency "minitest"
|
26
|
+
spec.add_development_dependency "bundler"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "minitest"
|
29
29
|
end
|
data/lib/adyen_cse/encrypter.rb
CHANGED
@@ -5,27 +5,34 @@ require "json"
|
|
5
5
|
|
6
6
|
module AdyenCse
|
7
7
|
class Encrypter
|
8
|
-
PREFIX
|
9
|
-
VERSION
|
8
|
+
PREFIX = "adyenrb"
|
9
|
+
VERSION = "0_1_1"
|
10
10
|
|
11
|
-
attr_reader
|
12
|
-
attr_accessor :holder_name, :number, :expiry_month, :expiry_year, :cvc, :generation_time
|
11
|
+
attr_reader :public_key
|
13
12
|
|
14
13
|
def initialize(public_key)
|
15
14
|
@public_key = public_key
|
16
|
-
yield self rescue nil
|
17
|
-
self.generation_time ||= Time.now
|
18
15
|
end
|
19
16
|
|
20
|
-
def encrypt!
|
21
|
-
validate!
|
17
|
+
def encrypt!(params = {})
|
18
|
+
validate!(params.keys)
|
22
19
|
|
23
20
|
key = SecureRandom.random_bytes(32)
|
24
21
|
nonce = SecureRandom.random_bytes(12)
|
25
|
-
|
22
|
+
generation_time = params.fetch(:generation_time, Time.now)
|
23
|
+
|
24
|
+
# keys sorted alphabetically
|
25
|
+
json_data = {
|
26
|
+
"cvc" => params[:cvc],
|
27
|
+
"expiryMonth" => params[:expiry_month],
|
28
|
+
"expiryYear" => params[:expiry_year],
|
29
|
+
"generationtime" => generation_time.utc.strftime("%FT%T.%LZ"),
|
30
|
+
"holderName" => params[:holder_name],
|
31
|
+
"number" => params[:number],
|
32
|
+
}.to_json
|
26
33
|
|
27
34
|
ccm = OpenSSL::CCM.new("AES", key, 8)
|
28
|
-
encrypted_card = ccm.encrypt(
|
35
|
+
encrypted_card = ccm.encrypt(json_data, nonce)
|
29
36
|
|
30
37
|
rsa = self.class.parse_public_key(public_key)
|
31
38
|
encrypted_aes_key = rsa.public_encrypt(key)
|
@@ -35,32 +42,25 @@ module AdyenCse
|
|
35
42
|
[PREFIX, VERSION, "$", Base64.strict_encode64(encrypted_aes_key), "$", Base64.strict_encode64(encrypted_card_component)].join
|
36
43
|
end
|
37
44
|
|
38
|
-
def card_data
|
39
|
-
# keys sorted alphabetically
|
40
|
-
{
|
41
|
-
"cvc" => cvc,
|
42
|
-
"expiryMonth" => expiry_month,
|
43
|
-
"expiryYear" => expiry_year,
|
44
|
-
"generationtime" => generation_time.utc.strftime("%FT%T.%LZ"),
|
45
|
-
"holderName" => holder_name,
|
46
|
-
"number" => number,
|
47
|
-
}
|
48
|
-
end
|
49
|
-
|
50
45
|
def self.parse_public_key(public_key)
|
51
46
|
exponent, modulus = public_key.split("|").map { |n| n.to_i(16) }
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
if RUBY_VERSION < '2.4.0'
|
49
|
+
OpenSSL::PKey::RSA.new.tap do |rsa|
|
50
|
+
rsa.e = OpenSSL::BN.new(exponent)
|
51
|
+
rsa.n = OpenSSL::BN.new(modulus)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
rsa = OpenSSL::PKey::RSA.new
|
55
|
+
rsa.set_key(OpenSSL::BN.new(modulus), OpenSSL::BN.new(exponent), nil)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
private
|
60
60
|
|
61
|
-
def validate!
|
62
|
-
%
|
63
|
-
raise ArgumentError, "param `#{param}' is required"
|
61
|
+
def validate!(params)
|
62
|
+
%i(holder_name number expiry_month expiry_year cvc).each do |param|
|
63
|
+
raise ArgumentError, "param `#{param}' is required" unless params.include?(param)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
data/lib/adyen_cse/version.rb
CHANGED
metadata
CHANGED
@@ -1,71 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adyen-cse-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joey Cheng
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: openssl-ccm
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: minitest
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
description: Adyen's Client Side Encryption (CSE) library for Ruby.
|
70
70
|
email:
|
71
71
|
- jooeycheng@gmail.com
|
@@ -75,14 +75,15 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- ".gitignore"
|
77
77
|
- ".travis.yml"
|
78
|
+
- DEVELOPMENT.md
|
78
79
|
- Gemfile
|
80
|
+
- Gemfile.lock
|
79
81
|
- LICENSE
|
80
82
|
- README.md
|
81
83
|
- Rakefile
|
82
84
|
- adyen-cse-ruby.gemspec
|
83
85
|
- bin/console
|
84
86
|
- bin/setup
|
85
|
-
- development.md
|
86
87
|
- lib/adyen_cse.rb
|
87
88
|
- lib/adyen_cse/encrypter.rb
|
88
89
|
- lib/adyen_cse/version.rb
|
@@ -105,8 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
106
|
- !ruby/object:Gem::Version
|
106
107
|
version: '0'
|
107
108
|
requirements: []
|
108
|
-
|
109
|
-
rubygems_version: 2.5.1
|
109
|
+
rubygems_version: 3.1.2
|
110
110
|
signing_key:
|
111
111
|
specification_version: 4
|
112
112
|
summary: Adyen Client-side encryption library for Ruby
|
data/development.md
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
## Development
|
2
|
-
|
3
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
4
|
-
|
5
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
6
|
-
|
7
|
-
To release a new version, update the version number in `version.rb`,
|
8
|
-
and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|