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
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export enum SubscriptionApiOperations {
CancelingInvite,
ListingInvites,
AcceptingInvite,
ConfirmAppleIAP,
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { SubscriptionInviteAcceptResponse } from '../../Response/Subscription/Su
import { SubscriptionApiServiceInterface } from './SubscriptionApiServiceInterface'
import { SubscriptionApiOperations } from './SubscriptionApiOperations'
import { Uuid } from '@standardnotes/common'
import { AppleIAPConfirmResponse } from './../../Response/Subscription/AppleIAPConfirmResponse'
import { AppleIAPConfirmRequestParams } from '../../Request'

export class SubscriptionApiService implements SubscriptionApiServiceInterface {
private operationsInProgress: Map<SubscriptionApiOperations, boolean>
Expand All @@ -31,11 +33,11 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface {
[ApiEndpointParam.ApiVersion]: ApiVersion.v0,
})

this.operationsInProgress.set(SubscriptionApiOperations.ListingInvites, false)

return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericFail)
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.ListingInvites, false)
}
}

Expand All @@ -52,11 +54,11 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface {
inviteUuid,
})

this.operationsInProgress.set(SubscriptionApiOperations.CancelingInvite, false)

return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericFail)
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.CancelingInvite, false)
}
}

Expand All @@ -73,11 +75,11 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface {
identifier: inviteeEmail,
})

this.operationsInProgress.set(SubscriptionApiOperations.Inviting, false)

return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericFail)
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.Inviting, false)
}
}

Expand All @@ -93,11 +95,27 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface {
inviteUuid,
})

this.operationsInProgress.set(SubscriptionApiOperations.AcceptingInvite, false)

return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericFail)
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.AcceptingInvite, false)
}
}

async confirmAppleIAP(params: AppleIAPConfirmRequestParams): Promise<AppleIAPConfirmResponse> {
if (this.operationsInProgress.get(SubscriptionApiOperations.ConfirmAppleIAP)) {
throw new ApiCallError(ErrorMessage.GenericInProgress)
}

this.operationsInProgress.set(SubscriptionApiOperations.ConfirmAppleIAP, true)

try {
const response = await this.subscriptionServer.confirmAppleIAP(params)

return response
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.ConfirmAppleIAP, false)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Uuid } from '@standardnotes/common'

