2011年9月21日 星期三

如何實作通知使用者有version update

可能有一種需求是我們希望如果appstore上有新版的軟體上架
我們會要通知使用者是否要更新
這時候我們可以透過這個URL去取得你的app資訊
http://itunes.apple.com/lookup?id=appid
回傳的結果可能是這樣.
中間就有版本號碼啦
不要問我怎麼抓怎麼parse json
這個solution很好找的
{
    "resultCount": 1,
    "results": [
        {
            "kind": "software",
            "artistId": 291728775,
            "artistName": "5Knot",
            "price": 0,
            "version": "1.1",
            "description": "90 Minutes .....",
            "genreIds": [
                "6005",
                "6012"
            ]
        }
    ]
}
然後自己local的版本可以這樣拿
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]
自己再寫一個NSString的category去比較版本
@implementation NSString(VersionCompare)
- (NSComparisonResult)compareVersion:(NSString *)version
{
     NSArray *thisVersionParts = [self componentsSeparatedByString:@"."];
     NSArray *versionParts = [version componentsSeparatedByString:@"."];
     NSUInteger count = MIN([thisVersionParts count], [versionParts count]);
     NSUInteger i;
     for (i = 0; i < count; i++)
     {
          NSUInteger thisPart = [[thisVersionParts objectAtIndex:i] integerValue];
          NSUInteger part = [[versionParts objectAtIndex:i] integerValue];
          if (thisPart > part)
          {
               return NSOrderedDescending; //version is older
          }
          else if (thisPart < part)
          {
               return NSOrderedAscending; //version is newer
          }
     }
     if ([thisVersionParts count] > [versionParts count])
     {
          return NSOrderedDescending; //version is older
     }
     else if ([thisVersionParts count] < [versionParts count])
     {
          return NSOrderedAscending; //version is newer
     }
     return NSOrderedSame; //version is the same
}
搞定!!

Rerefenace
[1] Official search API
[2] iVersion


In App Purchase的實作心得分享

其實IAP的一些概念跟使用方法已經有嘎李羊的詳細介紹了,在此貼上連結,但就不再重複分享了
1. iOS In App Purchase 學習筆記 (1)
2. iOS In App Purchase 學習筆記 (2)
3. iOS In App Purchase 學習筆記 (3) : 如何從App Store取得商品資訊

我這邊就補充一下我最近研究IAP的心得,我就分別以三個類型Consumable, Non-consumable, Auto-renewable subscription來分別分享
Consumable
1. 可以透過此來購買Credit(虛擬貨幣),但是必須要在你的app中消費掉,不能拿來購買app以外的商品或是實體商品。
2. 通常實作的方法是交易成功後,程式自己增加購買的點數,這邊的邏輯StoreKit並不會負責幫你做credit增加的部份。
3. 雖然Consumable product可以設定quantity,來一次購買多量的商品,但是我建議還是不要這麼做。你可以用陳列多個商品來達到一次買多量credit的目的。例如:
10credits $0.99
25credits $1.99
50credits $2.99
4. 如果要讓多個device share你的credit好像沒有比較好的方法,因為我們無法取得apple id,所以不知道怎麼share。
而如果把credit存在server,那會不會違背policy這我就不敢說了。

Non-consumble
1. 買了之後就永久有效。即使app移除了再裝回來,或是在別的device裝app,只要用同個apple id就可以restore。
2. 有關restore相關的文章請看 Restoring Transactions
建議在你的app中如果有支援Non-consumable的app,要提供restore的功能,讓使用者有辦法恢復購買。
當然用原本的buy的方法也可以restore,但是比較不user friendly。
3. 交易成功後,記得要把買成功的狀態儲存起來,而app也要對應的打開對應的功能給end-user。

Auto renewable subscription
1. 有點類似Non-consumable product,但是是有時效性的服務。當訂閱週期到了,app store會自動展期,除非使用者取消自動展期。
2. 在itunes connect上面我們可以設定多種duration
3. 使用者可以透過[設定]這個app中的 Store -> Apple ID: -? -> 檢視Apple ID -> Manage Subscriptions 來取消訂閱或是更改週期
4. 比較多人可能會遇到的問題是我要怎麼知道subscription已經因為使用者取消註冊而過期失效了呢?
方法是App中可以透過http post去詢問subscription狀態,
你需要的是記住最後一次交易的receipt (-[SKPaymentTransaction transactionReceipt]),
或是透過restoreTransaction來取得transaction object,再透過其中的receipt來詢問 。
相關的文件在這 Verifying an Auto-renewable Subscription Receipt
下面是如果成功的話會回傳的結果,status = 0 代表成功。
而last_receipt_info可能會跟receipt不一樣,因為有可能server會自動renew subscription。

