Skip to content

Commit 5b3b5f9

Browse files
authored
Merge pull request #285 from qonversion/kamo/dev-343-purchase-with-transaction-info
2 parents 1de97bd + a80f29b commit 5b3b5f9

18 files changed

Lines changed: 345 additions & 131 deletions

Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public static synchronized void purchase(
132132
TypeReference<List<String>> typeRef = new TypeReference<List<String>>() {};
133133
contextKeysList = mapper.readValue(contextKeys, typeRef);
134134
}
135-
qonversionSandwich.purchase(
135+
qonversionSandwich.purchaseWithResult(
136136
productId,
137137
offerId,
138138
applyOffer,
@@ -146,17 +146,6 @@ public static synchronized void purchase(
146146
}
147147
}
148148

149-
public static synchronized void updatePurchase(
150-
String productId,
151-
@Nullable String offerId,
152-
boolean applyOffer,
153-
String oldProductId,
154-
@Nullable String updatePolicyKey,
155-
String unityCallbackName
156-
) {
157-
purchase(productId, offerId, applyOffer, oldProductId, updatePolicyKey, null, unityCallbackName);
158-
}
159-
160149
public static synchronized void restore(String unityCallbackName) {
161150
qonversionSandwich.restore(getResultListener(unityCallbackName));
162151
}

Runtime/Android/QonversionWrapperAndroid.cs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -131,41 +131,11 @@ public void Purchase(string productId, PurchaseOptions purchaseOptions, string c
131131
);
132132
}
133133

134-
public void Purchase(PurchaseModel purchaseModel, string callbackName)
135-
{
136-
CallQonversion(
137-
"purchase",
138-
purchaseModel.ProductId,
139-
purchaseModel.OfferId,
140-
purchaseModel.ApplyOffer,
141-
null,
142-
null,
143-
null,
144-
callbackName
145-
);
146-
}
147-
148134
public void Restore(string callbackName)
149135
{
150136
CallQonversion("restore", callbackName);
151137
}
152138

