itunes_receipt_decoder 0.0.2 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 64a4d44ac99c4a2f403abce0757f8d2967fb892f
4
- data.tar.gz: 4fb7ac5d8944a5179aa948b81896656f0a184486
3
+ metadata.gz: 3af07c85acedd565c74e51d29053205b49134fd4
4
+ data.tar.gz: 5da51cb846cacc7a182f4938147835744ce2149d
5
5
  SHA512:
6
- metadata.gz: c0dad4a0219e4e283733abc18e025eeb7c338bec797797a14dc5bc4d1c97af26287b4f81c2e3b80b914f6b699cbc4ed90067edcedc2b38c12f89ec2c7f0f539b
7
- data.tar.gz: 36e8317e6cd14c12828f60a7e886630dabe791c61d188a23af5006ba4ac8020a1792f8834b1e6704d27fc5d29e8bdc72e1307d998515cc7036ae7c75a336a137
6
+ metadata.gz: bc3acb82230669e4633a443ecec9c4c6115879c205f3c790d282360fa7734a31606730d5d0241b29be8a017f68fa9b46efed58d56af001c726cd35ba16b410cd
7
+ data.tar.gz: 665a657a448c447a1c22e03a8a9a1049ca9cffc55db5f2dccaf32e67a130863d60bb7adee2334dbf2e42a850102e914bc05e63dda6a7584dc6198a818fc0d7bf
@@ -0,0 +1,29 @@
1
+ ##
2
+ # ItunesReceiptDecoder
3
+ module ItunesReceiptDecoder
4
+ ##
5
+ # ItunesReceiptDecoder::Decode
6
+ module Decode
7
+ ##
8
+ # ItunesReceiptDecoder::Decode::Base
9
+ class Base
10
+ attr_reader :raw_receipt
11
+
12
+ def initialize(raw_receipt)
13
+ @raw_receipt = raw_receipt
14
+ end
15
+
16
+ def receipt
17
+ decode && @receipt
18
+ end
19
+
20
+ def production?
21
+ environment == 'Production'
22
+ end
23
+
24
+ def sandbox?
25
+ !production?
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ ##
2
+ # ItunesReceiptDecoder
3
+ module ItunesReceiptDecoder
4
+ ##
5
+ # ItunesReceiptDecoder::Decode
6
+ module Decode
7
+ ##
8
+ # ItunesReceiptDecoder::Decode::TransactionReceipt
9
+ class TransactionReceipt < Base
10
+ def decode
11
+ @receipt ||= purchase_info
12
+ self
13
+ end
14
+
15
+ def style
16
+ :transaction
17
+ end
18
+
19
+ def environment
20
+ payload['environment']
21
+ end
22
+
23
+ private
24
+
25
+ def purchase_info
26
+ contents = Base64.strict_decode64(payload['purchase-info'])
27
+ result = parse_plist(contents)
28
+ result.keys.each do |key|
29
+ new_key = key.tr('-', '_').to_sym
30
+ result[new_key] = result.delete(key)
31
+ end
32
+ result
33
+ end
34
+
35
+ def payload
36
+ @payload ||= parse_plist(raw_receipt)
37
+ end
38
+
39
+ def parse_plist(contents)
40
+ plist = CFPropertyList::List.new(data: contents)
41
+ CFPropertyList.native_types(plist.value)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,77 @@
1
+ ##
2
+ # ItunesReceiptDecoder
3
+ module ItunesReceiptDecoder
4
+ ##
5
+ # ItunesReceiptDecoder::Decode
6
+ module Decode
7
+ ##
8
+ # ItunesReceiptDecoder::Decode::UnifiedReceipt
9
+ class UnifiedReceipt < Base
10
+ RECEIPT_FIELDS = {
11
+ 0 => :environment,
12
+ 2 => :bundle_id,
13
+ 3 => :application_version,
14
+ 12 => :creation_date,
15
+ 17 => :in_app,
16
+ 19 => :original_application_version,
17
+ 21 => :expiration_date,
18
+ 1701 => :quantity,
19
+ 1702 => :product_id,
20
+ 1703 => :transaction_id,
21
+ 1705 => :original_transaction_id,
22
+ 1704 => :purchase_date,
23
+ 1706 => :original_purchase_date,
24
+ 1708 => :expires_date,
25
+ 1712 => :cancellation_date,
26
+ 1711 => :web_order_line_item_id
27
+ }
28
+
29
+ def decode
30
+ @receipt ||= parse_app_receipt_fields(payload.value)
31
+ self
32
+ end
33
+
34
+ def style
35
+ :unified
36
+ end
37
+
38
+ def environment
39
+ decode.receipt[:environment]
40
+ end
41
+
42
+ private
43
+
44
+ def parse_app_receipt_fields(fields)
45
+ result = {}
46
+ fields.each do |seq|
47
+ type, _version, value = seq.value.map(&:value)
48
+ next unless (field = RECEIPT_FIELDS[type.to_i])
49
+ build_result(result, field, value)
50
+ end
51
+ result
52
+ end
53
+
54
+ def build_result(result, field, value)
55
+ value = OpenSSL::ASN1.decode(value).value
56
+ case field
57
+ when :in_app
58
+ (result[field] ||= []).push(parse_app_receipt_fields(value))
59
+ else
60
+ result[field] = value.class == OpenSSL::BN ? value.to_i : value.to_s
61
+ end
62
+ end
63
+
64
+ def payload
65
+ verify && OpenSSL::ASN1.decode(pkcs7.data)
66
+ end
67
+
68
+ def verify
69
+ pkcs7.verify(nil, Config.certificate_store, nil, nil)
70
+ end
71
+
72
+ def pkcs7
73
+ @pkcs7 ||= OpenSSL::PKCS7.new(raw_receipt)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,5 +1,5 @@
1
1
  ##
