Skip to content

Commit 573329a

Browse files
authored
Добавлен возврат со страницы с куаркодом в заявку и автопроверка статуса. Обновлен текст о платеже. (#2780)
1 parent 845e925 commit 573329a

File tree

7 files changed

+163
-29
lines changed

7 files changed

+163
-29
lines changed

src/JoinRpg.Portal/Controllers/Money/PaymentsController.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Net;
12
using JoinRpg.DataModel;
23
using JoinRpg.Interfaces;
34
using JoinRpg.Services.Interfaces;
@@ -268,6 +269,27 @@ public async Task<ActionResult> UpdateClaimPayment(int projectId, int claimId, i
268269
}
269270
}
270271

272+
[HttpGet]
273+
[Authorize]
274+
public async Task<ActionResult> CheckClaimPayment(int projectId, int claimId, int orderId)
275+
{
276+
try
277+
{
278+
var result = await _payments.UpdateClaimPaymentAsync(projectId, claimId, orderId);
279+
return result switch
280+
{
281+
FinanceOperationState.Approved => Ok(),
282+
FinanceOperationState.Proposed => StatusCode((int)HttpStatusCode.Accepted),
283+
FinanceOperationState.Declined or FinanceOperationState.Invalid => StatusCode((int)HttpStatusCode.UnprocessableEntity),
284+
_ => BadRequest(),
285+
};
286+
}
287+
catch (Exception)
288+
{
289+
return BadRequest();
290+
}
291+
}
292+
271293
[HttpPost]
272294
[Authorize]
273295
[ValidateAntiForgeryToken]

src/JoinRpg.Portal/Views/Finances/_PayOnlineDialog.cshtml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
}
3434

3535
<div class="join alert alert-info">
36-
<i class="glyphicon glyphicon-info-sign"></i>
3736
<div style="font-size: smaller;">
3837
@await Html.PartialAsync("..\\Finances\\_PaymentLegalInfoPartial")
3938
</div>
@@ -72,9 +71,9 @@
7271
</div>
7372

7473
<div class="form-group">
75-
<div class="col-md-12">
74+
<div class="col-md-12" style="display: flex; flex-direction: row; align-items: center;">
7675
@Html.CheckBoxFor(m => m.AcceptContract, new { id = "onp_contract", onchange = "onlinePaymentMoneyChangeHandler()" })
77-
<label for="onp_contract">Я прочитал(а), понял(а) и принимаю условия @Html.ActionLink("оферты", "user-agreement", "OnlinePayments")</label>
76+
<label for="onp_contract" style="margin-left: 1em;">Я прочитал(а), понял(а) и принимаю условия @Html.ActionLink("оферты", "user-agreement", "OnlinePayments")</label>
7877
</div>
7978
</div>
8079
</div>

src/JoinRpg.Portal/Views/Finances/_PaymentLegalInfoPartial.cshtml

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
@using JoinRpg.Web.Models
22
@using JoinRpg.Helpers
33
<p>
4-
<strong>Оплата картой.</strong>
5-
После нажатия кнопки «@PaymentMethodViewModel.BankCard.GetDisplayName()» вы будете перенаправлены
6-
на страницу платежного сервиса «ПСКБ Онлайн» для ввода данных своей банковской карты. Поддерживаются
7-
карты МИР и другие российские карты. Если банк, выдавший вам карту, требует дополнительную проверку,
8-
то произойдет переадресация на страницу банка для ввода одноразового пароля (технология 3D Secure).
4+
Кнопка «<strong>@PaymentMethodViewModel.BankCard.GetDisplayName()</strong>» — оплата банковской картой,
5+
выпущенной в России. Может потребоваться ввод одноразового пароля (технология 3D Secure).
96
</p>
107
<p>
11-
<strong>Оплата по QR-коду.</strong>
12-
После нажатия кнопки «@PaymentMethodViewModel.FastPaymentsSystem.GetDisplayName()» вы будете
13-
перенаправлены на страницу платежного сервиса «ПСКБ Онлайн», на которой произойдет отображение
14-
QR-кода <a target="_blank" href="https://sbp.nspk.ru/">Системы Быстрых Платежей</a>. Для выполнения
15-
оплаты мобильное приложение вашего банка должно поддерживать оплату по QR-коду.
8+
Кнопка «<strong>@PaymentMethodViewModel.FastPaymentsSystem.GetDisplayName()</strong>» — оплата
9+
либо сканированием QR-кода, либо через приложение вашего банка (если вы с мобильного устройства).
1610
</p>
17-
<p>
18-
JoinRpg.Ru не имеет доступа к данным вашей карты или банковского аккаунта, и соответственно
19-
не обрабатывает и не хранит их, они обрабатываются платежным сервисом «ПСКБ Онлайн» согласно
11+
<p style="font-size: smaller;">
12+
JoinRpg.Ru не имеет доступа к данным вашей карты или банковского аккаунта, не обрабатывает
13+
и не хранит их, они обрабатываются платежным сервисом «ПСКБ Онлайн» согласно
2014
требованиям стандарта безопасности PCI&nbsp;DSS&nbsp;3.0, передаются через соединение, зашифрованное
2115
по технологии SSL. Безопасность гарантирует <a target="_blank" href="https://pscb.ru">АО&nbsp;Банк&nbsp;«ПСКБ»</a>.
2216
</p>

