<commit_before><?php
/**
 * WooCommerce Svea Payments Gateway
 *
 * @package WooCommerce Svea Payments Gateway
 */

/**
 * Svea Payments Gateway Plugin for WooCommerce 3.x, 4.x
 * Plugin developed for Svea
 * Last update: 30/11/2020
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * [GNU LGPL v. 2.1 @gnu.org] (https://www.gnu.org/licenses/lgpl-2.1.html)
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

require_once 'class-wc-data-hasher.php';

/**
 * Class WC_Gateway_Abstract_Maksuturva.
 *
 * Abstract for the Svea payments gateway. Handles basic functionality against the Svea Payments Gateway.
 *
 * @since 2.0.0
 *
 * @property int $pmt_orderid The Svea order id.
 * @property int $pmt_id      The Svea payment id.
 */
abstract class WC_Gateway_Abstract_Maksuturva {

	/**
	 * Status query not found.
	 *
	 * @var string STATUS_QUERY_NOT_FOUND
	 */
	const STATUS_QUERY_NOT_FOUND = '00';

	/**
	 * Status query failed.
	 *
	 * @var string STATUS_QUERY_FAILED
	 */
	const STATUS_QUERY_FAILED = '01';

	/**
	 * Status query waiting.
	 *
	 * @var string STATUS_QUERY_WAITING
	 */
	const STATUS_QUERY_WAITING = '10';

	/**
	 * Status query unpaid.
	 *
	 * @var string STATUS_QUERY_UNPAID
	 */
	const STATUS_QUERY_UNPAID = '11';

	/**
	 * Status query unpaid delivery.
	 *
	 * @var string STATUS_QUERY_UNPAID_DELIVERY
	 */
	const STATUS_QUERY_UNPAID_DELIVERY = '15';

	/**
	 * Status query paid.
	 *
	 * @var string STATUS_QUERY_PAID
	 */
	const STATUS_QUERY_PAID = '20';

	/**
	 * Status query paid delivery.
	 *
	 * @var string STATUS_QUERY_PAID_DELIVERY
	 */
	const STATUS_QUERY_PAID_DELIVERY = '30';

	/**
	 * Status query compensated.
	 *
	 * @var string STATUS_QUERY_COMPENSATED
	 */
	const STATUS_QUERY_COMPENSATED = '40';

	/**
	 * Status query payer cancelled.
	 *
	 * @var string STATUS_QUERY_PAYER_CANCELLED
	 */
	const STATUS_QUERY_PAYER_CANCELLED = '91';

	/**
	 * Status query payer cancelled partial.
	 *
	 * @var string STATUS_QUERY_PAYER_CANCELLED_PARTIAL
	 */
	const STATUS_QUERY_PAYER_CANCELLED_PARTIAL = '92';

	/**
	 * Status query payer cancelled partial return.
	 *
	 * @var string STATUS_QUERY_PAYER_CANCELLED_PARTIAL_RETURN
	 */
	const STATUS_QUERY_PAYER_CANCELLED_PARTIAL_RETURN = '93';

	/**
	 * Status query payer reclamation.
	 *
	 * @var string STATUS_QUERY_PAYER_RECLAMATION
	 */
	const STATUS_QUERY_PAYER_RECLAMATION = '95';

	/**
	 * Status query cancelled.
	 *
	 * @var string STATUS_QUERY_CANCELLED
	 */
	const STATUS_QUERY_CANCELLED = '99';

	/**
	 * Code algorithm not supported.
	 *
	 * @var string EXCEPTION_CODE_ALGORITHMS_NOT_SUPPORTED
	 */
	const EXCEPTION_CODE_ALGORITHMS_NOT_SUPPORTED = '00';

	/**
	 * URL generation errors.
	 *
	 * @var string EXCEPTION_CODE_URL_GENERATION_ERRORS
	 */
	const EXCEPTION_CODE_URL_GENERATION_ERRORS = '01';

	/**
	 * Field array generation errors.
	 *
	 * @var string EXCEPTION_CODE_FIELD_ARRAY_GENERATION_ERRORS
	 */
	const EXCEPTION_CODE_FIELD_ARRAY_GENERATION_ERRORS = '02';

	/**
	 * Reference number below 100.
	 *
	 * @var string EXCEPTION_CODE_REFERENCE_NUMBER_UNDER_100
	 */
	const EXCEPTION_CODE_REFERENCE_NUMBER_UNDER_100 = '03';

