helu 0.5 → 0.6

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: 63367011c2bac9119e14a1eec6a5b2216406181b
4
- data.tar.gz: 55cdd3775667b53eb18ab3549bec8d10a03f64c1
3
+ metadata.gz: 53fb21dab5afe5f99d560e4326b61e8222040089
4
+ data.tar.gz: 743acc254c9f25923817058f0028d1ddbf35fc2c
5
5
  SHA512:
6
- metadata.gz: 309593bf1d36c34ca54c1754e7d1eedba3039871f5f068b2aff12ddac6201cb57f6d4b9c17b2c9d2db4d001f411d95436d4ebb6657f2f1c966410ec7a6edf992
7
- data.tar.gz: 58b695a813139495f55fd1de3222d17bf4dfca018e8f9a8915891251a099d8dac78c95b61506d7041f6145463512da33ee08e2ccf81555988bfa5b77e8a990b3
6
+ metadata.gz: 45cae952adc479e019b24bce56d7c64e7a5ab68aa5d4545b3736e0220099b8848ca167e16e3df84d72f67f0c53ed8a1880d010497dd5778630511e374e4bf7cf
7
+ data.tar.gz: 41dff4c9c13efa64328622dfa0543996fb0eefbd8c5ec0078bed9c5cfbb655b61685986efab632adbb4b2b5bacc5ad46a8b10e64d74c7b12b39aba142f7437b5
data/README.md CHANGED
@@ -1,7 +1,10 @@
1
- # helu
1
+ # Helu
2
2
 