src/JoinRpg.Portal/Views/Payments/FastPaymentsSystemPayment.cshtml

Lines changed: 124 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@
2222
width: 100%;
2323
height: 100%;
2424
overflow: hidden;
25-
padding: 0.5em;
2625
display: flex;
2726
flex-direction: column;
28-
align-items: stretch;
27+
align-items: center;
2928
justify-content: stretch;
3029
}
3130
@@ -34,6 +33,7 @@
3433
flex-shrink: 0;
3534
padding: 0.5em;
3635
font-weight: bold;
36+
max-width: 1000px;
3737
}
3838
3939
div.header {
@@ -47,12 +47,21 @@
4747
padding: 0.5em 0;
4848
margin-top: 0.5em;
4949
border-top: 1px solid silver;
50+
width: 100%;
51+
display: flex;
52+
flex-direction: column;
53+
align-items: center;
54+
}
55+
56+
div.footer-content {
57+
width: 100%;
58+
max-width: 1000px;
5059
display: flex;
5160
flex-direction: row;
5261
}
5362
54-
div.footer button,
55-
div.footer a {
63+
div.footer-content button,
64+
div.footer-content a {
5665
border: 1px solid lightgray;
5766
padding: 0.3em;
5867
font-size: 0.9em;
@@ -79,12 +88,41 @@
7988
justify-content: center;
8089
}
8190
91+
.qr-container-inner {
92+
display: flex;
93+
flex-direction: column;
94+
align-items: center;
95+
}
96+
97+
#qrbuttons {
98+
margin-top: 1em;
99+
display: flex;
100+
flex-direction: row;
101+
align-items: center;
102+
justify-content: center;
103+
}
104+
105+
#qrbuttons button {
106+
border: 1px solid lightgray;
107+
padding: 0.5em;
108+
font-size: 1.2em;
109+
border-radius: 0.3em;
110+
color: black;
111+
background-color: lightgreen;
112+
text-decoration: none;
113+
display: inline-block;
114+
}
115+
82116
#qrcode {
83117
display: block;
84118
max-width: 100%;
85119
max-height: 100%;
86120
}
87121
122+
#qrdone {
123+
124+
}
125+
88126
#payment-app {
89127
width: 100%;
90128
height: 100%;
@@ -179,7 +217,13 @@
179217
<div id="payment-qrcode" style="display: none;">
180218
<div class="header">Отсканируйте QR-код, чтобы оплатить <b>@(Model.Amount)&nbsp;₽</b></div>
181219
<div id="qrcontainer">
182-
<img id="qrcode" src="@Model.QrCodeUrl" alt="QR код"/>
220+
<div class="qr-container-inner">
221+
<div id="qrdone" style="display: none;">Переадресация обратно на @Html.ActionLink("заявку", "UpdateClaimPayment", "Payments", new { projectId = Model.ProjectId, claimId = Model.ClaimId, orderId = Model.OperationId })&hellip;</div>
222+
<img id="qrcode" src="@Model.QrCodeUrl" alt="QR код"/>
223+
<div id="qrbuttons">
224+
<button type="button" id="btn-confirm" onclick="paid();">Я все оплатил, вернуться к заявке</button>
225+
</div>
226+
</div>
183227
</div>
184228
</div>
185229

