diff --git a/ios/IapUtils.swift b/ios/IapUtils.swift index 2eb221dc9..852c77524 100644 --- a/ios/IapUtils.swift +++ b/ios/IapUtils.swift @@ -7,7 +7,7 @@ import Foundation import StoreKit -import React +import React_Core public func debugMessage(_ object: Any...) { #if DEBUG diff --git a/ios/RNIapIos.m b/ios/RNIapIos.m index 3b99b6bad..1bf2e8e68 100644 --- a/ios/RNIapIos.m +++ b/ios/RNIapIos.m @@ -27,6 +27,7 @@ @interface RCT_EXTERN_MODULE (RNIapIos, NSObject) RCT_EXTERN_METHOD(buyProduct: (NSString*)sku + requestJSONString:(NSString*)requestJSONString andDangerouslyFinishTransactionAutomatically:(BOOL)andDangerouslyFinishTransactionAutomatically applicationUsername:(NSString*)applicationUsername quantity:(NSInteger)quantity diff --git a/ios/RNIapIos.swift b/ios/RNIapIos.swift index 7abd65cce..7b33f1aa3 100644 --- a/ios/RNIapIos.swift +++ b/ios/RNIapIos.swift @@ -1,4 +1,4 @@ -import React +import React_Core import StoreKit @objc(RNIapIos) @@ -184,6 +184,7 @@ class RNIapIos: RCTEventEmitter, SKRequestDelegate, SKPaymentTransactionObserver @objc public func buyProduct( _ sku: String, + requestJSONString: String?, andDangerouslyFinishTransactionAutomatically: Bool, applicationUsername: String?, quantity: Int, @@ -197,23 +198,29 @@ class RNIapIos: RCTEventEmitter, SKRequestDelegate, SKPaymentTransactionObserver let payment = SKMutablePayment(product: product) - if #available(iOS 12.2, tvOS 12.2, *) { - if let discountOffer = discountOffer, let identifier = discountOffer["identifier"], let keyIdentifier = discountOffer["keyIdentifier"], let nonce = discountOffer["nonce"], let signature = discountOffer["signature"], let timestamp = discountOffer["timestamp"] { - let discount = SKPaymentDiscount( - identifier: identifier, - keyIdentifier: keyIdentifier, - nonce: UUID(uuidString: nonce)!, - signature: signature, - timestamp: NSNumber(value: Int(timestamp)!)) - payment.paymentDiscount = discount - } - } - if let applicationUsername = applicationUsername { payment.applicationUsername = applicationUsername } - if quantity > 0 { - payment.quantity = quantity + + if let requestJSONString = requestJSONString { + let requestData = Data(requestJSONString.utf8) + payment.requestData = requestData + } else { + if #available(iOS 12.2, tvOS 12.2, *) { + if let discountOffer = discountOffer, let identifier = discountOffer["identifier"], let keyIdentifier = discountOffer["keyIdentifier"], let nonce = discountOffer["nonce"], let signature = discountOffer["signature"], let timestamp = discountOffer["timestamp"] { + let discount = SKPaymentDiscount( + identifier: identifier, + keyIdentifier: keyIdentifier, + nonce: UUID(uuidString: nonce)!, + signature: signature, + timestamp: NSNumber(value: Int(timestamp)!)) + payment.paymentDiscount = discount + } + } + + if quantity > 0 { + payment.quantity = quantity + } } SKPaymentQueue.default().add(payment) diff --git a/ios/RNIapIosSk2.m b/ios/RNIapIosSk2.m index 7ae7d307f..a4fa1364d 100644 --- a/ios/RNIapIosSk2.m +++ b/ios/RNIapIosSk2.m @@ -39,6 +39,7 @@ @interface RCT_EXTERN_MODULE (RNIapIosSk2, NSObject) RCT_EXTERN_METHOD(buyProduct: (NSString*)sku + requestJSONString:(NSString*)requestJSONString andDangerouslyFinishTransactionAutomatically:(BOOL)andDangerouslyFinishTransactionAutomatically appAccountToken:(NSString*)appAccountToken quantity:(NSInteger)quantity diff --git a/ios/RNIapIosSk2.swift b/ios/RNIapIosSk2.swift index c276dfa43..9e1e44636 100644 --- a/ios/RNIapIosSk2.swift +++ b/ios/RNIapIosSk2.swift @@ -1,5 +1,5 @@ import Foundation -import React +import React_Core import StoreKit protocol Sk2Delegate { @@ -33,6 +33,7 @@ protocol Sk2Delegate { func buyProduct( _ sku: String, + requestJSONString: String?, andDangerouslyFinishTransactionAutomatically: Bool, appAccountToken: String?, quantity: Int, @@ -155,6 +156,7 @@ class DummySk2: Sk2Delegate { func buyProduct( _ sku: String, + requestJSONString: String?, andDangerouslyFinishTransactionAutomatically: Bool, appAccountToken: String?, quantity: Int, @@ -330,6 +332,7 @@ class RNIapIosSk2: RCTEventEmitter, Sk2Delegate { @objc public func buyProduct( _ sku: String, + requestJSONString: String?, andDangerouslyFinishTransactionAutomatically: Bool, appAccountToken: String?, quantity: Int, @@ -339,6 +342,7 @@ class RNIapIosSk2: RCTEventEmitter, Sk2Delegate { ) { delegate.buyProduct( sku, + requestJSONString: requestJSONString, andDangerouslyFinishTransactionAutomatically: andDangerouslyFinishTransactionAutomatically, appAccountToken: appAccountToken, quantity: quantity, @@ -699,6 +703,7 @@ class RNIapIosSk2iOS15: Sk2Delegate { public func buyProduct( _ sku: String, + requestJSONString: String?, andDangerouslyFinishTransactionAutomatically: Bool, appAccountToken: String?, quantity: Int, @@ -712,18 +717,24 @@ class RNIapIosSk2iOS15: Sk2Delegate { if let product = product { do { var options: Set = [] - if quantity > -1 { - options.insert(.quantity(quantity)) - } - let offerID = withOffer["offerID"] - let keyID = withOffer["keyID"] - let nonce = withOffer["nonce"] - let signature = withOffer["signature"] - let timestamp = withOffer["timestamp"] + if let requestJSONString = requestJSONString { + let requestData = Data(requestJSONString.utf8) + options.insert(Product.PurchaseOption.custom(key: "requestData", value: requestData)) + } else { + if quantity > -1 { + options.insert(.quantity(quantity)) + } - if let offerID = offerID, let keyID = keyID, let nonce = nonce, let nonce = UUID(uuidString: nonce), let signature = signature, let signature = signature.data(using: .utf8), let timestamp = timestamp, let timestamp = Int(timestamp) { - options.insert(.promotionalOffer(offerID: offerID, keyID: keyID, nonce: nonce, signature: signature, timestamp: timestamp )) + let offerID = withOffer["offerID"] + let keyID = withOffer["keyID"] + let nonce = withOffer["nonce"] + let signature = withOffer["signature"] + let timestamp = withOffer["timestamp"] + + if let offerID = offerID, let keyID = keyID, let nonce = nonce, let nonce = UUID(uuidString: nonce), let signature = signature, let signature = signature.data(using: .utf8), let timestamp = timestamp, let timestamp = Int(timestamp) { + options.insert(.promotionalOffer(offerID: offerID, keyID: keyID, nonce: nonce, signature: signature, timestamp: timestamp )) + } } if let appAccountToken = appAccountToken, let appAccountToken = UUID(uuidString: appAccountToken) { options.insert(.appAccountToken(appAccountToken)) diff --git a/package.json b/package.json index 5c5b9736b..546673ba4 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "bootstrap": "yarn example && yarn && yarn example pods", "gen:doc": "typedoc", "build:plugin": "tsc --build plugin", - "clean:plugin": "expo-module clean plugin", + "clean:plugin": "node -e \"if (process.platform !== 'win32'){process.exit(1)} \" || expo-module clean plugin", "lint:plugin": "eslint plugin/src/*" }, "devDependencies": { diff --git a/plugin/build/withIAP.js b/plugin/build/withIAP.js index 290c60306..53f1357cd 100644 --- a/plugin/build/withIAP.js +++ b/plugin/build/withIAP.js @@ -56,15 +56,15 @@ const withIAPAndroid = (config, { paymentProvider }) => { const withIAP = (config, props) => { const paymentProvider = props?.paymentProvider ?? 'Play Store'; if (!hasPaymentProviderProperValue(paymentProvider)) { - 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'.`); + 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'.`); return config; } try { config = withIAPAndroid(config, { paymentProvider }); } catch (error) { - config_plugins_1.WarningAggregator.addWarningAndroid('react-native-iap', `There was a problem configuring react-native-iap in your native Android project: ${error}`); + config_plugins_2.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_2.createRunOncePlugin)(withIAP, pkg.name, pkg.version); +exports.default = (0, config_plugins_1.createRunOncePlugin)(withIAP, pkg.name, pkg.version); diff --git a/src/iap.ts b/src/iap.ts index e9739fe41..97e43a2ea 100644 --- a/src/iap.ts +++ b/src/iap.ts @@ -597,6 +597,7 @@ export const requestPurchase = ( appAccountToken, quantity, withOffer, + requestJSONString, } = request; if (andDangerouslyFinishTransactionAutomaticallyIOS) { @@ -610,6 +611,7 @@ export const requestPurchase = ( const purchase = transactionSk2ToPurchaseMap( await RNIapIosSk2.buyProduct( sku, + requestJSONString, andDangerouslyFinishTransactionAutomaticallyIOS, appAccountToken, quantity ?? -1, @@ -620,6 +622,7 @@ export const requestPurchase = ( } else { return RNIapIos.buyProduct( sku, + requestJSONString, andDangerouslyFinishTransactionAutomaticallyIOS, appAccountToken, quantity ?? -1, @@ -753,6 +756,7 @@ export const requestSubscription = ( appAccountToken, quantity, withOffer, + requestJSONString, } = request; if (andDangerouslyFinishTransactionAutomaticallyIOS) { @@ -767,6 +771,7 @@ export const requestSubscription = ( const purchase = transactionSk2ToPurchaseMap( await RNIapIosSk2.buyProduct( sku, + requestJSONString, andDangerouslyFinishTransactionAutomaticallyIOS, appAccountToken, quantity ?? -1, @@ -777,6 +782,7 @@ export const requestSubscription = ( } else { return RNIapIos.buyProduct( sku, + requestJSONString, andDangerouslyFinishTransactionAutomaticallyIOS, appAccountToken, quantity ?? -1, diff --git a/src/modules/ios.ts b/src/modules/ios.ts index 7b7f8f65a..2d93b0e83 100644 --- a/src/modules/ios.ts +++ b/src/modules/ios.ts @@ -22,6 +22,7 @@ type getAvailableItems = ( export type BuyProduct = ( sku: Sku, + requestJSONString: string | undefined, andDangerouslyFinishTransactionAutomaticallyIOS: boolean, applicationUsername: string | undefined, quantity: number, diff --git a/src/modules/iosSk2.ts b/src/modules/iosSk2.ts index 35240a800..f7f66a29f 100644 --- a/src/modules/iosSk2.ts +++ b/src/modules/iosSk2.ts @@ -21,6 +21,7 @@ type getAvailableItems = ( export type BuyProduct = ( sku: Sku, + requestJSONString: string | undefined, andDangerouslyFinishTransactionAutomaticallyIOS: boolean, applicationUsername: string | undefined, quantity: number, diff --git a/src/types/index.ts b/src/types/index.ts index c7af8fbcb..22e455bc2 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -230,6 +230,7 @@ export interface RequestPurchaseAndroid extends RequestPurchaseBaseAndroid { export interface RequestPurchaseIOS { sku: Sku; andDangerouslyFinishTransactionAutomaticallyIOS?: boolean; + requestJSONString?: string; /** * UUID representing user account */