你的退款報告在 Apple、Google 和你的伺服器之間從來對不上,教你如何逐筆核對
Apple 用兩份報告呈現退款,Google 又用兩份,你的伺服器還會看到第四種。這些數字沒有一個能對上,而且這些差異是刻意設計的。這裡解釋為什麼每個管道對退款的歸屬方式各不相同,以及如何逐筆交易將退款報告與你自己的紀錄核對。

重點摘要
- Apple 把退款報告拆分到兩個工具裡,它們在設計上就永遠對不上。Sales and Trends 用 USD 快速估算退款,而 Payments and Financial Reports 稍後按 Apple 的財務日曆結算退款。你伺服器上的 REFUND 通知則是對同一事件的第三種即時視角。
- 在 Apple 的 Summary Sales Report 裡,一筆退款是獨立的一行,Units 為負、Customer Price 為負,而且這份報告並沒有把退款抵扣掉。如果你用肉眼去彙總某一欄,就會數錯,因為退款列是和銷售列並排放在一起的,而不是相互抵銷。
- Apple 的財務報告採用 4-4-5 財務日曆,而不是日曆月,某個財務月的報告會在下一個財務月的第一個星期五之前發布。任何你拿來和普通日曆月對比的退款合計,從一開始就會對不上。
- Google Play 也用同樣的方式區分退款。earnings report 把 Charge refund 和 Google fee refund 列為各自獨立的交易類型,每一筆都標註 Full 或 Partial,而 estimated sales report 是低延遲的分析資料,Google 明確表示它不用於記帳。
- 退款按它結算的日期歸屬,而不是原始銷售的日期,所以一筆 3 月購買的退款在兩個商店裡都會落到你 4 月的數字裡。用 transaction id 來核對退款,絕不要靠對齊每月合計。
- 開發者經常發現,在同一時間段內,REFUND 通知的數量比 Summary Sales Report 裡的退款列還多,因為這兩者統計的是不同的時刻。Apple 的 App Store Server API Get Refund History 端點才是核對的權威依據,每次核對一個 transaction id。
- 這些管道裡只有兩個是為記帳而設計的:Apple 的 financial report 和 Google 的 earnings report。金額要拿這兩個來核對,存取權限要拿你的伺服器通知來核對,絕不要讓一個數字去做另一個數字的工作。
從 App Store Connect 擷取退款數量,再從你的伺服器擷取一次,這兩個數字對不上。再從你的 financial report 擷取第三個,它和前兩個也都對不上。這並不是誰的系統出了 bug。Apple 和 Google 各自都透過不止一個管道報告退款,每個管道統計的是退款生命週期中的不同時刻,而你的伺服器看到的是第四種。如果你曾經試著核對退款報告,卻因為各項合計越差越多而放棄,這裡就講清楚它們為什麼會有差異、哪個數字該用在哪件事上,以及如何按交易而不是按月份把它們對齊。
為什麼一筆退款會呈現為三個不同的數字
一筆退款在結算之前會經過好幾個系統,而每個系統記錄它的時刻都不一樣。你的伺服器最先聽到它,作為一個事件。接著是一份快速分析報告對它進行估算。記帳報告最後才記錄它,也就是在錢真正劃轉之後。同一筆退款,三個時間戳,三個合計。錯誤在於把其中任意兩個當成應該在同一天相等。
Apple 給你兩大類報告,再加上你的 webhook
Apple 在兩個地方報告退款,它們既不是同一個工具,也並不打算在某一天對得上。Sales and Trends 是快速的估算視圖:每日報告在第二天發布,每週報告在星期一發布,每月報告在月末大約五天後發布,一般不遲於 Pacific 時間 8 a.m.。它用上個月匯率的滾動平均值以 USD 估算銷售額和收入,這讓它適合發現趨勢,卻不適合對帳某一筆付款。Payments and Financial Reports 是結算後的視圖:按 Apple 的財務日曆每月生成一次,會在當前財務月的第一個星期五之前發布上一個財務月的報告,而且只有在該期間內存在購買或退款時才會生成。它使用套用於你付款的最終匯率。那份報告才是記帳依據。除了這兩者,你的伺服器會在 Apple 批准退款的那一刻收到 App Store Server Notification REFUND,它以單個 transaction id 為鍵。
Google 也以同樣的方式拆分
Google Play 是同樣的拆分。earnings report 是記帳依據,每月生成,通常在次月 5 日之前發布,它把退款列為各自獨立的交易類型:Charge refund 表示退還給買家的金額,Google fee refund 表示 Google 退回的服務費,每一筆都標註 Full 或 Partial。estimated sales report 是低延遲的分析視圖,顯示買家在扣除稅費之前支付的金額,Google 明確表示它適合用於分析,不建議用於記帳。在伺服器端,你會收到即時的 Real-time Developer Notification,還可以從 Voided Purchases API 讀回一筆退款。
Apple 在報告裡如何呈現退款,以及負數列的陷阱
打開 Summary Sales Report,退款並不會悄悄地從某筆銷售裡扣掉自己。它會作為獨立的一行出現。那一行的 Units 和 Customer Price 都是負數,這正是你發現退款的方式,而 Developer Proceeds 這個數值的表現方式和價格並不相同。這份報告本身並沒有把退款抵扣掉。它把退款列放在銷售列旁邊,把它們歸類是你自己的事。用肉眼去彙總 Units 欄,你要麼會重複計數,要麼會完全漏掉退款,因為一個負一的退款列和你的正數銷售處在同一欄裡。
實用規則很簡單:透過負數 Units 找出退款,把這些列單獨加起來,絕不要以為報告已經替你把它們抵扣掉了。你退款數量的一句話答案,是負 Unit 列的數量,而不是某一欄的算術總和。
| Apple 管道 | 用途 | 更新時間 | 退款如何呈現 |
|---|---|---|---|
| Sales and Trends | 快速趨勢估算,不用於記帳 | 每日在次日,每月在月末大約 5 天後 | 趨勢中的負數單位,以 USD 估算 |
| Summary Sales Report | Sales and Trends 背後可下載的明細 | 與 Sales and Trends 相同的節奏 | 獨立的一行,Units 為負、Customer Price 為負 |
| Payments and Financial Reports | 記帳與付款紀錄 | 按 Apple 的財務日曆每月發布,不遲於第一個星期五 | 從該財務月收入中結算扣除 |
| REFUND 伺服器通知 | 即時存取控制 | Apple 批准退款的那一刻 | 一個事件,一個 transaction id |
財務日曆就是你每月合計永遠對不上的原因
這就是一份仔細的試算表仍然無法對平的最大單一原因。Apple 的財務報告不按日曆月運行。它們按 4-4-5 財務日曆運行,其中大多數財務月是四週,每第三個月是五週。一個開發者拿 Financial Report 和一個普通的 1 月到 1 月的區間對比,其實是在對比兩段不同的天數跨度,所以即使每個底層數字都正確,退款合計也不可能對上。正是出於這個原因,Apple 官方論壇上的開發者眼看著 Sales 數字和 Financial Report 數字相差數千美元,而且只要放任不管,差距每個月都在擴大。
Google 的 earnings report 是按月的,但它有自己的時間安排和自己的時區,兩者都不是你伺服器的 UTC 時鐘。更深層的陷阱是兩個商店共有的:退款按它結算的日期歸屬,而不是原始銷售的日期。在 4 月初為一筆 3 月的購買退款,它會減少你 4 月的數字,而不是 3 月的。按標籤把兩個月對齊,退款看上去就像是從一個月裡消失、又在另一個月裡冒了出來。

