258 lines
8.2 KiB
PHP
258 lines
8.2 KiB
PHP
|
|
<?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();
|
||
|
|
}
|