这是indexloc提供的服务,不要输入任何密码
Skip to content
This repository was archived by the owner on Feb 1, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ gemfile:
- Gemfile
script:
- bundle install
- bundle exec rake clean
- bundle exec rake spec
114 changes: 106 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# ProMotion-iap

[![Gem Version](https://badge.fury.io/rb/ProMotion-iap.svg)](http://badge.fury.io/rb/ProMotion-iap)
[![Build Status](https://travis-ci.org/clearsightstudio/ProMotion-iap.svg)](https://travis-ci.org/clearsightstudio/ProMotion-iap)

ProMotion-iap is in-app purchase notification support for the
popular RubyMotion gem [ProMotion](https://github.com/clearsightstudio/ProMotion).
popular RubyMotion gem [ProMotion](https://github.com/clearsightstudio/ProMotion).

## Installation

Expand All @@ -11,7 +14,79 @@ gem 'ProMotion-iap'

## Usage

### AppDelegate
### PM::IAP::Product Class

The `Product` class is an abstraction layer that provides a simpler interface when working with a single IAP product.
If you are dealing with multiple products you will want to use the IAP Module directly (documented below).

```ruby
class PurchaseScreen < PM::Screen

def on_load

product = PM::IAP::Product.new("productid")

product.retrieve do |product, error|
# product looks something like the following
{
product_id: "productid1",
title: "title",
description: "description",
price: <BigDecimal 0.99>,
formatted_price: "$0.99",
price_locale: <NSLocale>,
downloadable: false,
download_content_lengths: <?>, # TODO: ?
download_content_version: <?>, # TODO: ?
product: <SKProduct>
}
end

product.purchase do |status, transaction|
case status
when :in_progress
# Usually do nothing, maybe a spinner
when :deferred
# Waiting on a prompt to the user
when :purchased
# Notify the user, update any affected UI elements
when :canceled
# They just canceled, no big deal.
when :error
# Failed to purchase
transaction.error.localizedDescription # => error message
end
end

product.restore do |status, product|
if status == :restored
# Update your UI, notify the user
end
end

end
end

```

#### Product.new(product_id)

Stores the product_id for use in the instance methods.

#### retrieve(&callback)

Retrieves the product.

#### purchase(&callback)

Begins a purchase of the product.

#### restore(&callback)

Begins a restoration of the previously purchased product.


### IAP Module

Include `PM::IAP` to add some in-app purchase methods to a screen, app delegate, or other class.

Expand All @@ -22,7 +97,7 @@ class PurchaseScreen < PM::Screen

def on_load

retrieve_iaps([ "productid1", "productid2" ]) do |products, error|
retrieve_iaps [ "productid1", "productid2" ] do |products, error|
# products looks something like the following
[{
product_id: "productid1",
Expand Down Expand Up @@ -54,7 +129,7 @@ class PurchaseScreen < PM::Screen
end
end

restore_iaps do |status, products|
restore_iaps "productid" do |status, products|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the product id required here? I don't remember. I think not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It probably shouldn't be. You often want to get all products.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if status == :restored
# Update your UI, notify the user
end
Expand All @@ -65,19 +140,42 @@ class PurchaseScreen < PM::Screen
end
```

#### purchase_iap(*product_ids, &callback)
#### retrieve_iaps(`*`product_ids, &callback)

Retrieves in-app purchase products in an array of mapped hashes. The callback method should accept `products` and `error`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The * screws this up. Might need to add backticks around the methods to avoid issues.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or at least around the *



#### purchase_iaps(`*`product_ids, &callback)

Prompts the user to login to their Apple ID and complete the purchase. The callback method should accept `status` and `transaction`.
The callback method will be called several times with the various statuses in the process. If more than one `product_id` is provided
the callback method will be called several times per product with the applicable transaction.


#### restore_iaps(`*`product_ids, &callback)

Restores a previously purchased IAP to the user (for example if they have upgraded their device). This relies on the Apple ID the user
enters at the prompt. Unfortunately, if there is no purchase to restore for the signed-in account, no error message is generated and
will fail silently.


TODO

```ruby

```

Find the Product ID here:

![product id](http://clrsight.co/jh/2015-02-11-d8xw6.png?+)


## Authors
| Contributor | Twitter |
| Jamon Holmgren | [@jamonholmgren](http://twitter.com/jamonholmgren) |
| Kevin VanGelder | [@kevinvangelder](http://twitter.com/kevin_vangelder) |

## Inspired By
- [Helu](https://github.com/ivanacostarubio/helu)
- [Mark Rickert's Code Example](https://github.com/OTGApps/TheShowCloser/blob/master/app/helpers/iap_helper.rb)


## Contributing

Expand Down
1 change: 1 addition & 0 deletions lib/ProMotion-iap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
Motion::Project::App.setup do |app|
lib_dir_path = File.dirname(File.expand_path(__FILE__))
app.files << File.join(lib_dir_path, "ProMotion/iap.rb")
app.files << File.join(lib_dir_path, "ProMotion/product.rb")
app.frameworks << "StoreKit"
end
8 changes: 4 additions & 4 deletions lib/ProMotion/iap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ module ProMotion
module IAP
attr_accessor :completion_handlers

def purchase_iaps(product_id, &callback)
def purchase_iaps(*product_ids, &callback)
iap_setup
retrieve_iaps product_id do |products|
retrieve_iaps product_ids do |products|
products.each do |product|
self.completion_handlers["purchase-#{product[:product_id]}"] = callback
payment = SKPayment.paymentWithProduct(product[:product])
Expand All @@ -14,9 +14,9 @@ def purchase_iaps(product_id, &callback)
end
alias purchase_iap purchase_iaps

def restore_iaps(product_id, &callback)
def restore_iaps(*product_ids, &callback)
iap_setup
retrieve_iaps product_id do |products|
retrieve_iaps product_ids do |products|
products.each do |product|
self.completion_handlers["restore-#{product[:product_id]}"] = callback
SKPaymentQueue.defaultQueue.restoreCompletedTransactions
Expand Down
27 changes: 27 additions & 0 deletions lib/ProMotion/product.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module ProMotion
class IAP::Product
include PM::IAP

attr_reader :product_id

def initialize(product_id)
@product_id = product_id
end

def retrieve(&callback)
retrieve_iaps(product_id) do |products, error|
callback.call products.first, error
end
end

def purchase(&callback)
purchase_iaps(product_id, &callback)
end

def restore(&callback)
restore_iaps(product_id) do |status, products|
callback.call status, products.find{|p| p[:product_id] == product_id }
end
end
end
end
35 changes: 35 additions & 0 deletions spec/iap_product_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
describe PM::IAP::Product do


it "#retrieve" do
subject = PM::IAP::Product.new("retrieveid")
subject.mock!(:retrieve_iaps) do |product_ids, &callback|
product_ids.should.include "retrieveid"
end
subject.retrieve do |products, error|
end

end

it "#purchase" do
subject = PM::IAP::Product.new("purchaseid")
subject.mock!(:purchase_iaps) do |product_ids, &callback|
product_ids.should.include "purchaseid"
end
subject.purchase do |status, transaction|
end
end

it "#restore" do
subject = PM::IAP::Product.new("restoreid")
subject.mock!(:restore_iaps) do |product_ids, &callback|
product_ids.should.include "restoreid"
callback.call(:restored, [{product_id: "restoreid2"}, {product_id: "restoreid"}, {product_id: "restoreid4"}])
end
subject.restore do |status, product|
status.should == :restored
product.should == { product_id: "restoreid" }
end
end

end