	/**
	 * Field missing.
	 *
	 * @var string EXCEPTION_CODE_FIELD_MISSING
	 */
	const EXCEPTION_CODE_FIELD_MISSING = '04';

	/**
	 * Invalid item.
	 *
	 * @var string EXCEPTION_CODE_INVALID_ITEM
	 */
	const EXCEPTION_CODE_INVALID_ITEM = '05';

	/**
	 * Curl not installed.
	 *
	 * @var string EXCEPTION_CODE_PHP_CURL_NOT_INSTALLED
	 */
	const EXCEPTION_CODE_PHP_CURL_NOT_INSTALLED = '06';

	/**
	 * Hash don't match.
	 *
	 * @var string EXCEPTION_CODE_HASHES_DONT_MATCH
	 */
	const EXCEPTION_CODE_HASHES_DONT_MATCH = '07';

	/**
	 * Order vs status query response data mismatch
	 *
	 * @var string EXCEPTION_CODE_DATA_MISMATCH
	 */
	const EXCEPTION_CODE_DATA_MISMATCH = '08';

	/**
	 * Route to payment.
	 *
	 * @var string ROUTE_PAYMENT
	 */
	const ROUTE_PAYMENT = '/NewPaymentExtended.pmt';

	/**
	 * Route to status query.
	 *
	 * @var string ROUTE_STATUS_QUERY
	 */
	const ROUTE_STATUS_QUERY = '/PaymentStatusQuery.pmt';

	/**
	 * Base URL.
	 *
	 * @since 2.0.0
	 *
	 * @var string $base_url Gateway URL for making new payments.
	 */
	protected $base_url = 'https://www.maksuturva.fi/NewPaymentExtended.pmt';

	/**
	 * Status query URL.
	 *
	 * @since 2.0.0
	 *
	 * @var string $base_url_status_query Gateway URL for checking payment statuses.
	 */
	protected $base_url_status_query = 'https://www.maksuturva.fi/PaymentStatusQuery.pmt';

	/**
	 * The WC_Payment_Gateway extension.
	 *
	 * @since 2.1.3
	 * 
	 * @var WC_Gateway_Maksuturva $wc_gateway The WC_Payment_Gateway extension.
	 */
	public $wc_gateway;

	/**
	 * Seller ID.
	 *
	 * @since 2.0.0
	 *
	 * @var string $seller_id Seller ID to use for identification when calling the gateway.
	 */
	protected $seller_id;

	/**
	 * Charset.
	 *
	 * @since 2.0.0
	 *
	 * @var string $charset Charset for the payment data.
	 */
	protected $charset = 'UTF-8';

	/**
	 * HTTP charset.
	 *
	 * @since 2.0.0
	 *
	 * @var string $charset_http Charset for the payment http data.
	 */
	protected $charset_http = 'UTF-8';

	/**
	 * Payment ID prefix.
	 *
	 * @since 2.0.0
	 *
	 * @var string $pmt_id_prefix Prefix used for the `pmt_id` field.
	 */
	protected $pmt_id_prefix;

	/**
	 * Hash algorithm.
	 *
	 * @since 2.0.0
	 *
	 * @var string Algorithm used for hashing (sha512, sha256, sha1 or md5).
	 */
	protected $hash_algorithm;

	/**
	 * Payment data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $payment_data The payment data.
	 */
	protected $payment_data = array(
		'pmt_action'              => 'NEW_PAYMENT_EXTENDED',
		'pmt_version'             => '0004',
		'pmt_escrow'              => 'Y',
		'pmt_keygeneration'       => '001',
		'pmt_currency'            => 'EUR',
		'pmt_escrowchangeallowed' => 'N',
		'pmt_charset'             => 'UTF-8',
		'pmt_charsethttp'         => 'UTF-8',
	);

	/**
	 * Status query data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $status_query_data Payment query status data.
	 */
	protected $status_query_data = array();

