ProMotion-iap 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b7e41cfc55cf06853a59e0f826b7161765189039
4
+ data.tar.gz: a2eba57b0b4f0d42ddd1fde6dd0f38c27c4f1bb6
5
+ SHA512:
6
+ metadata.gz: ea6ebbe840ca8d1718d22a7f48706084917b62f1d8473d5e21550bdebdc53073bb76049def4d3f3fff77a613e0e0d410a21d66902c704f92abd61d5437bac9f1
7
+ data.tar.gz: 391efff17e8eb4ee1d5d9cd92f34469d59c6de8d8b9eb24fd8899437e2de2579cddf29e710a002f1fdb9a7d72436ad0f1192dd2fcb94dc3c04caed2c66bc8ce2
@@ -0,0 +1,89 @@
1
+ # ProMotion-iap
2
+
3
+ ProMotion-iap is in-app purchase notification support for the
4
+ popular RubyMotion gem [ProMotion](https://github.com/clearsightstudio/ProMotion).
5
+
6
+ ## Installation
7
+
8
+ ```ruby
9
+ gem 'ProMotion-iap'
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ### AppDelegate
15
+
16
+ Include `PM::IAP` to add some in-app purchase methods to a screen, app delegate, or other class.
17
+
18
+ ```ruby
19
+ # app/screens/purchase_screen.rb
20
+ class PurchaseScreen < PM::Screen
21
+ include PM::IAP
22
+
23
+ def on_load
24
+
25
+ retrieve_iaps([ "productid1", "productid2" ]) do |products, error|
26
+ # products looks something like the following
27
+ [{
28
+ product_id: "productid1",
29
+ title: "title",
30
+ description: "description",
31
+ price: <BigDecimal 0.99>,
32
+ formatted_price: "$0.99",
33
+ price_locale: <NSLocale>,
34
+ downloadable: false,
35
+ download_content_lengths: <?>, # TODO: ?
36
+ download_content_version: <?>, # TODO: ?
37
+ product: <SKProduct>
38
+ }, {...}]
39
+ end
40
+
41
+ purchase_iap "productid" do |status, transaction|
42
+ case status
43
+ when :in_progress
44
+ # Usually do nothing, maybe a spinner
45
+ when :deferred
46
+ # Waiting on a prompt to the user
47
+ when :purchased
48
+ # Notify the user, update any affected UI elements
49
+ when :canceled
50
+ # They just canceled, no big deal.
51
+ when :error
52
+ # Failed to purchase
53
+ transaction.error.localizedDescription # => error message
54
+ end
55
+ end
56
+
57
+ restore_iaps do |status, products|
58
+ if status == :restored
59
+ # Update your UI, notify the user
60
+ end
61
+ end
62
+
63
+
64
+ end
65
+ end
66
+ ```
67
+
68
+ #### purchase_iap(*product_ids, &callback)
69
+
70
+ TODO
71
+
72
+ ```ruby
73
+
74
+ ```
75
+
76
+ Find the Product ID here:
77
+
78
+ ![product id](http://clrsight.co/jh/2015-02-11-d8xw6.png?+)
79
+
80
+
81
+
82
+ ## Contributing
83
+
84
+ 1. Fork it
85
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
86
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
87
+ 4. Make some specs pass
88
+ 5. Push to the branch (`git iap origin my-new-feature`)
89
+ 6. Create new Pull Request
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ unless defined?(Motion::Project::Config)
4
+ raise "ProMotion-iap must be required within a RubyMotion project."
5
+ end
6
+
7
+ Motion::Project::App.setup do |app|
8
+ lib_dir_path = File.dirname(File.expand_path(__FILE__))
9
+ app.files << File.join(lib_dir_path, "ProMotion/iap.rb")
10
+ app.frameworks << "StoreKit"
11
+ end
@@ -0,0 +1,132 @@
1
+ module ProMotion
2
+ module IAP
3
+ attr_accessor :completion_handlers
4
+
5
+ def purchase_iap(product_id, &callback)
6
+ iap_setup
7
+ retrieve_iaps product_id do |products|
8
+ products.each do |product|
9
+ self.completion_handlers["purchase-#{product[:product_id]}"] = callback
10
+ payment = SKPayment.paymentWithProduct(product[:product])
11
+ SKPaymentQueue.defaultQueue.addPayment(payment)
12
+ end
13
+ end
14
+ end
15
+
16
+ def restore_iaps(product_id, &callback)
17
+ iap_setup
18
+ retrieve_iaps product_id do |products|
19
+ products.each do |product|
20
+ self.completion_handlers["restore-#{product[:product_id]}"] = callback
21
+ SKPaymentQueue.defaultQueue.restoreCompletedTransactions
22
+ end
23
+ end
24
+ end
25
+
26
+ def retrieve_iaps(*product_ids, &callback)
27
+ iap_setup
28
+ self.completion_handlers["retrieve_iaps"] = callback
29
+ @products_request = SKProductsRequest.alloc.initWithProductIdentifiers(NSSet.setWithArray(product_ids.flatten))
30
+ @products_request.delegate = self
31
+ @products_request.start
32
+ end
33
+ alias retrieve_iap retrieve_iaps
34
+
35
+ def completion_handlers
36
+ @completion_handlers ||= {}
37
+ end
38
+
39
+ # private methods
40
+
41
+ private
42
+
43
+ def iap_setup
44
+ SKPaymentQueue.defaultQueue.addTransactionObserver(self)
45
+ end
46
+
47
+ def iap_shutdown
48
+ SKPaymentQueue.defaultQueue.removeTransactionObserver(self)
49
+ end
50
+
51
+ def retrieved_iaps_handler(products, &callback)
52
+ sk_products = products.map do |sk_product|
53
+ {
54
+ product_id: sk_product.productIdentifier,
55
+ title: sk_product.localizedTitle,
56
+ description: sk_product.localizedDescription,
57
+ formatted_price: formatted_iap_price(sk_product.price, sk_product.priceLocale),
58
+ price: sk_product.price,
59
+ price_locale: sk_product.priceLocale,
60
+ downloadable: sk_product.isDownloadable,
61
+ download_content_lengths: sk_product.downloadContentLengths,
62
+ download_content_version: sk_product.downloadContentVersion,
63
+ product: sk_product,
64
+ }
65
+ end
66
+
67
+ callback.call(sk_products, nil) if callback.arity == 2
68
+ callback.call(sk_products) if callback.arity < 2
69
+ end
70
+
71
+ def formatted_iap_price(price, price_locale)
72
+ num_formatter = NSNumberFormatter.new
73
+ num_formatter.setFormatterBehavior NSNumberFormatterBehaviorDefault
74
+ num_formatter.setNumberStyle NSNumberFormatterCurrencyStyle
75
+ num_formatter.setLocale price_locale
76
+ num_formatter.stringFromNumber price
77
+ end
78
+
79
+ public
80
+
81
+ # SKProductsRequestDelegate methods
82
+
83
+ def productsRequest(_, didReceiveResponse:response)
84
+ unless response.invalidProductIdentifiers.empty?
85
+ PM.logger.error "PM::IAP Error - invalid product identifier(s) '#{response.invalidProductIdentifiers.join("', '")}' for application identifier #{NSBundle.mainBundle.infoDictionary['CFBundleIdentifier'].inspect}"
86
+ end
87
+ retrieved_iaps_handler(response.products, &self.completion_handlers["retrieve_iaps"]) if self.completion_handlers["retrieve_iaps"]
88
+ @products_request = nil
89
+ self.completion_handlers["retrieve_iaps"] = nil
90
+ end
91
+
92
+ def request(_, didFailWithError:error)
93
+ self.completion_handlers["retrieve_iaps"].call([], error) if self.completion_handlers["retrieve_iaps"].arity == 2
94
+ self.completion_handlers["retrieve_iaps"].call([]) if self.completion_handlers["retrieve_iaps"].arity < 2
95
+ @products_request = nil
96
+ self.completion_handlers["retrieve_iaps"] = nil
97
+ end
98
+
99
+ # SKPaymentTransactionObserver methods
100
+
101
+ def paymentQueue(_, updatedTransactions:transactions)
102
+ transactions.each do |transaction|
103
+ case transaction.transactionState
104
+ when SKPaymentTransactionStatePurchasing then iap_callback(:in_progress, transaction)
105
+ when SKPaymentTransactionStateDeferred then iap_callback(:deferred, transaction)
106
+ when SKPaymentTransactionStatePurchased then iap_callback(:purchased, transaction, true)
107
+ when SKPaymentTransactionStateRestored then iap_callback(:restored, transaction, true)
108
+ when SKPaymentTransactionStateFailed
109
+ if transaction.error.code == SKErrorPaymentCancelled
110
+ iap_callback(:canceled, transaction, true)
111
+ else
112
+ iap_callback(:error, transaction, true)
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ def iap_callback(status, transaction, finish=false)
119
+ product_id = transaction.payment.productIdentifier
120
+ if self.completion_handlers["purchase-#{product_id}"]
121
+ self.completion_handlers["purchase-#{product_id}"].call status, transaction
122
+ self.completion_handlers["purchase-#{product_id}"] = nil if finish
123
+ end
124
+ if self.completion_handlers["restore-#{product_id}"]
125
+ self.completion_handlers["restore-#{product_id}"].call status, transaction
126
+ self.completion_handlers["restore-#{product_id}"] = nil if finish
127
+ end
128
+ SKPaymentQueue.defaultQueue.finishTransaction(transaction) if finish
129
+ end
130
+
131
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ProMotion-iap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jamon Holmgren
8
+ - Kevin VanGelder
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-02-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ProMotion
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '2.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '2.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: motion-stump
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '0.3'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '0.3'
42
+ - !ruby/object:Gem::Dependency
43
+ name: motion-redgreen
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: Adds in-app purchase support to ProMotion.
71
+ email:
72
+ - jamon@clearsightstudio.com
73
+ - kevin@clearsightstudio.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - README.md
79
+ - lib/ProMotion-iap.rb
80
+ - lib/ProMotion/iap.rb
81
+ homepage: https://github.com/clearsightstudio/ProMotion-iap
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.4.5
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Adds in-app purchase support to ProMotion.
105
+ test_files: []