Добавление срока для оплаты счёта, по истечению - удаление счёта.

This commit is contained in:
justuser-31 2025-11-24 19:06:22 +03:00
parent be8f5e37f0
commit 0e382d8f72

View File

@ -22,6 +22,7 @@ import java.io.FileInputStream
import java.util.Properties import java.util.Properties
import kotlin.collections.mutableMapOf import kotlin.collections.mutableMapOf
import kotlin.math.abs import kotlin.math.abs
import java.util.Date
class Vp_server_integration() : JavaPlugin(), CommandExecutor { class Vp_server_integration() : JavaPlugin(), CommandExecutor {
companion object { companion object {
@ -38,6 +39,7 @@ class Vp_server_integration() : JavaPlugin(), CommandExecutor {
var COURSE_STATIC_VALUE: Double = DEFAULT_COURSE_STATIC_VALUE var COURSE_STATIC_VALUE: Double = DEFAULT_COURSE_STATIC_VALUE
lateinit var COURSE_DYNAMIC_COMMAND: String lateinit var COURSE_DYNAMIC_COMMAND: String
var COURSE_COMMISSION: Float = DEFAULT_COURSE_COMMISSION var COURSE_COMMISSION: Float = DEFAULT_COURSE_COMMISSION
var INVOICE_TIMEOUT_SECONDS: Long = DEFAULT_INVOICE_TIMEOUT_SECONDS
// Default configuration values // Default configuration values
const val DEFAULT_USERNAME: String = "test" const val DEFAULT_USERNAME: String = "test"
@ -51,6 +53,7 @@ class Vp_server_integration() : JavaPlugin(), CommandExecutor {
const val DEFAULT_COURSE_STATIC_VALUE: Double = 1000.0 const val DEFAULT_COURSE_STATIC_VALUE: Double = 1000.0
const val DEFAULT_COURSE_DYNAMIC_COMMAND: String = "baltop force" const val DEFAULT_COURSE_DYNAMIC_COMMAND: String = "baltop force"
const val DEFAULT_COURSE_COMMISSION: Float = 5.0f const val DEFAULT_COURSE_COMMISSION: Float = 5.0f
const val DEFAULT_INVOICE_TIMEOUT_SECONDS: Long = 300 // 5 minutes
const val PREFIX = "&9[&bVPC&7-&6I&9] &3" const val PREFIX = "&9[&bVPC&7-&6I&9] &3"
@ -67,6 +70,10 @@ class Vp_server_integration() : JavaPlugin(), CommandExecutor {
var TO_PAY_INVOICES: MutableMap<String, String> = mutableMapOf() // Pair: {player: invoice_id} var TO_PAY_INVOICES: MutableMap<String, String> = mutableMapOf() // Pair: {player: invoice_id}
@JvmStatic @JvmStatic
var INVOICES_AMOUNT: MutableMap<String, Double> = mutableMapOf() // How many should we pay to player after invoice? var INVOICES_AMOUNT: MutableMap<String, Double> = mutableMapOf() // How many should we pay to player after invoice?
// Track invoice creation times for timeout handling
@JvmStatic
var INVOICE_CREATION_TIMES: MutableMap<String, Long> = mutableMapOf() // Pair: {invoice_id: creation_timestamp}
} }
/** /**
@ -102,6 +109,7 @@ class Vp_server_integration() : JavaPlugin(), CommandExecutor {
COURSE_STATIC_VALUE = properties.getProperty("course_static_value", DEFAULT_COURSE_STATIC_VALUE.toString()).replace("'", "").toDouble() COURSE_STATIC_VALUE = properties.getProperty("course_static_value", DEFAULT_COURSE_STATIC_VALUE.toString()).replace("'", "").toDouble()
COURSE_DYNAMIC_COMMAND = properties.getProperty("course_dynamic_command", DEFAULT_COURSE_DYNAMIC_COMMAND).replace("'", "") COURSE_DYNAMIC_COMMAND = properties.getProperty("course_dynamic_command", DEFAULT_COURSE_DYNAMIC_COMMAND).replace("'", "")
COURSE_COMMISSION = properties.getProperty("course_commission", DEFAULT_COURSE_COMMISSION.toString()).replace("'", "").toFloat() COURSE_COMMISSION = properties.getProperty("course_commission", DEFAULT_COURSE_COMMISSION.toString()).replace("'", "").toFloat()
INVOICE_TIMEOUT_SECONDS = properties.getProperty("invoice_timeout_seconds", DEFAULT_INVOICE_TIMEOUT_SECONDS.toString()).replace("'", "").toLong()
logger.info("Configuration loaded successfully - Username: $USERNAME, API URL: $USER_API_URL") logger.info("Configuration loaded successfully - Username: $USERNAME, API URL: $USER_API_URL")
} catch (e: Exception) { } catch (e: Exception) {
@ -163,6 +171,11 @@ course_dynamic_command='$DEFAULT_COURSE_DYNAMIC_COMMAND'
# For dynamic course recommended 5% and higher (avoid dupe), for static course you can set 0% # For dynamic course recommended 5% and higher (avoid dupe), for static course you can set 0%
course_commission=$DEFAULT_COURSE_COMMISSION course_commission=$DEFAULT_COURSE_COMMISSION
# -------------------- END ------------------------ # -------------------- END ------------------------
# --------- Invoice timeout configuration ----------
# After how many seconds unpaid invoices will be deleted (default: 300 seconds = 5 minutes)
invoice_timeout_seconds=$DEFAULT_INVOICE_TIMEOUT_SECONDS
# -------------------- END ------------------------
""".trimIndent() """.trimIndent()
) )
} }
@ -381,6 +394,7 @@ course_commission=$DEFAULT_COURSE_COMMISSION
val invoiceId = VpcApi.create_invoice(amount).toString() val invoiceId = VpcApi.create_invoice(amount).toString()
TO_PAY_INVOICES[sender.name] = invoiceId TO_PAY_INVOICES[sender.name] = invoiceId
INVOICES_AMOUNT[invoiceId] = amountLC INVOICES_AMOUNT[invoiceId] = amountLC
INVOICE_CREATION_TIMES[invoiceId] = System.currentTimeMillis()
sendPaymentPrompt(sender, amount, amountLC, invoiceId) sendPaymentPrompt(sender, amount, amountLC, invoiceId)
} }
@ -437,6 +451,7 @@ course_commission=$DEFAULT_COURSE_COMMISSION
synchronized(TO_AUTH_PLAYERS) { synchronized(TO_AUTH_PLAYERS) {
TO_AUTH_PLAYERS[sender.name] = vpcUsernameInput TO_AUTH_PLAYERS[sender.name] = vpcUsernameInput
TO_AUTH_PLAYERS_INVOICES[sender.name] = invoiceId.toString() TO_AUTH_PLAYERS_INVOICES[sender.name] = invoiceId.toString()
INVOICE_CREATION_TIMES[invoiceId.toString()] = System.currentTimeMillis()
} }
LOGGER.info("Authentication lists updated") LOGGER.info("Authentication lists updated")
@ -502,6 +517,7 @@ course_commission=$DEFAULT_COURSE_COMMISSION
override fun run() { override fun run() {
processAuthenticationInvoices() processAuthenticationInvoices()
processPaymentInvoices() processPaymentInvoices()
cleanupExpiredInvoices()
} }
}.runTaskTimerAsynchronously(this, 0L, 20L) }.runTaskTimerAsynchronously(this, 0L, 20L)
} }
@ -531,6 +547,7 @@ course_commission=$DEFAULT_COURSE_COMMISSION
// Clean up tracking maps // Clean up tracking maps
TO_AUTH_PLAYERS.remove(entry.key) TO_AUTH_PLAYERS.remove(entry.key)
INVOICE_CREATION_TIMES.remove(entry.value)
iterator.remove() iterator.remove()
} }
} else { } else {
@ -583,6 +600,7 @@ course_commission=$DEFAULT_COURSE_COMMISSION
// Clean up tracking maps // Clean up tracking maps
INVOICES_AMOUNT.remove(entry.key) INVOICES_AMOUNT.remove(entry.key)
INVOICE_CREATION_TIMES.remove(entry.value)
iterator.remove() iterator.remove()
} }
} else { } else {
@ -596,4 +614,72 @@ course_commission=$DEFAULT_COURSE_COMMISSION
} }
} }
} }
/**
* Cleanup expired invoices based on timeout configuration
*/
private fun cleanupExpiredInvoices() {
val currentTime = System.currentTimeMillis()
val timeoutMillis = INVOICE_TIMEOUT_SECONDS * 1000
// Cleanup auth invoices
synchronized(TO_AUTH_PLAYERS_INVOICES) {
val authIterator = TO_AUTH_PLAYERS_INVOICES.iterator()
while (authIterator.hasNext()) {
val entry = authIterator.next()
val invoiceId = entry.value
val creationTime = INVOICE_CREATION_TIMES[invoiceId] ?: continue
if (currentTime - creationTime > timeoutMillis) {
LOGGER.info("Deleting expired auth invoice: $invoiceId")
try {
VpcApi.delete_invoice(invoiceId)
} catch (e: Exception) {
LOGGER.error("Error deleting expired auth invoice $invoiceId: ${e.message}")
}
// Clean up tracking maps
TO_AUTH_PLAYERS.remove(entry.key)
INVOICE_CREATION_TIMES.remove(invoiceId)
authIterator.remove()
// Notify player if online
val player = Bukkit.getPlayer(entry.key)
if (player != null && player.isOnline) {
Utils.send(player, "&cВаша авторизационная оплата истекла. Пожалуйста, попробуйте снова: /vpi auth <ник>")
}
}
}
}
// Cleanup payment invoices
synchronized(TO_PAY_INVOICES) {
val paymentIterator = TO_PAY_INVOICES.iterator()
while (paymentIterator.hasNext()) {
val entry = paymentIterator.next()
val invoiceId = entry.value
val creationTime = INVOICE_CREATION_TIMES[invoiceId] ?: continue
if (currentTime - creationTime > timeoutMillis) {
LOGGER.info("Deleting expired payment invoice: $invoiceId")
try {
VpcApi.delete_invoice(invoiceId)
} catch (e: Exception) {
LOGGER.error("Error deleting expired payment invoice $invoiceId: ${e.message}")
}
// Clean up tracking maps
INVOICES_AMOUNT.remove(invoiceId)
INVOICE_CREATION_TIMES.remove(invoiceId)
paymentIterator.remove()
// Notify player if online
val player = Bukkit.getPlayer(entry.key)
if (player != null && player.isOnline) {
Utils.send(player, "&cВаша оплата истекла. Пожалуйста, создайте новую: /vpi convert lc <сумма>")
}
}
}
}
}
} }