	/**
	 * Mandatory data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $mandatory_data Mandatory properties in the payment data.
	 */
	private static $mandatory_data = array(
		'pmt_action',               // Alphanumeric  max-length: 50   min-length: 4   NEW_PAYMENT_EXTENDED.
		'pmt_version',              // Alphanumeric  max-length: 4    min-length: 4   0004.
		'pmt_sellerid',             // Alphanumeric  max-length: 15   -.
		'pmt_id',                   // Alphanumeric  max-length: 20   -.
		'pmt_orderid',              // Alphanumeric  max-length: 50   -.
		'pmt_reference',            // Numeric       max-length: 20   min-length: 4   Reference number + check digit.
		'pmt_duedate',              // Alphanumeric  max-length: 10   min-length: 10  dd.MM.yyyy.
		'pmt_amount',               // Alphanumeric  max-length: 17   min-length: 4.
		'pmt_currency',             // Alphanumeric  max-length: 3    min-length: 3   EUR.
		'pmt_okreturn',             // Alphanumeric  max-length: 200  -.
		'pmt_errorreturn',          // Alphanumeric  max-length: 200  -.
		'pmt_cancelreturn',         // Alphanumeric  max-length: 200  -.
		'pmt_delayedpayreturn',     // Alphanumeric  max-length: 200  -.
		'pmt_escrow',               // Alpha         max-length: 1    min-length: 1   Y/N.
		'pmt_escrowchangeallowed',  // Alpha         max-length: 1    min-length: 1   N.
		'pmt_buyername',            // Alphanumeric  max-length: 40   -.
		'pmt_buyeraddress',         // Alphanumeric  max-length: 40   -.
		'pmt_buyerpostalcode',      // Numeric       max-length: 5    -.
		'pmt_buyercity',            // Alphanumeric  max-length: 40   -.
		'pmt_buyercountry',         // Alpha         max-length: 2    -               Respecting the ISO 3166.
		'pmt_deliveryname',         // Alphanumeric  max-length: 40   -.
		'pmt_deliveryaddress',      // Alphanumeric  max-length: 40   -.
		'pmt_deliverypostalcode',   // Numeric       max-length: 5    -.
		'pmt_deliverycountry',      // Alpha         max-length: 2    -               Respecting the ISO 3166.
		'pmt_sellercosts',          // Alphanumeric  max-length: 17   min-length: 4   n,nn.
		'pmt_rows',                 // Numeric       max-length: 4    min-length: 1.
		'pmt_charset',              // Alphanumeric  max-length: 15   -               {ISO-8859-1, ISO-8859-15, UTF-8}.
		'pmt_charsethttp',          // Alphanumeric  max-length: 15   -               {ISO-8859-1, ISO-8859-15, UTF-8}.
		'pmt_hashversion',          // Alphanumeric  max-length: 10   -               {SHA-512, SHA-256, SHA-1, MD5}.
		'pmt_keygeneration',        // N umeric       max-length: 3    -..
	);

	/**
	 * Optional data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $optional_data Optional properties in the payment data.
	 */
	private static $optional_data = array(
		'pmt_selleriban',
		'pmt_userlocale',
		'pmt_invoicefromseller',
		'pmt_paymentmethod',
		'pmt_buyeridentificationcode',
		'pmt_buyerphone',
		'pmt_buyeremail',
	);

	/**
	 * Mandatory row data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $row_mandatory_data Mandatory properties for the payment data rows.
	 */
	private static $row_mandatory_data = array(
		'pmt_row_name',                  // Alphanumeric  max-length: 40    -.
		'pmt_row_desc',                  // Alphanumeric  max-length: 1000  min-length: 1.
		'pmt_row_quantity',              // Numeric       max-length: 10     min-length: 1.
		'pmt_row_deliverydate',          // Alphanumeric  max-length: 10    min-length: 10  dd.MM.yyyy.
		'pmt_row_price_gross',           // Alphanumeric  max-length: 17    min-length: 4   n,nn.
		'pmt_row_price_net',             // Alphanumeric  max-length: 17    min-length: 4   n,nn.
		'pmt_row_vat',                   // Alphanumeric  max-length: 5     min-length: 4   n,nn.
		'pmt_row_discountpercentage',    // Alphanumeric  max-length: 5     min-length: 4   n,nn.
		'pmt_row_type',                  // Numeric       max-length: 5     min-length: 1.
	);

	/**
	 * Optional row data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $row_optional_data Optional properties for the payment data rows.
	 */
	private static $row_optional_data = array(
		'pmt_row_articlenr',
		'pmt_row_unit',
	);

