Datamark.by.png
Работает на Powershell 5 начиная с Win7SP1/Win8.1/Win2012.
Команды:
- Get-DatamarkBYOrders - сбор метрик по заказам
- Get-DatamarkBYShips - сбор метрик по отгрузкам
- Get-DatamarkBYMetrics - сбор всех метрик
Параметры:
- username - имя пользователя
- password - пароль
- hash - имя файла, содержащего зашифрованные имя пользователя и пароль
- days_from - начало даты запроса метрик в днях от текущей даты
- days_to - конец даты запроса метрик в днях от текущей даты
- uri - адрес API
При перовом запуске команд с параметрами username и password будет создаваться два файла, имена которых являются хэши данных аутентификации и токена. Расположение файлов зависит от имени пользователя, под которым запускается служба сборщика метрик Telegraf (для пользователя "Локальная система" это каталог "Windows\System32"). Для того, чтобы не хранить данные аутентификации (логин и пароль) в конфигурационном файле сборщика метрик Telegraf, необходимо в качестве параметра hash указать имя файла (один из двух файлов с наименьшим размером).
Telegraf config:
[global_tags]
[agent]
interval = "10s"
round_interval = true
metric_buffer_limit = 5000
flush_buffer_when_full = true
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
debug = false
quiet = false
logfile = "/Program Files/Telegraf/telegraf.log"
hostname = ""
[[outputs.influxdb]]
urls = ["http://docker:8086"] # required
database = "telegraf" # required
precision = "s"
timeout = "5s"
username = "username"
password = "password"
[outputs.influxdb.tagdrop]
influxdb_tag = ["*"]
[[outputs.influxdb]]
urls = ["http://docker:8086"]
database = "datamarkby"
precision = "s"
timeout = "5s"
username = "username"
password = "password"
[outputs.influxdb.tagpass]
influxdb_tag = ["datamarkby"]
[[inputs.exec]]
interval = "1h"
commands = [
"powershell Get-DatamarkBYOrders -hash 'hash'",
"powershell Get-DatamarkBYShips -hash 'hash' -days_from 30"
]
timeout = "5m"
name_suffix = ""
data_format = "influx"
[inputs.exec.tags]
influxdb_tag = "datamarkby"
Collector Configuration Details
Windows\System32\WindowsPowerShell\v1.0\Modules\Influxdata.Telegraf.DatamarkBY\Influxdata.Telegraf.DatamarkBY.psm1
[console]::OutputEncoding = [System.Text.Encoding]::UTF8
function isEmpty($value) {
if ([string]::isnullorempty($value)) { return "0" } # Empty string or Null
else { return $value -Replace " ", "\ " -Replace ",", "." }
}
function Get-SecureFromString {
param (
[parameter(Mandatory = $true, ValueFromPipeline=$true)][string]$string
)
return $string | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
}
function Get-StringFromSecure {
[CmdletBinding()]
param (
[parameter(Mandatory = $true, ValueFromPipeline=$true)][string]$secure
)
try {
$string = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR(($secure | ConvertTo-SecureString -EA 0)))
}
catch {
Write-Debug $_.Exception.Message
return $null
}
return $string
}
function Get-SecureFromAuth { # Convert username/password to hash
param (
[parameter(Mandatory = $true)][string]$username,
[parameter(Mandatory = $true)][string]$password
)
return ($username + [char]29 + $password) | Get-SecureFromString
}
function Get-AuthFromSecure { # Convert hash to username/password
[CmdletBinding()]
param (
[parameter(Mandatory = $true, ValueFromPipeline=$true)][string]$hash
)
if ($auth = $hash | Get-StringFromSecure) {
$auth = $auth.Split([char]29)
if ($auth.count -eq 2) { return @{username = $auth[0]; password = $auth[1]} }
}
Write-Debug "Get-AuthFromSecure: auth not found"
return $null
}
function Get-HashFromString {
[CmdletBinding()]
param (
[parameter(Mandatory = $true, ValueFromPipeline=$true)][string]$string,
[string]$algorithm = 'MD5'
)
try {
$ms = [System.IO.MemoryStream]::new()
$sw = [System.IO.StreamWriter]::new($ms)
$sw.Write($string)
$sw.Flush()
$ms.Position = 0
$hash = (Get-FileHash -InputStream $ms -Algorithm $algorithm).Hash
}
catch {
Write-Debug $_.Exception.Message
return $null
}
return $hash
}
function Get-DatamarkBYToken {
[CmdletBinding()]
param (
[AllowNull()][AllowEmptyString()][string]$username,
[AllowNull()][AllowEmptyString()][string]$password,
[AllowNull()][AllowEmptyString()][string]$hash,
[string]$uri = 'https://api.datamark.by'
)
function Check-DatamarkBYToken {
[CmdletBinding()]
param (
[parameter(Mandatory = $true)][string]$username,
[parameter(Mandatory = $true)][string]$password,
[AllowNull()][AllowEmptyString()][string]$token,
[string]$uri = 'https://api.datamark.by'
)
if ($token) {
$response = Get-DatamarkBYRequestResponse -request '/directories' -method 'Post' -token $token -uri $uri
}
if ($response -eq $null) {
try {
$response = Invoke-RestMethod -Method 'Post' -Uri ($uri + '/auth') -Body @{username = $username; password = $password}
}
catch {
Write-Debug $_.Exception.Message
return $null
}
return $response.token # return new token
}
return $token # return old token
}
if ($hash -and (Test-Path $hash)) {
if ($auth = Get-Content $hash | Get-AuthFromSecure) { $username = $auth.username; $password = $auth.password }
}
if (!$username -or !$password) {
Write-Debug "Get-DatamarkBYToken: hash not found"
return $null
}
# Get MD5 hash from username
$username_hash = $username | Get-HashFromString
if (Test-Path $username_hash) { # Get token from file by MD5 hash
$token = Get-Content $username_hash | Get-StringFromSecure
}
$token_check = Check-DatamarkBYToken -username $username -password $password -token $token -uri $uri
if ($token -ne $token_check -and $token_check) { # Get a new token and save it
$token_check | Get-SecureFromString | Set-Content $username_hash
Get-SecureFromAuth -username $username -password $password | Set-Content ( ($username + [char]29 + $password) | Get-HashFromString)
}
return $token_check
}
function Get-DatamarkBYRequestResponse {
[CmdletBinding()]
param (
[parameter(Mandatory = $true)][string]$request,
[parameter(Mandatory = $true)][string]$method,
[parameter(Mandatory = $true)][string]$token,
[string]$body = '{}',
[string]$uri = 'https://api.datamark.by'
)
Write-Debug ($method + ' ' + $uri + $request)
try {
if ($body -eq '{}') { # For Get method
$response = Invoke-RestMethod -Method $method -Uri ($uri + $request) -Headers @{token = $token}
}
else {
$response = Invoke-RestMethod -Method $method -Uri ($uri + $request) -Headers @{token = $token} -Body $body
}
}
catch {
Write-Debug "$_.Exception.Response.StatusCode.value__: $_.Exception.Response.StatusDescription"
return $null
}
return $response
}
function Build-DatamarkBYRequestBody {
param (
[parameter(Mandatory = $true)][string]$date_from,
[parameter(Mandatory = $true)][string]$date_to,
[byte]$label_type = 0,
[byte]$page = 1
)
if ($label_type -eq 0) { # ships body
$body = "{
`"date_from`": `"$date_from`",
`"date_to`": `"$date_to`",
`"page`": $page
}"
}
else { # orders body
$body = "{
`"date_from`": `"$date_from`",
`"date_to`": `"$date_to`",
`"date_type`": `"created`",
`"label_type`": $label_type,
`"page`": $page
}"
}
return $body
}
function Get-DatamarkBYOrders {
param (
[string]$username,
[string]$password,
[string]$hash,
[byte]$days_from = 0,
[byte]$days_to = 0,
[string]$uri = 'https://api.datamark.by'
)
if ($days_to -gt $days_from) { return }
else {
$date_from = (Get-Date (Get-Date).AddDays(-$days_from) -Format 'yyyy-MM-dd').ToString()
$date_to = (Get-Date (Get-Date).AddDays(-$days_to) -Format 'yyyy-MM-dd').ToString()
}
if (!($token = Get-DatamarkBYToken -username $username -password $password -hash $hash)) { return }
$base = "datamarkby_orders"
$tags = "label_type={0}"
$values = "id={1}i,count={2}i,status={3}i {4}000000000"
$output = $base + "," + $tags + " " + $values
5..7 | % { # 5 - Серийный номер; 6 - Код агрегации (SSCC); 7 - Код стран ЕАЭС идентификации товара
$label_type = $_
if ($label_type -eq 7) {
$tags = "label_type={0},gtin={1}"
$values = "id={2}i,count={3}i,status={4}i {5}000000000"
$output = $base + "," + $tags + " " + $values
}
$body = Build-DatamarkBYRequestBody -date_from $date_from -date_to $date_to -label_type $label_type
$request = '/orders/list'
$method = 'Post'
$response = Get-DatamarkBYRequestResponse -request $request -method $method -token $token -body $body -uri $uri
if ($response -and $response.count -gt 0) {
$pages = [math]::Ceiling($response.count / $response.orders_list.count)
1..$pages | % {
$response.orders_list | % {
if ($label_type -eq 7) {
$output -f (isEmpty($_.type.id)), (isEmpty($_.gtin)), (isEmpty($_.id)), (isEmpty($_.count)), (isEmpty($_.status.code)), `
(Get-Date -Date ([datetime]::parseexact($_.created_at.SubString(0, 19), 'yyyy-MM-dd HH:mm:ss', $null)) -UFormat %s)
}
else {
$output -f (isEmpty($_.type.id)), (isEmpty($_.id)), (isEmpty($_.count)), (isEmpty($_.status.code)), `
(Get-Date -Date ([datetime]::parseexact($_.created_at.SubString(0, 19), 'yyyy-MM-dd HH:mm:ss', $null)) -UFormat %s)
}
}
if ($_ -ne $pages) {
$body = Build-DatamarkBYRequestBody -date_from $date_from -date_to $date_to -label_type $label_type -page ($_ + 1)
$response = Get-DatamarkBYRequestResponse -request $request -method $method -token $token -body $body -uri $uri
}
}
}
}
}
function Get-DatamarkBYShips {
param (
[string]$username,
[string]$password,
[string]$hash,
[byte]$days_from = 0,
[byte]$days_to = 0,
[string]$uri = 'https://api.datamark.by'
)
if ($days_to -gt $days_from) { return }
else {
$date_from = (Get-Date (Get-Date).AddDays(-$days_from) -Format 'yyyy-MM-dd').ToString()
$date_to = (Get-Date (Get-Date).AddDays(-$days_to) -Format 'yyyy-MM-dd').ToString()
}
if (!($token = Get-DatamarkBYToken -username $username -password $password -hash $hash)) { return }
$base = "datamarkby_ships"
$body = Build-DatamarkBYRequestBody -date_from $date_from -date_to $date_to
$request = '/ships/shipped'
$method = 'Post'
$response = Get-DatamarkBYRequestResponse -request $request -method $method -token $token -body $body -uri $uri
if ($response -and $response.count -gt 0) {
$pages = [math]::Ceiling($response.count / $response.ships_list.count)
1..$pages | % {
$response.ships_list | % {
$tags = "currency={0},user_to_name={1},user_to_unp={2},user_to_country={3},country={4}"
$values = "id={5}i,real_count={6}i,received_count={7}i,status={8}i,price={9},doc_name=`"{10}`",contract_id={11}i {12}000000000"
$output = $base + "," + $tags + " " + $values
$output -f (isEmpty($_.price.currency)), (isEmpty($_.user_to.name)), (isEmpty($_.user_to.unp)), (isEmpty($_.user_to.country)), (isEmpty($_.country.id)), `
(isEmpty($_.code)), (isEmpty($_.real_count)), (isEmpty($_.received_count)), (isEmpty($_.status.code)), (isEmpty($_.price.price)), (isEmpty($_.name)), (isEmpty($_.contract.id)), `
(Get-Date -Date ([datetime]::parseexact($_.created_at.SubString(0, 19), 'yyyy-MM-dd HH:mm:ss', $null)) -UFormat %s)
$ships = Get-DatamarkBYRequestResponse -request ('/ships/' + $_.code) -method 'Get' -token $token -uri $uri
if ($ships) {
$tags = "currency={0},user_to_name={1},user_to_unp={2},user_to_country={3},country={4},gtin={5},name={6},articul={7}"
$values = "id={8}i,count={9}i,status={10}i,price={11},doc_name=`"{12}`",contract_id={13}i {14}000000000"
$output = $base + "," + $tags + " " + $values
foreach ($item in $ships.items) {
$output -f (isEmpty($_.price.currency)), (isEmpty($_.user_to.name)), (isEmpty($_.user_to.unp)), (isEmpty($_.user_to.country)), (isEmpty($_.country.id)), (isEmpty($item.gtin)), (isEmpty($item.name)), (isEmpty($item.articul)), `
(isEmpty($_.code)), (isEmpty($item.count)), (isEmpty($_.status.code)), (isEmpty($_.price.price)), (isEmpty($_.name)), (isEmpty($_.contract.id)), `
(Get-Date -Date ([datetime]::parseexact($_.created_at.SubString(0, 19), 'yyyy-MM-dd HH:mm:ss', $null)) -UFormat %s)
}
}
}
if ($_ -ne $pages) {
$body = Build-DatamarkBYRequestBody -date_from $date_from -date_to $date_to -page ($_ + 1)
$response = Get-DatamarkBYRequestResponse -request $request -method $method -token $token -body $body -uri $uri
}
}
}
}
function Get-DatamarkBYMetrics {
param (
[string]$username,
[string]$password,
[string]$hash,
[byte]$days_from = 0,
[byte]$days_to = 0,
[string]$uri = 'https://api.datamark.by'
)
Get-DatamarkBYOrders -username $username -password $password -hash $hash -days_from $days_from -days_to $date_to -uri $uri
Get-DatamarkBYShips -username $username -password $password -hash $hash -days_from $days_from -days_to $date_to -uri $uri
}