2024-01-03 01:07:16 +08:00
|
|
|
|
"use client";
|
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
|
|
|
import { useSearchParams } from "next/navigation";
|
|
|
|
|
import { setCookie, getCookie } from "cookies-next";
|
|
|
|
|
import { useRouter } from "next/navigation";
|
|
|
|
|
import { Checkbox } from "antd-mobile";
|
|
|
|
|
import Link from "next/link";
|
|
|
|
|
import baseRequest from "@/utils/baseRequest";
|
|
|
|
|
import Divider from "@/components/Divider";
|
|
|
|
|
import { Toast } from "antd-mobile";
|
|
|
|
|
import { generateSignature } from "@/utils/crypto";
|
2024-01-08 22:26:35 +08:00
|
|
|
|
import { JSEncrypt } from "jsencrypt";
|
2024-01-03 01:07:16 +08:00
|
|
|
|
|
|
|
|
|
export default function WithDrawal() {
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const searchParams = useSearchParams();
|
|
|
|
|
const mid = searchParams.get("mid");
|
|
|
|
|
const token = searchParams.get("token");
|
|
|
|
|
const mobile_phone = searchParams.get("mobile_phone");
|
|
|
|
|
|
|
|
|
|
//将searchParams中的mid和token写入cookie,并重定向到没有searchParams的路由
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (mid && token && mobile_phone) {
|
|
|
|
|
setCookie("mid", mid);
|
|
|
|
|
setCookie("token", token);
|
|
|
|
|
setCookie("mobile_phone", mobile_phone);
|
|
|
|
|
router.replace("/withdrawal");
|
|
|
|
|
}
|
|
|
|
|
}, [mid, token, mobile_phone]);
|
|
|
|
|
|
|
|
|
|
//查看主播实名认证情况
|
|
|
|
|
const [data, setData] = useState({});
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const getData = async () => {
|
|
|
|
|
const mid = getCookie("mid");
|
|
|
|
|
if (!mid) return;
|
|
|
|
|
try {
|
|
|
|
|
const base = baseRequest();
|
|
|
|
|
const signature = generateSignature({
|
|
|
|
|
mid: parseInt(mid, 10),
|
|
|
|
|
...base,
|
|
|
|
|
});
|
|
|
|
|
const verificationResponse = await fetch(
|
|
|
|
|
`/api/realname_authentication/list_by_mid?signature=${signature}`,
|
|
|
|
|
{
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
mid: parseInt(mid, 10),
|
|
|
|
|
...base,
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
const verificationData = await verificationResponse.json();
|
|
|
|
|
if (verificationData.ret === -1) {
|
|
|
|
|
Toast.show({
|
|
|
|
|
content: verificationData.msg,
|
|
|
|
|
});
|
2024-01-08 22:26:35 +08:00
|
|
|
|
}
|
|
|
|
|
const signature2 = generateSignature({
|
|
|
|
|
...base,
|
|
|
|
|
});
|
|
|
|
|
const withdrawalResponse = await fetch(
|
|
|
|
|
`/api/vas/withdraw_page?signature=${signature2}`,
|
|
|
|
|
{
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
...base,
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
const withdrawalData = await withdrawalResponse.json();
|
|
|
|
|
if (withdrawalData.ret === -1) {
|
|
|
|
|
Toast.show({
|
|
|
|
|
content: withdrawalData.msg,
|
|
|
|
|
});
|
2024-01-03 01:07:16 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
setData({
|
|
|
|
|
verificationStatus:
|
2024-01-08 22:26:35 +08:00
|
|
|
|
verificationData.data?.realname_authentication_api_vo?.status,
|
|
|
|
|
withdrawal_diamond: withdrawalData.data.withdraw_diamonds,
|
2024-01-03 01:07:16 +08:00
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
getData();
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const [withdrawalNum, setWithdrawalNum] = useState("");
|
|
|
|
|
const [alipayAccount, setAlipayAccount] = useState("");
|
|
|
|
|
const [payee, setPayee] = useState("");
|
|
|
|
|
const [maskedMobilePhone, setMaskedMobilePhone] = useState("");
|
|
|
|
|
const [veriCode, setVeriCode] = useState("");
|
|
|
|
|
|
|
|
|
|
//设置checkbox
|
|
|
|
|
const [checked, setChecked] = useState(false);
|
|
|
|
|
|
|
|
|
|
//从cookie中读取mobile_phone并做脱敏处理
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const mobilePhoneCache = getCookie("mobile_phone");
|
2024-01-08 22:26:35 +08:00
|
|
|
|
const maskedNumber = mobilePhoneCache?.replace(
|
2024-01-03 01:07:16 +08:00
|
|
|
|
/(\d{3})\d{4}(\d{4})/,
|
|
|
|
|
"$1****$2"
|
|
|
|
|
);
|
|
|
|
|
setMaskedMobilePhone(maskedNumber);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
//这是提现钻石的数量
|
|
|
|
|
const handleChangeWithdrawalNum = (e) => {
|
|
|
|
|
let newValue = parseInt(e.target.value, 10);
|
|
|
|
|
// 确保输入的值在最小值和最大值范围内
|
|
|
|
|
if (
|
|
|
|
|
newValue >= 0 &&
|
|
|
|
|
newValue <= Math.min(data?.withdrawal_diamond, 20000)
|
|
|
|
|
) {
|
|
|
|
|
setWithdrawalNum(newValue);
|
|
|
|
|
} else if (isNaN(newValue)) {
|
|
|
|
|
setWithdrawalNum(0);
|
|
|
|
|
} else if (newValue > Math.min(data?.withdrawal_diamond, 20000)) {
|
|
|
|
|
setWithdrawalNum(Math.min(data?.withdrawal_diamond, 20000));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//重新获取验证码的计时器
|
|
|
|
|
const [isCounting, setIsCounting] = useState(false);
|
|
|
|
|
const [seconds, setSeconds] = useState(60);
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
let interval;
|
|
|
|
|
if (isCounting && seconds > 0) {
|
|
|
|
|
interval = setInterval(() => {
|
|
|
|
|
setSeconds(seconds - 1);
|
|
|
|
|
}, 1000);
|
|
|
|
|
} else {
|
|
|
|
|
setIsCounting(false);
|
|
|
|
|
setSeconds(60);
|
|
|
|
|
clearInterval(interval);
|
|
|
|
|
}
|
|
|
|
|
return () => {
|
|
|
|
|
clearInterval(interval);
|
|
|
|
|
};
|
|
|
|
|
}, [isCounting, seconds]);
|
|
|
|
|
|
|
|
|
|
//点击获取验证码
|
|
|
|
|
const handleVerification = async () => {
|
|
|
|
|
//开始倒计时
|
|
|
|
|
setIsCounting(true);
|
2024-01-08 22:26:35 +08:00
|
|
|
|
//发送短信验证码
|
|
|
|
|
const base = baseRequest();
|
|
|
|
|
const signature = generateSignature({
|
|
|
|
|
...base,
|
|
|
|
|
});
|
|
|
|
|
try {
|
|
|
|
|
await fetch(`/api/vas/withdraw_send_verifycode?signature=${signature}`, {
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
...base,
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
}
|
2024-01-03 01:07:16 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//点击提交申请按钮
|
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
|
if (!withdrawalNum || withdrawalNum < 2000) {
|
|
|
|
|
Toast.show({
|
|
|
|
|
content: "提现最低金额为200元(即2000钻石)",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!alipayAccount || !payee) {
|
|
|
|
|
Toast.show({
|
|
|
|
|
content: "请完善收款信息",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!veriCode) {
|
|
|
|
|
Toast.show({
|
|
|
|
|
content: "请输入验证码",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!checked) {
|
|
|
|
|
Toast.show({
|
|
|
|
|
content: "请先同意《用户提现协议》",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
document.getElementById("comfirm_modal").showModal();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//点击二次确认按钮
|
|
|
|
|
const [errorMessage, setErrorMessage] = useState("");
|
2024-01-08 22:26:35 +08:00
|
|
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
2024-01-03 01:07:16 +08:00
|
|
|
|
const handleConfirm = async () => {
|
2024-01-08 22:26:35 +08:00
|
|
|
|
try {
|
|
|
|
|
setIsSubmitting(true);
|
|
|
|
|
//对支付宝账号和真实姓名进行RSA加密
|
|
|
|
|
const encrypt = new JSEncrypt();
|
|
|
|
|
encrypt.setPublicKey(process.env.NEXT_PUBLIC_WITHDRAW_RSA_KEY);
|
|
|
|
|
const auth_alipay_id = encrypt.encrypt(alipayAccount);
|
|
|
|
|
const auth_alipay_name = encrypt.encrypt(payee);
|
|
|
|
|
const base = baseRequest();
|
|
|
|
|
const signature = generateSignature({
|
|
|
|
|
diamonds: parseInt(withdrawalNum, 10),
|
|
|
|
|
auth_alipay_id: auth_alipay_id,
|
|
|
|
|
auth_alipay_name: auth_alipay_name,
|
|
|
|
|
verify_code: veriCode,
|
|
|
|
|
...base,
|
|
|
|
|
});
|
|
|
|
|
const applyResponse = await fetch(
|
|
|
|
|
`/api/vas/withdraw_apply?signature=${signature}`,
|
|
|
|
|
{
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
diamonds: parseInt(withdrawalNum, 10),
|
|
|
|
|
auth_alipay_id: auth_alipay_id,
|
|
|
|
|
auth_alipay_name: auth_alipay_name,
|
|
|
|
|
verify_code: veriCode,
|
|
|
|
|
...base,
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
const applyData = await applyResponse.json();
|
|
|
|
|
if (applyData.ret === -1) {
|
|
|
|
|
setErrorMessage(applyData.msg);
|
|
|
|
|
setIsSubmitting(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
router.push("/withdrawal/success");
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsSubmitting(false);
|
|
|
|
|
}
|
2024-01-03 01:07:16 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<section className="container flex flex-col flex-1 p-4">
|
|
|
|
|
<div className="flex flex-col items-center justify-around w-full h-32 rounded-2xl bg-gradient-to-r from-[#FF668B] to-[#FF66F0]">
|
|
|
|
|
<p className="text-base text-white font-medium">可提现钻石:</p>
|
|
|
|
|
<div className="flex flex-col items-center">
|
|
|
|
|
<p className="text-2xl text-white font-medium">
|
|
|
|
|
{data?.withdrawal_diamond}
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-xs text-white font-medium">
|
|
|
|
|
(新入帐钻石需等待7日才能提现哦)
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<p className="text-base text-white font-medium">
|
|
|
|
|
兑换比例:10钻石=1RMB
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<p className="text-white text-base mt-2">
|
|
|
|
|
<span className="text-error">*</span>提现数量
|
|
|
|
|
</p>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
placeholder={`可提现${data?.withdrawal_diamond}钻石`}
|
|
|
|
|
value={withdrawalNum.toString()}
|
|
|
|
|
onChange={handleChangeWithdrawalNum}
|
|
|
|
|
className="input input-bordered input-md input-primary w-full"
|
|
|
|
|
/>
|
|
|
|
|
<p className="text-secondary text-base">
|
|
|
|
|
预计提现金额:{withdrawalNum ? withdrawalNum / 10 + "元" : "自动计算"}
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-white text-base mt-2">
|
|
|
|
|
<span className="text-error">*</span>支付宝账号
|
|
|
|
|
</p>
|
|
|
|
|
{data?.verificationStatus === 0 ? (
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="请输入本人支付宝账号"
|
|
|
|
|
value={alipayAccount}
|
|
|
|
|
onChange={(e) => setAlipayAccount(e.target.value)}
|
|
|
|
|
className="input input-bordered input-md input-primary w-full"
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => router.push("/verification")}
|
|
|
|
|
className="btn btn-info text-white w-full"
|
|
|
|
|
>
|
|
|
|
|
{data?.verificationStatus === 1
|
|
|
|
|
? "您已提交实名认证,请等待审核"
|
|
|
|
|
: "您还未通过实名认证,请点击此处进行认证"}
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
<p className="text-white text-base mt-2">
|
|
|
|
|
<span className="text-error">*</span>收款人姓名
|
|
|
|
|
</p>
|
|
|
|
|
{data?.verificationStatus === 0 ? (
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="请输入收款人姓名"
|
|
|
|
|
value={payee}
|
|
|
|
|
onChange={(e) => setPayee(e.target.value)}
|
|
|
|
|
className="input input-bordered input-md input-primary w-full"
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => router.push("/verification")}
|
|
|
|
|
className="btn btn-info text-white w-full"
|
|
|
|
|
>
|
|
|
|
|
{data?.verificationStatus === 1
|
|
|
|
|
? "您已提交实名认证,请等待审核"
|
|
|
|
|
: "您还未通过实名认证,请点击此处进行认证"}
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
<p className="text-white text-base mt-2">
|
|
|
|
|
<span className="text-error">*</span>绑定手机
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-secondary text-base">{maskedMobilePhone}</p>
|
|
|
|
|
<p className="text-white text-base mt-2">
|
|
|
|
|
<span className="text-error">*</span>验证码
|
|
|
|
|
</p>
|
|
|
|
|
{data?.verificationStatus === 0 ? (
|
|
|
|
|
<div className="flex flex-row">
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
placeholder="请输入正确验证码"
|
|
|
|
|
value={veriCode}
|
|
|
|
|
onChange={(e) => setVeriCode(e.target.value)}
|
|
|
|
|
className="input input-bordered input-md input-primary w-full"
|
|
|
|
|
/>
|
|
|
|
|
<button
|
|
|
|
|
disabled={isCounting}
|
|
|
|
|
onClick={handleVerification}
|
|
|
|
|
className="btn btn-primary text-white ml-2"
|
|
|
|
|
>
|
|
|
|
|
{isCounting ? `(${seconds})重新发送` : "获取验证码"}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => router.push("/verification")}
|
|
|
|
|
className="btn btn-info text-white w-full"
|
|
|
|
|
>
|
|
|
|
|
{data?.verificationStatus === 1
|
|
|
|
|
? "您已提交实名认证,请等待审核"
|
|
|
|
|
: "您还未通过实名认证,请点击此处进行认证"}
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
<div className="flex justify-center mt-8 mb-4">
|
|
|
|
|
<Checkbox
|
|
|
|
|
style={{
|
|
|
|
|
"--icon-size": "18px",
|
|
|
|
|
"--font-size": "14px",
|
|
|
|
|
"--gap": "6px",
|
|
|
|
|
}}
|
|
|
|
|
checked={checked}
|
|
|
|
|
onChange={() => setChecked(!checked)}
|
|
|
|
|
>
|
|
|
|
|
<p className="text-gray-400 text-sm">
|
|
|
|
|
同意
|
|
|
|
|
<Link className="link text-primary" href="/doc/withdrawalagreement">
|
|
|
|
|
《用户提现协议》
|
|
|
|
|
</Link>
|
|
|
|
|
</p>
|
|
|
|
|
</Checkbox>
|
|
|
|
|
</div>
|
|
|
|
|
<button
|
|
|
|
|
onClick={handleSubmit}
|
|
|
|
|
className="btn btn-md btn-primary text-white rounded-full w-full mb-4"
|
|
|
|
|
>
|
|
|
|
|
提交申请
|
|
|
|
|
</button>
|
|
|
|
|
<Divider />
|
|
|
|
|
<p className="text-error text-base mt-2">注意事项:</p>
|
|
|
|
|
<p className="text-error text-sm">
|
|
|
|
|
1.需实名认证后方可提现,详情请点击
|
|
|
|
|
<Link className="link text-info" href="/verification">
|
|
|
|
|
“实名认证”
|
|
|
|
|
</Link>
|
|
|
|
|
;
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-error text-sm">
|
|
|
|
|
2.请确保输入信息准确无误,并且支付宝收款人与实名认证本人保持一致,以防提现失败,由输入错误带来的损失与平台方无关;
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-error text-sm">
|
|
|
|
|
3.单笔最低提现金额为200元(即2000钻石),若提现金额大于2000元(即20000钻石)请联系客服;
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-error text-sm">
|
2024-01-08 22:26:35 +08:00
|
|
|
|
4.自助提现渠道每日只能提现一次,若有更多提现需求,请联系客服。
|
2024-01-03 01:07:16 +08:00
|
|
|
|
</p>
|
|
|
|
|
<dialog id="comfirm_modal" className="modal">
|
|
|
|
|
<div className="modal-box bg-[#13121F]">
|
|
|
|
|
<p className="text-white text-base font-medium">
|
|
|
|
|
提现金额:
|
|
|
|
|
<span className="text-secondary">¥{withdrawalNum / 10}</span>
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-white text-base font-medium">
|
|
|
|
|
收款人姓名:<span className="text-secondary">{payee}</span>
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-white text-base font-medium">
|
|
|
|
|
收款支付宝:<span className="text-secondary">{alipayAccount}</span>
|
|
|
|
|
</p>
|
|
|
|
|
{errorMessage && (
|
|
|
|
|
<p className="text-error text-base font-medium mt-2">
|
|
|
|
|
提现失败:{errorMessage}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
<div className="flex flex-col mt-4">
|
|
|
|
|
<button
|
2024-01-08 22:26:35 +08:00
|
|
|
|
disabled={isSubmitting}
|
2024-01-03 01:07:16 +08:00
|
|
|
|
onClick={handleConfirm}
|
|
|
|
|
className="flex items-center justify-center bg-[#FF669E] rounded-lg py-2"
|
|
|
|
|
>
|
2024-01-08 22:26:35 +08:00
|
|
|
|
{isSubmitting && (
|
|
|
|
|
<span className="loading loading-spinner"></span>
|
|
|
|
|
)}
|
|
|
|
|
{isSubmitting ? "提交中..." : "确认提交"}
|
2024-01-03 01:07:16 +08:00
|
|
|
|
</button>
|
|
|
|
|
<form method="dialog" className="flex mt-2">
|
|
|
|
|
<button className="flex flex-row flex-1 items-center justify-center border border-secondary rounded-lg py-2">
|
|
|
|
|
<p className="text-secondary text-base ml-1">返回修改</p>
|
|
|
|
|
</button>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</dialog>
|
|
|
|
|
</section>
|
|
|
|
|
);
|
|
|
|
|
}
|