itunes_receipt_encoder 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 389838e63604ad8eca54e6ffce19a8f846a2a159
4
+ data.tar.gz: 5717db2e0eef76637858030ff38a30de9f82fd6e
5
+ SHA512:
6
+ metadata.gz: 2e098be05c5b76611439a75836814c02c179024945d683bffb9f9d019964108ebc18dfbb19fc591d80386e396bb45e650b6919d006efde253c6383ac538cb4b6
7
+ data.tar.gz: 3d5a71c47406936b24507df03b18acc5ca5ff71fba3bd2a026fe4e77fcc6188029e742b85d59afb50253d0dc7b7b4a7dcd8c4467eff98806ce2f228ba209258c
@@ -0,0 +1,42 @@
1
+ require 'openssl'
2
+
3
+ ##
4
+ # ItunesReceiptEncoder
5
+ module ItunesReceiptEncoder
6
+ ##
7
+ # ItunesReceiptEncoder::ASN1
8
+ module ASN1
9
+ ##
10
+ # ItunesReceiptEncoder::ASN1::Sequence
11
+ class Sequence
12
+ attr_reader :encoding, :type
13
+
14
+ def initialize(value, type, encoding = nil)
15
+ @value = value
16
+ @encoding = encoding
17
+ @type = type
18
+ end
19
+
20
+ def value
21
+ case encoding
22
+ when :utf8_string
23
+ OpenSSL::ASN1::UTF8String.new(@value.to_s).to_der
24
+ when :ia5_string
25
+ OpenSSL::ASN1::IA5String.new(@value.to_s).to_der
26
+ when :integer
27
+ OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(@value.to_s)).to_der
28
+ else
29
+ @value
30
+ end
31
+ end
32
+
33
+ def to_seq
34
+ OpenSSL::ASN1::Sequence.new([
35
+ OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(type.to_s)),
36
+ OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(ASN1_VERSION.to_s)),
37
+ OpenSSL::ASN1::OctetString.new(value.to_s)
38
+ ])
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ require 'openssl'
2
+ require 'itunes_receipt_encoder/asn1/sequence'
3
+
4
+ ##
5
+ # ItunesReceiptEncoder
6
+ module ItunesReceiptEncoder
7
+ ##
8
+ # ItunesReceiptEncoder::ASN1
9
+ module ASN1
10
+ ASN1_VERSION = 1
11
+
12
+ def self.sequence(value, encoding, type = nil)
13
+ Sequence.new(value, encoding, type).to_seq
14
+ end
15
+
16
+ def self.set(array)
17
+ OpenSSL::ASN1::Set.new(array.compact)
18
+ end
19
+
20
+ def self.time(time)
21
+ time && time.utc.strftime('%FT%TZ')
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,96 @@
1
+ require 'itunes_receipt_encoder/utils'
2
+ require 'itunes_receipt_encoder/asn1'
3
+
4
+ ##
5
+ # ItunesReceiptEncoder
6
+ module ItunesReceiptEncoder
7
+ ##
8
+ # ItunesReceiptEncoder::InApp
9
+ class InApp
10
+ include Utils
11
+
12
+ attr_accessor :quantity, :product_id, :transaction_id,
13
+ :original_transaction_id, :purchase_date,
14
+ :original_purchase_date, :expires_date, :cancellation_date,
15
+ :web_order_line_item_id, :item_id
16
+
17
+ def initialize(attrs = {})
18
+ attrs.each { |key, val| send("#{key}=", val) }
19
+ end
20
+
21
+ def to_asn1_set
22
+ ASN1.set [
23
+ asn1_quantity,
24
+ asn1_product_id,
25
+ asn1_transaction_id,
26
+ asn1_original_transaction_id,
27
+ asn1_purchase_date,
28
+ asn1_original_purchase_date,
29
+ asn1_web_order_line_item_id,
30
+ (asn1_expires_date if expires_date),
31
+ (asn1_cancellation_date if cancellation_date)
32
+ ]
33
+ end
34
+
35
+ def to_plist_hash(options = {})
36
+ hash = {
37
+ 'quantity' => quantity,
38
+ 'product-id' => product_id,
39
+ 'transaction-id' => transaction_id,
40
+ 'original_transaction-id' => original_transaction_id,
41
+ 'purchase-date' => gmt_time(purchase_date),
42
+ 'original-purchase-date' => gmt_time(original_purchase_date),
43
+ 'expires-date-formatted' => gmt_time(expires_date)
44
+ }
45
+ hash.merge!(
46
+ 'purchase-date-ms' => ms_time(purchase_date),
47
+ 'original-purchase_date_ms' => ms_time(original_purchase_date),
48
+ 'expires-date' => gmt_time(expires_date)
49
+ ) unless options[:no_ms_dates]
50
+ hash.merge!(
51
+ 'purchase-date-pst' => pst_time(purchase_date),
52
+ 'original-purchase-date-pst' => pst_time(original_purchase_date),
53
+ 'expires-date-pst' => pst_time(expires_date)
54
+ ) unless options[:no_pst_dates]
55
+ hash
56
+ end
57
+
58
+ private
59
+
60
+ def asn1_quantity
61
+ ASN1.sequence quantity, 1701, :integer
62
+ end
63
+
64
+ def asn1_product_id
65
+ ASN1.sequence product_id, 1702, :utf8_string
66
+ end
67
+
68
+ def asn1_transaction_id
69
+ ASN1.sequence transaction_id, 1703, :utf8_string
70
+ end
71
+
72
+ def asn1_original_transaction_id
73
+ ASN1.sequence original_transaction_id, 1705, :utf8_string
74
+ end
75
+
76
+ def asn1_web_order_line_item_id
77
+ ASN1.sequence web_order_line_item_id, 1711, :integer
78
+ end
79
+
80
+ def asn1_purchase_date
81
+ ASN1.sequence ASN1.time(purchase_date), 1704, :ia5_string
82
+ end
83
+
84
+ def asn1_original_purchase_date
85
+ ASN1.sequence ASN1.time(original_purchase_date), 1706, :ia5_string
86
+ end
87
+
88
+ def asn1_expires_date
89
+ ASN1.sequence ASN1.time(expires_date), 1708, :ia5_string
90
+ end
91
+
92
+ def asn1_cancellation_date
93
+ ASN1.sequence ASN1.time(cancellation_date), 1712, :ia5_string
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,86 @@
1
+ require 'itunes_receipt_encoder/utils'
2
+ require 'itunes_receipt_encoder/in_app'
3
+ require 'itunes_receipt_encoder/asn1'
4
+
5
+ ##
6
+ # ItunesReceiptEncoder
7
+ module ItunesReceiptEncoder
8
+ ##
9
+ # ItunesReceiptEncoder::Payload
10
+ class Payload
11
+ include Utils
12
+
13
+ attr_accessor :environment, :bundle_id, :application_version,
14
+ :original_application_version, :creation_date,
15
+ :expiration_date, :opaque_value, :sha1_hash, :in_app,
16
+ :unique_vendor_identifier
17
+
18
+ def initialize(attrs = {})
19
+ attrs.each { |key, val| send("#{key}=", val) }
20
+ @in_app ||= []
21
+ yield self if block_given?
22
+ end
23
+
24
+ def to_asn1_set
25
+ ASN1.set [
26
+ asn1_environment,
27
+ asn1_bundle_id,
28
+ asn1_application_version,
29
+ asn1_original_application_version,
30
+ asn1_creation_date,
31
+ (asn1_opaque_value if opaque_value),
32
+ (asn1_sha1_hash if sha1_hash),
33
+ (asn1_expiration_date if expiration_date)
34
+ ].concat(asn1_in_app)
35
+ end
36
+
37
+ def to_plist_hash(options = {})
38
+ transaction = InApp.new(in_app[options.fetch(:index, 0)])
39
+ {
40
+ 'bid' => bundle_id.to_s,
41
+ 'bvrs' => application_version.to_s,
42
+ 'unique-vendor-identifier' => unique_vendor_identifier.to_s
43
+ }.merge(transaction.to_plist_hash(options))
44
+ end
45
+
46
+ private
47
+
48
+ def asn1_environment
49
+ ASN1.sequence environment, 0, :utf8_string
50
+ end
51
+
52
+ def asn1_bundle_id
53
+ ASN1.sequence bundle_id, 2, :utf8_string
54
+ end
55
+
56
+ def asn1_application_version
57
+ ASN1.sequence application_version, 3, :utf8_string
58
+ end
59
+
60
+ def asn1_opaque_value
61
+ ASN1.sequence opaque_value, 4
62
+ end
63
+
64
+ def asn1_sha1_hash
65
+ ASN1.sequence sha1_hash, 5
66
+ end
67
+
68
+ def asn1_original_application_version
69
+ ASN1.sequence original_application_version, 19, :utf8_string
70
+ end
71
+
72
+ def asn1_creation_date
73
+ ASN1.sequence ASN1.time(creation_date), 12, :ia5_string
74
+ end
75
+
76
+ def asn1_expiration_date
77
+ ASN1.sequence ASN1.time(expiration_date), 21, :ia5_string
78
+ end
79
+
80
+ def asn1_in_app
81
+ in_app.map do |in_app|
82
+ ASN1.sequence InApp.new(in_app).to_asn1_set.to_der, 17
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,91 @@
1
+ require 'base64'
2
+ require 'cfpropertylist'
3
+ require 'itunes_receipt_encoder/payload'
4
+
5
+ ##
6
+ # ItunesReceiptEncoder
7
+ module ItunesReceiptEncoder
8
+ ##
9
+ # ItunesReceiptEncoder::Receipt
10
+ class Receipt
11
+ PRIVATE_KEY = <<-EOF
12
+ -----BEGIN RSA PRIVATE KEY-----
13
+ MIICXgIBAAKBgQCwFAFtL0PVWIAhkZGvOieoG+FYbSxGsQZ+oj8p71kSIPj4zo1/
14
+ tNAB4hZZkhNUcys1WXb1AK5dXlMs4AwK6zIANvlwJxu4fBIW+sENc4yHaJWfcZJR
15
+ tgX35aWzAPTSjy/ChsYGwV9eVHNN1iG47E5vwLYH7B8xmagK8ame5cNIhwIDAQAB
16
+ AoGBAK8VhYGbYRkw4l/+zt1tt2c7Ke1yyXcVqj6beLFrNaeIL+nAAgW9tqRYux6f
17
+ 2Sa9SnbHGjlvTvK6y3ww4OiujEzxRO/0ERUk49bkKt/wmEgBpp76mNcoosBu21Gq
18
+ p/C9NGkqqvV31nDhcgqYBAqI7Yc2d0vsUV4pPBw8tGl4yjKpAkEA4lTYxtXn7y2j
19
+ TFOQvmQkctqwC1zi2OtvP4uo3llnLsE1ffIQYk8c1jBXChiGgT7v2frZIv+fIUk/
20
+ DSxUEkDG7QJBAMcoxq91664GOZSsmZJK6R8uDbOrQ/PGTSrBfvwPP/CtUSJotaP2
21
+ qOFl8CttDs7DJbS6mY5oplNjN8s0MknwisMCQA13FMqHkVvmcC+rTRI2rQB0SEL0
22
+ zL4xC5ZRPcO0t/HNJtyOWTEwGbwYdiUwnlf0IZrrVJ3DbXkyfWDQQVQwrGUCQQCT
23
+ 7T+Wd/n0Kn9+ZK00shtxo11eBGnWmYYbqdlOE22ksLdA3ZF9FerecD7xonGLNfu9
24
+ v5Pq6OQRr/JzJnPr45TNAkEAkqll2DUKWTKiva4MPvda30vZFbraRkW0WUWNIara
25
+ RDUtoqjlu22PZhexNT4aulrb7OVBxq4yjqdGq5Kgo1z8mw==
26
+ -----END RSA PRIVATE KEY-----
27
+ EOF
28
+ CERTIFICATE = <<-EOF
29
+ -----BEGIN CERTIFICATE-----
30
+ MIIC3jCCAkegAwIBAgIJAN0obOgx+IbBMA0GCSqGSIb3DQEBBQUAMFQxCzAJBgNV
31
+ BAYTAkRFMQ8wDQYDVQQIEwZCZXJsaW4xDzANBgNVBAcTBkJlcmxpbjEjMCEGA1UE
32
+ ChMabWJhYXN5IG1vYmlsZSBzb2x1dGlvbnMgVUcwHhcNMTUxMjExMTczNjU3WhcN
33
+ MTYxMjEwMTczNjU3WjBUMQswCQYDVQQGEwJERTEPMA0GA1UECBMGQmVybGluMQ8w
34
+ DQYDVQQHEwZCZXJsaW4xIzAhBgNVBAoTGm1iYWFzeSBtb2JpbGUgc29sdXRpb25z
35
+ IFVHMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwFAFtL0PVWIAhkZGvOieo
36
+ G+FYbSxGsQZ+oj8p71kSIPj4zo1/tNAB4hZZkhNUcys1WXb1AK5dXlMs4AwK6zIA
37
+ NvlwJxu4fBIW+sENc4yHaJWfcZJRtgX35aWzAPTSjy/ChsYGwV9eVHNN1iG47E5v
38
+ wLYH7B8xmagK8ame5cNIhwIDAQABo4G3MIG0MB0GA1UdDgQWBBRWJ8qIehJu60Jt
39
+ 8QDfEjx/BZIFqTCBhAYDVR0jBH0we4AUVifKiHoSbutCbfEA3xI8fwWSBamhWKRW
40
+ MFQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZCZXJsaW4xDzANBgNVBAcTBkJlcmxp
41
+ bjEjMCEGA1UEChMabWJhYXN5IG1vYmlsZSBzb2x1dGlvbnMgVUeCCQDdKGzoMfiG
42
+ wTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABBYeC04N2OMT5pPEeC2
43
+ Ckl6J9RkVghCz/LurxcqWXzZvt4SbBhKTGRxoIGKIbtkz8Kk3MoCH2/HwSNd56+W
44
+ LRZiVl2m9xTwOjNmZI2hqe8Ps3oY5IJyPp/9A6OQqVCB59zW2Br547Su+5hhxRcX
45
+ iZxrB9LI1CXppp9/9b8D0vYf
46
+ -----END CERTIFICATE-----
47
+ EOF
48
+
49
+ attr_reader :payload
50
+
51
+ def initialize(attrs = {})
52
+ @payload = Payload.new(attrs)
53
+ yield self if block_given?
54
+ end
55
+
56
+ def to_unified(options = {})
57
+ receipt = OpenSSL::PKCS7.sign(
58
+ OpenSSL::X509::Certificate.new(options.fetch(:cert, CERTIFICATE)),
59
+ OpenSSL::PKey::RSA.new(options.fetch(:key, PRIVATE_KEY)),
60
+ payload.to_asn1_set.to_der,
61
+ [],
62
+ OpenSSL::PKCS7::BINARY
63
+ ).to_der
64
+ options[:raw] ? receipt : [receipt].pack('m0')
65
+ end
66
+
67
+ def to_transaction(options = {})
68
+ data = {
69
+ 'purchase-info' => purchase_info_plist(options),
70
+ 'signature' => options.fetch(:signature, 'unsigned'),
71
+ 'pod' => options.fetch(:pod, 100),
72
+ 'signing-status' => options.fetch(:signing_status, 0)
73
+ }
74
+ data.merge!('environment' => payload.environment) unless
75
+ payload.environment == 'Production'
76
+ plist = CFPropertyList::List.new
77
+ plist.value = CFPropertyList.guess data
78
+ receipt = plist.to_str(CFPropertyList::List::FORMAT_PLAIN)
79
+ options[:raw] ? receipt : [receipt].pack('m0')
80
+ end
81
+
82
+ private
83
+
84
+ def purchase_info_plist(options)
85
+ plist = CFPropertyList::List.new
86
+ plist.value = CFPropertyList.guess payload.to_plist_hash(options)
87
+ purchase_info = plist.to_str(CFPropertyList::List::FORMAT_PLAIN)
88
+ [purchase_info].pack('m0')
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,20 @@
1
+ ##
2
+ # ItunesReceiptEncoder
3
+ module ItunesReceiptEncoder
4
+ ##
5
+ # ItunesReceiptEncoder::Receipt
6
+ module Utils
7
+ def gmt_time(time)
8
+ time.utc.strftime('%F %T') + ' Etc/GMT'
9
+ end
10
+
11
+ def pst_time(time)
12
+ (time + Time.zone_offset('PST'))
13
+ .strftime('%F %T') + ' America/Los_Angeles'
14
+ end
15
+
16
+ def ms_time(time)
17
+ (time.to_i * 1000).to_s
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ ##
2
+ # ItunesReceiptEncoder
3
+ module ItunesReceiptEncoder
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,9 @@
1
+ require 'itunes_receipt_encoder/receipt'
2
+
3
+ ##
4
+ # ItunesReceiptEncoder
5
+ module ItunesReceiptEncoder
6
+ def self.new(attrs = {}, &block)
7
+ Receipt.new(attrs, &block)
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,208 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: itunes_receipt_encoder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - mbaasy.com
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: CFPropertyList
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubygems-tasks
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.10'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.10'
83
+ - !ruby/object:Gem::Dependency
84
+ name: codeclimate-test-reporter
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.4'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.33'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.33'
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.22'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.22'
125
+ - !ruby/object:Gem::Dependency
126
+ name: byebug
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '8.2'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '8.2'
139
+ - !ruby/object:Gem::Dependency
140
+ name: ffaker
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '2.1'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '2.1'
153
+ - !ruby/object:Gem::Dependency
154
+ name: itunes_receipt_decoder
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '='
158
+ - !ruby/object:Gem::Version
159
+ version: 0.2.3
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '='
165
+ - !ruby/object:Gem::Version
166
+ version: 0.2.3
167
+ description: |2
168
+ Encodes receipt data into iTunes encoded receipts and exports as
169
+ appStoreReceiptURL or transactionReceipt formats.
170
+ email: hello@mbaasy.com
171
+ executables: []
172
+ extensions: []
173
+ extra_rdoc_files: []
174
+ files:
175
+ - lib/itunes_receipt_encoder.rb
176
+ - lib/itunes_receipt_encoder/asn1.rb
177
+ - lib/itunes_receipt_encoder/asn1/sequence.rb
178
+ - lib/itunes_receipt_encoder/in_app.rb
179
+ - lib/itunes_receipt_encoder/payload.rb
180
+ - lib/itunes_receipt_encoder/receipt.rb
181
+ - lib/itunes_receipt_encoder/utils.rb
182
+ - lib/itunes_receipt_encoder/version.rb
183
+ homepage: https://github.com/mbaasy/itunes_receipt_encoder
184
+ licenses:
185
+ - MIT
186
+ metadata: {}
187
+ post_install_message:
188
+ rdoc_options: []
189
+ require_paths:
190
+ - lib
191
+ required_ruby_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: 2.0.0
196
+ required_rubygems_version: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ requirements: []
202
+ rubyforge_project:
203
+ rubygems_version: 2.4.6
204
+ signing_key:
205
+ specification_version: 4
206
+ summary: Encodes receipt data into iTunes encoded receipts
207
+ test_files: []
208
+ has_rdoc: