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 +4 -4
- data/lib/itunes_receipt_decoder/decode/base.rb +29 -0
- data/lib/itunes_receipt_decoder/decode/transaction_receipt.rb +45 -0
- data/lib/itunes_receipt_decoder/decode/unified_receipt.rb +77 -0
- data/lib/itunes_receipt_decoder/version.rb +1 -1
- data/lib/itunes_receipt_decoder.rb +12 -2
- metadata +19 -3
- data/lib/itunes_receipt_decoder/decode.rb +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3af07c85acedd565c74e51d29053205b49134fd4
|
4
|
+
data.tar.gz: 5da51cb846cacc7a182f4938147835744ce2149d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,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
|
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-
|
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
|