初步实现iap

This commit is contained in:
yezian 2024-05-28 16:05:56 +08:00
parent d41253352e
commit f28703244d
7 changed files with 719 additions and 548 deletions

2
.gitignore vendored
View File

@ -11,6 +11,8 @@ npm-debug.*
web-build/
test.jsx
example.jsx
ios
android
# macOS

1070
App.jsx

File diff suppressed because it is too large Load Diff

68
context/IapProvider.jsx Normal file
View File

@ -0,0 +1,68 @@
import React, { useState, createContext, useContext, useEffect } from "react";
import { Platform } from "react-native";
import Purchases, { LOG_LEVEL } from "react-native-purchases";
import { AuthContext } from "../App";
import { get } from "../utils/storeInfo";
const IapContext = createContext();
export const IapProvider = ({ children }) => {
const [isReady, setIsReady] = useState(false);
const [packages, setPackages] = useState([]);
const { state } = useContext(AuthContext);
useEffect(() => {
const init = async () => {
if (Platform.OS === "ios" && state.isSignin) {
const account = await get("account");
await Purchases.configure({
apiKey: process.env.EXPO_PUBLIC_RC_APPLE_KEY,
appUserID: account.mid.toString(),
});
Purchases.setLogLevel(LOG_LEVEL.DEBUG);
await loadOfferings();
}
setIsReady(true);
};
init();
}, [state]);
const loadOfferings = async () => {
const offerings = await Purchases.getOfferings();
if (offerings.current) {
setPackages(offerings.current.availablePackages);
}
};
const purchasePackage = async (pack) => {
if (Platform.OS !== "ios") return;
try {
await Purchases.purchasePackage(pack);
} catch (e) {
console.error(e);
}
};
const getCustomerInformation = async () => {
if (Platform.OS !== "ios") return;
try {
const customerInfo = await Purchases.getCustomerInfo();
return customerInfo;
} catch (e) {
console.error(e);
}
};
const value = {
packages,
purchasePackage,
getCustomerInformation,
};
if (!isReady) return <></>;
return <IapContext.Provider value={value}>{children}</IapContext.Provider>;
};
export const useIap = () => useContext(IapContext);

View File

@ -40,6 +40,7 @@
"expo-clipboard": "~5.0.1",
"expo-constants": "~15.4.5",
"expo-crypto": "~12.8.1",
"expo-dev-client": "~3.3.11",
"expo-device": "~5.9.3",
"expo-file-system": "~16.0.8",
"expo-image": "~1.10.6",
@ -66,6 +67,7 @@
"react-native-pager-view": "6.2.3",
"react-native-parsed-text": "^0.0.22",
"react-native-picker-select": "^8.1.0",
"react-native-purchases": "^7.27.2",
"react-native-reanimated": "~3.6.2",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",

View File

