itunes_receipt_decoder 0.1.0 → 0.1.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 +4 -4
- data/lib/itunes_receipt_decoder.rb +11 -3
- data/lib/itunes_receipt_decoder/config.rb +6 -0
- data/lib/itunes_receipt_decoder/decode/base.rb +17 -2
- data/lib/itunes_receipt_decoder/decode/transaction_receipt.rb +6 -0
- data/lib/itunes_receipt_decoder/decode/unified_receipt.rb +30 -0
- data/lib/itunes_receipt_decoder/version.rb +3 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de043b4c77b3fbaac346b799f365f057b321c3fb
|
4
|
+
data.tar.gz: 1d15e3c79f6d797db3ff2fdf3b1c95d1599b5e67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5acfe178ab3c36e0697ed3cf466551c94eb726413ccc2806cd7b40ec3177a9b394895eb0f4850051f3735c7a419d83338a082f16f3ca4aaeedc778f10bb87456
|
7
|
+
data.tar.gz: 8a534a10ce32f203b7c450b02c7d60747880632abebc2765d064bc0fe85014c1a243dde361b9e74c497fc4aff2ec3718e472286050895c35798b54fcef668eca
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'time'
|
1
2
|
require 'base64'
|
2
3
|
require 'openssl'
|
3
4
|
require 'cfpropertylist'
|
@@ -10,12 +11,19 @@ require 'itunes_receipt_decoder/decode/unified_receipt'
|
|
10
11
|
##
|
11
12
|
# ItunesReceiptDecoder
|
12
13
|
module ItunesReceiptDecoder
|
13
|
-
|
14
|
+
##
|
15
|
+
# Initializes either ItunesReceiptDecoder::Decode::Transaction or
|
16
|
+
# ItunesReceiptDecoder::Decode::Unified with the base64 encoded receipt
|
17
|
+
# ==== Arguments
|
18
|
+
#
|
19
|
+
# * +receipt_data+ - the base64 encoded receipt
|
20
|
+
# * +options+ - optional arguments
|
21
|
+
def self.new(receipt_data, options = {})
|
14
22
|
raw_receipt = Base64.strict_decode64(receipt_data)
|
15
23
|
if /^\{*+\}$/ =~ raw_receipt
|
16
|
-
Decode::TransactionReceipt.new(raw_receipt)
|
24
|
+
Decode::TransactionReceipt.new(raw_receipt, options)
|
17
25
|
else
|
18
|
-
Decode::UnifiedReceipt.new(raw_receipt)
|
26
|
+
Decode::UnifiedReceipt.new(raw_receipt, options)
|
19
27
|
end
|
20
28
|
end
|
21
29
|
end
|
@@ -5,15 +5,21 @@ module ItunesReceiptDecoder
|
|
5
5
|
# ItunesReceiptDecoder::Config
|
6
6
|
class Config
|
7
7
|
class << self
|
8
|
+
##
|
9
|
+
# Set this to the path of the AppleIncRootCertificate.cer file
|
8
10
|
attr_accessor :certificate_path
|
9
11
|
end
|
10
12
|
|
13
|
+
##
|
14
|
+
# Returns the OpenSSL X509 Store for the certificate
|
11
15
|
def self.certificate_store
|
12
16
|
return @certificate_store if @certificate_store
|
13
17
|
@certificate_store = OpenSSL::X509::Store.new
|
14
18
|
@certificate_store.add_cert(certificate)
|
15
19
|
end
|
16
20
|
|
21
|
+
##
|
22
|
+
# returns the OpenSSL X509 Certificate
|
17
23
|
def self.certificate
|
18
24
|
@certificate ||= OpenSSL::X509::Certificate.new(
|
19
25
|
File.read(certificate_path)
|
@@ -7,20 +7,35 @@ module ItunesReceiptDecoder
|
|
7
7
|
##
|
8
8
|
# ItunesReceiptDecoder::Decode::Base
|
9
9
|
class Base
|
10
|
-
|
10
|
+
##
|
11
|
+
# The raw receipt, i.e. not base64 encoded
|
12
|
+
attr_reader :raw_receipt, :options
|
11
13
|
|
12
|
-
|
14
|
+
##
|
15
|
+
# Initializes with a raw (base64 decoded receipt)
|
16
|
+
#
|
17
|
+
# ==== Arguments
|
18
|
+
#
|
19
|
+
# * +raw_receipt+ - the raw receipt, i.e. not base64 encoded
|
20
|
+
def initialize(raw_receipt, options = {})
|
13
21
|
@raw_receipt = raw_receipt
|
22
|
+
@options = options
|
14
23
|
end
|
15
24
|
|
25
|
+
##
|
26
|
+
# Returns the receipt receipt properties
|
16
27
|
def receipt
|
17
28
|
decode && @receipt
|
18
29
|
end
|
19
30
|
|
31
|
+
##
|
32
|
+
# Returns true if the receipt is created in the Production environment
|
20
33
|
def production?
|
21
34
|
environment == 'Production'
|
22
35
|
end
|
23
36
|
|
37
|
+
##
|
38
|
+
# Returns true if the receipt is +not+ created in Production
|
24
39
|
def sandbox?
|
25
40
|
!production?
|
26
41
|
end
|
@@ -7,15 +7,21 @@ module ItunesReceiptDecoder
|
|
7
7
|
##
|
8
8
|
# ItunesReceiptDecoder::Decode::TransactionReceipt
|
9
9
|
class TransactionReceipt < Base
|
10
|
+
##
|
11
|
+
# Decodes the receipt
|
10
12
|
def decode
|
11
13
|
@receipt ||= purchase_info
|
12
14
|
self
|
13
15
|
end
|
14
16
|
|
17
|
+
##
|
18
|
+
# Just returns :transaction
|
15
19
|
def style
|
16
20
|
:transaction
|
17
21
|
end
|
18
22
|
|
23
|
+
##
|
24
|
+
# Gets the environment from the payload
|
19
25
|
def environment
|
20
26
|
payload['environment']
|
21
27
|
end
|
@@ -7,6 +7,10 @@ module ItunesReceiptDecoder
|
|
7
7
|
##
|
8
8
|
# ItunesReceiptDecoder::Decode::UnifiedReceipt
|
9
9
|
class UnifiedReceipt < Base
|
10
|
+
##
|
11
|
+
# ASN.1 Field types
|
12
|
+
#
|
13
|
+
# See https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1
|
10
14
|
RECEIPT_FIELDS = {
|
11
15
|
0 => :environment,
|
12
16
|
2 => :bundle_id,
|
@@ -26,15 +30,25 @@ module ItunesReceiptDecoder
|
|
26
30
|
1711 => :web_order_line_item_id
|
27
31
|
}
|
28
32
|
|
33
|
+
TIMESTAMP_FIELDS = %i(creation_date expiration_date purchase_date
|
34
|
+
original_purchase_date expires_date
|
35
|
+
cancellation_date)
|
36
|
+
|
37
|
+
##
|
38
|
+
# Decodes the receipt
|
29
39
|
def decode
|
30
40
|
@receipt ||= parse_app_receipt_fields(payload.value)
|
31
41
|
self
|
32
42
|
end
|
33
43
|
|
44
|
+
##
|
45
|
+
# Just returns :unified
|
34
46
|
def style
|
35
47
|
:unified
|
36
48
|
end
|
37
49
|
|
50
|
+
##
|
51
|
+
# Gets the environment from the receipt
|
38
52
|
def environment
|
39
53
|
decode.receipt[:environment]
|
40
54
|
end
|
@@ -56,11 +70,27 @@ module ItunesReceiptDecoder
|
|
56
70
|
case field
|
57
71
|
when :in_app
|
58
72
|
(result[field] ||= []).push(parse_app_receipt_fields(value))
|
73
|
+
when *timestamp_fields
|
74
|
+
result.merge! expand_timestamp(field, value) unless value.empty?
|
59
75
|
else
|
60
76
|
result[field] = value.class == OpenSSL::BN ? value.to_i : value.to_s
|
61
77
|
end
|
62
78
|
end
|
63
79
|
|
80
|
+
def timestamp_fields
|
81
|
+
options[:expand_timestamps] && TIMESTAMP_FIELDS
|
82
|
+
end
|
83
|
+
|
84
|
+
def expand_timestamp(field, value)
|
85
|
+
time = Time.parse(value).utc
|
86
|
+
{
|
87
|
+
field => time.strftime('%F %T') + ' Etc/GMT',
|
88
|
+
"#{field}_ms".to_sym => (time.to_i * 1000).to_s,
|
89
|
+
"#{field}_pst".to_sym => (time + Time.zone_offset('PST'))
|
90
|
+
.strftime('%F %T') + ' America/Los_Angeles'
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
64
94
|
def payload
|
65
95
|
verify && OpenSSL::ASN1.decode(pkcs7.data)
|
66
96
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: itunes_receipt_decoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
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-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: CFPropertyList
|
@@ -134,7 +134,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
134
|
requirements:
|
135
135
|
- - ">="
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version:
|
137
|
+
version: 2.0.0
|
138
138
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
139
|
requirements:
|
140
140
|
- - ">="
|