Skip to content

Commit

Permalink
feat: add renewal info for Storekit 2 (#2614)
Browse files Browse the repository at this point in the history
- add renewal info (uncomment and serialize)
- change debugSerialize to serialize - there is info in this property
useful for production not only for development
- added transactionReasonIOS enum (to distinguish between type of
renewing transactions of purchase events)

see also:
[JWSTransactionDecodedPayload](https://developer.apple.com/documentation/appstoreserverapi/jwstransactiondecodedpayload)
  • Loading branch information
cervebar committed Dec 8, 2023
1 parent de8a854 commit 2be708c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
27 changes: 24 additions & 3 deletions ios/IapSerializationUtils.swift
Expand Up @@ -31,6 +31,10 @@ func serializeDebug (_ d: Data) -> String? {
#endif
}

func serialize (_ d: Data) -> String? {
return String( decoding: d, as: UTF8.self)
}

func serializeDebug (_ s: String) -> String? {
#if DEBUG
return s
Expand Down Expand Up @@ -75,12 +79,29 @@ func serialize(_ sp: Product.SubscriptionPeriod.Unit?) -> String? {
@available(iOS 15.0, tvOS 15.0, *)
func serialize(_ s: Product.SubscriptionInfo.Status?) -> [String: Any?]? {
guard let s = s else {return nil}
return ["state": serialize( s.state)
// "renewalInfo": serialize(s.renewalInfo),
return ["state": serialize( s.state),
"renewalInfo": serialize(s.renewalInfo)
// "transaction": serialize(s.transaction),
]
}

@available(iOS 15.0, tvOS 15.0, *)
func serialize(_ vri: VerificationResult<Product.SubscriptionInfo.RenewalInfo>?) -> [String: Any?]? {
guard let vri = vri else {return nil}
do {
let ri = try vri.payloadValue
let jsonStringRepresentation = String(data: ri.jsonRepresentation, encoding: .utf8) ?? ""
return [
"jsonRepresentation": jsonStringRepresentation,
"willAutoRenew": ri.willAutoRenew,
"autoRenewPreference": ri.autoRenewPreference
]
} catch {
print("Error in parsing VerificationResult<Product.SubscriptionInfo.RenewalInfo>")
return nil
}
}

@available(iOS 15.0, tvOS 15.0, *)
func serialize(_ rs: Product.SubscriptionInfo.RenewalState?) -> String? {
guard let rs = rs else {return nil}
Expand Down Expand Up @@ -158,7 +179,7 @@ func serialize(_ t: Transaction) -> [String: Any?] {
"environment": environment,
"id": t.id,
"isUpgraded": t.isUpgraded,
"jsonRepresentation": serializeDebug(t.jsonRepresentation),
"jsonRepresentation": serialize(t.jsonRepresentation),
"offerID": t.offerID,
"offerType": serialize(t.offerType),
"originalID": t.originalID,
Expand Down
28 changes: 27 additions & 1 deletion src/types/appleSk2.ts
Expand Up @@ -134,8 +134,22 @@ export type SubscriptionStatus =
| 'revoked'
| 'subscribed';

/**
* Renewal info for whole subscription group.
* see: https://developer.apple.com/documentation/storekit/product/subscriptioninfo/status/3822294-renewalinfo
* WARN:
* - autoRenewPreference is serialised as autoRenewProductId in jsonRepresentation
* - renewalDate is available in jsonRepresentation (will change with Xcode 15 https://developer.apple.com/forums/thread/738833)
*/
export type RenewalInfo = {
jsonRepresentation?: string;
willAutoRenew: boolean;
autoRenewPreference?: string;
};

export type ProductStatus = {
state: SubscriptionStatus;
renewalInfo?: RenewalInfo;
};

export const transactionSk2ToPurchaseMap = ({
Expand All @@ -146,8 +160,19 @@ export const transactionSk2ToPurchaseMap = ({
purchasedQuantity,
originalID,
verificationResult,
appAccountToken
appAccountToken,
jsonRepresentation,
}: TransactionSk2): Purchase => {
let transactionReasonIOS;
try {
const transactionData = JSON.parse(jsonRepresentation);
transactionReasonIOS = transactionData.transactionReason;
} catch (e) {
console.log(
'AppleSK2.ts react-native-iap: Error parsing jsonRepresentation',
e,
);
}
const purchase: Purchase = {
productId: productID,
transactionId: String(id),
Expand All @@ -159,6 +184,7 @@ export const transactionSk2ToPurchaseMap = ({
originalTransactionIdentifierIOS: originalID,
verificationResultIOS: verificationResult ?? '',
appAccountToken: appAccountToken ?? '',
transactionReasonIOS: transactionReasonIOS ?? '',
};
return purchase;
};
Expand Down
6 changes: 6 additions & 0 deletions src/types/index.ts
Expand Up @@ -46,6 +46,11 @@ export enum ProductType {
iap = 'iap',
}

export enum TransactionReason {
PURCHASE = 'PURCHASE',
RENEWAL = 'RENEWAL',
}

export interface ProductCommon {
type: 'subs' | 'sub' | 'inapp' | 'iap';
productId: string; //iOS
Expand Down Expand Up @@ -102,6 +107,7 @@ export interface SubscriptionPurchase extends ProductPurchase {
originalTransactionDateIOS?: number;
originalTransactionIdentifierIOS?: string;
verificationResultIOS?: string;
transactionReasonIOS?: TransactionReason | string;
}

export type Purchase = ProductPurchase | SubscriptionPurchase;
Expand Down

0 comments on commit 2be708c

Please sign in to comment.