2
2
  # ItunesReceiptDecoder
3
3
  module ItunesReceiptDecoder
4
- VERSION = '0.0.2'
4
+ VERSION = '0.1.0'
5
5
  end
@@ -1,11 +1,21 @@
1
- require 'time'
2
1
  require 'base64'
3
2
  require 'openssl'
3
+ require 'cfpropertylist'
4
4
  require 'itunes_receipt_decoder/version'
5
5
  require 'itunes_receipt_decoder/config'
6
- require 'itunes_receipt_decoder/decode'
6
+ require 'itunes_receipt_decoder/decode/base'
7
+ require 'itunes_receipt_decoder/decode/transaction_receipt'
8
+ require 'itunes_receipt_decoder/decode/unified_receipt'
7
9
 
8
10
  ##
9
11
  # ItunesReceiptDecoder
10
12
  module ItunesReceiptDecoder
13
+ def self.new(receipt_data)
14
+ raw_receipt = Base64.strict_decode64(receipt_data)
15
+ if /^\{*+\}$/ =~ raw_receipt
16
+ Decode::TransactionReceipt.new(raw_receipt)
17
+ else
18
+ Decode::UnifiedReceipt.new(raw_receipt)
19
+ end
20
+ end
11
21
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itunes_receipt_decoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mbaasy.com
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-23 00:00:00.000000000 Z
11
+ date: 2015-10-26 00:00:00.000000000 Z
12
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'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rake
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -104,7 +118,9 @@ extra_rdoc_files: []
104
118
  files:
105
119
  - lib/itunes_receipt_decoder.rb
106
120
  - lib/itunes_receipt_decoder/config.rb
107
- - lib/itunes_receipt_decoder/decode.rb
121
+ - lib/itunes_receipt_decoder/decode/base.rb
122
+ - lib/itunes_receipt_decoder/decode/transaction_receipt.rb
123
+ - lib/itunes_receipt_decoder/decode/unified_receipt.rb
108
124
  - lib/itunes_receipt_decoder/version.rb
109
125
  homepage: https://github.com/mbaasy/itunes_receipt_decoder
110
126
  licenses:
@@ -1,74 +0,0 @@
1
- ##
2
- # ItunesReceiptDecoder
3
- module ItunesReceiptDecoder
4
- ##
5
- # ItunesReceiptDecoder::Decode
6
- class Decode
7
- RECEIPT_FIELDS = {
8
- 0 => :environment,
9
- 2 => :bundle_id,
10
- 3 => :application_version,
11
- 12 => :creation_date,
12
- 17 => :in_app,
13
- 19 => :original_application_version,
14
- 21 => :expiration_date,
15
- 1701 => :quantity,
16
- 1702 => :product_id,
17
- 1703 => :transaction_id,
18
- 1705 => :original_transaction_id,
19
- 1704 => :purchase_date,
20
- 1706 => :original_purchase_date,
21
- 1708 => :expires_date,
22
- 1712 => :cancellation_date,
23
- 1711 => :web_order_line_item_id
24
- }
25
-
26
- attr_accessor :receipt_data
27
- attr_accessor :receipt
28
-
29
- def initialize(receipt_data)
30
- @receipt_data = Base64.strict_decode64(receipt_data)
31
- @receipt = {}
32
- end
33
-
34
- def decode
35
- self.receipt = parse_app_receipt_fields(payload.value)
36
- end
37
-
38
- private
39
-
40
- def parse_app_receipt_fields(fields)
41
- result = {}
42
- fields.each do |seq|
43
- type, _version, value = seq.value.map(&:value)
44
- next unless (field = RECEIPT_FIELDS[type.to_i])
45
- build_result(result, field, value)
46
- end
47
- result
48
- end
49
-
50
- def build_result(result, field, value)
51
- value = OpenSSL::ASN1.decode(value).value
52
- case field
53
- when :in_app
54
- (result[field] ||= []).push(parse_app_receipt_fields(value))
55
- when :creation_date, :expiration_date, :purchase_date,
56
- :original_purchase_date, :expires_date, :cancellation_date
57
- result[field] = value.empty? ? nil : Time.parse(value).utc
58
- else
59
- result[field] = value.class == OpenSSL::BN ? value.to_i : value.to_s
60
- end
61
- end
62
-
63
- def payload
64
- @payload ||= OpenSSL::ASN1.decode(pkcs7.data)
65
- end
66
-
67
- def pkcs7
68
- return @pkcs7 if @pkcs7
69
- @pkcs7 = OpenSSL::PKCS7.new(receipt_data)
70
- @pkcs7.verify(nil, Config.certificate_store, nil, nil)
71
- @pkcs7
72
- end
73
- end
74
- end