rm_vendor 0.2 → 0.3
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 +8 -8
- data/README.md +14 -16
- data/lib/Vendor.rb +1 -1
- data/lib/project/buy.rb +10 -9
- data/lib/project/info.rb +14 -8
- data/lib/project/product.rb +7 -19
- data/lib/project/products.rb +43 -0
- data/lib/project/receipt.rb +6 -22
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YjUyYzdhMWQ5OTY1OTdmOGEyYmJlODQzYjk5ZmRhNDlhN2I4OWIzOQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YjFlNDA4NTkyMjA3ZDAxYThmZmZiNTBhNDlhOTk2ODZlOGJiOTkxZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjlkYWJiMDNmNjIwODVhYWIxM2ZlNjdhYWVkZWY4MjczZmJkNTUzOTZhMWMz
|
10
|
+
NGNkYzBhMWU5ZmRmYzVlZDI3MTQxODE2YjVhODY1NTNjNWExYThhZThmOThj
|
11
|
+
NTdkOTczY2U4ZWMxZTNmODhkMWYwNzY3OGNjYTMxMWZiMTg4NDQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NWJiY2EwZGMwNjJhYTI5NGM2MjIzZDIwNDE1NzY3ZjExNjZhNGEyNWRjOGZj
|
14
|
+
ZjQ5NjBmYTVkN2ZiMWJhNmE5NjM3ZTM2ZTczYmMxMTk0MjlkN2I5Y2I3ZDI5
|
15
|
+
Yjk1NzA3OGQ2NDkyOGE1Nzc3OTEzMTk1Mjc5NjkzYzVjNTI3MDY=
|
data/README.md
CHANGED
@@ -14,19 +14,18 @@ And then execute:
|
|
14
14
|
|
15
15
|
#### Initialize.
|
16
16
|
|
17
|
-
Initialize your
|
17
|
+
Initialize your products with your In App Purchase ID. Vendor will check if the product exists and return it's attributes:
|
18
18
|
|
19
19
|
```Ruby
|
20
|
-
@
|
21
|
-
|
22
|
-
p "Product response: #{product.response}"
|
20
|
+
@products = Vendor::Products.new([{:name => "first_item", :id => "com.your.first_item.id"}, {:name => "second_item", :id => "com.your.second_item.id"}]) do |products|
|
21
|
+
products.map{ |product| NSLog "Product exists?: #{product.success}" }
|
23
22
|
end
|
24
23
|
```
|
25
24
|
|
26
25
|
You don't need to pass along a block though. If you're sure your product exists, then you can just do this:
|
27
26
|
|
28
27
|
```Ruby
|
29
|
-
@
|
28
|
+
@products = Vendor::Products.new([{:name => "first_item", :id => "com.your.first_item.id"}, {:name => "second_item", :id => "com.your.second_item.id"}])
|
30
29
|
```
|
31
30
|
|
32
31
|
#### Get product info.
|
@@ -34,10 +33,10 @@ You don't need to pass along a block though. If you're sure your product exists,
|
|
34
33
|
After you've initialized your product, you get its information:
|
35
34
|
|
36
35
|
```Ruby
|
37
|
-
@product.price
|
38
|
-
@product.title
|
39
|
-
@product.description
|
40
|
-
@product.bought?
|
36
|
+
@product[:first_item].price
|
37
|
+
@product[:first_item].title
|
38
|
+
@product[:first_item].description
|
39
|
+
@product[:first_item].bought?
|
41
40
|
```
|
42
41
|
|
43
42
|
#### Purchase product.
|
@@ -45,7 +44,7 @@ After you've initialized your product, you get its information:
|
|
45
44
|
To purchase a product, simply do:
|
46
45
|
|
47
46
|
```Ruby
|
48
|
-
@product.purchase do |product|
|
47
|
+
@product[:first_item].purchase do |product|
|
49
48
|
p "Purchase successful: #{product.success}"
|
50
49
|
p "Purchase transaction: #{product.transaction}"
|
51
50
|
end
|
@@ -56,16 +55,15 @@ end
|
|
56
55
|
Vendor also works with subscriptions. To initialize a subscription:
|
57
56
|
|
58
57
|
```Ruby
|
59
|
-
@
|
60
|
-
|
61
|
-
p "Subscription response: #{subscription.response}"
|
58
|
+
@subscription_products = Vendor::Products.new([{:name => "subscription", :id => "com.your.subscription.id", :secret => "abcdefg12345", :subscription => true}]) do |subscriptions|
|
59
|
+
subscriptions.map{ |subscription| NSLog "Subscription exists?: #{subscription.success}" }
|
62
60
|
end
|
63
61
|
```
|
64
62
|
|
65
63
|
To purchase a subscription:
|
66
64
|
|
67
65
|
```Ruby
|
68
|
-
@subscription.purchase do |subscription|
|
66
|
+
@subscription_products[:subscription].purchase do |subscription|
|
69
67
|
p "Subscription successful: #{subscription.success}"
|
70
68
|
p "Subscription transaction: #{subscription.transaction}"
|
71
69
|
end
|
@@ -74,8 +72,8 @@ end
|
|
74
72
|
To see wether product is registered as a subscription and if user is currently subscribed:
|
75
73
|
|
76
74
|
```Ruby
|
77
|
-
@subscription.subscribed?
|
78
|
-
@subscription.subscription?
|
75
|
+
@subscription_products[:subscription].subscribed?
|
76
|
+
@subscription_products[:subscription].subscription?
|
79
77
|
```
|
80
78
|
|
81
79
|
## Example App.
|
data/lib/Vendor.rb
CHANGED
data/lib/project/buy.rb
CHANGED
@@ -2,8 +2,7 @@ module Vendor
|
|
2
2
|
class Buy
|
3
3
|
attr_accessor :params, :block, :request_operation_queue
|
4
4
|
|
5
|
-
def initialize
|
6
|
-
@params = params
|
5
|
+
def initialize
|
7
6
|
SKPaymentQueue.defaultQueue.addTransactionObserver(self)
|
8
7
|
end
|
9
8
|
|
@@ -14,12 +13,14 @@ module Vendor
|
|
14
13
|
|
15
14
|
|
16
15
|
# PUBLIC METHODS
|
17
|
-
def purchase(&block)
|
16
|
+
def purchase(params, &block)
|
17
|
+
@params = params
|
18
18
|
@block = block
|
19
19
|
SKPaymentQueue.defaultQueue.addPayment(SKPayment.paymentWithProductIdentifier(@params.id))
|
20
20
|
end
|
21
21
|
|
22
|
-
def restore(&block)
|
22
|
+
def restore(params, &block)
|
23
|
+
@params = params
|
23
24
|
@block = block
|
24
25
|
SKPaymentQueue.defaultQueue.restoreCompletedTransactions
|
25
26
|
end
|
@@ -29,13 +30,13 @@ module Vendor
|
|
29
30
|
# DELEGATE METHODS
|
30
31
|
def finishTransaction(transaction, success:success)
|
31
32
|
SKPaymentQueue.defaultQueue.finishTransaction(transaction)
|
32
|
-
|
33
|
-
|
33
|
+
return if @params.nil?
|
34
|
+
password = @params.secret=="no_secret" ? nil : @params.secret
|
35
|
+
|
34
36
|
if success
|
37
|
+
# Verify transaction receipt
|
35
38
|
Vendor::Receipt.new(transaction.transactionReceipt, @params) do |block|
|
36
|
-
|
37
|
-
valid_receipt = block.success && result_object.status.to_i == 0
|
38
|
-
|
39
|
+
valid_receipt = block[:success] && block[:object][:status]==0
|
39
40
|
@block.call({success: valid_receipt, transaction: transaction}.to_object) unless @block.blank?
|
40
41
|
end
|
41
42
|
else
|
data/lib/project/info.rb
CHANGED
@@ -12,7 +12,10 @@ module Vendor
|
|
12
12
|
productsRequest.start
|
13
13
|
|
14
14
|
# Update receipt if bought and subscription
|
15
|
-
|
15
|
+
receipt = NSUserDefaults["#{@params.id}.receipt"]
|
16
|
+
decoder = CocoaSecurityDecoder.new
|
17
|
+
latest_receipt_data = decoder.base64(receipt[:latest_receipt])
|
18
|
+
Vendor::Receipt.new(latest_receipt_data, @params) if bought? && subscription?
|
16
19
|
end
|
17
20
|
|
18
21
|
|
@@ -40,22 +43,26 @@ module Vendor
|
|
40
43
|
end
|
41
44
|
|
42
45
|
def subscribed?
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
# Return false if product is not a subscription or not bought
|
47
|
+
return false if !subscription? || !bought?
|
48
|
+
receipt = NSUserDefaults["#{@params.id}.receipt"]
|
49
|
+
return false if receipt[:status].to_i!=0
|
46
50
|
|
51
|
+
# Get the latest receipt
|
52
|
+
receipt = NSUserDefaults["#{@params.id}.receipt"]
|
47
53
|
decoder = CocoaSecurityDecoder.new
|
48
|
-
latest_receipt_data = decoder.base64(
|
54
|
+
latest_receipt_data = decoder.base64(receipt[:latest_receipt])
|
49
55
|
latest_receipt_plist = NSPropertyListSerialization.propertyListWithData(latest_receipt_data, options:NSPropertyListImmutable, format:nil, error:nil)
|
50
56
|
|
57
|
+
# Get the time for the latest receipt
|
51
58
|
purchase_info_data = decoder.base64(latest_receipt_plist.objectForKey("purchase-info"))
|
52
59
|
purchase_info_plist = NSPropertyListSerialization.propertyListWithData(purchase_info_data, options:NSPropertyListImmutable, format:nil, error:nil)
|
53
|
-
purchase_info_plist = NSPropertyListSerialization.propertyListWithData(purchase_info_data, options:NSPropertyListImmutable, format:nil, error:nil)
|
54
60
|
|
61
|
+
# Manipulate the time for the latest receipt
|
55
62
|
expires_date = purchase_info_plist.objectForKey("expires-date")
|
56
|
-
# ap "expires_date: #{expires_date}"
|
57
63
|
expires_calc = expires_date.to_i/1000
|
58
64
|
|
65
|
+
# Check if the latest receipt is too old
|
59
66
|
return expires_calc > NSDate.date.timeIntervalSince1970
|
60
67
|
end
|
61
68
|
|
@@ -79,6 +86,5 @@ module Vendor
|
|
79
86
|
def request(request, didFailWithError:error)
|
80
87
|
@block.call({success: false, error: error}.to_object)
|
81
88
|
end
|
82
|
-
|
83
89
|
end
|
84
90
|
end
|
data/lib/project/product.rb
CHANGED
@@ -2,20 +2,11 @@ module Vendor
|
|
2
2
|
class Product
|
3
3
|
attr_reader :params, :block, :exists, :info, :buy
|
4
4
|
|
5
|
-
def initialize(options
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
:subscription => false,
|
11
|
-
:price => "0.99",
|
12
|
-
:title => "No Title",
|
13
|
-
:desc => "No Description."
|
14
|
-
}
|
15
|
-
|
16
|
-
# Set global params and block
|
17
|
-
options = default_options.merge(options)
|
18
|
-
@params = options.to_object
|
5
|
+
def initialize(options, buy_class, &block)
|
6
|
+
|
7
|
+
# Set params and block
|
8
|
+
@buy = buy_class
|
9
|
+
@params = options
|
19
10
|
@block = block
|
20
11
|
|
21
12
|
# Raise argument error if id is not included
|
@@ -27,20 +18,17 @@ module Vendor
|
|
27
18
|
@exists = block.success
|
28
19
|
@block.call(block) unless @block.nil?
|
29
20
|
end
|
30
|
-
|
31
|
-
# Initialize purchase
|
32
|
-
@buy = Vendor::Buy.new(@params)
|
33
21
|
end
|
34
22
|
|
35
23
|
|
36
24
|
|
37
25
|
# PURCHASE METHODS
|
38
26
|
def purchase(&block)
|
39
|
-
@buy.purchase { |result| block.call(result)}
|
27
|
+
@buy.purchase(@params) { |result| block.call(result)}
|
40
28
|
end
|
41
29
|
|
42
30
|
def restore(&block)
|
43
|
-
@buy.restore { |result| block.call(result)}
|
31
|
+
@buy.restore(@params) { |result| block.call(result)}
|
44
32
|
end
|
45
33
|
|
46
34
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Vendor
|
2
|
+
class Products
|
3
|
+
attr_reader :block, :products
|
4
|
+
|
5
|
+
def [](key)
|
6
|
+
return @products.select{ |p| p.params[:name]==key.to_s }.first
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(products=[], &block)
|
10
|
+
# Set up products array
|
11
|
+
@products = []
|
12
|
+
|
13
|
+
# Set up block
|
14
|
+
@block = block
|
15
|
+
|
16
|
+
# Set up blocks for giving a callback
|
17
|
+
@blocks = []
|
18
|
+
|
19
|
+
# Initialize buy block
|
20
|
+
@buy = Vendor::Buy.new
|
21
|
+
|
22
|
+
# Set up info for products
|
23
|
+
products.each do |product|
|
24
|
+
# Set default options
|
25
|
+
default_options = {
|
26
|
+
:id => "no_id",
|
27
|
+
:secret => "no_secret",
|
28
|
+
:subscription => false,
|
29
|
+
:price => "0.99",
|
30
|
+
:title => "No Title",
|
31
|
+
:desc => "No Description."
|
32
|
+
}
|
33
|
+
options = default_options.merge(product)
|
34
|
+
|
35
|
+
# Update product and set exists variable
|
36
|
+
@products << Vendor::Product.new(options.to_object, @buy) do |block|
|
37
|
+
@blocks << block
|
38
|
+
@block.call(@blocks) unless @block.nil? || @blocks.count!=@products.count
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/project/receipt.rb
CHANGED
@@ -1,41 +1,25 @@
|
|
1
1
|
module Vendor
|
2
2
|
class Receipt
|
3
3
|
|
4
|
-
attr_reader :receipt_data, :params, :
|
4
|
+
attr_reader :receipt_data, :params, :block
|
5
5
|
|
6
6
|
def initialize(receipt_data, params, &block)
|
7
7
|
@receipt_data = receipt_data
|
8
8
|
@params = params
|
9
9
|
@block = block
|
10
|
-
@request_operation_queue = NSOperationQueue.alloc.init
|
11
10
|
|
12
11
|
check_receipt(receipt_data)
|
13
12
|
end
|
14
13
|
|
15
14
|
def check_receipt(receipt_data)
|
16
|
-
|
17
|
-
json_data = {"receipt-data" => encoder.base64(receipt_data)}
|
18
|
-
json_data[:password] = @params.secret if @params.secret != "no_secret"
|
19
|
-
server = App.development? ? "sandbox" : "buy"
|
20
|
-
base_url = NSURL.URLWithString("https://#{server}.itunes.apple.com")
|
15
|
+
password = @params.secret != "no_secret" ? @params.secret : nil
|
21
16
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
client.setParameterEncoding(AFJSONParameterEncoding)
|
27
|
-
AFJSONRequestOperation.addAcceptableContentTypes(NSSet.setWithObject("text/plain"))
|
28
|
-
|
29
|
-
request = client.requestWithMethod("POST", path:"verifyReceipt", parameters:json_data)
|
30
|
-
request_operation = client.HTTPRequestOperationWithRequest(request, success: lambda { |operation, response_object|
|
31
|
-
NSUserDefaults["#{@params.id}.receipt_data"] = receipt_data
|
32
|
-
NSUserDefaults["#{@params.id}.receipt"] = response_object
|
33
|
-
@block.call({success: true, object: response_object}.to_object) unless @block.blank?
|
34
|
-
}, failure: lambda {|operation, error|
|
17
|
+
CargoBay.sharedManager.verifyTransactionReceipt(receipt_data, password:password, success:lambda { |receipt|
|
18
|
+
NSUserDefaults["#{@params.id}.receipt"] = receipt
|
19
|
+
@block.call({success: true, object: receipt}.to_object) unless @block.blank?
|
20
|
+
}, failure: lambda { |error|
|
35
21
|
@block.call({success: false, error: error}.to_object) unless @block.blank?
|
36
22
|
})
|
37
|
-
|
38
|
-
@request_operation_queue.addOperation(request_operation)
|
39
23
|
end
|
40
24
|
|
41
25
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rm_vendor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Holger Sindbaek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -78,6 +78,7 @@ files:
|
|
78
78
|
- lib/project/buy.rb
|
79
79
|
- lib/project/info.rb
|
80
80
|
- lib/project/product.rb
|
81
|
+
- lib/project/products.rb
|
81
82
|
- lib/project/receipt.rb
|
82
83
|
- lib/Vendor.rb
|
83
84
|
homepage: https://github.com/holgersindbaek/Vendor
|