แอปของคุณสามารถแสดงชีตคำขอคืนเงินภายในแอปได้ และนี่คือสิ่งที่ Apple ทำหลังจากลูกค้าแตะส่ง
คำขอคืนเงินภายในแอปของ Apple ให้ลูกค้าขอคืนเงินได้โดยไม่ต้องออกจากแอปของคุณ บนชีตที่ Apple สร้างและตรวจสอบเอง นี่คือสิ่งที่ beginRefundRequest ส่งคืน นาฬิกา CONSUMPTION_REQUEST และ 48 ชั่วโมงที่มันเริ่มจับเวลาบนเซิร์ฟเวอร์ของคุณ และปุ่มนี้คุ้มค่าที่จะปล่อยใช้งานหรือไม่

ประเด็นสำคัญ
- beginRefundRequest ของ Apple เป็นเมธอด StoreKit 2 ที่แสดงชีตคืนเงินของ Apple เองภายในแอปของคุณ ลูกค้าจะเห็นรายละเอียดการซื้อและรายการรหัสเหตุผล เลือกหนึ่งข้อ แล้วคำขอจะถูกส่งไปยัง Apple คุณไม่ได้สร้างฟอร์มและไม่ได้ตัดสินผลลัพธ์
- การเรียกนี้ส่งคืนสถานะ success หรือ userCancelled หรือโยน duplicateRequest หรือ failed สถานะ success หมายความว่า App Store ได้รับคำขอแล้ว ไม่ใช่ว่าอนุมัติแล้ว อย่าแสดงการคืนเงินที่ยืนยันแล้วใน UI ของคุณเมื่อได้ success เด็ดขาด
- หลังจากลูกค้าส่ง Apple ใช้เวลาไม่เกิน 48 ชั่วโมงในการอนุมัติหรือปฏิเสธ สำหรับการซื้อแบบสิ้นเปลือง มันจะส่ง CONSUMPTION_REQUEST ไปยังเซิร์ฟเวอร์ของคุณก่อน และคุณมีเวลาตามปกติ 12 ชั่วโมงในการตอบด้วยข้อมูลการใช้งานหากลูกค้ายินยอม
- ผลลัพธ์มาถึงเซิร์ฟเวอร์ของคุณในรูปแบบ App Store Server Notification ซึ่งเป็นฟีดเดียวกับที่คุณรับอยู่แล้ว การอนุมัติคือการแจ้งเตือน REFUND การปฏิเสธคือ REFUND_DECLINED คำขอภายในแอปจะเข้าฟีดนั้นเหมือนกับการคืนเงินที่เริ่มบนหน้า reportaproblem ของ Apple ทุกประการ
- ปุ่มนี้ใช้ได้ตั้งแต่ iOS 15 และ iPadOS 15, Mac Catalyst 15 และ visionOS 1 ดังนั้นแอปใดก็ตามที่รองรับเวอร์ชันเหล่านั้นสามารถแสดงมันได้ตั้งแต่วันนี้
- เหตุผลทางการเงินคือการคืนเงินที่คุณโต้แย้งได้ดีกว่าการเรียกคืนเงินผ่านบัตรที่คุณโต้แย้งไม่ได้ การเก็บลูกค้าไว้ในกระบวนการของ Apple จะกระตุ้น CONSUMPTION_REQUEST ที่คุณตอบได้ แทนที่จะเป็นการเรียกคืนเงินผ่านธนาคารซึ่งเป็นที่สิ้นสุดและมีค่าธรรมเนียม
- คำแนะนำเรื่องตำแหน่งวางของ Apple คือให้เรียกมันจากการตั้งค่าบัญชีหรือเมนูช่วยเหลือ ไม่ใช่หน้าจอการซื้อ เพื่อให้ลูกค้าที่ไม่พอใจหามันเจอโดยไม่ต้องโฆษณาการคืนเงินให้คนอื่น ๆ ทั้งหมด
Apple ให้ลูกค้าขอคืนเงินได้โดยไม่ต้องออกจากแอปของคุณเลย การเรียก StoreKit เพียงครั้งเดียวคือ beginRefundRequest จะแสดงชีตคืนเงินของ Apple เองภายในหน้าจอของคุณ ลูกค้าเลือกเหตุผล แล้วคำขอจะถูกส่งไปให้ Apple ตรวจสอบ คุณไม่ได้สร้างฟอร์ม คุณไม่ได้แตะต้องเงิน และคุณไม่ได้ตัดสินผลลัพธ์ สิ่งที่คุณได้คือวิธีวางเส้นทางคืนเงินไว้ตรงจุดที่ลูกค้าที่กำลังหงุดหงิดอยู่แล้ว แทนที่จะสูญเสียเขาไปให้ธนาคารของเขา นี่คือคำขอคืนเงินภายในแอป และคุณควรเข้าใจมันก่อนตัดสินใจว่าจะปล่อยปุ่มนี้หรือไม่
นี่คือส่วนที่สำคัญต่อรายได้ของคุณ ปุ่มนี้ไม่ได้คืนเงินอะไรด้วยตัวมันเอง มันเปิดคำขอขึ้นมา Apple ใช้เวลาไม่เกิน 48 ชั่วโมงในการอนุมัติหรือปฏิเสธ และสำหรับการซื้อแบบสิ้นเปลือง มันจะยิง CONSUMPTION_REQUEST ไปยังเซิร์ฟเวอร์ของคุณก่อน ดังนั้นชีตนี้จึงไม่ใช่การแจกฟรี มันคือกรวยที่นำเข้าสู่การตรวจสอบคืนเงินแบบเดียวกับที่คุณมีอิทธิพลต่อได้อยู่แล้ว และมันสามารถดึงข้อพิพาทกลับมาจากเครือข่ายบัตรก่อนที่มันจะกลายเป็นการเรียกคืนเงินที่คุณโต้แย้งไม่ได้
ชีตคำขอคืนเงินภายในแอปคืออะไรกันแน่
beginRefundRequest เป็นเมธอด StoreKit 2 ที่แสดงชีตคำขอคืนเงินสำหรับ transaction หนึ่งใน window scene ลายเซ็นของมันสั้น: func beginRefundRequest(in scene: UIWindowScene) async throws -> Transaction.RefundRequestStatus เมื่อคุณเรียกมัน ระบบจะแสดงชีตพร้อมรายละเอียดการซื้อของลูกค้าและรายการรหัสเหตุผลให้เลือก Apple เป็นผู้สร้างและควบคุม UI นั้น คุณส่ง scene และ transaction ให้ ไม่มีอะไรอื่น
คำแนะนำของ Apple เรื่องที่จะวางมันไว้ตรงไหนนั้นชัดเจน ให้เรียกฟังก์ชันนี้จากการตั้งค่าบัญชีหรือเมนูช่วยเหลือ เพื่อให้ลูกค้าที่ต้องการคืนเงินหามันเจอในที่ที่เขาจะไปหาการสนับสนุน มันมาพร้อมกับ iOS 15 และ iPadOS 15, Mac Catalyst 15 และ visionOS 1 ดังนั้นแอปใดก็ตามที่รองรับเวอร์ชันเหล่านั้นสามารถแสดงมันได้ตั้งแต่วันนี้
สองวิธีในการเปิดชีต
มีจุดเข้าสองจุด คุณสามารถเรียก beginRefundRequest(in:) บน transaction เฉพาะที่คุณถืออยู่แล้ว ซึ่งจำกัดชีตไว้ที่การซื้อนั้นเพียงรายการเดียว คุณยังสามารถเปิดชีตด้วยตัวระบุผลิตภัณฑ์เมื่อคุณต้องการให้ลูกค้าคืนเงินการซื้อของผลิตภัณฑ์หนึ่ง ไม่ว่าทางใด ชีต รายการเหตุผล และการตัดสินใจล้วนเป็นของ Apple งานของคุณจบลงที่การแสดงมันและอ่านผลลัพธ์
การเรียกส่งคืนอะไร และอะไรที่อาจผิดพลาดได้
เมธอดนี้เป็น async throws ดังนั้นมันจะส่งคืนสถานะหรือโยนข้อผิดพลาด ทั้งสองอย่างเป็นรายการสั้น ๆ และทั้งสองอย่างควรค่าแก่การจัดการ เพื่อให้ UI ของคุณบอกอะไรที่เป็นความจริงหลังจากชีตปิดลง
| ผลลัพธ์ | ประเภท | ความหมาย |
|---|---|---|
| success | RefundRequestStatus | App Store ได้รับคำขอคืนเงินแล้ว ส่งแล้ว ไม่ใช่อนุมัติแล้ว |
| userCancelled | RefundRequestStatus | ลูกค้าปิดชีตโดยไม่ส่ง ไม่มีอะไรถูกส่งไป |
| duplicateRequest | RefundRequestError | App Store มีคำขอคืนเงินสำหรับการซื้อนี้อยู่แล้ว |
| failed | RefundRequestError | การส่งเองล้มเหลว ให้ลูกค้าลองใหม่ |
เกิดอะไรขึ้นบนเซิร์ฟเวอร์ของคุณหลังจากลูกค้าแตะส่ง
การที่ชีตปิดลงคือจุดเริ่มต้นของกระบวนการ ไม่ใช่จุดจบ Apple ตรวจสอบคำขอและใช้เวลาไม่เกิน 48 ชั่วโมงในการอนุมัติหรือปฏิเสธ สำหรับการซื้อภายในแอปแบบสิ้นเปลือง ก่อนที่มันจะตัดสินใจ App Store จะส่งการแจ้งเตือน CONSUMPTION_REQUEST ไปยังเซิร์ฟเวอร์ของคุณเพื่อขอข้อมูลการใช้งาน หากลูกค้ายินยอมให้แบ่งปันข้อมูลนั้น คุณตอบผ่าน endpoint Send Consumption Information หากเขาไม่ยินยอม คำสั่งของ Apple เองคือไม่ต้องตอบการแจ้งเตือนนั้นเลย
เมื่อ Apple ตัดสินแล้ว ผลลัพธ์จะมาถึงเซิร์ฟเวอร์ของคุณในรูปแบบ App Store Server Notification นั่นคือฟีดเดียวกับที่คุณรับอยู่แล้ว และคำขอภายในแอปจะเข้าสู่มันเหมือนกับการคืนเงินที่ลูกค้าเริ่มบนหน้า reportaproblem ของ Apple ทุกประการ ไม่มีอะไรเกี่ยวกับการจัดการเปลี่ยนไปเพียงเพราะคำขอเริ่มต้นภายในแอปของคุณ
| ขั้นตอน | อะไรถูกกระตุ้น | สิ่งที่คุณทำ | นาฬิกา |
|---|---|---|---|
| ลูกค้าส่งชีต | beginRefundRequest ส่งคืน success | บันทึกไว้ แสดงว่ากำลังรอ ไม่ใช่คืนเงินแล้ว | ทันที |
| เฉพาะแบบสิ้นเปลือง Apple ถามก่อน | การแจ้งเตือน CONSUMPTION_REQUEST | ส่งข้อมูลการใช้งานหากลูกค้ายินยอม มิฉะนั้นให้เงียบไว้ | 12 ชั่วโมงในการตอบ |
| Apple อนุมัติ | การแจ้งเตือน REFUND | เพิกถอนสิทธิ์สำหรับ transaction นั้น | ไม่เกิน 48 ชั่วโมงในการตัดสิน |
| Apple ปฏิเสธ | การแจ้งเตือน REFUND_DECLINED | คงยอดขายไว้ ไม่ต้องเปลี่ยนอะไร | ไม่เกิน 48 ชั่วโมงในการตัดสิน |