3
3
  [![Build Status](https://travis-ci.org/ivanacostarubio/helu.png)](https://travis-ci.org/ivanacostarubio/helu)
4
4
 
5
+ In-App purchases for RubyMotion.
6
+
7
+ ![Money](https://raw.github.com/ivanacostarubio/helu/readme/resources/money.jpg)
5
8
 
6
9
  ## Installation
7
10
 
@@ -16,6 +19,7 @@ And then execute:
16
19
  Or install it yourself as:
17
20
 
18
21
  $ gem install helu
22
+
19
23
 
20
24
  ## USAGE
21
25
 
@@ -47,17 +51,62 @@ The transaction object on the lambda is the one we get from Apple; Therefore, it
47
51
  @helu.restore
48
52
 
49
53
 
50
- ### Make sure that if your code ever throws out the Helu object, it better also close the store before doing so.
54
+ #### Make sure that if your code ever throws out the Helu object, it better also close the store before doing so.
51
55
 
52
56
  @helu.close
53
57
 
58
+ ### Supported types of In App Purchases
59
+
60
+ + Consumables and Non-Consumables are supported.
61
+ + Auto-Renewable subscriptions and Non-Renewing Subscriptions are not supported yet. However, we would love some help making it happen.
62
+
63
+ ### Requesting product information:
64
+
65
+ Asynchronous, raw:
66
+
67
+ inapps = %w[first second third]
68
+ @x = Helu::ProductInfoFetcher.new(inapps) do |pi|
69
+ p pi
70
+ end
71
+
72
+ Asynchronous, wrapped in method call:
73
+
74
+ Helu::ProductInfoFetcher.fetch(inapps) do |pi|
75
+ p pi
76
+ end
77
+
78
+ Synchronous:
79
+
80
+ pi = Helu::ProductInfoFetcher.fetch(inapps)
81
+ p pi
82
+
83
+
84
+ All three calls return hash of the following form:
85
+
86
+ {
87
+ "inapp_id": {
88
+ id: "inapp_id",
89
+ title: "inapp_localized_title",
90
+ description: "inapp_localized_description",
91
+ price: "0.89", # float
92
+ currency: "EUR",
93
+ price_str: "\u20AC0.89",
94
+ }, # ....
95
+ }
96
+
54
97
 
55
98
  ## Example App:
56
99
 
57
- [You can find an example app here](https://github.com/ivanacostarubio/helu-example). Remember that for this to work properly, you must add your app identifier to the Rakefile.
58
-
59
-
60
- ## Supported types of In App Purchases
100
+ [You can find an example app here](https://github.com/ivanacostarubio/helu-example).
101
+ Remember that for this to work properly, you must add your app identifier to the Rakefile.
102
+
61
103
 
62
- + Consumables and Non-Consumables are supported.
63
- + Auto-Renewable subscriptions and Non-Renewing Subscriptions are not supported yet. However, we would love some help making it happen.
104
+ ## License
105
+
106
+ Helu is relase under the [MIT license](http://opensource.org/licenses/MIT).
107
+
108
+ ## Credits
109
+
110
+ Ivan Acosta-Rubio | Initial work
111
+ Michal J. | Product Info Fetcher
112
+ Simon Traels Ravn | Removing Observer and Bug fixes.
@@ -5,4 +5,5 @@ end
5
5
  lib_dir_path = File.dirname(File.expand_path(__FILE__))
6
6
  Motion::Project::App.setup do |app|
7
7
  app.files.unshift(Dir.glob(File.join(lib_dir_path, "project/**/*.rb")))
8
+ app.frameworks << "StoreKit"
8
9
  end
@@ -0,0 +1,35 @@
1
+ class FakeHelu
2
+ attr_reader :product_id
3
+ attr_accessor :storage, :winning, :restore, :fail
4
+
5
+ def initialize(product_id)
6
+ @produc_id = product_id
7
+ end
8
+
9
+ def bought?
10
+ #TODO. Be able to switch this
11
+ false
12
+ end
13
+
14
+ def close
15
+ # just implementing Helu's interface
16
+ end
17
+
18
+ def buy
19
+ winning.call(fake_transaction)
20
+ end
21
+
22
+ def fake_fail
23
+ # TODO: We need to implement a way to fake a fail
24
+ end
25
+
26
+ def restore
27
+ winning.call(fake_transaction)
28
+ end
29
+
30
+ private
31
+
32
+ def fake_transaction
33
+ ""
34
+ end
35
+ end
@@ -3,6 +3,13 @@ class Helu
3
3
  attr_reader :product_id
4
4
  attr_accessor :storage, :winning, :restore, :fail
5
5
 
6
+ class <<self
7
+ # see product_info_fetcher.rb for info
8
+ def fetch_product_info(*products, &b)
9
+ ProductInfoFetcher.fetch(*products, &b)
10
+ end
11
+ end
12
+
6
13
  def initialize(product_id)
7
14
  @product_id = product_id
8
15
  SKPaymentQueue.defaultQueue.addTransactionObserver(self)
@@ -26,11 +33,8 @@ class Helu
26
33
  @storage.all.include?(product_id)
27
34
  end
28
35
 
29
- # private
30
-
31
36
  def finishTransaction(transaction, wasSuccessful:wasSuccessful)
32
37
  SKPaymentQueue.defaultQueue.finishTransaction(transaction)
33
- produt_id = transaction.payment.productIdentifier
34
38
  if wasSuccessful
35
39
  @winning.call(transaction)
36
40
  storage.add(product_id)
@@ -48,11 +52,9 @@ class Helu
48
52
  end
49
53
 
50
54
  def failedTransaction(transaction)
51
- produt_id = transaction.payment.productIdentifier
52
-
53
- if (transaction.error.code != SKErrorPaymentCancelled)
55
+ if transaction.error && (transaction.error.code != SKErrorPaymentCancelled)
54
56
  finishTransaction(transaction, wasSuccessful:false)
55
- elsif transaction.error.code == SKErrorPaymentCancelled
57
+ elsif transaction.error && (transaction.error.code == SKErrorPaymentCancelled)
56
58
  @fail.call(transaction)
57
59
  else
58
60
  SKPaymentQueue.defaultQueue.finishTransaction(transaction)
@@ -119,4 +121,4 @@ class Helu
119
121
 
120
122
  end
121
123
 
122
- end
124
+ end
@@ -0,0 +1,115 @@
1
+ =begin
2
+ # Sample use:
3
+ ## Asynchronous, raw:
4
+ inapps = %w[first second third]
5
+ @x = Helu::ProductInfoFetcher.new(inapps) do |pi|
6
+ p pi
7
+ end
8
+
9
+ ## Asynchronous, wrapped in method call:
10
+ Helu::ProductInfoFetcher.fetch(inapps) do |pi|
11
+ p pi
12
+ end
13
+
14
+ ## Synchronous:
15
+ pi = Helu::ProductInfoFetcher.fetch(inapps)
16
+ p pi
17
+
18
+
19
+ # All three calls return hash of the following form:
20
+ # {
21
+ # "inapp_id": {
22
+ # id: "inapp_id",
23
+ # title: "inapp_localized_title",
24
+ # description: "inapp_localized_description",
25
+ # price: "0.89", # float
26
+ # currency: "EUR",
27
+ # price_str: "\u20AC0.89",
28
+ # },
29
+ # # ...
30
+ # }
31
+ =end
32
+ class Helu
33
+ class ProductInfoFetcher
34
+ @@mutex = Mutex.new
35
+ @@cache = {}
36
+ def initialize(*products, &b)
37
+ raise LocalJumpError, "block expected" if b.nil?
38
+ @callback = b
39
+ @products = products.flatten
40
+
41
+ # all cached? skip the call...
42
+ if (@@cache.keys & @products).sort == @products.sort
43
+ h = @products.inject({}) { |m, prod| m[prod] = @@cache[prod]; m }
44
+ @callback.call(h)
45
+ else
46
+ @sr = SKProductsRequest.alloc.initWithProductIdentifiers(@products)
47
+ @sr.delegate = self
48
+ @sr.start
49
+ end
50
+
51
+ self
52
+ end
53
+
54
+ def productsRequest(req, didReceiveResponse: resp)
55
+ if resp.nil?
56
+ @callback.call(nil)
57
+ else
58
+ h = resp.products.inject({}) { |m, prod|
59
+ m.merge(sk_to_hash(prod))
60
+ }
61
+ @@mutex.synchronize { @@cache.merge!(h) }
62
+ @callback.call(h)
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def sk_to_hash(sk)
69
+ nf = NSNumberFormatter.alloc.init
70
+ nf.setFormatterBehavior(NSNumberFormatterBehavior10_4)
71
+ nf.setNumberStyle(NSNumberFormatterCurrencyStyle)
72
+ nf.setLocale(sk.priceLocale)
73
+ price_str = nf.stringFromNumber(sk.price)
74
+
75
+ {
76
+ sk.productIdentifier => {
77
+ id: sk.productIdentifier,
78
+ title: sk.localizedTitle,
79
+ description: sk.localizedDescription,
80
+ price: sk.price,
81
+ currency: sk.priceLocale.objectForKey(NSLocaleCurrencyCode),
82
+ price_str: price_str,
83
+ }
84
+ }
85
+ end
86
+
87
+ class <<self
88
+ # make a sync call out of an async one
89
+ def call_synchronized(method, *args)
90
+ finished = false
91
+ result = nil
92
+ send(method, *args) do |res|
93
+ result = res
94
+ finished = true
95
+ end
96
+ sleep 0.1 until finished
97
+ result
98
+ end
99
+
100
+ def fetch(*products, &b)
101
+ products.flatten!
102
+ if b.nil?
103
+ call_synchronized(:fetch, *products)
104
+ else
105
+ new(*products, &b)
106
+ end
107
+ end
108
+
109
+ def clear_cache
110
+ @@mutex.synchronize { @@cache = {} }
111
+ end
112
+ end
113
+
114
+ end
115
+ end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: helu
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.5'
4
+ version: '0.6'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Acosta-Rubio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-22 00:00:00.000000000 Z
11
+ date: 2014-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  description: 'RubyMotion :: StoreKit Wrapper :: Allows In App Purchases '
@@ -33,7 +33,9 @@ extra_rdoc_files: []
33
33
  files:
34
34
  - README.md
35
35
  - lib/helu.rb
36
+ - lib/project/fake_helu.rb
36
37
  - lib/project/helu.rb
38
+ - lib/project/product_info_fetcher.rb
37
39
  homepage: http://www.ivanacostarubio.com
38
40
  licenses:
39
41
  - MIT
@@ -44,17 +46,17 @@ require_paths:
44
46
  - lib
45
47
  required_ruby_version: !ruby/object:Gem::Requirement
46
48
  requirements:
47
- - - '>='
49
+ - - ">="
48
50
  - !ruby/object:Gem::Version
49
51
  version: '0'
50
52
  required_rubygems_version: !ruby/object:Gem::Requirement
51
53
  requirements:
52
- - - '>='
54
+ - - ">="
53
55
  - !ruby/object:Gem::Version
54
56
  version: '0'
55
57
  requirements: []
56
58
  rubyforge_project:
57
- rubygems_version: 2.0.3
59
+ rubygems_version: 2.2.2
58
60
  signing_key:
59
61
  specification_version: 4
60
62
  summary: RubyMotion StoreKit Wrapper