@tinkerlandai/longplay-react-native 0.10.18 → 0.10.19-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +61365 -32414
- package/dist/index.d.ts +61365 -32414
- package/dist/index.js +2 -2
- package/native-sdk/android/assets/indiana/index.html +33 -33
- package/native-sdk/android/java/ai/tinkerland/indiana/MerchantCommerceSemantics.kt +65 -2
- package/native-sdk/android/java/ai/tinkerland/indiana/SDKVersion.kt +1 -1
- package/native-sdk/android/resources/funnel-wire-schemas.json +1 -1
- package/native-sdk/ios/MerchantCommerceSemantics.swift +72 -1
- package/native-sdk/ios/SDKVersion.swift +1 -1
- package/native-sdk/ios/WebView/index.html +33 -33
- package/native-sdk/ios/funnel-wire-schemas.json +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
+
import CryptoKit
|
|
3
|
+
import CoreFoundation
|
|
2
4
|
|
|
3
5
|
/// Merchant refinements dispatch on generated DTO fields, not user JSON.
|
|
4
6
|
enum IndianaMerchantCommerceSemantics {
|
|
@@ -8,6 +10,13 @@ enum IndianaMerchantCommerceSemantics {
|
|
|
8
10
|
let o = IndianaCustomerResponseSemantics.o, a = IndianaCustomerResponseSemantics.a
|
|
9
11
|
let s = IndianaCustomerResponseSemantics.s, n = IndianaCustomerResponseSemantics.n
|
|
10
12
|
let nilValue = IndianaCustomerResponseSemantics.nilValue
|
|
13
|
+
if has(["merchantTerms", "operationId", "currency"]), let terms = v["merchantTerms"] as? [String: Any] {
|
|
14
|
+
let action = has(["provider", "lines"]) ? "purchase" : has(["revokes"]) ? "refund" : "subscription_change"
|
|
15
|
+
let provider = s(v["provider"] ?? o(v["execution"])["provider"]), request = o(terms["request"])
|
|
16
|
+
try require(provider == "merchant" && s(request["operationId"]) == s(v["operationId"]) && s(request["action"]) == action && s(terms["currency"]) == s(v["currency"]))
|
|
17
|
+
}
|
|
18
|
+
if has(["merchantQuoteId", "requestDigest", "quoteTermsDigest", "request"]) { try prepared(v) }
|
|
19
|
+
if has(["reference", "kind", "description", "quantity", "unit"]) { try require(nilValue(v["quantity"]) == nilValue(v["unit"])) }
|
|
11
20
|
if has(["configurationRevision", "connectionRevision", "lineItems", "catalogAmountMinor", "discount"]) {
|
|
12
21
|
let lines = a(v["lineItems"]), discount = o(v["discount"])
|
|
13
22
|
try require(lines.reduce(0) { $0 + n($1["totalMinor"]) } == n(v["catalogAmountMinor"]) && (discount.isEmpty || n(discount["amountMinor"]) <= n(v["catalogAmountMinor"])) && Set(lines.map { s($0["priceId"]) }).count == lines.count)
|
|
@@ -27,6 +36,10 @@ enum IndianaMerchantCommerceSemantics {
|
|
|
27
36
|
}
|
|
28
37
|
if has(["scope", "operationId", "customerId", "confirmedAt", "initialExecutionAllowed", "instruction"]) {
|
|
29
38
|
let instruction = o(v["instruction"])
|
|
39
|
+
if let terms = v["merchantTerms"] as? [String: Any] {
|
|
40
|
+
let request = o(terms["request"]), subject = o(o(terms["request"])["subject"])
|
|
41
|
+
try require(s(request["operationId"]) == s(v["operationId"]) && s(subject["customerId"]) == s(v["customerId"]) && canonical(o(subject["scope"])) == canonical(o(v["scope"])) && s(request["action"]) == s(instruction["type"]) && s(terms["currency"]) == s(instruction["currency"]))
|
|
42
|
+
}
|
|
30
43
|
try require(s(instruction["operationId"]) == s(v["operationId"]) && s(instruction["customerId"]) == s(v["customerId"]))
|
|
31
44
|
}
|
|
32
45
|
if has(["merchantSubscriptionId", "periodStartsAt", "periodEndsAt", "items"]) {
|
|
@@ -41,11 +54,69 @@ enum IndianaMerchantCommerceSemantics {
|
|
|
41
54
|
try require(Set(lines.map { s($0["merchantLineId"]) }).count == lines.count)
|
|
42
55
|
for key in ["subtotalMinor", "discountMinor", "taxMinor", "totalMinor"] { try require(lines.reduce(0) { $0 + n($1[key]) } == n(v[key])) }
|
|
43
56
|
}
|
|
44
|
-
if has(["merchantLineId", "subtotalMinor", "discountMinor", "taxMinor", "totalMinor"]) {
|
|
57
|
+
if has(["merchantPriceId", "merchantLineId", "subtotalMinor", "discountMinor", "taxMinor", "totalMinor"]) { try quoteLine(v) }
|
|
58
|
+
else if has(["merchantLineId", "subtotalMinor", "discountMinor", "taxMinor", "totalMinor"]) {
|
|
45
59
|
let subtotal = n(v["subtotalMinor"]), discount = n(v["discountMinor"]), tax = n(v["taxMinor"])
|
|
46
60
|
try require(subtotal - discount + tax == n(v["totalMinor"]) && (subtotal < 0 ? discount == 0 && tax == 0 : discount <= subtotal))
|
|
47
61
|
}
|
|
48
62
|
if has(["provider", "eventId", "merchantOrderId", "paymentStatus", "invoice"]), s(v["paymentStatus"]) == "paid" { try require(!nilValue(v["invoice"])) }
|
|
49
63
|
if has(["provider", "merchantInvoiceId", "cancelSubscriptions", "entitlementAction", "amountMinor"]) || has(["provider", "eventId", "merchantRefundId", "amountMinor", "status"]) { try require(n(v["amountMinor"]) > 0) }
|
|
50
64
|
}
|
|
65
|
+
private static func canonical(_ value: Any) -> String {
|
|
66
|
+
if value is NSNull { return "null" }
|
|
67
|
+
if let object = value as? [String: Any] {
|
|
68
|
+
return "{" + object.keys.sorted { $0.utf16.lexicographicallyPrecedes($1.utf16) }.map { canonical($0) + ":" + canonical(object[$0]!) }.joined(separator: ",") + "}"
|
|
69
|
+
}
|
|
70
|
+
if let array = value as? [Any] { return "[" + array.map(canonical).joined(separator: ",") + "]" }
|
|
71
|
+
if let text = value as? String {
|
|
72
|
+
var result = "\""
|
|
73
|
+
for scalar in text.unicodeScalars {
|
|
74
|
+
switch scalar.value {
|
|
75
|
+
case 34: result += "\\\""
|
|
76
|
+
case 92: result += "\\\\"
|
|
77
|
+
case 8: result += "\\b"
|
|
78
|
+
case 12: result += "\\f"
|
|
79
|
+
case 10: result += "\\n"
|
|
80
|
+
case 13: result += "\\r"
|
|
81
|
+
case 9: result += "\\t"
|
|
82
|
+
case 0..<32: result += String(format: "\\u%04x", scalar.value)
|
|
83
|
+
default: result.unicodeScalars.append(scalar)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return result + "\""
|
|
87
|
+
}
|
|
88
|
+
if let number = value as? NSNumber {
|
|
89
|
+
if CFGetTypeID(number) == CFBooleanGetTypeID() { return number.boolValue ? "true" : "false" }
|
|
90
|
+
return number.stringValue.contains(".") ? String(number.int64Value) : number.stringValue
|
|
91
|
+
}
|
|
92
|
+
return ""
|
|
93
|
+
}
|
|
94
|
+
private static func digest(_ value: Any) -> String {
|
|
95
|
+
SHA256.hash(data: Data(canonical(value).utf8)).map { String(format: "%02x", $0) }.joined()
|
|
96
|
+
}
|
|
97
|
+
private static func quoteLine(_ v: [String: Any]) throws {
|
|
98
|
+
let nilValue = IndianaCustomerResponseSemantics.nilValue, n = IndianaCustomerResponseSemantics.n
|
|
99
|
+
try IndianaCustomerResponseSemantics.require(nilValue(v["taxMinor"]) == nilValue(v["totalMinor"]) && (nilValue(v["totalMinor"]) || n(v["totalMinor"]) == n(v["subtotalMinor"]) - n(v["discountMinor"]) + n(v["taxMinor"])))
|
|
100
|
+
}
|
|
101
|
+
private static func prepared(_ v: [String: Any]) throws {
|
|
102
|
+
let require = IndianaCustomerResponseSemantics.require, o = IndianaCustomerResponseSemantics.o, a = IndianaCustomerResponseSemantics.a
|
|
103
|
+
let s = IndianaCustomerResponseSemantics.s, n = IndianaCustomerResponseSemantics.n, nilValue = IndianaCustomerResponseSemantics.nilValue, time = IndianaCustomerResponseSemantics.time
|
|
104
|
+
let request = o(v["request"]), action = s(o(v["request"])["action"]), recurring = !nilValue(v["subscriptionTerms"])
|
|
105
|
+
var unsigned = v; unsigned.removeValue(forKey: "quoteTermsDigest")
|
|
106
|
+
try require(s(v["requestDigest"]) == digest(request) && s(v["quoteTermsDigest"]) == digest(unsigned) && s(v["currency"]) == s(request["currency"]))
|
|
107
|
+
try require(time(v["observedAt"]) < time(v["expiresAt"]) && time(v["expiresAt"]) <= time(request["expiresAt"]))
|
|
108
|
+
try require(action != "purchase" || (s(request["mode"]) == "subscription") == recurring)
|
|
109
|
+
try require(!recurring || !(action == "refund" || action == "subscription_change" && s(o(request["change"])["type"]) == "cancel"))
|
|
110
|
+
let lines = a(v["lines"]), subtotal = a(v["lines"]).reduce(Decimal(0)) { $0 + n($1["subtotalMinor"]) }, discount = a(v["lines"]).reduce(Decimal(0)) { $0 + n($1["discountMinor"]) }
|
|
111
|
+
for line in lines { try quoteLine(line) }
|
|
112
|
+
for (rows, field) in [(lines, "merchantLineId"), (a(v["sourceRevisions"]), "reference"), (a(v["requiredConsents"]), "reference")] { try require(Set(rows.map { s($0[field]) }).count == rows.count) }
|
|
113
|
+
let known = lines.allSatisfy { !nilValue($0["taxMinor"]) }, tax = lines.reduce(Decimal(0)) { $0 + n($1["taxMinor"]) }
|
|
114
|
+
try require(subtotal == n(v["subtotalMinor"]) && discount == n(v["discountMinor"]) && !nilValue(v["taxMinor"]) == known && nilValue(v["taxMinor"]) == nilValue(v["totalMinor"]))
|
|
115
|
+
try require(known ? tax == n(v["taxMinor"]) && n(v["totalMinor"]) == subtotal - discount + tax : v["automaticTax"] as? Bool == true)
|
|
116
|
+
try require(!lines.isEmpty || action == "subscription_change" && subtotal == 0 && discount == 0 && tax == 0 && !nilValue(v["totalMinor"]) && n(v["totalMinor"]) == 0)
|
|
117
|
+
try require(action == "subscription_change" || subtotal >= 0 && (nilValue(v["totalMinor"]) || n(v["totalMinor"]) >= 0))
|
|
118
|
+
if action == "refund" { try require((s(request["mode"]) == "partial") == (request["amountMinor"] != nil) && known && n(v["totalMinor"]) > 0 && (s(request["mode"]) != "partial" || n(v["totalMinor"]) == n(request["amountMinor"]))) }
|
|
119
|
+
for effect in a(v["expectedEffects"]) { try require(nilValue(effect["quantity"]) == nilValue(effect["unit"])) }
|
|
120
|
+
}
|
|
121
|
+
|
|
51
122
|
}
|