ปุ่มนี้ทำให้คุณเสียอะไร และมันช่วยประหยัดอะไรได้บ้าง
การคืนเงินที่คุณโต้แย้งได้ดีกว่าการเรียกคืนเงินที่คุณโต้แย้งไม่ได้
ลูกค้าที่หาเส้นทางคืนเงินภายในแอปของคุณไม่เจอจะไม่ยอมแพ้ เขาจะไปหาธนาคารของเขา การเรียกคืนเงินผ่านบัตรเป็นที่สิ้นสุดกับธนาคาร มันมีค่าธรรมเนียมข้อพิพาท และมันดึงการตัดสินออกไปจากมือของทั้งคุณและ Apple คำขอคืนเงินภายในแอปเก็บลูกค้าคนเดียวกันนั้นไว้ในระบบของ Apple ที่ซึ่งการซื้อแบบสิ้นเปลืองกระตุ้น CONSUMPTION_REQUEST ที่คุณตอบได้และการตัดสินที่คุณมีอิทธิพลต่อได้ การแลกการเรียกคืนเงินที่โต้แย้งไม่ได้กับการตรวจสอบของ Apple ที่โต้แย้งได้คือเหตุผลทางการเงินทั้งหมดของปุ่มนี้
คุณกำลังลดแรงเสียดทานในการคืนเงิน
น้ำหนักถ่วงที่ซื่อสัตย์คือเส้นทางคืนเงินที่มองเห็นได้และแตะครั้งเดียวสร้างคำขอคืนเงินมากกว่าอีเมลสนับสนุนที่ถูกซ่อนไว้ บางคำขอในนั้นคงไม่มีวันเกิดขึ้น นั่นเป็นต้นทุนจริง และนั่นคือเหตุผลที่ Apple บอกให้คุณวางจุดเข้าไว้ในการตั้งค่าบัญชีหรือเมนูช่วยเหลือแทนที่จะเป็นบนหน้าจอการซื้อ คุณต้องการให้ลูกค้าที่ไม่พอใจอยู่แล้วหามันเจอ ไม่ใช่ลูกค้าที่เพียงแค่อยากรู้อยากเห็น
ต้นทุนที่เดินอยู่ตลอดเวลาคือการให้บริการบัญชีที่คืนเงินไปแล้ว
ไม่ว่าการตัดสินจะไปทางไหน มิเตอร์ของการส่งมอบยังคงเดินต่อไปจนกว่าคุณจะลงมือทำตามผลลัพธ์ ทุก ๆ ชั่วโมงที่สิทธิ์ที่คืนเงินไปแล้วยังเปิดใช้งานอยู่ คุณยังคงจ่ายต้นทุนจริงที่อยู่เบื้องหลังมัน: การประมวลผล การเรียก model API พื้นที่จัดเก็บ และการจ่ายเงินให้ครีเอเตอร์หรือพาร์ตเนอร์ใด ๆ ที่ผูกกับการใช้งานของลูกค้าคนนั้น คำขอภายในแอปไม่เปลี่ยนสิ่งนั้น การเพิกถอนอย่างทันท่วงทีเมื่อได้การแจ้งเตือน REFUND ต่างหากที่เปลี่ยน ปุ่มนี้ถูกก็ต่อเมื่อคุณจัดการการแจ้งเตือนที่มันสร้างขึ้นในที่สุดได้ดีเท่านั้น
คุณควรปล่อยคำขอคืนเงินภายในแอปหรือไม่
วางไว้ที่ที่การสนับสนุนอยู่ ไม่ใช่ที่ที่การขายอยู่
ทำตามคำแนะนำเรื่องตำแหน่งวางของ Apple การตั้งค่าบัญชีและเมนูช่วยเหลือคือบ้านที่ถูกต้อง ลิงก์คืนเงินข้าง ๆ paywall ฝึกให้ผู้คนคาดหวังว่าจะได้เงินคืน และมันเชื้อเชิญการคืนเงินเพราะความอยากรู้ที่คุณไม่เคยจำเป็นต้องเสนอ
ทดสอบกระบวนการทั้งหมดใน sandbox ก่อนที่คุณจะไว้ใจมัน
คุณสามารถจำลองเส้นทางทั้งหมดใน sandbox และในการทดสอบ StoreKit ของ Xcode โดยย้ายคำขอจากกำลังรอไปเป็นอนุมัติหรือปฏิเสธ การอนุมัติจะส่งการแจ้งเตือน REFUND ไปยังเซิร์ฟเวอร์ของคุณ และการปฏิเสธจะส่ง REFUND_DECLINED ดังนั้นคุณสามารถพิสูจน์ได้ว่าตัวจัดการของคุณตอบสนองอย่างถูกต้องก่อนที่ลูกค้าจริงจะแตะส่งเสียอีก
จัดการทุกผลลัพธ์ และอย่ากล่าวอ้างเกินจริงเด็ดขาด
แสดงกำลังรอเมื่อ success เสนอให้ลองใหม่เมื่อ failed บอกว่าไม่มีอะไรเปลี่ยนเมื่อ userCancelled และปฏิบัติต่อ duplicateRequest เป็นบันทึกเงียบ ๆ ว่าคำขอก่อนหน้าของลูกค้ายังคงมีผลอยู่ ความผิดพลาดเดียวที่สร้างความเสียหายคือการบอกลูกค้าว่าการคืนเงินของเขาเสร็จสิ้นแล้วทั้งที่สิ่งที่คุณถืออยู่มีเพียงคำขอที่ส่งไปเท่านั้น
RefundHalt จัดการเรื่องที่ตามมาอย่างไร
ชีตภายในแอปเป็นของ Apple สิ่งที่ตามมาหลังจากนั้นเป็นของคุณ และนั่นคือส่วนที่ RefundHalt ดูแล เมื่อลูกค้าส่งคำขอคืนเงินจากภายในแอปของคุณ RefundHalt จะดักจับ CONSUMPTION_REQUEST สำหรับการซื้อแบบสิ้นเปลืองและตอบมันภายในหน้าต่าง 12 ชั่วโมงด้วยหลักฐานการใช้งานที่ช่วยให้ Apple ตัดสิน เมื่อ Apple ตัดสิน มันจะเพิกถอนเมื่อได้ REFUND และคงการเข้าถึงไว้ไม่แตะต้องเมื่อได้ REFUND_DECLINED โดยแต่ละอย่างผูกกับ transaction ที่ถูกต้อง คุณจะสามารถเสนอเส้นทางคืนเงินภายในแอปที่เป็นมิตรกว่าได้โดยไม่ต้องปล่อยการตรวจสอบ หลักฐาน หรือการเพิกถอนไว้กับการวิ่งวุ่นแบบทำมือ
คำถามที่พบบ่อย
- beginRefundRequest ทำอะไร?
- มันแสดงชีตคำขอคืนเงินของ Apple ภายในแอปของคุณสำหรับ transaction เฉพาะรายการหนึ่ง ลูกค้าจะเห็นรายละเอียดการซื้อและรายการรหัสเหตุผล เลือกหนึ่งข้อ แล้วคำขอจะถูกส่งไปยัง Apple เมธอดนี้ส่งคืนสถานะ success หรือ userCancelled หรือโยน duplicateRequest หรือ failed มันไม่ได้คืนเงินการซื้อด้วยตัวมันเอง เพราะ Apple ตรวจสอบคำขอและใช้เวลาไม่เกิน 48 ชั่วโมงในการตัดสิน
- คำขอคืนเงินภายในแอปคืนเงินทันทีเลยหรือไม่?
- ไม่ ผลลัพธ์ success หมายความว่า App Store ได้รับคำขอแล้ว ไม่ใช่ว่าอนุมัติแล้ว Apple ใช้เวลาไม่เกิน 48 ชั่วโมงในการอนุมัติหรือปฏิเสธ และสำหรับสินค้าสิ้นเปลือง มันจะขอข้อมูลการใช้งานจากเซิร์ฟเวอร์ของคุณก่อนผ่านการแจ้งเตือน CONSUMPTION_REQUEST แสดงสถานะกำลังรอให้ลูกค้าเห็นเมื่อได้ success อย่าแสดงการคืนเงินที่ยืนยันแล้วเด็ดขาด
- iOS เวอร์ชันไหนรองรับคำขอคืนเงินภายในแอป?
- iOS 15 และ iPadOS 15, Mac Catalyst 15 และ visionOS 1 เมธอด StoreKit 2 beginRefundRequest(in:) ใช้ได้ตั้งแต่เวอร์ชันเหล่านั้น ดังนั้นแอปใดก็ตามที่รองรับ iOS 15 ขึ้นไปสามารถแสดงชีตคืนเงินของ Apple จากภายในแอปได้
- ฉันควรวางปุ่มคืนเงินภายในแอปไว้ที่ไหน?
- คำแนะนำของ Apple คือให้เรียกมันจากการตั้งค่าบัญชีหรือเมนูช่วยเหลือ ไม่ใช่จากหน้าจอการซื้อหรือ paywall นั่นวางเส้นทางคืนเงินไว้ในที่ที่ลูกค้าที่ไม่พอใจมองหาการสนับสนุน โดยไม่ต้องโฆษณาการคืนเงินให้ลูกค้าที่ไม่ได้ตั้งใจจะขอ
- คำขอคืนเงินภายในแอปดีกว่าการที่ลูกค้าติดต่อธนาคารของเขาหรือไม่?
- โดยทั่วไปแล้วใช่ สำหรับรายได้ของคุณ การเรียกคืนเงินผ่านธนาคารเป็นที่สิ้นสุดและมีค่าธรรมเนียม และมันตัดทั้ง Apple และคุณออกจากการตัดสิน คำขอคืนเงินภายในแอปเก็บลูกค้าไว้ในกระบวนการของ Apple ที่ซึ่งการซื้อแบบสิ้นเปลืองกระตุ้น CONSUMPTION_REQUEST ที่คุณตอบได้และการตรวจสอบที่คุณมีอิทธิพลต่อได้ การคืนเงินที่โต้แย้งได้ดีกว่าการเรียกคืนเงินที่โต้แย้งไม่ได้
แหล่งข้อมูลและเนื้อหาเพิ่มเติม
- Apple Developer: beginRefundRequest(in:)
- Apple Developer: Transaction.RefundRequestStatus
- Apple Developer: Transaction.RefundRequestError
- Apple Developer: App Store Server Notifications V2 notificationType
- Apple Developer: Send Consumption Information
- Apple Developer: Support customers and handle refunds (WWDC21)
RefundHalt
ระบบอัตโนมัติสำหรับการคืนเงินบน App Store และ Google Play
อ่านต่อ
เมื่อการซื้อบน Google Play ถูกคืนเงินหรือถูก chargeback, Voided Purchases API คือวิธีที่ทำให้คุณรู้
Google Play จะเพิกถอนการซื้อแบบเงียบ ๆ เมื่อมันถูกคืนเงินหรือถูก chargeback. Voided Purchases API คือรายการของออร์เดอร์เหล่านั้น เพื่อให้คุณเพิกถอนสิทธิ์การเข้าถึงได้. นี่คือทุกฟิลด์ หน้าต่าง 30 วัน ตัวเลือก revoke ที่ซ่อนออร์เดอร์ และค่าใช้จ่ายของมัน
การแจ้งเตือนการคืนเงินของ App Store สามรายการจะมาถึงหลังจาก Apple ตัดสิน และ REFUND_REVERSED จะคืนยอดขายกลับมาให้
Apple ส่งข้อความเกี่ยวกับการคืนเงินสี่รายการผ่าน App Store Server Notifications V2 และแอปส่วนใหญ่จัดการเพียงสองรายการ REFUND บอกให้คุณเพิกถอนสิทธิ์ REFUND_DECLINED หมายถึงเก็บยอดขายไว้ และ REFUND_REVERSED คืนยอดขายกลับมาและขอให้คุณคืนสิ่งที่คุณได้นำออกไป นี่คือสิ่งที่แต่ละรายการต้องการ