Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Runtime/Client/LootLockerEndPoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ public class LootLockerEndPoints
public static EndPointClass querySteamPurchaseRedemptionStatus = new EndPointClass("store/steam/redeem/query", LootLockerHTTPMethod.POST);
public static EndPointClass finalizeSteamPurchaseRedemption = new EndPointClass("store/steam/redeem/finalise", LootLockerHTTPMethod.POST);

// Refund
[Header("Refund")]
public static EndPointClass refundByEntitlementIds = new EndPointClass("game/refund/v1", LootLockerHTTPMethod.POST);

// Triggers
public static EndPointClass InvokeTriggers = new EndPointClass("triggers/cozy-crusader/v1", LootLockerHTTPMethod.POST);

Expand Down
32 changes: 32 additions & 0 deletions Runtime/Game/LootLockerSDKManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6994,6 +6994,38 @@ public static void FinalizeSteamPurchaseRedemption(string entitlementId, Action<
LootLockerServerRequest.CallAPI(forPlayerWithUlid, LootLockerEndPoints.finalizeSteamPurchaseRedemption.endPoint, LootLockerEndPoints.finalizeSteamPurchaseRedemption.httpMethod, body, onComplete: (serverResponse) => { LootLockerResponse.Deserialize(onComplete, serverResponse); });
}

/// <summary>
/// Refund one or more previously purchased items by their entitlement IDs.
///
/// On success, the response contains:
/// - player_inventory_events: the assets removed from (or skipped in) the player's inventory
/// - currency_refunded: currency credited back to the player's wallet (the purchase price returned)
/// - currency_clawback: currency debited from the player's wallet (currency rewards from the entitlement reclaimed)
/// - warnings: any conditions that could not be fully reversed (e.g. non-reversible rewards, insufficient funds). A non-empty warnings list does not mean the refund failed.
/// </summary>
/// <param name="entitlementIds">The list of entitlement IDs to refund</param>
/// <param name="onComplete">onComplete Action for handling the response of type LootLockerRefundByEntitlementIdsResponse</param>
/// <param name="forPlayerWithUlid">Optional : Execute the request for the specified player. If not supplied, the default player will be used.</param>
public static void RefundByEntitlementIds(string[] entitlementIds, Action<LootLockerRefundByEntitlementIdsResponse> onComplete, string forPlayerWithUlid = null)
{
if (!CheckInitialized(false, forPlayerWithUlid))
{
onComplete?.Invoke(LootLockerResponseFactory.SDKNotInitializedError<LootLockerRefundByEntitlementIdsResponse>(forPlayerWithUlid));
return;
}
if (entitlementIds == null || entitlementIds.Length == 0)
{
onComplete?.Invoke(LootLockerResponseFactory.ClientError<LootLockerRefundByEntitlementIdsResponse>("entitlementIds must not be null or empty", forPlayerWithUlid));
return;
}
var body = LootLockerJson.SerializeObject(new LootLockerRefundByEntitlementIdsRequest
{
entitlement_ids = entitlementIds
});

LootLockerServerRequest.CallAPI(forPlayerWithUlid, LootLockerEndPoints.refundByEntitlementIds.endPoint, LootLockerEndPoints.refundByEntitlementIds.httpMethod, body, onComplete: (serverResponse) => { LootLockerResponse.Deserialize(onComplete, serverResponse); });
}

#endregion

#region Collectables
Expand Down
133 changes: 133 additions & 0 deletions Runtime/Game/Requests/PurchaseRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,139 @@ public class LootLockerFinalizeSteamPurchaseRedemptionRequest
/// </summary>
public string entitlement_id { get; set; }
}

//==================================================
// Refund Data Definitions
//==================================================

/// <summary>
/// Request to refund items by their entitlement IDs
/// </summary>
public class LootLockerRefundByEntitlementIdsRequest
{
/// <summary>
/// The list of entitlement IDs to refund
/// </summary>
public string[] entitlement_ids { get; set; }
}

/// <summary>
/// Describes an asset that was added or removed from the player's inventory as part of a refund
/// </summary>
public class LootLockerRefundInventoryEvent
{
/// <summary>
/// The legacy numeric ID of the asset
/// </summary>
public ulong asset_id { get; set; }
/// <summary>
/// Display name of the asset
/// </summary>
public string name { get; set; }
/// <summary>
/// The action taken on this asset: "removed" if the asset was successfully taken back from the player's inventory, "skipped" if it could not be removed (e.g. already consumed or transferred)
/// </summary>
public string action { get; set; }
}

/// <summary>
/// A currency amount credited or debited as part of a refund
/// </summary>
public class LootLockerRefundCurrencyEntry
{
/// <summary>
/// The ULID of the currency
/// </summary>
public string currency_id { get; set; }
/// <summary>
/// Short code identifying the currency (e.g. "gold", "gems")
/// </summary>
public string currency_code { get; set; }
/// <summary>
/// The amount credited or debited, represented as a string to support arbitrary precision
/// </summary>
public string amount { get; set; }
}

/// <summary>
/// A reward that could not be reversed as part of a refund
/// </summary>
public class LootLockerRefundNonReversibleReward
{
/// <summary>
/// The kind of reward: "progression_points" (points were added to a progression) or "progression_reset" (a progression was reset to its initial state)
/// </summary>
public string kind { get; set; }
/// <summary>
/// The ULID of the progression that was affected
/// </summary>
public string id { get; set; }
/// <summary>
/// Display name of the progression
/// </summary>
public string name { get; set; }
/// <summary>
/// The number of points that were granted and cannot be reversed. Only present for "progression_points"
/// </summary>
public string amount { get; set; }
}

/// <summary>
/// A warning detail for a specific condition encountered during refund processing
/// </summary>
public class LootLockerRefundWarningDetail
{
/// <summary>
/// The warning category: "non_reversible_rewards", "insufficient_funds", "already_refunded", or "refund_failed"
/// </summary>
public string type { get; set; }
/// <summary>
/// Human-readable explanation of the warning
/// </summary>
public string message { get; set; }
/// <summary>
/// The specific rewards that could not be reversed. Only present when type is "non_reversible_rewards"
/// </summary>
public LootLockerRefundNonReversibleReward[] rewards { get; set; }
}

/// <summary>
/// Warnings encountered during refund processing for a particular entitlement
/// </summary>
public class LootLockerRefundWarning
{
/// <summary>
/// The entitlement ULID this warning applies to
/// </summary>
public string entitlement_id { get; set; }
/// <summary>
/// One or more warning conditions for this entitlement
/// </summary>
public LootLockerRefundWarningDetail[] details { get; set; }
}

/// <summary>
/// Response from refunding items by entitlement IDs
/// </summary>
public class LootLockerRefundByEntitlementIdsResponse : LootLockerResponse
{
/// <summary>
/// Assets that were added or removed from the player's inventory as part of the refund
/// </summary>
public LootLockerRefundInventoryEvent[] player_inventory_events { get; set; }
/// <summary>
/// Currency amounts credited back to the player's wallet (i.e. the purchase price being returned)
/// </summary>
public LootLockerRefundCurrencyEntry[] currency_refunded { get; set; }
/// <summary>
/// Currency amounts debited from the player's wallet (i.e. currency rewards from the entitlement being reclaimed)
/// </summary>
public LootLockerRefundCurrencyEntry[] currency_clawback { get; set; }
/// <summary>
/// Warnings encountered during refund processing, grouped by entitlement. A non-empty warnings array does not mean the refund failed — it means some aspects could not be fully reversed.
/// </summary>
public LootLockerRefundWarning[] warnings { get; set; }
}
}

namespace LootLocker
Expand Down