アプリ内課金のレシート情報をCodableでパースして色々チェックしていたが、上手く動作しないパターンがあったのでメモ。
動作しなかったのは、Non-ConsumableとAuto-renewable subscriptionsのレシートが含まれている復元処理。
下記のような感じで定義していたら、パースできないエラーメッセージに遭遇。
///
/// ReceiptDetail
///
struct ReceiptDetail: Codable {
let receipt_type: String
let adam_id: Int
let app_item_id: Int
let bundle_id: String
let application_version: String
let download_id: Int
let version_external_identifier: Int
let receipt_creation_date: String
let receipt_creation_date_ms: String
let receipt_creation_date_pst: String
let request_date: String
let request_date_ms: String
let request_date_pst: String
let original_purchase_date: String
let original_purchase_date_ms: String
let original_purchase_date_pst: String
let original_application_version: String
let in_app: [ReceiptInfo]
}
///
/// ReceiptInfo
///
struct ReceiptInfo: Codable {
let quantity: String
let product_id: String
let transaction_id: String
let original_transaction_id: String
let purchase_date: String
let purchase_date_ms: String
let purchase_date_pst: String
let original_purchase_date: String
let original_purchase_date_ms: String
let original_purchase_date_pst: String
let expires_date: String
let expires_date_ms: String
let expires_date_pst: String
let web_order_line_item_id: String
let is_trial_period: String
}
パースする前のJSONをログに出力して確認したら、in-appに含まれる情報に差異があった。
///
/// ReceiptInfo - Auto-renewable subscriptions
///
struct ReceiptInfo: Codable {
let quantity: String
let product_id: String
let transaction_id: String
let original_transaction_id: String
let purchase_date: String
let purchase_date_ms: String
let purchase_date_pst: String
let original_purchase_date: String
let original_purchase_date_ms: String
let original_purchase_date_pst: String
let expires_date: String
let expires_date_ms: String
let expires_date_pst: String
let web_order_line_item_id: String
let is_trial_period: String
}
///
/// ReceiptInfo - Non-Consumable
///
struct ReceiptInfo: Codable {
let quantity: String
let product_id: String
let transaction_id: String
let original_transaction_id: String
let purchase_date: String
let purchase_date_ms: String
let purchase_date_pst: String
let original_purchase_date: String
let original_purchase_date_ms: String
let original_purchase_date_pst: String
let is_trial_period: String
}
と言う感じで、有効期限関連の情報が存在しなかった。
let expires_date: String
let expires_date_ms: String
let expires_date_pst: String
let web_order_line_item_id: String
と言うことで、下記の定義でAuto-renewable subscriptionsとNon-Consumableのパースをする必要があるので注意。
///
/// ReceiptInfo
///
struct ReceiptInfo: Codable {
let quantity: String
let product_id: String
let transaction_id: String
let original_transaction_id: String
let purchase_date: String
let purchase_date_ms: String
let purchase_date_pst: String
let original_purchase_date: String
let original_purchase_date_ms: String
let original_purchase_date_pst: String
var expires_date: String? /// Non-Consumable には存在しない
var expires_date_ms: String? /// Non-Consumable には存在しない
var expires_date_pst: String? /// Non-Consumable には存在しない
var web_order_line_item_id: String? /// Non-Consumable には存在しない
let is_trial_period: String
}
今後、Auto-renewable subscriptionsのレシートをCodableでパースしてみようと思う人も増えそうなので、もしパースでエラーになるのであれば、一度in-appの情報をご確認いただければと思います。
ちなみに、Non-Consumableの場合はnilになりますので、guard letやif letで判定も出来ると思います。
追記
一回もAuto-renewable subscriptionsを購入していない場合は下記もJSONに含まれなかったので注意してください。
latest_receipt_info
latest_receipt
なので全体の定義を以下のようにして無事解決しました。
struct Receipt: Codable {
let status: Int
let environment: String
let receipt: ReceiptDetail
var latest_receipt_info: [ReceiptInfo]?
var latest_receipt: String?