Neste artigo, parafusaremos a rosquinha sem Deus no servidor baunilha do Minecraft usando o Powershell. A vantagem do método é que o minecraft é apenas um caso especial da implementação de pagamentos automáticos usando comandos do console. Apenas ouvimos o que o sistema de pagamento nos envia e agrupamos em uma equipe. E o mais importante - sem plugins.E vamos aceitar pagamentos através do PayPal. Mais importante, para começar a aceitar pagamentos, você não precisa alterar o código, o PayPal nos enviará tudo o que você precisa. Usaremos os botões no site, para que o site possa funcionar com HTML puro. Nós abstraímos das complexidades do próprio sistema de pagamento e nos concentramos apenas nos pontos principais do código.A propósito, o autor ficará muito feliz se você examinar todos os seus módulos e encontrar erros de crianças que você aponta ou corrige. Aqui está um link para o projeto github .Algumas palavras sobre IPN
IPN
Aceitaremos pagamentos através dos botões. Os botões não requerem nenhum back-end, eles funcionam em HTML puro e também possuem seus próprios campos.Os botões acionam o IPN - Notificação de pagamento instantâneo, na qual os dados são enviados ao nosso WebListener. Vamos considerar a estrutura do IPN abaixo.Além disso, qualquer pessoa que tenha uma conta no PayPal pode criar seu próprio botão.O IPN não possui a API REST completa do PayPal, mas a funcionalidade básica pode ser implementada nele. De fato, o IPN que estamos considerando não é uma API REST no sentido pleno da palavra, apenas porque o próprio PayPal não espera nada de nós, exceto o código 200.Levar o WebListener
O PayPal, por motivos de segurança, não envia solicitações via HTTP, portanto, precisamos emitir um certificado para começar. O autor usou o WinAcme . Você pode emitir um certificado para qualquer domínio e precisa colocá-lo em um armazenamento de certificados local. A propósito, o WinAcme está localizado na raiz do disco na imagem.
Get-ChildItem -Path Cert:\LocalMachine\My
netsh http add sslcert ipport=0.0.0.0:443 certhash=D106F5676534794B6767D1FB75B58D5E33906710 "appid={00112233-4455-6677-8899-AABBCCDDEEFF}"
O Powershell pode usar classes do .net, o que o torna quase igual ao .net. Primeiro, usando a classe HttpListener, levante o servidor da Web.
$http = [System.Net.HttpListener]::new()
$http.Prefixes.Add("http://donate.to/")
$http.Prefixes.Add("https://donate.to/")
$http.Start()
Para verificar se tudo está bem, execute o netstat.
Se nosso script começou a escutar a porta 443 na lista, significa que você fez tudo corretamente e podemos continuar aceitando o processamento da solicitação. Só não se esqueça do firewall.Aceitar pedido
Usando o IPN Simulator, podemos enviar uma solicitação POST de teste para ver o que é. Como você não pode incluir seus próprios campos, o autor recomenda que você faça um botão e compre imediatamente algo de si mesmo. O Histórico de IPN exibirá uma solicitação normal no botão que você usará. O autor fez exatamente isso comprando um carvão por um rublo.Aceitaremos o uso do loop While. Enquanto o servidor da web estiver em execução, podemos ler o fluxo de dados recebidos.while ($http.IsListening) {
$context = $http.GetContext()
if ($context.Request.HttpMethod -eq 'POST' -and $context.Request.RawUrl -eq '/') {
$Reader = [System.IO.StreamReader]::new($context.Request.InputStream).ReadToEnd()
$DecodedContent = [System.Web.HttpUtility]::UrlDecode($Reader)
$Payment | Format-Table
$context.Response.Headers.Add("Content-Type", "text/plain")
$context.Response.StatusCode = 200
$ResponseBuffer = [System.Text.Encoding]::UTF8.GetBytes("")
$context.Response.ContentLength64 = $ResponseBuffer.Length
$context.Response.OutputStream.Write($ResponseBuffer, 0, $ResponseBuffer.Length)
$context.Response.Close()
}
}
Se você receber uma aletria como esta, aplique:$Payment = $DecodedContent -split "&" | ConvertFrom-StringData
Depois disso, você finalmente receberá um objeto normal, onde todo o valor é String.
Você pode parar de ler aqui mesmo se não quiser aprofundar o código, mas apenas deseja aceitar solicitações da API de alguém.Aqui está o código que funciona imediatamente, copie e use:
$http = [System.Net.HttpListener]::new()
$http.Prefixes.Add("http://localhost/")
$http.Prefixes.Add("https://localhost/")
$http.Start()
while ($http.IsListening) {
$context = $http.GetContext()
if ($context.Request.HttpMethod -eq 'POST' -and $context.Request.RawUrl -eq '/') {
$Reader = [System.IO.StreamReader]::new($context.Request.InputStream).ReadToEnd()
$DecodedContent = [System.Web.HttpUtility]::UrlDecode($Reader)
$Payment = $DecodedContent -split "&" | ConvertFrom-StringData
$Payment | Format-Table
$context.Response.Headers.Add("Content-Type", "text/plain")
$context.Response.StatusCode = 200
$ResponseBuffer = [System.Text.Encoding]::UTF8.GetBytes("")
$context.Response.ContentLength64 = $ResponseBuffer.Length
$context.Response.OutputStream.Write($ResponseBuffer, 0, $ResponseBuffer.Length)
$context.Response.Close()
}
}
Minecraft Nuances
Então, descobrimos como podemos receber alertas sobre pagamentos, agora podemos creditá-los. Mas aqui também não é tão simples. O problema é que o jogo não fornece itens ou altera o status dos jogadores que não estão no servidor. Ou seja, precisamos esperar até que uma pessoa entre no servidor para lhe dar o que pagou.Portanto, sua atenção é apresentada ao conceito geral de fumante, para crédito de pagamentos.
Os pagamentos são recebidos pelo Ouvinte acima; apenas uma linha foi adicionada a ele para gravar o objeto no arquivo. O Pagamento Completo (Processador) examina o apelido e o combina com o nome do arquivo. Se ele encontrar um arquivo, compila um comando para o rcon e o executa.Iniciar minecraftsobre o qual o autor escreveu em um artigo anterior foi ligeiramente modificado. Agora ele ouve a conclusão, olha os apelidos dos jogadores e os passa para o processador de pagamentos.Fazendo retornos de chamada reais
Sem usar plug-ins, faremos retornos de chamada verdadeiros. Para isso, o Start-Minecraft foi modificado. Agora ele não apenas sabe como adicionar o StdOut a um arquivo, mas também percorre cada linha com uma programação regular. Felizmente, o minecraft deixa uma mensagem muito específica quando um jogador entra no servidor.[04:20:00 INFO]: UUID of player XXPROHUNTERXX is 23e93d2e-r34d-7h15 -5h17-a9192cd70b48
É muito fácil escolher um apelido nesta linha. Aqui está todo o código que precisamos para obter dados das seqüências de caracteres Stdout.$Regex = [Regex]::new("of player ([^ ]+)")
powershell.exe -file ".\Start-MinecraftHandler.ps1" -type $type -MinecraftPath $MinecraftPath | Tee-Object $LogFile -Append | ForEach-Object {
Write-host $_
$Player = $Regex.Matches($_).value -replace "of player "
if ($true -eq $Regex.Matches($_).Success) {
}
}
Uma nova linha é inserida no pipeline $ _, nós a escrevemos na janela do console e a analisamos regularmente. O regular em si nos notifica quando funciona, o que é muito conveniente.A partir daqui, podemos chamar qualquer código. Por exemplo, usando o mesmo RCON, podemos cumprimentar o jogador no PM, usando o bot na discórdia para notificar que alguém fez logon no servidor, banir o xeque-mate e assim por diante.Fazendo pagamentos
Desde que começamos a processar os pagamentos, gostaríamos de ter dados pelo menos bastante completos sobre a operação e o histórico das operações realizadas, porque estamos falando de números com dois zeros, por assim dizer.O autor quer deixar tudo extremamente simples e ainda não simular uma base. Vejamos a abordagem NoSQL. Vamos criar nossa própria classe, que importará todos os pagamentos aceitos para a pasta / payment / nos arquivos Json. class Payment {
[datetime]$Date = [datetime]::ParseExact($i.payment_date, "HH:mm:ss MMM dd, yyyy PDT", [System.Globalization.CultureInfo]::InvariantCulture)
[string]$Item = $i.item_name
[UInt16]$Quantity = $i.Quantity
[UInt16]$AmountPaid = $AmountPaid -as [UInt16]
[string]$Currency = $i.mc_currency
[string]$Player = $i.option_selection1
[bool]$Completed = $false
[UInt16]$ItemId = $i.item_number
}
/source>
, , , .
, <b>option_selection1</b> – . input, , .
<b>option_selection1</b>,<b>option_selection2</b> .
, , .
<source lang="powershell">
$Payment = [Payment]::new()
$Payment | Format-Table
$FileName = $Payment.Player + "-" + $Payment.date.Hour + "-" + $Payment.date.Minute + "-" + $Payment.date.Day + "-" + $Payment.date.Month + "-" + $Payment.date.Year + ".json"
$JsonPath = Join-Path $MinecraftPath \payments\Pending $FileName
$Payment | ConvertTo-Json | Out-File $JsonPath
Isso é tudo o que foi exigido do nosso ouvinte. Receba dados do PayPal e grave em um arquivo.Fazemos o processamento do pagamento
O manipulador será chamado de regular que foi escrito anteriormente. Transferimos o apelido do jogador para o módulo e é isso. Em seguida, um novo script é iniciado, que procura o arquivo e, se houver, ele fornece ao player o item que está escrito no arquivo.powershell.exe -file "C:\mc.fern\Start-MinecraftHandler.ps1" -type $type -MinecraftPath $MinecraftPath | Tee-Object $LogFile -Append | ForEach-Object {
Write-host $_
if ($true -eq $Regex.Matches($_).Success) {
$Player = $Regex.Matches($_).value -replace "of player "
Complete-Payment -Player $Player
}
}
Quando a regularidade é acionada, é lançado um módulo que completa o pagamento, ou seja, fornece um item ao jogador. Para fazer isso, na pasta / Pagamentos / Pendente /, o script procura arquivos que contenham o apelido do jogador que entrou no jogo e lê seu conteúdo.Agora você precisa coletar o comando para o servidor e enviá-lo para lá. Ele será coletado de um arquivo. Sabemos o apelido do jogador, o nome do item e seu ID foram registrados, quantas peças também foram registradas, resta apenas enviar um comando ao servidor do jogo. Para isso, usaremos o mcrcon .
$JsonPath = Join-Path $MinecraftPath\payments\Pending -ChildPath $Player*
$i = $JsonPath | Get-Item | Where-Object { !$_.PSIsContainer } | Get-Content | ConvertFrom-Json -ErrorVariable Errored
if ($null -ne $i) {
$Command = '"' + "give " + $i.Player + " " + $i.Item + " " + $i.Quantity + '"'
Write-host $Command -ForegroundColor Green
Start-Process -FilePath mcrcon.exe -ArgumentList "-H localhost -p 123 -w 5 $Command"
$JsonPath = Join-Path $MinecraftPath\payments\Pending -ChildPath $FileName
$i | ConvertTo-Json | Out-File $JsonPath
Move-Item -Path $JsonPath -Destination $MinecraftPath\payments\Completed
}
Fazemos tudo isso em um módulo conveniente
O processo Java e o processo WebListener requerem encadeamentos diferentes, mas o autor não está satisfeito com a necessidade de executar o WebListener separadamente e o servidor separadamente. O autor quer tudo de uma vez com uma equipe.Portanto, usando o Powershell 7, lançaremos isso e aquilo. E isso nos ajudará:ForEach-Object -Parallel {}
O cmdlet trabalha com inputObject, portanto, alimentamos uma matriz descomplicada e compartilhamos os fluxos usando uma opção."A", "B" | ForEach-Object -Parallel {
Import-Module ".\Start-Minecraft.ps1"
Import-Module ".\Start-WebListener.ps1"
switch ($_) {
"A" {
Start-WebListener -Path "C:\mc\"
}
"B" {
Start-Minecraft -Type Vanilla -LogFile ".\stdout.txt" -MinecraftPath "C:\mc\"
}
}
}
Então, de uma maneira muleta, iniciamos dois processos diferentes em um terminal e nem perdemos informações. Mas havia outro problema. O WebListener bloqueia o console após um desligamento regular do servidor e não deseja ir a lugar algum.Para não reiniciar o terminal toda vez, uma chave aleatória foi adicionada ao Start-MinecraftHandler.ps1 e ao Start-WebListener.ps1, que interromperá o servidor via POST no WebListener.Start-MinecraftHandler.ps1, quando registra uma conclusão bem-sucedida, executa o comando:Invoke-WebRequest -Method Post -Uri localhost -Body $StopToken | Out-Null
$ StopToken contém um valor numérico aleatório que é pré-passado pelo script de inicialização para o Listener e o Handler. O Ouvinte examina o que recebeu na solicitação e desativa se o corpo da solicitação corresponder a $ StopToken.if ($DecodedContent -eq $StopToken) {
Write-Host "Stopping WebListener"
$context.Response.Headers.Add("Content-Type", "text/plain")
$context.Response.StatusCode = 200
$ResponseBuffer = [System.Text.Encoding]::UTF8.GetBytes("")
$context.Response.ContentLength64 = $ResponseBuffer.Length
$context.Response.OutputStream.Write($ResponseBuffer, 0, $ResponseBuffer.Length)
$context.Response.Close()
$http.Close()
break
}
É seguro o suficiente, apenas a RAM conhece o token e mais ninguém. Todos os módulos são iniciados no PowerShell 7 e o caminho para os módulos do PowerShell 7 é diferente do caminho no Windows Powershell. Tudo estava empilhado aqui. Lembre-se de escrever o seu próprio.C:\Program Files\PowerShell\7\Modules
Nós fazemos um arquivo de configuração
Para que toda essa desgraça possa ser usada sem uma forte dor de cabeça, você precisa criar um arquivo de configuração normal. O arquivo conterá variáveis e nada mais. A configuração se apega usando o padrão:Import-Module $MinecraftPath\config.ps1 -Force
Precisamos apontar a coisa mais importante. O domínio que está sendo tocado é o comum que procura o apelido do jogador, pois a saída pode variar de versão para versão e a senha é da rcon.Se parece com isso:
$DomainName = "localhost"
$RegExp = "of player ([^ ]+)"
$RegExpCut = "of player "
$rconPassword = "123"
É desejável colocar a configuração na pasta do servidor, porque o script a está procurando no caminho-MinecraftPath raizComo usar tudo isso?
Antes de tudo, esses scripts estão instalados e prontos para uso no mercado Ruvds , mas se você ainda não possui um cliente ou ainda não experimentou a imagem, aqui está um link para todos os arquivos no repositório , não hesite em confirmar. - Baixe e instale o PowerShell 7
- Baixe e descompacte o arquivo de módulos
Agora todos os módulos e comandos necessários apareceram. O que eles estão fazendo?Iniciar minecraft
Opções:-TipoForge ou Baunilha. Ele inicia o servidor no Server.Jar ou Forge, escolhendo a versão mais recente que está na pasta.-MinecraftPathAponta para a pasta na qual o servidor será iniciado.-LogFileUma maneira alternativa de coletar logs. Indica um arquivo no qual tudo que aparece no console será gravado.-StartPaymentListenerJuntamente com o servidor, ele inicia e aceita pagamentos. A própria aceitação de pagamento está disponível como um módulo separado. Substitui o cmdlet Start-WeblistenerStart-weblistener
Inicia o módulo de aceitação de pagamento.-MinecraftPathAponta para a pasta com o arquivo de configuração.-StopTokenEspecifica a solicitação -Body HTTP POST para parar o WebListener'a.Conclusão:
Bem, milagres acontecem.