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 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'>

View File

@ -5,8 +5,15 @@
import axios from "axios";
import { sayError, sayInfo } from "../lib/toaster";
import LoadingSpinner from "../lib/loadingSpinner.svelte";
import { addMinutes, formatDistanceToNow, parseISO } from "date-fns";
import { ca, ru } from "date-fns/locale";
import {
addMinutes,
differenceInMinutes,
differenceInSeconds,
formatDistanceToNow,
formatDistanceToNowStrict,
parseISO,
} from "date-fns";
import { ca, el, ru } from "date-fns/locale";
const apiBase = "https://24paymentgateway.ru/api/v1/";
@ -19,17 +26,19 @@
//http://localhost:8080/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJleHAiOjE3MjQzNjEzOTgsImlhdCI6MTcyMTk0MjE5OCwiaW5fY3VycmVuY3lfY29kZSI6IktHUyIsImlzcyI6Ikhvc3RhcGF5Iiwib3JkZXJfaWQiOiIxZjhjOTI2NC1lZWQ3LTRhYzMtYTEyZC0xYzEzMjg4MWM4NzQiLCJvdXRfY3VycmVuY3lfY29kZSI6IktHUyJ9.w_ki56Hb81kX2SoS9qm0Je3atBhmUWTQaYYrLX-udCM
/**
* hpp:
1) GET: /api/v1/getPaymentMethods
2) GET: /api/v1/getRequisites
3) GET: /api/v1/getOrderStatus
4) POST: /api/v1/loadDisputeReceipt
5) POST: /api/v1/createDispute
5) POST: /api/v1/choosePaymentMethod
6) POST: /api/v1/cancelOrder
*/
1) GET: /api/v1/getPaymentMethods
2) GET: /api/v1/getRequisites
3) GET: /api/v1/getOrderStatus
4) POST: /api/v1/loadDisputeReceipt
5) POST: /api/v1/createDispute
5) POST: /api/v1/choosePaymentMethod
6) POST: /api/v1/cancelOrder
*/
// let tries = 0;
let tokenURL = "";
let orderID = "";
let invalidURL = true;
let validJWT = false;
async function getTokenFromURL() {
const queryString = window.location.search;
// //console.log(queryString);
@ -39,13 +48,12 @@
//console.log(tokenURL);
validateJWT(tokenURL);
// //console.log();
if (invalidURL == true) {
if (validJWT !== true) {
sayError("Неверный ID заявки");
} else {
await getOrderStatus();
//console.log(orderStatus);
switch (orderStatus) {
case 1:
getPaymentMethods();
@ -68,6 +76,7 @@
default:
break;
}
invalidURL = false;
// getPaymentMethods();
}
@ -80,9 +89,9 @@
let t = jwtDecode(token);
orderID = t["order_id"];
// //console.log(t);
invalidURL = false;
validJWT = true;
} catch (error) {
invalidURL = true;
validJWT = false;
// //console.log(error);
}
}
@ -92,15 +101,34 @@
function calculateDate(src) {
const originalDate = parseISO(src);
//console.log(originalDate);
const newDate = addMinutes(originalDate, 10);
timeLeftInterval = setInterval(() => {
timeLeft = formatDistanceToNow(newDate, {
addSuffix: true,
includeSeconds: true,
locale: ru,
});
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}`;
if(timeLeft === "00:00" || timeLeft.includes("-"))
{
orderStatus = 6;
showTimeout = true;
clearInterval(timeLeftInterval);
}
}, 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 = "";
@ -182,12 +210,16 @@
"8d895e75b7a0def7699e6c4d7cd54c51d9844775bd5fd5e8e3d34748",
);
const captchaInput = form.querySelector("input");
if (captchaInput?.value !== "") {
captchaVerified = true;
captchaValue = captchaInput.value;
} else {
captchaVerified = true;
captchaValue = undefined;
try {
if (captchaInput?.value !== "") {
captchaVerified = true;
captchaValue = captchaInput.value;
} else {
captchaVerified = true;
captchaValue = undefined;
}
} catch (error) {
console.error(error);
}
}, 500);
@ -249,44 +281,61 @@
}
// getRequisites();
// window.location.href = "httpa://www.google.com";
let orderStatus;
let redirectURL = "";
async function getOrderStatus() {
// tries++;
try {
let result = await axios.get(apiBase + "getOrderStatus", {
headers: {
Authorization: "Bearer " + tokenURL,
"Content-Type": "application/json",
},
});
orderStatus = result.data.status;
// //console.log(result);
if(orderStatus === 4)
{
selectedBank = result.data["bank_id"]+"";
}
else if (orderStatus === 5)
{
//console.log('hello!');
selectedBank = result.data["bank_id"] + "";
requisites = result.data["requisite"];
calculateDate(result.data["requisite_creation_time"]);
disableGetReqBtn = true;
showReqs = true;
}
} catch (error) {
//console.log(error);
orderStatus=6;
}
}
headers: {
Authorization: "Bearer " + tokenURL,
"Content-Type": "application/json",
},
timeout: 5000,
});
orderStatus = result.data.status;
if (result.data["successURL"] || result.data["errorURL"]) {
redirectURL = result.data["successURL"]
? result.data["successURL"]
: result.data["errorURL"];
}
// 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!');
selectedBank = result.data["bank_id"] + "";
requisites = result.data["requisite"];
calculateDate(result.data["requisite_creation_time"]);
disableGetReqBtn = true;
showReqs = true;
}
} catch (error) {
if (error.code === "ECONNABORTED") {
location.reload();
} else {
orderStatus = 6;
}
//console.log(error);
// if (tries > 3) {
// } else {
// getOrderStatus();
// }
}
}
let value_disputeSum = 0;
async function loadReceipt() {
const formData = new FormData();
let file = document.getElementById("loaded-file").files[0];
// formData.append("uuid", orderID);
formData.append("data", file);
formData.append("amount", Number(value_disputeSum));
let result = await axios.post(apiBase + "openDispute", formData, {
headers: {
Authorization: "Bearer " + tokenURL,
@ -294,6 +343,11 @@
},
});
// //console.log(result);
if (result.status > 300) {
sayError("Что-то пошло не так");
return;
}
sayInfo("Успешно!");
}
async function createDispute() {
@ -344,37 +398,52 @@
//console.log(result);
}
async function copyToClipboard() {
async function copyToClipboard(val) {
try {
await navigator.clipboard.writeText(requisites[1]);
await navigator.clipboard.writeText(val);
sayInfo("Скопировано!");
} catch (err) {
//console.error("Failed to copy: ", err);
}
}
function startPingingStatus() {ping();}
function startPingingStatus() {
ping();
}
async function ping() {
await getOrderStatus();
// console.log(orderStatus);
// console.log("url", redirectURL);
if (orderStatus === 2) {
showReject = true;
showLoadingScreen = false;
await delay(500);
if (redirectURL !== "") {
window.open(redirectURL, "_self");
}
return;
}
if(orderStatus === 3)
{
if (orderStatus === 3) {
showAccept = true;
showLoadingScreen = false;
await delay(500);
if (redirectURL !== "") {
window.open(redirectURL, "_self");
}
return;
}
if(orderStatus===6)
{
if (orderStatus === 6) {
showTimeout = true;
showLoadingScreen = false;
await delay(500);
if (redirectURL !== "") {
window.open(redirectURL, "_self");
}
return;
}
await delay(1000);
await delay(1500);
ping();
}
</script>
@ -406,7 +475,7 @@
</svg>
</div>
</div>
{:else}
{:else if !showAccept && !showTimeout && !showReject}
<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"
>
@ -418,7 +487,13 @@
</div>
<div class="flex flex-col w-full gap-8">
{#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}
<div class="flex">
<button
@ -468,27 +543,47 @@
{#if showReqs}
{#if !showHelpSection}
<div class="w-full flex p-8 rounded-3xl bg-indigo-950">
<div class="flex flex-col gap-2">
<p class="text-lg">Номер карты для перевода</p>
<div class="flex gap-4 items-center">
<p class="text-2xl font-bold">
<div class="flex flex-col gap-2 w-full">
<p class="text-lg">Реквизиты</p>
<div
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]}
</p>
<button
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
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
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>
</button>
</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">
Время на оплату: {timeLeft}
</p>
@ -519,6 +614,12 @@
</button>
{/if}
{#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>
@ -659,9 +760,11 @@
<div class="bg-indigo-600 w-10 h-10 rounded-full"></div>
</div>
<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-sm">Номер платежа: {orderID}</p>
<p class="text-white opacity-50 text-sm">
<p class="text-white opacity-50 text-xl mt-2">
Это не займет много времени
</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"
>@hosta_pay</a
>
@ -710,9 +813,21 @@
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 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
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>
<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">
@ -725,4 +840,50 @@
</p>
</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}