一筆退款的成本是多少,以及該在哪份報告裡查看它
核對本質上是一個記帳問題,所以要跟著錢走。發生退款時,商店會退回它自己的佣金,這意味著真正從你帳戶裡流出的金額是你在這筆銷售中的分成,而不是客戶看到被退回的全款。在 Google Play 上,這筆退回是一條可見的行:你 earnings report 上的 Google fee refund 交易類型就是退回給你的服務費,它緊挨著退給買家的 Charge refund。在 App Store 上,Apple 扣除你扣佣後的收入,並在同一動作中退回它的佣金,所以 financial report 顯示的扣除額已經扣掉了 Apple 的抽成。
現金流的時間點是開發者會感到意外的地方。在 Google Play 上,如果你在 Google 為某筆訂單向你付款之前就退款,你根本不會收到那筆金額。如果你在付款之後退款,Google 會從未來的一次付款中扣除它。而如果一波退款把你的餘額推成負數,並且持續為負至少 48 小時,Google 會從通常接收你付款的銀行帳戶中扣除這筆差額。拒付是同一事件更尖銳的版本:在 Google Play 上,對於在 2026 年 8 月 3 日當天或之後下的訂單,拒付會把購買價格加上銀行手續費轉嫁到開發者身上,而且它落在比銷售更晚的一個月的報告裡。
| 發生退款時 | App Store | Google Play |
|---|---|---|
| 從你帳戶流出的 | 你扣佣後的收入 | 購買價格減去 Play 的服務費 |
| 商店退回的 | Apple 的佣金 | 服務費,作為一條 Google fee refund 行 |
| 用哪份報告核對 | Payments and Financial Reports | Earnings report |
| 何時結算 | 處理它的那個財務月,不遲於其後的第一個星期五 | 從該期間或下一期間的付款中扣除 |
| 拒付的轉折 | Apple 吸收信用卡爭議處理的一整套機制 | 從 Aug 3 2026 起,價格加銀行手續費轉到你身上 |
如何一步步核對你的退款報告
一旦你不再試圖讓每個數字都相等,而是把每個數字分派給它所回答的問題,這件事就變簡單了。問題只有兩個:有多少錢發生了劃轉,以及誰還擁有存取權限。
- 打開報告之前先確定問題。對於金額,答案就在 Apple 的 financial report 和 Google 的 earnings report 裡,沒有別的。對於存取權限,答案在你的伺服器通知裡。絕不要拿一個去核對另一個。
- 選擇 transaction id 作為貫穿這四個管道的關聯鍵。它是銷售、它的退款、各份報告和你的 webhook 都共享的那一個欄位。
- 對於 Apple,當 Summary Sales Report 和你的 webhook 不一致時,呼叫 App Store Server API Get Refund History 端點
/inApps/v2/refund/lookup/{transactionId}。它返回某個客戶已簽名的退款交易,帶有 revocationDate 和 revocationReason,每次針對一個 transaction id,並會分頁遍歷他們的歷史紀錄。那個端點就是決勝項。 - 對於 Google,把 earnings report 上的 Charge refund 行與 Voided Purchases API 針對同一批訂單所報告的內容交叉核對,並記住部分退款會被標註為 Partial,不會把原始扣款清零。
- 以報告的時鐘為準,而不是你的。Apple 用的是 Pacific 時間下的財務月。Google 的 earnings report 有自己的月份和時區。你的日誌幾乎肯定是 UTC。在對比之前先轉換到報告的日曆,否則光是日期邊界就會製造出虛假的不匹配。
- 預期估算值會變動。Sales and Trends 是一個估算,會隨著交易結算而不斷變化。要拿 financial report 來核對,絕不要拿估算來核對,也絕不要拿昨天那份估算的快照來核對。
當你的伺服器顯示的退款比報告還多時
最常見的恐慌是發現在同一時間段內,你伺服器上的 REFUND 通知比銷售報告裡的退款列還多。這通常並不是錢丟了。這兩個管道統計的是不同的時刻,一條通知可能比報告裡的那一行早好幾天,而且一筆部分退款或一次重新提交的請求都可能產生不止一個事件。開發者們報告過的正是這種情形:同一個月裡數以千計的 REFUND 通知,對應著數量更少的負 Unit 列。每次都用同樣的方式解決它:拿你伺服器看到的那些 transaction id,把它們送進 Get Refund History,讓 Apple 自己的紀錄來判定哪些真正退了款、退了多少。
簡短版
你沒辦法讓 Apple 的估算、Apple 的 financial report、Google 的 earnings report 和你的 webhook 在同一天全都顯示相同的退款合計,你應該放棄這種嘗試。每一個都按它被設計來告訴你的內容去讀。金額上信任 financial report 和 earnings report,存取權限上信任你的伺服器通知,當兩個管道打架時,用 transaction id 把它們關聯起來,讓 Get Refund History 或 Voided Purchases 查詢來打破僵局。核對好的退款不是對上的合計。它們是對上的交易。
常見問題解答
- 為什麼我的 App Store 銷售和 financial report 對不上?
- 它們在不同的時鐘上衡量不同的東西。Sales and Trends 是以 USD 計、採用滾動平均匯率的快速估算,而 Payments and Financial Reports 是按 Apple 的 4-4-5 財務日曆、使用最終匯率的結算記帳紀錄。因為財務月不是日曆月,而且退款的結算比銷售更晚,這兩個合計在設計上就會有差異。凡是涉及金額的事,都用 financial report 來核對。
- 退款在 App Store Summary Sales Report 裡是怎麼顯示的?
- 一筆退款會作為獨立的一行出現,Units 為負、Customer Price 為負。這份報告並沒有把退款抵扣掉,所以退款列是挨著銷售列放的,而不是相互抵銷。透過負數 Units 來識別退款,並把這些列單獨彙總,因為用肉眼去彙總這一欄會數錯你的退款。
- 退款什麼時候會出現在 Google Play 的 earnings report 裡?
- earnings report 每月生成,通常在次月 5 日之前發布。一筆退款會以兩種交易類型出現:Charge refund 表示退還給買家的金額,Google fee refund 表示 Google 退回給你的服務費,每一筆都標註 Full 或 Partial。如果你在 Google 向你付款之前退款,你根本不會收到那筆金額;如果是在付款之後,它會從未來的一次付款中扣除。
- 為什麼我的伺服器顯示的 REFUND 通知比我的銷售報告還多?
- 因為這兩者統計的是不同的時刻。你的伺服器即時聽到退款事件,而銷售報告稍後才記錄結算後的那一行,並且部分退款或重新提交的退款可能產生不止一條通知。要解決這個差異,拿你伺服器看到的那些 transaction id,把它們送進 App Store Server API Get Refund History 端點,它會返回 Apple 自己關於實際退款情況的紀錄。
- 記帳時我應該用哪個退款數字?
- Apple 的 Payments and Financial Reports 和 Google Play 的 earnings report。那些是結算後的、達到記帳級別的紀錄。Apple 的 Sales and Trends 和 Google 的 estimated sales report 是快速分析資料,兩個商店都告訴你不要用於記帳,而你的伺服器通知是用於控制存取的,不是用於認列營收的。
- 退款會和原始銷售出現在同一個月裡嗎?
- 通常不會。在兩個商店裡,退款都按它結算的日期歸屬,而不是原始購買的日期。一筆 3 月的銷售在 4 月退款,會減少你 4 月的合計,所以按標籤比對兩個月會讓退款看上去像是從一個月裡消失、又出現在另一個月裡。改用 transaction id 來比對。
資料來源與延伸閱讀
- Apple: Differences between Sales and Trends and Financial Reports
- Apple: Summary Sales Report reference (refunds as negative units)
- Apple: Download financial reports (fiscal calendar, first Friday)
- Apple: Get Refund History (App Store Server API)
- Google Play Help: Understand your earnings report
- Google Play Help: Manage your app's orders and issue refunds
- Apple Developer Forums: Reconciling finance reports with App Store service state
RefundHalt
App Store 與 Google Play 的退款自動駕駛
繼續閱讀
Google Play 允許你自己發起部分退款,而 App Store 把每一筆退款都交給 Apple 處理
在 Google Play 上,你可以在 Console 中按百分比或按金額退還一筆訂單的一部分,並與 Google 的手續費一起分攤損失。在 App Store 上,你根本無法發起任何退款。以下講清楚部分退款在每家商店如何運作,以及它會讓你付出多少成本。
健康的應用程式退款率落在 2% 到 5% 之間,這篇文章告訴你去哪裡查自己的數字,以及它真正的代價
大多數行動應用程式的退款率落在已付款交易的 2% 到 5% 之間,但 Apple 和 Google 把這個數字放在不同的後台裡。這篇文章告訴你去哪裡查看你的應用程式退款率,依訂閱方案和類別區分的正常水準是多少,以及扣除手續費後,每一筆退款真正花掉你多少錢。