Skip to content
Merged
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
16 changes: 16 additions & 0 deletions ios/IapSerializationUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,19 @@ func serialize(_ pt: Product.ProductType?) -> String? {
return nil
}
}
@available(iOS 15.0, tvOS 15.0, *)
func serialize(_ s: Storefront?) -> [String: Any]? {
guard let s = s else {return nil}

var result: [String: Any] = [
"countryCode": s.countryCode,
]

if #available(iOS 17.0, tvOS 17.0, *) {
result["currencyCode"] = s.currency?.identifier
} else {
result["currencyCode"] = nil
}

return result;
}
24 changes: 20 additions & 4 deletions ios/RNIapIosSk2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ class RNIapIosSk2: RCTEventEmitter, Sk2Delegate {
"purchase-updated", "purchase-error" are for backward compatibility
*/
override func supportedEvents() -> [String]? {
return [ "purchase-updated", "purchase-error", "iap-transaction-updated"]
return [ "purchase-updated", "purchase-error", "iap-transaction-updated", "storefront-updated"]
}

@objc public func initConnection(
Expand Down Expand Up @@ -451,6 +451,7 @@ class RNIapIosSk2iOS15: Sk2Delegate {
private let _hasListenersQueue = DispatchQueue(label: "com.dooboolab.rniap.hasListenersQueue", attributes: .concurrent)
private var transactions: [String: Transaction]
private var updateListenerTask: Task<Void, Error>?
private var storefrontListenerTask: Task<Void, Error>?
fileprivate var sendEvent: ((String?, Any?) -> Void)?
var hasListeners: Bool {
get {
Expand Down Expand Up @@ -509,18 +510,33 @@ class RNIapIosSk2iOS15: Sk2Delegate {
if updateListenerTask == nil {
updateListenerTask = listenForTransactions()
}
if storefrontListenerTask == nil {
storefrontListenerTask = listenForStorefrontChanges()
}
}

func removeTransactionObserver() {
updateListenerTask?.cancel()
updateListenerTask = nil
storefrontListenerTask?.cancel()
storefrontListenerTask = nil
}

func addTransaction(_ transaction: Transaction) {
let transactionId = String(transaction.id)
self.transactions[transactionId] = transaction
}

func listenForStorefrontChanges() -> Task<Void, Error> {
return Task.detached {
for await storefront in Storefront.updates {
if self.hasListeners {
self.sendEvent?("storefront-updated", serialize(storefront))
}
}
}
}

func listenForTransactions() -> Task<Void, Error> {
return Task.detached {
// Iterate through any transactions that don't come from a direct call to `purchase()`.
Expand Down Expand Up @@ -846,7 +862,7 @@ class RNIapIosSk2iOS15: Sk2Delegate {

reject(
IapErrors.E_UNKNOWN.rawValue,
"Purchased failed for sku:\(sku): \(error.localizedDescription)",
"Purchased failed for sku:\(sku): \(error.localizedDescription); error: \(error)",
error)
}
} else {
Expand Down Expand Up @@ -1087,9 +1103,9 @@ class RNIapIosSk2iOS15: Sk2Delegate {
}

public func getStorefront(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
Task {
Task {
let storefront = await Storefront.current
resolve(storefront?.countryCode)
resolve(serialize(storefront))
}
}
}
6 changes: 3 additions & 3 deletions plugin/build/withIAP.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ const withIAPAndroid = (config, { paymentProvider }) => {
const withIAP = (config, props) => {
const paymentProvider = props?.paymentProvider ?? 'Play Store';
if (!hasPaymentProviderProperValue(paymentProvider)) {
config_plugins_2.WarningAggregator.addWarningAndroid('react-native-iap', `The payment provider '${paymentProvider}' is not supported. Please update your app.json file with one of the following supported values: 'Play Store', 'Amazon AppStore', or 'both'.`);
config_plugins_1.WarningAggregator.addWarningAndroid('react-native-iap', `The payment provider '${paymentProvider}' is not supported. Please update your app.json file with one of the following supported values: 'Play Store', 'Amazon AppStore', or 'both'.`);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh i did not notice this change. i think this is from claude code. i need to see what this is doing

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh it's not claude, it's an auto generated file

return config;
}
try {
config = withIAPAndroid(config, { paymentProvider });
}
catch (error) {
config_plugins_2.WarningAggregator.addWarningAndroid('react-native-iap', `There was a problem configuring react-native-iap in your native Android project: ${error}`);
config_plugins_1.WarningAggregator.addWarningAndroid('react-native-iap', `There was a problem configuring react-native-iap in your native Android project: ${error}`);
}
return config;
};
exports.default = (0, config_plugins_1.createRunOncePlugin)(withIAP, pkg.name, pkg.version);
exports.default = (0, config_plugins_2.createRunOncePlugin)(withIAP, pkg.name, pkg.version);
11 changes: 9 additions & 2 deletions src/iap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -975,11 +975,18 @@ export const deepLinkToSubscriptions = ({
* };
* ```
*/
export const getStorefront = (): Promise<string> => {
export const getStorefront = (): Promise<{
countryCode: string;
currency: string | null;
} | null> => {
return (
Platform.select({
android: async () => {
return await RNIapModule.getStorefront();
const countryCode = await RNIapModule.getStorefront();
return {
countryCode,
currency: null,
Comment thread
tjmabey marked this conversation as resolved.
};
},
ios: async () => {
return await RNIapIosSk2.getStorefront();
Expand Down
5 changes: 4 additions & 1 deletion src/modules/iosSk2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ type finishTransaction = (transactionIdentifier: string) => Promise<boolean>;
type getPendingTransactions = () => Promise<ProductPurchase[]>;
type presentCodeRedemptionSheet = () => Promise<null>;
type showManageSubscriptions = () => Promise<null>;
type getStorefront = () => Promise<string>;
type getStorefront = () => Promise<{
countryCode: string;
currency: string | null;
} | null>;

export interface IosModulePropsSk2 extends NativeModuleProps {
isAvailable(): number;
Expand Down
Loading