<?php
/**
* My Calendar Submission Payment Processing
*
* @category Payments
* @package My Calendar Pro
* @author Joe Dolson
* @license GPLv2 or later
* @link https://www.joedolson.com/my-calendar-pro/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Get receipt ID and verify
*/
function mcs_verify_receipt() {
global $wpdb;
if ( isset( $_GET['mcs_receipt'] ) ) {
$receipt = ( isset( $_GET['mcs_receipt'] ) ) ? sanitize_text_field( wp_unslash( $_GET['mcs_receipt'] ) ) : false;
$email = ( isset( $_POST['mcs_email'] ) ) ? sanitize_text_field( is_email( $_POST['mcs_email'] ) ) : false;
if ( $receipt && $email ) {
if ( wp_verify_nonce( $_POST['_wpnonce'], 'mcs_receipt_nonce' ) ) {
$result = $wpdb->get_var( $wpdb->prepare( 'SELECT id FROM ' . my_calendar_payments_table() . ' WHERE hash = %s AND payer_email = %s', $receipt, $email ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( $result ) {
if ( version_compare( PHP_VERSION, '7.3.0', '>' ) ) {
// Fix syntax.
$options = array(
'expires' => time() + 60 * 60,
'path' => COOKIEPATH,
'domain' => COOKIE_DOMAIN,
'secure' => false,
'httponly' => true,
'samesite' => 'Lax',
);
setcookie( 'mcs_receipt', 'true', $options );
} else {
setcookie( 'mcs_receipt', 'true', time() + 60 * 60, COOKIEPATH, COOKIE_DOMAIN, false, true );
}
}
wp_safe_redirect( add_query_arg( 'mcs_receipt', $receipt, home_url() ) );
}
}
}
}
/**
* Print receipt header.
*/
function mcs_receipt_header() {
$url = plugin_dir_url( __FILE__ );
global $mcs_version;
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<meta name="viewport" content="width=device-width" />
<title><?php bloginfo( 'name' ); ?> - <?php esc_html_e( 'My Calendar Pro: Receipt', 'my-calendar-pro' ); ?></title>
<meta name="generator" content="My Calendar for WordPress" />
<meta name="robots" content="noindex,nofollow" />
<?php
if ( function_exists( 'mc_file_exists' ) && mc_file_exists( 'mcs-receipt.css' ) ) {
$stylesheet = mc_get_file( 'mcs-receipt.css', 'url' );
} else {
$stylesheet = $url . 'css/mcs-receipt.css';
}
?>
<!-- Copy mcs-receipt.css to your theme directory if you wish to replace the default print styles -->
<link rel='stylesheet' href='<?php echo esc_url( add_query_arg( 'version', $mcs_version, $stylesheet ) ); ?>' />
</head>
<body>
<div class='mcs-receipt'>
<?php
mcs_receipt_logo();
}
/**
* Print custom receipt logo section.
*/
function mcs_receipt_logo() {
$logo = get_custom_logo();
if ( ! $logo ) {
// translators: 1) link to site home; 2) name of site.
$logo = sprintf( '<h1><a href="%1$s">%2$s</a></h1>', home_url(), get_bloginfo( 'blogname' ) );
/**
* Filter the site name on receipts.
*
* @hook mcs_receipt_logo
*
* @param {string} $logo Site name wrapped in link to home and h1 element. Does not include logo.
*
* @return {string}
*/
$logo = apply_filters( 'mcs_receipt_logo', $logo );
} else {
$logo = '<h1>' . $logo . '</h1>';
}
?>
<header class="mcs-receipt-header">
<?php echo wp_kses_post( $logo ); ?>
</header>
<main>
<?php
}
/**
* Print receipt footer.
*/
function mcs_receipt_footer() {
?>
</main>
<footer>
<p><?php esc_html_e( 'Receipt generated by My Calendar Pro', 'my-calendar-pro' ); ?></p>
</footer>
</div>
</body>
</html>
<?php
}
add_filter( 'mcs_receipt_template', 'wpautop' );
/**
* Display the receipt for purchase of event submission
*/
function mcs_show_receipt() {
// verify validity of viewer.
if ( isset( $_GET['mcs_receipt'] ) && isset( $_COOKIE['mcs_receipt'] ) && 'true' === $_COOKIE['mcs_receipt'] ) {
global $wpdb;
$receipt_id = sanitize_text_field( wp_unslash( $_GET['mcs_receipt'] ) );
$query = 'SELECT * FROM ' . my_calendar_payments_table() . ' WHERE hash = %s';
$results = $wpdb->get_row( $wpdb->prepare( $query, $receipt_id ), ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$template = '
<h2>' . __( 'Payment Key Purchase Receipt', 'my-calendar-pro' ) . '</h2>
<strong>Purchased By</strong><span> {first_name} {last_name}</span>
<strong>Transaction ID</strong><span> {txn_id}</span>
<strong>Payment Key</strong><span> {hash}</span>
<strong>Payer Email</strong><span> {payer_email}</span>
<strong>Amount Paid</strong><span> ${price}</span>
<strong>Submissions Granted</strong><span> {total}</span>
<strong>Submissions Remaining</strong><span> {quantity}</span>
<strong>Transaction Date</strong><span> {transaction_date}</span>';
$template = apply_filters( 'mcs_receipt_template', $template, $results );
mcs_receipt_header();
echo wp_kses( mc_draw_template( $results, $template ), mc_kses_elements() );
echo '<a href="javascript:window.print()">' . esc_html__( 'Print Receipt', 'my-calendar-pro' ) . '</a>';
mcs_receipt_footer();
exit;
} elseif ( isset( $_GET['mcs_receipt'] ) ) {
$nonce = wp_create_nonce( 'mcs_receipt_nonce' );
mcs_receipt_header();
?>
<form action='' method='POST'>
<input type='hidden' name='_wpnonce' value='<?php echo esc_attr( $nonce ); ?>' />
<div>
<label for='mcs-email'>Your purchase email</label>
<input type='email' name='mcs_email' id='mcs-email' autocomplete='email' />
<input type='submit' name='mcs-verify' value='<?php esc_html_e( 'Verify Email', 'my-calendar-pro' ); ?>' />
</div>
</form>
<?php
mcs_receipt_footer();
exit;
}
}
add_action( 'init', 'mcs_setup_gateway' );
/**
* Gateway setup function.
*/
function mcs_setup_gateway() {
$gateway = get_option( 'mcs_gateway' );
switch ( $gateway ) {
case 'paypal':
require_once 'gateways/my-calendar-paypal.php';
break;
case 'stripe':
require_once 'gateways/my-calendar-stripe.php';
break;
}
// Support for custom gatways.
do_action( 'mcs_enqueue_gateway', $gateway );
}
/**
* Process IPN data returned from payment gateways
*/
function mcs_receive_ipn() {
if ( isset( $_GET['mcsipn'] ) && 'true' === $_GET['mcsipn'] ) {
mcs_check();
$gateway = get_option( 'mcs_gateway' );
do_action( 'mcs_process_payment', $gateway );
}
}
/**
* Map statuses from Auth.net to match PayPal responses.
*
* @param integer $status Auth.net response ID.
*
* @return string
*/
function mcs_map_status( $status ) {
switch ( $status ) {
case 1:
$response = 'Completed';
break;
case 2:
$response = 'Declined';
break;
case 3:
$response = 'Error';
break;
case 4:
$response = 'Held for Review';
break;
default:
$response = 'Completed';
}
return $response;
}
/**
* Insert new payment into database and send notifications.
*
* @param array $values Values passed from gateway.
* @param string $status Status of this payment.
*
* @return string status
*/
function mcs_process_payment( $values, $status ) {
$item_number = $values['item_number'];
$txn_id = $values['txn_id'];
$price = $values['price'];
$mc_fee = $values['mc_fee'];
$payer_first = $values['payer_first'];
$payer_last = $values['payer_last'];
$payer_email = $values['payer_email'];
$payment = mcs_get_payment( $item_number, $txn_id );
if ( $payment ) {
$post = array(
'price' => $price,
'first_name' => $payer_first,
'last_name' => $payer_last,
'email' => $payer_email,
'fee' => $mc_fee,
'txn_id' => $txn_id,
'item_number' => $item_number,
'status' => $status,
);
$args = mcs_update_payment( $post, $payment );
if ( isset( $args['status'] ) && 'Completed' === $args['status'] ) {
$status = 'Completed';
}
} else {
$post = array(
'price' => $price,
'first_name' => $payer_first,
'last_name' => $payer_last,
'email' => $payer_email,
'fee' => $mc_fee,
'txn_id' => $txn_id,
'item_number' => $item_number,
'status' => $status,
);
$args = mcs_create_payment( $post );
}
if ( 'Completed' === $status ) {
$notifications = mcs_send_notifications( $args );
setcookie( 'mcs_receipt', 'true', time() + 60 * 60, COOKIEPATH, COOKIE_DOMAIN, false, true );
}
return $status;
}
/**
* Get payment based on item number or txn id.
*
* @param int $item_number Post ID.
* @param string $txn_id Transaction ID (from payment gateway.).
*
* @return array
*/
function mcs_get_payment( $item_number = false, $txn_id = false ) {
// get payment based on either item number or txnid.
global $wpdb;
if ( $item_number || $txn_id ) {
$result = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_payments_table() . ' WHERE id = %d', $item_number ), 'ARRAY_A' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( $result ) {
return $result;
} else {
$result = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_payments_table() . ' WHERE txn_id = %s', $txn_id ), 'ARRAY_A' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( $result ) {
return $result;
}
}
}
return false;
}
/**
* Delete a payment.
*
* @param int $payment_id Payment ID.
*
* @return string
*/
function mcs_delete_payment( $payment_id ) {
// get payment based on either item number or txnid.
global $wpdb;
if ( $payment_id ) {
$result = $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . my_calendar_payments_table() . ' WHERE id = %d', $payment_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( $result ) {
return __( 'Payment record deleted.', 'my-calendar-pro' );
}
}
return false;
}
/**
* Update a payment.
*
* @param array $post Post data.
* @param array|int $payment Payment array or payment ID.
*
* @return array|false
*/
function mcs_update_payment( $post, $payment ) {
if ( ! $payment ) {
return false;
}
if ( is_numeric( $payment ) ) {
$post = array_merge( $post, array( 'item_number' => $payment ) );
$payment = mcs_get_payment( $payment );
}
if ( ! is_array( $payment ) ) {
return false;
}
global $wpdb;
// Price & Quantity minimum values available.
$quantity = ( isset( $post['quantity'] ) ) ? (int) $post['quantity'] : $payment['quantity'];
$total = ( isset( $post['total'] ) ) ? (int) $post['total'] : $quantity;
if ( $total !== $quantity ) {
// If we change the total purchased, increment up the quantity available to match.
$quantity = $quantity + ( $total - $quantity );
}
$price = sprintf( '%01.2f', $post['price'] );
$first_name = ( isset( $post['first_name'] ) ) ? $post['first_name'] : '';
$last_name = ( isset( $post['last_name'] ) ) ? $post['last_name'] : '';
$email = ( isset( $post['email'] ) ) ? is_email( $post['email'] ) : '';
$txn_id = ( isset( $post['txn_id'] ) ) ? $post['txn_id'] : 'Manual Entry';
$status = ( isset( $post['status'] ) ) ? $post['status'] : 'Completed';
$fee = ( isset( $post['mc_fee'] ) ) ? $post['mc_fee'] : '0.00';
$metadata = ( isset( $post['metadata'] ) ) ? $post['metadata'] : array();
// Commented out keys are in Payment but not updated.
$update = array(
// 'item_number' => $post['item_number'],.
// 'event_id' => 0,.
// 'hash' => '',
// 'transaction_date' => '',.
'quantity' => $quantity,
'total' => $total,
'txn_id' => $txn_id,
'price' => $price,
'fee' => '0.00',
'status' => $status,
'first_name' => $first_name,
'last_name' => $last_name,
'payer_email' => $email,
'gateway' => get_option( 'mcs_gateway' ),
'metadata' => serialize( $metadata ),
);
if ( isset( $payment['id'] ) ) {
unset( $payment['id'] );
}
$update = array_merge( $payment, $update );
$formats = array(
'%d', // Item Number.
'%d', // Event ID.
'%d', // Quantity.
'%d', // Total count.
'%s', // Hash.
'%s', // Txn ID.
'%f', // Price.
'%f', // Fee.
'%s', // Status.
'%s', // Transaction Date.
'%s', // First Name.
'%s', // Last Name.
'%s', // Payer Email.
'%s', // Gateway.
'%s', // Metadata.
);
$update = $wpdb->update( my_calendar_payments_table(), $update, array( 'id' => $post['item_number'] ), $formats );
$id = $wpdb->insert_id;
$args = array(
'first' => $first_name,
'last' => $last_name,
'email' => $email,
'price' => $price,
'hash' => $payment['hash'],
'quantity' => $quantity,
'id' => $id,
'status' => $status,
);
return $args;
}
/**
* Update a single payment field.
*
* @param int $item_number Payment ID.
* @param string $field Field name.
* @param string|int|float $value Field value.
*
* @return bool|int
*/
function mcs_update_payment_field( $item_number, $field, $value ) {
global $wpdb;
$update = array(
$field => $value,
);
switch ( $field ) {
case 'hash':
case 'transaction_date':
case 'txn_id':
case 'status':
case 'first_name':
case 'last_name':
case 'payer_email':
case 'gateway':
case 'metadata':
$format = array( '%s' );
break;
case 'quantity':
$format = array( '%d' );
break;
case 'item_number':
case 'event_id':
case 'total':
case 'price':
case 'fee':
$format = array( '%f' );
break;
}
$result = $wpdb->update( my_calendar_payments_table(), $update, array( 'id' => $item_number ), $format );
return $result;
}
/**
* Get the value of a single payment field.
*
* @param int $item_number Payment ID.
* @param string $field Field name.
*
* @return string|int|float
*/
function mcs_get_payment_field( $item_number, $field ) {
global $wpdb;
switch ( $field ) {
case 'hash':
case 'transaction_date':
case 'txn_id':
case 'status':
case 'first_name':
case 'last_name':
case 'payer_email':
case 'gateway':
case 'metadata':
case 'quantity':
case 'item_number':
case 'event_id':
case 'total':
case 'price':
case 'fee':
$field_name = $field;
break;
default:
$field_name = false;
}
if ( ! $field_name ) {
return $item_number;
}
$value = $wpdb->get_var( $wpdb->prepare( 'SELECT ' . $field_name . ' FROM ' . my_calendar_payments_table() . ' WHERE id = %d', $item_number ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
return $value;
}
/**
* Send notifications about completed purchases.
*
* @param array $args Array of passed values.
*/
function mcs_send_notifications( $args = array() ) {
// Define message variables.
$first = $args['first'];
$last = $args['last'];
$email = $args['email'];
$price = $args['price'];
$hash = $args['hash'];
$quantity = $args['quantity'];
$blogname = get_option( 'blogname' );
$receipt = add_query_arg( 'mcs_receipt', $hash, home_url() );
$search = array(
'first_name' => $first,
'last_name' => $last,
'blogname' => $blogname,
'price' => $price,
'key' => $hash,
'quantity' => $quantity,
'receipt' => $receipt,
);
$mail_from = "From: $blogname Events <" . get_option( 'mcs_from', get_option( 'admin_email' ) ) . '>';
$admin_subject = get_option( 'mcs_payment_subject' );
$client_subject = get_option( 'mcs_payment_confirmation_subject' );
// Draw templates.
$admin_subject = mc_draw_template( $search, $admin_subject );
$client_subject = mc_draw_template( $search, $client_subject );
$admin_body = mc_draw_template( $search, get_option( 'mcs_payment_response' ) );
$client_body = mc_draw_template( $search, get_option( 'mcs_payment_confirmation' ) );
$send_html = false;
$warning = '';
if ( 'true' === get_option( 'mcs_html_email' ) ) {
add_filter( 'wp_mail_content_type', 'mcs_html_email' );
$send_html = true;
}
$client = wp_mail( $email, $client_subject, $client_body, $mail_from );
if ( ! $client ) {
// Translators: Purchaser email address.
$warning = ' ' . sprintf( __( 'There was an error sending the purchaser email notification. You will need to contact the purchaser directly at %s', 'my-calendar-pro' ), $email );
$warning = ( $send_html ) ? wpautop( $warning ) : $warning . "\n\n";
}
$admin_email = get_option( 'mcs_to', get_option( 'admin_email' ) );
wp_mail( $admin_email, $admin_subject, $warning . $admin_body, $mail_from );
if ( 'true' === get_option( 'mcs_html_email' ) ) {
remove_filter( 'wp_mail_content_type', 'mcs_html_email' );
}
}
/**
* Check Unique ID in the database
*
* @param string $hash Saved key.
* @param int $i Check number.
*
* @return string
*/
function mcs_uniqid( $hash, $i = 1 ) {
global $wpdb;
$sql = $wpdb->prepare( 'SELECT hash FROM ' . my_calendar_payments_table() . ' WHERE hash=%s', $hash ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( $wpdb->get_var( $sql ) ) { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$hash = uniqid( 'E' . $i );
mcs_uniqid( $hash, $i++ );
} else {
return $hash;
}
}
/**
* Set cURL to use SSL version supporting TLS 1.2
*
* @param object $handle CURL object.
*/
function mcs_http_api_curl( $handle ) {
curl_setopt( $handle, CURLOPT_SSLVERSION, 6 );
}
add_action( 'http_api_curl', 'mcs_http_api_curl' );
/**
* Submit payment form
*/
function mcs_payment_form() {
$ret = '';
$form = '';
$gateway = get_option( 'mcs_gateway' );
if ( isset( $_GET['response_code'] ) ) {
$mcs = sanitize_text_field( $_GET['response_code'] );
$item = isset( $_GET['item_number'] ) ? absint( $_GET['item_number'] ) : '';
$payment = mcs_get_payment( $item );
$ret = apply_filters( 'mcs_gateway_response', '', $mcs, $payment, $gateway );
}
if ( mcs_payment_required() ) {
$price = mcs_get_price();
$currency = get_option( 'mcs_currency' );
$discounts = mcs_check_discount();
if ( is_array( $discounts ) ) {
$discount_rate = (int) $discounts['rate'];
$discount = ( 0 !== $discount_rate ) ? true : false;
$begins = $discounts['begins'];
$ends = $discounts['ends'];
} else {
$discount_rate = 0;
$discount = false;
$begins = '';
$ends = '';
}
if ( isset( $_GET['response_code'] ) ) {
$message = '';
} else {
$message = wpautop(
mc_draw_template(
array(
'price' => $price,
'currency' => $currency,
'discount' => $discount_rate,
'begins' => $begins,
'ends' => $ends,
),
get_option( 'mcs_payment_message' )
)
);
}
$nonce = wp_create_nonce( 'mcs-payments-nonce' );
$args = array(
'nonce' => $nonce,
'price' => $price,
'discount' => $discount,
'discount_rate' => $discount_rate,
'discounts' => $discounts,
'currency' => $currency,
);
$form = "<div class='mc-payments-form " . esc_attr( $gateway ) . "'>$ret$message";
$form .= '<div class="mc-create-purchase">';
$form .= mcs_set_quantity_form( $price );
$form .= "</div><div class='mc-payment-form'>";
$form .= apply_filters( 'mcs_payment_gateway', '', $gateway, $args );
$form .= '</div></div>';
}
return $form;
}
add_shortcode( 'submit_payment', 'mcs_payment_form' );
/**
* Get information about purchase.
*/
function mcs_purchase_request() {
if ( isset( $_REQUEST['action'] ) && 'mcs_purchase_request' === $_REQUEST['action'] ) {
$quantity = ( isset( $_REQUEST['quantity'] ) ) ? absint( $_REQUEST['quantity'] ) : 1;
$security = $_REQUEST['security'];
$payment_id = ( is_numeric( $_REQUEST['payment_id'] ) ) ? absint( $_REQUEST['payment_id'] ) : false;
if ( ! wp_verify_nonce( $security, 'mc-query-purchase' ) ) {
wp_send_json(
array(
'success' => 0,
'response' => '',
'payment_id' => $payment_id,
)
);
}
if ( isset( $_REQUEST['payer_name'] ) && isset( $_REQUEST['payer_email'] ) ) {
// We're updating data in an existing payment.
$name = sanitize_text_field( wp_unslash( $_REQUEST['payer_name'] ) );
$email = sanitize_email( wp_unslash( $_REQUEST['payer_email'] ) );
$names = explode( ' ', $name );
$first = array_shift( $names );
$last = implode( ' ', $names );
mcs_update_payment_field( $payment_id, 'payer_email', $email );
mcs_update_payment_field( $payment_id, 'first_name', $first );
mcs_update_payment_field( $payment_id, 'last_name', $last );
wp_send_json(
array(
'success' => 1,
'response' => 'Saved',
'payment_id' => $payment_id,
)
);
}
$price = mcs_get_price();
$total = ( $price * $quantity );
$post = array(
'quantity' => $quantity,
'price' => $total,
'txn_id' => '--',
'status' => 'Pending',
'item_number' => $payment_id,
);
if ( ! is_numeric( $payment_id ) ) {
$insert = mcs_create_payment( $post );
} else {
$insert = mcs_update_payment( $post, $payment_id );
}
$gateway = get_option( 'mcs_gateway' );
if ( 'stripe' === $gateway ) {
$total = ( mcs_zerodecimal_currency() ) ? $total : $total * 100;
$intent = mcs_generate_intent( $total, $insert['id'] );
$post['metadata'] = serialize( array( 'intent_id' => $intent->id ) );
mcs_update_payment( $post, $insert['id'] );
}
$insert_id = $insert['id'];
$response = array(
'success' => 1,
'response' => $price,
'payment_id' => $insert_id,
);
if ( 'stripe' === $gateway && is_object( $intent ) ) {
$response['client_secret'] = $intent->client_secret;
}
wp_send_json( $response );
}
}
add_action( 'wp_ajax_mcs_purchase_request', 'mcs_purchase_request' );
add_action( 'wp_ajax_nopriv_mcs_purchase_request', 'mcs_purchase_request' );
/**
* Check whether payment is required to submit.
*
* @return boolean
*/
function mcs_payment_required() {
$enabled = ( 'true' === get_option( 'mcs_payments' ) ) ? true : false;
if ( current_user_can( 'manage_options' ) || ! $enabled ) {
$return = false;
} else {
if ( ( ! is_user_logged_in() ) || ( is_user_logged_in() && get_option( 'mcs_members_discount' ) < 100 ) ) {
$return = true;
} else {
$return = false;
}
}
return apply_filters( 'mcs_payment_required', $return );
}
add_action( 'admin_notices', 'mcs_stripe_requires_ssl' );
/**
* Stripe only functions under SSL. Notify user that this is required.
*/
function mcs_stripe_requires_ssl() {
global $current_screen;
if ( stripos( $current_screen->id, 'my-calendar-pro' ) ) {
if ( 0 === stripos( home_url(), 'https' ) || 'true' !== get_option( 'mcs_payments' ) ) {
return;
} else {
wp_admin_notice(
__( 'Payment processing requires an SSL Certificate. Please switch your site to HTTPS. <a href="https://wordpress.org/support/article/https-for-wordpress/">How to switch WordPress to HTTPS</a>', 'my-calendar-pro' ),
array(
'type' => 'error',
'additional_classes' => array( 'my-calendar-pro' ),
)
);
}
}
}
/**
* Check for a user discount.
*
* @param string $role Filtered variable for user roles.
*
* @return mixed float/boolean Value of discount.
*/
function mcs_check_discount( $role = 'auto' ) {
$discounts = get_option( 'mcs_discount' );
$discounts = apply_filters( 'mcs_alter_discount', $discounts, $role );
if ( $discounts ) {
$on_sale = mcs_on_sale( $discounts );
if ( $on_sale ) {
return $discounts;
} else {
return false;
}
}
return false;
}
/**
* Calculate the price to add an event.
*
* @param int $quantity How many event keys to buy.
* @param float $price Price per event.
* @param boolean $discount User has discount.
* @param float $discount_rate Percentage discount.
*
* @return float.
*/
function mcs_calculate_price( $quantity, $price, $discount, $discount_rate ) {
$total = $price * $quantity;
if ( $discount ) {
$total = $price * $discount_rate;
}
return $total;
}
/**
* Show quantity form to select a number of keys to buy.
*
* @param float $price Price per event.
*
* @return string
*/
function mcs_set_quantity_form( $price ) {
$currency = get_option( 'mcs_currency' );
$form = "<form action='' method='POST'>
<input type='hidden' name='mcs_payment_id' id='mcs_payment_id' value='' />
<div>
<label for='mcs_quantity'>" . __( 'Number of events?', 'my-calendar-pro' ) . "</label>
<input type='number' name='mcs_quantity' value='1' min='1' id='mcs_quantity' />
</div>
<div>
<button type='button' class='mc-purchase-key' name='mcs_set_quantity'>" . __( 'Go to Payment', 'my-calendar-pro' ) . "</button>
</div>
</form>
<div class='mcs-payment-total' role='alert'>
<strong>" . __( 'Total:', 'my-calendar-pro' ) . '</strong> ' .
// Translators: Count, Price per, Total price.
sprintf( __( '%1$s at %2$s: %3$s', 'my-calendar-pro' ), '<span class="mcs-event-count">1</span>', '<span class="mcs-event-currency">' . mcs_symbols( $currency ) . '</span><span class="mcs-event-price">' . $price . '</span>', '<span class="mcs-event-currency">' . mcs_symbols( $currency ) . '</span><strong class="mcs-event-total">' . $price . '</strong>' ) . '
</div>';
return $form;
}
/**
* Is there a sale on?
*
* @param array $discounts Discount information.
*
* @return boolean
*/
function mcs_on_sale( $discounts ) {
if ( ! isset( $discounts['begins'] ) || ! isset( $discounts['ends'] ) || ! isset( $discounts['rate'] ) ) {
$return = false;
}
if ( '' === $discounts['begins'] ) {
$return = false;
}
$end = ( '' === $discounts['ends'] ) ? mcs_date( 'Y-m-d', time() + 60 * 60 * 24 * 7 ) : $discounts['ends'];
if ( function_exists( 'my_calendar_date_xcomp' ) ) {
if ( my_calendar_date_xcomp( $discounts['begins'], mcs_date( 'Y-m-d', time() ) ) && my_calendar_date_xcomp( mcs_date( 'Y-m-d', time() ), $end ) && (int) $discounts['rate'] > 0 ) {
$return = true;
}
} else {
$return = false;
}
return $return;
}
/**
* Get event submission price.
*
* @return float.
*/
function mcs_get_price() {
$logged_in = ( is_admin() ) ? true : is_user_logged_in();
$price = apply_filters( 'mcs_get_price', get_option( 'mcs_submission_fee' ) );
if ( $logged_in ) {
$discounts = mcs_check_discount();
if ( is_array( $discounts ) ) {
$discount = $discounts['rate'];
$discounted = ( 0 !== $discount ) ? $price - ( $price * ( $discount / 100 ) ) : $price;
$price = $discounted;
}
}
return (float) sprintf( '%01.2f', $price );
}
add_action( 'wp_enqueue_scripts', 'mcs_payments_enqueue_scripts' );
/**
* Enqueue payment gateway scripts.
*/
function mcs_payments_enqueue_scripts() {
if ( ! mcs_user_can_submit_events() ) {
return;
}
global $mcs_version;
if ( SCRIPT_DEBUG && true === SCRIPT_DEBUG ) {
$mcs_version = $mcs_version . uniqid();
}
$stripe_options = get_option( 'mcs_stripe' );
$gateway = get_option( 'mcs_gateway' );
wp_enqueue_script( 'mcs-payments', plugins_url( 'js/mcs-payments.js', __FILE__ ), array( 'jquery' ), $mcs_version, true );
if ( ! empty( $stripe_options ) && 'stripe' === $gateway ) {
// check if we are using test mode.
if ( 'true' === get_option( 'mcs_use_sandbox' ) ) {
$publishable = trim( $stripe_options['test_public'] );
} else {
$publishable = trim( $stripe_options['prod_public'] );
}
wp_enqueue_style( 'mcs.stripe.css', plugins_url( 'css/stripe.css', __FILE__ ) );
wp_enqueue_script( 'stripe', 'https://js.stripe.com/v3/' );
wp_enqueue_script( 'mcs.stripe', plugins_url( 'js/stripe.js', __FILE__ ), array( 'jquery', 'mcs-payments' ), $mcs_version, true );
$url = ( is_numeric( get_option( 'mcs_submit_id' ) ) ) ? get_permalink( get_option( 'mcs_submit_id' ) ) : home_url();
$return_url = add_query_arg(
array(
'response_code' => 'thanks',
'gateway' => 'stripe',
'item_number' => '%d',
),
$url
);
wp_localize_script(
'mcs.stripe',
'mcs_stripe',
array(
'publishable_key' => $publishable,
'currency' => get_option( 'mcs_currency', 'USD' ),
'purchase_descriptor' => __( 'Calendar Submissions Order', 'my-calendar-pro' ),
'return_url' => $return_url,
'selected' => __( 'Selected', 'my-calendar-pro' ),
'processing' => __( 'Processing...', 'my-calendar-pro' ),
'pay' => __( 'Pay Now', 'my-calendar-pro' ),
'success' => __( 'Successful Payment', 'my-calendar-pro' ),
)
);
}
}
/**
* Is the current currency a zerodecimal type.
*
* @return bool
*/
function mcs_zerodecimal_currency() {
$currency = get_option( 'mcs_currency', 'USD' );
$currencies = mcs_currency();
$data = $currencies[ $currency ];
if ( isset( $data['zerodecimal'] ) && true === $data['zerodecimal'] ) {
return true;
}
return false;
}
/**
* UPdate the available quantity on this key.
*
* @param string $key Purchase key.
* @param int $quantity How many events to adjust.
*
* @return integer update result
*/
function mcs_update_key_quantity( $key, $quantity ) {
global $wpdb;
$data = array(
'quantity' => $quantity - 1,
);
$formats = array( '%d' );
$result = $wpdb->update(
my_calendar_payments_table(),
$data,
array(
'hash' => $key,
),
$formats,
'%s'
);
return $result;
}
/**
* Verify validity of a key.
*
* @param string $key Purchase key.
*
* @return int|false
*/
function mcs_check_key( $key ) {
if ( ! $key ) {
return false;
}
global $wpdb;
$sql = 'SELECT quantity FROM ' . my_calendar_payments_table() . " WHERE hash = %s AND status = 'Completed'";
$quantity = $wpdb->get_var( $wpdb->prepare( $sql, $key ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( ! $quantity || 0 === $quantity ) {
$return = false;
} else {
$return = $quantity;
}
/**
* Filter payment key response. Can add checks against other posted data, e.g. email, etc.
*
* @hook mcs_check_key
*
* @param {int|false} $return Number of events available or false.
* @param {string} $key Key to check.
*
* @return {int|false}
*/
return apply_filters( 'mcs_check_key', $return, $key );
}
/**
* Get the status of a purchase key.
*
* @param string $key Purchase key.
*
* @return boolean
*/
function mcs_key_status( $key ) {
if ( ! $key ) {
return false;
}
global $wpdb;
$sql = 'SELECT quantity,status FROM ' . my_calendar_payments_table() . ' WHERE hash = %s';
$key = $wpdb->get_row( $wpdb->prepare( $sql, $key ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if ( ! $key ) {
$return = __( 'That payment key does not exist', 'my-calendar-pro' );
} elseif ( 0 === (int) $key->quantity ) {
$return = __( 'Your payment key has been used up!', 'my-calendar-pro' );
} elseif ( 'Completed' !== $key->status ) {
// Translators: Payment key status.
$return = sprintf( __( 'Your payment key status is "%s".', 'my-calendar-pro' ), $key->status );
}
return $return;
}