-
-
Notifications
You must be signed in to change notification settings - Fork 666
/
Copy pathandroid.ts
176 lines (153 loc) · 4.92 KB
/
android.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import {Linking, NativeModules} from 'react-native';
import {
checkNativeAndroidAvailable,
getAndroidModule,
isAndroid,
} from '../internal';
import {
InstallSourceAndroid,
Product,
ProductType,
Purchase,
PurchaseResult,
ReplacementModesAndroid,
Sku,
} from '../types';
import type * as Android from '../types/android';
import type {NativeModuleProps} from './common';
const {RNIapModule} = NativeModules;
type FlushFailedPurchasesCachedAsPending = () => Promise<boolean>;
type GetItemsByType = <T = Product>(
type: ProductType,
skus: Sku[],
) => Promise<T[]>;
type GetAvailableItemsByType = <T = Purchase>(
type: ProductType,
) => Promise<T[]>;
type GetPurchaseHistoryByType = <T = Purchase>(
type: ProductType,
) => Promise<T[]>;
export type BuyItemByType = (
type: string,
skus: Sku[],
purchaseToken: string | undefined,
externalTransactionIdAndroid: string | undefined,
replacementModeAndroid: ReplacementModesAndroid | -1,
obfuscatedAccountId: string | undefined,
obfuscatedProfileId: string | undefined,
subscriptionOffers: string[],
isOfferPersonalized: boolean,
) => Promise<Purchase>;
type AcknowledgePurchase = (
purchaseToken: string,
developerPayloadAndroid?: string,
) => Promise<PurchaseResult | boolean>;
type ConsumeProduct = (
purchaseToken: string,
developerPayloadAndroid?: string,
) => Promise<PurchaseResult | boolean>;
type StartListening = () => Promise<void>;
type GetPackageName = () => Promise<string>;
export interface AndroidModuleProps extends NativeModuleProps {
flushFailedPurchasesCachedAsPending: FlushFailedPurchasesCachedAsPending;
getItemsByType: GetItemsByType;
getAvailableItemsByType: GetAvailableItemsByType;
getPurchaseHistoryByType: GetPurchaseHistoryByType;
buyItemByType: BuyItemByType;
acknowledgePurchase: AcknowledgePurchase;
consumeProduct: ConsumeProduct;
/** @deprecated to be renamed to sendUnconsumedPurchases if not removed completely */
startListening: StartListening;
getPackageName: GetPackageName;
isFeatureSupported: (feature: Android.FeatureType) => Promise<boolean>;
}
export const AndroidModule = NativeModules.RNIapModule as AndroidModuleProps;
export const getInstallSourceAndroid = (): InstallSourceAndroid => {
return RNIapModule
? InstallSourceAndroid.GOOGLE_PLAY
: InstallSourceAndroid.AMAZON;
};
/**
* Deep link to subscriptions screen on Android.
* @param {string} sku The product's SKU (on Android)
* @returns {Promise<void>}
*/
export const deepLinkToSubscriptionsAndroid = async ({
sku,
}: {
sku: Sku;
}): Promise<void> => {
checkNativeAndroidAvailable();
return Linking.openURL(
`https://play.google.com/store/account/subscriptions?package=${await RNIapModule.getPackageName()}&sku=${sku}`,
);
};
/**
* Validate receipt for Android. NOTE: This method is here for debugging purposes only. Including
* your access token in the binary you ship to users is potentially dangerous.
* Use server side validation instead for your production builds
* @param {string} packageName package name of your app.
* @param {string} productId product id for your in app product.
* @param {string} productToken token for your purchase.
* @param {string} accessToken accessToken from googleApis.
* @param {boolean} isSub whether this is subscription or inapp. `true` for subscription.
* @returns {Promise<object>}
*/
export const validateReceiptAndroid = async ({
packageName,
productId,
productToken,
accessToken,
isSub,
}: {
packageName: string;
productId: string;
productToken: string;
accessToken: string;
isSub?: boolean;
}): Promise<Android.ReceiptType> => {
const type = isSub ? 'subscriptions' : 'products';
const url =
'https://androidpublisher.googleapis.com/androidpublisher/v3/applications' +
`/${packageName}/purchases/${type}/${productId}` +
`/tokens/${productToken}?access_token=${accessToken}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw Object.assign(new Error(response.statusText), {
statusCode: response.status,
});
}
return response.json();
};
/**
* Acknowledge a product (on Android.) No-op on iOS.
* @param {string} token The product's token (on Android)
* @returns {Promise<PurchaseResult | void>}
*/
export const acknowledgePurchaseAndroid = ({
token,
developerPayload,
}: {
token: string;
developerPayload?: string;
}): Promise<PurchaseResult | boolean | void> => {
return getAndroidModule().acknowledgePurchase(token, developerPayload);
};
/**
* Acknowledge a product (on Android.) No-op on iOS.
* @param {Android.FeatureType} feature to be checked
* @returns {Promise<boolean>}
*/
export const isFeatureSupported = (
feature: Android.FeatureType,
): Promise<boolean> => {
if (!(isAndroid && RNIapModule)) {
return Promise.reject('This is only available on Android clients');
}
return AndroidModule.isFeatureSupported(feature);
};