google_pay_ruby 1.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +25 -0
- data/LICENSE.txt +9 -0
- data/README.md +158 -0
- data/lib/google_pay_ruby/ec_v2_decryption_strategy.rb +101 -0
- data/lib/google_pay_ruby/google_payment_decryption_error.rb +26 -0
- data/lib/google_pay_ruby/google_payment_method_token_context.rb +60 -0
- data/lib/google_pay_ruby/version.rb +5 -0
- data/lib/google_pay_ruby.rb +10 -0
- metadata +83 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 11c693c4ee510867c2a52137125cbb477c076e966ebb8341643ade2138a85418
|
|
4
|
+
data.tar.gz: aae173c01a2bb5f41255e6c372e947dbfcb4e0461a13234aefe2ab2ca77accba
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a15ac114c7aece47d4e96e89dbe59ed0f52913fac131d8bc2854ac73c992c2323c8ba4c77440b48fb69124f5e4b069cf7b2a17a5c43d7e4fc9462fa8c86bcab7
|
|
7
|
+
data.tar.gz: 9ecb09181a31652d1bb2fada7f3251bf7d247cb5a09fe32d7fabcebe0f6ef54d8a29931aae810338765f6a6a78c432742eff1d596ee35f04d72c4b4b03e88875
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-02-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release
|
|
12
|
+
- ECv2 protocol support for Google Pay token decryption
|
|
13
|
+
- Multiple merchant key support for key rotation
|
|
14
|
+
- Pure Ruby implementation using OpenSSL
|
|
15
|
+
- Comprehensive error handling with detailed error messages
|
|
16
|
+
- Support for both string and symbol keys in token hashes
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
- `GooglePaymentMethodTokenContext` class for managing decryption context
|
|
20
|
+
- `EcV2DecryptionStrategy` class implementing ECv2 decryption algorithm
|
|
21
|
+
- `GooglePaymentDecryptionError` exception class with detailed error tracking
|
|
22
|
+
- ECDH shared secret computation
|
|
23
|
+
- HKDF key derivation
|
|
24
|
+
- HMAC verification
|
|
25
|
+
- AES-256-CTR decryption
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
Copyright <2026> <Sahil Gadimbayli>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# GooglePayRuby
|
|
2
|
+
|
|
3
|
+
A Ruby utility for securely decrypting Google Pay PaymentMethodTokens using the ECv2 protocol. This gem is inspired from [Basis Theory google-pay-js](https://github.com/Basis-Theory/google-pay-js) library.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Google Pay PaymentMethodToken Decryption**: Securely decrypt user-authorized Google Pay transaction tokens using easy-to-use interfaces
|
|
8
|
+
- **Key Rotation Support**: Handle multiple private keys simultaneously to support seamless key rotation without missing payments
|
|
9
|
+
- **Pure Ruby Implementation**: No external dependencies beyond OpenSSL (included in Ruby standard library)
|
|
10
|
+
- **ECv2 Protocol Support**: Implements Google Pay's ECv2 encryption protocol
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
Add this line to your application's Gemfile:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
gem 'google_pay_ruby'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
And then execute:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
bundle install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or install it yourself as:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
gem install google_pay_ruby
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Google Pay Setup
|
|
33
|
+
|
|
34
|
+
Follow [Google Pay API guides](https://developers.google.com/pay/api) for your platform. To use this library, you need to:
|
|
35
|
+
|
|
36
|
+
1. Be PCI Level 1 certified
|
|
37
|
+
2. Choose tokenization type `DIRECT`
|
|
38
|
+
3. Generate and register your encryption keys with Google
|
|
39
|
+
|
|
40
|
+
⚠️ **Important**: If you are not PCI Level 1 certified, consider using `PAYMENT_GATEWAY` tokenization type or contact a payment gateway provider.
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### Basic Example
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
require 'google_pay_ruby'
|
|
48
|
+
|
|
49
|
+
# Load your private key (from file, KMS, secrets manager, etc.)
|
|
50
|
+
private_key_pem = File.read('path/to/your/private_key.pem')
|
|
51
|
+
|
|
52
|
+
# Create the decryption context
|
|
53
|
+
context = GooglePayRuby::GooglePaymentMethodTokenContext.new(
|
|
54
|
+
merchants: [
|
|
55
|
+
{
|
|
56
|
+
identifier: 'my-merchant-identifier', # Optional, for debugging
|
|
57
|
+
private_key_pem: private_key_pem
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Get the token from Google Pay API response
|
|
63
|
+
token = {
|
|
64
|
+
'protocolVersion' => 'ECv2',
|
|
65
|
+
'signature' => '...',
|
|
66
|
+
'signedMessage' => '{"encryptedMessage":"...","ephemeralPublicKey":"...","tag":"..."}'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Decrypt the token
|
|
70
|
+
begin
|
|
71
|
+
decrypted_data = context.decrypt(token)
|
|
72
|
+
|
|
73
|
+
puts "PAN: #{decrypted_data['paymentMethodDetails']['pan']}"
|
|
74
|
+
puts "Expiration: #{decrypted_data['paymentMethodDetails']['expirationMonth']}/#{decrypted_data['paymentMethodDetails']['expirationYear']}"
|
|
75
|
+
puts "Cryptogram: #{decrypted_data['paymentMethodDetails']['cryptogram']}"
|
|
76
|
+
rescue GooglePayRuby::GooglePaymentDecryptionError => e
|
|
77
|
+
puts "Decryption failed: #{e.message}"
|
|
78
|
+
end
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Key Rotation Support
|
|
82
|
+
|
|
83
|
+
Handle key rotation gracefully by providing multiple private keys:
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
context = GooglePayRuby::GooglePaymentMethodTokenContext.new(
|
|
87
|
+
merchants: [
|
|
88
|
+
{
|
|
89
|
+
identifier: 'current-key',
|
|
90
|
+
private_key_pem: File.read('current_key.pem')
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
identifier: 'previous-key',
|
|
94
|
+
private_key_pem: File.read('previous_key.pem')
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# The library will try each key until decryption succeeds
|
|
100
|
+
decrypted_data = context.decrypt(token)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Decrypted Data Structure
|
|
104
|
+
|
|
105
|
+
The decrypted payment data contains:
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
{
|
|
109
|
+
"gatewayMerchantId" => "your-gateway-merchant-id",
|
|
110
|
+
"messageExpiration" => "1234567890123",
|
|
111
|
+
"messageId" => "AH2Ejtc...",
|
|
112
|
+
"paymentMethod" => "CARD",
|
|
113
|
+
"paymentMethodDetails" => {
|
|
114
|
+
"pan" => "4111111111111111",
|
|
115
|
+
"expirationMonth" => 12,
|
|
116
|
+
"expirationYear" => 2025,
|
|
117
|
+
"authMethod" => "CRYPTOGRAM_3DS",
|
|
118
|
+
"cryptogram" => "AAAAAA...",
|
|
119
|
+
"eciIndicator" => "05"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Error Handling
|
|
125
|
+
|
|
126
|
+
The gem raises `GooglePayRuby::GooglePaymentDecryptionError` when decryption fails:
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
begin
|
|
130
|
+
decrypted_data = context.decrypt(token)
|
|
131
|
+
rescue GooglePayRuby::GooglePaymentDecryptionError => e
|
|
132
|
+
# Access detailed error information
|
|
133
|
+
puts e.message
|
|
134
|
+
puts e.full_message # Includes details from all attempted keys
|
|
135
|
+
|
|
136
|
+
# Access individual errors
|
|
137
|
+
e.errors.each do |error|
|
|
138
|
+
puts "Merchant: #{error.merchant_identifier}"
|
|
139
|
+
puts "Error: #{error.message}"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Development
|
|
145
|
+
|
|
146
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `ruby test/test_decrypt.rb` to run the tests.
|
|
147
|
+
|
|
148
|
+
## Contributing
|
|
149
|
+
|
|
150
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/better-payment/google-pay-ruby.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
155
|
+
|
|
156
|
+
## Credits
|
|
157
|
+
|
|
158
|
+
This Ruby implementation is inspired from [Basis Theory google-pay-js](https://github.com/Basis-Theory/google-pay-js) library.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'openssl'
|
|
4
|
+
require 'base64'
|
|
5
|
+
require 'json'
|
|
6
|
+
|
|
7
|
+
module GooglePayRuby
|
|
8
|
+
class EcV2DecryptionStrategy
|
|
9
|
+
def initialize(private_key_pem)
|
|
10
|
+
@private_key = OpenSSL::PKey::EC.new(private_key_pem)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def decrypt(signed_message)
|
|
14
|
+
parsed_message = JSON.parse(signed_message)
|
|
15
|
+
|
|
16
|
+
ephemeral_public_key = parsed_message['ephemeralPublicKey']
|
|
17
|
+
encrypted_message = parsed_message['encryptedMessage']
|
|
18
|
+
tag = parsed_message['tag']
|
|
19
|
+
|
|
20
|
+
shared_key = get_shared_key(ephemeral_public_key)
|
|
21
|
+
derived_key = get_derived_key(ephemeral_public_key, shared_key)
|
|
22
|
+
|
|
23
|
+
symmetric_encryption_key = derived_key[0...64]
|
|
24
|
+
mac_key = derived_key[64..-1]
|
|
25
|
+
|
|
26
|
+
verify_message_hmac(mac_key, tag, encrypted_message)
|
|
27
|
+
|
|
28
|
+
decrypted_message = decrypt_message(encrypted_message, symmetric_encryption_key)
|
|
29
|
+
|
|
30
|
+
JSON.parse(decrypted_message)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def get_shared_key(ephemeral_public_key_b64)
|
|
36
|
+
# Decode the ephemeral public key from base64
|
|
37
|
+
ephemeral_public_key_bytes = Base64.strict_decode64(ephemeral_public_key_b64)
|
|
38
|
+
|
|
39
|
+
# Create an EC point object for the ephemeral public key
|
|
40
|
+
group = OpenSSL::PKey::EC::Group.new('prime256v1')
|
|
41
|
+
point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(ephemeral_public_key_bytes, 2))
|
|
42
|
+
|
|
43
|
+
# Compute ECDH shared secret directly from the point (OpenSSL 3.0 compatible)
|
|
44
|
+
shared_secret = @private_key.dh_compute_key(point)
|
|
45
|
+
|
|
46
|
+
shared_secret.unpack1('H*')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get_derived_key(ephemeral_public_key, shared_key)
|
|
50
|
+
# Concatenate ephemeral public key and shared key
|
|
51
|
+
info = Base64.strict_decode64(ephemeral_public_key) + [shared_key].pack('H*')
|
|
52
|
+
|
|
53
|
+
# Use HKDF with SHA-256
|
|
54
|
+
salt = "\x00" * 32
|
|
55
|
+
|
|
56
|
+
# HKDF implementation
|
|
57
|
+
prk = OpenSSL::HMAC.digest('SHA256', salt, info)
|
|
58
|
+
|
|
59
|
+
# Expand with info="Google" to get 64 bytes
|
|
60
|
+
t = ''
|
|
61
|
+
okm = ''
|
|
62
|
+
counter = 1
|
|
63
|
+
|
|
64
|
+
while okm.length < 64
|
|
65
|
+
t = OpenSSL::HMAC.digest('SHA256', prk, t + 'Google' + [counter].pack('C'))
|
|
66
|
+
okm += t
|
|
67
|
+
counter += 1
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
okm[0...64].unpack1('H*')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def verify_message_hmac(mac_key, tag, encrypted_message)
|
|
74
|
+
mac_key_bytes = [mac_key].pack('H*')
|
|
75
|
+
encrypted_message_bytes = Base64.strict_decode64(encrypted_message)
|
|
76
|
+
|
|
77
|
+
calculated_hmac = OpenSSL::HMAC.digest('SHA256', mac_key_bytes, encrypted_message_bytes)
|
|
78
|
+
calculated_tag = Base64.strict_encode64(calculated_hmac)
|
|
79
|
+
|
|
80
|
+
unless calculated_tag == tag
|
|
81
|
+
raise GooglePaymentDecryptionError, 'Tag is not a valid MAC for the encrypted message'
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def decrypt_message(encrypted_message, symmetric_encryption_key)
|
|
86
|
+
key = [symmetric_encryption_key].pack('H*')
|
|
87
|
+
iv = "\x00" * 16
|
|
88
|
+
|
|
89
|
+
encrypted_data = Base64.strict_decode64(encrypted_message)
|
|
90
|
+
|
|
91
|
+
decipher = OpenSSL::Cipher.new('AES-256-CTR')
|
|
92
|
+
decipher.decrypt
|
|
93
|
+
decipher.key = key
|
|
94
|
+
decipher.iv = iv
|
|
95
|
+
|
|
96
|
+
decrypted = decipher.update(encrypted_data) + decipher.final
|
|
97
|
+
|
|
98
|
+
decrypted.force_encoding('UTF-8')
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GooglePayRuby
|
|
4
|
+
class GooglePaymentDecryptionError < StandardError
|
|
5
|
+
attr_reader :errors
|
|
6
|
+
|
|
7
|
+
def initialize(message, errors = [])
|
|
8
|
+
@errors = errors
|
|
9
|
+
super(message)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def full_message
|
|
13
|
+
message_parts = [message]
|
|
14
|
+
|
|
15
|
+
if errors.any?
|
|
16
|
+
message_parts << "\nDecryption attempts failed:"
|
|
17
|
+
errors.each_with_index do |error, index|
|
|
18
|
+
merchant_id = error.respond_to?(:merchant_identifier) ? error.merchant_identifier : "Unknown"
|
|
19
|
+
message_parts << " [#{index + 1}] Merchant: #{merchant_id} - #{error.message}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
message_parts.join("\n")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GooglePayRuby
|
|
4
|
+
class GooglePaymentMethodTokenContext
|
|
5
|
+
attr_reader :merchants
|
|
6
|
+
|
|
7
|
+
def initialize(options)
|
|
8
|
+
@merchants = options[:merchants] || []
|
|
9
|
+
|
|
10
|
+
if @merchants.empty?
|
|
11
|
+
raise GooglePaymentDecryptionError.new(
|
|
12
|
+
'No merchant configuration provided for decryption context.'
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
validate_merchant_configurations!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def decrypt(token)
|
|
20
|
+
protocol_version = token['protocolVersion'] || token[:protocolVersion]
|
|
21
|
+
unless protocol_version == 'ECv2'
|
|
22
|
+
raise GooglePaymentDecryptionError.new(
|
|
23
|
+
"Unsupported decryption for protocol version #{protocol_version}"
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
errors = []
|
|
28
|
+
signed_message = token['signedMessage'] || token[:signedMessage]
|
|
29
|
+
|
|
30
|
+
@merchants.each do |merchant|
|
|
31
|
+
begin
|
|
32
|
+
strategy = EcV2DecryptionStrategy.new(merchant[:private_key_pem])
|
|
33
|
+
return strategy.decrypt(signed_message)
|
|
34
|
+
rescue StandardError => e
|
|
35
|
+
e.define_singleton_method(:merchant_identifier) { merchant[:identifier] }
|
|
36
|
+
errors << e
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
raise GooglePaymentDecryptionError.new(
|
|
41
|
+
'Failed to decrypt payment data using provided merchant configuration(s).',
|
|
42
|
+
errors
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def validate_merchant_configurations!
|
|
49
|
+
@merchants.each_with_index do |merchant, index|
|
|
50
|
+
unless merchant.is_a?(Hash)
|
|
51
|
+
raise ArgumentError, "Merchant configuration at index #{index} must be a Hash"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
unless merchant[:private_key_pem]
|
|
55
|
+
raise ArgumentError, "Merchant configuration at index #{index} must include :private_key_pem"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "google_pay_ruby/version"
|
|
4
|
+
require_relative "google_pay_ruby/google_payment_method_token_context"
|
|
5
|
+
require_relative "google_pay_ruby/ec_v2_decryption_strategy"
|
|
6
|
+
require_relative "google_pay_ruby/google_payment_decryption_error"
|
|
7
|
+
|
|
8
|
+
module GooglePayRuby
|
|
9
|
+
class Error < StandardError; end
|
|
10
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: google_pay_ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Sahil Gadimbayli
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-05 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rake
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '13.0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '13.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rubocop
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.21'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.21'
|
|
41
|
+
description: A Ruby implementation for securely decrypting Google Pay PaymentMethodTokens
|
|
42
|
+
using ECv2 protocol. Supports key rotation and multiple merchant configurations.
|
|
43
|
+
email:
|
|
44
|
+
- contact@sahilgadimbayli.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- CHANGELOG.md
|
|
50
|
+
- LICENSE.txt
|
|
51
|
+
- README.md
|
|
52
|
+
- lib/google_pay_ruby.rb
|
|
53
|
+
- lib/google_pay_ruby/ec_v2_decryption_strategy.rb
|
|
54
|
+
- lib/google_pay_ruby/google_payment_decryption_error.rb
|
|
55
|
+
- lib/google_pay_ruby/google_payment_method_token_context.rb
|
|
56
|
+
- lib/google_pay_ruby/version.rb
|
|
57
|
+
homepage: https://github.com/better-payment/google-pay-ruby
|
|
58
|
+
licenses:
|
|
59
|
+
- MIT
|
|
60
|
+
metadata:
|
|
61
|
+
homepage_uri: https://github.com/better-payment/google-pay-ruby
|
|
62
|
+
source_code_uri: https://github.com/better-payment/google-pay-ruby
|
|
63
|
+
changelog_uri: https://github.com/better-payment/google-pay-ruby/blob/main/CHANGELOG.md
|
|
64
|
+
post_install_message:
|
|
65
|
+
rdoc_options: []
|
|
66
|
+
require_paths:
|
|
67
|
+
- lib
|
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: 2.7.0
|
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
requirements: []
|
|
79
|
+
rubygems_version: 3.4.19
|
|
80
|
+
signing_key:
|
|
81
|
+
specification_version: 4
|
|
82
|
+
summary: Ruby utility for decrypting Google Pay Tokens
|
|
83
|
+
test_files: []
|