@@ -205,8 +249,10 @@
205249
}
206250

207251
<div class="footer">
208-
@Html.ActionLink("Вернуться без оплаты", "Edit", "Claim", new { projectId = Model.ProjectId, claimId = Model.ClaimId }, new { id = "btn-cancel" })
209-
<button id="btn-showqr" style="margin-left: auto; display: none;" type="button" onclick="toggleQrCode()">Показать QR-код</button>
252+
<div class="footer-content">
253+
@Html.ActionLink("Вернуться без оплаты", "Edit", "Claim", new { projectId = Model.ProjectId, claimId = Model.ClaimId }, new { id = "btn-cancel" })
254+
<button id="btn-showqr" style="margin-left: auto; display: none;" type="button" onclick="toggleQrCode()">Показать QR-код</button>
255+
</div>
210256
</div>
211257
</div>
212258
<script type="text/javascript">
@@ -215,8 +261,18 @@ const blockQr = document.getElementById('payment-qrcode');
215261
const blockBanks = document.getElementById('payment-app');
216262
const btnShowQr = document.getElementById('btn-showqr');
217263
let banksMode = false;
264+
const checkPaymentUrl = '@Html.Raw(Url.Action("CheckClaimPayment", "Payments", new { projectId = Model.ProjectId, claimId = Model.ClaimId, orderId = Model.OperationId }))';
265+
const returnUrl = '@Html.Raw(Url.Action("UpdateClaimPayment", "Payments", new { projectId = Model.ProjectId, claimId = Model.ClaimId, orderId = Model.OperationId }))';
266+
const btnConfirm = document.getElementById('btn-confirm');
267+
const blockQrImage = document.getElementById('qrcode');
268+
const blockQrButtons = document.getElementById('qrbuttons');
269+
const blockQrDone = document.getElementById('qrdone');
270+
let paymentValidationTaskInstaller = null;
271+
let paymentValidationTask = null;
272+
218273
if (document.platform.type === 'desktop' || document.platform.type !== expectedPlatform || !blockBanks) {
219274
blockQr.style.display = 'flex';
275+
startValidationTask();
220276
} else {
221277
blockBanks.style.display = 'flex';
222278
btnShowQr.style.display = 'block';
@@ -247,7 +303,9 @@ function toggleQrCode() {
247303
blockBanks.style.display = 'none';
248304
blockQr.style.display = 'flex';
249305
banksMode = false;
306+
startValidationTask();
250307
} else {
308+
stopValidationTask();
251309
btnShowQr.innerHTML = 'Показать QR-код';
252310
blockQr.style.display = 'none';
253311
blockBanks.style.display = 'flex';
@@ -317,6 +375,65 @@ function showAllBanks() {
317375
}
318376
allBanksVisible = true;
319377
}
378+
379+
async function isPaid() {
380+
const result = await fetch(checkPaymentUrl);
381+
return result.status === 200;
382+
}
383+
384+
async function validatePayment() {
385+
386+
if (await isPaid()) {
387+
paid();
388+
}
389+
}
390+
391+
function startValidationTask() {
392+
if (!paymentValidationTask) {
393+
if (!paymentValidationTaskInstaller) {
394+
paymentValidationTaskInstaller = setTimeout(
395+
() => {
396+
if (paymentValidationTaskInstaller && !paymentValidationTask) {
397+
paymentValidationTask = setInterval(validatePayment, 1000);
398+
}
399+
paymentValidationTaskInstaller = null;
400+
},
401+
10000);
402+
}
403+
}
404+
}
405+
406+
function stopValidationTask() {
407+
if (paymentValidationTaskInstaller) {
408+
try {
409+
clearTimeout(paymentValidationTaskInstaller);
410+
} finally {
411+
paymentValidationTaskInstaller = null;
412+
}
413+
}
414+
if (paymentValidationTask) {
415+
try {
416+
clearInterval(paymentValidationTask);
417+
} finally {
418+
paymentValidationTask = null;
419+
}
420+
}
421+
}
422+
423+
let ispaid = false;
424+
425+
function paid() {
426+
if (ispaid) {
427+
return;
428+
}
429+
ispaid = true;
430+
stopValidationTask();
431+
blockQrImage.style.display = 'none';
432+
blockQrButtons.style.display = 'none';
433+
blockQrDone.style.display = 'block';
434+
document.location.href = returnUrl;
435+
}
436+
320437
</script>
321438
</body>
322439
</html>

src/JoinRpg.Services.Impl/PaymentsService.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,11 @@ private void UpdateFinanceOperationStatus(FinanceOperation fo, PaymentData payme
567567
}
568568
}
569569

