This commit is contained in:
you 2024-09-05 13:11:57 +03:00
parent 0159fa07e9
commit 9258c40f25
4 changed files with 242 additions and 81 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

View File

@ -4,7 +4,7 @@
<meta charset='utf-8'> <meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'> <meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title> <title>HPay</title>
<link rel='icon' type='image/png' href='/favicon.png'> <link rel='icon' type='image/png' href='/favicon.png'>

View File

@ -5,8 +5,15 @@
import axios from "axios"; import axios from "axios";
import { sayError, sayInfo } from "../lib/toaster"; import { sayError, sayInfo } from "../lib/toaster";
import LoadingSpinner from "../lib/loadingSpinner.svelte"; import LoadingSpinner from "../lib/loadingSpinner.svelte";
import { addMinutes, formatDistanceToNow, parseISO } from "date-fns"; import {
import { ca, ru } from "date-fns/locale"; addMinutes,
differenceInMinutes,
differenceInSeconds,
formatDistanceToNow,
formatDistanceToNowStrict,
parseISO,
} from "date-fns";
import { ca, el, ru } from "date-fns/locale";
const apiBase = "https://24paymentgateway.ru/api/v1/"; const apiBase = "https://24paymentgateway.ru/api/v1/";
@ -27,9 +34,11 @@
5) POST: /api/v1/choosePaymentMethod 5) POST: /api/v1/choosePaymentMethod
6) POST: /api/v1/cancelOrder 6) POST: /api/v1/cancelOrder
*/ */
// let tries = 0;
let tokenURL = ""; let tokenURL = "";
let orderID = ""; let orderID = "";
let invalidURL = true; let invalidURL = true;
let validJWT = false;
async function getTokenFromURL() { async function getTokenFromURL() {
const queryString = window.location.search; const queryString = window.location.search;
// //console.log(queryString); // //console.log(queryString);
@ -39,13 +48,12 @@
//console.log(tokenURL); //console.log(tokenURL);
validateJWT(tokenURL); validateJWT(tokenURL);
// //console.log(); // //console.log();
if (invalidURL == true) { if (validJWT !== true) {
sayError("Неверный ID заявки"); sayError("Неверный ID заявки");
} else { } else {
await getOrderStatus(); await getOrderStatus();
//console.log(orderStatus); //console.log(orderStatus);
switch (orderStatus) { switch (orderStatus) {
case 1: case 1:
getPaymentMethods(); getPaymentMethods();
@ -68,6 +76,7 @@
default: default:
break; break;
} }
invalidURL = false;
// getPaymentMethods(); // getPaymentMethods();
} }
@ -80,9 +89,9 @@
let t = jwtDecode(token); let t = jwtDecode(token);
orderID = t["order_id"]; orderID = t["order_id"];
// //console.log(t); // //console.log(t);
invalidURL = false; validJWT = true;
} catch (error) { } catch (error) {
invalidURL = true; validJWT = false;
// //console.log(error); // //console.log(error);
} }
} }
@ -95,12 +104,31 @@
const newDate = addMinutes(originalDate, 10); const newDate = addMinutes(originalDate, 10);
timeLeftInterval = setInterval(() => { timeLeftInterval = setInterval(() => {
timeLeft = formatDistanceToNow(newDate, { const now = new Date();
addSuffix: true, const minutes = differenceInMinutes(newDate, now);
includeSeconds: true, const seconds = differenceInSeconds(newDate, now) % 60;
locale: ru,
}); // Форматируем минуты и секунды
const formattedMinutes = String(minutes).padStart(2, "0");
const formattedSeconds = String(seconds).padStart(2, "0");
timeLeft = `${formattedMinutes}:${formattedSeconds}`;
if(timeLeft === "00:00" || timeLeft.includes("-"))
{
orderStatus = 6;
showTimeout = true;
clearInterval(timeLeftInterval);
}
}, 1000); }, 1000);
const now = new Date();
const minutes = differenceInMinutes(newDate, now);
const seconds = differenceInSeconds(newDate, now) % 60;
// Форматируем минуты и секунды
const formattedMinutes = String(minutes).padStart(2, "0");
const formattedSeconds = String(seconds).padStart(2, "0");
timeLeft = `${formattedMinutes}:${formattedSeconds}`;
} }
let selectedBank = ""; let selectedBank = "";
@ -182,6 +210,7 @@
"8d895e75b7a0def7699e6c4d7cd54c51d9844775bd5fd5e8e3d34748", "8d895e75b7a0def7699e6c4d7cd54c51d9844775bd5fd5e8e3d34748",
); );
const captchaInput = form.querySelector("input"); const captchaInput = form.querySelector("input");
try {
if (captchaInput?.value !== "") { if (captchaInput?.value !== "") {
captchaVerified = true; captchaVerified = true;
captchaValue = captchaInput.value; captchaValue = captchaInput.value;
@ -189,6 +218,9 @@
captchaVerified = true; captchaVerified = true;
captchaValue = undefined; captchaValue = undefined;
} }
} catch (error) {
console.error(error);
}
}, 500); }, 500);
let showAlertQuit = false; let showAlertQuit = false;
@ -249,44 +281,61 @@
} }
// getRequisites(); // getRequisites();
// window.location.href = "httpa://www.google.com";
let orderStatus; let orderStatus;
let redirectURL = "";
async function getOrderStatus() { async function getOrderStatus() {
// tries++;
try { try {
let result = await axios.get(apiBase + "getOrderStatus", { let result = await axios.get(apiBase + "getOrderStatus", {
headers: { headers: {
Authorization: "Bearer " + tokenURL, Authorization: "Bearer " + tokenURL,
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
timeout: 5000,
}); });
orderStatus = result.data.status; orderStatus = result.data.status;
// //console.log(result); if (result.data["successURL"] || result.data["errorURL"]) {
if(orderStatus === 4) redirectURL = result.data["successURL"]
{ ? result.data["successURL"]
selectedBank = result.data["bank_id"]+""; : result.data["errorURL"];
} }
else if (orderStatus === 5) // console.log("got redirect:", result.data["successURL"], result.data["errorURL"]);
{ // console.log("written: ", redirectURL);
// //console.log(result);
if (orderStatus === 4) {
selectedBank = result.data["bank_id"] + "";
} else if (orderStatus === 5) {
//console.log('hello!'); //console.log('hello!');
selectedBank = result.data["bank_id"] + ""; selectedBank = result.data["bank_id"] + "";
requisites = result.data["requisite"]; requisites = result.data["requisite"];
calculateDate(result.data["requisite_creation_time"]); calculateDate(result.data["requisite_creation_time"]);
disableGetReqBtn = true; disableGetReqBtn = true;
showReqs = true; showReqs = true;
} }
} catch (error) { } catch (error) {
//console.log(error); if (error.code === "ECONNABORTED") {
location.reload();
} else {
orderStatus = 6; orderStatus = 6;
} }
//console.log(error);
// if (tries > 3) {
// } else {
// getOrderStatus();
// }
} }
}
let value_disputeSum = 0;
async function loadReceipt() { async function loadReceipt() {
const formData = new FormData(); const formData = new FormData();
let file = document.getElementById("loaded-file").files[0]; let file = document.getElementById("loaded-file").files[0];
// formData.append("uuid", orderID); // formData.append("uuid", orderID);
formData.append("data", file); formData.append("data", file);
formData.append("amount", Number(value_disputeSum));
let result = await axios.post(apiBase + "openDispute", formData, { let result = await axios.post(apiBase + "openDispute", formData, {
headers: { headers: {
Authorization: "Bearer " + tokenURL, Authorization: "Bearer " + tokenURL,
@ -294,6 +343,11 @@
}, },
}); });
// //console.log(result); // //console.log(result);
if (result.status > 300) {
sayError("Что-то пошло не так");
return;
}
sayInfo("Успешно!");
} }
async function createDispute() { async function createDispute() {
@ -344,37 +398,52 @@
//console.log(result); //console.log(result);
} }
async function copyToClipboard() { async function copyToClipboard(val) {
try { try {
await navigator.clipboard.writeText(requisites[1]); await navigator.clipboard.writeText(val);
sayInfo("Скопировано!"); sayInfo("Скопировано!");
} catch (err) { } catch (err) {
//console.error("Failed to copy: ", err); //console.error("Failed to copy: ", err);
} }
} }
function startPingingStatus() {ping();} function startPingingStatus() {
ping();
}
async function ping() { async function ping() {
await getOrderStatus(); await getOrderStatus();
// console.log(orderStatus);
// console.log("url", redirectURL);
if (orderStatus === 2) { if (orderStatus === 2) {
showReject = true; showReject = true;
showLoadingScreen = false; showLoadingScreen = false;
await delay(500);
if (redirectURL !== "") {
window.open(redirectURL, "_self");
}
return; return;
} }
if(orderStatus === 3) if (orderStatus === 3) {
{
showAccept = true; showAccept = true;
showLoadingScreen = false; showLoadingScreen = false;
await delay(500);
if (redirectURL !== "") {
window.open(redirectURL, "_self");
}
return; return;
} }
if(orderStatus===6) if (orderStatus === 6) {
{
showTimeout = true; showTimeout = true;
showLoadingScreen = false; showLoadingScreen = false;
await delay(500);
if (redirectURL !== "") {
window.open(redirectURL, "_self");
}
return; return;
} }
await delay(1000); await delay(1500);
ping(); ping();
} }
</script> </script>
@ -406,7 +475,7 @@
</svg> </svg>
</div> </div>
</div> </div>
{:else} {:else if !showAccept && !showTimeout && !showReject}
<div <div
class="fixed inset-0 bg-slate-950 w-full min-h-screen overflow-auto flex flex-col items-center gap-4 p-8 text-white" class="fixed inset-0 bg-slate-950 w-full min-h-screen overflow-auto flex flex-col items-center gap-4 p-8 text-white"
> >
@ -418,7 +487,13 @@
</div> </div>
<div class="flex flex-col w-full gap-8"> <div class="flex flex-col w-full gap-8">
{#if showBankSelection} {#if showBankSelection}
<p class="text-3xl font-bold">{selectedBank === "" ? "Выбор банка":(requisites.length < 1 ? "Запрос реквизитов":"Оплата заявки")}</p> <p class="text-3xl font-bold">
{selectedBank === ""
? "Выбор банка"
: requisites.length < 1
? "Запрос реквизитов"
: "Оплата заявки"}
</p>
{#each paymentMethods as pm} {#each paymentMethods as pm}
<div class="flex"> <div class="flex">
<button <button
@ -468,27 +543,47 @@
{#if showReqs} {#if showReqs}
{#if !showHelpSection} {#if !showHelpSection}
<div class="w-full flex p-8 rounded-3xl bg-indigo-950"> <div class="w-full flex p-8 rounded-3xl bg-indigo-950">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2 w-full">
<p class="text-lg">Номер карты для перевода</p> <p class="text-lg">Реквизиты</p>
<div class="flex gap-4 items-center"> <div
<p class="text-2xl font-bold"> class="flex mt-2 w-full gap-4 items-center justify-center p-2 bg-indigo-900 rounded-xl"
>
<p class="text-2xl font-bold font-mono">
{requisites[1]} {requisites[1]}
</p> </p>
<button <button
on:click={() => { on:click={() => {
copyToClipboard(); copyToClipboard(requisites[1]);
}} }}
class="relative w-11 h-10 p-2 rounded-full bg-indigo-900 group hover:bg-indigo-800" class="relative w-6 h-6"
> >
<div <div
class="absolute bg-transparent ring-2 ring-white top-2 left-3 w-4 h-5 rounded-[3px]" class="absolute bg-transparent ring-2 ring-white w-4 h-4 top-1 left-1 rounded-[3px]"
></div> ></div>
<div <div
class="absolute bg-indigo-900 ring-2 ring-white top-3 group-hover:bg-indigo-800 left-4 w-4 h-5 rounded-[3px]" class="absolute bg-indigo-900 ring-2 ring-white top-0 group-hover:bg-indigo-800 left-0 w-4 h-4 rounded-[3px]"
></div> ></div>
</button> </button>
</div> </div>
<p class="text-lg">Получатель: {requisites[0]}</p> <div
class="w-full p-2 bg-indigo-900 flex justify-center gap-4 rounded-xl font-mono"
>
<p class="text-2xl font-bold">+{requisites[2]}</p>
<button
on:click={() => {
copyToClipboard(requisites[2]);
}}
class="relative w-6 h-6 mt-1"
>
<div
class="absolute bg-transparent ring-2 ring-white w-4 h-4 top-1 left-1 rounded-[3px]"
></div>
<div
class="absolute bg-indigo-900 ring-2 ring-white top-0 group-hover:bg-indigo-800 left-0 w-4 h-4 rounded-[3px]"
></div>
</button>
</div>
<p class="text-xl font-bold">{requisites[0]}</p>
<p class="text-lg mt-4"> <p class="text-lg mt-4">
Время на оплату: {timeLeft} Время на оплату: {timeLeft}
</p> </p>
@ -519,6 +614,12 @@
</button> </button>
{/if} {/if}
{#if showHelpSection} {#if showHelpSection}
<p class="p-8 bg-slate-900 text-xl rounded-3xl">Укажите сумму:</p>
<input
bind:value={value_disputeSum}
type="number"
class="w-[350px] p-3 rounded-[10px] bg-gray-800 border-gray-700 transition-all duration-75 outline-none placeholder:text-gray-500 focus:ring-inset focus:ring-1 focus:outline-none focus:ring-indigo-600 focus:border-indigo-600"
/>
<p class="p-8 bg-slate-900 text-xl rounded-3xl"> <p class="p-8 bg-slate-900 text-xl rounded-3xl">
Загрузите чек, чтобы мы могли подтвердить перевод Загрузите чек, чтобы мы могли подтвердить перевод
</p> </p>
@ -659,9 +760,11 @@
<div class="bg-indigo-600 w-10 h-10 rounded-full"></div> <div class="bg-indigo-600 w-10 h-10 rounded-full"></div>
</div> </div>
<p class="text-white text-2xl mt-8">Ваш платёж обрабатывается</p> <p class="text-white text-2xl mt-8">Ваш платёж обрабатывается</p>
<p class="text-white opacity-50 text-xl">Это не займет много времени</p> <p class="text-white opacity-50 text-xl mt-2">
<p class="text-white opacity-50 text-sm">Номер платежа: {orderID}</p> Это не займет много времени
<p class="text-white opacity-50 text-sm"> </p>
<p class="text-white opacity-50 text-sm mt-1">Номер платежа: {orderID}</p>
<p class="text-white opacity-50 text-sm mt-1">
Телеграм: <a class="underline" href="https://t.me/hosta_pay" Телеграм: <a class="underline" href="https://t.me/hosta_pay"
>@hosta_pay</a >@hosta_pay</a
> >
@ -710,8 +813,20 @@
class="fixed inset-0 bg-slate-950 flex justify-center items-center text-white" class="fixed inset-0 bg-slate-950 flex justify-center items-center text-white"
> >
<div class="flex flex-col gap-1 justify-center items-center"> <div class="flex flex-col gap-1 justify-center items-center">
<svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg
<path d="M10 15L12 13M12 13L14 11M12 13L10 11M12 13L14 15M21 6L19 4M10 2H14M12 21C7.58172 21 4 17.4183 4 13C4 8.58172 7.58172 5 12 5C16.4183 5 20 8.58172 20 13C20 17.4183 16.4183 21 12 21Z" stroke="#f00" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> width="64px"
height="64px"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10 15L12 13M12 13L14 11M12 13L10 11M12 13L14 15M21 6L19 4M10 2H14M12 21C7.58172 21 4 17.4183 4 13C4 8.58172 7.58172 5 12 5C16.4183 5 20 8.58172 20 13C20 17.4183 16.4183 21 12 21Z"
stroke="#f00"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg> </svg>
<p class="text-xl font-bold">Время заявки истекло</p> <p class="text-xl font-bold">Время заявки истекло</p>
<p class="text-white opacity-50 text-sm">Номер платежа: {orderID}</p> <p class="text-white opacity-50 text-sm">Номер платежа: {orderID}</p>
@ -725,4 +840,50 @@
</p> </p>
</div> </div>
</div> </div>
{:else if showReject}
<div
class="fixed inset-0 bg-slate-950 flex justify-center items-center text-white"
>
<div class="flex flex-col gap-1 justify-center items-center">
<svg
width="64px"
height="64px"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
fill="none"
>
<path
stroke="#f00"
stroke-width="2"
d="M584,1117 C576.268,1117 570,1110.73 570,1103 C570,1095.27 576.268,1089 584,1089 C591.732,1089 598,1095.27 598,1103 C598,1110.73 591.732,1117 584,1117 L584,1117 Z M584,1087 C575.163,1087 568,1094.16 568,1103 C568,1111.84 575.163,1119 584,1119 C592.837,1119 600,1111.84 600,1103 C600,1094.16 592.837,1087 584,1087 L584,1087 Z M589.717,1097.28 C589.323,1096.89 588.686,1096.89 588.292,1097.28 L583.994,1101.58 L579.758,1097.34 C579.367,1096.95 578.733,1096.95 578.344,1097.34 C577.953,1097.73 577.953,1098.37 578.344,1098.76 L582.58,1102.99 L578.314,1107.26 C577.921,1107.65 577.921,1108.29 578.314,1108.69 C578.708,1109.08 579.346,1109.08 579.74,1108.69 L584.006,1104.42 L588.242,1108.66 C588.633,1109.05 589.267,1109.05 589.657,1108.66 C590.048,1108.27 590.048,1107.63 589.657,1107.24 L585.42,1103.01 L589.717,1098.71 C590.11,1098.31 590.11,1097.68 589.717,1097.28 L589.717,1097.28 Z"
>
</path>
</svg>
<p class="text-xl font-bold">Заявка отклонена</p>
<p class="text-white opacity-50 text-sm">Номер платежа: {orderID}</p>
<p class="text-white opacity-50 text-sm">
Телеграм: <a class="underline" href="https://t.me/hosta_pay"
>@hosta_pay</a
>
</p>
<p class="text-white opacity-50 text-sm">
Почта: support@24paymentgateway.ru
</p>
</div>
</div>
<!-- <svg width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<title>cross-circle</title>
<desc>Created with Sketch Beta.</desc>
<defs>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Icon-Set" sketch:type="MSLayerGroup" transform="translate(-568.000000, -1087.000000)" fill="#000000">
<path d="M584,1117 C576.268,1117 570,1110.73 570,1103 C570,1095.27 576.268,1089 584,1089 C591.732,1089 598,1095.27 598,1103 C598,1110.73 591.732,1117 584,1117 L584,1117 Z M584,1087 C575.163,1087 568,1094.16 568,1103 C568,1111.84 575.163,1119 584,1119 C592.837,1119 600,1111.84 600,1103 C600,1094.16 592.837,1087 584,1087 L584,1087 Z M589.717,1097.28 C589.323,1096.89 588.686,1096.89 588.292,1097.28 L583.994,1101.58 L579.758,1097.34 C579.367,1096.95 578.733,1096.95 578.344,1097.34 C577.953,1097.73 577.953,1098.37 578.344,1098.76 L582.58,1102.99 L578.314,1107.26 C577.921,1107.65 577.921,1108.29 578.314,1108.69 C578.708,1109.08 579.346,1109.08 579.74,1108.69 L584.006,1104.42 L588.242,1108.66 C588.633,1109.05 589.267,1109.05 589.657,1108.66 C590.048,1108.27 590.048,1107.63 589.657,1107.24 L585.42,1103.01 L589.717,1098.71 C590.11,1098.31 590.11,1097.68 589.717,1097.28 L589.717,1097.28 Z" id="cross-circle" sketch:type="MSShapeGroup">
</path>
</g>
</g>
</svg> -->
{/if} {/if}