也就是程式是免費的,
但是如果你想要無廣告,取得所有關卡,增加某些功能,或者購買某些武器等等,
此時你就需要花錢購買,這就是所謂的In-App Purchases (IAP).
底下會同時考慮Android和iOS系統,
我們先將需要的共同程式部份貼出,然後再分別討論:
local store local currentProductList = nil local appleProductList = { {"com.gmail.myTest.DemoApp.GetFullVersion"} } local googleProductList = { "com.gmail.mytest.demo_app.getfullversion", } local function storeTransaction( event ) local transaction = event.transaction if ( transaction.state == "purchased" ) then print("transaction.state == purchased") if(fullVersion == false) then fullVersion = true end elseif ( transaction.state == "restored" ) then --iOS only print("transaction.state == restored") print( "productIdentifier:", transaction.productIdentifier ) print( "originalReceipt:", transaction.originalReceipt ) print( "originalTransactionIdentifier:", transaction.originalIdentifier ) print( "originalDate:", transaction.originalDate ) if(fullVersion == false) then fullVersion = true end elseif ( transaction.state == "refunded" ) then --refunds are only supported by the Android print("transaction.state == refunded") print( "productIdentifier:", transaction.productIdentifier ) if(fullVersion == true) then fullVersion = false end elseif ( transaction.state == "consumed" ) then --consumed are only supported by the Android print("transaction.state == consumed") print( "productIdentifier:", transaction.productIdentifier ) if(fullVersion == true) then fullVersion = false end elseif event.transaction.state == "cancelled" then --For iOS, if user cancels the IAP action, it will come to here print("transaction.state == cancelled") elseif event.transaction.state == "failed" then --[[ -1003: unknown -1005: user canclled,For Android, if user cancels the IAP action, it will come to here -7: already owned 8: item not owned ]] print("transaction.state == failed") print("Transaction failed, type:"..tostring(event.transaction.errorType)..",-1005") print("Transaction failed, error:"..tostring(event.transaction.errorString)) end store.finishTransaction( event.transaction ) end if ( isAndroid ) then store = require( "plugin.google.iap.v3" ) currentProductList = googleProductList store.init( "google", storeTransaction ) else store = require( "store" ) currentProductList = appleProductList store.init( "apple", storeTransaction ) end --put the following codes somewhere, such as when user press some button if(store.canMakePurchases) then store.purchase( currentProductList[1] ) end
Android
首先你必須到Play Store Publish內新增你的APP,
成功後,再進入到那個APP項目內新增應用程式內商品,
IAP種類可以分為管理的(managed),未管理的(unmanaged)和定閱的(subscription),
管理的,是指一次的,例如從試用版變成完成版之類的,
如果你的IAP是這種種類的,使用者購買後,Google會將購買紀錄存下來,如果使用者換機或者移除程式再重新安裝程式,可以將已購買部份回復。
未管理的,通常是指可以重複購買的,例如武器或主角的血值等等,
Google不會將購買紀錄存下來,
也就是說,如果使用者換了手機或者移除程式再重新安裝程式,
這部份的相關紀錄,需要開發者另外有方法將其紀錄下來,
定閱的,這部份就先不討論。
完成後,把那個項目id填入程式裡的googleProductList內,
在Play Store Publish內同一個APP裡,有一個服務和API項目,
點進去,裡面有一個授權金鑰,
它會是一段字串的格式,將它貼到config.lua內的key欄位:
application = { content = { width = 640, height = 960, scale = "zoomStretch", }, license = { google = { key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", }, }, }上面的過程,只要你可以申請成功即可,不用經過審查,<br />
再來,我們還需要在build.settings裡新增plugins和權限:
settings = { plugins = { ["plugin.google.iap.v3"] = { publisherId = "com.coronalabs", supportedPlatforms = { android=true } }, }, android = { usesPermissions = { "com.android.vending.BILLING", }, }, }
購買Purchase
要購買時,我們只要呼叫store.purchase( currentProductList[1] )即可,
不過,在實測前,我們需要將build好的apk檔上傳,
因為我們還沒測試好,所以上傳到ALPHA或BETA階段都可以,
重點就是要先上傳,不然實測時會得到"這一版的應用程式未提供Google Play結帳功能"之類的錯誤訊息,
之前是不用先上傳apk就可以測試,但現在規則改了,
上面的範例會先判斷store.canMakePurchases是iOS才有作用,
Android平台的話都會是true,
購買成功之後,在callback function storeTransaction裡會進入transaction.state == "purchased",
我們在裡面再將相關的權限打開即可,
測試Test
因為Google規定不能用自己的帳號來測試,所以你必須再弄個新帳號,
如果你的手機和你開發用的帳號是一樣的,
那就必須回到出廠設定,然後再設成新帳號,
我們可以到Play Store Publish 的設定畫面裡新增測試用Gmail帳戶,
也就是說,用這些帳戶購買你的IAP商品時,都不會被扣錢,
如果你沒有先去設定測試用帳戶,一樣可執行測試,
只是要真的花錢就是了,
當然,花了錢還是可以透過下面會提到的退貨機制來退錢,
另外,一開始測試有問題是,我們會不確定是因為程式有問題,
還是因為我們在Play Store Publish上面的設定有問題,
所以Google建議我們在測試IAP時,最好是先做所謂的"Static Responses"測試,
也就是將上面的googleProductList內項目換成
"android.test.purchased"
"android.test.canceled"
"android.test.refunded"
"android.test.item_unavailable"
等等,
這些項目google內定的,
你不用到Play Store Publish內先設定好,
也不用將apk先上傳,
它們可以測試程式內有關於IAP的處理流程,
程式加入IAP功能時,建議最好先做這樣的測試。
退貨Refund
Google允許使用者可以退貨,使用者可能會在電子錢包執行退貨動作,
原則上,我們只要在callback function storeTransaction裡的transaction.state == "refunded"做一些權限的改變即可
清除購買項目Comsuming items
這是Google特有的,
如果你的項目是管理的(managed),你可能測試之後發現有問題,
如果你修改程式之後想要再測一次,該怎麼處理呢?
因為你已經購買過了,我們可以用comsuming的方式將購買紀錄消除掉,
然後再進行購買試試
方法如下:
store.consumePurchase( currentProductList[1], storeTransaction )執行上面的動作後,callback function storeTransaction會進入transaction.state == "consumed"表示紀錄已消除,然後你可以再執行store.purchase( currentProductList[1] )
如果你沒有執行清除就直接再購買一次,那會出現錯誤"already owned",
callback function storeTransaction裡會進入transaction.state == "failed"
回復
如果使用者曾經買過管理的(managed)的商品,
使用者可能移除程式再安裝,或者同樣的帳號安裝在不同的機器呢?
我們必須將相關的權限回復,
程式可呼叫:
store.restore( )呼叫之後,會跑到callback function storeTransaction的transaction.state == "purchased"
Google沒有規定何時該執行回復,
你可以程式執行時自動回復,或者弄個按鈕讓使用者啓動回復,
如果使用者沒有買過,那執行回復不會有任何反應,
如上一段所說,已經買過了,
使用者再買一次時會得到錯誤訊息,而不是直接變成回復,
所以程式裡一定要有執行回復的動作
iOS
你必須先到iTunes Connect內新增你的APP,
成功後,再進入到那個APP項目內新增App內購買項目,
Apple提供5種購買項目種類,
一般我們最常用的大概就是消耗性項目(consumable products),和非消耗性項目(non-consumable products),
消耗性項目,和Google的未管理項目一樣,
非消耗性項目,和Google的管理項目一樣,
請參考前面Android部份的說明,
接著,我們把那個項目id填入程式裡的的appleProductList內,
注意, appleProductList內要用table格式,和Android用的格式不同,
上面的過程,只要你可以申請成功即可,不用經過審查,
購買Purchase
要購買時,我們只要呼叫store.purchase( currentProductList[1] )即可,
上面的範例會先判斷store.canMakePurchases是因為在iOS裝置可以將IAP功能鎖住,
主要是為了怕小孩誤按之類的,
購買成功之後,在callback function storeTransaction裡會進入transaction.state == "purchased",
我們在裡面再將相關的權限打開即可,
測試Test
因為App還未上架,在實機上測試IAP功能時,
我們會得到無法連接iTunes Store的錯誤訊息,
要測試,我們必須先iTunes Connect的"使用者和職能"裡面新增沙箱技術測試人員,
新增的帳號不能是現在已經存在的,什麼意思呢?
也就是說,你不能把你手機或平板的帳號設成測試人員帳號,
我們必須新增一個Apple帳號,這點和前面Android的設定測試人員不同,
因為這個新增帳號我們只拿來測試,所以資料可以亂寫,
一個簡單方法就是用你既有的帳號加上test1,test2之類的,
例如,你手機的帳號是"ABC",那就新增帳號"ABC+test1", "ABC+test2"...
你會需要新增很多測試帳號,
因為如果你的IAP商品是非消耗性項目(non-consumable products),
只要買過一次,系統就會紀錄,
Apple沒有像Google有消除購買項目的功能,
當然你再執行購買時,它會告訴你已經買過,可以再免費取得一次,
成功後,在callback function storeTransaction裡也是會進入transaction.state == "purchased",
它並不會像Android平台會進入transaction.state == "failed"
不過,如果你要模擬新使用者的狀態,那還是再新增一個測試帳
回復
如果使用者曾經買過非消耗性項目(non-consumable products)的商品,
使用者可能移除程式再安裝,或者同樣的帳號安裝在不同的機器呢?
我們必須將相關的權限回復,
程式可呼叫:
store.restore( )呼叫之後,會跑到callback function storeTransaction的transaction.state == "restored"
Apple規定如果你的App有非消耗性項目(non-consumable products)的IAP功能,
那就必須提供回復的按鈕,
等使用者按了之後,再執行回復的動作,
為什麼程式不能自動幫它回復呢?
因為你程式執行回復的動作,會跳出要使用者輸入帳號密碼的畫面,
如果你的程式是自動回復,突然跳出輸入密碼的畫面會讓使用者會覺得莫名其妙,
前面提過,已經購買過了,再購買也不用花錢,也不會像Google會得到錯誤訊息,
那就請使用者再按一次購買就好了啊,為什麼要再弄個回復的按鈕,
因為使用者已經購買過了,按購買的按鈕會讓使用者覺得需要再花一次錢,
不用錢的提示訊息是程式真的執行購買動作後才會跳出,
不管Android的Play Store Publish還是iOS的iTunes Connect,
設定新的IAP商品後,都需要一段時間才會生效,
有時可能要等幾個小時,
沒有任何地方告訴你已經可以開始測試,
如果你一直測試有問題,又找不出原因,那就隔天再試,
如果是Android,如前面提的,你可以先做"Static Responses"看看
沒有留言:
張貼留言