153-
public void UpdatePurchase(PurchaseUpdateModel purchaseUpdateModel, string callbackName) {
154-
var updatePolicyKey = purchaseUpdateModel.UpdatePolicy == null
155-
? null
156-
: Enum.GetName(typeof(PurchaseUpdatePolicy), purchaseUpdateModel.UpdatePolicy);
157-
158-
CallQonversion(
159-
"updatePurchase",
160-
purchaseUpdateModel.ProductId,
161-
purchaseUpdateModel.OfferId,
162-
purchaseUpdateModel.ApplyOffer,
163-
purchaseUpdateModel.OldProductId,
164-
updatePolicyKey,
165-
callbackName
166-
);
167-
}
168-
169139
public void Products(string callbackName)
170140
{
171141
CallQonversion("products", callbackName);
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
using System.Collections.Generic;
2+
using JetBrains.Annotations;
3+
using UnityEngine.Scripting;
4+
5+
namespace QonversionUnity
6+
{
7+
/// <summary>
8+
/// Represents the result of a purchase operation.
9+
/// Contains the status of the purchase, entitlements, and store transaction details.
10+
/// </summary>
11+
public class PurchaseResult
12+
{
13+
/// <summary>
14+
/// The status of the purchase operation.
15+
/// </summary>
16+
public readonly PurchaseResultStatus Status;
17+
18+
/// <summary>
19+
/// The user's entitlements after the purchase.
20+
/// May be null if the purchase failed or is pending.
21+
/// </summary>
22+
[CanBeNull] public readonly Dictionary<string, Entitlement> Entitlements;
23+
24+
/// <summary>
25+
/// The error that occurred during the purchase, if any.
26+
/// </summary>
27+
[CanBeNull] public readonly QonversionError Error;
28+
29+
/// <summary>
30+
/// Indicates whether the entitlements were generated from a fallback source.
31+
/// </summary>
32+
public readonly bool IsFallbackGenerated;
33+
34+
/// <summary>
35+
/// The source of the purchase result data.
36+
/// </summary>
37+
public readonly PurchaseResultSource Source;
38+
39+
/// <summary>
40+
/// The store transaction details from the native platform.
41+
/// Contains raw transaction information from Apple App Store or Google Play Store.
42+
/// </summary>
43+
[CanBeNull] public readonly StoreTransaction StoreTransaction;
44+
45+
[Preserve]
46+
public PurchaseResult(Dictionary<string, object> dict)
47+
{
48+
if (dict.TryGetValue("status", out object value))
49+
{
50+
Status = FormatStatus(value as string);
51+
}
52+
else
53+
{
54+
Status = PurchaseResultStatus.Unknown;
55+
}
56+
57+
if (dict.TryGetValue("entitlements", out value) && value is Dictionary<string, object> entitlementsDict)
58+
{
59+
Entitlements = new Dictionary<string, Entitlement>();
60+
foreach (var pair in entitlementsDict)
61+
{
62+
if (pair.Value is Dictionary<string, object> entitlementDict)
63+
{
64+
Entitlements[pair.Key] = new Entitlement(entitlementDict);
65+
}
66+
}
67+
}
68+
69+
if (dict.TryGetValue("error", out value) && value is Dictionary<string, object> errorDict)
70+
{
71+
Error = new QonversionError(errorDict);
72+
}
73+
74+
if (dict.TryGetValue("isFallbackGenerated", out value) && value != null)
75+
{
76+
IsFallbackGenerated = (bool)value;
77+
}
78+
79+
if (dict.TryGetValue("source", out value))
80+
{
81+
Source = FormatSource(value as string);
82+
}
83+
else
84+
{
85+
Source = PurchaseResultSource.Unknown;
86+
}
87+
88+
if (dict.TryGetValue("storeTransaction", out value) && value is Dictionary<string, object> transactionDict)
89+
{
90+
StoreTransaction = new StoreTransaction(transactionDict);
91+
}
92+
}
93+
94+
/// <summary>
95+
/// Returns true if the purchase was successful.
96+
/// </summary>
97+
public bool IsSuccess => Status == PurchaseResultStatus.Success;
98+
99+
/// <summary>
100+
/// Returns true if the purchase was canceled by the user.
101+
/// </summary>
102+
public bool IsCanceled => Status == PurchaseResultStatus.UserCanceled;
103+
104+
/// <summary>
105+
/// Returns true if the purchase is pending.
106+
/// </summary>
107+
public bool IsPending => Status == PurchaseResultStatus.Pending;
108+
109+
/// <summary>
110+
/// Returns true if an error occurred during the purchase.
111+
/// </summary>
112+
public bool IsError => Status == PurchaseResultStatus.Error;
113+
114+
public override string ToString()
115+
{
116+
return $"{nameof(Status)}: {Status}, " +
117+
$"{nameof(Entitlements)}: {Entitlements?.Count ?? 0} items, " +
118+
$"{nameof(Error)}: {Error}, " +
119+
$"{nameof(IsFallbackGenerated)}: {IsFallbackGenerated}, " +
120+
$"{nameof(Source)}: {Source}, " +
121+
$"{nameof(StoreTransaction)}: {StoreTransaction}";
122+
}
123+
124+
private static PurchaseResultStatus FormatStatus(string value)
125+
{
126+
switch (value)
127+
{
128+
case "Success":
129+
return PurchaseResultStatus.Success;
130+
case "UserCanceled":
131+
return PurchaseResultStatus.UserCanceled;
132+
case "Pending":
133+
return PurchaseResultStatus.Pending;
134+
case "Error":
135+
return PurchaseResultStatus.Error;
136+
default:
137+
return PurchaseResultStatus.Unknown;
138+
}
139+
}
140+
141+
private static PurchaseResultSource FormatSource(string value)
142+
{
143+
switch (value)
144+
{
145+
case "Api":
146+
return PurchaseResultSource.Api;
147+
case "Local":
148+
return PurchaseResultSource.Local;
149+
default:
150+
return PurchaseResultSource.Unknown;
151+
}
152+
}
153+
}
154+
}

Runtime/Scripts/Dto/PurchaseResult.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace QonversionUnity
2+
{
3+
/// <summary>
4+
/// Source of the purchase result data.
5+
/// </summary>
6+
public enum PurchaseResultSource
7+
{
8+
/// <summary>
9+
/// Unknown source.
10+
/// </summary>
11+
Unknown,
12+
13+
/// <summary>
14+
/// The result was obtained from the Qonversion API.
15+
/// </summary>
16+
Api,
17+
18+
/// <summary>
19+
/// The result was obtained from the local store.
20+
/// </summary>
21+
Local
22+
}
23+
}

Runtime/Scripts/Dto/PurchaseResultSource.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace QonversionUnity
2+
{
3+
/// <summary>
4+
/// Status of the purchase result.
5+
/// </summary>
6+
public enum PurchaseResultStatus
7+
{
8+
/// <summary>
9+
/// Unknown status.
10+
/// </summary>
11+
Unknown,
12+
13+
/// <summary>
14+
/// The purchase was successful.
15+
/// </summary>
16+
Success,
17+
18+
/// <summary>
19+
/// The purchase was canceled by the user.
20+
/// </summary>
21+
UserCanceled,
22+
23+
/// <summary>
24+
/// The purchase is pending (e.g., waiting for parental approval).
25+
/// </summary>
26+
Pending,
27+
28+
/// <summary>
29+
/// An error occurred during the purchase.
30+
/// </summary>
31+
Error
32+
}
33+
}

Runtime/Scripts/Dto/PurchaseResultStatus.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using JetBrains.Annotations;
4+
using UnityEngine.Scripting;
5+
6+
namespace QonversionUnity
7+
{
8+
/// <summary>
9+
/// Represents a raw store transaction from the native platform.
10+
/// This is the transaction information as received from Apple App Store or Google Play Store.
11+
/// </summary>
12+
public class StoreTransaction
13+
{
14+
/// <summary>
15+
/// The unique identifier for this transaction.
16+
/// </summary>
17+
[CanBeNull] public readonly string TransactionId;
18+
19+
/// <summary>
20+
/// The original transaction identifier.
21+
/// For subscriptions, this identifies the first transaction in the subscription chain.
22+
/// </summary>
23+
[CanBeNull] public readonly string OriginalTransactionId;
24+
25+
/// <summary>
26+
/// The date and time when the transaction occurred.
27+
/// </summary>
28+
[CanBeNull] public readonly DateTime? TransactionDate;
29+
30+
/// <summary>
31+
/// The store product identifier associated with this transaction.
32+
/// </summary>
33+
[CanBeNull] public readonly string ProductId;
34+
35+
/// <summary>
36+
/// The quantity of items purchased.
37+
/// </summary>
38+
public readonly int Quantity;
39+
40+
/// <summary>
41+
/// iOS only. The identifier of the promotional offer applied to this purchase.
42+
/// </summary>
43+
[CanBeNull] public readonly string PromoOfferId;
44+
45+
/// <summary>
46+
/// Android only. The purchase token from Google Play.
47+
/// </summary>
48+
[CanBeNull] public readonly string PurchaseToken;
49+
50+
[Preserve]
51+
public StoreTransaction(Dictionary<string, object> dict)
52+
{
53+
if (dict.TryGetValue("transactionId", out object value)) TransactionId = value as string;
54+
if (dict.TryGetValue("originalTransactionId", out value)) OriginalTransactionId = value as string;
55+
if (dict.TryGetValue("transactionTimestamp", out value) && value != null)
56+
{
57+
TransactionDate = FormatDate(value);
58+
}
59+
if (dict.TryGetValue("productId", out value)) ProductId = value as string;
60+
if (dict.TryGetValue("quantity", out value) && value != null)
61+
{
62+
Quantity = Convert.ToInt32(value);
63+
}
64+
else
65+
{
66+
Quantity = 1;
67+
}
68+
if (dict.TryGetValue("promoOfferId", out value)) PromoOfferId = value as string;
69+
if (dict.TryGetValue("purchaseToken", out value)) PurchaseToken = value as string;
70+
}
71+
72+
public override string ToString()
73+
{
74+
return $"{nameof(TransactionId)}: {TransactionId}, " +
75+
$"{nameof(OriginalTransactionId)}: {OriginalTransactionId}, " +
76+
$"{nameof(TransactionDate)}: {TransactionDate}, " +
77+
$"{nameof(ProductId)}: {ProductId}, " +
78+
$"{nameof(Quantity)}: {Quantity}, " +
79+
$"{nameof(PromoOfferId)}: {PromoOfferId}, " +
80+
$"{nameof(PurchaseToken)}: {PurchaseToken}";
81+
}
82+
83+
private DateTime FormatDate(object time)
84+
{
85+
if (time is double doubleTime)
86+
{
87+
return Utils.FormatDate(Convert.ToInt64(doubleTime));
88+
}
89+
90+
return Utils.FormatDate(Convert.ToInt64(time));
91+
}
92+
}
93+
}

Runtime/Scripts/Dto/StoreTransaction.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)