{
 "latest_receipt_info" =     {
        bid = "com.smartq.MyStore";
        bvrs = "1.0";
        "expires_date" = 1316424354739;
        "expires_date_formatted" = "2011-09-19 09:25:54 Etc/GMT";
        "item_id" = 465588051;
        "original_purchase_date" = "2011-09-19 08:34:24 Etc/GMT";
        "original_transaction_id" = 1000000008159291;
        "product_id" = "com.smartq.mystore.sub1m";
        "purchase_date" = "2011-09-19 09:20:54 Etc/GMT";
        quantity = 1;
        "transaction_id" = 1000000008162671;
    };
    receipt =     {
        bid = "com.smartq.MyStore";
        bvrs = "1.0";
        "expires_date" = 1316424354739;
        "expires_date_formatted" = "2011-09-19 09:25:54 Etc/GMT";
        "item_id" = 465588051;
        "original_purchase_date" = "2011-09-19 08:34:24 Etc/GMT";
        "original_transaction_id" = 1000000008159291;
        "product_id" = "com.smartq.mystore.sub1m";
        "purchase_date" = "2011-09-19 09:20:54 Etc/GMT";
        quantity = 1;
        "transaction_id" = 1000000008162671;
    };
    status = 0;  
而如果失敗的話可能會如下所示,
status = 21006代表subscription expired。
注意的是這次他不會回傳latest_receipt_info,而是lastest_expired_receipt_info

{
    "latest_expired_receipt_info" =     {
        bid = "com.smartq.MyStore";
        bvrs = "1.0";
        "expires_date" = 1316424354739;
        "expires_date_formatted" = "2011-09-19 09:25:54 Etc/GMT";
        "item_id" = 465588051;
        "original_purchase_date" = "2011-09-19 08:34:24 Etc/GMT";
        "original_transaction_id" = 1000000008159291;
        "product_id" = "com.smartq.mystore.sub1m";
        "purchase_date" = "2011-09-19 09:20:54 Etc/GMT";
        quantity = 1;
        "transaction_id" = 1000000008162671;
    };
    receipt =     {
        bid = "com.smartq.MyStore";
        bvrs = "1.0";
        "expires_date" = 1316424354739;
        "expires_date_formatted" = "2011-09-19 09:25:54 Etc/GMT";
        "item_id" = 465588051;
        "original_purchase_date" = "2011-09-19 08:34:24 Etc/GMT";
        "original_transaction_id" = 1000000008159291;
        "product_id" = "com.smartq.mystore.sub1m";
        "purchase_date" = "2011-09-19 09:20:54 Etc/GMT";
        quantity = 1;
        "transaction_id" = 1000000008162671;
    };
    status = 21006;
}    
5. 在開發中我們都是在sandbox mode中測試,但是subscription的週期會因為為了測試方便會短很多,相關的mapping如下
6. 在sandbox mode中只會自動展期五次,第六次會直接expire。

其他注意事項
1. IAP只能在實機上測試,並且只能在sandbox mode下測試,而sandbox mode也只能用測試帳號測試。
2. 測試帳號必須要先在你的itunes connect中,簽署“iOS Paid Applications”這份contract才可以產生。
3. 因為IAP product的價錢可以透過itunes connect上調整,建議商品售價可以透過SKProductRequest去跟itunes connect詢問,而非寫死在code。
下面是4/12/2013新增的
4. Test account請不要在系統的設定(Settings)去登入,也不要留下信用卡帳號,因為一旦使用就不能在sandbox mode中使用
5. 如果你有gmail帳號,你可以用gmail的alias來新增Test account。例如你原本的email是 example@gmail.com,那你可以用example+test@gmail.com去申請。這樣就可以申請一堆測試帳號。
6. 即使是測試帳號,交易過的就不能移除,這對non-consumable product測是很麻煩,唯一的解法就是多產生幾個測試帳號。

Ref
[1] iTunes Connect Developer Guide 7.0
[2] In App Purchase Programming Guide