@ -8,6 +8,7 @@ import * as Clipboard from "expo-clipboard";
import Toast from "react-native-toast-message";
import MyModal from "../../components/MyModal";
import baseRequest from "../../utils/baseRequest";
import { useIap } from "../../context/IapProvider";
export default function WebWithHeader({ navigation, route }) {
//
@ -87,6 +88,13 @@ export default function WebWithHeader({ navigation, route }) {
Linking.openURL(data);
};
//iap
const { packages, purchasePackage } = useIap();
const purchase = async (product) => {
const pack = packages.find((p) => p.identifier === product);
await purchasePackage(pack);
};
//
const handleUrlRedirect = (event) => {
const { url } = event;
@ -154,14 +162,24 @@ export default function WebWithHeader({ navigation, route }) {
userAgent="FromWebview"
onMessage={async (event) => {
const msg = JSON.parse(event.nativeEvent.data);
if (msg.type === "SAVE_IMAGE") {
saveImage(msg.data);
} else if (msg.type === "COPY_URL") {
copy(msg.data);
} else if (msg.type === "NAVIGATE") {
navigation.navigate(msg.data.page, { ...msg.data.params });
} else if (msg.type === "OPEN_BROWSER") {
openBrowser(msg.data);
switch (msg.type) {
case "SAVE_IMAGE":
saveImage(msg.data);
break;
case "COPY_URL":
copy(msg.data);
break;
case "NAVIGATE":
navigation.navigate(msg.data.page, { ...msg.data.params });
break;
case "OPEN_BROWSER":
openBrowser(msg.data);
break;
case "IAP":
purchase(msg.data);
break;
default:
break;
}
}}
injectedJavaScript={setCookieScript}

View File

@ -8,6 +8,7 @@ import * as Clipboard from "expo-clipboard";
import Toast from "react-native-toast-message";
import MyModal from "../../components/MyModal";
import baseRequest from "../../utils/baseRequest";
import { useIap } from "../../context/IapProvider";
export default function WebWithoutHeader({ navigation, route }) {
//
@ -80,6 +81,13 @@ export default function WebWithoutHeader({ navigation, route }) {
Linking.openURL(data);
};
//iap
const { packages, purchasePackage } = useIap();
const purchase = async (product) => {
const pack = packages.find((p) => p.identifier === product);
await purchasePackage(pack);
};
//
const handleUrlRedirect = (event) => {
const { url } = event;
@ -147,14 +155,24 @@ export default function WebWithoutHeader({ navigation, route }) {
userAgent="FromWebview"
onMessage={async (event) => {
const msg = JSON.parse(event.nativeEvent.data);
if (msg.type === "SAVE_IMAGE") {
saveImage(msg.data);
} else if (msg.type === "COPY_URL") {
copy(msg.data);
} else if (msg.type === "NAVIGATE") {
navigation.navigate(msg.data.page, { ...msg.data.params });
} else if (msg.type === "OPEN_BROWSER") {
openBrowser(msg.data);
switch (msg.type) {
case "SAVE_IMAGE":
saveImage(msg.data);
break;
case "COPY_URL":
copy(msg.data);
break;
case "NAVIGATE":
navigation.navigate(msg.data.page, { ...msg.data.params });
break;
case "OPEN_BROWSER":
openBrowser(msg.data);
break;
case "IAP":
purchase(msg.data);
break;
default:
break;
}
}}
injectedJavaScript={setCookieScript}

View File

@ -2318,6 +2318,11 @@
dependencies:
nanoid "^3.1.23"
"@revenuecat/purchases-typescript-internal@10.6.2":
version "10.6.2"
resolved "https://registry.npmmirror.com/@revenuecat/purchases-typescript-internal/-/purchases-typescript-internal-10.6.2.tgz#718c9f6e74e5673f53a1b612f930713783c2eafe"
integrity sha512-bWSNwhCyiiB0CGq5092PsADBeFFtAIr4jshKghY37dtPa1jpqck0ga77+BWT9jN/J4Jtq1ME/dKKg0hIuGI+LQ==
"@rneui/base@^4.0.0-rc.8":
version "4.0.0-rc.8"
resolved "https://registry.npmmirror.com/@rneui/base/-/base-4.0.0-rc.8.tgz#6fbf9b3049a9207d47c3c53b70c0f68f3627a170"
@ -2755,6 +2760,16 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0"
indent-string "^4.0.0"
ajv@8.11.0:
version "8.11.0"
resolved "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f"
integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
require-from-string "^2.0.2"
uri-js "^4.2.2"
ajv@^8.11.0:
version "8.12.0"
resolved "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
@ -4065,6 +4080,41 @@ expo-crypto@~12.8.1:
dependencies:
base64-js "^1.3.0"
expo-dev-client@~3.3.11:
version "3.3.11"
resolved "https://registry.npmmirror.com/expo-dev-client/-/expo-dev-client-3.3.11.tgz#f2541ccbcfc2ba32bcea47293bc9beae4e10db60"
integrity sha512-9nhhbfbskfmjp/tlRS5KvDpCoW0BREJBxpu2GyjKu7nDB33W8fJLL0wXgNhP+QEb93r37o3uezKmUm2kibOvTw==
dependencies:
expo-dev-launcher "3.6.9"
expo-dev-menu "4.5.8"
expo-dev-menu-interface "1.7.2"
expo-manifests "~0.13.0"
expo-updates-interface "~0.15.1"
expo-dev-launcher@3.6.9:
version "3.6.9"
resolved "https://registry.npmmirror.com/expo-dev-launcher/-/expo-dev-launcher-3.6.9.tgz#5e104e0533a46f3614c1691673da3351092e8d1d"
integrity sha512-MBDMAqjCMVYt1Zv47u2dJTp4d8gCZMfM4GWAFhfQy3G6XzkUlFtewaQefAqy93FcYOv6BYdC9yZOLOb06tqTfA==
dependencies:
ajv "8.11.0"
expo-dev-menu "4.5.8"
expo-manifests "~0.13.0"
resolve-from "^5.0.0"
semver "^7.5.3"
expo-dev-menu-interface@1.7.2:
version "1.7.2"
resolved "https://registry.npmmirror.com/expo-dev-menu-interface/-/expo-dev-menu-interface-1.7.2.tgz#772fb97c6b0a44c27965cdfcfa078f316b0930ca"
integrity sha512-V/geSB9rW0IPTR+d7E5CcvkV0uVUCE7SMHZqE/J0/dH06Wo8AahB16fimXeh5/hTL2Qztq8CQ41xpFUBoA9TEw==
expo-dev-menu@4.5.8:
version "4.5.8"
resolved "https://registry.npmmirror.com/expo-dev-menu/-/expo-dev-menu-4.5.8.tgz#21940385124c7d2745066bbcb42185ebd35f66bc"
integrity sha512-GXfI0CmYlqjOqyFjtplXO9PSoJQoy89+50lbUSNZykDsGyvzCPzl4txdQcdHHSglKYr7lWV7aeMVeehuSct60w==
dependencies:
expo-dev-menu-interface "1.7.2"
semver "^7.5.3"
expo-device@~5.9.3:
version "5.9.3"
resolved "https://registry.npmmirror.com/expo-device/-/expo-device-5.9.3.tgz#0ad61da681424aa682fa03001d0344394c01f8a1"
@ -6587,6 +6637,13 @@ react-native-picker-select@^8.1.0:
"@react-native-picker/picker" "^1.8.3"
lodash.isequal "^4.5.0"
react-native-purchases@^7.27.2:
version "7.27.2"
resolved "https://registry.npmmirror.com/react-native-purchases/-/react-native-purchases-7.27.2.tgz#435eecb86db412e66c81a9cd0887a726a17b8135"
integrity sha512-sLO85vTehwS4rlBJRmBYersIuNjmcjRJKvd5YY6y5xBVkw80LRJDmp7NTEfN9Dzp36XxnGb8KYcKOz1ZkubCXg==
dependencies:
"@revenuecat/purchases-typescript-internal" "10.6.2"
react-native-ratings@^8.1.0:
version "8.1.0"
resolved "https://registry.npmmirror.com/react-native-ratings/-/react-native-ratings-8.1.0.tgz#3fa9ad29128dc3a88e59518ba151e61c59dd0647"