"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 [isBackupPaymentVisible, setIsBackupPaymentVisible] = useState(false); //任意金额充值的金币数量 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 handleBackupPaymentVisible = () => { setIsBackupPaymentVisible(true); }; //获取当前充值档位 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 createBackupPaymentOrder = 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", ver: "aliv2", }; //如果是微信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> {isBackupPaymentVisible ? ( <div className="px-2 mt-4"> <div onClick={() => createBackupPaymentOrder("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> ) : ( <p className="text-secondary text-xs font-medium mt-4 text-center mb-1"> 若无法支付,请尝试 <span className="link text-[#309EDC]" onClick={handleBackupPaymentVisible} > 备用支付渠道 </span> </p> )} <p className="text-secondary text-xs font-medium mt-2 text-center mb-1"> 确认购买即视为同意 <Link className="link text-[#309EDC]" href="/doc/rechargeagreement" > 《用户充值协议》 </Link> </p> </div> </div> </div> </section> ); }