570-
private async Task UpdateClaimPaymentAsync(FinanceOperation fo, PaymentInfo? paymentInfo = null)
570+
private async Task<FinanceOperationState> UpdateClaimPaymentAsync(FinanceOperation fo, PaymentInfo? paymentInfo = null)
571571
{
572572
if (fo.State != FinanceOperationState.Proposed)
573573
{
574-
return;
574+
return fo.State;
575575
}
576576

577577
logger.LogInformation("Updating online payment {financeOperationId} for claim {claimId} to project {projectId}", fo.CommentId, fo.ClaimId, fo.ProjectId);
@@ -701,6 +701,8 @@ private async Task UpdateClaimPaymentAsync(FinanceOperation fo, PaymentInfo? pay
701701
Debug.Assert(claim is not null);
702702
await SendPaymentNotification(claim, fo.MoneyAmount, paymentNotification);
703703
}
704+
705+
return fo.State;
704706
}
705707

706708
private enum PaymentNotification
@@ -769,7 +771,7 @@ private async Task SendPaymentNotification(Claim claim, int sum, PaymentNotifica
769771
}
770772

771773
/// <inheritdoc />
772-
public async Task UpdateClaimPaymentAsync(int projectId, int claimId, int orderId)
774+
public async Task<FinanceOperationState> UpdateClaimPaymentAsync(int projectId, int claimId, int orderId)
773775
=> await UpdateClaimPaymentAsync(await LoadFinanceOperationAsync(projectId, claimId, orderId));
774776

775777
/// <inheritdoc />

src/JoinRpg.Services.Interfaces/IPaymentsService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ Task<FastPaymentsSystemMobilePaymentContext> GetFastPaymentsSystemMobilePaymentC
237237
/// <param name="projectId">Database Id of a project</param>
238238
/// <param name="claimId">Database Id of a claim</param>
239239
/// <param name="orderId">Finance operation Id</param>
240-
Task UpdateClaimPaymentAsync(int projectId, int claimId, int orderId);
240+
Task<FinanceOperationState> UpdateClaimPaymentAsync(int projectId, int claimId, int orderId);
241241

242242
/// <summary>
243243
/// Updates status of the last proposed payment

src/JoinRpg.WebPortal.Models/Money/PaymentMethodViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ namespace JoinRpg.Web.Models;
55

66
public enum PaymentMethodViewModel
77
{
8-
[Display(Name = "Оплатить картой", Description = "Оплата банковской картой МИР — нужно будет ввести данные карты")]
8+
[Display(Name = "Оплата картой", Description = "Оплата банковской картой МИР — нужно будет ввести данные карты")]
99
BankCard = PaymentMethod.BankCard,
1010

11-
[Display(Name = "Оплатить по QR-коду", Description = "Оплата через Систему Быстрых Платежей при помощи QR-кода — нужно будет отсканировать QR-код в приложении вашего банка")]
11+
[Display(Name = "Оплата по QR-коду", Description = "Оплата через Систему Быстрых Платежей при помощи QR-кода — нужно будет отсканировать QR-код в приложении вашего банка")]
1212
FastPaymentsSystem = PaymentMethod.FastPaymentsSystem,
1313
}

0 commit comments

Comments
 (0)