This commit is contained in:
Mo
2022-11-13 09:28:16 -06:00
committed by GitHub
parent e56a960bbf
commit d519aca685
49 changed files with 512 additions and 151 deletions

View File

@@ -1,5 +1,6 @@
import AsyncStorage from '@react-native-community/async-storage'
import SNReactNative from '@standardnotes/react-native-utils'
import { AppleIAPReceipt } from '@standardnotes/services/dist/Domain/Subscription/AppleIAPReceipt'
import {
ApplicationIdentifier,
Environment,
@@ -11,6 +12,7 @@ import {
RawKeychainValue,
removeFromArray,
TransferPayload,
AppleIAPProductId,
UuidString,
} from '@standardnotes/snjs'
import { ColorSchemeObserverService } from 'ColorSchemeObserverService'
@@ -41,6 +43,7 @@ import Share from 'react-native-share'
import { AndroidBackHandlerService } from '../AndroidBackHandlerService'
import { AppStateObserverService } from './../AppStateObserverService'
import Keychain from './Keychain'
import { PurchaseManager } from '../PurchaseManager'
export type BiometricsType = 'Fingerprint' | 'Face ID' | 'Biometrics' | 'Touch ID'
@@ -99,6 +102,10 @@ export class MobileDevice implements MobileDeviceInterface {
private colorSchemeService?: ColorSchemeObserverService,
) {}
purchaseSubscriptionIAP(plan: AppleIAPProductId): Promise<AppleIAPReceipt | undefined> {
return PurchaseManager.getInstance().purchase(plan)
}
deinit() {
this.stateObserverService?.deinit()
;(this.stateObserverService as unknown) = undefined
@@ -108,7 +115,7 @@ export class MobileDevice implements MobileDeviceInterface {
;(this.colorSchemeService as unknown) = undefined
}
consoleLog(...args: any[]): void {
consoleLog(...args: unknown[]): void {
// eslint-disable-next-line no-console
console.log(args)
}

View File

@@ -0,0 +1,18 @@
import { log as utilsLog } from '@standardnotes/snjs'
export enum LoggingDomain {
AppleIAP,
}
const LoggingStatus: Record<LoggingDomain, boolean> = {
[LoggingDomain.AppleIAP]: true,
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function log(domain: LoggingDomain, ...args: any[]): void {
if (!LoggingStatus[domain]) {
return
}
utilsLog(LoggingDomain[domain], ...args)
}

View File

@@ -0,0 +1,80 @@
import { LoggingDomain, log } from './Lib/Logging'
import { EmitterSubscription } from 'react-native'
import {
initConnection,
endConnection,
purchaseErrorListener,
purchaseUpdatedListener,
type ProductPurchase,
type PurchaseError,
type SubscriptionPurchase,
finishTransaction,
requestSubscription,
getSubscriptions,
} from 'react-native-iap'
import { AppleIAPReceipt, AppleIAPProductId } from '@standardnotes/snjs'
export class PurchaseManager {
private static instance: PurchaseManager
private listenerDisposer: EmitterSubscription
private errorDisposer: EmitterSubscription
private constructor() {
this.listenerDisposer = purchaseUpdatedListener((purchase: SubscriptionPurchase | ProductPurchase) => {
log(LoggingDomain.AppleIAP, 'purchaseUpdatedListener', purchase)
const receipt = purchase.transactionReceipt
if (receipt) {
void finishTransaction({ purchase, isConsumable: false })
}
})
this.errorDisposer = purchaseErrorListener((error: PurchaseError) => {
log(LoggingDomain.AppleIAP, 'purchaseErrorListener', error)
})
}
public static getInstance(): PurchaseManager {
if (!PurchaseManager.instance) {
PurchaseManager.instance = new PurchaseManager()
}
return PurchaseManager.instance
}
deinit() {
this.listenerDisposer.remove()
this.errorDisposer.remove()
void endConnection()
}
async purchase(sku: AppleIAPProductId): Promise<AppleIAPReceipt | undefined> {
await initConnection()
const subscriptions = await getSubscriptions({
skus: [AppleIAPProductId.PlusPlanYearly, AppleIAPProductId.ProPlanYearly],
})
log(LoggingDomain.AppleIAP, 'Retrieved subscriptions', subscriptions)
try {
const result = await requestSubscription({ sku, andDangerouslyFinishTransactionAutomaticallyIOS: true })
log(LoggingDomain.AppleIAP, 'Purchase result', result)
if (result && result.transactionId && result.transactionDate) {
return {
transactionId: result.transactionId,
productId: result.productId as AppleIAPProductId,
transactionDate: String(result.transactionDate),
transactionReceipt: result.transactionReceipt,
}
} else {
log(LoggingDomain.AppleIAP, 'Purchase method returning undefined even though successful')
return undefined
}
} catch (error) {
log(LoggingDomain.AppleIAP, error)
return undefined
}
}
}