Files
suixinkan_uikit/suixinkan/Features/Payment/Models/PaymentModels.swift
T

208 lines
6.2 KiB
Swift

//
// PaymentModels.swift
// suixinkan
//
import Foundation
/// 收款页展示配置接口响应。
struct PayPageConfigResponse: Decodable, Sendable, Equatable {
let background: String
let logo: String
let title: String
let subtitle: String
init(background: String, logo: String, title: String, subtitle: String) {
self.background = background
self.logo = logo
self.title = title
self.subtitle = subtitle
}
}
/// 收款页最终可展示并可持久化的品牌配置。
struct PayPageConfig: Codable, Sendable, Equatable {
let background: String
let logo: String
let title: String
let subtitle: String
/// 那拉提景区随包默认配置。
static let nalatiDefault = PayPageConfig(
background: "",
logo: "",
title: "那拉提旅拍管理收费平台",
subtitle: "那拉提景区"
)
/// 赛里木湖景区随包默认文案,图片由展示层选择本地资源。
static let sailimuDefault = PayPageConfig(
background: "",
logo: "",
title: "赛里木湖旅拍管理\n收费平台",
subtitle: "赛里木湖景区"
)
/// 将服务端非空有效字段合并到当前可用配置。
func merging(_ response: PayPageConfigResponse) -> PayPageConfig {
PayPageConfig(
background: Self.validRemoteImageURL(response.background) ?? background,
logo: Self.validRemoteImageURL(response.logo) ?? logo,
title: response.title.trimmedNonEmpty ?? title,
subtitle: response.subtitle.trimmedNonEmpty ?? subtitle
)
}
private static func validRemoteImageURL(_ value: String) -> String? {
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
guard let url = URL(string: trimmed),
url.scheme?.lowercased() == "https",
url.host != nil else {
return nil
}
return trimmed
}
}
/// 收款页品牌化景区判定策略。
enum PayPageBrandingPolicy {
/// 那拉提景区正式 ID。
static let nalatiScenicId = 128
/// 赛里木湖景区正式 ID。
static let sailimuScenicId = 125
/// 判断当前景区是否为那拉提。
static func isNalati(scenicId: Int) -> Bool {
scenicId == nalatiScenicId
}
/// 返回支持品牌收款页的景区默认配置;其他景区继续使用普通页面。
static func defaultConfig(scenicId: Int) -> PayPageConfig? {
switch scenicId {
case nalatiScenicId: return .nalatiDefault
case sailimuScenicId: return .sailimuDefault
default: return nil
}
}
}
/// 收款页当前账号信息的展示文本格式化规则。
enum PaymentAccountDisplayFormatter {
/// 解析当前登录摄影师的真实姓名,空值显示占位符。
static func photographerName(realName: String) -> String {
realName.trimmedNonEmpty ?? "-"
}
/// 去除空值与重复项后,合并当前账号的全部店铺名称。
static func storeNames(_ names: [String]) -> String {
var seen = Set<String>()
let resolved = names.compactMap(\.trimmedNonEmpty).filter { seen.insert($0).inserted }
return resolved.isEmpty ? "-" : resolved.joined(separator: "、")
}
}
/// 摄影师收款码响应,包含静态与动态支付 URL。
struct PayCodeResponse: Decodable, Sendable, Equatable {
let staticPayURL: String
let dynamicPayURL: String
enum CodingKeys: String, CodingKey {
case staticPayURL = "static_pay_url"
case dynamicPayURL = "dynamic_pay_url"
}
init(staticPayURL: String, dynamicPayURL: String) {
self.staticPayURL = staticPayURL
self.dynamicPayURL = dynamicPayURL
}
}
/// 收款记录响应,含按日汇总与明细列表。
struct RepaymentCollectionRecordResponse: Decodable, Sendable, Equatable {
let analyse: [RepaymentCollectionRecordAnalyseItem]
let list: [RepaymentCollectionRecordItem]
init(
analyse: [RepaymentCollectionRecordAnalyseItem] = [],
list: [RepaymentCollectionRecordItem] = []
) {
self.analyse = analyse
self.list = list
}
}
/// 收款记录按日汇总项。
struct RepaymentCollectionRecordAnalyseItem: Decodable, Sendable, Equatable, Hashable {
let date: String
let orderCount: Int
let orderAmountSum: String
enum CodingKeys: String, CodingKey {
case date
case orderCount = "order_count"
case orderAmountSum = "order_amount_sum"
}
init(date: String, orderCount: Int, orderAmountSum: String) {
self.date = date
self.orderCount = orderCount
self.orderAmountSum = orderAmountSum
}
}
/// 收款记录明细项。
struct RepaymentCollectionRecordItem: Decodable, Sendable, Equatable, Hashable {
let orderNumber: String
let userPhone: String
let orderAmount: String
let createDate: String
let createTime: String
enum CodingKeys: String, CodingKey {
case orderNumber = "order_number"
case userPhone = "user_phone"
case orderAmount = "order_amount"
case createDate = "create_date"
case createTime = "create_time"
}
init(
orderNumber: String,
userPhone: String,
orderAmount: String,
createDate: String,
createTime: String
) {
self.orderNumber = orderNumber
self.userPhone = userPhone
self.orderAmount = orderAmount
self.createDate = createDate
self.createTime = createTime
}
}
/// 按日分组的收款记录,对齐 Android `RepaymentCollectionRecordGroup`。
struct RepaymentCollectionRecordGroup: Sendable, Equatable, Hashable {
let analyse: RepaymentCollectionRecordAnalyseItem
let items: [RepaymentCollectionRecordItem]
}
/// 收款商户展示信息。
struct PaymentMerchantInfo: Sendable, Equatable {
let name: String
let company: String
static let defaultInfo = PaymentMerchantInfo(
name: "元智享",
company: "扬州元智享网络科技有限公司"
)
}
private extension String {
var trimmedNonEmpty: String? {
let value = trimmingCharacters(in: .whitespacesAndNewlines)
return value.isEmpty ? nil : value
}
}