基本完成iap和金币支付
This commit is contained in:
parent
f28703244d
commit
eba607cd10
4
.env
4
.env
|
@ -1,3 +1,5 @@
|
|||
EXPO_PUBLIC_API_URL=https://api.tiefen.fun
|
||||
EXPO_PUBLIC_RSA_KEY=-----BEGIN PUBLIC KEY-----MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMXPIjKV6CMi5O9tIXJWNIfnqXjqOZ1KmRByRAP073DU+gzMLygzEsrztJzbz/K/Julkz6XhheZ8vdz+boAl1HsCAwEAAQ==-----END PUBLIC KEY-----
|
||||
EXPO_PUBLIC_WEB_URL=https://tiefen.fun
|
||||
EXPO_PUBLIC_WEB_URL=https://tiefen.fun
|
||||
EXPO_PUBLIC_RC_APPLE_KEY=appl_QkkgJKLkfdCfcwPvsncIdbwPwQk
|
||||
SENTRY_AUTH_TOKEN=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
|
|
@ -0,0 +1,245 @@
|
|||
import { View, Text, Modal, TouchableOpacity } from "react-native";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
import { Button } from "@rneui/themed";
|
||||
import Toast from "react-native-toast-message";
|
||||
import baseRequest from "../../utils/baseRequest";
|
||||
import { generateSignature } from "../../utils/crypto";
|
||||
import { get } from "../../utils/storeInfo";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
|
||||
export default function CoinPayModal({
|
||||
visible,
|
||||
setVisible,
|
||||
url,
|
||||
body = {},
|
||||
product,
|
||||
coinPrice,
|
||||
validity,
|
||||
info,
|
||||
onPurchaseDone = () => {},
|
||||
}) {
|
||||
const tailwind = useTailwind();
|
||||
const navigation = useNavigation();
|
||||
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
|
||||
|
||||
//用户金币余额
|
||||
const [coinBalance, setCoinBalance] = useState();
|
||||
useEffect(() => {
|
||||
if (!visible) {
|
||||
setIsCoinEnough(true);
|
||||
setIsWaitingConfirm(false);
|
||||
return;
|
||||
}
|
||||
const init = async () => {
|
||||
const base = await baseRequest();
|
||||
const account = await get("account");
|
||||
const body = {
|
||||
...base,
|
||||
mid: account.mid,
|
||||
};
|
||||
const signature = await generateSignature(body);
|
||||
const _response = await fetch(
|
||||
`${apiUrl}/api/account/list_by_mid?signature=${signature}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
}
|
||||
);
|
||||
const _data = await _response.json();
|
||||
if (_data.ret === -1) {
|
||||
Toast.show({
|
||||
type: "error",
|
||||
text1: _data.msg,
|
||||
topOffset: 60,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setCoinBalance(_data.data.account.gold_num);
|
||||
};
|
||||
init();
|
||||
}, [visible]);
|
||||
|
||||
//判断余额是否充足
|
||||
const [isCoinEnough, setIsCoinEnough] = useState(true);
|
||||
const [isWaitingConfirm, setIsWaitingConfirm] = useState(false);
|
||||
const checkCoinBalance = async () => {
|
||||
if (coinBalance < coinPrice) {
|
||||
setIsCoinEnough(false);
|
||||
return;
|
||||
}
|
||||
setIsWaitingConfirm(true);
|
||||
};
|
||||
|
||||
//进行金币支付
|
||||
const handleCoinPay = async () => {
|
||||
try {
|
||||
const base = await baseRequest();
|
||||
const _body = {
|
||||
...base,
|
||||
...body,
|
||||
pay_type: "coin",
|
||||
from: "app",
|
||||
};
|
||||
const signature = await generateSignature(_body);
|
||||
const _response = await fetch(`${apiUrl + url}?signature=${signature}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(_body),
|
||||
});
|
||||
const _data = await _response.json();
|
||||
if (_data.ret === -1) {
|
||||
Toast.show({
|
||||
type: "error",
|
||||
text1: _data.msg,
|
||||
topOffset: 60,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setVisible(false);
|
||||
onPurchaseDone();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
transparent={true}
|
||||
statusBarTranslucent
|
||||
animationType="fade"
|
||||
>
|
||||
<TouchableOpacity
|
||||
activeOpacity={1}
|
||||
onPress={() => setVisible(false)}
|
||||
style={{
|
||||
backgroundColor: "#00000080",
|
||||
...tailwind("flex-1 justify-center items-center"),
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity
|
||||
activeOpacity={1}
|
||||
style={tailwind("p-4 rounded-2xl bg-[#17161A] items-center w-3/4")}
|
||||
>
|
||||
<View style={tailwind("flex flex-col w-full px-4")}>
|
||||
{isCoinEnough ? (
|
||||
isWaitingConfirm ? (
|
||||
<>
|
||||
<Text
|
||||
style={tailwind(
|
||||
"text-white text-xl font-semibold text-center mt-2"
|
||||
)}
|
||||
>
|
||||
本次消费将扣除您{coinPrice}金币,是否确认购买?
|
||||
</Text>
|
||||
<Text style={tailwind("text-white text-sm text-center mt-2")}>
|
||||
当前余额:{coinBalance}金币
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text
|
||||
style={tailwind("text-white text-xl font-semibold mt-2")}
|
||||
>
|
||||
项目:{product}
|
||||
</Text>
|
||||
<Text
|
||||
style={tailwind("text-white text-xl font-semibold mt-2")}
|
||||
>
|
||||
价格:{coinPrice}金币
|
||||
</Text>
|
||||
<Text style={tailwind("text-[#FFFFFF80] text-sm mt-2")}>
|
||||
( 1 RMB = 10 金币 )
|
||||
</Text>
|
||||
{validity && (
|
||||
<Text
|
||||
style={tailwind("text-white text-xl font-semibold mt-2")}
|
||||
>
|
||||
有效期:{validity}
|
||||
</Text>
|
||||
)}
|
||||
{info && (
|
||||
<Text style={tailwind("text-[#FFFFFF80] text-sm mt-2")}>
|
||||
{info}
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
) : (
|
||||
<>
|
||||
<Text
|
||||
style={tailwind(
|
||||
"text-white text-xl font-semibold text-center mt-2"
|
||||
)}
|
||||
>
|
||||
余额不足,请先充值金币
|
||||
</Text>
|
||||
<Text style={tailwind("text-white text-sm text-center mt-2")}>
|
||||
当前余额:{coinBalance}金币
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
{!isWaitingConfirm && isCoinEnough && (
|
||||
<Button
|
||||
onPress={checkCoinBalance}
|
||||
color="#FF669E"
|
||||
radius="999"
|
||||
size="md"
|
||||
titleStyle={tailwind("text-base")}
|
||||
containerStyle={tailwind("w-full mt-4")}
|
||||
>
|
||||
购买
|
||||
</Button>
|
||||
)}
|
||||
{isWaitingConfirm && (
|
||||
<Button
|
||||
onPress={handleCoinPay}
|
||||
color="#FF669E"
|
||||
radius="999"
|
||||
size="md"
|
||||
titleStyle={tailwind("text-base")}
|
||||
containerStyle={tailwind("w-full mt-4")}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
)}
|
||||
{!isCoinEnough && (
|
||||
<Button
|
||||
onPress={() => {
|
||||
navigation.navigate("Wallet");
|
||||
setVisible(false);
|
||||
setIsCoinEnough(true);
|
||||
}}
|
||||
color="#FF669E"
|
||||
radius="999"
|
||||
size="md"
|
||||
titleStyle={tailwind("text-base")}
|
||||
containerStyle={tailwind("w-full mt-4")}
|
||||
>
|
||||
前往充值
|
||||
</Button>
|
||||
)}
|
||||
<TouchableOpacity
|
||||
onPress={() => setVisible(false)}
|
||||
style={tailwind("mt-4")}
|
||||
>
|
||||
<Text
|
||||
style={tailwind(
|
||||
"text-[#FFFFFF80] text-base font-medium text-center"
|
||||
)}
|
||||
>
|
||||
取消
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</TouchableOpacity>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -22,6 +22,7 @@ import { Icon } from "@rneui/themed";
|
|||
import ParsedText from "react-native-parsed-text";
|
||||
import * as Linking from "expo-linking";
|
||||
import { useImageViewer } from "../../context/ImageViewProvider";
|
||||
import CoinPayModal from "../CoinPayModal";
|
||||
|
||||
//todo:完善视频逻辑;完善图片模糊逻辑
|
||||
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
|
||||
|
@ -34,6 +35,9 @@ export default function SpacePost({ data }) {
|
|||
);
|
||||
const [showVideo, setShowVideo] = useState(false);
|
||||
|
||||
//金币支付Modal是否展示
|
||||
const [isCoinPayModalVisible, setIsCoinPayModalVisible] = useState(false);
|
||||
|
||||
//是否查看全文
|
||||
const [isFullTextBtnShow, setIsFullTextBtnShow] = useState(false);
|
||||
const [isTextCollapsed, setIsTextCollapsed] = useState(true);
|
||||
|
@ -301,7 +305,11 @@ export default function SpacePost({ data }) {
|
|||
{data.c_type === 1 && data.is_zone_moment_unlocked === 0 && (
|
||||
<TouchableOpacity
|
||||
activeOpacity={1}
|
||||
onPress={() =>
|
||||
onPress={() => {
|
||||
if (Platform.OS === "ios") {
|
||||
setIsCoinPayModalVisible(true);
|
||||
return;
|
||||
}
|
||||
navigation.navigate("WebWithoutHeader", {
|
||||
uri:
|
||||
process.env.EXPO_PUBLIC_WEB_URL +
|
||||
|
@ -309,8 +317,8 @@ export default function SpacePost({ data }) {
|
|||
data?.zid +
|
||||
"/h5_zone_moment/" +
|
||||
data?.id,
|
||||
})
|
||||
}
|
||||
});
|
||||
}}
|
||||
style={{
|
||||
backgroundColor:
|
||||
data.is_ironfan_visible === 1 ? "#301024" : "#331F0B",
|
||||
|
@ -335,7 +343,9 @@ export default function SpacePost({ data }) {
|
|||
...tailwind("text-base font-semibold ml-1"),
|
||||
}}
|
||||
>
|
||||
{data.price / 100}
|
||||
{Platform.OS === "ios"
|
||||
? data.coin_price
|
||||
: data.price / 100}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
|
@ -344,7 +354,7 @@ export default function SpacePost({ data }) {
|
|||
...tailwind("text-sm font-medium"),
|
||||
}}
|
||||
>
|
||||
元
|
||||
{Platform.OS === "ios" ? "金币" : "元"}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={tailwind("flex flex-row items-center")}>
|
||||
|
@ -373,7 +383,11 @@ export default function SpacePost({ data }) {
|
|||
</View>
|
||||
{data.is_ironfan_visible === 1 && (
|
||||
<Text style={tailwind("text-xs text-[#FFFFFF40] mt-1")}>
|
||||
空间内任意消费满{data.ironfanship_price / 100}元即可成为铁粉
|
||||
空间内任意消费满
|
||||
{Platform.OS === "ios"
|
||||
? data.ironfanship_coin_price + "金币"
|
||||
: data.ironfanship_price / 100 + "元"}
|
||||
即可成为铁粉
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
@ -412,7 +426,9 @@ export default function SpacePost({ data }) {
|
|||
...tailwind("text-base font-semibold ml-1"),
|
||||
}}
|
||||
>
|
||||
{data.price / 100}
|
||||
{Platform.OS === "ios"
|
||||
? data.coin_price
|
||||
: data.price / 100}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
|
@ -423,7 +439,7 @@ export default function SpacePost({ data }) {
|
|||
...tailwind("text-sm font-medium"),
|
||||
}}
|
||||
>
|
||||
元
|
||||
{Platform.OS === "ios" ? "金币" : "元"}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={tailwind("flex flex-row items-center")}>
|
||||
|
@ -494,7 +510,9 @@ export default function SpacePost({ data }) {
|
|||
...tailwind("text-base font-semibold ml-1"),
|
||||
}}
|
||||
>
|
||||
{data.price / 100}
|
||||
{Platform.OS === "ios"
|
||||
? data.coin_price
|
||||
: data.price / 100}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
|
@ -503,7 +521,7 @@ export default function SpacePost({ data }) {
|
|||
...tailwind("text-sm font-medium"),
|
||||
}}
|
||||
>
|
||||
元
|
||||
{Platform.OS === "ios" ? "金币" : "元"}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={tailwind("flex flex-row items-center")}>
|
||||
|
@ -528,7 +546,11 @@ export default function SpacePost({ data }) {
|
|||
</View>
|
||||
{data.is_ironfan_visible === 1 && (
|
||||
<Text style={tailwind("text-xs text-[#FFFFFF40] mt-1")}>
|
||||
空间内任意消费满{data.ironfanship_price / 100}元即可成为铁粉
|
||||
空间内任意消费满
|
||||
{Platform.OS === "ios"
|
||||
? data.ironfanship_coin_price + "金币"
|
||||
: data.ironfanship_price / 100 + "元"}
|
||||
即可成为铁粉
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
@ -585,6 +607,27 @@ export default function SpacePost({ data }) {
|
|||
</View>
|
||||
</View>
|
||||
<View style={tailwind("h-[3px] rounded-full mx-4 bg-[#FFFFFF26]")}></View>
|
||||
{/* 金币支付Modal */}
|
||||
<CoinPayModal
|
||||
visible={isCoinPayModalVisible}
|
||||
setVisible={setIsCoinPayModalVisible}
|
||||
url="/api/zone/create_order"
|
||||
body={{
|
||||
zid: data?.zid,
|
||||
moment_id: data?.id,
|
||||
product_id: "h5_zone_moment",
|
||||
}}
|
||||
product="单条付费动态"
|
||||
coinPrice={data?.coin_price}
|
||||
info="购买完成后,请刷新当前页面查看"
|
||||
onPurchaseDone={() =>
|
||||
Toast.show({
|
||||
type: "success",
|
||||
text1: "购买完成,请刷新当前页面查看",
|
||||
topOffset: 60,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Platform } from "react-native";
|
|||
import Purchases, { LOG_LEVEL } from "react-native-purchases";
|
||||
import { AuthContext } from "../App";
|
||||
import { get } from "../utils/storeInfo";
|
||||
import Toast from "react-native-toast-message";
|
||||
|
||||
const IapContext = createContext();
|
||||
|
||||
|
@ -54,10 +55,25 @@ export const IapProvider = ({ children }) => {
|
|||
}
|
||||
};
|
||||
|
||||
const restorePurchases = async () => {
|
||||
if (Platform.OS !== "ios") return;
|
||||
try {
|
||||
await Purchases.restorePurchases();
|
||||
Toast.show({
|
||||
type: "success",
|
||||
text1: "恢复成功",
|
||||
topOffset: 60,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const value = {
|
||||
packages,
|
||||
purchasePackage,
|
||||
getCustomerInformation,
|
||||
restorePurchases,
|
||||
};
|
||||
|
||||
if (!isReady) return <></>;
|
||||
|
|
|
@ -23,7 +23,7 @@ export default function Login() {
|
|||
const [index, setIndex] = useState(0);
|
||||
const [routes] = useState([
|
||||
{ key: "phoneNumLogin", title: "验证码登录" },
|
||||
{ key: "passwordLogin", title: "账号密码登陆" },
|
||||
{ key: "passwordLogin", title: "账号密码登录" },
|
||||
]);
|
||||
|
||||
const renderScene = useCallback(
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
TouchableOpacity,
|
||||
ScrollView,
|
||||
Image as NativeImage,
|
||||
Platform,
|
||||
} from "react-native";
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
|
@ -24,7 +25,7 @@ export default function My({ navigation }) {
|
|||
|
||||
//获取当前页面数据
|
||||
const [data, setData] = useState();
|
||||
const [vipPrice, setVipPrice] = useState();
|
||||
const [vipPrice, setVipPrice] = useState({});
|
||||
useEffect(() => {
|
||||
const initData = async () => {
|
||||
const account = await get("account");
|
||||
|
@ -59,7 +60,7 @@ export default function My({ navigation }) {
|
|||
});
|
||||
return;
|
||||
}
|
||||
setVipPrice(_data.data.product.real_price / 100);
|
||||
setVipPrice(_data.data.product);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
@ -352,7 +353,9 @@ export default function My({ navigation }) {
|
|||
activeOpacity={1}
|
||||
onPress={() =>
|
||||
navigation.navigate("WebWithoutHeader", {
|
||||
uri: process.env.EXPO_PUBLIC_WEB_URL + "/vip",
|
||||
uri:
|
||||
process.env.EXPO_PUBLIC_WEB_URL +
|
||||
`/vip?use_coinpay=${Platform.OS === "ios" ? "1" : "0"}`,
|
||||
})
|
||||
}
|
||||
style={tailwind(
|
||||
|
@ -388,7 +391,12 @@ export default function My({ navigation }) {
|
|||
)}
|
||||
>
|
||||
<Text style={tailwind("text-white text-sm font-medium")}>
|
||||
¥{vipPrice}/永久
|
||||
{`${
|
||||
Platform.OS === "ios"
|
||||
? vipPrice?.real_coin_price + "金币"
|
||||
: "¥" + vipPrice?.real_price / 100
|
||||
}`}
|
||||
/永久
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { View, Text } from "react-native";
|
||||
import React from "react";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import Toast from "react-native-toast-message";
|
||||
|
||||
export default function RechargeGold({ navigation, route }) {
|
||||
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
|
||||
|
||||
const tailwind = useTailwind();
|
||||
const insets = useSafeAreaInsets();
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
paddingTop: insets.top,
|
||||
paddingBottom: insets.bottom,
|
||||
paddingLeft: insets.left,
|
||||
paddingRight: insets.right,
|
||||
...tailwind("flex-1"),
|
||||
}}
|
||||
>
|
||||
<Text>Example</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,10 @@
|
|||
import { View, Text, ScrollView, TouchableOpacity } from "react-native";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
Platform,
|
||||
} from "react-native";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
@ -6,11 +12,15 @@ import { Icon, Button } from "@rneui/themed";
|
|||
import * as FileSystem from "expo-file-system";
|
||||
import { AuthContext } from "../../../App";
|
||||
import MyDivider from "../../../components/MyDivider";
|
||||
import { useIap } from "../../../context/IapProvider";
|
||||
|
||||
export default function SelectSettingItem({ navigation }) {
|
||||
const tailwind = useTailwind();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
//恢复购买
|
||||
const { restorePurchases } = useIap();
|
||||
|
||||
//点击退出登陆
|
||||
const { signOut } = useContext(AuthContext);
|
||||
|
||||
|
@ -67,6 +77,16 @@ export default function SelectSettingItem({ navigation }) {
|
|||
<SettingItem title="黑名单" to="BannedList" />
|
||||
<SettingItem title="意见反馈" to="Feedback" />
|
||||
<SettingItem title="账号注销" to="DeleteAccount" />
|
||||
{Platform.OS === "ios" && (
|
||||
<TouchableOpacity
|
||||
onPress={restorePurchases}
|
||||
style={tailwind("flex-row justify-between pt-4 pb-2")}
|
||||
>
|
||||
<Text style={tailwind("text-base text-white")}>恢复购买</Text>
|
||||
<Icon name="chevron-forward-outline" type="ionicon" color="white" />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<MyDivider />
|
||||
<TouchableOpacity
|
||||
onPress={clearCache}
|
||||
style={tailwind("flex-row justify-between pt-4 pb-2")}
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
Image as NativeImage,
|
||||
TouchableOpacity,
|
||||
ScrollView,
|
||||
Platform,
|
||||
} from "react-native";
|
||||
import React, { useState, useCallback } from "react";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
|
@ -20,6 +21,7 @@ import SpaceIntroduceSkeleton from "./skeleton";
|
|||
import { usePreventScreenCapture } from "expo-screen-capture";
|
||||
import { useFocusEffect } from "@react-navigation/native";
|
||||
import { useImageViewer } from "../../context/ImageViewProvider";
|
||||
import CoinPayModal from "../../components/CoinPayModal";
|
||||
|
||||
export default function SpaceIntroduce({ navigation, route }) {
|
||||
usePreventScreenCapture();
|
||||
|
@ -130,6 +132,9 @@ export default function SpaceIntroduce({ navigation, route }) {
|
|||
//是否展示视频Modal
|
||||
const [showVideo, setShowVideo] = useState(false);
|
||||
|
||||
//金币支付Modal是否展示
|
||||
const [isCoinPayModalVisible, setIsCoinPayModalVisible] = useState(false);
|
||||
|
||||
//加载初始骨架屏
|
||||
if (isLoading) return <SpaceIntroduceSkeleton />;
|
||||
|
||||
|
@ -345,14 +350,19 @@ export default function SpaceIntroduce({ navigation, route }) {
|
|||
onPress={
|
||||
data?.admission_price === 0
|
||||
? handleJoinFreeSpace
|
||||
: () =>
|
||||
: () => {
|
||||
if (Platform.OS === "ios") {
|
||||
setIsCoinPayModalVisible(true);
|
||||
return;
|
||||
}
|
||||
navigation.navigate("WebWithoutHeader", {
|
||||
uri:
|
||||
process.env.EXPO_PUBLIC_WEB_URL +
|
||||
"/zone/pay/" +
|
||||
data?.id +
|
||||
"/h5_zone_admission/0",
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
style={tailwind(
|
||||
"flex flex-row items-center justify-center h-12 rounded-full px-10 bg-[#FF669E]"
|
||||
|
@ -367,12 +377,28 @@ export default function SpaceIntroduce({ navigation, route }) {
|
|||
<Text style={tailwind("text-base text-white font-medium ml-2")}>
|
||||
{data?.admission_price === 0
|
||||
? "免费加入"
|
||||
: `${data?.admission_price / 100}元立即加入`}
|
||||
: `${
|
||||
Platform.OS === "ios"
|
||||
? data?.admission_coin_price + "金币"
|
||||
: data?.admission_price / 100 + "元"
|
||||
}立即加入`}
|
||||
</Text>
|
||||
<NativeImage source={require("../../assets/icon/32DP/link.png")} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
{/* 金币支付Modal */}
|
||||
<CoinPayModal
|
||||
visible={isCoinPayModalVisible}
|
||||
setVisible={setIsCoinPayModalVisible}
|
||||
url="/api/zone/create_order"
|
||||
body={{ zid: data?.id, product_id: "h5_zone_admission" }}
|
||||
product="当前空间成员"
|
||||
coinPrice={data?.admission_coin_price}
|
||||
onPurchaseDone={() =>
|
||||
navigation.replace("SpaceIntroduce", route.params)
|
||||
}
|
||||
/>
|
||||
{/* 查看微信Modal */}
|
||||
{data?.streamer_ext?.wechat_lock_type === 0 ? (
|
||||
<GetWechatModal
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
Animated,
|
||||
Easing,
|
||||
Modal,
|
||||
Platform,
|
||||
} from "react-native";
|
||||
import React, { useState, useEffect, useCallback, useMemo } from "react";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
|
@ -30,6 +31,7 @@ import { LinearGradient } from "expo-linear-gradient";
|
|||
import { usePreventScreenCapture } from "expo-screen-capture";
|
||||
import { Svg, Path } from "react-native-svg";
|
||||
import MyModal from "../../components/MyModal";
|
||||
import CoinPayModal from "../../components/CoinPayModal";
|
||||
|
||||
export default function StreamerSpace({ navigation, route }) {
|
||||
usePreventScreenCapture();
|
||||
|
@ -45,6 +47,9 @@ export default function StreamerSpace({ navigation, route }) {
|
|||
//退款中Modal是否展示
|
||||
const [isRefundingModalVisible, setIsRefundingModalVisible] = useState(false);
|
||||
|
||||
//金币支付Modal是否展示
|
||||
const [isCoinPayModalVisible, setIsCoinPayModalVisible] = useState(false);
|
||||
|
||||
//获取空间数据并将该空间标为已读
|
||||
const [data, setData] = useState({});
|
||||
const getData = async () => {
|
||||
|
@ -257,14 +262,37 @@ export default function StreamerSpace({ navigation, route }) {
|
|||
color="#FF669E"
|
||||
variant="determinate"
|
||||
/>
|
||||
<Text style={tailwind("text-sm text-[#FF669E] font-medium")}>{`${
|
||||
data?.expenditure / 100
|
||||
} / ${data?.ironfanship_price / 100}`}</Text>
|
||||
<Text style={tailwind("text-sm font-medium text-[#FFFFFF80] mt-2")}>
|
||||
空间内累计消费达到¥{data?.ironfanship_price / 100}即可成为
|
||||
<Text style={tailwind("text-[#FF669E]")}>铁粉</Text>
|
||||
,可查看所有铁粉专享内容哦,快来成为我的铁粉吧~
|
||||
</Text>
|
||||
{Platform.OS === "ios" ? (
|
||||
<>
|
||||
<Text
|
||||
style={tailwind("text-sm text-[#FF669E] font-medium")}
|
||||
>{`${data?.expenditure / 10} / ${
|
||||
data?.ironfanship_coin_price
|
||||
}`}</Text>
|
||||
<Text
|
||||
style={tailwind("text-sm font-medium text-[#FFFFFF80] mt-2")}
|
||||
>
|
||||
空间内累计消费达到{data?.ironfanship_coin_price}金币即可成为
|
||||
<Text style={tailwind("text-[#FF669E]")}>铁粉</Text>
|
||||
,可查看所有铁粉专享内容哦,快来成为我的铁粉吧~
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text
|
||||
style={tailwind("text-sm text-[#FF669E] font-medium")}
|
||||
>{`${data?.expenditure / 100} / ${
|
||||
data?.ironfanship_price / 100
|
||||
}`}</Text>
|
||||
<Text
|
||||
style={tailwind("text-sm font-medium text-[#FFFFFF80] mt-2")}
|
||||
>
|
||||
空间内累计消费达到¥{data?.ironfanship_price / 100}即可成为
|
||||
<Text style={tailwind("text-[#FF669E]")}>铁粉</Text>
|
||||
,可查看所有铁粉专享内容哦,快来成为我的铁粉吧~
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
onPress={() => {
|
||||
setIndex(1);
|
||||
|
@ -444,10 +472,15 @@ export default function StreamerSpace({ navigation, route }) {
|
|||
...tailwind("text-[#FFFFFF80] font-medium mt-0.5"),
|
||||
}}
|
||||
>
|
||||
{`${parseInt(data?.expenditure / 100, 10)}/${parseInt(
|
||||
data?.ironfanship_price / 100,
|
||||
10
|
||||
)}`}
|
||||
{Platform.OS === "ios"
|
||||
? `${parseInt(data?.expenditure / 10, 10)}/${parseInt(
|
||||
data?.ironfanship_coin_price,
|
||||
10
|
||||
)}`
|
||||
: `${parseInt(data?.expenditure / 100, 10)}/${parseInt(
|
||||
data?.ironfanship_price / 100,
|
||||
10
|
||||
)}`}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
@ -456,14 +489,19 @@ export default function StreamerSpace({ navigation, route }) {
|
|||
onPress={
|
||||
data?.is_superfanship_unlocked === 1
|
||||
? () => setIndex(2)
|
||||
: () =>
|
||||
: () => {
|
||||
if (Platform.OS === "ios") {
|
||||
setIsCoinPayModalVisible(true);
|
||||
return;
|
||||
}
|
||||
navigation.navigate("WebWithoutHeader", {
|
||||
uri:
|
||||
process.env.EXPO_PUBLIC_WEB_URL +
|
||||
"/zone/pay/" +
|
||||
data?.id +
|
||||
"/h5_zone_superfanship/0",
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
style={tailwind("flex flex-col items-center")}
|
||||
>
|
||||
|
@ -477,6 +515,16 @@ export default function StreamerSpace({ navigation, route }) {
|
|||
? "尊贵超粉"
|
||||
: "成为超粉"}
|
||||
</Text>
|
||||
{data?.is_superfanship_give_wechat === 1 && (
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 10,
|
||||
...tailwind("text-[#FFFFFF80] font-medium mt-0.5"),
|
||||
}}
|
||||
>
|
||||
赠微信
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<TouchableOpacity
|
||||
|
@ -568,14 +616,19 @@ export default function StreamerSpace({ navigation, route }) {
|
|||
onPress={
|
||||
data?.is_superfanship_unlocked === 1
|
||||
? () => setIndex(2)
|
||||
: () =>
|
||||
: () => {
|
||||
if (Platform.OS === "ios") {
|
||||
setIsCoinPayModalVisible(true);
|
||||
return;
|
||||
}
|
||||
navigation.navigate("WebWithoutHeader", {
|
||||
uri:
|
||||
process.env.EXPO_PUBLIC_WEB_URL +
|
||||
"/zone/pay/" +
|
||||
data?.id +
|
||||
"/h5_zone_superfanship/0",
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
style={tailwind("flex flex-col items-center")}
|
||||
>
|
||||
|
@ -589,6 +642,16 @@ export default function StreamerSpace({ navigation, route }) {
|
|||
? "尊贵超粉"
|
||||
: "成为超粉"}
|
||||
</Text>
|
||||
{data?.is_superfanship_give_wechat === 1 && (
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 10,
|
||||
...tailwind("text-[#FFFFFF80] font-medium mt-0.5"),
|
||||
}}
|
||||
>
|
||||
赠微信
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<TouchableOpacity
|
||||
|
@ -612,15 +675,36 @@ export default function StreamerSpace({ navigation, route }) {
|
|||
...tailwind("text-[#FFFFFF80] font-medium mt-0.5"),
|
||||
}}
|
||||
>
|
||||
{`${parseInt(data?.expenditure / 100, 10)}/${parseInt(
|
||||
data?.ironfanship_price / 100,
|
||||
10
|
||||
)}`}
|
||||
{Platform.OS === "ios"
|
||||
? `${parseInt(data?.expenditure / 10, 10)}/${parseInt(
|
||||
data?.ironfanship_coin_price,
|
||||
10
|
||||
)}`
|
||||
: `${parseInt(data?.expenditure / 100, 10)}/${parseInt(
|
||||
data?.ironfanship_price / 100,
|
||||
10
|
||||
)}`}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
{/* 金币支付Modal */}
|
||||
<CoinPayModal
|
||||
visible={isCoinPayModalVisible}
|
||||
setVisible={setIsCoinPayModalVisible}
|
||||
url="/api/zone/create_order"
|
||||
body={{ zid: data?.id, product_id: "h5_zone_superfanship" }}
|
||||
product="当前空间超粉"
|
||||
coinPrice={data?.superfanship_coin_price}
|
||||
validity={data?.superfanship_validity}
|
||||
info={`开通后可免费查看本空间内全部动态${
|
||||
data?.is_superfanship_give_wechat === 1 && ",并且解锁Ta的微信。"
|
||||
}`}
|
||||
onPurchaseDone={() =>
|
||||
navigation.replace("StreamerSpace", route.params)
|
||||
}
|
||||
/>
|
||||
{/* 点击成为铁粉Modal */}
|
||||
<BecomeIronFanModal />
|
||||
{/* 创建帖子Modal */}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { View, Text, Image, TouchableOpacity } from "react-native";
|
||||
import { View, Text, Image, TouchableOpacity, Platform } from "react-native";
|
||||
import React, { useState, useCallback } from "react";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
@ -11,12 +11,16 @@ import Toast from "react-native-toast-message";
|
|||
import * as Linking from "expo-linking";
|
||||
import { generateSignature } from "../../utils/crypto";
|
||||
import { useFocusEffect } from "@react-navigation/native";
|
||||
import { useIap } from "../../context/IapProvider";
|
||||
|
||||
export default function Wallet({ navigation, route }) {
|
||||
const tailwind = useTailwind();
|
||||
const insets = useSafeAreaInsets();
|
||||
const headerHeight = useHeaderHeight();
|
||||
|
||||
//获取iap商品
|
||||
const { packages } = useIap();
|
||||
|
||||
const [tokenAndMobilePhone, setTokenAndMobilePhone] = useState("");
|
||||
const [data, setData] = useState("");
|
||||
//每次focus都更新一次数据
|
||||
|
@ -121,7 +125,14 @@ export default function Wallet({ navigation, route }) {
|
|||
onPress={() =>
|
||||
navigation.navigate("WebWithHeader", {
|
||||
title: "充值中心",
|
||||
uri: process.env.EXPO_PUBLIC_WEB_URL + "/pay",
|
||||
uri:
|
||||
process.env.EXPO_PUBLIC_WEB_URL +
|
||||
`/pay${
|
||||
Platform.OS === "ios"
|
||||
? "?product=" +
|
||||
encodeURIComponent(JSON.stringify(packages))
|
||||
: ""
|
||||
}`,
|
||||
})
|
||||
}
|
||||
style={tailwind("flex-row justify-between items-center py-4")}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { Alert } from "react-native";
|
||||
import { Alert, Modal, View, Text } from "react-native";
|
||||
import { WebView } from "react-native-webview";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import * as MediaLibrary from "expo-media-library";
|
||||
|
@ -9,8 +9,12 @@ import Toast from "react-native-toast-message";
|
|||
import MyModal from "../../components/MyModal";
|
||||
import baseRequest from "../../utils/baseRequest";
|
||||
import { useIap } from "../../context/IapProvider";
|
||||
import CoinPayModal from "../../components/CoinPayModal";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
import { Icon } from "@rneui/themed";
|
||||
|
||||
export default function WebWithHeader({ navigation, route }) {
|
||||
const tailwind = useTailwind();
|
||||
//设置页面标题
|
||||
useEffect(() => {
|
||||
navigation.setOptions({
|
||||
|
@ -90,9 +94,30 @@ export default function WebWithHeader({ navigation, route }) {
|
|||
|
||||
//iap
|
||||
const { packages, purchasePackage } = useIap();
|
||||
const [connectingAppStore, setConnectingAppStore] = useState(false);
|
||||
const purchase = async (product) => {
|
||||
setConnectingAppStore(true);
|
||||
const pack = packages.find((p) => p.identifier === product);
|
||||
await purchasePackage(pack);
|
||||
setConnectingAppStore(false);
|
||||
};
|
||||
|
||||
//金币支付
|
||||
const [isCoinPayModalVisible, setIsCoinPayModalVisible] = useState(false);
|
||||
const [coinPayData, setCoinPayData] = useState({
|
||||
url: "",
|
||||
body: {},
|
||||
product: "",
|
||||
coinPrice: null,
|
||||
validity: "",
|
||||
info: "",
|
||||
onPurchaseDone: () => {},
|
||||
});
|
||||
const purchaseByCoin = async (data) => {
|
||||
setCoinPayData((prev) => {
|
||||
return { ...prev, ...data };
|
||||
});
|
||||
setIsCoinPayModalVisible(true);
|
||||
};
|
||||
|
||||
//唤起支付宝或微信
|
||||
|
@ -178,6 +203,9 @@ export default function WebWithHeader({ navigation, route }) {
|
|||
case "IAP":
|
||||
purchase(msg.data);
|
||||
break;
|
||||
case "COINPAY":
|
||||
purchaseByCoin(msg.data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -205,6 +233,43 @@ export default function WebWithHeader({ navigation, route }) {
|
|||
setOverlayVisible(false);
|
||||
}}
|
||||
/>
|
||||
{/* 金币支付Modal */}
|
||||
<CoinPayModal
|
||||
visible={isCoinPayModalVisible}
|
||||
setVisible={setIsCoinPayModalVisible}
|
||||
url={coinPayData.url}
|
||||
body={coinPayData.body}
|
||||
product={coinPayData.product}
|
||||
coinPrice={coinPayData.coinPrice}
|
||||
validity={coinPayData.validity}
|
||||
info={coinPayData.info}
|
||||
onPurchaseDone={coinPayData.onPurchaseDone}
|
||||
/>
|
||||
{/* 正在连接appstore的Modal */}
|
||||
<Modal
|
||||
visible={connectingAppStore}
|
||||
transparent={true}
|
||||
statusBarTranslucent
|
||||
animationType="fade"
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "#00000080",
|
||||
...tailwind("flex-1 justify-center items-center"),
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={tailwind(
|
||||
"flex flex-col p-4 rounded bg-[#17161A] items-center"
|
||||
)}
|
||||
>
|
||||
<Icon type="ionicon" name="logo-apple" size={32} color="white" />
|
||||
<Text style={tailwind("text-white text-base font-medium mt-4")}>
|
||||
正在连接AppStore...
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { Alert } from "react-native";
|
||||
import { Alert, Modal, View, Text } from "react-native";
|
||||
import { WebView } from "react-native-webview";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import * as MediaLibrary from "expo-media-library";
|
||||
|
@ -9,8 +9,12 @@ import Toast from "react-native-toast-message";
|
|||
import MyModal from "../../components/MyModal";
|
||||
import baseRequest from "../../utils/baseRequest";
|
||||
import { useIap } from "../../context/IapProvider";
|
||||
import CoinPayModal from "../../components/CoinPayModal";
|
||||
import { useTailwind } from "tailwind-rn";
|
||||
import { Icon } from "@rneui/themed";
|
||||
|
||||
export default function WebWithoutHeader({ navigation, route }) {
|
||||
const tailwind = useTailwind();
|
||||
//前往打开权限弹窗
|
||||
const [overlayVisible, setOverlayVisible] = useState(false);
|
||||
|
||||
|
@ -83,9 +87,30 @@ export default function WebWithoutHeader({ navigation, route }) {
|
|||
|
||||
//iap
|
||||
const { packages, purchasePackage } = useIap();
|
||||
const [connectingAppStore, setConnectingAppStore] = useState(false);
|
||||
const purchase = async (product) => {
|
||||
setConnectingAppStore(true);
|
||||
const pack = packages.find((p) => p.identifier === product);
|
||||
await purchasePackage(pack);
|
||||
setConnectingAppStore(false);
|
||||
};
|
||||
|
||||
//金币支付
|
||||
const [isCoinPayModalVisible, setIsCoinPayModalVisible] = useState(false);
|
||||
const [coinPayData, setCoinPayData] = useState({
|
||||
url: "",
|
||||
body: {},
|
||||
product: "",
|
||||
coinPrice: null,
|
||||
validity: "",
|
||||
info: "",
|
||||
onPurchaseDone: () => {},
|
||||
});
|
||||
const purchaseByCoin = async (data) => {
|
||||
setCoinPayData((prev) => {
|
||||
return { ...prev, ...data };
|
||||
});
|
||||
setIsCoinPayModalVisible(true);
|
||||
};
|
||||
|
||||
//唤起支付宝或微信
|
||||
|
@ -171,6 +196,9 @@ export default function WebWithoutHeader({ navigation, route }) {
|
|||
case "IAP":
|
||||
purchase(msg.data);
|
||||
break;
|
||||
case "COINPAY":
|
||||
purchaseByCoin(msg.data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -198,6 +226,43 @@ export default function WebWithoutHeader({ navigation, route }) {
|
|||
setOverlayVisible(false);
|
||||
}}
|
||||
/>
|
||||
{/* 金币支付Modal */}
|
||||
<CoinPayModal
|
||||
visible={isCoinPayModalVisible}
|
||||
setVisible={setIsCoinPayModalVisible}
|
||||
url={coinPayData.url}
|
||||
body={coinPayData.body}
|
||||
product={coinPayData.product}
|
||||
coinPrice={coinPayData.coinPrice}
|
||||
validity={coinPayData.validity}
|
||||
info={coinPayData.info}
|
||||
onPurchaseDone={coinPayData.onPurchaseDone}
|
||||
/>
|
||||
{/* 正在连接appstore的Modal */}
|
||||
<Modal
|
||||
visible={connectingAppStore}
|
||||
transparent={true}
|
||||
statusBarTranslucent
|
||||
animationType="fade"
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "#00000080",
|
||||
...tailwind("flex-1 justify-center items-center"),
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={tailwind(
|
||||
"flex flex-col p-4 rounded bg-[#17161A] items-center"
|
||||
)}
|
||||
>
|
||||
<Icon type="ionicon" name="logo-apple" size={32} color="white" />
|
||||
<Text style={tailwind("text-white text-base font-medium mt-4")}>
|
||||
正在连接AppStore...
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue