Commit ffbc6b92c807a5b281bad648885fc9c1e23a9dea

Authored by 权海
1 parent 89245012

feat(ui):调整支付返回值,增加errorCode

... ... @@ -79,20 +79,6 @@ class FlutterError (
val details: Any? = null
) : Throwable()
enum class AppleProductPaymentErrorMsg(val raw: Int) {
MISSING_UUID(0),
PRODUCT_NOT_FOUND(1),
USER_CANCELLED(2),
FAILED_VERIFICATION(3),
UNKNOWN(4);
companion object {
fun ofRaw(raw: Int): AppleProductPaymentErrorMsg? {
return values().firstOrNull { it.raw == raw }
}
}
}
/** Generated class from Pigeon that represents data sent in messages. */
data class AppleSignInModel (
val userId: String,
... ... @@ -193,13 +179,18 @@ data class AppleProductPaymentResult (
val appAccountToken: String? = null,
val originalTransactionId: String? = null,
val transactionId: String? = null,
/**
* success 为空时是支付pending状态,不需要处理
* 只有 true/false时才是支付结果出来的时候
*/
val success: Boolean? = null,
/**
* 错误描述:
* 和AppleProductPaymentErrorMsg匹配的flutter处理,
* 不匹配的则是StoreKit 直接给的错误描述,直接展示即可
* 错误描述, success = false时取用:
* 优先取 errorCode: -1: UUID格式错误, -2: productID查询商品失败,-3:用户取消支付, -4:支付校验失败,-5:未知错误(Apple未知错误)
* errorCode 为空时,取用 errorMessage
*/
val errorMessage: String? = null
val errorMessage: String? = null,
val errorCode: Long? = null
)
{
companion object {
... ... @@ -210,7 +201,8 @@ data class AppleProductPaymentResult (
val transactionId = pigeonVar_list[3] as String?
val success = pigeonVar_list[4] as Boolean?
val errorMessage = pigeonVar_list[5] as String?
return AppleProductPaymentResult(productId, appAccountToken, originalTransactionId, transactionId, success, errorMessage)
val errorCode = pigeonVar_list[6] as Long?
return AppleProductPaymentResult(productId, appAccountToken, originalTransactionId, transactionId, success, errorMessage, errorCode)
}
}
fun toList(): List<Any?> {
... ... @@ -221,6 +213,7 @@ data class AppleProductPaymentResult (
transactionId,
success,
errorMessage,
errorCode,
)
}
override fun equals(other: Any?): Boolean {
... ... @@ -238,21 +231,16 @@ private open class PlatformApiPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
129.toByte() -> {
return (readValue(buffer) as Long?)?.let {
AppleProductPaymentErrorMsg.ofRaw(it.toInt())
}
}
130.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AppleSignInModel.fromList(it)
}
}
131.toByte() -> {
130.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AppleProductInfo.fromList(it)
}
}
132.toByte() -> {
131.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AppleProductPaymentResult.fromList(it)
}
... ... @@ -262,20 +250,16 @@ private open class PlatformApiPigeonCodec : StandardMessageCodec() {
}
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is AppleProductPaymentErrorMsg -> {
stream.write(129)
writeValue(stream, value.raw)
}
is AppleSignInModel -> {
stream.write(130)
stream.write(129)
writeValue(stream, value.toList())
}
is AppleProductInfo -> {
stream.write(131)
stream.write(130)
writeValue(stream, value.toList())
}
is AppleProductPaymentResult -> {
stream.write(132)
stream.write(131)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
... ...
... ... @@ -3,15 +3,15 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 77;
objects = {
/* Begin PBXBuildFile section */
0798E27DB95F2A823881D75A /* Pods_Runner_Watch_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A488EFC0BD642ED604C4E43 /* Pods_Runner_Watch_App.framework */; };
20A3C4994C9B0F60D1F3BCBE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8DC48B3736B7FEB548D0E65 /* Pods_Runner.framework */; };
66FB19002FDBC80100F515B4 /* DFWatchFigmaTokens.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19032FDBC80100F515B4 /* DFWatchFigmaTokens.swift */; };
66FB19012FDBC80100F515B4 /* DFWatchFigmaHomeViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19042FDBC80100F515B4 /* DFWatchFigmaHomeViews.swift */; };
66FB19022FDBC80100F515B4 /* DFWatchFigmaDetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19052FDBC80100F515B4 /* DFWatchFigmaDetailViews.swift */; };
66FB19002FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19032FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift */; };
66FB19012FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19042FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift */; };
66FB19022FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19052FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift */; };
66FBE58C2FDA4F0F00F515B4 /* Runner Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 66FBE58B2FDA4F0F00F515B4 /* Runner Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
... ... @@ -54,9 +54,9 @@
27E4D5A8995AB1EC91E7330E /* Pods-Runner Watch App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner Watch App.debug.xcconfig"; path = "Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App.debug.xcconfig"; sourceTree = "<group>"; };
4A9B7C102FDB0A1200F515B4 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
4A9B7C112FDB0A1200F515B4 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
66FB19032FDBC80100F515B4 /* DFWatchFigmaTokens.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift"; sourceTree = "<group>"; };
66FB19042FDBC80100F515B4 /* DFWatchFigmaHomeViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift"; sourceTree = "<group>"; };
66FB19052FDBC80100F515B4 /* DFWatchFigmaDetailViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift"; sourceTree = "<group>"; };
66FB19032FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift"; sourceTree = "<group>"; };
66FB19042FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift"; sourceTree = "<group>"; };
66FB19052FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift"; sourceTree = "<group>"; };
66FBE57E2FDA4F0E00F515B4 /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
66FBE58B2FDA4F0F00F515B4 /* Runner Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Runner Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
66FBE5A72FDA518C00F515B4 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
... ... @@ -97,8 +97,6 @@
};
66FBE58F2FDA4F0F00F515B4 /* Runner Watch App */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
);
path = "Runner Watch App";
sourceTree = "<group>";
};
... ... @@ -136,9 +134,9 @@
66FB19072FDBC80100F515B4 /* FigmaHome Preview Sources */ = {
isa = PBXGroup;
children = (
66FB19052FDBC80100F515B4 /* DFWatchFigmaDetailViews.swift */,
66FB19042FDBC80100F515B4 /* DFWatchFigmaHomeViews.swift */,
66FB19032FDBC80100F515B4 /* DFWatchFigmaTokens.swift */,
66FB19052FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift */,
66FB19042FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift */,
66FB19032FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift */,
);
name = "FigmaHome Preview Sources";
sourceTree = "<group>";
... ... @@ -305,10 +303,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
... ... @@ -379,10 +381,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
... ... @@ -396,10 +402,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks.sh\"\n";
... ... @@ -441,9 +451,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
66FB19022FDBC80100F515B4 /* DFWatchFigmaDetailViews.swift in Sources */,
66FB19012FDBC80100F515B4 /* DFWatchFigmaHomeViews.swift in Sources */,
66FB19002FDBC80100F515B4 /* DFWatchFigmaTokens.swift in Sources */,
66FB19022FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift in Sources */,
66FB19012FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift in Sources */,
66FB19002FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
... ...
... ... @@ -112,14 +112,6 @@ func deepHashPlatformApi(value: Any?, hasher: inout Hasher) {
enum AppleProductPaymentErrorMsg: Int {
case missingUUID = 0
case productNotFound = 1
case userCancelled = 2
case failedVerification = 3
case unknown = 4
}
/// Generated class from Pigeon that represents data sent in messages.
struct AppleSignInModel: Hashable {
var userId: String
... ... @@ -224,11 +216,14 @@ struct AppleProductPaymentResult: Hashable {
var appAccountToken: String? = nil
var originalTransactionId: String? = nil
var transactionId: String? = nil
/// success 为空时是支付pending状态,不需要处理
/// 只有 true/false时才是支付结果出来的时候
var success: Bool? = nil
/// 错误描述:
/// 和AppleProductPaymentErrorMsg匹配的flutter处理,
/// 不匹配的则是StoreKit 直接给的错误描述,直接展示即可
/// 错误描述, success = false时取用:
/// 优先取 errorCode: -1: UUID格式错误, -2: productID查询商品失败,-3:用户取消支付, -4:支付校验失败,-5:未知错误(Apple未知错误)
/// errorCode 为空时,取用 errorMessage
var errorMessage: String? = nil
var errorCode: Int64? = nil
// swift-format-ignore: AlwaysUseLowerCamelCase
... ... @@ -239,6 +234,7 @@ struct AppleProductPaymentResult: Hashable {
let transactionId: String? = nilOrValue(pigeonVar_list[3])
let success: Bool? = nilOrValue(pigeonVar_list[4])
let errorMessage: String? = nilOrValue(pigeonVar_list[5])
let errorCode: Int64? = nilOrValue(pigeonVar_list[6])
return AppleProductPaymentResult(
productId: productId,
... ... @@ -246,7 +242,8 @@ struct AppleProductPaymentResult: Hashable {
originalTransactionId: originalTransactionId,
transactionId: transactionId,
success: success,
errorMessage: errorMessage
errorMessage: errorMessage,
errorCode: errorCode
)
}
func toList() -> [Any?] {
... ... @@ -257,6 +254,7 @@ struct AppleProductPaymentResult: Hashable {
transactionId,
success,
errorMessage,
errorCode,
]
}
static func == (lhs: AppleProductPaymentResult, rhs: AppleProductPaymentResult) -> Bool {
... ... @@ -270,16 +268,10 @@ private class PlatformApiPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 129:
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
if let enumResultAsInt = enumResultAsInt {
return AppleProductPaymentErrorMsg(rawValue: enumResultAsInt)
}
return nil
case 130:
return AppleSignInModel.fromList(self.readValue() as! [Any?])
case 131:
case 130:
return AppleProductInfo.fromList(self.readValue() as! [Any?])
case 132:
case 131:
return AppleProductPaymentResult.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
... ... @@ -289,17 +281,14 @@ private class PlatformApiPigeonCodecReader: FlutterStandardReader {
private class PlatformApiPigeonCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? AppleProductPaymentErrorMsg {
if let value = value as? AppleSignInModel {
super.writeByte(129)
super.writeValue(value.rawValue)
} else if let value = value as? AppleSignInModel {
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? AppleProductInfo {
super.writeByte(131)
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? AppleProductPaymentResult {
super.writeByte(132)
super.writeByte(131)
super.writeValue(value.toList())
} else {
super.writeValue(value)
... ...
... ... @@ -72,7 +72,7 @@ final class PlatformHostApiImpl: PlatformHostApi {
displayPrice = offer.displayPrice
}
let unitPrice = price/Decimal(baseUnit)
let unitPrice = originPrice/Decimal(baseUnit)
let currencyCode = product.priceFormatStyle.currencyCode
let productInfo = AppleProductInfo(
... ...
... ... @@ -9,6 +9,14 @@ import Foundation
import StoreKit
enum AppleProductPaymentErrorMsg: Int64 {
case missingUUID = -1
case productNotFound = -2
case userCancelled = -3
case failedVerification = -4
case unknown = -5
}
enum StoreKitError: Error, LocalizedError {
case productNotFound
case failedVerification
... ... @@ -46,7 +54,7 @@ class ApplePayment {
return paymentResult(
productId: productId,
success: false,
errorMessage: String(describing: AppleProductPaymentErrorMsg.missingUUID)
errorCode: AppleProductPaymentErrorMsg.missingUUID.rawValue
)
}
let appleProduct = try await requestProducts(productId)
... ... @@ -78,26 +86,24 @@ class ApplePayment {
originalTransactionId: String(transaction.originalID),
transactionId: String(transaction.id),
success: false,
errorMessage: String(describing: AppleProductPaymentErrorMsg.unknown)
errorCode: AppleProductPaymentErrorMsg.failedVerification.rawValue
)
}
case .userCancelled:
return paymentResult(
productId: productId,
success: false,
errorMessage: String(describing: AppleProductPaymentErrorMsg.userCancelled)
errorCode: AppleProductPaymentErrorMsg.userCancelled.rawValue
)
case .pending:
return paymentResult(
productId: productId,
success: false,
errorMessage: String(describing: AppleProductPaymentErrorMsg.unknown)
productId: productId
)
@unknown default:
return paymentResult(
productId: productId,
success: false,
errorMessage: String(describing: AppleProductPaymentErrorMsg.unknown)
errorCode: AppleProductPaymentErrorMsg.unknown.rawValue
)
}
} catch {
... ... @@ -272,8 +278,9 @@ class ApplePayment {
appAccountToken: String? = nil,
originalTransactionId: String? = nil,
transactionId: String? = nil,
success: Bool?,
errorMessage: String? = nil
success: Bool? = nil,
errorMessage: String? = nil,
errorCode: Int64? = nil,
) -> AppleProductPaymentResult {
AppleProductPaymentResult(
productId: productId,
... ... @@ -281,7 +288,8 @@ class ApplePayment {
originalTransactionId: originalTransactionId,
transactionId: transactionId,
success: success,
errorMessage: errorMessage
errorMessage: errorMessage,
errorCode: errorCode
)
}
... ...
... ... @@ -30,14 +30,6 @@ bool _deepEquals(Object? a, Object? b) {
}
enum AppleProductPaymentErrorMsg {
missingUUID,
productNotFound,
userCancelled,
failedVerification,
unknown,
}
class AppleSignInModel {
AppleSignInModel({
required this.userId,
... ... @@ -186,6 +178,7 @@ class AppleProductPaymentResult {
this.transactionId,
this.success,
this.errorMessage,
this.errorCode,
});
String productId;
... ... @@ -196,13 +189,17 @@ class AppleProductPaymentResult {
String? transactionId;
/// success 为空时是支付pending状态,不需要处理
/// 只有 true/false时才是支付结果出来的时候
bool? success;
/// 错误描述:
/// 和AppleProductPaymentErrorMsg匹配的flutter处理,
/// 不匹配的则是StoreKit 直接给的错误描述,直接展示即可
/// 错误描述, success = false时取用:
/// 优先取 errorCode: -1: UUID格式错误, -2: productID查询商品失败,-3:用户取消支付, -4:支付校验失败,-5:未知错误(Apple未知错误)
/// errorCode 为空时,取用 errorMessage
String? errorMessage;
int? errorCode;
List<Object?> _toList() {
return <Object?>[
productId,
... ... @@ -211,6 +208,7 @@ class AppleProductPaymentResult {
transactionId,
success,
errorMessage,
errorCode,
];
}
... ... @@ -226,6 +224,7 @@ class AppleProductPaymentResult {
transactionId: result[3] as String?,
success: result[4] as bool?,
errorMessage: result[5] as String?,
errorCode: result[6] as int?,
);
}
... ... @@ -255,17 +254,14 @@ class _PigeonCodec extends StandardMessageCodec {
if (value is int) {
buffer.putUint8(4);
buffer.putInt64(value);
} else if (value is AppleProductPaymentErrorMsg) {
buffer.putUint8(129);
writeValue(buffer, value.index);
} else if (value is AppleSignInModel) {
buffer.putUint8(130);
buffer.putUint8(129);
writeValue(buffer, value.encode());
} else if (value is AppleProductInfo) {
buffer.putUint8(131);
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is AppleProductPaymentResult) {
buffer.putUint8(132);
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
... ... @@ -276,13 +272,10 @@ class _PigeonCodec extends StandardMessageCodec {
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 129:
final int? value = readValue(buffer) as int?;
return value == null ? null : AppleProductPaymentErrorMsg.values[value];
case 130:
return AppleSignInModel.decode(readValue(buffer)!);
case 131:
case 130:
return AppleProductInfo.decode(readValue(buffer)!);
case 132:
case 131:
return AppleProductPaymentResult.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
... ...
... ... @@ -50,25 +50,20 @@ class AppleProductInfo {
});
}
enum AppleProductPaymentErrorMsg {
missingUUID,
productNotFound,
userCancelled,
failedVerification,
unknown,
}
class AppleProductPaymentResult {
final String productId;
final String? appAccountToken;
final String? originalTransactionId;
final String? transactionId;
/// success 为空时是支付pending状态,不需要处理
/// 只有 true/false时才是支付结果出来的时候
final bool? success;
/// 错误描述:
/// 和AppleProductPaymentErrorMsg匹配的flutter处理,
/// 不匹配的则是StoreKit 直接给的错误描述,直接展示即可
/// 错误描述, success = false时取用:
/// 优先取 errorCode: -1: UUID格式错误, -2: productID查询商品失败,-3:用户取消支付, -4:支付校验失败,-5:未知错误(Apple未知错误)
/// errorCode 为空时,取用 errorMessage
final String? errorMessage;
final int? errorCode;
AppleProductPaymentResult({
required this.productId,
... ... @@ -77,6 +72,7 @@ class AppleProductPaymentResult {
this.transactionId,
this.success,
this.errorMessage,
this.errorCode,
});
}
... ...