Files
suixinkan_ios_new/suixinkan/Core/Push/PushPayload.swift
汉秋 3dcfb99254 对齐 Android 立即收款页面 UI,并补齐推送状态与语音开关。
统一收款详情布局、设置金额弹窗和收款记录样式,接入 type 6/1 推送驱动与轮询 fallback,使 iOS 收款反馈与 Android 一致。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:17:09 +08:00

128 lines
4.3 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// PushPayload.swift
// suixinkan
//
// Created by Codex on 2026/6/26.
//
import Foundation
/// APNs token Data
enum APNsDeviceToken {
static func hexString(from data: Data) -> String {
data.map { String(format: "%02x", $0) }.joined()
}
}
/// payload extras/data
struct PushPayload: Sendable {
enum Route: Sendable, Equatable {
case payment
case order
case verificationOrder
case task
case queue
case messageCenter
}
private let values: [String: String]
nonisolated init(userInfo: [AnyHashable: Any]) {
var result: [String: String] = [:]
for (key, value) in userInfo {
guard let key = key as? String else { continue }
result[key] = Self.stringValue(value)
if key == "extras" || key == "extra" || key == "data" || key == "JMessageExtra" {
Self.mergeJSON(value, into: &result)
}
}
values = result
}
nonisolated var route: Route {
let typeText = values["type"] ?? ""
let routeText = values["route"] ?? ""
let uriText = values["uri"] ?? ""
let actionText = values["action"] ?? ""
let merged = [typeText, routeText, uriText, actionText].joined(separator: " ").lowercased()
if typeText == "1" || typeText == "6" || merged.contains("payment") || merged.contains("pay") || merged.contains("收款") {
return .payment
}
if merged.contains("queue") || merged.contains("排队") || merged.contains("叫号") || uriText == "/scenic-queue" {
return .queue
}
if merged.contains("verification") || merged.contains("writeoff") || merged.contains("核销") {
return .verificationOrder
}
if merged.contains("order") || merged.contains("订单") {
return .order
}
if merged.contains("task") || merged.contains("任务") {
return .task
}
return .messageCenter
}
/// extras type /
nonisolated var paymentEventType: Int? {
guard let typeText = values["type"], !typeText.isEmpty else { return nil }
return Int(typeText)
}
/// extras data JSON
nonisolated var paymentEventData: String? {
let data = values["data"]?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
return data.isEmpty ? nil : data
}
/// data JSON 使
nonisolated var paymentSuccessAmount: String? {
guard let dataJSON = paymentEventData,
let data = dataJSON.data(using: .utf8),
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
return nil
}
if let amount = json["order_amount"] as? String, !amount.isEmpty {
return amount
}
if let amount = json["order_amount"] as? NSNumber {
return amount.stringValue
}
return nil
}
nonisolated private static func mergeJSON(_ value: Any, into result: inout [String: String]) {
if let dict = value as? [String: Any] {
for (key, value) in dict {
result[key] = stringValue(value)
mergeJSON(value, into: &result)
}
return
}
guard let text = value as? String,
let data = text.data(using: .utf8),
let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
else { return }
for (key, value) in object {
result[key] = stringValue(value)
mergeJSON(value, into: &result)
}
}
nonisolated private static func stringValue(_ value: Any?) -> String {
switch value {
case let string as String:
return string
case let number as NSNumber:
return number.stringValue
case .some(let value):
return "\(value)"
case nil:
return ""
}
}
}