helu 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
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