Hotel Raxa - Advanced Booking System Implementation
🏨 Hotel Booking Enhancements: - Implemented Eagle Booking Advanced Pricing add-on - Added Booking.com-style rate management system - Created professional calendar interface for pricing - Integrated deals and discounts functionality 💰 Advanced Pricing Features: - Dynamic pricing models (per room, per person, per adult) - Base rates, adult rates, and child rates management - Length of stay discounts and early bird deals - Mobile rates and secret deals implementation - Seasonal promotions and flash sales 📅 Availability Management: - Real-time availability tracking - Stop sell and restriction controls - Closed to arrival/departure functionality - Minimum/maximum stay requirements - Automatic sold-out management 💳 Payment Integration: - Maintained Redsys payment gateway integration - Seamless integration with existing Eagle Booking - No modifications to core Eagle Booking plugin 🛠️ Technical Implementation: - Custom database tables for advanced pricing - WordPress hooks and filters integration - AJAX-powered admin interface - Data migration from existing Eagle Booking - Professional calendar view for revenue management 📊 Admin Interface: - Booking.com-style management dashboard - Visual rate and availability calendar - Bulk operations for date ranges - Statistics and analytics dashboard - Modal dialogs for quick editing 🔧 Code Quality: - WordPress coding standards compliance - Secure database operations with prepared statements - Proper input validation and sanitization - Error handling and logging - Responsive admin interface 🤖 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class EB_Redsys_Settings {
|
||||
private $option_group = 'eb_redsys_settings';
|
||||
private $page_slug = 'eb-redsys-settings';
|
||||
|
||||
public function __construct() {
|
||||
add_action('admin_menu', array($this, 'add_settings_page'));
|
||||
add_action('admin_init', array($this, 'register_settings'));
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
|
||||
add_filter('eb_payment_methods', array($this, 'add_payment_method'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings page to menu
|
||||
*/
|
||||
public function add_settings_page() {
|
||||
if (!function_exists('eb_get_option')) {
|
||||
add_menu_page(
|
||||
__('Redsys Gateway', 'eb-redsys-gateway'),
|
||||
__('Redsys Gateway', 'eb-redsys-gateway'),
|
||||
'manage_options',
|
||||
$this->page_slug,
|
||||
array($this, 'render_settings_page'),
|
||||
'dashicons-money-alt',
|
||||
85
|
||||
);
|
||||
} else {
|
||||
add_submenu_page(
|
||||
'eb_bookings',
|
||||
__('Redsys Gateway', 'eb-redsys-gateway'),
|
||||
__('Redsys Gateway', 'eb-redsys-gateway'),
|
||||
'manage_options',
|
||||
$this->page_slug,
|
||||
array($this, 'render_settings_page')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugin settings
|
||||
*/
|
||||
public function register_settings() {
|
||||
register_setting($this->option_group, 'eb_redsys_enabled', array('default' => 'yes'));
|
||||
register_setting($this->option_group, 'eb_redsys_test_mode', array('default' => 'yes'));
|
||||
register_setting($this->option_group, 'eb_redsys_merchant_code');
|
||||
register_setting($this->option_group, 'eb_redsys_terminal');
|
||||
register_setting($this->option_group, 'eb_redsys_encryption_key');
|
||||
register_setting($this->option_group, 'eb_redsys_title', array(
|
||||
'default' => __('Credit Card (Redsys)', 'eb-redsys-gateway')
|
||||
));
|
||||
register_setting($this->option_group, 'eb_redsys_description', array(
|
||||
'default' => __('Pay securely via credit card using Redsys.', 'eb-redsys-gateway')
|
||||
));
|
||||
register_setting($this->option_group, 'eb_redsys_enable_future_payments', array('default' => 'no'));
|
||||
register_setting($this->option_group, 'eb_redsys_enable_subscriptions', array('default' => 'no'));
|
||||
|
||||
// Register sections and fields
|
||||
add_settings_section(
|
||||
'eb_redsys_general_section',
|
||||
__('General Settings', 'eb-redsys-gateway'),
|
||||
array($this, 'render_general_section'),
|
||||
$this->page_slug
|
||||
);
|
||||
|
||||
add_settings_section(
|
||||
'eb_redsys_api_section',
|
||||
__('API Credentials', 'eb-redsys-gateway'),
|
||||
array($this, 'render_api_section'),
|
||||
$this->page_slug
|
||||
);
|
||||
|
||||
add_settings_section(
|
||||
'eb_redsys_advanced_section',
|
||||
__('Advanced Settings', 'eb-redsys-gateway'),
|
||||
array($this, 'render_advanced_section'),
|
||||
$this->page_slug
|
||||
);
|
||||
|
||||
// General Fields
|
||||
$this->add_field('enabled', 'checkbox', __('Enable/Disable', 'eb-redsys-gateway'), 'general');
|
||||
$this->add_field('test_mode', 'checkbox', __('Test Mode', 'eb-redsys-gateway'), 'general');
|
||||
$this->add_field('title', 'text', __('Title', 'eb-redsys-gateway'), 'general');
|
||||
$this->add_field('description', 'textarea', __('Description', 'eb-redsys-gateway'), 'general');
|
||||
|
||||
// API Fields
|
||||
$this->add_field('merchant_code', 'text', __('Merchant Code (FUC)', 'eb-redsys-gateway'), 'api');
|
||||
$this->add_field('terminal', 'text', __('Terminal Number', 'eb-redsys-gateway'), 'api');
|
||||
$this->add_field('encryption_key', 'password', __('Encryption Key', 'eb-redsys-gateway'), 'api');
|
||||
|
||||
// Advanced Fields
|
||||
$this->add_field('enable_future_payments', 'checkbox', __('Future Payments', 'eb-redsys-gateway'), 'advanced');
|
||||
$this->add_field('enable_subscriptions', 'checkbox', __('Subscriptions', 'eb-redsys-gateway'), 'advanced');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add field to settings
|
||||
*/
|
||||
private function add_field($name, $type, $label, $section) {
|
||||
add_settings_field(
|
||||
'eb_redsys_' . $name,
|
||||
$label,
|
||||
array($this, 'render_field'),
|
||||
$this->page_slug,
|
||||
'eb_redsys_' . $section . '_section',
|
||||
array(
|
||||
'name' => 'eb_redsys_' . $name,
|
||||
'type' => $type,
|
||||
'label' => $label
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render field based on type
|
||||
*/
|
||||
public function render_field($args) {
|
||||
$name = $args['name'];
|
||||
$type = $args['type'];
|
||||
$value = get_option($name);
|
||||
|
||||
switch ($type) {
|
||||
case 'checkbox':
|
||||
?>
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
name="<?php echo esc_attr($name); ?>"
|
||||
value="yes"
|
||||
<?php checked($value, 'yes'); ?>>
|
||||
<?php esc_html_e('Enable', 'eb-redsys-gateway'); ?>
|
||||
</label>
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'text':
|
||||
?>
|
||||
<input type="text"
|
||||
name="<?php echo esc_attr($name); ?>"
|
||||
value="<?php echo esc_attr($value); ?>"
|
||||
class="regular-text">
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'password':
|
||||
?>
|
||||
<input type="password"
|
||||
name="<?php echo esc_attr($name); ?>"
|
||||
value="<?php echo esc_attr($value); ?>"
|
||||
class="regular-text">
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'textarea':
|
||||
?>
|
||||
<textarea name="<?php echo esc_attr($name); ?>"
|
||||
class="large-text"
|
||||
rows="3"><?php echo esc_textarea($value); ?></textarea>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render section descriptions
|
||||
*/
|
||||
public function render_general_section() {
|
||||
echo '<p>' . esc_html__('Configure how Redsys appears on your site.', 'eb-redsys-gateway') . '</p>';
|
||||
}
|
||||
|
||||
public function render_api_section() {
|
||||
echo '<p>' . esc_html__('Enter your Redsys API credentials. You can find these in your Redsys merchant dashboard.', 'eb-redsys-gateway') . '</p>';
|
||||
}
|
||||
|
||||
public function render_advanced_section() {
|
||||
echo '<p>' . esc_html__('Advanced settings for special payment scenarios.', 'eb-redsys-gateway') . '</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Redsys to Eagle Booking payment methods
|
||||
*/
|
||||
public function add_payment_method($methods) {
|
||||
if (get_option('eb_redsys_enabled') === 'yes') {
|
||||
$methods['redsys'] = array(
|
||||
'title' => get_option('eb_redsys_title', __('Credit Card (Redsys)', 'eb-redsys-gateway')),
|
||||
'description' => get_option('eb_redsys_description'),
|
||||
'action_type' => 'redsys'
|
||||
);
|
||||
}
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue admin scripts
|
||||
*/
|
||||
public function enqueue_admin_scripts($hook) {
|
||||
if (strpos($hook, $this->page_slug) !== false) {
|
||||
wp_enqueue_style(
|
||||
'eb-redsys-admin',
|
||||
EB_REDSYS_URL . 'assets/css/admin.css',
|
||||
array(),
|
||||
EB_REDSYS_VERSION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the settings page
|
||||
*/
|
||||
public function render_settings_page() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||||
|
||||
<?php
|
||||
if (isset($_GET['settings-updated'])) {
|
||||
add_settings_error(
|
||||
'eb_redsys_messages',
|
||||
'eb_redsys_message',
|
||||
__('Settings Saved', 'eb-redsys-gateway'),
|
||||
'updated'
|
||||
);
|
||||
}
|
||||
settings_errors('eb_redsys_messages');
|
||||
?>
|
||||
|
||||
<form action="options.php" method="post">
|
||||
<?php
|
||||
settings_fields($this->option_group);
|
||||
do_settings_sections($this->page_slug);
|
||||
submit_button();
|
||||
?>
|
||||
</form>
|
||||
|
||||
<div class="eb-redsys-info postbox">
|
||||
<h3 class="hndle"><?php esc_html_e('Important Information', 'eb-redsys-gateway'); ?></h3>
|
||||
<div class="inside">
|
||||
<h4><?php esc_html_e('Test Mode', 'eb-redsys-gateway'); ?></h4>
|
||||
<p><?php esc_html_e('For testing, use these credentials:', 'eb-redsys-gateway'); ?></p>
|
||||
<ul>
|
||||
<li><?php esc_html_e('Test Card: 4548 8120 4940 0004', 'eb-redsys-gateway'); ?></li>
|
||||
<li><?php esc_html_e('Expiry Date: 12/24', 'eb-redsys-gateway'); ?></li>
|
||||
<li><?php esc_html_e('CVV2: 123', 'eb-redsys-gateway'); ?></li>
|
||||
</ul>
|
||||
|
||||
<h4><?php esc_html_e('Getting Started', 'eb-redsys-gateway'); ?></h4>
|
||||
<p><?php esc_html_e('To get your credentials:', 'eb-redsys-gateway'); ?></p>
|
||||
<ol>
|
||||
<li><?php esc_html_e('Log in to your Redsys merchant account', 'eb-redsys-gateway'); ?></li>
|
||||
<li><?php esc_html_e('Go to Administration → Technical Configuration', 'eb-redsys-gateway'); ?></li>
|
||||
<li><?php esc_html_e('Find your Merchant Code (FUC) and Terminal number', 'eb-redsys-gateway'); ?></li>
|
||||
<li><?php esc_html_e('Generate your Encryption Key in the Security section', 'eb-redsys-gateway'); ?></li>
|
||||
</ol>
|
||||
|
||||
<h4><?php esc_html_e('Support', 'eb-redsys-gateway'); ?></h4>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: URL */
|
||||
esc_html__('For support, please visit our %s.', 'eb-redsys-gateway'),
|
||||
'<a href="https://support.informatiq.com" target="_blank">' . esc_html__('support center', 'eb-redsys-gateway') . '</a>'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
if(!class_exists('RESTConstants')){
|
||||
class RESTConstants {
|
||||
|
||||
// Environments
|
||||
public static $INICIA = "0";
|
||||
public static $TRATA = "1";
|
||||
|
||||
public static $ENV_SANDBOX = "0";
|
||||
// Endpoints TEST
|
||||
public static $SANDBOX_JS = "https://sis-t.redsys.es:25443/sis/NC/sandbox/redsysV3.js";
|
||||
public static $SANDBOX_ENDPOINT = "https://sis-t.redsys.es:25443/sis/rest/trataPeticionREST";
|
||||
public static $SANDBOX_ENDPOINT_INICIA = "https://sis-t.redsys.es:25443/sis/rest/iniciaPeticionREST";
|
||||
|
||||
public static $ENV_PRODUCTION = "1";
|
||||
public static $PRODUCTION_JS = "https://sis.redsys.es/sis/NC/redsysV3.js";
|
||||
public static $PRODUCTION_ENDPOINT = "https://sis.redsys.es/sis/rest/trataPeticionREST";
|
||||
public static $PRODUCTION_ENDPOINT_INICIA = "https://sis.redsys.es/sis/rest/iniciaPeticionREST";
|
||||
|
||||
public static $CONNECTION_TIMEOUT_VALUE = 10;
|
||||
public static $READ_TIMEOUT_VALUE = 120;
|
||||
public static $SSL_TLSv12 = 6;
|
||||
public static $TARGET = "http://webservice.sis.sermepa.es";
|
||||
public static $SERVICE_NAME = "SerClsWSEntradaService";
|
||||
public static $PORT_NAME = "SerClsWSEntrada";
|
||||
|
||||
|
||||
// Request message constants
|
||||
public static $REQUEST_SIGNATURE = "DS_SIGNATURE";
|
||||
public static $REQUEST_SIGNATUREVERSION_VALUE = "HMAC_SHA256_V1";
|
||||
public static $REQUEST_MERCHANT_ORDER = "DS_MERCHANT_ORDER";
|
||||
public static $REQUEST_MERCHANT_MERCHANTCODE = "DS_MERCHANT_MERCHANTCODE";
|
||||
public static $REQUEST_MERCHANT_TERMINAL = "DS_MERCHANT_TERMINAL";
|
||||
public static $REQUEST_MERCHANT_TRANSACTIONTYPE = "DS_MERCHANT_TRANSACTIONTYPE";
|
||||
public static $REQUEST_MERCHANT_IDOPER = "DS_MERCHANT_IDOPER";
|
||||
public static $REQUEST_MERCHANT_CURRENCY = "DS_MERCHANT_CURRENCY";
|
||||
public static $REQUEST_MERCHANT_AMOUNT = "DS_MERCHANT_AMOUNT";
|
||||
public static $REQUEST_MERCHANT_IDENTIFIER = "DS_MERCHANT_IDENTIFIER";
|
||||
public static $REQUEST_MERCHANT_IDENTIFIER_REQUIRED = "REQUIRED";
|
||||
public static $REQUEST_MERCHANT_DIRECTPAYMENT = "DS_MERCHANT_DIRECTPAYMENT";
|
||||
public static $REQUEST_MERCHANT_DIRECTPAYMENT_TRUE = "true";
|
||||
|
||||
//Nuevos para API REST-IS respecto a API IS
|
||||
public static $REQUEST_MERCHANT_DIRECTPAYMENT_MOTO = "MOTO";
|
||||
public static $REQUEST_MERCHANT_CVV2 = "DS_MERCHANT_CVV2";
|
||||
public static $REQUEST_MERCHANT_PAN = "DS_MERCHANT_PAN";
|
||||
public static $REQUEST_MERCHANT_EXPIRYDATE = "DS_MERCHANT_EXPIRYDATE";
|
||||
public static $REQUEST_MERCHANT_COF_INI = "DS_MERCHANT_COF_INI";
|
||||
public static $REQUEST_MERCHANT_COF_INI_TRUE = "S";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE = "DS_MERCHANT_COF_TYPE";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE_INSTALLMENTS = "I";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE_RECURRING = "R";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE_REAUTHORIZATION = "H";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE_RESUBMISSION = "E";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE_DELAYED = "D";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE_INCREMENTAL = "M";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE_NOSHOW = "N";
|
||||
public static $REQUEST_MERCHANT_COF_TYPE_OTRAS = "C";
|
||||
|
||||
public static $REQUEST_MERCHANT_COF_TXNID = "DS_MERCHANT_COF_TXNID";
|
||||
|
||||
//No se usan
|
||||
//public static $REQUEST_REQUEST_TAG = "REQUEST";
|
||||
//public static $REQUEST_DATOSENTRADA_TAG = "DATOSENTRADA";
|
||||
//public static $REQUEST_SIGNATUREVERSION_TAG = "DS_SIGNATUREVERSION";
|
||||
//public static $REQUEST_MERCHANT_SIS_CURRENCY_TAG = "Sis_Divisa";
|
||||
//public static $REQUEST_MERCHANT_SESSION_TAG = "DS_MERCHANT_SESION";
|
||||
//public static $REQUEST_MERCHANT_DIRECTPAYMENT_3DS = "3DS";
|
||||
|
||||
|
||||
//Request EMV3DS constants
|
||||
public static $REQUEST_MERCHANT_EMV3DS = "DS_MERCHANT_EMV3DS";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_THREEDSINFO = "threeDSInfo";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_CARDDATA = "CardData";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_AUTHENTICACIONDATA = "AuthenticationData";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_CHALLENGEREQUEST = "ChallengeRequest";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_CHALLENGEREQUESTRESPONSE = "ChallengeResponse";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_PROTOCOLVERSION = "protocolVersion";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_PROTOCOLVERSION_102 = "1.0.2";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_PROTOCOLVERSION_210 = "2.1.0";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_PROTOCOLVERSION_220 = "2.2.0";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_ACCEPT_HEADER = "browserAcceptHeader";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_ACCEPT_HEADER_VALUE = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_USER_AGENT = "browserUserAgent";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_USER_AGENT_VALUE = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_JAVA_ENABLE = "browserJavaEnabled";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_JAVASCRIPT_ENABLE = "browserJavascriptEnabled";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_LANGUAGE = "browserLanguage";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_COLORDEPTH = "browserColorDepth";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_SCREEN_HEIGHT = "browserScreenHeight";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_SCREEN_WIDTH = "browserScreenWidth";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_BROWSER_TZ = "browserTZ";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_THREEDSSERVERTRANSID = "threeDSServerTransID";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_NOTIFICATIONURL= "notificationURL";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_THREEDSCOMPIND = "threeDSCompInd";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_PARES = "PARes";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_MD = "MD";
|
||||
public static $REQUEST_MERCHANT_EMV3DS_CRES = "cres";
|
||||
public static $REQUEST_MERCHANT_EXEMPTION = "DS_MERCHANT_EXCEP_SCA";
|
||||
public static $REQUEST_MERCHANT_EXEMPTION_VALUE_YES = "Y";
|
||||
public static $REQUEST_MERCHANT_EXEMPTION_VALUE_LWV = "LWV";
|
||||
public static $REQUEST_MERCHANT_EXEMPTION_VALUE_TRA = "TRA";
|
||||
public static $REQUEST_MERCHANT_EXEMPTION_VALUE_MIT = "MIT";
|
||||
public static $REQUEST_MERCHANT_EXEMPTION_VALUE_COR = "COR";
|
||||
public static $REQUEST_MERCHANT_EXEMPTION_VALUE_ATD = "ATD";
|
||||
public static $REQUEST_MERCHANT_EXEMPTION_VALUE_NDF = "NDF";
|
||||
|
||||
|
||||
// Response message constants
|
||||
public static $RESPONSE_AMOUNT = "Ds_Amount";
|
||||
public static $RESPONSE_CURRENCY = "Ds_Currency";
|
||||
public static $RESPONSE_ORDER = "Ds_Order";
|
||||
public static $RESPONSE_SIGNATURE = "Ds_Signature";
|
||||
public static $RESPONSE_MERCHANT = "Ds_MerchantCode";
|
||||
public static $RESPONSE_TERMINAL = "Ds_Terminal";
|
||||
public static $RESPONSE_DS_RESPONSE = "Ds_Response";
|
||||
public static $RESPONSE_AUTHORIZATION_CODE = "Ds_AuthorisationCode";
|
||||
public static $RESPONSE_TRANSACTION_TYPE = "Ds_TransactionType";
|
||||
public static $RESPONSE_SECURE_PAYMENT = "Ds_SecurePayment";
|
||||
public static $RESPONSE_LANGUAGE = "Ds_Language";
|
||||
public static $RESPONSE_MERCHANT_DATA = "Ds_MerchantData";
|
||||
public static $RESPONSE_CARD_COUNTRY = "Ds_Card_Country";
|
||||
public static $RESPONSE_CARD_NUMBER = "Ds_CardNumber";
|
||||
public static $RESPONSE_EXPIRY_DATE = "Ds_ExpiryDate";
|
||||
public static $RESPONSE_MERCHANT_IDENTIFIER = "Ds_CardNumber";
|
||||
public static $RESPONSE_AUTHENTICATION_REQUIRED = "authenticationRequired";
|
||||
public static $RESPONSE_AUTHENTICATION_NOT_REQUIRED = "authenticationNotRequired";
|
||||
|
||||
//No viene en Java y no se usa
|
||||
//public static $RESPONSE_CODE = "CODIGO";
|
||||
|
||||
|
||||
// Response message DCC
|
||||
public static $REQUEST_DS_MERCHANT_DCC = "DS_MERCHANT_DCC";
|
||||
public static $REQUEST_DS_MERCHANT_DCC_TRUE = "Y";
|
||||
public static $REQUEST_DS_MERCHANT_DCC_MONEDA = "monedaDCC";
|
||||
public static $REQUEST_DS_MERCHANT_DCC_IMPORTE = "importeDCC";
|
||||
|
||||
public static $RESPONSE_DCC_CURRENCY_TAG = "moneda";
|
||||
public static $RESPONSE_DCC_CURRENCY_STRING_TAG = "litMoneda";
|
||||
public static $RESPONSE_DCC_CURRENCY_CODE_TAG = "litMonedaR";
|
||||
public static $RESPONSE_DCC_CHANGE_RATE_TAG = "cambio";
|
||||
public static $RESPONSE_DCC_CHANGE_DATE_TAG = "fechaCambio";
|
||||
public static $RESPONSE_DCC_CHECKED_TAG = "checked";
|
||||
public static $RESPONSE_DCC_AMOUNT_TAG = "importe";
|
||||
public static $RESPONSE_DCC_MARGIN_TAG = "margenDCC";
|
||||
public static $RESPONSE_DCC_BANK_NAME_TAG = "nombreEntidad";
|
||||
|
||||
//No vienen en JAVA:
|
||||
public static $RESPONSE_DCC_TAG = "DCC";
|
||||
public static $RESPONSE_ACS_URL_TAG = "Ds_AcsUrl";
|
||||
public static $RESPONSE_JSON_ACS_ENTRY="acsURL";
|
||||
public static $RESPONSE_JSON_PAREQ_ENTRY="PAReq";
|
||||
public static $RESPONSE_JSON_PARES_ENTRY="PARes"; //No se usa
|
||||
public static $RESPONSE_JSON_MD_ENTRY="MD";
|
||||
public static $RESPONSE_JSON_PROTOCOL_VERSION_ENTRY="protocolVersion";
|
||||
public static $RESPONSE_JSON_THREEDSINFO_ENTRY="threeDSInfo";
|
||||
public static $RESPONSE_3DS_CHALLENGE_REQUEST="ChallengeRequest";
|
||||
public static $RESPONSE_3DS_CHALLENGE_RESPONSE="ChallengeResponse"; //No se usa
|
||||
public static $RESPONSE_3DS_VERSION_1="1.0.2";
|
||||
public static $RESPONSE_3DS_VERSION_2_PREFIX="2.";
|
||||
|
||||
|
||||
//Response 3DSecure
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_PROTOCOLVERSION = "protocolVersion";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_PROTOCOLVERSION_102 = "NO_3DS_v2";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_PROTOCOLVERSION_210 = "2.1.0";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_PROTOCOLVERSION_220 = "2.2.0";
|
||||
public static $RESPONSE_PSD2_TRUE = "Y";
|
||||
public static $RESPONSE_PSD2_FALSE = "N";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_THREEDSMETHODURL = "threeDSMethodURL";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_THREEDSINFO = "threeDSInfo";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_THREEDSSERVERTRANSID = "threeDSServerTransID";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_ACSURL = "acsURL";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_CREQ = "creq";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_MD = "MD";
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_PAREQ = "PAReq";
|
||||
//No viene en Java:
|
||||
public static $RESPONSE_MERCHANT_EMV3DS_CRES = "cres";
|
||||
|
||||
|
||||
// Response codes
|
||||
public static $RESP_CODE_OK = "0";
|
||||
public static $RESP_LITERAL_OK = "OK";
|
||||
public static $RESP_LITERAL_KO = "KO";
|
||||
public static $RESP_LITERAL_AUT = "AUT";
|
||||
//No vienen en Java
|
||||
public static $AUTHORIZATION_OK = 0000;
|
||||
public static $CONFIRMATION_OK = 900;
|
||||
public static $CANCELLATION_OK = 400;
|
||||
public static $UNFINISHED = 9998;
|
||||
|
||||
public static $AUTHORIZATION = "0";
|
||||
public static $REFUND = "3";
|
||||
public static $PREAUTHORIZATION = "1";
|
||||
public static $CONFIRMATION = "2";
|
||||
public static $CANCELLATION = "9";
|
||||
public static $VALIDATION = "7";
|
||||
public static $VALIDATION_CONFIRMATION = "8";
|
||||
public static $DELETE_REFERENCE = "44";
|
||||
public static $PAYMENT_CANCELLATION = "45";
|
||||
public static $PAYGOLD_REQUEST = "F";
|
||||
public static $REFUND_WITHOUT_ORIGINAL = "Y";
|
||||
public static $NULL = "NULL";
|
||||
|
||||
|
||||
//Get the JavaScript path depending on the environment we are in, production or test (sandbox)
|
||||
public static function getJSPath($env){
|
||||
if($env==RESTConstants::$ENV_PRODUCTION){
|
||||
return RESTConstants::$PRODUCTION_JS;
|
||||
}
|
||||
else{
|
||||
return RESTConstants::$SANDBOX_JS;
|
||||
}
|
||||
}
|
||||
|
||||
//Get the endpoint path depending on the environment and the operation we are in, production/test(sandbox) and inicia/trata
|
||||
public static function getEnviromentEndpoint($env, $operation){
|
||||
|
||||
if($env == RESTConstants::$ENV_PRODUCTION){
|
||||
if($operation == RESTConstants::$INICIA){
|
||||
return RESTConstants::$PRODUCTION_ENDPOINT_INICIA;
|
||||
}
|
||||
else{return RESTConstants::$PRODUCTION_ENDPOINT;}
|
||||
}
|
||||
else{
|
||||
if($operation == RESTConstants::$INICIA){
|
||||
return RESTConstants::$SANDBOX_ENDPOINT_INICIA;
|
||||
}
|
||||
else{return RESTConstants::$SANDBOX_ENDPOINT;}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTA SOBRE LA LICENCIA DE USO DEL SOFTWARE
|
||||
*
|
||||
* El uso de este software está sujeto a las Condiciones de uso de software que
|
||||
* se incluyen en el paquete en el documento "Aviso Legal.pdf". También puede
|
||||
* obtener una copia en la siguiente url:
|
||||
* http://www.redsys.es/wps/portal/redsys/publica/areadeserviciosweb/descargaDeDocumentacionYEjecutables
|
||||
*
|
||||
* Redsys es titular de todos los derechos de propiedad intelectual e industrial
|
||||
* del software.
|
||||
*
|
||||
* Quedan expresamente prohibidas la reproducción, la distribución y la
|
||||
* comunicación pública, incluida su modalidad de puesta a disposición con fines
|
||||
* distintos a los descritos en las Condiciones de uso.
|
||||
*
|
||||
* Redsys se reserva la posibilidad de ejercer las acciones legales que le
|
||||
* correspondan para hacer valer sus derechos frente a cualquier infracción de
|
||||
* los derechos de propiedad intelectual y/o industrial.
|
||||
*
|
||||
* Redsys Servicios de Procesamiento, S.L., CIF B85955367
|
||||
*/
|
||||
|
||||
include_once 'hmac.php';
|
||||
if (!defined('PHP_VERSION_ID')) {
|
||||
$version = explode('.', PHP_VERSION); //5.2.7 -> 50207 5.5.28 -> 50528
|
||||
define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
|
||||
}
|
||||
class RedsyspurAPI{
|
||||
|
||||
/****** Array de DatosEntrada ******/
|
||||
var $vars_pay = array();
|
||||
|
||||
/****** Set parameter ******/
|
||||
function setParameter($key,$value){
|
||||
$this->vars_pay[$key]=$value;
|
||||
}
|
||||
|
||||
/****** Get parameter ******/
|
||||
function getParameter($key){
|
||||
return $this->vars_pay[$key];
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////// FUNCIONES AUXILIARES: ////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/****** 3DES Function ******/
|
||||
function encrypt_3DES($message, $key){
|
||||
// Se establece un IV por defecto
|
||||
$bytes = array(0,0,0,0,0,0,0,0); //byte [] IV = {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
$iv = implode(array_map("chr", $bytes)); //PHP 4 >= 4.0.2
|
||||
|
||||
// Se cifra
|
||||
if(phpversion() < 7){
|
||||
|
||||
$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv); //PHP 4 >= 4.0.2
|
||||
return $ciphertext;
|
||||
|
||||
}else{
|
||||
|
||||
$long = ceil(strlen($message) / 8) * 8;
|
||||
$ciphertext = substr(openssl_encrypt($message . str_repeat("\0", $long - strlen($message)), 'des-ede3-cbc', $key, OPENSSL_RAW_DATA, $iv), 0, $long);
|
||||
|
||||
return $ciphertext;
|
||||
}
|
||||
}
|
||||
|
||||
/****** Base64 Functions ******/
|
||||
function base64_url_encode($input){
|
||||
return strtr(base64_encode($input), '+/', '-_');
|
||||
}
|
||||
function encodeBase64($data){
|
||||
$data = base64_encode($data);
|
||||
return $data;
|
||||
}
|
||||
function base64_url_decode($input){
|
||||
return base64_decode(strtr($input, '-_', '+/'));
|
||||
}
|
||||
function decodeBase64($data){
|
||||
$data = base64_decode($data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/****** MAC Function ******/
|
||||
function mac256($ent,$key){
|
||||
if (PHP_VERSION_ID < 50102) {
|
||||
$res = hash_hmac4('sha256', $ent, $key, true);
|
||||
} else {
|
||||
$res = hash_hmac('sha256', $ent, $key, true);//(PHP 5 >= 5.1.2)
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////// FUNCIONES PARA LA GENERACIÓN DEL FORMULARIO DE PAGO: ////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/****** Obtener Número de pedido ******/
|
||||
function getOrder(){
|
||||
$numPedido = "";
|
||||
if(empty($this->vars_pay['DS_MERCHANT_ORDER'])){
|
||||
$numPedido = $this->vars_pay['Ds_Merchant_Order'];
|
||||
} else {
|
||||
$numPedido = $this->vars_pay['DS_MERCHANT_ORDER'];
|
||||
}
|
||||
return $numPedido;
|
||||
}
|
||||
/****** Convertir Array en Objeto JSON ******/
|
||||
function arrayToJson(){
|
||||
$json = json_encode($this->vars_pay); //(PHP 5 >= 5.2.0)
|
||||
return $json;
|
||||
}
|
||||
function createMerchantParameters(){
|
||||
// Se transforma el array de datos en un objeto Json
|
||||
$json = $this->arrayToJson();
|
||||
// Se codifican los datos Base64
|
||||
return $this->encodeBase64($json);
|
||||
}
|
||||
function createMerchantSignature($key){
|
||||
// Se decodifica la clave Base64
|
||||
$key = $this->decodeBase64($key);
|
||||
// Se genera el parámetro Ds_MerchantParameters
|
||||
$ent = $this->createMerchantParameters();
|
||||
// Se diversifica la clave con el Número de Pedido
|
||||
$key = $this->encrypt_3DES($this->getOrder(), $key);
|
||||
// MAC256 del parámetro Ds_MerchantParameters
|
||||
$res = $this->mac256($ent, $key);
|
||||
// Se codifican los datos Base64
|
||||
return $this->encodeBase64($res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////// FUNCIONES PARA LA RECEPCIÓN DE DATOS DE PAGO (Notif, URLOK y URLKO): ////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/****** Obtener Número de pedido ******/
|
||||
function getOrderNotif(){
|
||||
$numPedido = "";
|
||||
if(empty($this->vars_pay['Ds_Order'])){
|
||||
$numPedido = $this->vars_pay['DS_ORDER'];
|
||||
} else {
|
||||
$numPedido = $this->vars_pay['Ds_Order'];
|
||||
}
|
||||
return $numPedido;
|
||||
}
|
||||
/****** Convertir String en Array ******/
|
||||
function stringToArray($datosDecod){
|
||||
$this->vars_pay = json_decode($datosDecod, true); //(PHP 5 >= 5.2.0)
|
||||
}
|
||||
function decodeMerchantParameters($datos){
|
||||
// Se decodifican los datos Base64
|
||||
$decodec = $this->base64_url_decode($datos);
|
||||
return $decodec;
|
||||
}
|
||||
function createMerchantSignatureNotif($key, $datos){
|
||||
// Se decodifica la clave Base64
|
||||
$key = $this->decodeBase64($key);
|
||||
// Se decodifican los datos Base64
|
||||
$decodec = $this->base64_url_decode($datos);
|
||||
// Los datos decodificados se pasan al array de datos
|
||||
$this->stringToArray($decodec);
|
||||
// Se diversifica la clave con el Número de Pedido
|
||||
$key = $this->encrypt_3DES($this->getOrderNotif(), $key);
|
||||
// MAC256 del parámetro Ds_Parameters que envía Redsys
|
||||
$res = $this->mac256($datos, $key);
|
||||
// Se codifican los datos Base64
|
||||
return $this->base64_url_encode($res);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class Redsys_API {
|
||||
|
||||
private $environment;
|
||||
private $api_client;
|
||||
|
||||
public function __construct() {
|
||||
require_once dirname(__FILE__) . '/apiRedsysFinal.php';
|
||||
require_once dirname(__FILE__) . '/RESTConstants.php';
|
||||
|
||||
$this->api_client = new RedsysAPI();
|
||||
$this->environment = get_option('eb_redsys_test_mode') === 'yes' ? 'test' : 'live';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create merchant parameters
|
||||
*/
|
||||
public function createMerchantParameters($params) {
|
||||
// Convert params to JSON
|
||||
$json = json_encode($params);
|
||||
|
||||
// Encode in base64
|
||||
return $this->api_client->encodeBase64($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create merchant signature
|
||||
*/
|
||||
public function createMerchantSignature($key, $data) {
|
||||
return $this->api_client->createMerchantSignature($key, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode merchant parameters
|
||||
*/
|
||||
public function decodeMerchantParameters($data) {
|
||||
$decoded = $this->api_client->decodeBase64($data);
|
||||
return json_decode($decoded, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check signature
|
||||
*/
|
||||
public function check_signature($merchant_parameters, $signature, $key) {
|
||||
$calculated_signature = $this->api_client->createMerchantSignatureNotif($key, $merchant_parameters);
|
||||
return $signature === $calculated_signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get endpoint URL
|
||||
*/
|
||||
public function get_endpoint() {
|
||||
if ($this->environment === 'test') {
|
||||
return 'https://sis-t.redsys.es:25443/sis/realizarPago';
|
||||
} else {
|
||||
return 'https://sis.redsys.es/sis/realizarPago';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create notification signature
|
||||
*/
|
||||
public function createNotificationSignature($key, $data) {
|
||||
return $this->api_client->createMerchantSignatureNotif($key, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format order number
|
||||
*/
|
||||
public function formatOrderNumber($booking_id) {
|
||||
// Ensure order number is exactly 12 digits
|
||||
return str_pad($booking_id, 12, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format amount
|
||||
*/
|
||||
public function formatAmount($amount) {
|
||||
// Convert to cents and ensure no decimal places
|
||||
return number_format($amount * 100, 0, '', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create future payment parameters
|
||||
*/
|
||||
public function createFuturePaymentParams($params, $execution_date) {
|
||||
$params['DS_MERCHANT_TRANSACTIONTYPE'] = 'L'; // Deferred payment
|
||||
$params['DS_MERCHANT_DATEFRECUENCY'] = '1'; // Daily frequency
|
||||
$params['DS_MERCHANT_CHARGEEXPIRYDATE'] = date('d/m/Y', strtotime($execution_date));
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create subscription parameters
|
||||
*/
|
||||
public function createSubscriptionParams($params) {
|
||||
$params['DS_MERCHANT_TRANSACTIONTYPE'] = 'L';
|
||||
$params['DS_MERCHANT_COF_INI'] = 'S'; // Initial recurring payment
|
||||
$params['DS_MERCHANT_COF_TYPE'] = 'R'; // Recurring payment type
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create subsequent payment parameters
|
||||
*/
|
||||
public function createSubsequentPaymentParams($params, $reference_id) {
|
||||
$params['DS_MERCHANT_TRANSACTIONTYPE'] = '0';
|
||||
$params['DS_MERCHANT_IDENTIFIER'] = $reference_id;
|
||||
$params['DS_MERCHANT_DIRECTPAYMENT'] = 'true';
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse notification response
|
||||
*/
|
||||
public function parseNotification($data) {
|
||||
if (!isset($data['Ds_SignatureVersion']) ||
|
||||
!isset($data['Ds_MerchantParameters']) ||
|
||||
!isset($data['Ds_Signature'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$decoded_params = $this->decodeMerchantParameters($data['Ds_MerchantParameters']);
|
||||
|
||||
return array(
|
||||
'params' => $decoded_params,
|
||||
'signature' => $data['Ds_Signature']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate response code
|
||||
*/
|
||||
public function isSuccessResponse($response_code) {
|
||||
// Response codes less than 100 indicate success
|
||||
return $response_code < 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response message
|
||||
*/
|
||||
public function getResponseMessage($response_code) {
|
||||
$messages = array(
|
||||
'0000' => __('Transaction authorized for payments and pre-authorizations', 'eb-redsys-gateway'),
|
||||
'0900' => __('Transaction authorized for refunds and confirmations', 'eb-redsys-gateway'),
|
||||
'0101' => __('Card expired', 'eb-redsys-gateway'),
|
||||
'0102' => __('Card temporarily suspended or under suspicion of fraud', 'eb-redsys-gateway'),
|
||||
'0104' => __('Operation not allowed for this type of card', 'eb-redsys-gateway'),
|
||||
'0116' => __('Insufficient funds', 'eb-redsys-gateway'),
|
||||
'0118' => __('Card not registered', 'eb-redsys-gateway'),
|
||||
'0129' => __('Security code (CVV2/CVC2) incorrect', 'eb-redsys-gateway'),
|
||||
'0180' => __('Card not recognized', 'eb-redsys-gateway'),
|
||||
'0184' => __('Cardholder authentication failed', 'eb-redsys-gateway'),
|
||||
'0190' => __('Transaction declined without specific reason', 'eb-redsys-gateway'),
|
||||
'0191' => __('Wrong expiration date', 'eb-redsys-gateway'),
|
||||
'0904' => __('Merchant not registered at FUC', 'eb-redsys-gateway'),
|
||||
'0909' => __('System error', 'eb-redsys-gateway'),
|
||||
'0912' => __('Issuer not available', 'eb-redsys-gateway'),
|
||||
'0913' => __('Duplicate order', 'eb-redsys-gateway'),
|
||||
'0944' => __('Wrong session', 'eb-redsys-gateway'),
|
||||
'0950' => __('Refund operation not allowed', 'eb-redsys-gateway'),
|
||||
);
|
||||
|
||||
return isset($messages[$response_code])
|
||||
? $messages[$response_code]
|
||||
: __('Unknown error', 'eb-redsys-gateway');
|
||||
}
|
||||
|
||||
/**
|
||||
* Log error
|
||||
*/
|
||||
public function log_error($message, $data = array()) {
|
||||
if (function_exists('eb_log')) {
|
||||
$log_message = 'Redsys API Error: ' . $message;
|
||||
if (!empty($data)) {
|
||||
$log_message .= ' | Data: ' . print_r($data, true);
|
||||
}
|
||||
eb_log($log_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Replace hash()
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_Compat
|
||||
* @license LGPL - http://www.gnu.org/licenses/lgpl.html
|
||||
* @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
|
||||
* @link http://php.net/function.hash
|
||||
* @author revulo <revulon@gmail.com>
|
||||
* @since PHP 5.1.2
|
||||
* @require PHP 4.0.0 (user_error)
|
||||
*/
|
||||
function php_compat_hash($algo, $data, $raw_output = false)
|
||||
{
|
||||
$algo = strtolower($algo);
|
||||
switch ($algo) {
|
||||
case 'md5':
|
||||
$hash = md5($data);
|
||||
break;
|
||||
|
||||
case 'sha1':
|
||||
if (!function_exists('sha1')) {
|
||||
require dirname(__FILE__) . '/sha1.php';
|
||||
}
|
||||
$hash = sha1($data);
|
||||
break;
|
||||
|
||||
case 'sha256':
|
||||
require_once dirname(__FILE__) . '/sha256.php';
|
||||
$hash = SHA256::hash($data);
|
||||
break;
|
||||
|
||||
default:
|
||||
user_error('hash(): Unknown hashing algorithm: ' . $algo, E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($raw_output) {
|
||||
return pack('H*', $hash);
|
||||
} else {
|
||||
return $hash;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Define
|
||||
if (!function_exists('hash')) {
|
||||
function hash($algo, $data, $raw_output = false)
|
||||
{
|
||||
return php_compat_hash($algo, $data, $raw_output);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
include 'hash.php';
|
||||
|
||||
/**
|
||||
* Replace hash_hmac()
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_Compat
|
||||
* @license LGPL - http://www.gnu.org/licenses/lgpl.html
|
||||
* @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
|
||||
* @link http://php.net/function.hash_hmac
|
||||
* @author revulo <revulon@gmail.com>
|
||||
* @since PHP 5.1.2
|
||||
* @require PHP 4.0.1 (str_pad)
|
||||
*/
|
||||
function php_compat_hash_hmac($algo, $data, $key, $raw_output = false)
|
||||
{
|
||||
// Block size (byte) for MD5, SHA-1 and SHA-256.
|
||||
$blocksize = 64;
|
||||
|
||||
$ipad = str_repeat("\x36", $blocksize);
|
||||
$opad = str_repeat("\x5c", $blocksize);
|
||||
|
||||
if (strlen($key) > $blocksize) {
|
||||
$key = hash($algo, $key, true);
|
||||
} else {
|
||||
$key = str_pad($key, $blocksize, "\x00");
|
||||
}
|
||||
|
||||
$ipad ^= $key;
|
||||
$opad ^= $key;
|
||||
|
||||
return hash($algo, $opad . hash($algo, $ipad . $data, true), $raw_output);
|
||||
}
|
||||
|
||||
|
||||
// Define
|
||||
if (!function_exists('hash_hmac4')) {
|
||||
function hash_hmac4($algo, $data, $key, $raw_output = false)
|
||||
{
|
||||
return php_compat_hash_hmac($algo, $data, $key, $raw_output);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,492 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTA SOBRE LA LICENCIA DE USO DEL SOFTWARE
|
||||
*
|
||||
* El uso de este software está sujeto a las Condiciones de uso de software que
|
||||
* se incluyen en el paquete en el documento "Aviso Legal.pdf". También puede
|
||||
* obtener una copia en la siguiente url:
|
||||
* http://www.redsys.es/wps/portal/redsys/publica/areadeserviciosweb/descargaDeDocumentacionYEjecutables
|
||||
*
|
||||
* Redsys es titular de todos los derechos de propiedad intelectual e industrial
|
||||
* del software.
|
||||
*
|
||||
* Quedan expresamente prohibidas la reproducción, la distribución y la
|
||||
* comunicación pública, incluida su modalidad de puesta a disposición con fines
|
||||
* distintos a los descritos en las Condiciones de uso.
|
||||
*
|
||||
* Redsys se reserva la posibilidad de ejercer las acciones legales que le
|
||||
* correspondan para hacer valer sus derechos frente a cualquier infracción de
|
||||
* los derechos de propiedad intelectual y/o industrial.
|
||||
*
|
||||
* Redsys Servicios de Procesamiento, S.L., CIF B85955367
|
||||
*/
|
||||
|
||||
/////////GLOBALES PARA LOG
|
||||
|
||||
$logLevel = 0;
|
||||
|
||||
$logDISABLED = 0;
|
||||
$logINFOR = 1;
|
||||
$logDEBUG = 2;
|
||||
|
||||
///////////////////// FUNCIONES DE VALIDACION
|
||||
//Firma
|
||||
function checkFirma($firma_local, $firma_remota) {
|
||||
if ($firma_local == $firma_remota)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
//Importe
|
||||
|
||||
function checkImporte($total) {
|
||||
return preg_match("/^\d+$/", $total);
|
||||
}
|
||||
|
||||
//Pedido
|
||||
function checkPedidoNum($pedido) {
|
||||
return preg_match("/^\d{1,12}$/", $pedido);
|
||||
}
|
||||
function checkPedidoAlfaNum($pedido, $pedidoExtendido = false) {
|
||||
if ($pedidoExtendido)
|
||||
return preg_match("/^\w{4,256}$/", $pedido);
|
||||
else
|
||||
return preg_match("/^\w{4,12}$/", $pedido);
|
||||
}
|
||||
|
||||
//Fuc
|
||||
function checkFuc($codigo) {
|
||||
$retVal = preg_match("/^\d{2,9}$/", $codigo);
|
||||
if($retVal) {
|
||||
$codigo = str_pad($codigo,9,"0",STR_PAD_LEFT);
|
||||
$fuc = intval($codigo);
|
||||
$check = substr($codigo, -1);
|
||||
$fucTemp = substr($codigo, 0, -1);
|
||||
$acumulador = 0;
|
||||
$tempo = 0;
|
||||
|
||||
for ($i = strlen($fucTemp)-1; $i >= 0; $i-=2) {
|
||||
$temp = intval(substr($fucTemp, $i, 1)) * 2;
|
||||
$acumulador += intval($temp/10) + ($temp%10);
|
||||
if($i > 0) {
|
||||
$acumulador += intval(substr($fucTemp,$i-1,1));
|
||||
}
|
||||
}
|
||||
$ultimaCifra = $acumulador % 10;
|
||||
$resultado = 0;
|
||||
if($ultimaCifra != 0) {
|
||||
$resultado = 10 - $ultimaCifra;
|
||||
}
|
||||
$retVal = $resultado == $check;
|
||||
}
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
//Moneda
|
||||
function checkMoneda($moneda) {
|
||||
return preg_match("/^\d{1,3}$/", $moneda);
|
||||
}
|
||||
|
||||
//Respuesta
|
||||
function checkRespuesta($respuesta) {
|
||||
return preg_match("/^\d{1,4}$/", $respuesta);
|
||||
}
|
||||
|
||||
//Firma
|
||||
function checkFirmaComposicion($firma) {
|
||||
return preg_match("/^[a-zA-Z0-9\/+]{32}$/", $firma);
|
||||
}
|
||||
|
||||
//AutCode
|
||||
function checkAutCode($id_trans) {
|
||||
return preg_match("/^.{0,6}$/", $id_trans);
|
||||
}
|
||||
|
||||
//Nombre del Comecio
|
||||
function checkNombreComecio($nombre) {
|
||||
return preg_match("/^\w*$/", $nombre);
|
||||
}
|
||||
|
||||
//Terminal
|
||||
function checkTerminal($terminal) {
|
||||
return preg_match("/^\d{1,3}$/", $terminal);
|
||||
}
|
||||
|
||||
|
||||
function getVersionClave() {
|
||||
return "HMAC_SHA256_V1";
|
||||
}
|
||||
|
||||
///////////////////// FUNCIONES DE LOG
|
||||
|
||||
function make_seed() {
|
||||
|
||||
list($usec, $sec) = explode(' ', microtime());
|
||||
return (float) $sec + ((float) $usec * 100000);
|
||||
|
||||
}
|
||||
|
||||
function generateIdLog($logLevel, $logString, $idCart = NULL, $force = false) {
|
||||
|
||||
($idCart == NULL) ? srand(make_seed()) : srand(intval($idCart));
|
||||
|
||||
$stringLength = strlen ( $logString );
|
||||
$idLog = '';
|
||||
|
||||
for($i = 0; $i < 30; $i ++) {
|
||||
|
||||
$idLog .= $logString [rand ( 0, $stringLength - 1 )];
|
||||
}
|
||||
|
||||
$GLOBALS["logLevel"] = (int)$logLevel;
|
||||
return $idLog;
|
||||
|
||||
}
|
||||
|
||||
function escribirLog($tipo, $idLog, $texto, $logLevel = NULL, $method = NULL) {
|
||||
|
||||
$log = wc_get_logger();
|
||||
$context = array( 'source' => 'REDSYS' );
|
||||
|
||||
$logfilename = dirname(__FILE__).'/../logs/redsysLog.log';
|
||||
$level = $logLevel ?: $GLOBALS["logLevel"];
|
||||
|
||||
(is_null($method)) ? ($methodLog = "") : ($methodLog = $method . " -- ");
|
||||
|
||||
$logEntry = $idLog . ' -- ' . $methodLog . $texto;
|
||||
|
||||
switch ($level) {
|
||||
case 0:
|
||||
|
||||
if ($tipo == "ERROR") {
|
||||
$log->error($logEntry, $context);
|
||||
file_put_contents($logfilename, date('M d Y G:i:s') . ' -- [' . $tipo . ']' . ' -- ' . $logEntry . "\r\n", is_file($logfilename)?FILE_APPEND:0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
$logEntry = $idLog . ' -- ' . $methodLog . $texto;
|
||||
|
||||
if ($tipo == "ERROR") {
|
||||
$log->error($logEntry, $context);
|
||||
file_put_contents($logfilename, date('M d Y G:i:s') . ' -- [' . $tipo . ']' . ' -- ' . $logEntry . "\r\n", is_file($logfilename)?FILE_APPEND:0);
|
||||
|
||||
} else if ($tipo == "INFO ") {
|
||||
$log->info($logEntry, $context);
|
||||
file_put_contents($logfilename, date('M d Y G:i:s') . ' -- [' . $tipo . ']' . ' -- ' . $logEntry . "\r\n", is_file($logfilename)?FILE_APPEND:0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
if ($tipo == "ERROR") {
|
||||
|
||||
$log->error($logEntry, $context);
|
||||
file_put_contents($logfilename, date('M d Y G:i:s') . ' -- [' . $tipo . ']' . ' -- ' . $logEntry . "\r\n", is_file($logfilename)?FILE_APPEND:0);
|
||||
|
||||
} else if ($tipo == "INFO ") {
|
||||
|
||||
$log->info($logEntry, $context);
|
||||
file_put_contents($logfilename, date('M d Y G:i:s') . ' -- [' . $tipo . ']' . ' -- ' . $logEntry . "\r\n", is_file($logfilename)?FILE_APPEND:0);
|
||||
|
||||
} else if ($tipo == "DEBUG") {
|
||||
|
||||
$log->debug($logEntry, $context);
|
||||
file_put_contents($logfilename, date('M d Y G:i:s') . ' -- [' . $tipo . ']' . ' -- ' . $logEntry . "\r\n", is_file($logfilename)?FILE_APPEND:0);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
# Nothing to do here...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** FUNCIONES COMUNES */
|
||||
|
||||
function generaNumeroPedido($idCart, $tipo, $pedidoExtendido = false) {
|
||||
|
||||
switch (intval($tipo)) {
|
||||
case 0 : // Hibrido
|
||||
$out = str_pad ( $idCart . "z" . time()%1000, 12, "0", STR_PAD_LEFT );
|
||||
$outExtended = str_pad ( $idCart . "z" . time()%1000, 4, "0", STR_PAD_LEFT );
|
||||
|
||||
break;
|
||||
case 1 : // idCart de la Tienda
|
||||
$out = str_pad ( intval($idCart), 12, "0", STR_PAD_LEFT );
|
||||
$outExtended = str_pad ( intval($idCart), 4, "0", STR_PAD_LEFT );
|
||||
|
||||
break;
|
||||
case 2: // Aleatorio
|
||||
mt_srand(time(), MT_RAND_MT19937);
|
||||
|
||||
$out = mt_rand (100000000000, 999999999999);
|
||||
$outExtended = mt_rand (1000, PHP_INT_MAX);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$out = (strlen($out) <= 12) ? $out : substr($out, -12);
|
||||
return ($pedidoExtendido) ? $outExtended : $out;
|
||||
}
|
||||
|
||||
function createMerchantData($moduleComent, $idCart) {
|
||||
|
||||
$data = (object) [
|
||||
'moduleComent' => $moduleComent,
|
||||
'idCart' => $idCart
|
||||
];
|
||||
|
||||
return json_encode($data);
|
||||
}
|
||||
|
||||
function createMerchantTitular($nombre, $apellidos, $email) {
|
||||
|
||||
$nombreCompleto = $nombre . " " . $apellidos;
|
||||
$nombreAbreviado = mb_substr($nombre, 0, 1) . ". " . $apellidos;
|
||||
|
||||
if (empty($email))
|
||||
return $nombreCompleto;
|
||||
|
||||
$nombreEmail = $nombreAbreviado . " | " . $email;
|
||||
|
||||
if (strlen($nombreEmail) > 70)
|
||||
return $email;
|
||||
else
|
||||
return $nombreEmail;
|
||||
|
||||
}
|
||||
|
||||
/** MONEDA */
|
||||
|
||||
function currency_code($currency) {
|
||||
$currency_codes = array(
|
||||
'ALL' => 8,
|
||||
'DZD' => 12,
|
||||
'AOK' => 24,
|
||||
'MON' => 30,
|
||||
'AZM' => 31,
|
||||
'ARS' => 32,
|
||||
'AUD' => 36,
|
||||
'BSD' => 44,
|
||||
'BHD' => 48,
|
||||
'BDT' => 50,
|
||||
'AMD' => 51,
|
||||
'BBD' => 52,
|
||||
'BMD' => 60,
|
||||
'BTN' => 64,
|
||||
'BOP' => 68,
|
||||
'BAD' => 70,
|
||||
'BWP' => 72,
|
||||
'BRC' => 76,
|
||||
'BZD' => 84,
|
||||
'SBD' => 90,
|
||||
'BND' => 96,
|
||||
'BGL' => 100,
|
||||
'BUK' => 104,
|
||||
'BIF' => 108,
|
||||
'BYB' => 112,
|
||||
'KHR' => 116,
|
||||
'CAD' => 124,
|
||||
'CAD' => 124,
|
||||
'CVE' => 132,
|
||||
'LKR' => 144,
|
||||
'CLP' => 152,
|
||||
'CLP' => 152,
|
||||
'CNY' => 156,
|
||||
'CNH' => 157,
|
||||
'COP' => 170,
|
||||
'COP' => 170,
|
||||
'KMF' => 174,
|
||||
'ZRZ' => 180,
|
||||
'CRC' => 188,
|
||||
'CRC' => 188,
|
||||
'CUP' => 192,
|
||||
'CYP' => 196,
|
||||
'CSK' => 200,
|
||||
'CZK' => 203,
|
||||
'DKK' => 208,
|
||||
'DOP' => 214,
|
||||
'ECS' => 218,
|
||||
'SVC' => 222,
|
||||
'GQE' => 226,
|
||||
'ETB' => 230,
|
||||
'ERN' => 232,
|
||||
'FKP' => 238,
|
||||
'FJD' => 242,
|
||||
'DJF' => 262,
|
||||
'GEL' => 268,
|
||||
'GMD' => 270,
|
||||
'DDM' => 278,
|
||||
'GHC' => 288,
|
||||
'GIP' => 292,
|
||||
'GTQ' => 320,
|
||||
'GNS' => 324,
|
||||
'GYD' => 328,
|
||||
'HTG' => 332,
|
||||
'HNL' => 340,
|
||||
'HKD' => 344,
|
||||
'HUF' => 348,
|
||||
'ISK' => 352,
|
||||
'INR' => 356,
|
||||
'ISK' => 356,
|
||||
'IDR' => 360,
|
||||
'IRR' => 364,
|
||||
'IRA' => 365,
|
||||
'IQD' => 368,
|
||||
'ILS' => 376,
|
||||
'JMD' => 388,
|
||||
'JPY' => 392,
|
||||
'JPY' => 392,
|
||||
'KZT' => 398,
|
||||
'JOD' => 400,
|
||||
'KES' => 404,
|
||||
'KPW' => 408,
|
||||
'KRW' => 410,
|
||||
'KWD' => 414,
|
||||
'KGS' => 417,
|
||||
'LAK' => 418,
|
||||
'LBP' => 422,
|
||||
'LSM' => 426,
|
||||
'LVL' => 428,
|
||||
'LRD' => 430,
|
||||
'LYD' => 434,
|
||||
'LTL' => 440,
|
||||
'MOP' => 446,
|
||||
'MGF' => 450,
|
||||
'MWK' => 454,
|
||||
'MYR' => 458,
|
||||
'MVR' => 462,
|
||||
'MLF' => 466,
|
||||
'MTL' => 470,
|
||||
'MRO' => 478,
|
||||
'MUR' => 480,
|
||||
'MXP' => 484,
|
||||
'MXN' => 484,
|
||||
'MNT' => 496,
|
||||
'MDL' => 498,
|
||||
'MAD' => 504,
|
||||
'MZM' => 508,
|
||||
'OMR' => 512,
|
||||
'NAD' => 516,
|
||||
'NPR' => 524,
|
||||
'ANG' => 532,
|
||||
'AWG' => 533,
|
||||
'NTZ' => 536,
|
||||
'VUV' => 548,
|
||||
'NZD' => 554,
|
||||
'NIC' => 558,
|
||||
'NGN' => 566,
|
||||
'NOK' => 578,
|
||||
'PCI' => 582,
|
||||
'PKR' => 586,
|
||||
'PAB' => 590,
|
||||
'PGK' => 598,
|
||||
'PYG' => 600,
|
||||
'PEI' => 604,
|
||||
'PEI' => 604,
|
||||
'PHP' => 608,
|
||||
'PLZ' => 616,
|
||||
'TPE' => 626,
|
||||
'QAR' => 634,
|
||||
'ROL' => 642,
|
||||
'RUB' => 643,
|
||||
'RWF' => 646,
|
||||
'SHP' => 654,
|
||||
'STD' => 678,
|
||||
'SAR' => 682,
|
||||
'SCR' => 690,
|
||||
'SLL' => 694,
|
||||
'SGD' => 702,
|
||||
'SKK' => 703,
|
||||
'VND' => 704,
|
||||
'SIT' => 705,
|
||||
'SOS' => 706,
|
||||
'ZAR' => 710,
|
||||
'ZWD' => 716,
|
||||
'YDD' => 720,
|
||||
'SSP' => 728,
|
||||
'SDP' => 736,
|
||||
'SDA' => 737,
|
||||
'SRG' => 740,
|
||||
'SZL' => 748,
|
||||
'SEK' => 752,
|
||||
'CHF' => 756,
|
||||
'CHF' => 756,
|
||||
'SYP' => 760,
|
||||
'TJR' => 762,
|
||||
'THB' => 764,
|
||||
'TOP' => 776,
|
||||
'TTD' => 780,
|
||||
'AED' => 784,
|
||||
'TND' => 788,
|
||||
'TRL' => 792,
|
||||
'PTL' => 793,
|
||||
'TMM' => 795,
|
||||
'UGS' => 800,
|
||||
'UAK' => 804,
|
||||
'MKD' => 807,
|
||||
'RUR' => 810,
|
||||
'EGP' => 818,
|
||||
'GBP' => 826,
|
||||
'TZS' => 834,
|
||||
'USD' => 840,
|
||||
'UYP' => 858,
|
||||
'UYP' => 858,
|
||||
'UZS' => 860,
|
||||
'VEB' => 862,
|
||||
'WST' => 882,
|
||||
'YER' => 886,
|
||||
'YUD' => 890,
|
||||
'YUG' => 891,
|
||||
'ZMK' => 892,
|
||||
'TWD' => 901,
|
||||
'TMT' => 934,
|
||||
'GHS' => 936,
|
||||
'RSD' => 941,
|
||||
'MZN' => 943,
|
||||
'AZN' => 944,
|
||||
'RON' => 946,
|
||||
'TRY' => 949,
|
||||
'TRY' => 949,
|
||||
'XAF' => 950,
|
||||
'XCD' => 951,
|
||||
'XOF' => 952,
|
||||
'XPF' => 953,
|
||||
'XEU' => 954,
|
||||
'ZMW' => 967,
|
||||
'SRD' => 968,
|
||||
'MGA' => 969,
|
||||
'AFN' => 971,
|
||||
'TJS' => 972,
|
||||
'AOA' => 973,
|
||||
'BYR' => 974,
|
||||
'BGN' => 975,
|
||||
'CDF' => 976,
|
||||
'BAM' => 977,
|
||||
'EUR' => 978,
|
||||
'UAH' => 980,
|
||||
'GEL' => 981,
|
||||
'PLN' => 985,
|
||||
'BRL' => 986,
|
||||
'BRL' => 986,
|
||||
'ZAL' => 991,
|
||||
'EEK' => 2333,
|
||||
);
|
||||
|
||||
return array_key_exists($currency, $currency_codes) ? $currency_codes[$currency] : 0;
|
||||
}
|
||||
|
||||
/** ENCODES ADICIONALES */
|
||||
|
||||
function b64url_encode($data) {
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
function b64url_decode($data) {
|
||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
|
||||
}
|
||||
210
wp-content/plugins/informatiq-eb-redsys/includes/api/sha256.php
Normal file
210
wp-content/plugins/informatiq-eb-redsys/includes/api/sha256.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
// Abstract base class for hash data
|
||||
if (!class_exists('hashData')) {
|
||||
class hashData {
|
||||
var $hash = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Abstract base class for hash
|
||||
if (!class_exists('hash')) {
|
||||
class hash {
|
||||
public function hash($str, $mode = 'hex') {
|
||||
trigger_error('hash::hash() NOT IMPLEMENTED', E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function hashChunk($str, $length, $mode = 'hex') {
|
||||
trigger_error('hash::hashChunk() NOT IMPLEMENTED', E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function hashFile($filename, $mode = 'hex') {
|
||||
trigger_error('hash::hashFile() NOT IMPLEMENTED', E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function hashChunkFile($filename, $length, $mode = 'hex') {
|
||||
trigger_error('hash::hashChunkFile() NOT IMPLEMENTED', E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SHA256Data class
|
||||
if (!class_exists('SHA256Data')) {
|
||||
class SHA256Data extends hashData {
|
||||
var $buf = array();
|
||||
var $chunks = null;
|
||||
|
||||
function __construct($str) {
|
||||
$M = strlen($str);
|
||||
$L1 = ($M >> 28) & 0x0000000F;
|
||||
$L2 = $M << 3;
|
||||
$l = pack('N*', $L1, $L2);
|
||||
|
||||
$k = $L2 + 64 + 1 + 511;
|
||||
$k -= $k % 512 + $L2 + 64 + 1;
|
||||
$k >>= 3;
|
||||
|
||||
$str .= chr(0x80) . str_repeat(chr(0), $k) . $l;
|
||||
|
||||
preg_match_all('#.{64}#', $str, $this->chunks);
|
||||
$this->chunks = $this->chunks[0];
|
||||
|
||||
// H(0)
|
||||
$this->hash = array(
|
||||
1779033703, -1150833019,
|
||||
1013904242, -1521486534,
|
||||
1359893119, -1694144372,
|
||||
528734635, 1541459225
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SHA256 class
|
||||
if (!class_exists('SHA256')) {
|
||||
class SHA256 extends hash {
|
||||
private static $K = array(
|
||||
1116352408, 1899447441, -1245643825, -373957723,
|
||||
961987163, 1508970993, -1841331548, -1424204075,
|
||||
-670586216, 310598401, 607225278, 1426881987,
|
||||
1925078388, -2132889090, -1680079193, -1046744716,
|
||||
-459576895, -272742522, 264347078, 604807628,
|
||||
770255983, 1249150122, 1555081692, 1996064986,
|
||||
-1740746414, -1473132947, -1341970488, -1084653625,
|
||||
-958395405, -710438585, 113926993, 338241895,
|
||||
666307205, 773529912, 1294757372, 1396182291,
|
||||
1695183700, 1986661051, -2117940946, -1838011259,
|
||||
-1564481375, -1474664885, -1035236496, -949202525,
|
||||
-778901479, -694614492, -200395387, 275423344,
|
||||
430227734, 506948616, 659060556, 883997877,
|
||||
958139571, 1322822218, 1537002063, 1747873779,
|
||||
1955562222, 2024104815, -2067236844, -1933114872,
|
||||
-1866530822, -1538233109, -1090935817, -965641998
|
||||
);
|
||||
|
||||
public function hash($str, $mode = 'hex') {
|
||||
static $modes = array('hex', 'bin', 'bit');
|
||||
$ret = false;
|
||||
|
||||
if (!in_array(strtolower($mode), $modes)) {
|
||||
trigger_error('mode specified is unrecognized: ' . $mode, E_USER_WARNING);
|
||||
} else {
|
||||
$data = new SHA256Data($str);
|
||||
self::compute($data);
|
||||
|
||||
$func = 'hash' . $mode;
|
||||
if (method_exists($this, $func)) {
|
||||
$ret = self::$func($data);
|
||||
} else {
|
||||
trigger_error('SHA256::' . $func . '() NOT IMPLEMENTED.', E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private static function sum() {
|
||||
$T = 0;
|
||||
for ($x = 0, $y = func_num_args(); $x < $y; $x++) {
|
||||
$a = func_get_arg($x);
|
||||
$c = 0;
|
||||
|
||||
for ($i = 0; $i < 32; $i++) {
|
||||
$j = (($T >> $i) & 1) + (($a >> $i) & 1) + $c;
|
||||
$c = ($j >> 1) & 1;
|
||||
$j &= 1;
|
||||
$T &= ~(1 << $i);
|
||||
$T |= $j << $i;
|
||||
}
|
||||
}
|
||||
return $T;
|
||||
}
|
||||
|
||||
private static function compute(&$hashData) {
|
||||
static $vars = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
|
||||
|
||||
$W = array();
|
||||
for ($i = 0, $numChunks = sizeof($hashData->chunks); $i < $numChunks; $i++) {
|
||||
for ($j = 0; $j < 8; $j++) {
|
||||
${$vars[$j]} = $hashData->hash[$j];
|
||||
}
|
||||
|
||||
for ($j = 0; $j < 64; $j++) {
|
||||
if ($j < 16) {
|
||||
$chunk = $hashData->chunks[$i];
|
||||
$T1 = ord($chunk[$j * 4]) & 0xFF;
|
||||
$T1 <<= 8;
|
||||
$T1 |= ord($chunk[$j * 4 + 1]) & 0xFF;
|
||||
$T1 <<= 8;
|
||||
$T1 |= ord($chunk[$j * 4 + 2]) & 0xFF;
|
||||
$T1 <<= 8;
|
||||
$T1 |= ord($chunk[$j * 4 + 3]) & 0xFF;
|
||||
$W[$j] = $T1;
|
||||
} else {
|
||||
$W[$j] = self::sum(
|
||||
((($W[$j - 2] >> 17) & 0x00007FFF) | ($W[$j - 2] << 15)) ^
|
||||
((($W[$j - 2] >> 19) & 0x00001FFF) | ($W[$j - 2] << 13)) ^
|
||||
(($W[$j - 2] >> 10) & 0x003FFFFF),
|
||||
$W[$j - 7],
|
||||
((($W[$j - 15] >> 7) & 0x01FFFFFF) | ($W[$j - 15] << 25)) ^
|
||||
((($W[$j - 15] >> 18) & 0x00003FFF) | ($W[$j - 15] << 14)) ^
|
||||
(($W[$j - 15] >> 3) & 0x1FFFFFFF),
|
||||
$W[$j - 16]
|
||||
);
|
||||
}
|
||||
|
||||
$T1 = self::sum(
|
||||
$h,
|
||||
((($e >> 6) & 0x03FFFFFF) | ($e << 26)) ^
|
||||
((($e >> 11) & 0x001FFFFF) | ($e << 21)) ^
|
||||
((($e >> 25) & 0x0000007F) | ($e << 7)),
|
||||
($e & $f) ^ (~$e & $g),
|
||||
self::$K[$j],
|
||||
$W[$j]
|
||||
);
|
||||
|
||||
$T2 = self::sum(
|
||||
((($a >> 2) & 0x3FFFFFFF) | ($a << 30)) ^
|
||||
((($a >> 13) & 0x0007FFFF) | ($a << 19)) ^
|
||||
((($a >> 22) & 0x000003FF) | ($a << 10)),
|
||||
($a & $b) ^ ($a & $c) ^ ($b & $c)
|
||||
);
|
||||
|
||||
$h = $g;
|
||||
$g = $f;
|
||||
$f = $e;
|
||||
$e = self::sum($d, $T1);
|
||||
$d = $c;
|
||||
$c = $b;
|
||||
$b = $a;
|
||||
$a = self::sum($T1, $T2);
|
||||
}
|
||||
|
||||
for ($j = 0; $j < 8; $j++) {
|
||||
$hashData->hash[$j] = self::sum(${$vars[$j]}, $hashData->hash[$j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function hashHex(&$hashData) {
|
||||
$str = '';
|
||||
reset($hashData->hash);
|
||||
do {
|
||||
$str .= sprintf('%08x', current($hashData->hash));
|
||||
} while (next($hashData->hash));
|
||||
return $str;
|
||||
}
|
||||
|
||||
private static function hashBin(&$hashData) {
|
||||
$str = '';
|
||||
reset($hashData->hash);
|
||||
do {
|
||||
$str .= pack('N', current($hashData->hash));
|
||||
} while (next($hashData->hash));
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class EB_Redsys_Payment_Gateway {
|
||||
|
||||
private $api;
|
||||
private $test_mode;
|
||||
private $merchant_code;
|
||||
private $terminal;
|
||||
private $encryption_key;
|
||||
|
||||
public function __construct() {
|
||||
$this->id = 'redsys';
|
||||
$this->title = __('Credit Card (Redsys)', 'eb-redsys-gateway');
|
||||
$this->description = __('Pay securely via credit card using Redsys.', 'eb-redsys-gateway');
|
||||
|
||||
// Load settings
|
||||
$this->test_mode = get_option('eb_redsys_test_mode', 'yes');
|
||||
$this->merchant_code = get_option('eb_redsys_merchant_code');
|
||||
$this->terminal = get_option('eb_redsys_terminal');
|
||||
$this->encryption_key = get_option('eb_redsys_encryption_key');
|
||||
|
||||
// Initialize API
|
||||
$this->api = new Redsys_API();
|
||||
|
||||
// Hooks
|
||||
add_action('eb_payment_gateway_redsys', array($this, 'process_payment'));
|
||||
add_action('eb_payment_gateway_redsys_callback', array($this, 'process_callback'));
|
||||
}
|
||||
|
||||
public function get_endpoint() {
|
||||
return ($this->test_mode === 'yes')
|
||||
? 'https://sis-t.redsys.es:25443/sis/realizarPago'
|
||||
: 'https://sis.redsys.es/sis/realizarPago';
|
||||
}
|
||||
|
||||
public function process_payment($booking_data) {
|
||||
$order_id = $booking_data['booking_id'];
|
||||
$amount = $booking_data['amount'];
|
||||
|
||||
// Prepare payment data
|
||||
$payment_data = array(
|
||||
'DS_MERCHANT_AMOUNT' => $amount * 100, // Amount in cents
|
||||
'DS_MERCHANT_ORDER' => $order_id,
|
||||
'DS_MERCHANT_MERCHANTCODE' => $this->merchant_code,
|
||||
'DS_MERCHANT_CURRENCY' => '978', // EUR
|
||||
'DS_MERCHANT_TRANSACTIONTYPE' => '0', // Authorization
|
||||
'DS_MERCHANT_TERMINAL' => $this->terminal,
|
||||
'DS_MERCHANT_MERCHANTURL' => add_query_arg('gateway', 'redsys', eb_get_callback_url()),
|
||||
'DS_MERCHANT_URLOK' => add_query_arg('result', 'success', eb_get_return_url($order_id)),
|
||||
'DS_MERCHANT_URLKO' => add_query_arg('result', 'failure', eb_get_return_url($order_id))
|
||||
);
|
||||
|
||||
// For future dated payments
|
||||
if (!empty($booking_data['check_in_date'])) {
|
||||
$payment_data['DS_MERCHANT_DATEFRECUENCY'] = '1'; // Daily frequency
|
||||
$payment_data['DS_MERCHANT_CHARGEEXPIRYDATE'] = date('d/m/Y', strtotime($booking_data['check_in_date']));
|
||||
$payment_data['DS_MERCHANT_TRANSACTIONTYPE'] = 'L'; // Deferred payment
|
||||
}
|
||||
|
||||
// Generate signature
|
||||
$signature = $this->api->createMerchantSignature($this->encryption_key, $payment_data);
|
||||
|
||||
// Build form
|
||||
$form = '<form method="post" id="redsys-payment-form" action="' . esc_url($this->get_endpoint()) . '">';
|
||||
$form .= '<input type="hidden" name="Ds_SignatureVersion" value="HMAC_SHA256_V1">';
|
||||
$form .= '<input type="hidden" name="Ds_MerchantParameters" value="' . $this->api->createMerchantParameters($payment_data) . '">';
|
||||
$form .= '<input type="hidden" name="Ds_Signature" value="' . $signature . '">';
|
||||
$form .= '</form>';
|
||||
$form .= '<script>document.getElementById("redsys-payment-form").submit();</script>';
|
||||
|
||||
echo $form;
|
||||
exit;
|
||||
}
|
||||
|
||||
public function process_callback() {
|
||||
$params = $_POST['Ds_MerchantParameters'];
|
||||
$signature = $_POST['Ds_Signature'];
|
||||
|
||||
// Verify signature
|
||||
if (!$this->api->check_signature($params, $signature, $this->encryption_key)) {
|
||||
wp_die('Invalid signature', 'Redsys Error', array('response' => 403));
|
||||
}
|
||||
|
||||
$response = $this->api->decode_parameters($params);
|
||||
|
||||
// Check response code
|
||||
if ($response['Ds_Response'] < 100) {
|
||||
// Payment successful
|
||||
$order_id = $response['Ds_Order'];
|
||||
$transaction_id = $response['Ds_AuthorisationCode'];
|
||||
|
||||
// Update booking status
|
||||
eb_update_booking_status($order_id, 'completed', $transaction_id);
|
||||
|
||||
echo "OK"; // Response to Redsys
|
||||
exit;
|
||||
}
|
||||
|
||||
// Payment failed
|
||||
$order_id = $response['Ds_Order'];
|
||||
eb_update_booking_status($order_id, 'failed');
|
||||
|
||||
echo "KO";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Core payment processing functions for Redsys gateway
|
||||
*/
|
||||
class EB_Redsys_Payment_Functions {
|
||||
|
||||
private static $instance = null;
|
||||
private $api;
|
||||
|
||||
public static function get_instance() {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private function __construct() {
|
||||
// Initialize Redsys API
|
||||
require_once EB_REDSYS_PATH . 'includes/api/apiRedsysFinal.php';
|
||||
$this->api = new RedsysAPI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process standard payment
|
||||
*/
|
||||
public function process_standard_payment($booking_data) {
|
||||
try {
|
||||
$params = $this->prepare_payment_params($booking_data);
|
||||
return $this->send_payment_request($params);
|
||||
} catch (Exception $e) {
|
||||
$this->log_error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process future dated payment
|
||||
*/
|
||||
public function process_future_payment($booking_data) {
|
||||
try {
|
||||
$params = $this->prepare_payment_params($booking_data);
|
||||
|
||||
// Add future payment parameters
|
||||
$params['DS_MERCHANT_TRANSACTIONTYPE'] = 'L'; // Deferred payment
|
||||
$params['DS_MERCHANT_DATEFRECUENCY'] = '1'; // Daily
|
||||
$params['DS_MERCHANT_CHARGEEXPIRYDATE'] = date('d/m/Y', strtotime($booking_data['check_in_date']));
|
||||
|
||||
return $this->send_payment_request($params);
|
||||
} catch (Exception $e) {
|
||||
$this->log_error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process subscription payment
|
||||
*/
|
||||
public function process_subscription_payment($booking_data) {
|
||||
try {
|
||||
$params = $this->prepare_payment_params($booking_data);
|
||||
|
||||
// Add subscription parameters
|
||||
$params['DS_MERCHANT_TRANSACTIONTYPE'] = 'L';
|
||||
$params['DS_MERCHANT_COF_INI'] = 'S'; // Initial recurring payment
|
||||
$params['DS_MERCHANT_COF_TYPE'] = 'R'; // Recurring payment type
|
||||
|
||||
return $this->send_payment_request($params);
|
||||
} catch (Exception $e) {
|
||||
$this->log_error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process subsequent subscription payment
|
||||
*/
|
||||
public function process_subscription_renewal($booking_data, $reference_id) {
|
||||
try {
|
||||
$params = $this->prepare_payment_params($booking_data);
|
||||
|
||||
// Add subsequent payment parameters
|
||||
$params['DS_MERCHANT_TRANSACTIONTYPE'] = '0';
|
||||
$params['DS_MERCHANT_IDENTIFIER'] = $reference_id;
|
||||
$params['DS_MERCHANT_DIRECTPAYMENT'] = 'true';
|
||||
|
||||
return $this->send_payment_request($params);
|
||||
} catch (Exception $e) {
|
||||
$this->log_error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare common payment parameters
|
||||
*/
|
||||
private function prepare_payment_params($booking_data) {
|
||||
return array(
|
||||
'DS_MERCHANT_AMOUNT' => $this->format_amount($booking_data['amount']),
|
||||
'DS_MERCHANT_ORDER' => $this->generate_order_number($booking_data['booking_id']),
|
||||
'DS_MERCHANT_MERCHANTCODE' => get_option('eb_redsys_merchant_code'),
|
||||
'DS_MERCHANT_CURRENCY' => '978', // EUR
|
||||
'DS_MERCHANT_TERMINAL' => get_option('eb_redsys_terminal'),
|
||||
'DS_MERCHANT_MERCHANTURL' => $this->get_notification_url($booking_data['booking_id']),
|
||||
'DS_MERCHANT_URLOK' => $this->get_return_url($booking_data['booking_id'], 'success'),
|
||||
'DS_MERCHANT_URLKO' => $this->get_return_url($booking_data['booking_id'], 'failure')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send payment request to Redsys
|
||||
*/
|
||||
private function send_payment_request($params) {
|
||||
$version = "HMAC_SHA256_V1";
|
||||
$key = get_option('eb_redsys_encryption_key');
|
||||
|
||||
// Create merchant parameters
|
||||
$merchant_params = $this->api->createMerchantParameters($params);
|
||||
|
||||
// Create merchant signature
|
||||
$signature = $this->api->createMerchantSignature($key, $merchant_params);
|
||||
|
||||
return array(
|
||||
'endpoint' => $this->get_endpoint(),
|
||||
'params' => array(
|
||||
'Ds_SignatureVersion' => $version,
|
||||
'Ds_MerchantParameters' => $merchant_params,
|
||||
'Ds_Signature' => $signature
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process Redsys notification
|
||||
*/
|
||||
public function process_notification($data) {
|
||||
try {
|
||||
$key = get_option('eb_redsys_encryption_key');
|
||||
$merchant_params = $data['Ds_MerchantParameters'];
|
||||
$signature = $data['Ds_Signature'];
|
||||
|
||||
// Validate signature
|
||||
if (!$this->api->check_signature($merchant_params, $signature, $key)) {
|
||||
throw new Exception('Invalid signature');
|
||||
}
|
||||
|
||||
// Decode parameters
|
||||
$decoded_params = $this->api->decodeMerchantParameters($merchant_params);
|
||||
|
||||
// Check response code
|
||||
$response_code = $decoded_params['Ds_Response'];
|
||||
if ($response_code < 100) {
|
||||
// Payment successful
|
||||
$order_id = $this->extract_booking_id($decoded_params['Ds_Order']);
|
||||
$transaction_id = $decoded_params['Ds_AuthorisationCode'];
|
||||
|
||||
// Store card reference for future payments if available
|
||||
if (isset($decoded_params['Ds_Merchant_Identifier'])) {
|
||||
$this->store_card_reference(
|
||||
$order_id,
|
||||
$decoded_params['Ds_Merchant_Identifier']
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'success' => true,
|
||||
'booking_id' => $order_id,
|
||||
'transaction_id' => $transaction_id
|
||||
);
|
||||
}
|
||||
|
||||
throw new Exception("Payment failed with code: $response_code");
|
||||
|
||||
} catch (Exception $e) {
|
||||
$this->log_error($e->getMessage());
|
||||
return array('success' => false, 'error' => $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store card reference for future payments
|
||||
*/
|
||||
private function store_card_reference($booking_id, $reference) {
|
||||
update_post_meta($booking_id, '_redsys_card_reference', $reference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stored card reference
|
||||
*/
|
||||
public function get_card_reference($booking_id) {
|
||||
return get_post_meta($booking_id, '_redsys_card_reference', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Redsys endpoint based on mode
|
||||
*/
|
||||
private function get_endpoint() {
|
||||
return (get_option('eb_redsys_test_mode') === 'yes')
|
||||
? 'https://sis-t.redsys.es:25443/sis/realizarPago'
|
||||
: 'https://sis.redsys.es/sis/realizarPago';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format amount for Redsys (in cents)
|
||||
*/
|
||||
private function format_amount($amount) {
|
||||
return number_format($amount * 100, 0, '', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate unique order number
|
||||
*/
|
||||
private function generate_order_number($booking_id) {
|
||||
return sprintf('%010d', $booking_id) . date('is');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notification URL
|
||||
*/
|
||||
private function get_notification_url($booking_id) {
|
||||
return add_query_arg(array(
|
||||
'eb-api' => 'redsys',
|
||||
'booking_id' => $booking_id
|
||||
), home_url('/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get return URL
|
||||
*/
|
||||
private function get_return_url($booking_id, $result) {
|
||||
return add_query_arg(array(
|
||||
'booking_id' => $booking_id,
|
||||
'result' => $result
|
||||
), eb_get_checkout_url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract booking ID from order number
|
||||
*/
|
||||
private function extract_booking_id($order_number) {
|
||||
return intval(substr($order_number, 0, 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log error message
|
||||
*/
|
||||
private function log_error($message) {
|
||||
if (function_exists('eb_log')) {
|
||||
eb_log('Redsys Error: ' . $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize payment functions
|
||||
function eb_redsys_payment() {
|
||||
return EB_Redsys_Payment_Functions::get_instance();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
?>
|
||||
<div id="eb-tab-redsys" class="payment-tab">
|
||||
<div class="payment-tab-content">
|
||||
<h3><?php esc_html_e('Pay with Credit Card', 'eb-redsys-gateway') ?></h3>
|
||||
<p><?php esc_html_e('You will be redirected to Redsys secure payment page to complete your purchase.', 'eb-redsys-gateway') ?></p>
|
||||
|
||||
<?php if (get_option('eb_redsys_test_mode') === 'yes'): ?>
|
||||
<div class="eb-alert eb-alert-warning">
|
||||
<?php esc_html_e('Test mode is enabled. Use test card details for payments.', 'eb-redsys-gateway') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form id="eb-redsys-payment-form" method="post" action="<?php echo esc_url(eb_checkout_url()) ?>">
|
||||
<input type="hidden" name="eb_arrive" value="1">
|
||||
<input type="hidden" name="eagle_booking_payment_method" value="redsys">
|
||||
<?php wp_nonce_field('eb_payment_nonce', 'eb_payment_nonce'); ?>
|
||||
<button type="submit" class="btn"><?php esc_html_e('Proceed to Payment', 'eb-redsys-gateway') ?></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
?>
|
||||
<li>
|
||||
<a href="#eb-tab-redsys" class="payment-method" data-gateway="redsys">
|
||||
<?php esc_html_e('Credit Card (Redsys)', 'eb-redsys-gateway') ?>
|
||||
<img src="<?php echo EB_REDSYS_URL; ?>assets/images/cards.png" alt="Credit Cards">
|
||||
</a>
|
||||
</li>
|
||||
Reference in New Issue
Block a user