() translation by (you can also view the original English article)



Pagsisimula
Ang in-app purchase ay isang mahusay na feature para sa mga developers na gustong makakuha ng mas malaking kita at mag handog ng karagdagang content at features sa kanilang mga applications. Halimbawa, para sa games maaari kang bumili ng mga gems or mga coins, at para sa mga photography apps, maaari kang mag-unlock ng mga bagong effects o mga tools. At maaari mo itong magawa lahat ng hindi gumagamit ng credit card o kahit na anong ibang paraan sa pagbabayad ng hindi umaalis sa app.
Sa pagtuturong ito, tatalakayin ko lahat ng mga kinakailangang hakbang upang makagawa ng isan Consumable at Non-Consumable IAP na produkto sa iTunes connect, at ipapakita ko ang code na kailangang bilhin para sa parehong gamit. Gumawa ako ng sample na Xcode project na may label at dalawang pindutan, kaya naman i-download na ito at sumunod sa tutorial na ito upang maintindihan kung papaano ito gumagana.
Gumawa ng Sandbox
Tester sa iTunes Connect
Pinagpapalagay kong nakagawa ka na ng isang iOS app sa My Apps na bahagi ng iTunes Connect. Ang unang bagay na kailangang gawin ay gumawa ng Sandbox Tester upang masubukan ang IAP sa iyong real device (hindi pwede ang Simulator-hindi nito suportado ang mga In-App Purchases).
Maglagay ng Users at Roles, tumungo sa Sandbox Tester tab, at pindutin ang (+) na simbolo kasunod ng Tester.



Punan ang form upang makapagdagdag ng isang bagong sandbox tester. Kapag nai-save na ninyo ang info, bumalik sa My App section at pindutin ang icon ng iyong app upang mailagay ang mga detalye nito at gumawa ng bagong IAP products.
Gumawa ng IAP Products sa iTunes Connect
Mga Consumable na Produkto
Pindutin ang Features tab, pagkatapos ay ang simbolo na (+) katabi ng In-App Purchases. Maaari kang makagawa ng paisa-isang produkto kada pagkakataon, kaya naman simulant natin sa isang Consumable.



Ang Consumable IAP, gaya ng
iminumungkahi ng pangalan, ay isang produkto na maaari mong bilhin ng maraming
beses Gagamitin natin
ito upang makapagkolekta ng karagdagang “coins” sa ating demo app.
Pindutin ang Create upang mag-initialize ang iyong IAP item. Sa susunod na screen, maaari mong i-setup lahat ng mga impormasyong kailangan mo para sa iyong produkto:
- Ang Pangalan ng Reference: ang pangalang ito ang gagamitin sa iTunes connect at sa pag-uulat ng Sales and Trends. Hindi ito lalabas sa App Store kaya naman maari mong gamitin maski na anong pangalan ang gusto mo, basta’t hindi ito lalagpas ng 64 na characters.
- Ang Product ID: Isang natatanging alpanumerikong identifier na kukunin ng app para makilala ang iyong produkto. Kadalasan, gumagamit ang mga developers ng isang web-reverse syntax para sa mga product ids. Para sa halimbawang ito, pinili natin ang com.iaptutorial.coins. Mamaya ay ipe-paste natin ang ID na ito bilang isang string sa ating code.
- Presyo: Pumili ng price tier mula sa dropdown menu. Tandaan na para maibenta natin ang iyong in-app purchase product sa App Store, dapat ay nakapag-apply ka na para sa isang Paid Application Agreement sa bahagi ng Agreements, Tax & Banking.
- Mga Lokalisasyon: Para sa pagtuturong ito, pinili natin ang English lamang, ngunit maaari ka ding magdagdag ng karagdagang mga wika sa pamamagitan ng pagpindot sa (+) na pindutan. Pagkatapos ay maglagay ng Display Name at Description. Parehong lalabas ang mga ito sa App Store.
- Screenshot: Mag-upload ng screenshot para sa pagsusuri. Hindi ito ipapakita sa App Store at dapat ay may nararapat na sukat ito para sa iyong app platform, kaya namang kung ang app mo ay Universal, pupuwede kang mag-upload ng iPad screenshot.
- Mga Tala Ukol sa Pagsusuri: Kahit na anong karagdagang impormasyon tungkol sa iyong IAP na maaaring makatulong sa magsusuri.