import { AppleIAPConfirmResponse } from './../../Response/Subscription/AppleIAPConfirmResponse'
import { AppleIAPConfirmRequestParams } from '../../Request'
import { SubscriptionInviteAcceptResponse } from '../../Response/Subscription/SubscriptionInviteAcceptResponse'
import { SubscriptionInviteCancelResponse } from '../../Response/Subscription/SubscriptionInviteCancelResponse'
import { SubscriptionInviteListResponse } from '../../Response/Subscription/SubscriptionInviteListResponse'
Expand All @@ -10,4 +12,5 @@ export interface SubscriptionApiServiceInterface {
listInvites(): Promise<SubscriptionInviteListResponse>
cancelInvite(inviteUuid: Uuid): Promise<SubscriptionInviteCancelResponse>
acceptInvite(inviteUuid: Uuid): Promise<SubscriptionInviteAcceptResponse>
confirmAppleIAP(params: AppleIAPConfirmRequestParams): Promise<AppleIAPConfirmResponse>
}
6 changes: 5 additions & 1 deletion packages/api/src/Domain/Http/HttpService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ describe('HttpService', () => {
const host = 'http://bar'
let updateMetaCallback: (meta: HttpResponseMeta) => void

const createService = () => new HttpService(environment, appVersion, snjsVersion, host, updateMetaCallback)
const createService = () => {
const service = new HttpService(environment, appVersion, snjsVersion, updateMetaCallback)
service.setHost(host)
return service
}

beforeEach(() => {
updateMetaCallback = jest.fn()
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/Domain/Http/HttpService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import { HttpErrorResponseBody } from './HttpErrorResponseBody'
export class HttpService implements HttpServiceInterface {
private authorizationToken?: string
private __latencySimulatorMs?: number
private host!: string

constructor(
private environment: Environment,
private appVersion: string,
private snjsVersion: string,
private host: string,
private updateMetaCallback: (meta: HttpResponseMeta) => void,
) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type AppleIAPConfirmRequestParams = {
productId: string
transactionId: string
transactionDate: string
transactionReceipt: string
subscription_token: string
}
1 change: 1 addition & 0 deletions packages/api/src/Domain/Request/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './ApiEndpointParam'
export * from './Subscription/AppleIAPConfirmRequestParams'
export * from './Subscription/SubscriptionInviteAcceptRequestParams'
export * from './Subscription/SubscriptionInviteCancelRequestParams'
export * from './Subscription/SubscriptionInviteDeclineRequestParams'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Either } from '@standardnotes/common'

import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody'
import { HttpResponse } from '../../Http/HttpResponse'
import { AppleIAPConfirmResponseBody } from './AppleIAPConfirmResponseBody'

export interface AppleIAPConfirmResponse extends HttpResponse {
data: Either<AppleIAPConfirmResponseBody, HttpErrorResponseBody>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type AppleIAPConfirmResponseBody = { success: true } | { success: false; message: string }
2 changes: 2 additions & 0 deletions packages/api/src/Domain/Response/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './Subscription/AppleIAPConfirmResponse'
export * from './Subscription/AppleIAPConfirmResponseBody'
export * from './Subscription/SubscriptionInviteAcceptResponse'
export * from './Subscription/SubscriptionInviteAcceptResponseBody'
export * from './Subscription/SubscriptionInviteCancelResponse'
Expand Down
5 changes: 5 additions & 0 deletions packages/api/src/Domain/Server/Subscription/Paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ const SharingPaths = {
listInvites: '/v1/subscription-invites',
}

const ApplePaths = {
confirmAppleIAP: '/v1/subscriptions/apple_iap_confirm',
}

export const Paths = {
v1: {
...SharingPaths,
...ApplePaths,
},
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { AppleIAPConfirmResponse } from './../../Response/Subscription/AppleIAPConfirmResponse'
import { HttpServiceInterface } from '../../Http/HttpServiceInterface'
import { AppleIAPConfirmRequestParams } from '../../Request'
import { SubscriptionInviteAcceptRequestParams } from '../../Request/Subscription/SubscriptionInviteAcceptRequestParams'
import { SubscriptionInviteCancelRequestParams } from '../../Request/Subscription/SubscriptionInviteCancelRequestParams'
import { SubscriptionInviteDeclineRequestParams } from '../../Request/Subscription/SubscriptionInviteDeclineRequestParams'
Expand Down Expand Up @@ -45,4 +47,10 @@ export class SubscriptionServer implements SubscriptionServerInterface {

return response as SubscriptionInviteResponse
}

async confirmAppleIAP(params: AppleIAPConfirmRequestParams): Promise<AppleIAPConfirmResponse> {
const response = await this.httpService.post(Paths.v1.confirmAppleIAP, params)

return response as AppleIAPConfirmResponse
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { AppleIAPConfirmResponse } from './../../Response/Subscription/AppleIAPConfirmResponse'
import { AppleIAPConfirmRequestParams } from './../../Request/Subscription/AppleIAPConfirmRequestParams'
import { SubscriptionInviteAcceptRequestParams } from '../../Request/Subscription/SubscriptionInviteAcceptRequestParams'
import { SubscriptionInviteCancelRequestParams } from '../../Request/Subscription/SubscriptionInviteCancelRequestParams'
import { SubscriptionInviteDeclineRequestParams } from '../../Request/Subscription/SubscriptionInviteDeclineRequestParams'
Expand All @@ -15,4 +17,5 @@ export interface SubscriptionServerInterface {
declineInvite(params: SubscriptionInviteDeclineRequestParams): Promise<SubscriptionInviteDeclineResponse>
cancelInvite(params: SubscriptionInviteCancelRequestParams): Promise<SubscriptionInviteCancelResponse>
listInvites(params: SubscriptionInviteListRequestParams): Promise<SubscriptionInviteListResponse>
confirmAppleIAP(params: AppleIAPConfirmRequestParams): Promise<AppleIAPConfirmResponse>
}
6 changes: 6 additions & 0 deletions packages/mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ PODS:
- React-Core
- RNFS (2.20.0):
- React-Core
- RNIap (12.4.4):
- React-Core
- RNKeychain (8.0.0):
- React-Core
- RNPrivacySnapshot (1.0.0):
Expand Down Expand Up @@ -422,6 +424,7 @@ DEPENDENCIES:
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- RNFileViewer (from `../node_modules/react-native-file-viewer`)
- RNFS (from `../node_modules/react-native-fs`)
- RNIap (from `../node_modules/react-native-iap`)
- RNKeychain (from `../node_modules/react-native-keychain`)
- RNPrivacySnapshot (from `../node_modules/react-native-privacy-snapshot`)
- RNShare (from `../node_modules/react-native-share`)
Expand Down Expand Up @@ -518,6 +521,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-file-viewer"
RNFS:
:path: "../node_modules/react-native-fs"
RNIap:
:path: "../node_modules/react-native-iap"
RNKeychain:
:path: "../node_modules/react-native-keychain"
RNPrivacySnapshot:
Expand Down Expand Up @@ -578,6 +583,7 @@ SPEC CHECKSUMS:
RNCAsyncStorage: b03032fdbdb725bea0bd9e5ec5a7272865ae7398
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
RNIap: 3bcd6982cf99503339cf9243e4ba70a45ea2cf72
RNKeychain: 4f63aada75ebafd26f4bc2c670199461eab85d94
RNPrivacySnapshot: 8eaf571478a353f2e5184f5c803164f22428b023
RNShare: a5dc3b9c53ddc73e155b8cd9a94c70c91913c43c
Expand Down
4 changes: 4 additions & 0 deletions packages/mobile/ios/StandardNotes.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
1C2EEB3B45F4EB07AC795C77 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
33BB1B14071EBE5978EBF3A8 /* libPods-StandardNotes-StandardNotesTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04FCB5A3A3387CA3CFC82AA3 /* libPods-StandardNotes-StandardNotesTests.a */; };
BC8DEA834BF198E8511F04FF /* libPods-StandardNotesDev.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F2D747BE02C2A1BCFEEFD1 /* libPods-StandardNotesDev.a */; };
CD6592A9291EEFCC00C09DC6 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD6592A8291EEFCC00C09DC6 /* StoreKit.framework */; };
CD7D5ECA27800609005FE1BF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CD7D5EC927800608005FE1BF /* LaunchScreen.storyboard */; };
CD7D5ECF278015D2005FE1BF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
CD7D5ED0278015D2005FE1BF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
Expand Down Expand Up @@ -59,6 +60,7 @@
66417CEB7622E77D89928FCA /* Pods-StandardNotes.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StandardNotes.debug.xcconfig"; path = "Target Support Files/Pods-StandardNotes/Pods-StandardNotes.debug.xcconfig"; sourceTree = "<group>"; };
948EE90E15EA48C27577820B /* Pods-StandardNotes.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StandardNotes.release.xcconfig"; path = "Target Support Files/Pods-StandardNotes/Pods-StandardNotes.release.xcconfig"; sourceTree = "<group>"; };
A09B7794259DBFABFC4D05CE /* Pods-StandardNotesDev.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StandardNotesDev.debug.xcconfig"; path = "Target Support Files/Pods-StandardNotesDev/Pods-StandardNotesDev.debug.xcconfig"; sourceTree = "<group>"; };
CD6592A8291EEFCC00C09DC6 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
CD7D5EC8278005B6005FE1BF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = StandardNotes/Info.plist; sourceTree = "<group>"; };
CD7D5EC927800608005FE1BF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
CD7D5EDF278015D2005FE1BF /* StandardNotesDev.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StandardNotesDev.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -86,6 +88,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
CD6592A9291EEFCC00C09DC6 /* StoreKit.framework in Frameworks */,
1C2EEB3B45F4EB07AC795C77 /* (null) in Frameworks */,
DD3D1CE428EC1C8BA0C49211 /* libPods-StandardNotes.a in Frameworks */,
);
Expand Down Expand Up @@ -153,6 +156,7 @@
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
isa = PBXGroup;
children = (
CD6592A8291EEFCC00C09DC6 /* StoreKit.framework */,
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
04FCB5A3A3387CA3CFC82AA3 /* libPods-StandardNotes-StandardNotesTests.a */,
51F2D747BE02C2A1BCFEEFD1 /* libPods-StandardNotesDev.a */,
Expand Down
1 change: 1 addition & 0 deletions packages/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"react-native-fingerprint-scanner": "standardnotes/react-native-fingerprint-scanner#b55d1c0ca627a87a130f758603f12911fbac200f",
"react-native-flag-secure-android": "standardnotes/react-native-flag-secure-android#cb08e74583c22a5d912842459b35ebbbb4bcd852",
"react-native-fs": "^2.19.0",
"react-native-iap": "^12.4.4",
"react-native-keychain": "standardnotes/react-native-keychain#d277d360494cbd02be4accb4a360772a8e0e97b6",
"react-native-privacy-snapshot": "standardnotes/react-native-privacy-snapshot#653e904c90fc6f2b578da59138f2bfe5d7f942fe",
"react-native-share": "^7.9.0",
Expand Down
9 changes: 8 additions & 1 deletion packages/mobile/src/Lib/Interface.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -11,6 +12,7 @@ import {
RawKeychainValue,
removeFromArray,
TransferPayload,
AppleIAPProductId,
UuidString,
} from '@standardnotes/snjs'
import { ColorSchemeObserverService } from 'ColorSchemeObserverService'
Expand Down Expand Up @@ -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'

Expand Down Expand Up @@ -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
Expand All @@ -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)
}
Expand Down
18 changes: 18 additions & 0 deletions packages/mobile/src/Lib/Logging.ts
Original file line number Diff line number Diff line change
@@ -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)
}
Loading