	/**
	 * Hash data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $hash_data Properties used for hashing.
	 */
	private static $hash_data = array(
		'pmt_action',
		'pmt_version',
		'pmt_selleriban',
		'pmt_id',
		'pmt_orderid',
		'pmt_reference',
		'pmt_duedate',
		'pmt_amount',
		'pmt_currency',
		'pmt_okreturn',
		'pmt_errorreturn',
		'pmt_cancelreturn',
		'pmt_delayedpayreturn',
		'pmt_escrow',
		'pmt_escrowchangeallowed',
		'pmt_invoicefromseller',
		'pmt_paymentmethod',
		'pmt_buyeridentificationcode',
		'pmt_buyername',
		'pmt_buyeraddress',
		'pmt_buyerpostalcode',
		'pmt_buyercity',
		'pmt_buyercountry',
		'pmt_deliveryname',
		'pmt_deliveryaddress',
		'pmt_deliverypostalcode',
		'pmt_deliverycity',
		'pmt_deliverycountry',
		'pmt_sellercosts',
	);

	/**
	 * Field filters.
	 *
	 * @since 2.0.0
	 *
	 * @var array $field_filters Field filters (min, max).
	 */
	private static $field_filters = array(
		'pmt_action'                  => array( 4, 50 ),
		'pmt_version'                 => array( 4, 4 ),
		'pmt_sellerid'                => array( 1, 15 ),
		'pmt_selleriban'              => array( 18, 30 ), // Optional.
		'pmt_id'                      => array( 1, 20 ),
		'pmt_orderid'                 => array( 1, 50 ),
		'pmt_reference'               => array( 3, 20 ), // > 100.
		'pmt_duedate'                 => array( 10, 10 ),
		'pmt_userlocale'              => array( 5, 5 ), // Optional.
		'pmt_amount'                  => array( 4, 17 ),
		'pmt_currency'                => array( 3, 3 ),
		'pmt_okreturn'                => array( 1, 200 ),
		'pmt_errorreturn'             => array( 1, 200 ),
		'pmt_cancelreturn'            => array( 1, 200 ),
		'pmt_delayedpayreturn'        => array( 1, 200 ),
		'pmt_escrow'                  => array( 1, 1 ),
		'pmt_escrowchangeallowed'     => array( 1, 1 ),
		'pmt_invoicefromseller'       => array( 1, 1 ), // Optional.
		'pmt_paymentmethod'           => array( 4, 4 ), // Optional.
		'pmt_buyeridentificationcode' => array( 9, 11 ), // Optional.
		'pmt_buyername'               => array( 1, 40 ),
		'pmt_buyeraddress'            => array( 1, 40 ),
		'pmt_buyerpostalcode'         => array( 1, 5 ),
		'pmt_buyercity'               => array( 1, 40 ),
		'pmt_buyercountry'            => array( 1, 2 ),
		'pmt_buyerphone'              => array( 0, 40 ), // Optional.
		'pmt_buyeremail'              => array( 0, 40 ), // Optional.
		'pmt_deliveryname'            => array( 1, 40 ),
		'pmt_deliveryaddress'         => array( 1, 40 ),
		'pmt_deliverypostalcode'      => array( 1, 5 ),
		'pmt_deliverycity'            => array( 1, 40 ),
		'pmt_deliverycountry'         => array( 1, 2 ),
		'pmt_sellercosts'             => array( 4, 17 ),
		'pmt_rows'                    => array( 1, 4 ),
		'pmt_row_name'                => array( 1, 40 ),
		'pmt_row_desc'                => array( 1, 1000 ),
		'pmt_row_quantity'            => array( 1, 10 ),
		'pmt_row_deliverydate'        => array( 10, 10 ),
		'pmt_row_price_gross'         => array( 4, 17 ),
		'pmt_row_price_net'           => array( 4, 17 ),
		'pmt_row_vat'                 => array( 4, 5 ),
		'pmt_row_discountpercentage'  => array( 4, 5 ),
		'pmt_row_type'                => array( 1, 5 ),
		'pmt_charset'                 => array( 1, 15 ),
		'pmt_charsethttp'             => array( 1, 15 ),
		'pmt_hashversion'             => array( 1, 10 ),<commit_msg>Buyer email max length from 40 to 320<commit_after><?php
/**
 * WooCommerce Svea Payments Gateway
 *
 * @package WooCommerce Svea Payments Gateway
 */

/**
 * Svea Payments Gateway Plugin for WooCommerce 3.x, 4.x
 * Plugin developed for Svea
 * Last update: 30/11/2020
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * [GNU LGPL v. 2.1 @gnu.org] (https://www.gnu.org/licenses/lgpl-2.1.html)
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

require_once 'class-wc-data-hasher.php';

/**
 * Class WC_Gateway_Abstract_Maksuturva.
 *
 * Abstract for the Svea payments gateway. Handles basic functionality against the Svea Payments Gateway.
 *
 * @since 2.0.0
 *
 * @property int $pmt_orderid The Svea order id.
 * @property int $pmt_id      The Svea payment id.
 */
abstract class WC_Gateway_Abstract_Maksuturva {

	/**
	 * Status query not found.
	 *
	 * @var string STATUS_QUERY_NOT_FOUND
	 */
	const STATUS_QUERY_NOT_FOUND = '00';

	/**
	 * Status query failed.
	 *
	 * @var string STATUS_QUERY_FAILED
	 */
	const STATUS_QUERY_FAILED = '01';

	/**
	 * Status query waiting.
	 *
	 * @var string STATUS_QUERY_WAITING
	 */
	const STATUS_QUERY_WAITING = '10';

	/**
	 * Status query unpaid.
	 *
	 * @var string STATUS_QUERY_UNPAID
	 */
	const STATUS_QUERY_UNPAID = '11';

	/**
	 * Status query unpaid delivery.
	 *
	 * @var string STATUS_QUERY_UNPAID_DELIVERY
	 */
	const STATUS_QUERY_UNPAID_DELIVERY = '15';

	/**
	 * Status query paid.
	 *
	 * @var string STATUS_QUERY_PAID
	 */
	const STATUS_QUERY_PAID = '20';

	/**
	 * Status query paid delivery.
	 *
	 * @var string STATUS_QUERY_PAID_DELIVERY
	 */
	const STATUS_QUERY_PAID_DELIVERY = '30';

	/**
	 * Status query compensated.
	 *
	 * @var string STATUS_QUERY_COMPENSATED
	 */
	const STATUS_QUERY_COMPENSATED = '40';

	/**
	 * Status query payer cancelled.
	 *
	 * @var string STATUS_QUERY_PAYER_CANCELLED
	 */
	const STATUS_QUERY_PAYER_CANCELLED = '91';

	/**
	 * Status query payer cancelled partial.
	 *
	 * @var string STATUS_QUERY_PAYER_CANCELLED_PARTIAL
	 */
	const STATUS_QUERY_PAYER_CANCELLED_PARTIAL = '92';

	/**
	 * Status query payer cancelled partial return.
	 *
	 * @var string STATUS_QUERY_PAYER_CANCELLED_PARTIAL_RETURN
	 */
	const STATUS_QUERY_PAYER_CANCELLED_PARTIAL_RETURN = '93';

	/**
	 * Status query payer reclamation.
	 *
	 * @var string STATUS_QUERY_PAYER_RECLAMATION
	 */
	const STATUS_QUERY_PAYER_RECLAMATION = '95';

	/**
	 * Status query cancelled.
	 *
	 * @var string STATUS_QUERY_CANCELLED
	 */
	const STATUS_QUERY_CANCELLED = '99';

	/**
	 * Code algorithm not supported.
	 *
	 * @var string EXCEPTION_CODE_ALGORITHMS_NOT_SUPPORTED
	 */
	const EXCEPTION_CODE_ALGORITHMS_NOT_SUPPORTED = '00';

	/**
	 * URL generation errors.
	 *
	 * @var string EXCEPTION_CODE_URL_GENERATION_ERRORS
	 */
	const EXCEPTION_CODE_URL_GENERATION_ERRORS = '01';

	/**
	 * Field array generation errors.
	 *
	 * @var string EXCEPTION_CODE_FIELD_ARRAY_GENERATION_ERRORS
	 */
	const EXCEPTION_CODE_FIELD_ARRAY_GENERATION_ERRORS = '02';

	/**
	 * Reference number below 100.
	 *
	 * @var string EXCEPTION_CODE_REFERENCE_NUMBER_UNDER_100
	 */
	const EXCEPTION_CODE_REFERENCE_NUMBER_UNDER_100 = '03';

	/**
	 * Field missing.
	 *
	 * @var string EXCEPTION_CODE_FIELD_MISSING
	 */
	const EXCEPTION_CODE_FIELD_MISSING = '04';

	/**
	 * Invalid item.
	 *
	 * @var string EXCEPTION_CODE_INVALID_ITEM
	 */
	const EXCEPTION_CODE_INVALID_ITEM = '05';

	/**
	 * Curl not installed.
	 *
	 * @var string EXCEPTION_CODE_PHP_CURL_NOT_INSTALLED
	 */
	const EXCEPTION_CODE_PHP_CURL_NOT_INSTALLED = '06';

	/**
	 * Hash don't match.
	 *
	 * @var string EXCEPTION_CODE_HASHES_DONT_MATCH
	 */
	const EXCEPTION_CODE_HASHES_DONT_MATCH = '07';

	/**
	 * Order vs status query response data mismatch
	 *
	 * @var string EXCEPTION_CODE_DATA_MISMATCH
	 */
	const EXCEPTION_CODE_DATA_MISMATCH = '08';

	/**
	 * Route to payment.
	 *
	 * @var string ROUTE_PAYMENT
	 */
	const ROUTE_PAYMENT = '/NewPaymentExtended.pmt';

	/**
	 * Route to status query.
	 *
	 * @var string ROUTE_STATUS_QUERY
	 */
	const ROUTE_STATUS_QUERY = '/PaymentStatusQuery.pmt';

	/**
	 * Base URL.
	 *
	 * @since 2.0.0
	 *
	 * @var string $base_url Gateway URL for making new payments.
	 */
	protected $base_url = 'https://www.maksuturva.fi/NewPaymentExtended.pmt';

	/**
	 * Status query URL.
	 *
	 * @since 2.0.0
	 *
	 * @var string $base_url_status_query Gateway URL for checking payment statuses.
	 */
	protected $base_url_status_query = 'https://www.maksuturva.fi/PaymentStatusQuery.pmt';

	/**
	 * The WC_Payment_Gateway extension.
	 *
	 * @since 2.1.3
	 * 
	 * @var WC_Gateway_Maksuturva $wc_gateway The WC_Payment_Gateway extension.
	 */
	public $wc_gateway;

	/**
	 * Seller ID.
	 *
	 * @since 2.0.0
	 *
	 * @var string $seller_id Seller ID to use for identification when calling the gateway.
	 */
	protected $seller_id;

	/**
	 * Charset.
	 *
	 * @since 2.0.0
	 *
	 * @var string $charset Charset for the payment data.
	 */
	protected $charset = 'UTF-8';

	/**
	 * HTTP charset.
	 *
	 * @since 2.0.0
	 *
	 * @var string $charset_http Charset for the payment http data.
	 */
	protected $charset_http = 'UTF-8';

	/**
	 * Payment ID prefix.
	 *
	 * @since 2.0.0
	 *
	 * @var string $pmt_id_prefix Prefix used for the `pmt_id` field.
	 */
	protected $pmt_id_prefix;

	/**
	 * Hash algorithm.
	 *
	 * @since 2.0.0
	 *
	 * @var string Algorithm used for hashing (sha512, sha256, sha1 or md5).
	 */
	protected $hash_algorithm;

	/**
	 * Payment data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $payment_data The payment data.
	 */
	protected $payment_data = array(
		'pmt_action'              => 'NEW_PAYMENT_EXTENDED',
		'pmt_version'             => '0004',
		'pmt_escrow'              => 'Y',
		'pmt_keygeneration'       => '001',
		'pmt_currency'            => 'EUR',
		'pmt_escrowchangeallowed' => 'N',
		'pmt_charset'             => 'UTF-8',
		'pmt_charsethttp'         => 'UTF-8',
	);

	/**
	 * Status query data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $status_query_data Payment query status data.
	 */
	protected $status_query_data = array();

	/**
	 * Mandatory data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $mandatory_data Mandatory properties in the payment data.
	 */
	private static $mandatory_data = array(
		'pmt_action',               // Alphanumeric  max-length: 50   min-length: 4   NEW_PAYMENT_EXTENDED.
		'pmt_version',              // Alphanumeric  max-length: 4    min-length: 4   0004.
		'pmt_sellerid',             // Alphanumeric  max-length: 15   -.
		'pmt_id',                   // Alphanumeric  max-length: 20   -.
		'pmt_orderid',              // Alphanumeric  max-length: 50   -.
		'pmt_reference',            // Numeric       max-length: 20   min-length: 4   Reference number + check digit.
		'pmt_duedate',              // Alphanumeric  max-length: 10   min-length: 10  dd.MM.yyyy.
		'pmt_amount',               // Alphanumeric  max-length: 17   min-length: 4.
		'pmt_currency',             // Alphanumeric  max-length: 3    min-length: 3   EUR.
		'pmt_okreturn',             // Alphanumeric  max-length: 200  -.
		'pmt_errorreturn',          // Alphanumeric  max-length: 200  -.
		'pmt_cancelreturn',         // Alphanumeric  max-length: 200  -.
		'pmt_delayedpayreturn',     // Alphanumeric  max-length: 200  -.
		'pmt_escrow',               // Alpha         max-length: 1    min-length: 1   Y/N.
		'pmt_escrowchangeallowed',  // Alpha         max-length: 1    min-length: 1   N.
		'pmt_buyername',            // Alphanumeric  max-length: 40   -.
		'pmt_buyeraddress',         // Alphanumeric  max-length: 40   -.
		'pmt_buyerpostalcode',      // Numeric       max-length: 5    -.
		'pmt_buyercity',            // Alphanumeric  max-length: 40   -.
		'pmt_buyercountry',         // Alpha         max-length: 2    -               Respecting the ISO 3166.
		'pmt_deliveryname',         // Alphanumeric  max-length: 40   -.
		'pmt_deliveryaddress',      // Alphanumeric  max-length: 40   -.
		'pmt_deliverypostalcode',   // Numeric       max-length: 5    -.
		'pmt_deliverycountry',      // Alpha         max-length: 2    -               Respecting the ISO 3166.
		'pmt_sellercosts',          // Alphanumeric  max-length: 17   min-length: 4   n,nn.
		'pmt_rows',                 // Numeric       max-length: 4    min-length: 1.
		'pmt_charset',              // Alphanumeric  max-length: 15   -               {ISO-8859-1, ISO-8859-15, UTF-8}.
		'pmt_charsethttp',          // Alphanumeric  max-length: 15   -               {ISO-8859-1, ISO-8859-15, UTF-8}.
		'pmt_hashversion',          // Alphanumeric  max-length: 10   -               {SHA-512, SHA-256, SHA-1, MD5}.
		'pmt_keygeneration',        // N umeric       max-length: 3    -..
	);

	/**
	 * Optional data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $optional_data Optional properties in the payment data.
	 */
	private static $optional_data = array(
		'pmt_selleriban',
		'pmt_userlocale',
		'pmt_invoicefromseller',
		'pmt_paymentmethod',
		'pmt_buyeridentificationcode',
		'pmt_buyerphone',
		'pmt_buyeremail',
	);

	/**
	 * Mandatory row data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $row_mandatory_data Mandatory properties for the payment data rows.
	 */
	private static $row_mandatory_data = array(
		'pmt_row_name',                  // Alphanumeric  max-length: 40    -.
		'pmt_row_desc',                  // Alphanumeric  max-length: 1000  min-length: 1.
		'pmt_row_quantity',              // Numeric       max-length: 10     min-length: 1.
		'pmt_row_deliverydate',          // Alphanumeric  max-length: 10    min-length: 10  dd.MM.yyyy.
		'pmt_row_price_gross',           // Alphanumeric  max-length: 17    min-length: 4   n,nn.
		'pmt_row_price_net',             // Alphanumeric  max-length: 17    min-length: 4   n,nn.
		'pmt_row_vat',                   // Alphanumeric  max-length: 5     min-length: 4   n,nn.
		'pmt_row_discountpercentage',    // Alphanumeric  max-length: 5     min-length: 4   n,nn.
		'pmt_row_type',                  // Numeric       max-length: 5     min-length: 1.
	);

	/**
	 * Optional row data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $row_optional_data Optional properties for the payment data rows.
	 */
	private static $row_optional_data = array(
		'pmt_row_articlenr',
		'pmt_row_unit',
	);

	/**
	 * Hash data.
	 *
	 * @since 2.0.0
	 *
	 * @var array $hash_data Properties used for hashing.
	 */
	private static $hash_data = array(
		'pmt_action',
		'pmt_version',
		'pmt_selleriban',
		'pmt_id',
		'pmt_orderid',
		'pmt_reference',
		'pmt_duedate',
		'pmt_amount',
		'pmt_currency',
		'pmt_okreturn',
		'pmt_errorreturn',
		'pmt_cancelreturn',
		'pmt_delayedpayreturn',
		'pmt_escrow',
		'pmt_escrowchangeallowed',
		'pmt_invoicefromseller',
		'pmt_paymentmethod',
		'pmt_buyeridentificationcode',
		'pmt_buyername',
		'pmt_buyeraddress',
		'pmt_buyerpostalcode',
		'pmt_buyercity',
		'pmt_buyercountry',
		'pmt_deliveryname',
		'pmt_deliveryaddress',
		'pmt_deliverypostalcode',
		'pmt_deliverycity',
		'pmt_deliverycountry',
		'pmt_sellercosts',
	);

	/**
	 * Field filters.
	 *
	 * @since 2.0.0
	 *
	 * @var array $field_filters Field filters (min, max).
	 */
	private static $field_filters = array(
		'pmt_action'                  => array( 4, 50 ),
		'pmt_version'                 => array( 4, 4 ),
		'pmt_sellerid'                => array( 1, 15 ),
		'pmt_selleriban'              => array( 18, 30 ), // Optional.
		'pmt_id'                      => array( 1, 20 ),
		'pmt_orderid'                 => array( 1, 50 ),
		'pmt_reference'               => array( 3, 20 ), // > 100.
		'pmt_duedate'                 => array( 10, 10 ),
		'pmt_userlocale'              => array( 5, 5 ), // Optional.
		'pmt_amount'                  => array( 4, 17 ),
		'pmt_currency'                => array( 3, 3 ),
		'pmt_okreturn'                => array( 1, 200 ),
		'pmt_errorreturn'             => array( 1, 200 ),
		'pmt_cancelreturn'            => array( 1, 200 ),
		'pmt_delayedpayreturn'        => array( 1, 200 ),
		'pmt_escrow'                  => array( 1, 1 ),
		'pmt_escrowchangeallowed'     => array( 1, 1 ),
		'pmt_invoicefromseller'       => array( 1, 1 ), // Optional.
		'pmt_paymentmethod'           => array( 4, 4 ), // Optional.
		'pmt_buyeridentificationcode' => array( 9, 11 ), // Optional.
		'pmt_buyername'               => array( 1, 40 ),
		'pmt_buyeraddress'            => array( 1, 40 ),
		'pmt_buyerpostalcode'         => array( 1, 5 ),
		'pmt_buyercity'               => array( 1, 40 ),
		'pmt_buyercountry'            => array( 1, 2 ),
		'pmt_buyerphone'              => array( 0, 40 ), // Optional.
		'pmt_buyeremail'              => array( 0, 320 ), // Optional.
		'pmt_deliveryname'            => array( 1, 40 ),
		'pmt_deliveryaddress'         => array( 1, 40 ),
		'pmt_deliverypostalcode'      => array( 1, 5 ),
		'pmt_deliverycity'            => array( 1, 40 ),
		'pmt_deliverycountry'         => array( 1, 2 ),
		'pmt_sellercosts'             => array( 4, 17 ),
		'pmt_rows'                    => array( 1, 4 ),
		'pmt_row_name'                => array( 1, 40 ),
		'pmt_row_desc'                => array( 1, 1000 ),
		'pmt_row_quantity'            => array( 1, 10 ),
		'pmt_row_deliverydate'        => array( 10, 10 ),
		'pmt_row_price_gross'         => array( 4, 17 ),
		'pmt_row_price_net'           => array( 4, 17 ),
		'pmt_row_vat'                 => array( 4, 5 ),
		'pmt_row_discountpercentage'  => array( 4, 5 ),
		'pmt_row_type'                => array( 1, 5 ),
		'pmt_charset'                 => array( 1, 15 ),
		'pmt_charsethttp'             => array( 1, 15 ),
		'pmt_hashversion'             => array( 1, 10 ),
{'fraction_non_alphanumeric': 0.127181601677745, 'fraction_numerical': 0.029289446557423666, 'mean_word_length': 2.3405366896224176, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 113, 'https://': 6, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3427934', 'n_tokens_mistral': 11508, 'n_tokens_neox': 9990, 'n_words': 2247}