Kapag tapos na, pindutin ang Save at makakuha ka ng ganitong alert:
Ang una mong In-App Purchase ay dapat ipasa gamit ang bagong app version. Piliin ito mmula sa parteng In-App Purchases ng app at pindutin ang Submit.
Non-Consumable Produkto
Ngayon ay pindutin ang In-App Purchases button sa listahan sa kaliwa, sa itaas lamang ng Game Center button, at magdagdag ng bagong IAP product. Sa pagkakataong ito, piliin ang Non-Consumable na pagpipilian:



Pindutin ang
Create at ulitin ang mga hakbang na nasabi na sa itaas. Dahil ito ay
magiging isang Non-Consumable na produkto, isang beses lang ito mabibili ng mga
users, at kakailanganin ng Apple ang kakayahang maulit ang mga pagbili na ito. Mangyayari ito
kapag inuninstall ang app at ininstall ito uli, o kapag dinownload ito mula sa
ibang device na may kaparehong Apple ID at kailangan mong makuha muli ang iyong
nabili ng hindi nagbabayad muli. Kaya naman mamaya
ay magdadagdag tayo ng Restore Purchase na function sa ating code.
Ang Product Id na ginawa natin ay nasa com.iaptutorial,premium, na may price tier na USD $ 2.99. Tinawag natin itong Unlock Premium Version.
Kapag tapos ka nang punan ang lahat ng mga fields, i-save ang produkto at bumalik sa pahina ng In-App Purchases. Ngayon dapat ay may listahan ka na ng iyong dalawang produkto, kasama ang kanilang Pangalan, Type, ID at Status na nakatakda bulang Ready to Submit.



Bumalik sa pahina
ng iyong app sa pamamagitan ng pagclick sa App Store at Prepare para Submission
na mga pindutan. Magscroll pababa
sa bahagi ng In-App Purchases, sa ibaba lang ng General App Information, at
pinutin ang (+) upang maidagdag ang iyong mga IAP products.



Piliin ang lahat ng mga ito at pindutin ang Done.



Panghuli, pindutin ang Save sa pinakakanan at taas na sulok ng screen at matatapos ka na sa pag-configure ng In-App Purchase products sa iTunes Connect.
Maglog-in sa Sandbox Tester sa isang iOS device
Bago pumunta sa code, may isang bagay pang kailangan gawin. Tumungo sa Settings > iTunes & AppStore sa iyong iOS device. Kung nakalog-in ka gamit ang iyong orihinal na Apple ID, pindutin ito at piliin ang Sign Out. Pagkatapos ay magsign in lang gamit ang credentials para sa sandbox tester na nilikha mo. Pagkasign in, maaaring makakita ka ng alert na gaya nito:
Huwag pansinin ang mensahe na ito at pindutin ang Cancel. Ang iyong device ay tatanungin ka muli kung ano ang iyong sandbox login credentials habang sinusubukan mong bumili at kikilalanin ang iyong test account upang hindi ka ma-charge ng kahit singko sa iyong credit card para sa kahit na anong pagbili.
Umalis sa Settings, isaksak ang iyong device sa iyong Mac sa pamamagitan ng USB cable, at sa wakas ay simulan na nating mag-code!
Ang Code
Kapag nadownload mo na ang ating demo project, makikita mo na ang lahat ng mga kailangang code para sa In-App Purchase ay naisulat na, kaya pag ni-run mo ito ay makakakita ka ng ganito:
Kung gusto mong
subukan ang app, kailangan mong baguhin ang Bundle Identifier sa sarili mong
ID. Kung hindi, hindi
ka hahayaan ng Xcode na mai-run ang iyong app sa isang real device at hindi
makikilala ng device ang dalawang IAP products na ginawa mo.
I-enter ang
ViewController.swift at tignan ang code. Una sa lahat ay
nagdagdag tayo ng isang import statement para sa StoreKit
at ang mga delegado
nito na kailangan natin upang ma-track ang payment transactions at mga product
request.
1 |
import StoreKit |
2 |
|
3 |
class ViewController: UIViewController, |
4 |
SKProductsRequestDelegate, |
5 |
SKPaymentTransactionObserver
|
6 |
{
|
Pagkatapos ay
nagdeklara tayo ng ilang views na maaari nating gamitin.
1 |
/* Views */
|
2 |
@IBOutlet weak var coinsLabel: UILabel! |
3 |
@IBOutlet weak var premiumLabel: UILabel! |
4 |
@IBOutlet weak var consumableLabel: UILabel! |
5 |
@IBOutlet weak var nonConsumableLabel: UILabel! |
6 |
Ang coinsLabel
at premiumLabel
ay
gagamitin natin upang maipakita ang mga resulta ng mga nabili para sa parehong
mga produkto. Ang consumableLabel
at nonConsumableLabel
ang
magpapakita ng pagkakakilanlan at presyo ng bawat isnag IAP product, ang mga
naunan nang nagawa sa iTunes Connect.
Ngayon naman ay oras nang magdagdag ng mga karagdagang variables:
1 |
/* Variables */
|
2 |
let COINS_PRODUCT_ID = "com.iaptutorial.coins" |
3 |
let PREMIUM_PRODUCT_ID = "com.iaptutorial.premium" |
4 |
|
5 |
var productID = "" |
6 |
var productsRequest = SKProductsRequest() |
7 |
var iapProducts = [SKProduct]() |
8 |
var nonConsumablePurchaseMade = UserDefaults.standard.bool(forKey: "nonConsumablePurchaseMade") |
9 |
var coins = UserDefaults.standard.integer(forKey: "coins") |
10 |
Ang unang
dalawang linya ay para matawag muli ang ating mga product IDs. Mahalaga na ang
mga strings na ito ay tugmang-tugma sa nakarehistro sa bahaging In-App Purchase
ng iTunes Connect.
- Ang
productID
ay isang string na gagamitin natin mamya upang malamang kung anong produkto ang pipiliin nating bilhin. - Ang
productsRequest
ay isang instance ngSKProductsRequestm
, na kailangan upang maghanap ng IAP products mula sa iyong app sa iTC. - Ang
iapProducts
ay isang simpleng array ngSKProducts
. Tandaan na ang unlaping SK ay nangangahulugang StoreKit, ang iOS framework na gagamitin natin upang humawak ng mga pagbili.
Ang huling
dalawang linya ay magloload ng dalawang variables na may tipong Boolean
at Integer
na kinakailangan upang ma-track ang pagbili ng mga coins at ang premium
version, pati na ang consumable at non-consumable na mga produkto.
Ang sumusunod na
code sa viewDidLoad()
ay nagsasagawa ng ilang mga bagay sa oras na tumakbo na
ang app:
1 |
// Check your In-App Purchases
|
2 |
print("NON CONSUMABLE PURCHASE MADE: \(nonConsumablePurchaseMade)") |
3 |
print("COINS: \(coins)") |
4 |
|
5 |
// Set text
|
6 |
coinsLabel.text = "COINS: \(coins)" |
7 |
|
8 |
if nonConsumablePurchaseMade { premiumLabel.text = "Premium version PURCHASED!" |
9 |
} else { premiumLabel.text = "Premium version LOCKED!"} |
10 |
|
11 |
// Fetch IAP Products available
|
12 |
fetchAvailableProducts() |
Una ay kailangan
nating i-log ang bawat pagbili sa Xcode console. Pagkatapos ay
ipapakita ang kabuuang bilang ng coins na nabili natin gamit ang coinsLabel
. Dahil pinagana
natin sa unang pagkakataon ang demo app, ipapakita nito ang COINS:0.
Ang if
statement
ay tinatakda ang nakasulat sa premiumLabel
ayon sa kung ang non-consumable
product ay nabili ba o hindi. Para magsimula,
ipapakita nito sayo na anf Premium version ay LOCKED! dahil hindi pa tayo
bumibili ng premium.
Ang huling linya ng code ay tinatawag ang method na makikita natin mamaya, na kinukuha lang ang mga produktong inilagay natin sa iTC.
Ngayon ay tignan natin ang ginagawa ng itinakda nating dalawang pagibli buttons sa ating demo app:
1 |
// MARK: - BUY 10 COINS BUTTON
|
2 |
@IBAction func buy10coinsButt(_ sender: Any) { |
3 |
purchaseMyProduct(product: iapProducts[0]) |
4 |
}
|
5 |
|
6 |
|
7 |
// MARK: - UNLOCK PREMIUM BUTTON
|
8 |
@IBAction func unlockPremiumButt(_ sender: Any) { |
9 |
purchaseMyProduct(product: iapProducts[1]) |
10 |
}
|
Ang parehong
methods ay tatawag ng isang function na magchecheck kung ang device ay maaaring
gumawa ng mga purchases, at kung pwede, ang app ay tatawagin ang StoreKit
delegate methods para iproseso ang purchase.
Gaya ng sinabi natin dati, kailangan natin ng ikatlong pindutan upang ibalik ang ating non-consumable purchase. Narito ang code nito:
1 |
// MARK: - RESTORE NON-CONSUMABLE PURCHASE BUTTON
|
2 |
@IBAction func restorePurchaseButt(_ sender: Any) { |
3 |
SKPaymentQueue.default().add(self) |
4 |
SKPaymentQueue.default().restoreCompletedTransactions() |
5 |
}
|
6 |
|
7 |
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { |
8 |
nonConsumablePurchaseMade = true |
9 |
UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade") |
10 |
|
11 |
UIAlertView(title: "IAP Tutorial", |
12 |
message: "You've successfully restored your purchase!", |
13 |
delegate: nil, cancelButtonTitle: "OK").show() |
14 |
}
|
15 |
Ang IBAction
function ay nakakabit sa Restore Purchase button sa Storyboard at nagsisimulang
kumonnect sa In-App Purchase system ng Apple para maibalik ang pagbili kapag
nagawa na ito.
Ang paymentQueueRestoreCompletedTransactionsFinished()
ay isang
delegate method mula sa StoreKit framework na magsesave sa ating nonConsumablePurchaseMade
variable
bilang true pagkatapos na ang pagbili ay matagumpay na naibalik.
Tapos na tayo sa
mga pindutan, kaya naman tignan natin kung ano ang nagagawa ng
fetchAvailableProducts()
function.:
1 |
// MARK: - FETCH AVAILABLE IAP PRODUCTS
|
2 |
func fetchAvailableProducts() { |
3 |
|
4 |
// Put here your IAP Products ID's
|
5 |
let productIdentifiers = NSSet(objects: |
6 |
COINS_PRODUCT_ID, |
7 |
PREMIUM_PRODUCT_ID
|
8 |
)
|
9 |
|
10 |
productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>) |
11 |
productsRequest.delegate = self |
12 |
productsRequest.start() |
13 |
}
|
14 |
Una ay gagawa
tayo ng isang instance ng NSSet
, na sa madaling salita ay isang array ng
strings. Ilalagay natin
ang ating dalawang product ID’s na nauna na nating nai-declare dito.
Pagkatapos ay
magsisimula tayo ng isang SKProductRequest
base sa mga identifiers na ito, para
magawa ng app na ipakita ang impormasyon ukol sa IAP Products (paglalarawan at
presyo), na ipoproseso ng delegate method na ito:
1 |
// MARK: - REQUEST IAP PRODUCTS
|
2 |
func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) { |
3 |
if (response.products.count > 0) { |
4 |
iapProducts = response.products |
5 |
|
6 |
// 1st IAP Product (Consumable) ------------------------------------
|
7 |
let firstProduct = response.products[0] as SKProduct |
8 |
|
9 |
// Get its price from iTunes Connect
|
10 |
let numberFormatter = NumberFormatter() |
11 |
numberFormatter.formatterBehavior = .behavior10_4 |
12 |
numberFormatter.numberStyle = .currency |
13 |
numberFormatter.locale = firstProduct.priceLocale |
14 |
let price1Str = numberFormatter.string(from: firstProduct.price) |
15 |
|
16 |
// Show its description
|
17 |
consumableLabel.text = firstProduct.localizedDescription + "\nfor just \(price1Str!)" |
18 |
// ------------------------------------------------
|
19 |
|
20 |
|
21 |
|
22 |
// 2nd IAP Product (Non-Consumable) ------------------------------
|
23 |
let secondProd = response.products[1] as SKProduct |
24 |
|
25 |
// Get its price from iTunes Connect
|
26 |
numberFormatter.locale = secondProd.priceLocale |
27 |
let price2Str = numberFormatter.string(from: secondProd.price) |
28 |
|
29 |
// Show its description
|
30 |
nonConsumableLabel.text = secondProd.localizedDescription + "\nfor just \(price2Str!)" |
31 |
// ------------------------------------
|
32 |
}
|
33 |
}
|
34 |
Sa function sa
itaas, una nating kailangan i-check kung meron bang mga produkto na nakarehistro
sa iTunes Connect at itakda ang ating iapProducts
array ayon dito. Pagkatapos ay
maaari na nating iinitialize ang dalawang SKProducts at i-print ang kanilang
paglalarawang at presyo sa mga label.
Bago tumungo sa pinakamahalagang bahagi ng code ng In-App Purchase, may ilang mga function pa tayong kailangan:
1 |
// MARK: - MAKE PURCHASE OF A PRODUCT |
2 |
func canMakePurchases() -> Bool { return SKPaymentQueue.canMakePayments() } |
3 |
func purchaseMyProduct(product: SKProduct) { |
4 |
if self.canMakePurchases() { |
5 |
let payment = SKPayment(product: product) |
6 |
SKPaymentQueue.default().add(self) |
7 |
SKPaymentQueue.default().add(payment) |
8 |
|
9 |
print("PRODUCT TO PURCHASE: \(product.productIdentifier)") |
10 |
productID = product.productIdentifier |
11 |
|
12 |
|
13 |
// IAP Purchases dsabled on the Device |
14 |
} else { |
15 |
UIAlertView(title: "IAP Tutorial", |
16 |
message: "Purchases are disabled in your device!", |
17 |
delegate: nil, cancelButtonTitle: "OK").show() |
18 |
} |
19 |
} |
Ang una ay
chinecheck kung ang ating device ay makakagawa ng mga pagbili. Ang ikalawang
function ay ang tinatawag natin mula sa dalawang mga pindutan. Nagsisimula ito
ng payment queue at binabago ang ating productID
variable sa napiling
productIdentifier
.
Ngayon ay nakarating na tayo sa huling delegate method, ang humahawak ng mga payment results:
1 |
// MARK:- IAP PAYMENT QUEUE
|
2 |
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { |
3 |
for transaction:AnyObject in transactions { |
4 |
if let trans = transaction as? SKPaymentTransaction { |
5 |
switch trans.transactionState { |
6 |
|
7 |
case .purchased: |
8 |
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) |
9 |
|
10 |
// The Consumable product (10 coins) has been purchased -> gain 10 extra coins!
|
11 |
if productID == COINS_PRODUCT_ID { |
12 |
|
13 |
// Add 10 coins and save their total amount
|
14 |
coins += 10 |
15 |
UserDefaults.standard.set(coins, forKey: "coins") |
16 |
coinsLabel.text = "COINS: \(coins)" |
17 |
|
18 |
UIAlertView(title: "IAP Tutorial", |
19 |
message: "You've successfully bought 10 extra coins!", |
20 |
delegate: nil, |
21 |
cancelButtonTitle: "OK").show() |
22 |
|
23 |
|
24 |
|
25 |
// The Non-Consumable product (Premium) has been purchased!
|
26 |
} else if productID == PREMIUM_PRODUCT_ID { |
27 |
|
28 |
// Save your purchase locally (needed only for Non-Consumable IAP)
|
29 |
nonConsumablePurchaseMade = true |
30 |
UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade") |
31 |
|
32 |
premiumLabel.text = "Premium version PURCHASED!" |
33 |
|
34 |
UIAlertView(title: "IAP Tutorial", |
35 |
message: "You've successfully unlocked the Premium version!", |
36 |
delegate: nil, |
37 |
cancelButtonTitle: "OK").show() |
38 |
}
|
39 |
|
40 |
break
|
41 |
|
42 |
case .failed: |
43 |
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) |
44 |
break
|
45 |
case .restored: |
46 |
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) |
47 |
break
|
48 |
|
49 |
default: break |
50 |
}}} |
51 |
}
|
Ang function na
ito ay may switch
statement na tinitignan ang bawat estado ng payment. Ang unang case
ay
tinatawag kapag ang pagbili ay matagumpay at kinukumpleto ang transaksyon.
Sa loob ng bloke
na ito, kailangan nating siguruhin kung anong product ID ang pinili natin at
gawin ang mga kailangang pagkilos upang mai-update ang ating app-para kung
tayo, ang gagamit, ay bibili ng sampung karagdagang coins
, magdadagdag tayo ng
10 sa ating coins variable, ise-save ang value nito gamit ang UserDefaults
,
ipakita ang bagong halaga na nakuha natin, at maglunsad ng alert tungkol dito.
Tandaan na maaari mong gawin ang pagbili na ito ng maraming beses ng walang limitasyon dahil ito ay isang consumable na IAP, at hindi na tayo mangangailangan pa ng restore purchase na function.
Kasabay nito,
kung bumili tayo ng non-consumable na premium na product, itatakda ng ating ap
ang ating nonConsumablePurchaseMade
variable bilang true
, ise-save ito,
babaguhin angteksto ng premiumLabel
, at magpapadala ng alert upang ipaalam sa
iyo na ang purchase ay nagging matagumpay.
Ang dalawa pang
ibang kaso
ay humahawak sa mga resulta ng pagbabayad para sa failure at
restoring. Ang app ay
magpapadala ng custom alerts a sarili nito kung ang iyong transaction ay nabigo
sa kung ano mang dahilan o kung nagrestore ka ng non-consumable purchase.
Iyan na yon! Ngayon, siguruhin lang na nakalog in ka gamit ang iyong Sandbox Tester credentials at patakbuhin ang app upang masubukan ito. Sa unang beses, makakakuha ka ng alert na gaya nito:
Piliin ang Use Existing Apple ID at muling ilagay ang iyong username at password ng Sandbox Tester upang makapagsign in. Nangyayari ito sapagkat ang app ay nakakakilala lang ng isang real user mula sa settings ng iTunes & App Store, at hindi sa isang galing sa Sandbox.
Kapag nakalog in ka na, magagawa mo na pagbili sa parehong produkto.






CodeCanyon Templates
Kung gumagamit ka ng iOS at gusto mong mas matutunan ang Swift language at apps development, tumungo na sa ilan sa aking mga iOS app templates sa CodeCanyon.
Meron ding daan-daan pang ibang iOS app templates sa Envato Market, nakahandang magamit muli at siguradong papabilisin ang iyong pagtatrabaho. Silipin na ang mga ito! Maaaring makatipid ka ng ilang oras ng pagtatrabaho sa iyong susunod na app.
Konklusyon
Sa pagtuturong ito, natalakay natin ang lahat ng mga hakbang na kailangan upang makagawa ng In-App Purchase na mga produkto sa iTunes Connect at kung papano sumulat ng code para mapagana ito sa iyong app. Sana ay magamit mo ang kaalaman na ito sa iyong susunod na iOS app!
Salamat sa pagbabasa, at kita-kits tayo muli! Tignan nyo rin ang iba pa naming mga kurso at mga pagtuturo tungkol sa iOS app development gamit ang Swift.