มาทำ In-App Purchases ใน iOS กันเถอะ :D
บทความนี้เกิดจากการที่ผมได้มีโอกาสได้ทำโปรเจ็คที่มีการซื้อสินค้าหรือเนื้อหาออนไลน์ เลยมานั่งค้นคว้าดูว่าการทำ In-App Purchase มันทำยังไงบ้างนะ เลยได้มีโอกาสได้เอามาแชร์กันครับ
ก่อนอื่นเลยถ้าจะทำ In-App Purchase เราต้องรู้ก่อนว่าทาง Apple เค้ามีสินค้าประเภทอะไรบ้างที่ให้เราใช้ได้บ้าง
ประเภทของสินค้า
ทาง Apple จะมีประเภทสินค้าด้วยกัน 4 แบบคือ
- Consumables คือ สินค้าประเภทสิ้นเปลือง โดยผู้ใช้สามารถซื้อซ้ำได้ เช่น เหรียญในเกมส์ เป็นต้น
- Non-Consumables คือ สินค้าที่ไม่ใช่ประเภทสิ้นเปลือง โดยผู้ใช้สามารถซื้อได้ครั้งเดียวและไม่มีวันหมดอายุ เช่น หนังสือ รูปภาพ เป็นต้น
- Auto-Renewable Subscriptions คือ บริการ หรือ เนื้อหา ที่ผู้ใช้สามารถซื้อครั้งเดียวและต่ออายุอัตโนมัติจนกว่าผู้ใช้จะตัดสินใจยกเลิก
- Non-renewing subscription คือ บริการ หรือ เนื้อหาที่ให้ผู้ใช้เข้าถึงในช่วงเวลาที่จำกัด และไม่ต่ออายุอัตโนมัติ ผู้ใช้สามารถซื้อซ้ำได้
การจัดการสินค้า
เราสามารถเพิ่ม ลบ แก้ไข ข้อมูลสินค้าได้ที่ https://appstoreconnect.apple.com/ โดยเข้าไปที่เมนู Manage ใน In-App Purchases โดยสามารถกดเครื่องหมาย “+” เพื่อเพิ่มสินค้า
ตั้งค่าโปรเจ็คเบื้องต้น
เริ่มแรกให้สร้างตัวโปรเจ็คขึ้นมาก่อน ในเดโมตัวนี้ผมใช้เป็น ภาษา Swift ส่วน Interface เป็น Storyboard ครับ
หลังจากนั้นให้เราทำการเพิ่ม In-App Purchase ใน Capability
ในตัวอย่างนี้ผมจะใช้ตัวไฟล์ StoreKit Configuration ในการเพิ่ม Product โดยให้ทำการ New File -> เลือก StoreKit Configuration File
เสร็จแล้วเราต้องตั้งค่าให้ Scheme ที่เราต้องการรันนั้นเรียกใช้ไฟล์ StoreKit Configuration ตัวนี้โดยเข้าไปที่ Edit Scheme เลือกเมนู Options -> StoreKit Configuration
ถ้าต้องการใช้กับสินค้าที่อยู่บน AppStoreConnect อย่าลืมเอาตัวนี้ออกนะ เคยลืมเอาออกแล้ว Fetch Product ไม่ตรงหาเกือบครึ่งวันแหนะ -_-”
การ Fetch Product
ในการดึงข้อมูล Product สิ่งแรกที่เราต้องรู้คือ Product IDs เพราะเป็นสิ่งที่เราจะใช้อ้างอิงในการ Fetch ข้อมูล ทีนี้เราจะทำการสร้าง Function สำหรับการดึงข้อมูล Product ดังนี้
- เราจะต้องสร้าง Request ผ่าน SKProductsRequest โดยค่าเป็น Set<String> ซึ่งเราสามารถ Fetch Product ได้มากว่า 1 Id
- ให้เพิ่ม Protocol ที่ชื่อ SKProductsRequestDelegate เพื่อรอรับ Callback ตัว Product เวลา fetch สำเร็จ
- หลังจากเพิ่ม SKProductsRequestDelegate แล้วจะถูก Require function ที่ชื่อ productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) ให้เพิ่มเข้าไปเพราะเมื่อ Fetch Product เสร็จจะมาเข้า Callback ที่ function ตัวนี้โดยเราสามารถเอาค่า Product จาก response.products มาใช้ต่อได้ โดย Object ของ Product จะชื่อว่า SKProduct
- หลังจากนั้น start request โลด โดยใช้คำสั่ง start()
func fetchProduct(productIds: Set<String>) { let request = SKProductsRequest(productIdentifiers: productIds) request.delegate = self request.start()}func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { print(response.products)}
การทำ Purchase
หลังจากที่เราได้ SKProduct มาแล้วทีนี้เราก็จะมาทำ Purchase โดย step จะมีดังนี้
- ทำการเช็คว่า Device เครื่องนี้สามารถทำ Payment ได้หรือไม่ โดยการเรียก SKPaymentQueue.canMakePayments() ค่า return ที่ได้จะเป็น Boolean ถ้าเป็น true สามารถทำ Payment ได้
- สร้าง Object ที่ชื่อ SKPayment โดยนำ Parameter ของ SKProduct ที่เรา Fetch ได้มาใส่
- ทำการ Add transaction observer ผ่าน SKPaymentQueue.default().add(self) โดย function นี้จะรับ Delegate Callback เมื่อมี Process Transaction เกิดขึ้น หรือ มีการ Update Transaction
- เพิ่ม SKPaymentTransactionObserver และ Implement function ที่ชื่อ paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) โดยเมื่อมี Transaction เกิดขึ้นจะถูก Callback มาที่ function นี้
- ทำการ add SKPayment เข้าไปในคิวด้วยคำสั่ง SKPaymentQueue.default().add(payment)
- ให้เราทำการดัก State ของ Transaction โดย state จะมีด้วยกัน 5 แบบคือ purchasing, purchased, failed, restored, deferred
- เมื่อเราทำ Process ต่างๆ เสร็จแล้วให้ใช้คำสั่ง SKPaymentQueue.default().finishTransaction(transaction) เพื่อเสร็จสิ้นการทำ Transaction นี้
func makePayment(product: SKProduct) { guard SKPaymentQueue.canMakePayments() else { return } let payment = SKPayment(product: product) SKPaymentQueue.default().add(self) SKPaymentQueue.default().add(payment)}func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { transactions.forEach { transaction in switch transaction.transactionState { case .purchasing: print("transaction is on process purchasing") case .purchased: /// Update to server SKPaymentQueue.default().finishTransaction(transaction) case .failed: /// Update to server SKPaymentQueue.default().finishTransaction(transaction) case .restored: break case .deferred: break @unknown default: break } }}
พอเสร็จแล้วก็ลองรันดูกันเลย
สร้าง User Sandbox
เราสามารถสร้าง Sandbox user เพื่อเอามาทดสอบ IAP ที่เราสร้างไว้ โดยเข้าไปที่ https://appstoreconnect.apple.com/ เมนู Users and Access จากนั้นมองหาหัวข้อ Sandbox บนแถบเมนูด้านซ้ายมือ จากนั้นเลือก Testers
ถ้าต้องการเพิ่ม User sandbox ให้กดที่เครื่องหมาย “+” จากนั้นจะมีฟอร์มให้กรอก ชื่อ นามสกุล อีเมลล์ พาสเวิร์ด ต่างๆ
หมายเหตุ: อีเมลล์ที่ใช้จะต้องไม่ใช่ Apple Id ที่มีอยู่
เพียงเท่านี้เราก็สามารถสร้าง app ที่ทำ In-App Purchase ได้ง่าย ๆ ครับ นี่เป็นบทความแรกของผม หากผิดพลาดประการใดสามารถ Comment ชี้แจงให้แก้ไขได้นะครับ 🙂
ยังมีเนื้อหาอื่นๆ ที่ผมอาจจะตกหล่นไปบ้างสามารถ หาอ่านเพิ่มเติมได้ที่นี่ครับ
SourceCode