tiefen_space_web/app/pay/page.jsx

333 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useState, useEffect, useCallback } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { Toast } from "antd-mobile";
import { generateSignature } from "@/utils/crypto";
import webviewBaseRequest from "@/utils/webviewBaseRequest";
import Link from "next/link";
export default function Pay() {
const router = useRouter();
const searchParams = useSearchParams();
const alipayBlock = () => {
if (base?.b_mid === 161) {
createOrder("alipay_h5");
return;
}
Toast.show({
content: "支付渠道维护升级中请24小时后再试",
});
};
//商品列表
const [productList, setProductList] = useState([]);
//选择的价格档位
const [selectedPrice, setSelectedPrice] = useState({});
//选择任意金额充值
const [customCoin, setCustomCoin] = useState({ selected: false, num: 1000 });
//任意金额充值的金币数量
const handleChangeCustomCoin = (e) => {
let newValue = parseInt(e.target.value, 10);
// 确保输入的值在最小值和最大值范围内
if (newValue >= 0 && newValue <= 100000) {
setCustomCoin({ ...customCoin, num: newValue });
} else if (isNaN(newValue)) {
setCustomCoin({ ...customCoin, num: 0 });
} else if (newValue > 100000) {
setCustomCoin({ ...customCoin, num: 100000 });
}
};
//获取当前充值档位
const [isFetching, setIsFetching] = useState(true);
const getBase = useCallback(
(webviewBase) => {
let searchParamsObj = null;
let currentBaseCode = searchParams.get("base");
if (currentBaseCode) {
let currentBase = JSON.parse(currentBaseCode);
searchParamsObj = { ...currentBase };
}
return searchParamsObj || webviewBase;
},
[searchParams]
);
useEffect(() => {
const getData = async () => {
const webviewBase = webviewBaseRequest();
const base = getBase(webviewBase);
const body = { ...base };
const signature = generateSignature(body);
try {
const response = await fetch(
`/api/vas/get_coins_product_list?signature=${signature}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}
);
const data = await response.json();
if (data.ret === -1) {
Toast.show({
content: data.msg,
});
return;
}
setProductList(data.data.list_alipay_h5);
setIsFetching(false);
} catch (error) {
console.error(error);
}
};
getData();
}, []);
//创建充值订单
const [isLoading, setIsLoading] = useState(false);
const createOrder = async (type = "alipay_h5") => {
if (!selectedPrice.id && !customCoin.selected) {
Toast.show({
content: "请选择充值档位",
});
return;
}
if (customCoin.selected && customCoin.num < 10) {
Toast.show({
content: "最低充值1元哦",
});
return;
}
const webviewBase = webviewBaseRequest();
const base = getBase(webviewBase);
const body = {
...base,
product_id: customCoin.selected ? "h5_custom_coin" : selectedPrice.id,
custom_coins: customCoin.selected ? customCoin.num : 0,
pay_type: type,
redirect_url: type === "yeepay_wxpay_h5" ? window.location.href : "",
from: searchParams.get("base") ? "web" : "app",
};
//如果是微信jsapi支付直接跳转到中间页
if (type === "wxpay_jsapi") {
router.push(`/pay/${encodeURIComponent(JSON.stringify(body))}`);
return;
}
setIsLoading(true);
const signature = generateSignature(body);
try {
const response = await fetch(
`/api/vas/create_order?signature=${signature}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}
);
const data = await response.json();
if (data.ret === -1) {
Toast.show({
content: data.msg,
});
return;
}
switch (type) {
case "yeepay_alipay_h5":
router.push(`${data.data.yeepay_alipay_h5_param_str}`);
break;
case "yeepay_wxpay_h5":
router.push(`${data.data.yeepay_wxpay_h5_param_str}`);
break;
case "alipay_h5":
router.push(`${data.data.alipay_h5_param_str}`);
break;
case "wxpay_h5":
router.push(
`https://shop.tiefen.fun/pay/wxpay_h5/${encodeURIComponent(
data.data.wxpay_h5_param_str
)}`
);
break;
default:
router.push(`${data.data.alipay_h5_param_str}`);
break;
}
} catch (error) {
console.error(error);
} finally {
setIsLoading(false);
}
};
const PriceItem = ({ item }) => {
const handleClickPrice = (item) => {
setSelectedPrice(item);
setCustomCoin({ ...customCoin, selected: false });
};
return (
<div className="basis-1/3 p-2">
<button
onClick={() => handleClickPrice(item)}
className={
selectedPrice.id === item.id
? "flex flex-col w-full py-4 border bg-[#FF61B030] border-primary rounded-lg items-center"
: "flex flex-col w-full py-4 border bg-[#FFFFFF1A] border-secondary rounded-lg items-center"
}
>
<p
className={
selectedPrice.id === item.id
? "text-base text-primary"
: "text-base text-secondary"
}
>
{item.name}
</p>
<p
className={
selectedPrice.real_price === item.real_price
? "text-base text-primary"
: "text-base text-secondary"
}
>
¥{item.real_price / 100}
</p>
</button>
</div>
);
};
if (isFetching) {
return (
<section className="flex flex-1 justify-center container">
<span className="absolute top-1/2 loading loading-spinner loading-lg"></span>
</section>
);
}
return (
<section className="flex flex-1 justify-center container">
{isLoading && (
<span className="absolute top-1/2 loading loading-spinner loading-lg"></span>
)}
<div className="flex flex-1 flex-col p-4">
<div
onClick={() => router.push("/pay/info")}
className="flex flex-row items-center bg-neutral rounded-lg w-full p-2"
>
<svg viewBox="0 0 1024 1024" width="24" height="24">
<path
d="M512 65.983389c-245.952318 0-446.016611 200.064292-446.016611 446.016611S266.047682 958.016611 512 958.016611 958.016611 757.952318 958.016611 512 757.952318 65.983389 512 65.983389zM544.00086 736.00086c0 17.695686-14.303454 32.00086-32.00086 32.00086s-32.00086-14.303454-32.00086-32.00086L479.99914 448c0-17.695686 14.303454-32.00086 32.00086-32.00086 17.695686 0 32.00086 14.303454 32.00086 32.00086L544.00086 736.00086zM512 352.00086c-26.496224 0-48.00043-21.53689-48.00043-48.00043 0-26.527187 21.504206-48.00043 48.00043-48.00043s48.00043 21.471523 48.00043 48.00043C560.00043 330.46397 538.496224 352.00086 512 352.00086z"
fill="#FFF04C"
></path>
</svg>
<div className="ml-2 flex flex-col">
<p className="text-base font-semibold text-white">支付遇到问题</p>
<p className="text-xs text-secondary">
无法唤起支付宝APP点击支付无反应
</p>
</div>
<div className="ml-auto">
<svg viewBox="0 0 1024 1024" width="24" height="24">
<path
d="M761.055557 532.128047c0.512619-0.992555 1.343475-1.823411 1.792447-2.848649 8.800538-18.304636 5.919204-40.703346-9.664077-55.424808L399.935923 139.743798c-19.264507-18.208305-49.631179-17.344765-67.872168 1.888778-18.208305 19.264507-17.375729 49.631179 1.888778 67.872168l316.960409 299.839269L335.199677 813.631716c-19.071845 18.399247-19.648112 48.767639-1.247144 67.872168 9.407768 9.791372 21.984142 14.688778 34.560516 14.688778 12.000108 0 24.000215-4.479398 33.311652-13.439914l350.048434-337.375729c0.672598-0.672598 0.927187-1.599785 1.599785-2.303346 0.512619-0.479935 1.056202-0.832576 1.567101-1.343475C757.759656 538.879828 759.199462 535.391265 761.055557 532.128047z"
fill="#ffffff"
></path>
</svg>
</div>
</div>
<p className="text-white text-base font-semibold my-2">选择充值金额</p>
<div className="flex flex-wrap">
{productList?.map((item) => (
<PriceItem key={item.id} item={item} />
))}
{/* 任意金额充值 */}
<div className="basis-1/3 p-2">
<button
onClick={() => {
setSelectedPrice([]);
setCustomCoin({ ...customCoin, selected: true });
}}
className={
customCoin.selected
? "flex flex-col w-full h-full py-4 border bg-[#FF61B030] border-primary rounded-lg items-center justify-center"
: "flex flex-col w-full h-full py-4 border bg-[#FFFFFF1A] border-secondary rounded-lg items-center justify-center"
}
>
<p
className={
customCoin.selected
? "text-base text-primary"
: "text-base text-secondary"
}
>
自定义金币
</p>
</button>
</div>
</div>
{customCoin.selected && (
<div className="px-2 mt-2">
<input
type="number"
name="custom_price"
placeholder="请输入金币数额"
value={customCoin.num.toString()}
onChange={handleChangeCustomCoin}
className="input input-bordered input-md text-base input-primary w-full"
/>
<p className="text-secondary text-base mt-2">
预估金额¥{customCoin.num / 10}
</p>
</div>
)}
<div className="flex flex-col w-full mt-auto z-20">
<div className="flex flex-col pt-3 pb-11 px-4 bg-[#07050AE5]">
<div className="flex flex-row justify-between">
<div className="w-full px-2">
<div
onClick={() => createOrder("alipay_h5")}
className="flex flex-row cursor-pointer gap-1.5 h-11 items-center justify-center bg-primary rounded-full"
>
<img
className="w-[22px]"
src={
process.env.NEXT_PUBLIC_CDN_URL +
"/public/images/alipay.png"
}
alt=""
/>
<p className="text-white text-base font-medium whitespace-nowrap">
支付宝支付
</p>
</div>
</div>
</div>
<p className="text-secondary text-xs font-medium mt-4 text-center mb-1">
确认购买即视为同意
<Link
className="link text-[#309EDC]"
href="/doc/rechargeagreement"
>
用户充值协议
</Link>
</p>
</div>
</div>
</div>
</section>
);
}