Autosave: 20260326-125529

This commit is contained in:
Flatlogic Bot 2026-03-26 12:55:30 +00:00
parent 6c0871c2d4
commit 0fd548462a
405 changed files with 77435 additions and 0 deletions

View File

@ -0,0 +1,129 @@
<?php
/**
* Plugin Name: Coach Payment Cards
* Description: Styles the Book Session test payment products as site-matching cards.
*/
add_action('wp_enqueue_scripts', function () {
if (!is_page('book-session')) {
return;
}
wp_register_style('coach-payment-cards', false, [], null);
wp_enqueue_style('coach-payment-cards');
$css = <<<'CSS'
body.coaching-mvp-active .coach-payment-section {
margin-top: clamp(1rem, 2vw, 1.5rem) !important;
}
body.coaching-mvp-active .coach-payment-section > .wp-block-group__inner-container {
display: grid;
gap: 1rem;
}
body.coaching-mvp-active .coach-payment-section h2.wp-block-heading {
margin: 0 !important;
max-width: 14ch;
font-size: clamp(2rem, 4.3vw, 3rem) !important;
line-height: .98 !important;
letter-spacing: -.04em !important;
}
body.coaching-mvp-active .coach-payment-section > .wp-block-group__inner-container > p:not(.coach-badge) {
max-width: 42rem;
margin: 0 !important;
color: var(--coach-muted) !important;
}
body.coaching-mvp-active .coach-payment-note {
padding: 1rem 1.1rem !important;
}
body.coaching-mvp-active .coach-payment-note p {
margin: 0 !important;
color: var(--coach-text) !important;
}
body.coaching-mvp-active .coach-payment-grid,
body.coaching-mvp-active .coach-payment-grid > .wp-block-group__inner-container {
display: grid !important;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1rem;
}
body.coaching-mvp-active .coach-payment-grid > .wp-block-group__inner-container > * {
margin: 0 !important;
}
body.coaching-mvp-active .coach-payment-grid .asp_product_item {
display: flex;
flex-direction: column;
gap: .9rem;
min-height: 100%;
margin: 0 !important;
padding: clamp(1.2rem, 2.2vw, 1.45rem) !important;
background: var(--coach-surface) !important;
border: 1px solid var(--coach-border) !important;
border-radius: 8px !important;
box-shadow: none !important;
}
body.coaching-mvp-active .coach-payment-grid .asp_product_item_top {
display: block !important;
}
body.coaching-mvp-active .coach-payment-grid .asp_product_item_thumbnail,
body.coaching-mvp-active .coach-payment-grid .asp_under_price_line,
body.coaching-mvp-active .coach-payment-grid .asp_product_description:empty,
body.coaching-mvp-active .coach-payment-grid .asp_product_item > div[style*="clear:both"] {
display: none !important;
}
body.coaching-mvp-active .coach-payment-grid .asp_product_name {
margin: 0 !important;
color: var(--coach-text) !important;
font-size: clamp(1.14rem, 1.8vw, 1.34rem) !important;
line-height: 1.18 !important;
font-weight: 600 !important;
letter-spacing: -.02em !important;
}
body.coaching-mvp-active .coach-payment-grid .asp_price_container {
margin-top: auto;
padding-top: .25rem;
}
body.coaching-mvp-active .coach-payment-grid .asp_price_amount {
display: inline-block;
color: var(--coach-text) !important;
font-size: clamp(1.75rem, 3vw, 2.2rem) !important;
line-height: 1 !important;
font-weight: 700 !important;
letter-spacing: -.04em !important;
}
body.coaching-mvp-active .coach-payment-grid .asp_product_buy_button {
margin-top: .1rem;
}
body.coaching-mvp-active .coach-payment-grid .asp_all_buttons_container,
body.coaching-mvp-active .coach-payment-grid .asp_product_buy_btn_container {
width: 100%;
}
body.coaching-mvp-active .coach-payment-grid .asp_product_buy_btn {
width: 100%;
min-height: 48px;
padding: .85rem 1rem !important;
border-radius: 6px !important;
border: 1px solid var(--coach-border) !important;
background: var(--color-button-secondary-bg) !important;
color: var(--color-button-secondary-text) !important;
box-shadow: none !important;
font-weight: 600 !important;
transition: border-color .16s ease, background-color .16s ease, color .16s ease, opacity .16s ease !important;
}
body.coaching-mvp-active .coach-payment-grid .asp_product_buy_btn:hover,
body.coaching-mvp-active .coach-payment-grid .asp_product_buy_btn:focus-visible {
background: var(--color-button-secondary-hover-bg) !important;
border-color: var(--coach-border) !important;
color: var(--coach-text) !important;
}
@media (max-width: 781px) {
body.coaching-mvp-active .coach-payment-section {
padding: 1rem !important;
}
body.coaching-mvp-active .coach-payment-grid,
body.coaching-mvp-active .coach-payment-grid > .wp-block-group__inner-container {
grid-template-columns: 1fr;
}
}
CSS;
wp_add_inline_style('coach-payment-cards', $css);
}, 30);

View File

@ -0,0 +1,104 @@
<?php
/**
* Plugin Name: Accept Stripe Payments
* Description: Easily accept credit card payments via Stripe payment gateway in WordPress.
* Version: 2.0.96
* Author: Tips and Tricks HQ, wptipsntricks
* Author URI: https://www.tipsandtricks-hq.com/
* Plugin URI: https://s-plugins.com
* License: GPLv2 or later
* Text Domain: stripe-payments
* Domain Path: /languages
*/
//Slug - asp
if ( ! defined( 'ABSPATH' ) ) {
//Exit if this file is accessed directly.
exit;
}
define( 'WP_ASP_PLUGIN_VERSION', '2.0.96' );
define( 'WP_ASP_MIN_PHP_VERSION', '7.4' );
define( 'WP_ASP_PLUGIN_URL', plugins_url( '', __FILE__ ) );
define( 'WP_ASP_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
define( 'WP_ASP_PLUGIN_FILE', __FILE__ );
define( 'WP_ASP_DEV_MODE', '1' );
class ASPMain {
public static $products_slug;
public static $temp_prod_slug;
public static $posts_processed = array();
public static $file;
public static $stripe_api_ver = '2024-12-18.acacia';
public function __construct() {
self::$products_slug = 'asp-products';
self::$temp_prod_slug = 'asp-products-temp';
self::$file = __FILE__;
if ( !defined( 'ASP_MANAGEMENT_PERMISSION' ) ){ //This will allow the user to define custom capability for this constant in wp-config file
define('ASP_MANAGEMENT_PERMISSION', 'manage_options');
}
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-utils.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-utils-misc.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-debug-logger.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-utils-bot-mitigation.php';
require_once WP_ASP_PLUGIN_PATH . 'admin/class-asp-admin.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-stripe-api.php';
require_once WP_ASP_PLUGIN_PATH . 'admin/includes/class-asp-admin-products.php';
require_once WP_ASP_PLUGIN_PATH . 'admin/includes/class-coupons.php';
require_once WP_ASP_PLUGIN_PATH . 'admin/includes/class-order.php';
require_once WP_ASP_PLUGIN_PATH . 'admin/views/blocks.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-addons-helper.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-product-item.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-payment-data.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-order-item.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-daily-txn-counter.php';
require_once WP_ASP_PLUGIN_PATH . 'admin/includes/class-variations.php';
register_activation_hook( __FILE__, array( 'AcceptStripePayments', 'activate' ) );
register_deactivation_hook( __FILE__, array( 'AcceptStripePayments', 'deactivate' ) );
add_action( 'plugins_loaded', array( 'AcceptStripePayments', 'get_instance' ) );
if ( is_admin() ) {
add_action( 'plugins_loaded', array( 'AcceptStripePayments_Admin', 'get_instance' ) );
}
require_once WP_ASP_PLUGIN_PATH . 'includes/session-handler-class.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/shortcodes/class-shortcode-asp.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/shortcodes/class-asp-shortcode-ng.php';
add_action( 'init', array( $this, 'init_handler' ), 0 );
// register custom post type
$asp_products = ASP_Admin_Products::get_instance();
add_action( 'init', array( $asp_products, 'register_post_type' ), 0 );
$asp_order = ASPOrder::get_instance();
add_action( 'init', array( $asp_order, 'register_post_type' ), 0 );
add_action( 'init', array( 'AcceptStripePaymentsShortcode', 'get_instance' ) );
add_action( 'init', array( 'ASP_Shortcode_NG', 'get_instance' ) );
}
public function init_handler() {
// hook to change product slug
self::$products_slug = apply_filters( 'asp_change_products_slug', self::$products_slug );
}
/**
* Use ASP_Utils::load_stripe_lib() instead
*/
public static function load_stripe_lib() {
ASP_Utils::load_stripe_lib();
}
}
new ASPMain();

View File

@ -0,0 +1,756 @@
/*=== Shortcode Inserter === */
i.mce-i-asp-shortcode-icon {
background-image: url(img/asp_shortcode.png);
}
.asp-shortcode-options-table input.asp-input-wide {
width: 90%;
}
table.asp-shortcode-options-table th, table.asp-shortcode-options-table td {
padding: 10px 10px 10px 0;
}
#TB_ajaxContent table.asp-shortcode-options-table p.description {
padding: 0;
}
#TB_ajaxContent #asp_form_err {
color: red;
padding: 0;
margin: 0;
}
#TB_window {
overflow: auto;
}
#TB_ajaxContent {
overflow: visible;
height: auto;
width: auto;
}
/*--- END Shortcode Inserter --- */
/*=== Product Settings === */
#asp_product_metaboxes_meta_box div.inside {
margin: 0;
padding: 0;
}
.wp-asp-product-meta-box-title {
font-size: 1.3em;
}
fieldset legend {
border-bottom: 1px solid #f7f7f7;
width: 100%;
padding: 0;
margin: 0;
padding-top: 5px;
padding-bottom: 5px;
margin-bottom: 5px;
font-weight: 600;
}
.wp-asp-product-settings-menu {
display: inline-block;
position: relative;
width: 20%;
}
.wp-asp-product-tab-item {
width: 76%;
padding-left: 2%;
padding-right: 2%;
vertical-align: top;
display: none;
padding-top: 6px;
padding-bottom: 10px;
}
.wp-asp-product-tab-item-visible {
display: inline-block;
}
#wp-asp-product-settings-menu-icon {
height: 38px;
width: 38px;
display: none;
cursor: pointer;
vertical-align: top;
position: absolute;
right: 0px;
}
#wp-asp-product-settings-menu-icon span {
vertical-align: middle;
font-size: 38px;
width: auto;
height: auto;
}
#wp-asp-product-settings-menu-icon.menu-visible {
float: none;
}
a.wp-asp-product-menu-nav-item {
border: 1px solid #e8e8e8;
border-left: none;
border-right: none;
border-top: none;
display: block;
width: 100%;
float: none;
margin: 0;
white-space: normal;
padding: 7px 0;
background-color: #f9f9f9;
}
a.wp-asp-product-menu-nav-item:hover {
background-color: #fdfdfd;
color: #2271b1;
}
a.wp-asp-product-menu-nav-item span {
padding-left: 10px;
padding-right: 10px;
display: block;
}
a.wp-asp-product-menu-nav-item:focus {
background-color: #f9f9f9;
outline: none;
box-shadow: none;
border-top: none;
}
a.wp-asp-product-menu-nav-item.nav-tab-active {
border-top: none;
background-color: #ededed;
}
a.wp-asp-product-menu-nav-item.nav-tab-active:focus {
border-top: none;
}
.asp_product_type_cont {
display: none;
}
.asp_product_type_active {
display: block;
}
.asp_product_type_select_cont label {
margin-right: 10px;
}
@media screen and (max-width: 960px) {
.wp-asp-product-settings-menu {
width: 100%;
display: block;
}
.wp-asp-product-tab-item {
width: auto;
padding: 10px 10px 15px 10px;
margin: 0 auto;
}
.wp-asp-product-tab-item input[type=text] {
width: auto;
}
a.wp-asp-product-menu-nav-item {
display: none;
}
a.wp-asp-product-menu-nav-item.nav-tab-active {
display: inline-block !important;
}
#wp-asp-product-settings-menu-icon {
display: inline-block;
}
.wp-asp-product-tab-item-visible {
display: block;
}
input[type=text] {
max-width: 100%;
}
fieldset {
width: auto;
max-width: 100%;
min-inline-size: auto;
}
.asp-variations-group-cont label {
display: block;
}
.asp-variations-group-cont .wp-asp-help {
float: none;
vertical-align: middle;
}
.asp-variations-delete-group-btn {
vertical-align: top !important;
}
}
#wp-asp-shipping-variations-tbl,
#wp-asp-tax-variations-tbl {
width: 75%;
}
#wp-asp-shipping-variations-tbl tr,
#wp-asp-tax-variations-tbl tr {
text-align: center;
}
.wp-asp-shipping-variations-input,
.wp-asp-tax-variations-input {
width: 100%;
}
.wp-asp-shipping-variations-del-btn span,
.wp-asp-tax-variations-del-btn span {
vertical-align: sub;
}
#wp-asp-shipping-variations-add-btn span,
#wp-asp-tax-variations-add-btn span {
vertical-align: middle;
}
@media screen and (max-width: 960px) {
#wp-asp-shipping-variations-tbl,
#wp-asp-tax-variations-tbl {
width: 100%;
}
#wp-asp-shipping-variations-tbl .wp-asp-shipping-variations-input,
#wp-asp-tax-variations-tbl .wp-asp-tax-variations-input{
width: 100%;
}
}
/*--- END Product Settings --- */
/*=== Product Variations === */
.asp-html-tpl {
display: none;
}
.asp-variations-group-cont {
margin-bottom: 10px;
padding: 10px;
border: 1px solid #ddd;
}
.asp-variations-group-title {
padding: 5px;
}
.asp-variations-group-name {
width: 60%;
display: inline-block;
}
.asp-variations-tbl {
margin-bottom: 5px;
}
.asp-variations-buttons-cont {
text-align: right;
}
#asp-variations-cont-main button span.dashicons {
vertical-align: middle !important;
}
#asp-variations-cont {
margin-bottom: 10px;
}
.asp-variations-tbl input[type=text] {
width: 100%;
max-width: 100%;
}
.asp-btn-small {
padding: 0 5px !important;
}
.asp-btn-small .dashicons {
font-size: 18px;
}
.asp-variations-select-from-ml-btn {
position: absolute;
top: 0;
bottom: 50%;
margin-top: 8px !important;
right: 7px;
}
.asp-variations-display-type-cont {
float: right;
}
@media screen and (max-width: 782px) {
.asp-variations-display-type-cont {
float: none;
}
.asp-variations-options-cont {
margin-top: 0.5rem;
}
}
/*--- END Variations --- */
/*=== Addons Listing === */
.stripe_addon_item_canvas {
font-family: sans-serif, arial;
font-size: 12px;
border: 1px solid #ddd;
box-sizing: border-box;
display: block;
float: left;
margin: 3px 12px 12px 0;
padding: 15px;
position: relative;
width: 300px;
height: 400px;
}
.stripe_addon_item_canvas:hover {
border-color: #d6d6d6;
}
.stripe_addon_item_thumb {
position: relative
}
.stripe-addon-item-installed-mark {
position: absolute;
right: 5px;
top: 5px;
}
.stripe-addon-item-installed-mark span {
border: none !important;
height: 50px;
color: #00e600;
font-size: 50px;
width: 50px;
}
.stripe_addon_item_thumb img {
padding: 5px;
border: 1px solid #ddd;
}
.stripe_addon_item_thumb a img {
border: 1px solid #ccc;
}
.stripe_addon_item_body {
line-height: 22px;
height: 170px;
overflow: hidden;
}
.stripe_addon_item_name {
font-size: 16px;
font-weight: bold;
text-align: center;
margin: 10px 10px 10px 0px;
}
.stripe_addon_item_description {
margin: 10px 10px 5px 0px;
text-align: justify;
overflow: hidden;
height: 70px;
}
.stripe_addon_clear {
clear: both;
}
.stripe_addon_item_details_link {
text-align: center;
}
.stripe_addon_item_details_link a {
border: 3px solid #2d3140;
color: #2d3140;
display: inline-block;
padding: 5px 15px;
text-decoration: none !important;
}
.stripe_addon_item_details_link a:hover {
background-color: #2d3140;
color: #FFF;
}
/*--- END Addons Listing --- */
/*=== Admin Inside Metabox === */
/* These can be used to style the metaboxes in admin dashboard to improve usability and appearance */
.asp-admin-metabox-subhead {
font-size: 1.1em;
font-weight: 600;
margin: 15px 0 10px 0;
}
/*--- END Admin Inside Metabox --- */
/*=== Admin Products Table === */
th.column-thumbnail {
max-width: 110px;
width: 110px;
}
th.column-title {
width: 20%;
}
th.column-shortcode {
width: 20%;
}
.column-shortcode input {
width: auto;
max-width: 100%;
}
.asp-product-thumbnail-container img {
width: 100px;
height: 100px
}
.asp-product-thumbnail-container img:hover {
box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8);
}
.asp-product-thumbnail-container a:focus {
box-shadow: none;
}
@media screen and (max-width: 782px) {
th.column-thumbnail {
display: none;
}
td.column-thumbnail {
display: none;
}
td.thumbnail.column-thumbnail::before {
content: '' !important;
}
.asp-product-thumbnail-container img {
width: 50px;
height: 50px;
}
}
/*--- END Admin Products Table --- */
/*=== Settings Page === */
div.wp-asp-settings-cont {
display: none;
}
div.wp-asp-tab-container {
display: none;
}
div.wp-asp-tab-container p.description span {
font-style: normal;
background: #e3e3e3;
padding: 2px 5px;
}
div.wp-asp-tabs {
width: 80%;
}
div.wp-asp-tabs input {
max-width: 100%;
}
div.wp-asp-tabs table {
width: 100%;
table-layout: fixed;
}
div.wp-asp-settings-sidebar-cont {
width: 19%;
float: right;
}
div.wp-asp-settings-grid {
display: inline-block;
}
div#poststuff {
min-width: 19%;
}
.wp-asp-stars-container {
text-align: center;
margin-top: 10px;
}
.wp-asp-stars-container span {
vertical-align: text-top;
color: #ffb900;
}
.wp-asp-stars-container a {
text-decoration: none;
}
div.postbox.yellowish {
background-color: #ffffc8;
}
@media (max-width: 782px) {
div.wp-asp-settings-grid {
display: block;
float: none;
width: 100%;
}
}
.asp-settings-spinner-container {
padding-bottom: 30px;
}
.asp-settings-spinner, .asp-settings-spinner:before, .asp-settings-spinner:after {
border-radius: 50%;
width: 2.5em;
height: 2.5em;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation: load7 1.8s infinite ease-in-out;
animation: load7 1.8s infinite ease-in-out;
}
.asp-settings-spinner {
color: grey;
font-size: 10px;
margin: 5px auto;
position: relative;
text-indent: -9999em;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
.asp-settings-spinner:before, .asp-settings-spinner:after {
content: '';
position: absolute;
top: 0;
}
.asp-settings-spinner:before {
left: -3.5em;
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.asp-settings-spinner:after {
left: 3.5em;
}
@-webkit-keyframes load7 {
0%, 80%, 100% {
box-shadow: 0 2.5em 0 -1.3em;
}
40% {
box-shadow: 0 2.5em 0 0;
}
}
@keyframes load7 {
0%, 80%, 100% {
box-shadow: 0 2.5em 0 -1.3em;
}
40% {
box-shadow: 0 2.5em 0 0;
}
}
/* === Hover over help hint === */
.wp-asp-help {
position: relative;
display: inline-block;
cursor: help;
vertical-align: text-bottom;
color: #aaa;
}
.wp-asp-help:hover {
color: blue;
}
.wp-asp-help .dashicons {
height: auto;
width: auto;
}
.wp-asp-help:hover .wp-asp-help-text {
visibility: visible;
}
.wp-asp-help .wp-asp-help-text p {
font-size: 0.95em;
}
.wp-asp-help .wp-asp-help-text {
font-size: 0.95em;
min-width: 200px;
top: -10px;
left: 50%;
transform: translate(-50%, -100%);
padding: 7px 10px;
color: #fff;
background-color: #111;
font-weight: normal;
border-radius: 8px;
position: absolute;
z-index: 99999999;
box-sizing: border-box;
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
visibility: hidden;
text-align: center;
}
.wp-asp-help .wp-asp-help-text::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: black transparent transparent transparent;
}
@media screen and (max-width: 782px) {
.wp-asp-help .wp-asp-help-text::after {
top: 50%;
left: 100%;
/* To the right of the tooltip */
margin-left: auto;
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent transparent black;
}
.wp-asp-help {
float: right;
}
.wp-asp-help .wp-asp-help-text {
min-width: auto;
top: 50%;
right: 100%;
left: auto;
margin-right: 10px;
transform: translate(0, -50%);
}
.wp-asp-help .dashicons {
vertical-align: bottom;
width: 30px;
height: 30px;
font-size: 200%;
}
.asp_acf_input_control span.dashicons {
vertical-align: middle;
}
}
/* END Hover over help hint */
/*--- END Settings Page --- */
/*=== Email tags hint === */
.wp-asp-tags-table-cont {
margin-top: 10px;
}
a.wp-asp-toggle {
text-decoration: none;
border-bottom: 1px dashed;
}
a.wp-asp-toggle.toggled-on::after {
content: " ↑";
}
a.wp-asp-toggle.toggled-off::after {
content: " ↓";
}
table.wp-asp-tags-hint td, table.wp-asp-tags-hint th {
padding: 5px 10px;
}
table.wp-asp-tags-hint {
background: #fff;
width: 100%;
}
table.wp-asp-tags-hint td.wp-asp-tag-name {
width: 150px;
border-bottom: 1px solid #ededed;
}
table.wp-asp-tags-hint td.wp-asp-tag-descr {
width: 70%;
border-bottom: 1px solid #ededed;
}
/*----- END Email tags hint ----- */
/*=== Allowed Currencies === */
#wp-asp-allowed-currencies-cont .wp-asp-allowed-currencies {
margin-top: 10px;
}
#wp-asp-allowed-currencies-cont .wp-asp-allowed-currencies-sel div {
display: inline-block;
line-height: 1.75em;
width: 50%;
}
.wp-asp-allowed-currencies-buttons-cont {
margin-top: 7px;
margin-bottom: 7px;
line-height: 2em;
}
.wp-asp-allowed-currencies-buttons-cont button {
margin-right: 5px;
}
@media screen and (max-width: 782px) {
#wp-asp-allowed-currencies-cont .wp-asp-allowed-currencies-sel div {
line-height: 2em;
}
}
@media screen and (max-width: 960px) {
#wp-asp-allowed-currencies-cont .wp-asp-allowed-currencies-sel div {
display: block;
width: 100%;
}
}
/*----- END Allowed Currencies ----- */
.asp-new-api-only {
color: green;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

View File

@ -0,0 +1,11 @@
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<rect fill="#fff" id="canvas_background" height="22" width="22" y="-1" x="-1"/>
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
<rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/>
</g>
</g>
<g>
<image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAAAbFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0Iv+qAAAAJHRSTlMA/pCMzgPU7jMolFQ++Mqnn2RfUC303cWwr4F5cW5bSUQ2IQpssnYVAAAAgklEQVQY04XQRw7DMAxEUY4K1ey4pvfk/neMDW9CBoj/8kHAEKK4gcpF4pCNKAcmGFJZ/MdUbo+XF+hzDWBbCbwsw3eB013ncWjkSwccox7qMcW9Wh/2M3ff6D1RagEn8GCrdFVIu+Wkk8Bmprp9C/Rj6Upa/ZBf5GCsyASm6KByzw/zBQTEfSHyvQAAAABJRU5ErkJggg==" id="svg_1" height="20" width="20" y="0" x="0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 980 B

View File

@ -0,0 +1 @@
<?php // Silence is golden

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.accordion.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-accordion{width:100%}.ui-accordion .ui-accordion-header{cursor:pointer;position:relative;margin-top:1px;zoom:1}.ui-accordion .ui-accordion-li-fix{display:inline}.ui-accordion .ui-accordion-header-active{border-bottom:0!important}.ui-accordion .ui-accordion-header a{display:block;font-size:1em;padding:.5em .5em .5em .7em}.ui-accordion-icons .ui-accordion-header a{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;margin-top:-2px;position:relative;top:1px;margin-bottom:2px;overflow:auto;display:none;zoom:1}.ui-accordion .ui-accordion-content-active{display:block}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.autocomplete.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-autocomplete{position:absolute;cursor:default}* html .ui-autocomplete{width:1px}.ui-menu{list-style:none;padding:2px;margin:0;display:block;float:left}.ui-menu .ui-menu{margin-top:-3px}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;float:left;clear:left;width:100%}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:.2em .4em;line-height:1.5;zoom:1}.ui-menu .ui-menu-item a.ui-state-hover,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.button.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;text-decoration:none!important;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.core.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px);clip:rect(1px,1px,1px,1px)}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.datepicker.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0em}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.dialog.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-dialog{position:absolute;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .1em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.progressbar.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.resizable.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.selectable.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.slider.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}

View File

@ -0,0 +1,5 @@
/*! jQuery UI - v1.8.24 - 2012-09-28
* https://github.com/jquery/jquery-ui
* Includes: jquery.ui.tabs.css
* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:1px;margin:0 .2em 1px 0;border-bottom:0!important;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-selected{margin-bottom:0;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-selected a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-state-processing a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tabs .ui-tabs-hide{display:none!important}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,55 @@
.column-total {
width: 15%;
}
.column-status {
width: 20%;
}
th.column-title {
width: auto;
}
.asp-order-status {
padding: 7px 15px;
width: auto;
display: inline-block;
text-align: center;
min-width: 80px;
border-radius: 5px;
}
.asp-order-status.paid, .os-paid {
background-color: #b6e4b6;
}
.asp-order-status.authorized, .os-authorized {
background-color: #b6dee4;
}
.asp-order-status.canceled, .os-canceled {
background-color: #e4d4b6;
}
.asp-order-status.incomplete, .os-incomplete {
background-color: #dedede;
}
.asp-order-status.error, .os-error {
background-color: #ffa5a5;
}
.asp-order-actions-cont {
padding-top: 5px;
}
.asp-order-event-date {
font-size: 90%;
float: right;
}
.asp-order-event-header {
margin-bottom: 5px;
}
.asp-order-event-cont {
border-radius: 5px;
padding: 10px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,19 @@
jQuery(function ($) {
$('input.asp-select-on-click,textarea.asp-select-on-click').click(function (e) {
$(this).select();
});
$('a.wp-asp-toggle').click(function (e) {
e.preventDefault();
var div = $(this).siblings('div');
if (div.is(':visible')) {
$(this).removeClass('toggled-on');
$(this).addClass('toggled-off');
} else {
$(this).removeClass('toggled-off');
$(this).addClass('toggled-on');
}
div.slideToggle('fast');
});
});

View File

@ -0,0 +1,45 @@
var el = wp.element.createElement,
registerBlockType = wp.blocks.registerBlockType,
ServerSideRender = wp.serverSideRender,
SelectControl = wp.components.SelectControl,
ToggleControl = wp.components.ToggleControl,
InspectorControls = wp.blockEditor.InspectorControls;
registerBlockType('stripe-payments/product-block', {
title: aspBlockProdStr.title,
icon: 'products',
category: 'common',
edit: function (props) {
return [
el(ServerSideRender, {
block: 'stripe-payments/product-block',
attributes: props.attributes,
}),
el(InspectorControls, {},
el(SelectControl, {
label: aspBlockProdStr.product,
value: props.attributes.prodId,
options: aspProdOpts,
onChange: (value) => {
props.setAttributes({ prodId: value });
},
})
),
el(InspectorControls, {},
el(ToggleControl, {
label: aspBlockProdStr.button_only,
help: aspBlockProdStr.button_only_help,
checked: props.attributes.btnOnly,
onChange: (state) => {
props.setAttributes({ btnOnly: state });
},
})
),
];
},
save: function () {
return null;
},
});

View File

@ -0,0 +1,313 @@
/* global jQuery, aspEditProdData, aspTaxVarData, aspShippingVarData */
jQuery(document).ready(function ($) {
var aspVariationsGroups = aspEditProdData.varGroups;
var aspVariationsNames = aspEditProdData.varNames;
var aspVariationsPrices = aspEditProdData.varPrices;
var aspVariationsUrls = aspEditProdData.varUrls;
var aspVariationsOpts = aspEditProdData.varOpts;
var aspVariationsGroupsId = 0;
var aspVariationsVarId = 0;
function asp_variations_get_type(groupId) {
var varType = 0;
if (typeof aspVariationsOpts[groupId] !== 'undefined') {
if (typeof aspVariationsOpts[groupId] === 'object') {
varType = aspVariationsOpts[groupId].type;
} else {
varType = aspVariationsOpts[groupId];
}
}
return varType;
}
function asp_create_variations_group(aspGroupId, groupName, focus) {
$('span.asp-variations-no-variations-msg').hide();
var tpl_html = $('div.asp-html-tpl-variations-group').html();
tpl_html = $.parseHTML(tpl_html);
$(tpl_html).find('input.asp-variations-group-name').attr('name', 'asp-variations-group-names[' + aspGroupId + ']');
$(tpl_html).find('input.asp-variations-group-name').val(groupName);
var displayType = asp_variations_get_type(aspGroupId);
$(tpl_html).find('select.asp-variations-display-type').attr('name', 'asp-variations-opts[' + aspGroupId + '][type]');
$(tpl_html).find('select.asp-variations-display-type').val(displayType);
$(tpl_html).closest('div.asp-variations-group-cont').attr('data-asp-group-id', aspGroupId);
$('div#asp-variations-cont').append(tpl_html);
if (focus) {
asp_add_variation(aspGroupId, '', 0, '', false);
$(tpl_html).find('input.asp-variations-group-name').focus();
}
}
function asp_add_variation(aspGroupId, variationName, variationPrice, variationUrl, focus) {
var tpl_html = $('table.asp-html-tpl-variation-row tbody').html();
tpl_html = $.parseHTML(tpl_html);
$(tpl_html).find('input.asp-variation-name').attr('name', 'asp-variation-names[' + aspGroupId + '][]');
$(tpl_html).find('input.asp-variation-name').val(variationName);
$(tpl_html).find('input.asp-variation-price').attr('name', 'asp-variation-prices[' + aspGroupId + '][]');
$(tpl_html).find('input.asp-variation-price').val(variationPrice);
$(tpl_html).find('input.asp-variation-url').attr('name', 'asp-variation-urls[' + aspGroupId + '][]');
$(tpl_html).find('input.asp-variation-url').val(variationUrl);
var var_opt_tpl = $('div.asp-html-tpl-variation-options-2').html();
var_opt_tpl = var_opt_tpl.replace(/%_group_id_%/g, aspGroupId);
var_opt_tpl = $.parseHTML(var_opt_tpl);
$(var_opt_tpl).find('input').prop('disabled', false);
$(tpl_html).find('input.asp-variation-name').after(var_opt_tpl);
$('div.asp-variations-group-cont[data-asp-group-id="' + aspGroupId + '"]').find('table.asp-variations-tbl').append(tpl_html);
var varType = $(tpl_html).closest('.asp-variations-group-cont').find('select.asp-variations-display-type').val();
$(tpl_html).closest('.asp-variations-group-cont').find('div[data-asp-var-type="' + varType + '"]').show();
if (focus) {
$(tpl_html).find('input.asp-variation-name').focus();
} else {
if (varType === '2') {
if (aspVariationsOpts[aspGroupId][aspVariationsVarId]['checked'] === '1') {
$(var_opt_tpl).find('input[type="checkbox"]').prop('checked', true);
$(var_opt_tpl).find('input[type="checkbox"]').trigger('change');
}
}
}
}
$('button#asp-create-variations-group-btn').click(function (e) {
e.preventDefault();
asp_create_variations_group(aspVariationsGroupsId, '', true);
aspVariationsGroupsId++;
});
$(document).on('click', 'button.asp-variations-delete-group-btn', function (e) {
e.preventDefault();
if (!confirm(aspEditProdData.str.groupDeleteConfirm)) {
return false;
}
$(this).closest('div.asp-variations-group-cont').remove();
if ($('div.asp-variations-group-cont').length <= 1) {
$('span.asp-variations-no-variations-msg').show();
}
});
$(document).on('click', 'button.asp-variations-delete-variation-btn', function (e) {
e.preventDefault();
if (!confirm(aspEditProdData.str.varDeleteConfirm)) {
return false;
}
const variationTable = $(this).closest('table');
$(this).closest('tr').remove();
// Check if it was the last variation item. If so, remove the variation group as well.
if (variationTable.children('tr').length < 1) {
variationTable.closest('.asp-variations-group-cont').remove();
}
});
$(document).on('click', 'button.asp-variations-add-variation-btn', function (e) {
e.preventDefault();
var aspGroupId = $(this).closest('div.asp-variations-group-cont').data('asp-group-id');
asp_add_variation(aspGroupId, '', 0, '', true);
});
$(document).on('click', 'button.asp-variations-select-from-ml-btn', function (e) {
e.preventDefault();
var asp_selectVarFile = wp.media({
title: 'Select File',
button: {
text: 'Insert'
},
multiple: false
});
var buttonEl = $(this);
asp_selectVarFile.open();
asp_selectVarFile.on('select', function () {
var attachment_var = asp_selectVarFile.state().get('selection').first().toJSON();
$(buttonEl).closest('tr').children().find('input.asp-variation-url').val(attachment_var.url);
});
return false;
});
$(document).on('change', 'input.asp-variations-opts-checked', function (e) {
$(this).siblings('input.asp-variations-opts-checked-hidden').attr('disabled', $(this).prop('checked'));
});
$(document).on('change', 'select.asp-variations-display-type', function (e) {
$(this).closest('.asp-variations-group-cont').find('div[data-asp-var-type]').hide();
$(this).closest('.asp-variations-group-cont').find('div[data-asp-var-type="' + $(this).val() + '"]').show();
});
if (aspVariationsGroups.length !== 0) {
$.each(aspVariationsGroups, function (index, item) {
aspVariationsGroupsId = index;
asp_create_variations_group(index, item, false);
if (aspVariationsNames !== null) {
aspVariationsVarId = 0;
$.each(aspVariationsNames[index], function (index, item) {
asp_add_variation(aspVariationsGroupsId, item, aspVariationsPrices[aspVariationsGroupsId][index], aspVariationsUrls[aspVariationsGroupsId][index], false);
aspVariationsVarId++;
});
}
});
aspVariationsGroupsId++;
}
$('input[name="asp_product_collect_billing_addr"]').change(function () {
var checked = $(this).is(':checked');
$('input[data-addr-radio="1"]').prop('disabled', !checked);
});
$('a.wp-asp-product-menu-nav-item').on('click', function (e) {
e.preventDefault();
if ($(this).hasClass('nav-tab-active')) {
if (!$('#wp-asp-product-settings-menu-icon').is(':visible')) {
return false;
}
$('#wp-asp-product-settings-menu-icon').click();
return;
}
if ($('#wp-asp-product-settings-menu-icon').hasClass('menu-visible')) {
$('#wp-asp-product-settings-menu-icon').click();
}
var itemId = $(this).data('asp-nav-item');
$('.wp-asp-product-tab-item').removeClass('wp-asp-product-tab-item-visible');
$('#' + itemId).addClass('wp-asp-product-tab-item-visible');
$('a.wp-asp-product-menu-nav-item').removeClass('nav-tab-active');
$(this).addClass('nav-tab-active');
});
$('#wp-asp-product-settings-menu-icon').on('click', function (e) {
if ($(this).hasClass('menu-visible')) {
$('a.wp-asp-product-menu-nav-item').css('display', 'none');
$(this).find('span').removeClass('dashicons-menu-alt').addClass('dashicons-menu');
$(this).removeClass('menu-visible');
} else {
$(this).addClass('menu-visible');
$(this).find('span').removeClass('dashicons-menu').addClass('dashicons-menu-alt');
$('a.wp-asp-product-menu-nav-item').css('display', 'block');
}
});
var aspPriceInputChange = function () {
$('input[name="asp_product_hide_amount_input"]').prop('disabled', !($(this).val() == 0));
};
$('input[name="asp_product_price"]').on('change', aspPriceInputChange);
$('input[name="asp_product_price"]').on('keyup', aspPriceInputChange);
$('input[name="asp_product_price"]').trigger('change');
$('input[name="asp_product_type_radio"]').on('change', function (e) {
aspProductTypeChange(this.value);
});
aspProductTypeChange($('input[name="asp_product_type_radio"]:checked').val());
$('input[name="asp_use_other_stripe_acc"]').on('change', function (e) {
$('input[data-asp-other-acc]').prop('disabled', !this.checked);
});
$('input[name="asp_use_other_stripe_acc"]').trigger('change');
$('input[name="asp_product_enable_stock"]').on('change', function (e) {
$('input[name="asp_product_show_remaining_items"]').prop('disabled', !this.checked);
});
$('input[name="asp_product_enable_stock"]').trigger('change');
function aspProductTypeChange(val) {
if (val === 'subscription') {
$('.asp-other-stripe-acc').hide();
if (aspTaxVarData.disabledForSub) {
jQuery('#wp-asp-tax-variations-cont').hide();
jQuery('#wp-asp-tax-variations-disabled-msg').show();
}
} else {
$('.asp-other-stripe-acc').show();
if (aspTaxVarData.disabledForSub) {
jQuery('#wp-asp-tax-variations-cont').show();
jQuery('#wp-asp-tax-variations-disabled-msg').hide();
}
}
}
jQuery('#wp-asp-tax-variations-add-btn').click(function (e) {
e.preventDefault();
var tplLine = aspTaxVarData.tplLine;
tplLine = tplLine.replaceAll('%1$s', aspTaxVarData.cOpts);
tplLine = tplLine.replaceAll('%2$s', 0);
tplLine = tplLine.replaceAll('%4$s', 'display:none;');
tplLine = tplLine.replaceAll('%5$s', 'display:none;');
tplLine = tplLine.replaceAll('%7$s', 'disabled');
tplLine = tplLine.replaceAll('%8$s', 'disabled');
tplLine = tplLine.replaceAll(/%[0-9]*\$s/g, '');
var tplLineHide = jQuery(tplLine).css('display', 'none');
jQuery('#wp-asp-tax-variations-tbl').find('tbody').append(tplLineHide);
jQuery('#wp-asp-tax-variations-tbl').show();
tplLineHide.fadeIn(200);
});
jQuery('#wp-asp-tax-variations-tbl').on('click', 'button.wp-asp-tax-variations-del-btn', function (e) {
e.preventDefault();
if (confirm(aspTaxVarData.str.delConfirm)) {
jQuery(this).closest('tr').fadeOut(300, function () { jQuery(this).remove(); });
// Check if the variation table gets empty. If so, hide the table.
const tableBody = jQuery('#wp-asp-tax-variations-tbl tbody tr');
if(tableBody.length < 2){
jQuery('#wp-asp-tax-variations-tbl').fadeOut(300);
}
}
});
jQuery('#wp-asp-tax-variations-tbl').on('change', 'select.wp-asp-tax-variation-base', function (e) {
var selBase = jQuery(this).val();
jQuery(this).closest('tr').find('div').hide();
jQuery(this).closest('tr').find('div').find('input,select').prop('disabled', true);
jQuery(this).closest('tr').find('.wp-asp-tax-variation-cont-type-' + selBase).show();
jQuery(this).closest('tr').find('.wp-asp-tax-variation-cont-type-' + selBase).find('input,select').prop('disabled', false);
});
jQuery('#wp-asp-shipping-variations-add-btn').click(function (e) {
e.preventDefault();
var tplLine = aspShippingVarData.tplLine;
tplLine = tplLine.replaceAll('%1$s', aspShippingVarData.cOpts);
tplLine = tplLine.replaceAll('%2$s', 0);
tplLine = tplLine.replaceAll('%4$s', 'display:none;');
tplLine = tplLine.replaceAll('%5$s', 'display:none;');
tplLine = tplLine.replaceAll('%7$s', 'disabled');
tplLine = tplLine.replaceAll('%8$s', 'disabled');
tplLine = tplLine.replaceAll(/%[0-9]*\$s/g, '');
var tplLineHide = jQuery(tplLine).css('display', 'none');
jQuery('#wp-asp-shipping-variations-tbl').find('tbody').append(tplLineHide);
jQuery('#wp-asp-shipping-variations-tbl').show();
tplLineHide.fadeIn(200);
});
jQuery('#wp-asp-shipping-variations-tbl').on('click', 'button.wp-asp-shipping-variations-del-btn', function (e) {
e.preventDefault();
if (confirm(aspShippingVarData.str.delConfirm)) {
jQuery(this).closest('tr').fadeOut(300, function () { jQuery(this).remove(); });
// Check if the variation table gets empty. If so, hide the table.
const tableBody = jQuery('#wp-asp-shipping-variations-tbl tbody tr');
if(tableBody.length < 2){
jQuery('#wp-asp-shipping-variations-tbl').fadeOut(300);
}
}
});
jQuery('#wp-asp-shipping-variations-tbl').on('change', 'select.wp-asp-shipping-variation-base', function (e) {
var selBase = jQuery(this).val();
jQuery(this).closest('tr').find('div').hide();
jQuery(this).closest('tr').find('div').find('input,select').prop('disabled', true);
jQuery(this).closest('tr').find('.wp-asp-shipping-variation-cont-type-' + selBase).show();
jQuery(this).closest('tr').find('.wp-asp-shipping-variation-cont-type-' + selBase).find('input,select').prop('disabled', false);
});
});
document.addEventListener('DOMContentLoaded', function () {
const auth_only_checkbox = document.getElementById('asp_product_authorize_only_checkbox');
const extended_authorization_checkbox = document.getElementById('asp_product_extended_authorization_checkbox');
if (!auth_only_checkbox || !extended_authorization_checkbox){
return;
}
auth_only_checkbox.addEventListener('change', function () {
if (auth_only_checkbox.checked){
extended_authorization_checkbox.disabled = false;
} else {
extended_authorization_checkbox.disabled = true;
}
})
})

View File

@ -0,0 +1 @@
<?php // Silence is golden

View File

@ -0,0 +1,36 @@
jQuery(function ($) {
$('a.asp-order-action').click(function (e) {
e.preventDefault();
var order_id = $(this).data('order-id');
var nonce = $(this).data('nonce');
var action = $(this).data('action');
var confirm_msg = action === 'confirm' ? aspOrdersVars.str.confirmCapture : aspOrdersVars.str.confirmCancel;
if (confirm(confirm_msg.replace('%s', order_id))) {
var status_td = $(this).closest('td');
var status_html = status_td.html();
status_td.html('<span class="spinner is-active" style="float: left;"></span>');
var ajax_action = 'asp_order_capture_' + action;
var req = jQuery.ajax({
url: ajaxurl,
type: 'post',
data: { action: ajax_action, 'order_id': order_id, 'nonce': nonce }
});
req.done(function (data) {
console.log(data);
if (data.success) {
} else {
alert(data.err_msg);
}
status_td.html(status_html);
if (data.order_status) {
console.log(data.order_status);
status_td.html(data.order_status);
}
});
req.fail(function (data) {
alert(aspOrdersVars.str.errorOccurred);
status_td.html(status_html);
});
}
});
});

View File

@ -0,0 +1,99 @@
var wp_asp_urlHash = window.location.hash.substr(1);
var wp_asp_transHash = aspSettingsData.transHash;
var wp_asp_currencies = aspSettingsData.currencies;
if (wp_asp_urlHash === '') {
if (wp_asp_transHash !== '') {
wp_asp_urlHash = wp_asp_transHash;
} else {
wp_asp_urlHash = 'general';
}
}
jQuery(function ($) {
var wp_asp_activeTab = "";
$('div.asp-settings-spinner-container').remove();
$('a.nav-tab').click(function (e) {
if ($(this).attr('data-tab-name') !== wp_asp_activeTab) {
$('div.wp-asp-tab-container[data-tab-name="' + wp_asp_activeTab + '"]').hide();
$('a.nav-tab[data-tab-name="' + wp_asp_activeTab + '"]').removeClass('nav-tab-active');
wp_asp_activeTab = $(this).attr('data-tab-name');
$('div.wp-asp-tab-container[data-tab-name="' + wp_asp_activeTab + '"]').show();
$(this).addClass('nav-tab-active');
$('input#wp-asp-urlHash').val(wp_asp_activeTab);
if (window.location.hash !== wp_asp_activeTab) {
window.location.hash = wp_asp_activeTab;
}
}
});
$('.wp-asp-curr-sel-all-btn').click(function (e) {
e.preventDefault();
$('.wp-asp-allowed-currencies').find('input[type="checkbox"]').prop('checked', true);
});
$('.wp-asp-curr-sel-none-btn').click(function (e) {
e.preventDefault();
$('.wp-asp-allowed-currencies').find('input[type="checkbox"]').prop('checked', false);
});
$('.wp-asp-curr-sel-invert-btn').click(function (e) {
e.preventDefault();
$('.wp-asp-allowed-currencies').find('input[type="checkbox"]').each(function (ind, el) {
$(el).prop('checked', !$(el).prop('checked'));
});
});
$('select[name="AcceptStripePayments-settings[custom_field_type]"]').change(function () {
if ($(this).val() === 'text') {
$(this).parents('tr').next().show();
} else {
$(this).parents('tr').next().hide();
}
});
$('select[name="AcceptStripePayments-settings[custom_field_validation]"]').change(function () {
if ($(this).val() === 'custom') {
$('div.wp-asp-custom-field-validation-custom-input-cont').show();
} else {
$('div.wp-asp-custom-field-validation-custom-input-cont').hide();
}
});
$('#asp_clear_log_btn').click(function (e) {
e.preventDefault();
if (confirm(aspSettingsData.str.logClearConfirm)) {
var req = jQuery.ajax({
url: ajaxurl,
type: "post",
data: { action: "asp_clear_log", nonce: aspSettingsData.asp_settings_ajax_nonce }
});
req.done(function (data) {
if (data === '1') {
alert(aspSettingsData.str.logCleared);
} else {
alert(aspSettingsData.str.errorOccured + ' ' + data);
}
});
}
});
$('#wp_asp_curr_code').change(function () {
$('#wp_asp_curr_symb').val(wp_asp_currencies[$('#wp_asp_curr_code').val()][1]);
});
$('input[name="AcceptStripePayments-settings[captcha_type]"]').change(function () {
$('[data-captcha-section]').slideUp('fast');
if (($(this).val())) {
$('div[data-captcha-section="' + $(this).val() + '"]').slideDown('fast');
}
});
$('#wp_asp_curr_code').change();
$('select[name="AcceptStripePayments-settings[custom_field_validation]"]').change();
$('select[name="AcceptStripePayments-settings[custom_field_type]"]').change();
$('a.nav-tab[data-tab-name="' + wp_asp_urlHash + '"]').trigger('click');
$('div.wp-asp-settings-cont').show();
});

View File

@ -0,0 +1,214 @@
var aspVarsData = {};
aspVarsData.dataReceived = false;
function asp_show_tab(tabid) {
jQuery('[data-tabid]').hide();
jQuery('[data-tabid=' + tabid + ']').show();
jQuery('a[data-switch-to-tab]').removeClass('nav-tab-active');
jQuery('a[data-switch-to-tab="' + tabid + '"]').addClass('nav-tab-active');
}
function asp_shortcode_type_button_handler() {
jQuery('#asp-shortcode-type-container').hide();
jQuery('#' + jQuery(this).attr('data-asp-display')).show();
}
function asp_get_content_and_settings() {
// Run an ajax call to the main.php to get all current CPT items
if (aspVarsData.dataReceived === false) {
jQuery.post(
asp_admin_ajax_url,
{
action: 'asp_tinymce_get_settings'
},
function (response) {
if (response) { // ** If response was successful
aspVarsData.dataReceived = true;
var res = JSON.parse(response);
jQuery('#asp-tinymce-container').append(res.content);
if (res.products_sel === '') {
jQuery('#asp_product_select').hide();
jQuery('#asp_product_select').siblings('p').hide();
jQuery('#asp-error-no-products').show();
jQuery('#asp-tinymce-product-submit').attr('disabled', true);
} else {
jQuery('#asp_product_select').append(res.products_sel);
}
jQuery('#asp_currency').append(res.currency_opts);
//bind shortcode select button click event
jQuery('button.asp-sc-type-sel-btn').on('click', asp_shortcode_type_button_handler);
//bind event to tab buttons click
jQuery('a[data-switch-to-tab]').on('click', asp_tab_click_handler);
// handles the click event of the submit button
jQuery('#asp-tinymce-submit').on('click', asp_form_submit_hanlder);
// habdles the click event of the product submit button
jQuery('#asp-tinymce-product-submit').on('click', asp_product_submit_handler);
asp_show_tab(1);
} else { // ** Else response was unsuccessful
alert('Stripe Payments Button AJAX Error! Please deactivate the plugin to permanently dismiss this alert.');
}
}
);
}
}
(function () {
tinymce.create('tinymce.plugins.aspShortcode', {
/**
* Initializes the plugin, this will be executed after the plugin has been created.
* This call is done before the editor instance has finished it's initialization so use the onInit event
* of the editor instance to intercept that event.
*
* @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
* @param {string} url Absolute URL to where the plugin is located.
*/
init: function (ed, url) {
ed.addButton('asp_shortcode', {
icon: 'asp-shortcode-icon',
tooltip: 'Stripe Payments Shortcode',
cmd: 'asp_shortcode'
});
ed.addCommand('asp_shortcode', function () {
// bind event on modal close
jQuery(window).one('tb_unload', function () {
jQuery('#asp-tinymce-container').html('');
aspVarsData.dataReceived = false;
});
var width = jQuery(window).width(),
H = jQuery(window).height(),
W = (720 < width) ? 720 : width;
// W = W - 80;
H = H - 84;
asp_get_content_and_settings();
tb_show('Stripe Payments Insert Shortcode', '#TB_inline?width=' + W + '&height=' + H + '&inlineId=asp-highlight-form');
});
},
/**
* Creates control instances based in the incomming name. This method is normally not
* needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons
* but you sometimes need to create more complex controls like listboxes, split buttons etc then this
* method can be used to create those.
*
* @param {String} n Name of the control to create.
* @param {tinymce.ControlManager} cm Control manager to use inorder to create new control.
* @return {tinymce.ui.Control} New control instance or null if no control was created.
*/
createControl: function (n, cm) {
return null;
},
/**
* Returns information about the plugin as a name/value array.
* The current keys are longname, author, authorurl, infourl and version.
*
* @return {Object} Name/value array containing information about the plugin.
*/
getInfo: function () {
return {
longname: 'Simple Stripe Payment Button',
author: 'Tips and Tricks HQ',
authorurl: 'http://www.tipsandtricks-hq.com/development-center',
infourl: 'https://www.tipsandtricks-hq.com/ecommerce/wordpress-stripe-plugin-accept-payments-using-stripe',
version: "1.0"
};
}
});
// Register plugin
tinymce.PluginManager.add('asp_shortcode', tinymce.plugins.aspShortcode);
})();
function asp_tab_click_handler(e) {
e.preventDefault();
asp_show_tab(jQuery(this).data('switch-to-tab'));
}
function asp_product_submit_handler() {
var product_id = jQuery('#asp_product_select').val();
var shortcode = '[asp_product id="' + product_id + '"]';
// inserts the shortcode into the active editor
tinyMCE.activeEditor.execCommand('mceInsertContent', 0, shortcode); // Send processed shortcode to editor
// close WP thickbox window
tb_remove();
}
function asp_form_submit_hanlder() {
var name = jQuery('#asp_name').val();
var price = jQuery('#asp_price').val();
var currency = jQuery('#asp_currency').val();
var quantity = jQuery('#asp_quantity').val();
var url = jQuery('#asp_url').val();
var thankyou_page_url = jQuery('#asp_thankyou_page_url').val();
var description = jQuery('#asp_description').val();
var button_text = jQuery('#asp_button_text').val();
var item_logo = jQuery('#asp_item_logo').val();
var billing_address = jQuery('#asp_billing_address').is(':checked');
var shipping_address = jQuery('#asp_shipping_address').is(':checked');
var css_class = jQuery('#asp_css_class').val();
//Build the shortcode with parameters according to the options
var shortcode = '[accept_stripe_payment';
//Add the fancy parameter to the shortcode (if needed
if (name != '') {
shortcode += ' name="' + name + '"';
} else {
jQuery('#asp_form_err').html('* You must specify item name.');
return false;
}
if (price != '') {
shortcode += ' price="' + price + '"';
}
if (currency != '') {
shortcode += ' currency="' + currency + '"';
}
if (quantity != '') {
shortcode += ' quantity="' + quantity + '"';
}
if (url != '') {
shortcode += ' url="' + url + '"';
}
if (thankyou_page_url != '') {
shortcode += ' thankyou_page_url="' + thankyou_page_url + '"';
}
if (description != '') {
shortcode += ' description="' + description + '"';
}
if (button_text != '') {
shortcode += ' button_text="' + button_text + '"';
}
if (item_logo != '') {
shortcode += ' item_logo="' + item_logo + '"';
}
if (billing_address) {
shortcode += ' billing_address="1"';
}
if (shipping_address) {
shortcode += ' shipping_address="1"';
}
if (css_class != '') {
shortcode += ' class="' + css_class + '"';
}
shortcode = shortcode + ']';//End the shortcode
// inserts the shortcode into the active editor
tinyMCE.activeEditor.execCommand('mceInsertContent', 0, shortcode); // Send processed shortcode to editor
// close WP thickbox window
tb_remove();
}
jQuery(function () {
// Instantiate a form in the wp thickbox window (hidden at start)
var form = jQuery('<div id="asp-highlight-form"><div id="asp-tinymce-container"></div></div>');
form.appendTo('body').hide(); // Hide form
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
<?php
class ASP_Admin_Order_Meta_Boxes {
public function __construct() {
add_action( 'add_meta_boxes_stripe_order', array( $this, 'add_meta_boxes' ), 0 );
}
public function add_meta_boxes() {
add_meta_box(
'asp_order_events_meta_box',
__( 'Order Events', 'stripe-payments' ),
array( $this, 'display_order_events_meta_box' ),
'stripe_order',
'side',
'default'
);
}
public function display_order_events_meta_box( $post ) {
$order_events = get_post_meta( $post->ID, 'asp_order_events', true );
if ( ! empty( $order_events ) && is_array( $order_events ) ) {
$i = 0;
foreach ( $order_events as $event ) {
$i++;
if ( 1 === $i && empty( $event['comment'] ) ) {
$event['comment'] = __( 'Order created.', 'stripe-payments' );
}
if ( 'paid' === $event['status'] && empty( $event['comment'] ) ) {
$event['comment'] = __( 'Payment completed.', 'stripe-payments' );
}
echo sprintf(
'<div class="asp-order-event-cont%s">
<div class="asp-order-event-header">
<span class="asp-order-event-status">%s</span>
<span class="asp-order-event-date" title="%s">%s</span>
</div>
<div class="asp-order-event-comment">%s</div>
</div>',
' os-' . $event['status'],
ASPOrder::get_status_str( $event['status'] ),
gmdate( 'Y-m-d H:i:s', $event['date'] ),
gmdate( 'M d H:i', $event['date'] ),
$event['comment']
);
if ( count( $order_events ) !== $i ) {
echo '<hr>';
}
}
} else {
echo __( 'No data available.', 'stripe-payments' );
}
}
}
new ASP_Admin_Order_Meta_Boxes();

View File

@ -0,0 +1,217 @@
<?php
class ASP_Admin_Products {
protected static $instance = null;
public function __construct() {
self::$instance = $this;
if ( is_admin() ) {
//products meta boxes handler
require_once WP_ASP_PLUGIN_PATH . 'admin/includes/class-asp-admin-product-meta-boxes.php';
}
}
public static function get_instance() {
// If the single instance hasn't been set, set it now.
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public function register_post_type() {
// Products post type
$labels = array(
'name' => _x( 'Products', 'Post Type General Name', 'stripe-payments' ),
'singular_name' => _x( 'Product', 'Post Type Singular Name', 'stripe-payments' ),
'menu_name' => __( 'Stripe Payments', 'stripe-payments' ),
'all_items' => __( 'Products', 'stripe-payments' ),
'view_item' => __( 'View Product', 'stripe-payments' ),
'add_new_item' => __( 'Add New Product', 'stripe-payments' ),
'add_new' => __( 'Add New Product', 'stripe-payments' ),
'edit_item' => __( 'Edit Product', 'stripe-payments' ),
'update_item' => __( 'Update Products', 'stripe-payments' ),
'search_items' => __( 'Search Product', 'stripe-payments' ),
'not_found' => __( 'Not found', 'stripe-payments' ),
'not_found_in_trash' => __( 'Not found in Trash', 'stripe-payments' ),
);
$menu_icon = WP_ASP_PLUGIN_URL . '/assets/asp-dashboard-menu-icon.png';
$asp_slug = untrailingslashit( ASPMain::$products_slug );
//Trigger filter hook to allow overriding of the default ASP Products Post Type capability.
$asp_post_capability = apply_filters( 'asp_post_type_capability', ASP_MANAGEMENT_PERMISSION );
$capabilities = array(
'edit_post' => $asp_post_capability,
'delete_post' => $asp_post_capability,
'read_post' => $asp_post_capability,
'edit_posts' => $asp_post_capability,
'edit_others_posts' => $asp_post_capability,
'delete_posts' => $asp_post_capability,
'publish_posts' => $asp_post_capability,
'read_private_posts' => $asp_post_capability,
);
$args = array(
'labels' => $labels,
'capability_type' => 'post',
'capabilities' => $capabilities,
'public' => true,
'publicly_queryable' => true,
'query_var' => true,
'has_archive' => false,
'hierarchical' => false,
'rewrite' => array( 'slug' => $asp_slug ),
'supports' => array( 'title' ),
'show_ui' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => true,
'menu_position' => 80,
'menu_icon' => $menu_icon,
);
$args = apply_filters( 'asp_products_post_type_before_register', $args );
register_post_type( ASPMain::$products_slug, $args );
//add custom columns for list view
add_filter( 'manage_' . ASPMain::$products_slug . '_posts_columns', array( $this, 'manage_columns' ) );
add_action( 'manage_' . ASPMain::$products_slug . '_posts_custom_column', array( $this, 'manage_custom_columns' ), 10, 2 );
//set custom columns sortable
add_filter( 'manage_edit-' . ASPMain::$products_slug . '_sortable_columns', array( $this, 'manage_sortable_columns' ) );
//set custom messages on post save\update etc.
add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) );
// Temp products post type
$labels = array(
'name' => _x( 'Products', 'Post Type General Name', 'stripe-payments' ),
'singular_name' => _x( 'Product', 'Post Type Singular Name', 'stripe-payments' ),
'all_items' => __( 'Products', 'stripe-payments' ),
'view_item' => __( 'View Product', 'stripe-payments' ),
'add_new_item' => __( 'Add New Product', 'stripe-payments' ),
'add_new' => __( 'Add New Product', 'stripe-payments' ),
'edit_item' => __( 'Edit Product', 'stripe-payments' ),
'update_item' => __( 'Update Products', 'stripe-payments' ),
'search_items' => __( 'Search Product', 'stripe-payments' ),
'not_found' => __( 'Not found', 'stripe-payments' ),
'not_found_in_trash' => __( 'Not found in Trash', 'stripe-payments' ),
);
$asp_slug = untrailingslashit( ASPMain::$temp_prod_slug );
$args = array(
'labels' => $labels,
'capability_type' => 'post',
'public' => false,
'publicly_queryable' => false,
'capability_type' => 'post',
'query_var' => true,
'has_archive' => false,
'hierarchical' => false,
'rewrite' => array( 'slug' => $asp_slug ),
'supports' => array( 'title' ),
'show_ui' => false,
'show_in_nav_menus' => false,
'show_in_admin_bar' => false,
'menu_position' => 80,
'menu_icon' => $menu_icon,
);
}
public function post_updated_messages( $messages ) {
$post = get_post();
$post_type = get_post_type( $post );
$slug = ASPMain::$products_slug;
if ( ASPMain::$products_slug === $post_type ) {
$permalink = get_permalink( $post->ID );
$view_link = sprintf( ' <a href="%s">%s</a>', esc_url( $permalink ), __( 'View product', 'stripe-payments' ) );
$preview_permalink = add_query_arg( 'preview', 'true', $permalink );
$preview_link = sprintf( ' <a target="_blank" href="%s">%s</a>', esc_url( $preview_permalink ), __( 'Preview product', 'stripe-payments' ) );
$messages[ $slug ] = $messages['post'];
$messages[ $slug ][1] = __( 'Product updated.', 'stripe-payments' ) . $view_link;
$messages[ $slug ][4] = __( 'Product updated.', 'stripe-payments' );
$messages[ $slug ][6] = __( 'Product published.', 'stripe-payments' ) . $view_link;
$messages[ $slug ][7] = __( 'Product saved.', 'stripe-payments' );
$messages[ $slug ][8] = __( 'Product submitted.', 'stripe-payments' ) . $preview_link;
$messages[ $slug ][10] = __( 'Product draft updated.', 'stripe-payments' ) . $preview_link;
}
return $messages;
}
public function manage_columns( $columns ) {
unset( $columns );
$columns = array(
'thumbnail' => __( 'Thumbnail', 'stripe-payments' ),
'title' => __( 'Product Name', 'stripe-payments' ),
'id' => __( 'ID', 'stripe-payments' ),
'price' => __( 'Price', 'stripe-payments' ),
'stock' => __( 'Stock', 'stripe-payments' ),
'shortcode' => __( 'Shortcode', 'stripe-payments' ),
'date' => __( 'Date', 'stripe-payments' ),
);
return $columns;
}
public function manage_custom_columns( $column, $post_id ) {
switch ( $column ) {
case 'id':
echo esc_html( $post_id );
break;
case 'stock':
if ( get_post_meta( $post_id, 'asp_product_enable_stock', true ) ) {
$stock_items = get_post_meta( $post_id, 'asp_product_stock_items', true );
echo ! $stock_items ? __( 'Out of stock', 'stripe-payments' ) : esc_attr( $stock_items );
} else {
echo '—';
}
break;
case 'thumbnail':
$thumb_url = ASP_Utils::get_small_product_thumb( $post_id );
if ( ! $thumb_url ) {
$thumb_url = WP_ASP_PLUGIN_URL . '/assets/product-thumb-placeholder.png';
}
$edit_link = get_edit_post_link( $post_id );
$title = __( 'Edit Product', 'stripe-payments' );
?>
<span class="asp-product-thumbnail-container">
<a href="<?php echo esc_attr( $edit_link ); ?>">
<img src="<?php echo esc_attr( $thumb_url ); ?>" title="<?php echo esc_attr( $title ); ?>">
</a>
</span>
<?php
break;
case 'price':
$price = get_post_meta( $post_id, 'asp_product_price', true );
$currency = get_post_meta( $post_id, 'asp_product_currency', true );
if ( ! $currency ) {
//we need to use default currency
$asp = AcceptStripePayments::get_instance();
$currency = $asp->get_setting( 'currency_code' );
}
if ( $price ) {
$output = AcceptStripePayments::formatted_price( $price, $currency );
} else {
$output = __( 'Custom', 'stripe-payments' );
}
//let's apply filter to let addons change price column output if needed
$output = apply_filters( 'asp_products_table_price_column', $output, $price, $currency, $post_id );
echo wp_kses_post( $output );
break;
case 'shortcode':
?>
<input type="text" name="asp_product_shortcode" class="asp-select-on-click" readonly value="[asp_product id=&quot;<?php echo esc_attr( $post_id ); ?>&quot;]">
<?php
break;
}
}
public function manage_sortable_columns( $columns ) {
$columns['id'] = 'id';
$columns['price'] = 'price';
$columns['stock'] = 'stock';
return $columns;
}
}

View File

@ -0,0 +1,187 @@
<?php
/**
* Asking users for their experience with the plugin.
*/
class ASP_Admin_User_Feedback {
/**
* The wp option for notice dismissal data.
*/
const OPTION_NAME = 'asp_plugin_user_feedback_notice';
/**
* How many days after activation it should display the user feedback notice.
*/
const DELAY_NOTICE = 14;
/**
* Initialize user feedback notice functionality.
*/
public function init() {
add_action( 'admin_notices', array( $this, 'maybe_display' ) );
add_action( 'wp_ajax_asp_feedback_notice_dismiss', array( $this, 'feedback_notice_dismiss' ) );
}
/**
* Maybe display the user feedback notice.
*/
public function maybe_display() {
// Only admin users should see the feedback notice.
if ( ! is_super_admin() ) {
return;
}
$options = get_option( self::OPTION_NAME );
// Set default options.
if ( empty( $options ) ) {
$options = array(
'time' => time(),
'dismissed' => false,
);
update_option( self::OPTION_NAME, $options );
}
// Check if the feedback notice was not dismissed already.
if ( isset( $options['dismissed'] ) && ! $options['dismissed'] ) {
$this->display();
}
}
/**
* Display the user feedback notice.
*/
private function display() {
// Skip if plugin is not being utilized.
if ( ! $this->is_plugin_configured() ) {
return;
}
// Fetch when plugin was initially activated.
$activated = get_option( 'asp_plugin_activated_time' );
if(empty($activated)){
add_option( 'asp_plugin_activated_time', time() );
}
// Skip if the plugin is active for less than a defined number of days.
if ( empty( $activated ) || ( $activated + ( DAY_IN_SECONDS * self::DELAY_NOTICE ) ) > time() ) {
// Not enough time;
return;
}
?>
<div class="notice notice-info is-dismissible asp-plugin-review-notice">
<div class="asp-plugin-review-step asp-plugin-review-step-1">
<p><?php esc_html_e( 'Are you enjoying the Accept Stripe Payments plugin?', 'stripe-payments' ); ?></p>
<p>
<a href="#" class="asp-plugin-review-switch-step" data-step="3"><?php esc_html_e( 'Yes', 'stripe-payments' ); ?></a><br />
<a href="#" class="asp-plugin-review-switch-step" data-step="2"><?php esc_html_e( 'Not Really', 'stripe-payments' ); ?></a>
</p>
</div>
<div class="asp-plugin-review-step asp-plugin-review-step-2" style="display: none">
<p><?php esc_html_e( 'We\'re sorry to hear you aren\'t enjoying the Accept Stripe Payments plugin. We would love a chance to improve. Could you take a minute and let us know what we can do better by using our contact form? ', 'stripe-payments' ); ?></p>
<p>
<?php
printf(
'<a href="https://s-plugins.com/contact-us/" class="asp-plugin-dismiss-review-notice asp-plugin-review-out" target="_blank" rel="noopener noreferrer">%s</a>',
esc_html__( 'Give Feedback', 'stripe-payments' )
);
?>
<br>
<a href="#" class="asp-plugin-dismiss-review-notice" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'No thanks', 'stripe-payments' ); ?>
</a>
</p>
</div>
<div class="asp-plugin-review-step asp-plugin-review-step-3" style="display: none">
<p><?php esc_html_e( 'That\'s great! Could you please do me a big favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'stripe-payments' ); ?></p>
<p><strong><?php esc_html_e( '~ Accept Stripe Payments Plugin Team', 'stripe-payments' ) ?></strong></p>
<p>
<a href="https://wordpress.org/support/plugin/stripe-payments/reviews/?filter=5#new-post" class="asp-plugin-dismiss-review-notice asp-plugin-review-out" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'OK, you deserve it', 'stripe-payments' ); ?>
</a><br>
<a href="#" class="asp-plugin-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Nope, maybe later', 'stripe-payments' ); ?></a><br>
<a href="#" class="asp-plugin-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'I already did', 'stripe-payments' ); ?></a>
</p>
</div>
</div>
<script type="text/javascript">
jQuery( document ).ready( function ( $ ) {
$( document ).on( 'click', '.asp-plugin-dismiss-review-notice, .asp-plugin-review-notice button', function( e ) {
if ( ! $( this ).hasClass( 'asp-plugin-review-out' ) ) {
e.preventDefault();
}
$.post( ajaxurl, { action: 'asp_feedback_notice_dismiss' } );
$( '.asp-plugin-review-notice' ).remove();
} );
$( document ).on( 'click', '.asp-plugin-review-switch-step', function( e ) {
e.preventDefault();
var target = parseInt( $( this ).attr( 'data-step' ), 10 );
if ( target ) {
var $notice = $( this ).closest( '.asp-plugin-review-notice' );
var $review_step = $notice.find( '.asp-plugin-review-step-' + target );
if ( $review_step.length > 0 ) {
$notice.find( '.asp-plugin-review-step:visible' ).fadeOut( function() {
$review_step.fadeIn();
} );
}
}
} );
} );
</script>
<?php
}
/**
* Check if the crucial plugin setting are configured.
*
* @return bool
*/
public function is_plugin_configured() {
$loop = new WP_Query(
array(
'post_type' => ASPMain::$products_slug,
'post_status' => 'publish',
'posts_per_page' => -1,
)
);
if( $loop->have_posts() ){
//Products have been configured.
return true;
}
return false;
}
/**
* Dismiss the user feedback admin notice.
*/
public function feedback_notice_dismiss() {
$options = get_option( self::OPTION_NAME, array() );
$options['time'] = time();
$options['dismissed'] = true;
update_option( self::OPTION_NAME, $options );
if ( is_super_admin() && is_multisite() ) {
$site_list = get_sites();
foreach ( (array) $site_list as $site ) {
switch_to_blog( $site->blog_id );
update_option( self::OPTION_NAME, $options );
restore_current_blog();
}
}
wp_send_json_success();
}
}

View File

@ -0,0 +1,127 @@
<?php
class ASP_Coupons_Table extends WP_List_Table {
public function prepare_items() {
$columns = $this->get_columns();
// $hidden = $this->get_hidden_columns();
$sortable = $this->get_sortable_columns();
$args = array(
'posts_per_page' => -1,
'offset' => 0,
'post_type' => 'asp_coupons',
);
$coupons = get_posts( $args );
$data = array();
foreach ( $coupons as $coupon ) {
$id = $coupon->ID;
$data[] = array(
'id' => $id,
'coupon' => get_post_meta( $id, 'asp_coupon_code', true ),
'active' => get_post_meta( $id, 'asp_coupon_active', true ),
'discount' => get_post_meta( $id, 'asp_coupon_discount', true ),
'discount_type' => get_post_meta( $id, 'asp_coupon_discount_type', true ),
'red_limit' => get_post_meta( $id, 'asp_coupon_red_limit', true ),
'red_count' => get_post_meta( $id, 'asp_coupon_red_count', true ),
'start_date' => get_post_meta( $id, 'asp_coupon_start_date', true ),
'exp_date' => get_post_meta( $id, 'asp_coupon_exp_date', true ),
);
}
wp_reset_postdata();
usort( $data, array( &$this, 'sort_data' ) );
$perPage = 10;
$currentPage = $this->get_pagenum();
$totalItems = count( $data );
$this->set_pagination_args(
array(
'total_items' => $totalItems,
'per_page' => $perPage,
)
);
$data = array_slice( $data, ( ( $currentPage - 1 ) * $perPage ), $perPage );
$this->_column_headers = array( $columns, array(), $sortable );
$this->items = $data;
}
public function get_columns() {
$columns = array(
'coupon' => __( 'Coupon Code', 'stripe-payments' ),
'id' => 'ID',
'active' => __( 'Active', 'stripe-payments' ),
'discount' => __( 'Discount Value', 'stripe-payments' ),
'red_count' => __( 'Redemption Count', 'stripe-payments' ),
'red_limit' => __( 'Redemption Limit', 'stripe-payments' ),
'start_date' => __( 'Start Date', 'stripe-payments' ),
'exp_date' => __( 'Expiry Date', 'stripe-payments' ),
);
return $columns;
}
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'exp_date':
return $item[ $column_name ] == 0 ? __( 'No expiry', 'stripe-payments' ) : $item[ $column_name ];
case 'active':
return $item[ $column_name ] == 0 ? __( 'No', 'stripe-payments' ) : __( 'Yes', 'stripe-payments' );
case 'coupon':
$str = '';
// translators: %s is coupon code
$confirm_coupon_delete_msg = sprintf( __( 'Are you sure you want to delete "%s" coupon? This can\'t be undone.', 'stripe-payments' ), $item['coupon'] );
ob_start();
?>
<a href="edit.php?post_type=<?php echo esc_attr( ASPMain::$products_slug ); ?>&page=stripe-payments-coupons&action=asp_add_edit_coupon&asp_coupon_id=<?php echo esc_attr( $item['id'] ); ?>" aria-label="<?php echo esc_attr( __( 'Edit coupon', 'stripe-payments' ) ); ?>"><?php echo esc_html( $item[ $column_name ] ); ?></a>
<div class="row-actions">
<span class="edit">
<a href="edit.php?post_type=<?php echo esc_attr( ASPMain::$products_slug ); ?>&page=stripe-payments-coupons&action=asp_add_edit_coupon&asp_coupon_id=<?php echo esc_attr( $item['id'] ); ?>" aria-label="<?php echo esc_attr( __( 'Edit coupon', 'stripe-payments' ) ); ?>"><?php echo esc_html( __( 'Edit', 'stripe-payments' ) ); ?></a> |
</span>
<span class="trash">
<a href="<?php echo esc_attr( wp_nonce_url( 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-coupons&action=asp_delete_coupon&asp_coupon_id=' . $item['id'], 'delete-coupon_' . $item['id'] ) ); ?>" class="submitdelete" aria-label="<?php echo esc_attr( __( 'Delete coupon', 'stripe-payments' ) ); ?>" onclick="return confirm('<?php echo esc_js( $confirm_coupon_delete_msg ); ?>');"><?php echo esc_attr( __( 'Delete', 'stripe-payments' ) ); ?></a>
</span>
</div>
<?php
$str .= ob_get_clean();
return $str;
case 'discount':
if ( $item['discount_type'] === 'perc' ) {
return $item[ $column_name ] . '%';
}
return $item[ $column_name ];
case 'red_limit':
return ! empty( $item[ $column_name ] ) ? $item[ $column_name ] : '—';
default:
return $item[ $column_name ];
}
}
public function get_sortable_columns() {
return array(
'id' => array( 'id', false ),
'coupon' => array( 'coupon', false ),
'active' => array( 'active', false ),
);
}
private function sort_data( $a, $b ) {
// Set defaults
$orderby = 'id';
$order = 'desc';
// If orderby is set, use this as the sort column
if ( ! empty( $_GET['orderby'] ) ) {
$orderby = sanitize_text_field($_GET['orderby']);
}
// If order is set use this as the order
if ( ! empty( $_GET['order'] ) ) {
$order = sanitize_text_field($_GET['order']);
}
$result = strcmp( $a[ $orderby ], $b[ $orderby ] );
if ( $order === 'asc' ) {
return $result;
}
return -$result;
}
}

View File

@ -0,0 +1,577 @@
<?php
class AcceptStripePayments_CouponsAdmin {
public static $post_slug = 'asp_coupons';
public function __construct() {
add_action( 'init', array( $this, 'init_handler' ) );
if ( is_admin() ) {
add_action( 'admin_menu', array( $this, 'add_menu' ) );
if ( wp_doing_ajax() ) {
add_action( 'wp_ajax_asp_check_coupon', array( $this, 'frontend_check_coupon' ) );
add_action( 'wp_ajax_nopriv_asp_check_coupon', array( $this, 'frontend_check_coupon' ) );
}
}
}
public static function get_coupon( $coupon_code ) {
$out = array(
'code' => $coupon_code,
'valid' => true,
);
//let's find coupon
$coupon = get_posts(
array(
'meta_key' => 'asp_coupon_code',
'meta_value' => $coupon_code,
'posts_per_page' => 1,
'offset' => 0,
'post_type' => self::$post_slug,
)
);
wp_reset_postdata();
if ( empty( $coupon ) ) {
//coupon not found
$out['valid'] = false;
$out['err_msg'] = __( 'Coupon not found.', 'stripe-payments' );
return $out;
}
$coupon = $coupon[0];
//check if coupon is active
if ( ! get_post_meta( $coupon->ID, 'asp_coupon_active', true ) ) {
$out['valid'] = false;
$out['err_msg'] = __( 'Coupon is not active.', 'stripe-payments' );
return $out;
}
//check if coupon start date has come
$start_date = get_post_meta( $coupon->ID, 'asp_coupon_start_date', true );
if ( empty( $start_date ) || strtotime( $start_date ) > time() ) {
$out['valid'] = false;
$out['err_msg'] = __( 'Coupon is not available yet.', 'stripe-payments' );
return $out;
}
//check if coupon has expired
$exp_date = get_post_meta( $coupon->ID, 'asp_coupon_exp_date', true );
if ( ! empty( $exp_date ) && strtotime( $exp_date ) < time() ) {
$out['valid'] = false;
$out['err_msg'] = __( 'Coupon has expired.', 'stripe-payments' );
return $out;
}
//check if redemption limit is reached
$red_limit = get_post_meta( $coupon->ID, 'asp_coupon_red_limit', true );
$red_count = get_post_meta( $coupon->ID, 'asp_coupon_red_count', true );
if ( ! empty( $red_limit ) && intval( $red_count ) >= intval( $red_limit ) ) {
$out['valid'] = false;
$out['err_msg'] = __( 'Coupon redemption limit is reached.', 'stripe-payments' );
return $out;
}
$out['id'] = $coupon->ID;
$out['discount'] = get_post_meta( $coupon->ID, 'asp_coupon_discount', true );
$out['discountType'] = get_post_meta( $coupon->ID, 'asp_coupon_discount_type', true );
return $out;
}
public static function is_coupon_allowed_for_product( $coupon_id, $prod_id ) {
//check if coupon is only available for specific products
$only_for_allowed_products = get_post_meta( $coupon_id, 'asp_coupon_only_for_allowed_products', true );
if ( $only_for_allowed_products ) {
$allowed_products = get_post_meta( $coupon_id, 'asp_coupon_allowed_products', true );
if ( is_array( $allowed_products ) && ! in_array( $prod_id, $allowed_products, true ) ) {
return false;
}
}
return true;
}
public function frontend_check_coupon() {
$out = array();
$coupon_code = isset( $_POST['coupon_code'] ) ? sanitize_text_field( stripslashes ( $_POST['coupon_code'] ) ) : '';
if ( empty( $coupon_code ) ) {
$out['success'] = false;
$out['msg'] = __( 'Empty coupon code', 'stripe-payments' );
wp_send_json( $out );
}
$coupon_code = strtoupper( $coupon_code );
$tax = filter_input( INPUT_POST, 'tax', FILTER_SANITIZE_NUMBER_INT );
$tax = empty( $tax ) ? 0 : absint( $tax );
$shipping = filter_input( INPUT_POST, 'shipping', FILTER_SANITIZE_NUMBER_INT );
$shipping = empty( $shipping ) ? 0 : absint( $shipping );
$coupon = self::get_coupon( $coupon_code );
if ( ! $coupon['valid'] ) {
$out['success'] = false;
$out['msg'] = $coupon['err_msg'];
wp_send_json( $out );
}
$prod_id = filter_input( INPUT_POST, 'product_id', FILTER_SANITIZE_NUMBER_INT );
if ( empty( $prod_id ) ) {
$out['success'] = false;
$out['msg'] = __( 'No product ID specified.', 'stripe-payments' );
wp_send_json( $out );
}
if ( ! self::is_coupon_allowed_for_product( $coupon['id'], $prod_id ) ) {
$out['success'] = false;
$out['msg'] = __( 'Coupon is not allowed for this product.', 'stripe-payments' );
wp_send_json( $out );
}
$curr = isset( $_POST['curr'] ) ? sanitize_text_field( stripslashes ( $_POST['curr'] ) ) : '';
$curr = isset( $curr ) ? $curr : '';
$discount = $coupon['discount'];
$discount_type = $coupon['discountType'];
$amount = filter_input( INPUT_POST, 'amount', FILTER_SANITIZE_NUMBER_INT );
$perc = AcceptStripePayments::is_zero_cents( $curr ) ? 0 : 2;
if ( $coupon['discountType'] === 'perc' ) {
$discount_amount = round( $amount * ( $coupon['discount'] / 100 ), 0 );
} else {
$discount_amount = $coupon['discount'] * ( $perc === 0 ? 1 : 100 );
}
$out['discountAmount'] = $discount_amount;
$amount = round( ( $amount - $discount_amount ) / ( $perc === 0 ? 1 : 100 ), $perc );
$amount = AcceptStripePayments::apply_tax( $amount, $tax, AcceptStripePayments::is_zero_cents( $curr ) );
$amount = round( $amount + $shipping / 100, 2 );
$out['tax'] = $tax;
$out['shipping'] = $shipping;
$out['amount'] = $amount;
$out['success'] = true;
$out['code'] = $coupon_code;
$out['discount'] = $discount;
$out['discountType'] = $discount_type;
$out['discountStr'] = $coupon_code . ': - ' . ( $discount_type === 'perc' ? $discount . '%' : AcceptStripePayments::formatted_price( $discount, $curr ) );
$out['newAmountFmt'] = AcceptStripePayments::formatted_price( $amount, $curr );
wp_send_json( $out );
}
public function init_handler() {
$args = array(
'supports' => array( '' ),
'hierarchical' => false,
'public' => false,
'show_ui' => false,
'can_export' => false,
'has_archive' => false,
'exclude_from_search' => true,
'publicly_queryable' => false,
'capability_type' => 'post',
);
register_post_type( self::$post_slug, $args );
if ( ! is_admin() ) {
return;
}
$post_action = isset( $_POST['asp_coupon_action'] ) ? sanitize_text_field( stripslashes ( $_POST['asp_coupon_action'] ) ) : '';
$post_action = empty( $post_action ) ? '0' : $post_action;
switch ( $post_action ) {
case 'save_coupon':
$this->save_coupon();
break;
case 'save_settings':
$this->save_settings();
break;
default:
break;
}
$action = isset( $_GET['action'] ) ? sanitize_text_field( stripslashes ( $_GET['action'] ) ) : '';
$action = empty( $action ) ? '' : $action;
if ( $action === 'asp_delete_coupon' ) {
$this->delete_coupon();
}
}
public function add_menu() {
//Trigger filter hook to allow overriding of the add-ons menu capability.
$asp_coupons_menu_capability = apply_filters( 'asp_coupons_menu_capability', ASP_MANAGEMENT_PERMISSION );
add_submenu_page( 'edit.php?post_type=' . ASPMain::$products_slug, __( 'Coupons', 'stripe-payments' ), __( 'Coupons', 'stripe-payments' ), $asp_coupons_menu_capability, 'stripe-payments-coupons', array( $this, 'display_coupons_menu_page' ) );
}
public function save_settings() {
check_admin_referer( 'asp-coupons-settings' );
$settings = get_option( 'AcceptStripePayments-settings' );
$opts = filter_input( INPUT_POST, 'asp_coupons_opts', FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY );
$settings['coupons_enabled'] = isset( $opts['coupons_enabled'] ) ? 1 : 0;
update_option( 'AcceptStripePayments-settings', $settings );
AcceptStripePayments_Admin::add_admin_notice(
'success',
__( 'Settings updated.', 'stripe-payments' ),
false
);
}
public function display_coupons_menu_page() {
$action = isset( $_GET['action'] ) ? sanitize_text_field( stripslashes ( $_GET['action'] ) ) : '';
if ( ! empty( $action ) ) {
if ( $action === 'asp_add_edit_coupon' ) {
//coupon add or edit content
$this->display_coupon_add_edit_page();
return;
}
}
$asp_main = AcceptStripePayments::get_instance();
$coupons_enabled = $asp_main->get_setting( 'coupons_enabled' );
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
require_once WP_ASP_PLUGIN_PATH . 'admin/includes/class-coupons-list-table.php';
$coupons_tbl = new ASP_Coupons_Table();
$coupons_tbl->prepare_items();
?>
<style>
th#id {
width: 10%;
}
</style>
<div class="wrap">
<h2><?php esc_html_e( 'Coupons', 'stripe-payments' ); ?></h2>
<div id="poststuff">
<div id="post-body">
<div class="postbox">
<h3 class="hndle"><label for="title"><?php esc_html_e( 'Coupon Settings', 'stripe-payments' ); ?></label></h3>
<div class="inside">
<form method="post">
<input type="hidden" name="asp_coupon_action" value="save_settings">
<table class="form-table">
<tr>
<th scope="row"><?php esc_html_e( 'Enable Coupons', 'stripe-payments' ); ?></th>
<td>
<input type="checkbox" name="asp_coupons_opts[coupons_enabled]" <?php echo $coupons_enabled ? ' checked' : ''; ?>>
<p class="description"><?php esc_html_e( 'Enables the discount coupon functionality.', 'stripe-payments' ); ?></p>
</td>
</tr>
</table>
<?php
wp_nonce_field( 'asp-coupons-settings' );
submit_button( __( 'Save Settings', 'stripe-payments' ) );
?>
</form>
</div>
</div>
</div>
</div>
<h2><?php esc_html_e( 'Coupons', 'stripe-payments' ); ?> <a class="page-title-action" href="?post_type=<?php echo esc_attr( ASPMain::$products_slug ); ?>&page=stripe-payments-coupons&action=asp_add_edit_coupon"><?php esc_html_e( 'Add a Coupon', 'stripe-payments' ); ?></a></h2>
<?php $coupons_tbl->display(); ?>
</div>
<?php
}
public function display_coupon_add_edit_page() {
wp_enqueue_script( 'jquery-ui-datepicker' );
wp_register_style( 'jquery-ui', WP_ASP_PLUGIN_URL . '/admin/assets/css/jquery-ui-theme/jquery-ui.min.css' );
wp_enqueue_style( 'jquery-ui' );
$coupon_id = filter_input( INPUT_GET, 'asp_coupon_id', FILTER_SANITIZE_NUMBER_INT );
$coupon_id = empty( $coupon_id ) ? false : absint( $coupon_id );
$is_edit = $coupon_id ? true : false;
if ( $is_edit ) {
if ( is_null( get_post( $coupon_id ) ) ) {
echo 'error';
return false;
}
$coupon = array(
'id' => $coupon_id,
'code' => get_post_meta( $coupon_id, 'asp_coupon_code', true ),
'active' => get_post_meta( $coupon_id, 'asp_coupon_active', true ),
'discount' => get_post_meta( $coupon_id, 'asp_coupon_discount', true ),
'discount_type' => get_post_meta( $coupon_id, 'asp_coupon_discount_type', true ),
'red_limit' => get_post_meta( $coupon_id, 'asp_coupon_red_limit', true ),
'red_count' => get_post_meta( $coupon_id, 'asp_coupon_red_count', true ),
'start_date' => get_post_meta( $coupon_id, 'asp_coupon_start_date', true ),
'exp_date' => get_post_meta( $coupon_id, 'asp_coupon_exp_date', true ),
'only_for_allowed_products' => get_post_meta( $coupon_id, 'asp_coupon_only_for_allowed_products', true ),
'allowed_products' => get_post_meta( $coupon_id, 'asp_coupon_allowed_products', true ),
'per_order' => get_post_meta( $coupon_id, 'asp_coupon_per_order', true ),
);
}
//generate array with all products
$posts = get_posts(
array(
'post_type' => untrailingslashit( ASPMain::$products_slug ),
'post_status' => 'publish',
'numberposts' => -1,
)
);
$prod_inputs = '';
$input_tpl = '<label><input type="checkbox" name="asp_coupon[allowed_products][]" value="%s"%s> %s</label>';
if ( $posts ) {
foreach ( $posts as $the_post ) {
$checked = '';
if ( ! empty( $coupon ) && is_array( $coupon['allowed_products'] ) ) {
if ( in_array( strval( $the_post->ID ), $coupon['allowed_products'], true ) ) {
$checked = ' checked';
}
}
$prod_inputs .= sprintf( $input_tpl, $the_post->ID, $checked, $the_post->post_title );
$prod_inputs .= '<br>';
}
} else {
$prod_inputs = __( 'No products created yet.', 'stripe-payments' );
}
wp_reset_postdata();
?>
<div class="wrap">
<h2><?php empty( $coupon_id ) ? esc_html_e( 'Add Coupon', 'stripe-payments' ) : esc_html_e( 'Edit Coupon', 'stripe-payments' ); ?></h2>
<form method="post">
<input type="hidden" name="asp_coupon_action" value="save_coupon">
<table class="form-table">
<tr>
<th scope="row"><?php esc_html_e( 'Active', 'stripe-payments' ); ?></th>
<td>
<input type="checkbox" name="asp_coupon[active]" <?php echo ( ! $is_edit ) || ( $is_edit && $coupon['active'] ) ? 'checked' : ''; ?>>
<p class="description"><?php esc_html_e( 'Use this to enable/disable this coupon.', 'stripe-payments' ); ?></p>
</td>
</tr>
<?php if ( $is_edit ) { ?>
<tr>
<th scope="row"><?php esc_html_e( 'Coupon ID', 'stripe-payments' ); ?></th>
<td>
<input type="hidden" name="asp_coupon_id" value="<?php echo esc_attr( $coupon_id ); ?>">
<?php echo esc_html( $coupon_id ); ?>
<p class="description"><?php esc_html_e( 'Coupon ID. This value cannot be changed.', 'stripe-payments' ); ?></p>
</td>
</tr>
<?php } ?>
<tr>
<th scope="row"><?php esc_html_e( 'Coupon Code', 'stripe-payments' ); ?></th>
<td>
<input type="text" name="asp_coupon[code]" value="<?php echo $is_edit ? esc_attr( $coupon['code'] ) : ''; ?>">
<p class="description"><?php esc_html_e( 'Coupon code that you can share with your customers. Example: GET10OFF', 'stripe-payments' ); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Discount', 'stripe-payments' ); ?></th>
<td>
<input style="vertical-align: middle;" type="number" name="asp_coupon[discount]" min="0" step="0.01" <?php echo $is_edit && $coupon['discount_type'] === 'perc' ? 'max="100"' : ''; ?>value="<?php echo $is_edit ? esc_attr( $coupon['discount'] ) : ''; ?>">
<select name="asp_coupon[discount_type]">
<option value="perc" <?php echo $is_edit && $coupon['discount_type'] === 'perc' ? ' selected' : ''; ?>><?php esc_html_e( 'Percent (%)', 'stripe-payments' ); ?></option>
<option value="fixed" <?php echo $is_edit && $coupon['discount_type'] === 'fixed' ? ' selected' : ''; ?>><?php esc_html_e( 'Fixed amount', 'stripe-payments' ); ?></option>
</select>
<p class="description"><?php esc_html_e( 'Select discount amount and type. Enter a numeric value only. Example: 25', 'stripe-payments' ); ?></p>
<div id="asp-coupon-per-order-cont" <?php echo $is_edit && $coupon['discount_type'] === 'fixed' ? '' : ' style="display:none;"'; ?>>
<br>
<label><input type="checkbox" name="asp_coupon[per_order]" value="1"<?php echo $is_edit && ! empty( $coupon['per_order'] ) ? ' checked' : ''; ?>> <?php esc_html_e( 'Apply Per-Order', 'stripe-payments' ); ?></label>
<p class="description">
<?php esc_html_e( 'If enabled, discount is applied on per-order basis rather than per-item.', 'stripe-payments' ); ?>
<br />
<em><?php esc_html_e( 'This option is only available for "fixed amount" type coupons.', 'stripe-payments' ); ?></em>
</p>
</div>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Redemption Limit', 'stripe-payments' ); ?></th>
<td>
<input type="number" name="asp_coupon[red_limit]" value="<?php echo $is_edit ? esc_attr( $coupon['red_limit'] ) : 0; ?>">
<p class="description"><?php esc_html_e( 'Set max number of coupons available for redemption. Put 0 to make it unlimited.', 'stripe-payments' ); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Redemption Count', 'stripe-payments' ); ?></th>
<td>
<input type="number" name="asp_coupon[red_count]" value="<?php echo $is_edit ? esc_attr( $coupon['red_count'] ) : 0; ?>">
<p class="description"><?php esc_html_e( 'Number of already redeemed coupons.', 'stripe-payments' ); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Start Date', 'stripe-payments' ); ?></th>
<td>
<input class="datepicker-input" type="text" name="asp_coupon[start_date]" value="<?php echo $is_edit ? esc_attr( $coupon['start_date'] ) : esc_attr( date( 'Y-m-d' ) ); ?>">
<p class="description"><?php esc_html_e( 'Start date when this coupon can be used.', 'stripe-payments' ); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Expiry Date', 'stripe-payments' ); ?></th>
<td>
<input class="datepicker-input" type="text" name="asp_coupon[exp_date]" value="<?php echo $is_edit ? esc_attr( $coupon['exp_date'] ) : 0; ?>">
<p class="description"><?php esc_html_e( 'Date when this coupon will expire. Put 0 to disable expiry check.', 'stripe-payments' ); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Coupon Available For:', 'stripe-payments' ); ?></th>
<td>
<label><input type="radio" name="asp_coupon[only_for_allowed_products]" value="0" <?php echo ! $is_edit || ( $is_edit && ! $coupon['only_for_allowed_products'] ) ? ' checked' : ''; ?>> <?php esc_html_e( 'All products', 'stripe-payments' ); ?></label>
<br>
<label><input type="radio" name="asp_coupon[only_for_allowed_products]" value="1" <?php echo $is_edit && $coupon['only_for_allowed_products'] ? ' checked' : ''; ?>> <?php esc_html_e( 'Specific Products Only', 'stripe-payments' ); ?></label>
<p class="asp-coupons-available-products" <?php echo ( $is_edit && ! $coupon['only_for_allowed_products'] ) || ( ! $is_edit ) ? ' style="display: none;"' : ''; ?>>
<?php echo wp_kses( $prod_inputs, ASP_Utils::asp_allowed_tags() ); ?>
</p>
<p class="description"><?php esc_html_e( 'Choose availability of the coupon. You can specify which products the coupon is available to when the "Specific Products Only" option is selected.', 'stripe-payments' ); ?></p>
</td>
</tr>
<?php
do_action( 'asp_admin_add_edit_coupon', $coupon_id );
?>
</table>
<?php
wp_nonce_field( 'asp-add-edit-coupon' );
submit_button( $is_edit ? __( 'Update Coupon', 'stripe-payments' ) : __( 'Create Coupon', 'stripe-payments' ) );
?>
</form>
</div>
<script>
jQuery(document).ready(function($) {
$('.datepicker-input').datepicker({
dateFormat: 'yy-mm-dd'
});
$('input[name="asp_coupon[only_for_allowed_products]"]').change(function() {
if ($(this).val() === "1") {
$('.asp-coupons-available-products').show();
} else {
$('.asp-coupons-available-products').hide();
}
});
$('select[name="asp_coupon[discount_type]"]').change(function() {
if (this.value === 'fixed') {
jQuery('input[name="asp_coupon[discount]"]').prop('max', '');
$('#asp-coupon-per-order-cont').slideDown('fast');
} else {
jQuery('input[name="asp_coupon[discount]"]').prop('max', 100);
$('#asp-coupon-per-order-cont').slideUp('fast');
}
});
});
</script>
<?php
}
public function delete_coupon() {
$coupon_id = isset( $_GET['asp_coupon_id'] ) ? absint( $_GET['asp_coupon_id'] ) : false;
if ( ! $coupon_id ) {
AcceptStripePayments_Admin::add_admin_notice(
'error',
__( 'Can\'t delete coupon: coupon ID is not provided.', 'stripe-payments' ),
false
);
return false;
}
$the_post = get_post( $coupon_id );
if ( is_null( $the_post ) ) {
AcceptStripePayments_Admin::add_admin_notice(
'error',
// translators: %d is coupon ID
sprintf( __( 'Can\'t delete coupon: coupon #%d not found.', 'stripe-payments' ), $coupon_id ),
false
);
return false;
}
if ( $the_post->post_type !== self::$post_slug ) {
AcceptStripePayments_Admin::add_admin_notice(
'error',
// translators: %d is coupon ID
sprintf( __( 'Can\'t delete coupon: post #%d is not a coupon.', 'stripe-payments' ), $coupon_id ),
false
);
return false;
}
check_admin_referer( 'delete-coupon_' . $coupon_id );
wp_delete_post( $coupon_id, true );
AcceptStripePayments_Admin::add_admin_notice(
'success',
// translators: %d is coupon ID
sprintf( __( 'Coupon #%d has been deleted.', 'stripe-payments' ), $coupon_id ),
false
);
wp_safe_redirect( remove_query_arg( array( 'action', 'asp_coupon_id', '_wpnonce' ) ) );
exit();
}
public function save_coupon() {
check_admin_referer( 'asp-add-edit-coupon' );
$coupon = filter_input( INPUT_POST, 'asp_coupon', FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY );
$coupon_id = isset( $_POST['asp_coupon_id'] ) ? absint( $_POST['asp_coupon_id'] ) : false;
$is_edit = $coupon_id ? true : false;
$err_msg = array();
$coupon['active'] = isset( $coupon['active'] ) ? 1 : 0;
$coupon['per_order'] = isset( $coupon['per_order'] ) ? 1 : 0;
$coupon['code'] = ! empty( $coupon['code'] ) ? sanitize_text_field( $coupon['code'] ) : '';
if ( empty( $coupon['code'] ) ) {
$err_msg[] = __( 'Please enter coupon code.', 'stripe-payments' );
}
if ( empty( $coupon['discount'] ) ) {
$err_msg[] = __( 'Please enter discount.', 'stripe-payments' );
}
if ( $coupon['discount_type'] === 'perc' && $coupon['discount'] > 100 ) {
$err_msg[] = __( "Discount can't be more than 100%.", 'stripe-payments' );
}
if ( ! empty( $err_msg ) ) {
foreach ( $err_msg as $msg ) {
AcceptStripePayments_Admin::add_admin_notice( 'error', $msg, false );
}
return false;
}
if ( ! $is_edit ) {
$post = array();
$post['post_title'] = '';
$post['post_status'] = 'publish';
$post['content'] = '';
$post['post_type'] = self::$post_slug;
$coupon_id = wp_insert_post( $post );
}
if ( empty( $coupon['allowed_products'] ) ) {
$coupon['allowed_products'] = array();
}
foreach ( $coupon as $key => $value ) {
update_post_meta( $coupon_id, 'asp_coupon_' . $key, $value );
}
do_action( 'asp_admin_save_coupon', $coupon_id, $coupon );
AcceptStripePayments_Admin::add_admin_notice(
'success',
// translators: %s is coupon code
sprintf( $is_edit ? __( 'Coupon "%s" has been updated.', 'stripe-payments' ) : __( 'Coupon "%s" has been created.', 'stripe-payments' ), $coupon['code'] ),
false
);
wp_safe_redirect( 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-coupons' );
exit;
}
}
new AcceptStripePayments_CouponsAdmin();

View File

@ -0,0 +1,408 @@
<?php
class ASPOrder {
/**
* Instance of this class.
*
* @since 1.0.0
*
* @var object
*/
protected static $instance = null;
private $order_status_tpl = '<span class="asp-order-status%s">%s</span>';
public $AcceptStripePayments;
public function __construct() {
self::$instance = $this;
$this->AcceptStripePayments = AcceptStripePayments::get_instance();
if ( is_admin() ) {
//products meta boxes handler
require_once WP_ASP_PLUGIN_PATH . 'admin/includes/class-asp-admin-order-meta-boxes.php';
$show_incomplete = $this->AcceptStripePayments->get_setting( 'show_incomplete_orders' );
if ( ! $show_incomplete ) {
add_filter( 'pre_get_posts', array( $this, 'filter_posts' ) );
add_filter( 'views_edit-stripe_order', array( $this, 'remove_views' ) );
}
}
}
public function register_post_type() {
$labels = array(
'name' => _x( 'Orders', 'Post Type General Name', 'stripe-payments' ),
'singular_name' => _x( 'Order', 'Post Type Singular Name', 'stripe-payments' ),
'parent_item_colon' => __( 'Parent Order:', 'stripe-payments' ),
'all_items' => __( 'Orders', 'stripe-payments' ),
'view_item' => __( 'View Order', 'stripe-payments' ),
'add_new_item' => __( 'Add New Order', 'stripe-payments' ),
'add_new' => __( 'Add New', 'stripe-payments' ),
'edit_item' => __( 'Edit Order', 'stripe-payments' ),
'update_item' => __( 'Update Order', 'stripe-payments' ),
'search_items' => __( 'Search Order', 'stripe-payments' ),
'not_found' => __( 'Not found', 'stripe-payments' ),
'not_found_in_trash' => __( 'Not found in Trash', 'stripe-payments' ),
);
$args = array(
'label' => __( 'orders', 'stripe-payments' ),
'description' => __( 'Stripe Orders', 'stripe-payments' ),
'labels' => $labels,
'supports' => array( 'title', 'editor', 'excerpt', 'revisions', 'custom-fields' ),
'hierarchical' => false,
'public' => false,
'show_ui' => true,
'show_in_menu' => 'edit.php?post_type=' . ASPMain::$products_slug,
'can_export' => true,
'has_archive' => false,
'exclude_from_search' => true,
'publicly_queryable' => false,
'capability_type' => 'post',
'capabilities' => array(
'create_posts' => false, // Removes support for the "Add New" function
),
'map_meta_cap' => true,
);
$args = apply_filters( 'asp_stripe_order_register_post_type_args', $args );
register_post_type( 'stripe_order', $args );
add_filter( 'manage_stripe_order_posts_columns', array( $this, 'manage_columns' ) );
add_action( 'manage_stripe_order_posts_custom_column', array( $this, 'manage_custom_columns' ), 10, 2 );
//set custom columns sortable
// add_filter( 'manage_edit-stripe_order_sortable_columns', array( $this, 'manage_sortable_columns' ) );
if ( wp_doing_ajax() ) {
add_action( 'wp_ajax_asp_order_capture_confirm', array( $this, 'order_capture_confirm' ) );
add_action( 'wp_ajax_asp_order_capture_cancel', array( $this, 'order_capture_cancel' ) );
}
}
/**
* Return an instance of this class.
*
* @since 1.0.0
*
* @return object A single instance of this class.
*/
public static function get_instance() {
// If the single instance hasn't been set, set it now.
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public function filter_posts( $wp_query ) {
global $pagenow;
if ( 'edit.php' !== $pagenow ) {
return;
}
if ( ! is_admin() ) {
return;
}
if ( $wp_query->is_main_query() && 'stripe_order' === $wp_query->query['post_type'] ) {
if ( empty( $wp_query->query_vars['post_status'] ) ) {
$wp_query->query_vars['post_status'] = array(
'publish',
'private',
'trash',
);
}
}
}
public function remove_views( $views ) {
if ( ! current_user_can( ASP_MANAGEMENT_PERMISSION ) ) {
return $views;
}
$remove_views = array( 'mine', 'pending', 'draft' );
foreach ( (array) $remove_views as $view ) {
if ( isset( $views[ $view ] ) ) {
unset( $views[ $view ] );
}
}
return $views;
}
public function manage_columns( $columns ) {
$custom_columns = array(
'total' => __( 'Total', 'stripe-payments' ),
'status' => __( 'Status', 'stripe-payments' ),
);
$columns = array_merge( $columns, $custom_columns );
return $columns;
}
public function manage_custom_columns( $column, $post_id ) {
switch ( $column ) {
case 'status':
$data = get_post_meta( $post_id, 'order_data', true );
$status = get_post_meta( $post_id, 'asp_order_status', true );
if ( empty( $status ) ) {
if ( ! isset( $data['charge']->paid ) ||
( isset( $data['charge']->paid ) && $data['charge']->paid &&
$data['charge']->captured ) ) {
echo sprintf( $this->order_status_tpl, ' paid', __( 'Paid', 'stripe-payments' ) );
} else {
if ( isset( $data['charge']->captured ) && false === $data['charge']->captured &&
empty( $data['charge']->amount_refunded ) ) {
echo sprintf( $this->order_status_tpl, ' authorized', __( 'Authorized', 'stripe-payments' ) );
$action_nonce = wp_create_nonce( 'asp-order-actions-' . $post_id );
echo '<div class="asp-order-actions-cont">';
echo sprintf( '<a class="asp-order-action" data-action="confirm" href="#" data-order-id="%d" data-nonce="%s">' . __( 'Capture', 'stripe-payments' ) . '</a> | ', $post_id, $action_nonce );
echo sprintf( '<a class= "asp-order-action" data-action="cancel" style="color:#a00;" href="#" data-order-id="%d" data-nonce="%s">' . __( 'Cancel', 'stripe-payments' ) . '</a>', $post_id, $action_nonce );
echo '</div>';
} else {
echo sprintf( $this->order_status_tpl, ' canceled', __( 'Canceled', 'stripe-payments' ) );
}
}
} else {
//we have status set
switch ( $status ) {
case 'authorized':
echo sprintf( $this->order_status_tpl, ' ' . $status, self::get_status_str( $status ) );
$action_nonce = wp_create_nonce( 'asp-order-actions-' . $post_id );
echo '<div class="asp-order-actions-cont">';
echo sprintf( '<a class="asp-order-action" data-action="confirm" href="#" data-order-id="%d" data-nonce="%s">' . __( 'Capture', 'stripe-payments' ) . '</a> | ', $post_id, $action_nonce );
echo sprintf( '<a class= "asp-order-action" data-action="cancel" style="color:#a00;" href="#" data-order-id="%d" data-nonce="%s">' . __( 'Cancel', 'stripe-payments' ) . '</a>', $post_id, $action_nonce );
echo '</div>';
break;
case 'error':
$order_events = get_post_meta( $post_id, 'asp_order_events', false );
if ( ! empty( $order_events ) && is_array( $order_events ) ) {
echo sprintf( '<span class="asp-order-status%s" data-balloon-length="medium" data-balloon-pos="up" aria-label="%s">%s</span>', ' ' . $status, end( $order_events[0] )['comment'], self::get_status_str( $status ) );
} else {
echo sprintf( $this->order_status_tpl, ' ' . $status, self::get_status_str( $status ) );
}
break;
default:
echo sprintf( $this->order_status_tpl, ' ' . $status, self::get_status_str( $status ) );
break;
}
}
break;
case 'total':
$data = get_post_meta( $post_id, 'order_data', true );
if ( $data ) {
echo ASP_Utils::formatted_price( $data['paid_amount'], $data['currency_code'] );
} else {
echo '—';
}
break;
}
}
public function order_capture_confirm() {
$post_id = filter_input( INPUT_POST, 'order_id', FILTER_SANITIZE_NUMBER_INT );
if ( empty( $post_id ) ) {
wp_send_json(
array(
'success' => false,
'err_msg' => __( 'Invalid order ID', 'stripe-payments' ),
)
);
}
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( stripslashes ( $_POST['nonce'] ) ) : '';
if ( empty( $nonce ) || false === wp_verify_nonce( $nonce, 'asp-order-actions-' . $post_id ) ) {
wp_send_json(
array(
'success' => false,
'err_msg' => __( 'Nonce check failed', 'stripe-payments' ),
)
);
}
$order = new ASP_Order_Item();
$order->set_id( $post_id );
ASP_Utils::load_stripe_php_sdk_if_enabled();//Load the Stripe SDK (if enabled) so it can read the Stripe classes in the order object.
$data = get_post_meta( $post_id, 'order_data', true );
$asp_main = AcceptStripePayments::get_instance();
try {
ASP_Utils::load_stripe_lib();
$key = $data['is_live'] ? $asp_main->APISecKey : $asp_main->APISecKeyTest;
\Stripe\Stripe::setApiKey( $key );
$api = ASP_Stripe_API::get_instance();
$api->set_api_key( $key );
if ( ASP_Utils::use_internal_api() ) {
$intent = $api->get( 'payment_intents/' . $data['charge']->payment_intent );
} else {
$intent = \Stripe\PaymentIntent::retrieve( $data['charge']->payment_intent );
}
if ( 'requires_capture' !== $intent->status ) {
//already captured or canceled
$data['charge'] = $intent->charges->data[0];
update_post_meta( $post_id, 'order_data', $data );
if ( 'canceled' === $intent->status ) {
$order->change_status( 'canceled' );
}
if ( 'succeeded' === $intent->status ) {
$order->change_status( 'paid' );
}
wp_send_json(
array(
'success' => false,
'err_msg' => __( 'Funds already captured or refunded', 'stripe-payments' ),
'order_status' => sprintf( $this->order_status_tpl, ' ' . $order->get_status(), self::get_status_str( $order->get_status() ) ),
)
);
}
if ( ASP_Utils::use_internal_api() ) {
$intent = $api->post( 'payment_intents/' . $data['charge']->payment_intent . '/capture' );
} else {
$intent->capture();
}
} catch ( \Exception $e ) {
wp_send_json(
array(
'success' => false,
'err_msg' => $e->getMessage(),
)
);
}
$data['charge'] = $intent->charges->data[0];
update_post_meta( $post_id, 'order_data', $data );
$order->change_status( 'paid' );
wp_send_json(
array(
'success' => true,
'order_status' => sprintf( $this->order_status_tpl, ' ' . $order->get_status(), self::get_status_str( $order->get_status() ) ),
)
);
}
public function order_capture_cancel() {
$post_id = filter_input( INPUT_POST, 'order_id', FILTER_SANITIZE_NUMBER_INT );
if ( empty( $post_id ) ) {
wp_send_json(
array(
'success' => false,
'err_msg' => __( 'Invalid order ID', 'stripe-payments' ),
)
);
}
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( stripslashes ( $_POST['nonce'] ) ) : '';
if ( empty( $nonce ) || false === wp_verify_nonce( $nonce, 'asp-order-actions-' . $post_id ) ) {
wp_send_json(
array(
'success' => false,
'err_msg' => __( 'Nonce check failed', 'stripe-payments' ),
)
);
}
$order = new ASP_Order_Item();
$order->set_id( $post_id );
ASP_Utils::load_stripe_php_sdk_if_enabled();//Load the Stripe SDK (if enabled) so it can read the Stripe classes in the order object.
$data = get_post_meta( $post_id, 'order_data', true );
$asp_main = AcceptStripePayments::get_instance();
try {
ASP_Utils::load_stripe_lib();
$key = $data['is_live'] ? $asp_main->APISecKey : $asp_main->APISecKeyTest;
\Stripe\Stripe::setApiKey( $key );
$api = ASP_Stripe_API::get_instance();
$api->set_api_key( $key );
if ( ASP_Utils::use_internal_api() ) {
$intent = $api->get( 'payment_intents/' . $data['charge']->payment_intent );
} else {
$intent = \Stripe\PaymentIntent::retrieve( $data['charge']->payment_intent );
}
if ( 'requires_capture' !== $intent->status ) {
//already captured or canceled
$data['charge'] = $intent->charges->data[0];
update_post_meta( $post_id, 'order_data', $data );
if ( 'canceled' === $intent->status ) {
$order->change_status( 'canceled' );
}
if ( 'succeeded' === $intent->status ) {
$order->change_status( 'paid' );
}
wp_send_json(
array(
'success' => false,
'err_msg' => __( 'Funds already captured or refunded', 'stripe-payments' ),
'order_status' => sprintf( $this->order_status_tpl, ' ' . $order->get_status(), self::get_status_str( $order->get_status() ) ),
)
);
}
if ( ASP_Utils::use_internal_api() ) {
$intent = $api->post( 'payment_intents/' . $data['charge']->payment_intent . '/cancel' );
} else {
$intent->cancel();
}
} catch ( \Exception $e ) {
wp_send_json(
array(
'success' => false,
'err_msg' => $e->getMessage(),
)
);
}
$data['charge'] = $intent->charges->data[0];
update_post_meta( $post_id, 'order_data', $data );
$order->change_status( 'canceled' );
wp_send_json(
array(
'success' => true,
'order_status' => sprintf( $this->order_status_tpl, ' ' . $order->get_status(), self::get_status_str( $order->get_status() ) ),
)
);
}
public static function get_status_str( $status ) {
$status_str = array(
'incomplete' => __( 'Incomplete', 'stripe-payments' ),
'paid' => __( 'Paid', 'stripe-payments' ),
'authorized' => __( 'Authorized', 'stripe-payments' ),
'canceled' => __( 'Canceled', 'stripe-payments' ),
'error' => __( 'Error', 'stripe-payments' ),
);
if ( isset( $status_str[ $status ] ) ) {
return $status_str[ $status ];
}
return false;
}
}

View File

@ -0,0 +1,70 @@
<?php
class ASPVariations {
var $groups = array();
var $variations = array();
var $prod_id = false;
function __construct( $prod_id ) {
$this->prod_id = $prod_id;
$this->_get_variations();
}
private function _get_variations() {
$variations_groups = get_post_meta( $this->prod_id, 'asp_variations_groups', true );
if ( empty( $variations_groups ) ) {
return false;
}
$this->groups = $variations_groups;
foreach ( $variations_groups as $grp_id => $group ) {
$variations_names = get_post_meta( $this->prod_id, 'asp_variations_names', true );
if ( ! empty( $variations_names ) ) {
$variations_prices_orig = get_post_meta( $this->prod_id, 'asp_variations_prices', true );
$variations_prices = apply_filters( 'asp_variations_prices_filter', $variations_prices_orig, $this->prod_id );
$variations_urls = get_post_meta( $this->prod_id, 'asp_variations_urls', true );
$variations_opts = get_post_meta( $this->prod_id, 'asp_variations_opts', true );
$this->variations[ $grp_id ]['names'] = $variations_names[ $grp_id ];
$this->variations[ $grp_id ]['prices'] = $variations_prices[ $grp_id ];
$this->variations[ $grp_id ]['urls'] = $variations_urls[ $grp_id ];
$this->variations[ $grp_id ]['opts'] = isset( $variations_opts[ $grp_id ] ) ? $variations_opts[ $grp_id ] : 0;
}
}
}
public function get_variation( $grp_id, $var_id ) {
if ( empty( $this->variations[ $grp_id ] ) ) {
return false;
}
if ( empty( $this->variations[ $grp_id ]['names'][ $var_id ] ) ) {
return false;
}
$var = array(
'grp_id' => $grp_id,
'id' => $var_id,
'group_name' => $this->groups[ $grp_id ],
'name' => $this->variations[ $grp_id ]['names'][ $var_id ],
'price' => $this->variations[ $grp_id ]['prices'][ $var_id ],
'url' => $this->variations[ $grp_id ]['urls'][ $var_id ],
'opts' => isset( $this->variations[ $grp_id ]['opts'][ $var_id ] ) ? $this->variations[ $grp_id ]['opts'][ $var_id ] : array(),
);
return $var;
}
public function get_group( $grp_id ) {
if ( empty( $this->variations[ $grp_id ] ) ) {
return false;
}
$grp = array(
'id' => $grp_id,
'group_name' => $this->groups[ $grp_id ],
'type' => isset( $this->variations[ $grp_id ]['opts']['type'] ) ? $this->variations[ $grp_id ]['opts']['type'] : $this->variations[ $grp_id ]['opts'],
'opts' => isset( $this->variations[ $grp_id ]['opts'] ) ? $this->variations[ $grp_id ]['opts'] : array(),
);
return $grp;
}
}

View File

@ -0,0 +1 @@
<?php // Silence is golden

View File

@ -0,0 +1,219 @@
<?php
/**
* Represents the view for the addons listing page.
*/
if ( ! current_user_can( ASP_MANAGEMENT_PERMISSION ) ) {
wp_die( 'You do not have permission to access this menu page.' );
}
$output = '';
?>
<div class="wrap">
<h1><?php _e( 'Add-ons', 'stripe-payments' ); ?></h1>
<div id="poststuff">
<div id="post-body">
<?php
$addons_data = array();
$addon_1 = array(
'name' => __( 'Subscription Payments', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/subscription-payments.png',
'description' => __( 'This addon allows you to configure and sell subscription and recurring payments to your customers.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-subscription-payments-addon/',
'settings_url' => sprintf( 'edit.php?post_type=%s&page=stripe-payments-settings#sub', ASPMain::$products_slug ),
'installed' => class_exists( 'ASPSUB_main' ) ? true : false,
);
array_push( $addons_data, $addon_1 );
$addon_2 = array(
'name' => __( 'Apple and Google Pay', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/apple-android-pay.png',
'description' => __( 'This addon allows you to accept payments from your customers using Apple and Google Pay.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-additional-payment-methods-addon/',
'settings_url' => sprintf( 'edit.php?post_type=%s&page=stripe-payments-settings#apm', ASPMain::$products_slug ),
'installed' => class_exists( 'ASPAPM_main' ) ? true : false,
);
array_push( $addons_data, $addon_2 );
$addon_3 = array(
'name' => __( 'Secure Downloads', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/secure-downloads.png',
'description' => __( 'Digital products sold to your customers are secured by an encrypted download link that expires automatically.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/protecting-your-digital-downloads-using-the-secure-downloads-addon/',
'settings_url' => sprintf( 'edit.php?post_type=%s&page=stripe-payments-settings#securedownloads', ASPMain::$products_slug ),
'installed' => class_exists( 'ASPSD_main' ) ? true : false,
);
array_push( $addons_data, $addon_3 );
$addon_4 = array(
'name' => __( 'MailChimp Integration', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/maichimp-integration.png',
'description' => __( 'This extension allows you to add customers to your Mailchimp list after they purchase a product.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/mailchimp-integration-addon-stripe-payments/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#mailchimp',
'installed' => class_exists( 'ASPMCI_main' ) ? true : false,
);
array_push( $addons_data, $addon_4 );
$addon_6 = array(
'name' => __( 'Alipay Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/alipay-stripe-payments-addon.png',
'description' => __( 'When you enable this addon, it gives you the ability to accept payments via Alipay on your website', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/alipay-addon-stripe-payments-plugin/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#alipay',
'installed' => class_exists( 'ASPALI_main' ) ? true : false,
);
array_push( $addons_data, $addon_6 );
$addon_7 = array(
'name' => __( 'WP Affiliate Integration', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/wp-affiliate-integration.png',
'description' => __( 'The affiliate plugin will track customers that purchase items and award the affiliate that referred the customer.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-payments-wp-affiliate-plugin-integration/',
'settings_url' => '',
'installed' => false,
);
array_push( $addons_data, $addon_7 );
$addon_8 = array(
'name' => __( 'Multi-Currency Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/stripe-multi-currency-addon.png',
'description' => __( 'The multi-currency addon allows your customers to pick a currency and pay for the item in that currency.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-payments-multi-currency-addon/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#multicurr',
'installed' => class_exists( 'ASPMULTICURR_main' ) ? true : false,
);
array_push( $addons_data, $addon_8 );
$addon_9 = array(
'name' => __( 'Custom Messages Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/stripe-custom-messages-addon.png',
'description' => __( 'This addon allows you to customize a number of common messages displayed by the Stripe Payments Plugin.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-payments-custom-messages-addon/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#custmsg',
'installed' => class_exists( 'ASPCUSTMSG_main' ) ? true : false,
);
array_push( $addons_data, $addon_9 );
$addon_10 = array(
'name' => __( 'AWeber Integration Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/aweber-integration-addon.png',
'description' => __( 'This addon allows you to add customers to your AWeber list after they purchase a product.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/aweber-integration-addon-for-stripe-payments/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#aweber',
'installed' => class_exists( 'ASPAWEBER_main' ) ? true : false,
);
array_push( $addons_data, $addon_10 );
$addon_11 = array(
'name' => __( 'ConvertKit Integration Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/convertkit-integration.png',
'description' => __( 'This addon allows you to add customers to your ConvertKit list after they purchase a product.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-convertkit-integration-addon/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#convertkit',
'installed' => class_exists( 'ASPCK_main' ) ? true : false,
);
array_push( $addons_data, $addon_11 );
$addon_12 = array(
'name' => __( 'Post Payment Actions Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/post-payment-actions.png',
'description' => __( 'Post Payment Actions are triggered after a successful Stripe Payments transaction has been completed.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/post-payment-actions-addon-for-stripe-payments/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#ppa',
'installed' => class_exists( 'ASPPPA_main' ) ? true : false,
);
array_push( $addons_data, $addon_12 );
$addon_13 = array(
'name' => __( 'SOFORT Payments Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/sofort-payments.png',
'description' => __( 'The SOFORT Addon can be used along side the Stripe Payments Plugin to allow your customers to pay using SOFORT.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-sofort-payment-addon/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#sofort',
'installed' => class_exists( 'ASPSOFORT_main' ) ? true : false,
);
array_push( $addons_data, $addon_13 );
$addon_14 = array(
'name' => __( 'iDEAL Payments Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/iDEAL-payment-gateway-addon.png',
'description' => __( 'The iDEAL Addon can be used along side the Stripe Payments Plugin to allow your customers to pay using iDEAL gateway.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-ideal-payment-addon/',
'settings_url' => sprintf( 'edit.php?post_type=%s&page=stripe-payments-settings#ideal', ASPMain::$products_slug ),
'installed' => class_exists( 'ASPIDEAL_main' ) ? true : false,
);
array_push( $addons_data, $addon_14 );
$addon_15 = array(
'name' => __( 'Additional Custom Fields', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/additional-custom-fields.png',
'description' => __( 'The Additional Custom Fields Addon allows you to collect information from your customers before they proceed to checkout.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-payments-additional-custom-fields-addon/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#acf',
'installed' => class_exists( 'ASPACF_main' ) ? true : false,
);
array_push( $addons_data, $addon_15 );
$addon_16 = array(
'name' => __( 'MailerLite Addon', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/mailer-lite-integration.png',
'description' => __( 'This addon allows you to add customers to your MailerLite group after they purchase a product.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-payments-mailerlite-integration-addon/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#mailerlite',
'installed' => class_exists( 'ASP_Mailerlite_Main' ) ? true : false,
);
array_push( $addons_data, $addon_16 );
$addon_17 = array(
'name' => __( 'Google Analytics Tracking', 'stripe-payments' ),
'thumbnail' => WP_ASP_PLUGIN_URL . '/admin/assets/images/google-analytics-ecommerce-tracking.png',
'description' => __( 'This addon allows you to do Google analytics eCommerce tracking for our Stripe plugin transactions.', 'stripe-payments' ),
'page_url' => 'https://s-plugins.com/stripe-payments-google-analytics-ecommerce-tracking-addon/',
'settings_url' => 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#gaet',
'installed' => class_exists( 'ASPGAET_main' ) ? true : false,
);
array_push( $addons_data, $addon_17 );
/* Show the addons list */
foreach ( $addons_data as $addon ) {
$output .= '<div class="stripe_addon_item_canvas">';
$output .= '<div class="stripe_addon_item_thumb">';
if ( $addon['installed'] ) {
$output .= '<div class="stripe-addon-item-installed-mark"><span class="dashicons dashicons-yes" title="' . __( 'Add-on installed', 'stripe-payments' ) . '"></span></div>';
}
$img_src = $addon['thumbnail'];
$output .= '<img width="256" height="190" src="' . $img_src . '" alt="' . $addon['name'] . '">';
$output .= '</div>'; //end thumbnail
$output .= '<div class="stripe_addon_item_body">';
$output .= '<div class="stripe_addon_item_name">';
$output .= '<a href="' . $addon['page_url'] . '" target="_blank">' . $addon['name'] . '</a>';
$output .= '</div>'; //end name
$output .= '<div class="stripe_addon_item_description">';
$output .= $addon['description'];
$output .= '</div>'; //end description
$output .= '<div class="stripe_addon_item_details_link">';
$output .= '<a href="' . $addon['page_url'] . '" class="stripe_addon_view_details" target="_blank">' . __( 'View Details', 'stripe-payments' ) . '</a>';
if ( $addon['installed'] ) {
$output .= ' <a href="' . $addon['settings_url'] . '" class="stripe_addon_view_details" target="_blank">' . __( 'Settings', 'stripe-payments' ) . '</a>';
}
$output .= '</div>'; //end detils link
$output .= '</div>'; //end body
$output .= '</div>'; //end canvas
}
echo wp_kses( $output, ASP_Utils::asp_allowed_tags() );
?>
</div>
</div><!-- end of poststuff and post-body -->
</div><!-- end of .wrap -->

View File

@ -0,0 +1,161 @@
<?php
/**
* Represents the view for the administration dashboard.
*
* This includes the header, options, and other information that should provide
* The User Interface to the end user.
*/
if ( ! current_user_can( ASP_MANAGEMENT_PERMISSION ) ) {
wp_die( 'You do not have permission to access this settings page.' );
}
if ( $_GET['page'] == 'stripe-payments-settings' ) {
$tab = get_transient( 'wp-asp-urlHash' );
if ( $tab ) {
delete_transient( 'wp-asp-urlHash' );
}
do_action( 'asp-settings-page-after-styles' );
$asp_admin = AcceptStripePayments_Admin::get_instance();
$asp_main = AcceptStripePayments::get_instance();
$captcha_type = $asp_main->get_setting('captcha_type');
?>
<div class="wrap">
<h2><?php echo esc_html( get_admin_page_title() ); ?></h2>
<?php settings_errors(); ?>
<form method="post" action="options.php">
<input type="hidden" id="wp-asp-urlHash" name="wp-asp-urlHash" value="">
<?php settings_fields( 'AcceptStripePayments-settings-group' ); ?>
<h2 class="nav-tab-wrapper">
<a href="#general" data-tab-name="general" class="nav-tab"><?php echo __( 'General Settings', 'stripe-payments' ); ?></a>
<a href="#email" data-tab-name="email" class="nav-tab"><?php echo __( 'Email Settings', 'stripe-payments' ); ?></a>
<a href="#advanced" data-tab-name="advanced" class="nav-tab"><?php echo __( 'Advanced Settings', 'stripe-payments' ); ?></a>
<a href="#captcha" data-tab-name="captcha" class="nav-tab"><?php echo __( 'Captcha', 'stripe-payments' ); ?></a>
<?php
do_action( 'asp-settings-page-after-tabs-menu' );
?>
</h2>
<div class="asp-settings-spinner-container">
<div class="asp-settings-spinner">Loading...</div>
</div>
<div class="wp-asp-settings-cont">
<div class="wp-asp-settings-grid wp-asp-tabs">
<div class="wp-asp-tab-container" data-tab-name="general">
<?php //do_settings_sections( 'accept_stripe_payment-docs' ); ?>
<?php do_settings_sections( 'accept_stripe_payment' ); ?>
</div>
<div class="wp-asp-tab-container" data-tab-name="email">
<?php do_settings_sections( 'accept_stripe_payment-email' ); ?>
</div>
<div class="wp-asp-tab-container" data-tab-name="advanced">
<?php do_settings_sections( 'accept_stripe_payment-advanced' ); ?>
</div>
<div class="wp-asp-tab-container" data-tab-name="captcha">
<?php do_settings_sections( 'accept_stripe_payment-captcha' ); ?>
<div data-captcha-section="recaptcha"<?php echo ( $captcha_type !== 'recaptcha' ? ' style="display:none;"' : '' ); ?>>
<?php do_settings_sections( $asp_admin->plugin_slug . '-recaptcha' ); ?>
</div>
<div data-captcha-section="eprecaptcha"<?php echo ( $captcha_type !== 'eprecaptcha' ? ' style="display:none;"' : '' ); ?>>
<?php do_settings_sections( $asp_admin->plugin_slug . '-eprecaptcha' ); ?>
</div>
<div data-captcha-section="hcaptcha"<?php echo ( $captcha_type !== 'hcaptcha' ? ' style="display:none;"' : '' ); ?>>
<?php do_settings_sections( $asp_admin->plugin_slug . '-hcaptcha' ); ?>
</div>
<div class="asp-render-txn-rate-limit-settings-section">
<?php do_settings_sections( $asp_admin->plugin_slug . '-txn-rate-limit' ); ?>
</div>
</div>
<?php
do_action( 'asp-settings-page-after-tabs' );
?>
</div>
<div id="poststuff" class="wp-asp-settings-grid wp-asp-settings-sidebar-cont">
<div class="postbox" style="min-width: inherit;">
<h3 class="hndle"><label for="title"><?php echo __( 'Plugin Documentation', 'stripe-payments' ); ?></label></h3>
<div class="inside">
<?php
// translators: %s is link to documentation page
echo sprintf( __( 'Please read the <a target="_blank" href="%s">Stripe Payments</a> plugin setup instructions and tutorials to learn how to configure and use it.', 'stripe-payments' ), 'https://s-plugins.com/stripe-payments-plugin-tutorials/' );
?>
</div>
</div>
<div class="postbox yellowish" style="min-width: inherit;">
<h3 class="hndle"><label for="title"><?php echo __( 'Add-ons', 'stripe-payments' ); ?></label></h3>
<div class="inside">
<?php
// translators: %s is link to addons page
echo sprintf( __( 'Want additional functionality like Subscriptions, Apple Pay support or MailChimp integration? Check out our <a target="_blank" href="%s">Add-Ons!</a>', 'stripe-payments' ), 'edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-addons' );
?>
</div>
</div>
<div class="postbox" style="min-width: inherit;">
<h3 class="hndle"><label for="title"><?php echo __( 'Need Something for PayPal?', 'stripe-payments' ); ?></label></h3>
<div class="inside">
<?php _ex( 'If you need a lightweight plugin to sell your products and services using PayPal then check out our', 'Followed by a link to Express Checkout and eStore plugins', 'stripe-payments' ); ?>
<a target="_blank" href="https://wordpress.org/plugins/wp-express-checkout/">Express Checkout Plugin</a> or
<a target="_blank" href="https://www.tipsandtricks-hq.com/wordpress-estore-plugin-complete-solution-to-sell-digital-products-from-your-wordpress-blog-securely-1059">WP eStore Plugin</a>.
</div>
</div>
<div class="postbox" style="min-width: inherit;">
<h3 class="hndle"><label for="title"><?php echo __( 'Help Us Keep the Plugin Free & Maintained', 'stripe-payments' ); ?></label></h3>
<div class="inside">
<?php
// translators: %s is replaced by "rating" link
echo sprintf( _x( 'Like the plugin? Please give it a good %s', '%s is replaced by "rating" link', 'stripe-payments' ), sprintf( '<a href="https://wordpress.org/support/plugin/stripe-payments/reviews/?filter=5" target="_blank">%s</a>', __( 'rating!', 'stripe-payments' ) ) );
?>
<div class="wp-asp-stars-container">
<a href="https://wordpress.org/support/plugin/stripe-payments/reviews/?filter=5" target="_blank">
<span class="dashicons dashicons-star-filled"></span>
<span class="dashicons dashicons-star-filled"></span>
<span class="dashicons dashicons-star-filled"></span>
<span class="dashicons dashicons-star-filled"></span>
<span class="dashicons dashicons-star-filled"></span>
</a>
</div>
</div>
</div>
<div class="postbox" style="min-width: inherit;">
<h3 class="hndle"><label for="title"><?php echo __( 'Testing Version', 'stripe-payments' ); ?></label></h3>
<div class="inside">
<?php
// translators: %s is replaced by "Testing Version" link for testing version
echo sprintf( _x( "Want to see or test upcoming features, bugfixes or changes before they're released? Install %s of the plugin.", '%s is replaced by "Testing Version" link for testing version', 'stripe-payments' ), sprintf( '<a href="https://s-plugins.com/testing-version/" target="_blank">%s</a>', _x( 'Testing Version', 'Link for testing version of the plugin', 'stripe-payments' ) ) );
?>
</div>
</div>
</div>
<?php submit_button(); ?>
</div>
</form>
<?php
do_action( 'asp-settings-page-after-form' );
?>
<?php
wp_localize_script(
'asp-admin-settings-js',
'aspSettingsData',
array(
'transHash' => $tab,
'currencies' => AcceptStripePayments::get_currencies(),
'str' => array(
'logClearConfirm' => __( 'Are you sure you want to clear log?', 'stripe-payments' ),
'logCleared' => __( 'Log cleared.', 'stripe-payments' ),
'errorOccurred' => __( 'Error occurred:', 'stripe-payments' ),
),
'asp_settings_ajax_nonce' => wp_create_nonce('asp_settings_ajax_nonce'),
)
);
wp_enqueue_script( 'asp-admin-settings-js' );
}
?>
</div>

View File

@ -0,0 +1,109 @@
<?php
class AcceptStripePayments_Blocks {
function __construct() {
add_action( 'init', array( $this, 'register_block' ) );
}
function register_block() {
if ( ! function_exists( 'register_block_type' ) ) {
// Gutenberg is not active.
return;
}
$deps = array( 'wp-blocks', 'wp-element', 'wp-components' );
$wp_version = get_bloginfo( 'version' );
if ( version_compare( $wp_version, '5.8.0', '<' ) ) {
array_push( $deps, 'wp-editor' );
}
wp_register_script(
'stripe-payments-product-block',
WP_ASP_PLUGIN_URL . '/admin/assets/js/blocks/product-block.js',
$deps,
WP_ASP_PLUGIN_VERSION,
true
);
wp_localize_script( 'stripe-payments-product-block', 'aspProdOpts', $this->get_products_array() );
wp_localize_script(
'stripe-payments-product-block',
'aspBlockProdStr',
array(
'title' => 'Stripe Payments Product',
'product' => __( 'Product', 'stripe-payments' ),
'button_only' => __( 'Show Button Only', 'stripe-payments' ),
'button_only_help' => __( 'Check this box if you just want to show the button only without any additional product info.', 'stripe-payments' ),
)
);
register_block_type(
'stripe-payments/product-block',
array(
'attributes' => array(
'prodId' => array(
'type' => 'string',
'default' => 0,
),
'btnOnly' => array(
'type' => 'boolean',
'default' => false,
),
),
'editor_script' => 'stripe-payments-product-block',
'render_callback' => array( $this, 'render_product_block' ),
)
);
}
function render_product_block( $atts ) {
$prodId = ! empty( $atts['prodId'] ) ? intval( $atts['prodId'] ) : 0;
if ( empty( $prodId ) ) {
return '<p>' . __( 'Select product to view', 'stripe-payments' ) . '</p>';
}
$sc_str = 'asp_product id="%d"';
$sc_str = sprintf( $sc_str, $prodId );
if ( ! empty( $atts['btnOnly'] ) ) {
$sc_str .= ' button_only="1"';
}
return do_shortcode( '[' . $sc_str . ']' );
}
private function get_products_array() {
$q = get_posts(
array(
'post_type' => ASPMain::$products_slug,
'post_status' => 'publish',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
)
);
$prodArr = array(
array(
'label' => __( '(Select product)', 'stripe-payments' ),
'value' => 0,
),
);
foreach ( $q as $post ) {
$title = html_entity_decode( $post->post_title );
$prodArr[] = array(
'label' => esc_attr( $title ),
'value' => $post->ID,
);
}
wp_reset_postdata();
return $prodArr;
}
}
new AcceptStripePayments_Blocks();

View File

@ -0,0 +1 @@
<?php // Silence is golden

View File

@ -0,0 +1,133 @@
<style>
div#asp-shortcode-type-container {
text-align: center;
margin: 0 auto;
}
#asp-default-shortcode-container, #asp-product-shortcode-container {
display: none;
}
table.asp-shortcode-options-table sup {
color: red;
}
div#asp-type-select-buttons button.asp-sc-type-sel-btn {
padding: 5px 20px;
height: auto;
font-size: 14px;
}
div#asp-type-select-buttons div {
margin-top: 20px;
margin-bottom: 10px;
}
#asp-error-no-products {
display: none;
color: red;
}
</style>
<div id="asp-shortcode-type-container">
<h2>Please select shortcode type you want to insert</h2>
<div id="asp-type-select-buttons">
<div>
<button class="button button-primary asp-sc-type-sel-btn" data-asp-display="asp-product-shortcode-container">Product Shortcode</button>
</div>
<div>
<button class="button button-primary asp-sc-type-sel-btn" data-asp-display="asp-default-shortcode-container">Custom Shortcode</button>
</div>
</div>
</div>
<div id="asp-product-shortcode-container">
<table class="form-table" style="text-align: left">
<tr>
<th scope="row">Product</th>
<td><select id ="asp_product_select" name="asp_product"></select>
<p class="description">Select product you want to insert.</p>
<span id="asp-error-no-products">No products found. You need to <a href="<?php echo admin_url() . 'post-new.php?post_type=' . ASPMain::$products_slug; ?>" tagert="_blank">create a product</a> first.</span>
</td>
</tr>
</table>
<p class="submit">
<input type="button" id="asp-tinymce-product-submit" class="button-primary" value="Insert Shortcode" />
</p>
</div>
<div id="asp-default-shortcode-container">
<h2 class="nav-tab-wrapper"><a class="nav-tab" href="javascript:void()" data-switch-to-tab="1">General Options</a><a class="nav-tab" href="javascript:void()" data-switch-to-tab="2">Additional Options</a></h2>
<table id="highlight-table" class="form-table asp-shortcode-options-table" style="text-align: left">
<tr data-tabid="1">
<th scope="row">Item Name <sup>*</sup></th>
<td><input type="text" name="asp_name" id="asp_name" class="asp-input-wide">
<p class="description">Your item name. This value should be unique so this item can be identified uniquely on the page.</p>
</td>
</tr>
<tr data-tabid="1">
<th scope="row">Price</th>
<td><input type="text" name="asp_price" id="asp_price">
<p class="description">Item price. Numbers only, no need to put currency symbol. Example: 99.95<br />
Leave it blank if you want your customers to enter the amount themselves (e.g. for donation button).
</p>
</td>
</tr>
<tr data-tabid="1">
<th scope="row">Currency</th>
<td><select name="asp_currency" id="asp_currency"></select>
<p class="description">Leave "(Default)" option selected if you want to use currency specified on settings page.</p>
</td>
</tr>
<tr data-tabid="1">
<th scope="row">Quantity</th>
<td><input type="text" name="asp_quantity" id="asp_quantity">
<p class="description">Specify a custom quantity for the item.<br /></p>
</td>
</tr>
<tr data-tabid="1">
<th scope="row">Button Text</th>
<td><input type="text" name="asp_button_text" id="asp_button_text" class="asp-input-wide">
<p class="description">Specify text to be displayed on the button. Leave it blank to use button text specified on settings page.</p>
</td>
</tr>
<tr data-tabid="2">
<th scope="row">URL</th>
<td><input type="text" name="asp_url" id="asp_url" class="asp-input-wide">
<p class="description">URL of your product (if you're selling digital products).</p>
</td>
</tr>
<tr data-tabid="2">
<th scope="row">Thank You Page URL</th>
<td><input type="text" name="asp_thankyou_page_url" id="asp_thankyou_page_url" class="asp-input-wide">
<p class="description">Page URL where users will be redirected after the payment is processed for this item. Useful if you want to make a custom "Thank you" page for this item. Leave it blank if you want to use the default URL specified in plugin settings.</p>
</td>
</tr>
<tr data-tabid="2">
<th scope="row">Description</th>
<td><input type="text" name="asp_description" id="asp_description" class="asp-input-wide">
<p class="description">You can optionally add a custom description for the item/product/service that will get shown in the stripe checkout/payment window of the item.</p>
</td>
</tr>
<tr data-tabid="2">
<th scope="row">Billing Address</th>
<td><input type="checkbox" name="asp_billing_address" id="asp_billing_address">
<p class="description">Enable this option to collect customer's billing address during the transaction.</p>
</td>
</tr>
<tr data-tabid="2">
<th scope="row">Shipping Address</th>
<td><input type="checkbox" name="asp_shipping_address" id="asp_shipping_address">
<p class="description">Enable this option to collect customer's shipping address during the transaction.</p>
</td>
</tr>
<tr data-tabid="2">
<th scope="row">Item Logo</th>
<td><input type="text" name="asp_item_logo" id="asp_item_logo" class="asp-input-wide">
<p class="description">You can optionally show an item logo in the Stripe payment window. Specify the logo image URL.</p>
</td>
</tr>
<tr data-tabid="2">
<th scope="row">Button CSS Class</th>
<td><input type="text" name="asp_css_class" id="asp_css_class" class="asp-input-wide">
<p class="description">CSS class to be assigned to the button. This is used for styling purposes. You can get additional information <a href="https://s-plugins.com/customize-stripe-payment-button-appearance-using-css/" target="_blank">in this tutorial</a>.</p>
</td>
</tr>
</table>
<p id="asp_form_err">&nbsp;</p>
<p class="submit">
<input type="button" id="asp-tinymce-submit" class="button-primary" value="Insert Shortcode" name="submit" style=""/>
</p>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path fill="green" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"/></svg>

After

Width:  |  Height:  |  Size: 437 B

View File

@ -0,0 +1 @@
<?php // Silence is golden

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,864 @@
= 2.0.74 =
- iDEAL addon fix (this payment method option was getting selected by default when enabled).
- Better thumbnail positioning within the product template display.
- The shop page is wrapped using a div element for better display in block themes.
= 2.0.73 =
- Added filter hooks to allow customization of the admin menu item capability.
- Added a new email merge tag {product_variations} that will include the selected variations of the order.
- Fixed an issue with the "authorize" and "capture" later feature (when the Stripe PHP SDK option is used).
= 2.0.72 =
- Removed the Legacy/Old API checkbox option from the settings. It will now always fallback to use the new API.
= 2.0.71 =
- Added a transaction request limit check on a per IP address basis. This will provide additional protection against card testing bot.
= 2.0.70 =
- Removed the "Invisible captcha" option as it doesn't provide the maximum protection against card testing bot.
- If you were using the Invisible captcha option, it will fallback to the standard reCAPTCHA option.
= 2.0.69 =
- Added a page load signature check on payment form submission.
= 2.0.68 =
- Japanese language translation file updated.
- Added Hungarian language translation file.
- Fixed - Special characters in the Customer Name field causing a Stripe API error.
- Added an additional captcha response check against saved data (when captcha is enabled) for bot mitigation.
= 2.0.67 =
- Added a settings option to specify a limit with captcha. You can disable it by entering a value of -1 in the settings field.
= 2.0.66 =
- Custom Fields - fixed an issue with the "required" custom field configuration.
- Added a new feature to apply a daily transaction limit to provide protection against card testing attack. This is applied when the captcha option is disabled on a site.
- Explanation of the new feature is available in [this documentation page](https://s-plugins.com/protect-yourself-from-card-testing/).
= 2.0.65 =
- Added CSS classes for "Item Price" and "Total Amount" on the thank you page. It can be used to target those items for CSS customization.
- Added additional currency position display options in the settings (left with space, right with space).
- Fixed a formatting issue with the shipping and tax string on the individual product post output.
- Added a new option in the settings for Enterprise reCAPTCHA of Google.
= 2.0.64 =
- Added escaping to the currency symbol output.
= 2.0.63 =
- Added output escaping in the settings interface.
= 2.0.62 =
- Added more filters so the "state" and "postcode" strings can be customized via the custom messages addon.
- Fixed an issue with the quick edit option causing the product configuration to be lost.
- Added a notice to enable captcha feature (if it is not already enabled).
= 2.0.61 =
- Tested on WP 6.0.
- Added a new utility function for escaping SVG output.
- Added escaping to the admin notice message.
- Removed the phpcs related comments from the code.
= 2.0.60 =
- PHP Debug warning fix for view debug request parameter.
= 2.0.59 =
- Added escaping to the extension/addon settings output.
= 2.0.58 =
- Fixed a typo in the "Experimental Settings" heading in the settings menu.
- Added escaping to "Additional CSS" description field in the settings menu.
- Added a utility function to help with output escaping.
- Removed two unused PHP files.
= 2.0.57 =
- Updated the captcha settings menu interface to mention that the "I am not a robot" checkbox captcha option should be used for better protection against bot.
- Added escaping to $data variable in the [Accept Stripe Payments] shortcode.
= 2.0.56 =
- Fixed the additional payments settings menu (it correctly renders the description field)
- Changed parse_str() call to using wp_parse_str()
- Removed the Advanced Custom Field addon's input processing code from the core plugin. This task is now done inside the ACF addon
- Minor code improvements (replaced the PHP buffer output with a direct require_once call)
= 2.0.55 =
- Added sanitization to inputs that were missing sanitization.
- Commented out the post data writing to the log file.
- Added escaping to description output of settings fields.
- Added nonce verification check to the payment intent handling code.
- Added nonce verification check to the 3D secure handling code.
= 2.0.54 =
- Added a capabilities check and a nonce check before the log file is cleared.
- Regenerated the translation POT file.
- Spanish Language translation file updated.
= 2.0.53 =
- Updated Stripe PHP SDK library to 7.110.0. This should resolve most issues related to PHP 8.0.X.
- Added hCaptcha support.
- Addressed improper validation of `Specific Products Only` option on coupon edit page.
- Better error handling for internal Stripe API.
= 2.0.52 =
- Added a checkbox to enable or disable the `Debug Log Shareable Link` option (disabled by default).
- The word `Variable` is displayed (in the store page) instead of zero as price for products that are constructed via variations.
- Fixed PHP warning on Widgets admin page.
= 2.0.51 =
- Improved the `Use variations only to construct final product price` option's reaction to product price change.
- Improvements to coupons edit page.
- Internal API improvements.
= 2.0.50 =
- Invisible reCaptcha option no longer causes an issue on some Apple devices.
- Minor improvements and optimizations to the debug logging feature.
= 2.0.49 =
- Addressed the `Class not found` error related issue on some configurations.
- Minor CSS update to improve the admin-side layout.
= 2.0.48 =
- Added a new feature to configure per-region tax variations option.
- Added checkbox variation type in the product variations feature.
- Only users with admin capabilities (administrator role) can add/edit products now.
- Improved layout and functionality of some admin-side pages.
- Added United Arab Emirates Dirham (AED) currency support.
- Minor improvements and bugfixes.
- Updated the Italian language translation file.
= 2.0.47 =
- Fixed all-off coupons issue in Firefox when payment popup is integrated via link URL.
- Added `{first_name}` and `{last_name}` email merge tags.
- Addressed rare PHP warnings issue when debug mode is enabled.
- More text messages can now be customized via Custom Messages add-on.
= 2.0.46 =
- Fixed a PHP syntax error in the payment popup template file.
= 2.0.45 =
- Added `Show the available quantity in the payment popup` product option.
- Trashed products no longer accessible via link URL.
- Variable currency option for donation product type is no longer applied to other product types.
- The "+" character can now be used in customer's email address on payment popup.
- Added Dominican Peso (DOP) currency support.
- Added German language translation files.
= 2.0.44 =
- Added a new email merge tag {item_short_desc} for the sale notification email.
- Payment popup now has its own slug `asp-payment-box`.
- Addressed variations index issue that could prevent payment popup display.
- Implemented some measures to avoid payment popup page caching by caching plugins.
- Addressed rare payment popup loading failure issue related to variations.
- Updated Stripe PHP SDK.
- Various improvements and bugfixes.
= 2.0.43 =
- Plugin's display name has been changed to "Accept Stripe Payments" according to WP guidelines.
- Improved sanitization of the incoming request data.
- Scripts and styles are now being loaded via `wp_enqueue_scripts` where possible.
- Addressed a few minor cosmetic issues and PHP warnings.
= 2.0.42 =
- 3D Secure feature's iframe loop issue has been addressed.
= 2.0.41 =
- Replaced 3D Secure redirect with full screen iframe.
- Added per-product option to use different Stripe account for some of the products.
- Payment process no longer fails if a variation with negative price mod is selected.
- Buyer name and email no longer missing when using add-ons with `Do Not Save Card Data on Stripe` option enabled.
- Trial period support for variable subscriptions.
- The jQuery UI CSS is included in the plugin (instead of including from an external URL).
- Removed the update checker library for add-ons to adhere to WordPress's guidelines.
You can install [Addons Update Checker plugin](https://s-plugins.com/update-checker-plugin-for-the-addons/) to keep your Stripe Payments add-ons upto date.
= 2.0.40 =
- Fixed an XSS issue with the "currency_code" settings field. Thanks to Park Won Seok.
= 2.0.39 =
- Buyer email address no longer missing when `Don't save card` option enabled.
- Added add-ons upgrade notice.
- WP 5.6 compatibility.
= 2.0.38 =
- Payment confirmation is now done on backend.
- Limit reCaptcha token reusage.
- Fixed full discount coupons were improperly handled in some situations.
- Fixed rare internal Stripe API wrapper issue.
= 2.0.37 =
- Proper tax amount rounding when quantity is >1.
- Coupons are supported for trial subscriptions now.
- Front-end card errors are now also sent via error email.
- Countries displayed in alphabetical order now.
- Prevented backend access to Legacy API functions if it's disabled.
- Added extra note to the "error email" body explaining what an "error email" means.
= 2.0.36 =
- Added "Apply Per-Order" option for fixed amount coupons.
- `2020-08-27` Stripe API version compatibility.
- Improved compatibility with caching plugins (W3 Total Cache, SG Optimizer, WP Rocket etc).
- Payment popup refreshes itself if its left inactive for too long. Should resolve issues related to "Invalid security token".
- Fixed rare payment popup closing issue in Safari browser.
- Success payment animation is now properly displayed in Safari browser.
- Added Egyptian Pound (EGP) currency.
= 2.0.35 =
- Donation type products using zero-decimal currencies no longer cause payment error.
- Products with applied coupons that reduce amount to 0 are properly handled now.
- Symbols with accents in product thumbnail URLs are no longer removed.
- Added Romanian Leu (RON) currency support.
- Fixed minor incompatibility issue with WP 5.5 on Settings page.
= 2.0.34 =
- `Currency not supported for this payment method` error message is now removed when another payment method is selected.
- Billing address postcode is no longer missing in the orders menu.
- Fixed an issue with the Order Events interface showing the "Paid" label twice.
- Payment popup blocks can now be rearranged via CSS tweaks.
- Minor payment popup appearance improvements.
= 2.0.33 =
- Fixed payment error when Legacy API option is still enabled.
- Changed the way security tokens are generated. Should help prevent `Invalid security token` error on servers with aggressive caching.
- Added `Disable Security Token Check` settings option (if the above fails).
- Fixed rare issue affecting `Authorize Only` products and payment methods that do not support it.
= 2.0.32 =
- reCAPTCHA add-on functionality is now built into the core plugin. You can enable reCAPTCHA from the settings menu of the plugin.
- Added security token check for subscriptions payments.
= 2.0.31 =
- Added `Authorize Only` option in the product configuration interface. You can use it to hold funds on a card and then capture it later from the Orders page.
- Added `Donation` product type and `Minimum Donation Amount` product option.
- Re-styled the Orders menu a little.
- Added `Order Events` meta-box to the Order menu.
- Added `Allowed Currencies` global settings option.
- Added `{payment_method}`, `{card_brand}` and `{card_last_4}` email merge tags.
- Payment popup `Close` button is now displayed instantly.
- Browser's `Back` button closes popup if it's open.
- Custom translations are properly loaded on payment popup window now.
- Currency format settings are no longer ignored on the payment popup.
- Empty value is now allowed for "Thousand Separator" option.
- Popup init errors are properly displayed now.
- Added Bulgarian Lev (BGN) currency.
- Minor improvements, bugfixes and optimizations.
= 2.0.30 =
- Added Argentine Peso (ARS), Chilean Peso (CLP), Colombian Peso (COP), Peruvian Nuevo Sol (PEN) and Uruguayan Peso (UYU) currencies.
- Fixed PHP 7.4 deprecation notices.
- Added `asp_ng_pp_countries_list` filter to programmatically modify countries list on payment popup.
- Minor fixes and improvements.
= 2.0.29 =
- Added `Do Not Use Stripe PHP SDK Library` experimental option.
- Plugin now shows warning if required PHP modules are not installed on the server.
- Minor code optimizations and improvements.
- Added subscriptions support for Additional Payment Methods addon.
= 2.0.28 =
- Coupon code is now saved in Stripe metadata.
- Restored `Don't Create Order` settings option (was hidden by mistake few versions back).
- Attempt to fix `mixed content` browser error on payment popup when product thumbnail is using `http` instead of `https`.
- Resolved issue with APM addon when shipping address collection is enabled.
= 2.0.27 =
- Added workaround for servers with aggressive caching when "Prefetch Payment Popup Scripts" option is enabled.
- Removed dev debug lines from the code.
- Fixed typos in text descriptions.
= 2.0.26.1 =
- Fixed a minor checkout issue with the Subscription addon when the `State` field is disabled.
= 2.0.26 =
- Added option to construct product price using variations only.
- Added support for Lebanese Pound (LBP) and Saudi Riyal (SAR) currencies.
- Added 'tax' parameter support for [asp_product] shortcode.
- Added {coupon_code} email merge tag.
- 'thankyou_page_url' parameter is no longer ignored by [asp_product] shortcode.
- State value is now properly handled.
- Shipping address is now properly saved if payment is made via payment addons.
- Made prefetch work for products attached via CSS and link URL.
- Upgraded Stripe PHP SDK to version 7.28.1.
- PHP 7.4 support.
- Minor improvements, bugfixes and optimizations.
- Added built-in integration with [WP PDF Stamper plugin](https://www.tipsandtricks-hq.com/wp-pdf-stamper-plugin-2332)
= 2.0.25 =
- Added "State" field for billing and shipping address.
- Added "Hide State Field" option to the settings menu. It's enabled by default for existing installations. This new option can be used to hide the field.
- Bundled translation files are properly loaded now.
- Minor improvements and optimizations.
- Added Italian language translation file.
= 2.0.24 =
- Empty lines in billing and shipping address are no longer displayed.
- Error is displayed when viewing subscription product with Subscriptions add-on disabled.
- Added Japanese language translation file.
= 2.0.23 =
- Added "Last Name First" option for user name prefill. Useful for languages where last name comes first (Japanese).
- Coupon discount amount was improperly displayed on checkout results page for products with variations.
- Additional functionality added for addons.
- Various minor improvements and bugfixes.
- Minimum PHP version requirement is set to PHP 5.6
= 2.0.22 =
- New Stripe API is now enabled by default on fresh new plugin installation.
- Added check if card details are properly filled in before making any backend requests (prevents excess Stripe API calls).
- Added "Force Test Mode" product option (located in Advanced Settings metabox on product edit page).
- Speed up payment popup display by removing unneeded Stripe library init.
- Added built-in integration with [Simple Membership plugin](https://wordpress.org/plugins/simple-membership/)
- WP eMember integration now works with new Stripe API and it handles customer's name and address properly.
- Some visual payment popup form tweaks.
= 2.0.21 =
- Added a new feature to insert custom CSS to payment popup window (it can be found in the advanced settings tab).
- Updated the code to remove a conflict with other plugins when "Enable Compact Product Edit Interface" option is enabled.
- Minor improvements and optimizations.
= 2.0.20 =
- Added validation for values on product edit page (tax, price, quantity etc).
- Discount coupons will now work with subscription products (requires Subscriptions addon 2.0.9+).
= 2.0.19 =
- Added 100% discount coupons support.
- Made amount rounding more consistent between frontend and backend.
- Added payment popup animation to indicate payment is accepted.
- Added quantity support for subscription products (requires Subscriptions addon 2.0.8+).
- Improved payment popup appearance on mobile devices.
- Made payment popup compatible with some older browsers (like IE11).
- Minor backend improvements and fixes.
= 2.0.18 =
- The invalid price display for subscription items on the "All products" page is fixed.
- Updated the code to remove a conflict with other plugins when "Enable Compact Product Edit Interface" option is enabled.
- Shipping value miscalculation during payment processing is fixed.
- Fixed an issue where the customer was getting redirected to login page instead of "checkout results" page on some configurations.
- Improved some text messages on the product edit interface.
= 2.0.17 =
- Improved prefetch payment scripts functionality.
- Optimization improvement to speed up the payment popup display by adding the essential CSS code directly into HTML page.
- Fixed coupon discount was improperly calculated for fixed amount coupons.
- Fixed Stripe receipt is not sent when "Send Receipt Email From Stripe" option enabled (new API only).
- On some servers, the update checker was causing an error. This has been fixed.
- Subscription product: removed the excess "Incomplete" payment entry that was being created in the Stripe Dashboard for the initial subscription charge.
= 2.0.16 =
- Replaced deprecated stripe.js functions to prevent potential issues with payments.
- Forced payment token regeneration if payment amount or currency changed.
- Made more strings available for translation.
- Fixed "Incomplete" subscription status when 3D Secure card is used for payments.
- Fixed an issue with email duplication (caused by multiple execution of some code parts).
= 2.0.15 =
- Payment popup now considers "Stripe Checkout Language" settings option.
- Made most admin interface pages responsive.
- Added MailerLite addon to addons listing menu.
- Fixed potential addon update checking issues on some servers.
- Some minor bugfixes and optimizations.
- Fixed issues with zero-cents currency amounts display and payment processing.
= 2.0.14 =
- Added "Embed Product" metabox to product edit page with available options to embed/attach payment buttons to any page or HTML element.
- Added a new feature that allows you to use a URL to make the payment button. Tutorial https://s-plugins.com/using-a-text-link-instead-of-the-buy-now-button-shortcode/
- Fixed payment popup issue when variable currency was set for subscription product.
- Addons update checker library is now bundled with core plugin.
= 2.0.13 =
- Fixed malformed download URL when [accept_stripe_payment] shortcode is used with new API.
- Added custom field validation support on payment popup.
- Added "Prefetch Payment Popup Scripts" option to speed up payment popup display when customer clicks payment button.
- Proper error message is now displayed if error occurs during frontend Stripe scripts init on payment popup.
- Removed excess output when payment button is displayed.
= 2.0.12 =
- Fixed subscription payment with tax validity check.
- Fixed subscription payment invalid tax amount displayed on checkout results page.
- Added support for [iDEAL](https://s-plugins.com/stripe-ideal-payment-addon/) and [Country Autodetect](https://s-plugins.com/stripe-country-autodetect-addon/) addons.
= 2.0.11 =
- Fixed an issue with duplicate buy emails being sent on some browsers.
- Fixed "Processing" text was showing in the product insert block.
- Added the Spanish language translation file.
- Fixed subscription payment with tax not processing correctly.
= 2.0.10 =
- [New API]: Fixed selected variations weren't properly passed upon payment form submission.
- [New API]: Fixed "Invalid email address" error when APM addon is installed and "Send Receipt Email From Stripe" option enabled.
- [New API]: Added Alipay addon support. Requires Alipay addon version 2.0.0+.
- Legacy API is disabled by default for fresh plugin installations.
- Added admin area notice regarding SCA compatibility.
- Added Bosnia and Herzegovina Convertible Mark (BAM) currency.
= 2.0.9 =
- [New API]: Fixed zero cents currencies were divided by 100 on payments result page and order info.
- [New API]: Fixed Stripe receipt wasn't sent if "Do Not Save Card Data on Stripe" option enabled.
- [New API]: ZIP\postal code is now requested on credit card input when "Validate ZIP Code" option enabled and address collection disabled for a product.
- [New API]: Product name and ID are now saved in payment metadata on Stripe Dashboard.
- [New API]: If product short description is empty, product name is used for payment details "Description" on Stripe Dashboard.
- [New API]: Added spinner after payment popup form submission.
- [New API]: Single variation in a row is now full-width (instead of half-width before).
- [New API]: Adjusted payment popup display on mobile devices.
= 2.0.8 =
- [New API]: Added compatibility with optimization plugins that do minify\combine JavaScript.
- [New API]: Fixed currency wasn't properly updated for variable currency payments in some situations.
- [New API]: Fixed product with stock control enabled could produce fatal error during payment process under some circumstances.
- [New API]: Fixed checkbox custom field display issue.
- [New API]: Added mandatory inputs validation for browsers that don't provide it.
- [New API]: Fixed rare issue that could break payment process if payment button was clicked multiple times.
- [New API]: Added per-product "Show Order Total On Payment Popup" option. When enabled, it displays detailed financial info (tax, variations, coupon etc) on payment popup.
- [New API]: Added support for reCaptcha addon. reCatpcha addon version 2.0.0+ is required to work with new payment popup.
- [New API]: Added support for Additional Payment Methods addon. APM addon version 2.0.0+ is required to work with new payment popup.
- [New API]: Some visual tweaks and fixes for payment popup.
- Fixed custom input wasn't properly validating and honoring "Mandatory" option if position was "Below Button" (legacy API only).
- Added new product edit interface. To see it in action, check the "Enable Compact Product Edit Interface" checkbox in the Advanced Settings tab.
= 2.0.7.1 =
- [New API]: Fixed visual bug on payment popup when coupons are enabled.
= 2.0.7 =
- [New API]: Moved process_ipn action to wp_loaded hook. Should fix issues with "The site is experiencing technical problems" error during payment processing on some configurations.
- [New API]: Restyled payment popup for better responsiveness on mobile devices.
- [New API]: Updated Stripe PHP SDK library to 6.43.1.
- [New API]: Added debug log warning when another Stripe PHP SDK is loaded. Warning is logged once per 6 hours in order to not flood the log.
- [New API]: Payment popup server interaction errors are now more informative.
- [New Api]: Removed excess "Coupon is invalid for the product" debug log message when no coupon code provided.
= 2.0.6 =
- [New API]: Customer info and card data is now saved on Stripe unless "Do Not Save Card Data on Stripe" option is enabled.
- [New API]: Added "Prefill Logged In User Name and Email" option to prefill corresponding payment popup fields with logged in user's name and email.
- Added 'asp_stripe_order_register_post_type_args' filter to override 'stripe-order' post type args.
= 2.0.5 =
- [New API]: Fixed payment popup was not scrollable on Apple devices.
- [New API]: Added "Send Emails In Parallel" option that should speed up checkout process.
- [New API]: Removed excess output for buttons when new API is used.
= 2.0.4 =
- [New API]: Added "Popup Default Country" option that sets default country on payment popup for billing and shipping address.
- Minor bugfixes for the new API.
= 2.0.3 =
- [New API]: Fixed new API was enabled by default. Now you need to disable "Enable Legacy Checkout API" option on Advanced Settings tab to use new API.
- [New API]: Fixed popup button text was empty on plugin update.
- [New API]: Fixed popup form was not scrollable on some mobile devices.
- [New API]: Added white background for popup item logo.
- [New API]: Fixed product description wasn't passed to Stripe.
- [New API]: Fixed customer_email shortcode parameter was ignored.
- [New API]: Added customer_name shortcode parameter to prefill customer name in payment popup.
= 2.0.2 =
- [New API]: Fixed checkout error when both billing and shipping address collection enabled.
- [New API]: Fixed popup JavaScript caching issue.
= 2.0.1 =
- Important: This is a major upgrade. We advise that you backup your site before upgrading the plugin.
- Added new SCA compliant API for checkout. There is a new payment popup that utilizes SCA-complaint payment process.
- You can enable the new SCA compliant checkout by going to the "Advanced Settings Menu" of the plugin then unchecking the "Enable Legacy Checkout API" checkbox.
- By default it uses the legacy API to ensure that it is a smooth upgrade. We don't want your checkout process to be broken after the upgrade.
= 1.9.25 =
- Fixed improper frontend total amount display in some circumstances.
- Fixed total amount was displayed instead of item price in some circumstances.
- Fixed issues that could lead to "button key mismatch" error when [accept_stripe_payment] shortcode is used.
- Paragraphs are automatically added to product description when needed.
= 1.9.24 =
- Added {item_url} email tag support.
- Fixed issue with the_content filter usage in product shortcode output that could cause some content duplication.
- Added checkout_lang shortcode parameter which sets checkout popup language for a product.
= 1.9.23 =
- PHP sessions are no longer used for security and better caching purposes.
- Disabled nonce checking for buttons.
- Fixed thankyou_page_url parameter was ignored for [asp_product] shortcode and by some addons.
- Fixed item URL wasn't processed by Secure Downloads addon when some other addons are enabled.
- Fixed frontend total amount calculation display for products with variations and custom amount enabled.
- Custom amount validation errors no longer displayed on page load for products with variations and custom amount enabled.
- Checkout results page no longer displays "Download links" message if there are no downloads set for variations.
- Checkout error message is now displayed even if no [accept_stripe_payment_checkout_error] shortcode inserted on custom checkout results page.
- Frontend amount and quantity inputs are disabled on payment form submit to prevent "Token can't be used more than once" error.
- Fixed zero-cent currencies displaying and handling issues.
- Product description now supports WP embeds.
- Tweaks for better compatibility with various page builders.
- Other minor bugfixes.
= 1.9.22 =
- Fixed archive pages list could be messed up when plugin is enabled.
- Fixed the "asp_stripe_payments_checkout_page_result" filter hook not triggering correctly.
= 1.9.21 =
- Fixed frontend discount amount display when custom quantity is enabled and initial quantity is set to 0 or empty.
- Fixed adding groups to existing product with variations caused improper variations placement.
- Fixed tax amount was displayed rounded down on frontend under some circumstances (wasn't affecting actual payment amount).
- Product variations are now added to payment metadata in Stripe account.
- Added admin side notice if required PHP modules are not installed on the server.
= 1.9.20 =
- Added Stripe Payments Product Gutenberg block.
- Added button_only parameter to [asp_product] shortcode. When set to "1", no product title and info is displayed.
- Fixed PHP notices when viewing some products with variations.
= 1.9.19 =
- Fixed issues on Settings page that prevented it from being properly displayed in some versions of Safari browser.
- Stripe Payments menu icon color changed to white to have better contrast with dark menu background.
- Fixed minor HTML-related admin interface issues.
= 1.9.18 =
- Trial subscriptions are now displaying 0 as payment amount on checkout results and email receipts.
Payment button in Stripe pop-up for those now shows "Start Free Trial" instead of payment amount.
Requires Subscriptions addon 1.4.5+
- Added validation for custom filed. You can use your own validation rules via custom JavaScript RegExp.
- Fixed invalid amount was displayed on Stripe pop-up when variable price and quantity is used.
- {product_details} merge tag is available for custom checkout results page.
- Purchase date is now displayed using WP date\time format settings and considers timezone.
- Added option to display product variations as radio buttons (can be set per product on product edit page).
= 1.9.17 =
- Fixed frontend stock control. Now customers cannot order more items than available in stock.
- Added [asp_show_my_transactions] shortcode to display transactions made by user.
- Added support for addons' email merge tags. They are also displayed in tags hint if available.
= 1.9.16 =
- Fixed coupon was still applied to the product even if it's not allowed for it.
= 1.9.15.1 =
- Fixed tax value was displayed rounded down on frontend.
- Fixed PHP notices displayed on products page.
= 1.9.15 =
- Updated Stripe PHP SDK to latest version. PHP versions below 5.4 are no longer supported.
- Some minor admin interface modifications.
= 1.9.14.2 =
- Fixed price consistency check for payment button shortcodes.
= 1.9.14.1 =
- Fixed Stripe mode was improperly set during subscriptions payment processing sometimes (requires Subscriptions addon 1.3.5+).
= 1.9.14 =
- Added product option that lets the customers select payment currency.
- Added support for variable amount subscriptions (requires Subscriptions addon version 1.3.4+).
- Added order info link to seller email.
- Fixed [accept_stripe_payment] shortcode was ignoring shipping_address option.
- Fixed quantity set for a product was ignored under some circumstances.
= 1.9.13 =
- Payment buttons are now replaced by a spinner during payment processing for better user experience.
- Added option to disable Order creation after purchase. Useful if you don't want to save purchase info on your website.
- Variable amount input is now considers only two digits after decimal separator.
- Customer shipping address is added to payment metadata if available. You can see it in your Stripe Dashboard.
- Added dismissible notice if PHP version is older than 5.4.
- Fixed a couple of issues with variations.
= 1.9.12 =
- Fixed product price could not be set to zero or empty value (for donation purposes).
- Added option to send buyer and seller emails in HTML format.
- Added spinner for settings page to indicate it's being loaded.
- Added support for upcoming Additional Custom Fields addon.
- If custom field enabled but its name is not set, it would be called "Custom Field".
- Made more strings available for translation.
- Minor bigfixes and imporvements.
= 1.9.11 =
- Price and shipping cost is being converted to appropriate format on product edit page.
- Fixed some buttons were not clickable when TOS enabled.
= 1.9.10 =
- Added {tax}, {tax_amt}, {currency} and {shipping_amt} checkout page customization tags. More tags [can be found here](https://s-plugins.com/customize-the-thank-page-message-of-stripe-payments-plugin/).
- Added {item_name} and {item_quantity} email tags.
- Added position settings options for custom field and TOS. You can display those below payment button now.
= 1.9.9 =
- Fixed incompatability with older PHP versions (prior to 5.4).
- Added SOFORT and Post Payment Actions addons to the list.
- Made more strings available for translations, regenerated .pot file.
= 1.9.8 =
- Fixed blank payment results page was displayed under some circumstances if customized [accept_stripe_payment_checkout] shortcode was used.
- Added ability to allow coupon usage only for specific products.
- Added option to store customer's IP address in order info.
- Plugin tries to create and use small product thumbnail for Stripe pop-up if available. This removes noticeable pop-up window lag when large image is being used.
= 1.9.7 =
- Fixed improper tax value calculation under some circumstances.
- Fixed session_start() error that occurs on some configurations after customer made a payment.
- Removed some of the CSS styles from the coupon field. So the style of the coupon field fits better with the theme you are using.
= 1.9.6 =
- Fixed zero amount was displayed on products with custom amount.
- Fixed products table display when viewed from mobile.
- Products table is now properly displaying large images for newly created or updated products.
- Added CSS to add some spacing after the variation label.
= 1.9.5 =
- Added product variations feature. Documentation here - https://s-plugins.com/creating-variable-products-using-the-stripe-payments-plugin/
- Added ability to offer 100% discount coupon. Plugin won't produce "Invalid positive integer" error if it is used.
- Fixed rare bug when customer wasn't redirected to results page on error if "Send Email On Payment Failure" option is not enabled.
- Billing name (if available) is now properly passed to MailChimp, AWeber, ConvertKit etc. addons if payment is made via Advanced Payment Methods addon.
- Added the necessary changes for the convertkit addon.
= 1.9.4 =
- Added "Debug Log Shareable Link" to share debug log without having to share WP Dashboard credentials.
- Added error message on product edit page if price is below or above Stripe's allowed min/max for selected currency.
- Installed add-ons are now marked on Add-ons page and have Settings button displayed.
- Compressed images to decrease plugin package size.
- Fixed coupon discount was visually applied on all products on page, not just the one where coupon was entered.
- Added spinner after "Apply" coupon button is clicked to indicate that coupon is being checked.
= 1.9.3 =
- Coupon discount is now applied to the product price, not the total amount.
- Coupon input is no longer displayed for custom amount products.
- Added Dropbox support for Secure Downloads addon (requires addon version 1.1.7+).
- Added WP eMember plugin integration options.
= 1.9.2 =
- Added Russian Ruble (RUB) currency.
- Fixed Secure Downloads addon was showing real download URL for products.
- Fixed per-product thank you page setting was ignored when payment error occurs.
- Added {paid_amount_curr} custom checkout result page merge tag. It displays formatted amount with currency code (example: $12.99).
= 1.9.1.1 =
- Fixed per-product coupons settings were set to "Disabled" in some circumstances (thanks to abelfinance for reporting).
= 1.9.1 =
- Added Coupons functionality. Coupons for subscriptions are not supported at the moment, we're working on it.
- Added {charge_date} checkout result merge tag.
- Advanced Payment Methods addon is now properly collecting Billing and\or shipping addresses.
- Clicking on "Shortcode" input on product page now selects the shortcode.
= 1.9.0 =
- Added "Validate ZIP code" option. In order for this to work, corresponding option should be enabled in your Stripe Dashboard as well.
- Added support for Custom Messages addon. You can use it to customize various text messages displayed by the plugin.
- Added {customer_name} email merge tag.
= 1.8.9 =
- Fixed "You passed an empty string for referrer" error which was caused by recent changes in Stripe API.
- Added option to apply decimal separator settings to customer input as well.
= 1.8.8 =
- Added option to add mandatory "I accept the Terms and Conditions" checkbox. Should help to comply with the EU GDPR. Go to Settings -> Advanced Settings tab to configure it as per your needs.
- Fixed zero-decimal currencies tax value was calculated improperly.
- More text available for translation. You can help in translating the plugin to your language [here](https://translate.wordpress.org/projects/wp-plugins/stripe-payments)
- Inline CSS is now minified.
- Some addons-related changes.
= 1.8.7 =
- Added some debug logging message after the notification email is sent by the plugin. This will be useful for troubleshooting email related issue.
- Added Alipay payment option as a free addon - https://s-plugins.com/alipay-addon-stripe-payments-plugin/
= 1.8.6 =
- Added basic products stock control functionality.
- Added option to select custom text field description location (placeholder or below input).
- Added links to documentation and add-ons on Settings page.
= 1.8.5 =
- Fixed "Invalid Stripe token" error in Safari on iPad (thanks to temparcweb for reporting and helping to debug).
- Fixed IE11 incompatibility (thanks to temparcweb).
- Additional information is put into debug log and error email if error occurs.
- Customer no longer redirected to download URL if error occurs during payment process.
= 1.8.4 =
- Fixed "Invalid positive integer" error when price is set to 0 in [accept_stripe_payment name] shortcode.
= 1.8.3 =
- Added some more hooks for better addons support.
= 1.8.2 =
- Tax and shipping info is now displayed in standard checkout result page, emails and order info (if applicable).
- New email tags added: {tax}, {tax_amt}, {shipping_amt}.
- Added proper check for minimum amount for following currencies: DKK (2.50-kr.), GPB (£0.30), HKD ($4.00), JPY (¥50), MXN ($10), NOK (3.00-kr.), SEK (3.00-kr.).
- Fixed products page was displaying incorrect number of products per row.
- Fixed product template was improperly displaying price if quantity was greater than 1.
- Fixed tax and shipping being improperly calculated when custom quantity was enabled.
- Various small bugfixes and improvements.
= 1.8.1 =
- New shortcode parameter added: compat_mode="1". Useful if you get "Invalid Stripe Token" error if using visual page builders.
- Added additional email tags: {item_price}, {item_price_curr}, {currency}, {currency_code}.
- Added {purchase_amt_curr} email tag to display formatted amount with currency symbol.
- Fixed {purchase_amt} email tag wasn't showing total purchase amount (was showing item price instead). Also made {purchase_amt} to be formatted according to Price Display Settings.
= 1.8.0 =
- Fixed variable price was improperly handled for products in some cases.
- Added option to make payment buttons not clickable until Javascript libraries are loaded on page view. This prevents "Invalid Stripe Token" errors on some configurations.
- You can customize currency symbol on settings page now.
- Prioritized button_text parameter for product shortcode (useful if you want to have several buttons with different text for same product).
- {custom_field} tag is now supported on custom Thank You page.
- Custom field name and value are now added to Stripe metadata.
= 1.7.9.1 =
- Fixed minor bug related to product quantity.
= 1.7.9 =
- "Send Error Email To" field now accepts coma-separated emails (thanks to pitfallindimate3746 for reporting).
- Added customer_email shortcode parameter which allows to specify customer email in Stripe pop-up (useful if you're dynamically generating payment buttons via do_shortcode() function).
- Minor bug fixes (mostly related to addons).
= 1.7.8 =
- Added Shipping and Tax support for products.
- Merged Price and Currency sections on product edit page.
- Product thumbnail is now displayed in Stripe pop-up. This can be disabled using corresponding option on product edit page.
= 1.7.7 =
- Added "Button CSS Class" and "Show Button Only" parameters to product edit page.
- Added "Thank You Page URL" field to product edit page.
- Added debug logging option to the settings.
= 1.7.6 =
- Fixed PHP warning displayed upon saving product when custom field is not configured (thanks to falcon13 for reporting).
- Plugin text domain is now properly set.
= 1.7.5 =
- Changed some currencies symbols to be more distinctive (e.g. Australian Dollar was using '$' symbol before, now is using 'AU$').
- Updated the language translation POT file.
- Made additional strings available for translation via translate.wordpress.org.
[Click here](https://translate.wordpress.org/projects/wp-plugins/stripe-payments) if you want to help in translating plugin to your language.
= 1.7.4 =
- Added "Send Email On Payment Failure" option to notify admin if payment failed.
- Fixed plugin conflict with WordPress Themes Editor (thanks to natecarlson1 for reporting).
= 1.7.3 =
- Stripe PHP Library updated to v5.8.0.
- Minimum PHP version required is PHP5.3.
= 1.7.2 =
- Added Custom Field to the advanced settings. Custom Field can be used to add an additional text field or checkbox to your buttons to collect an input from your customer.
- Fixed scripts were called too early, which rarely resulted in conflicts with other plugins and themes (thanks to mmeida for reporting and helping out).
= 1.7.1 =
- Fixed "Button key mismatch" error when special characters (like '&') are used in button name (thanks to damhnait for reporting and helping out).
- Removed "Use New Method To Display Buttons" setting. Now all buttons are displayed using the new method.
= 1.7.0 =
- Fixed a PHP warning in the settings menu of the plugin.
= 1.6.9 =
- Added "Send Receipt Email From Stripe" option. You can find this option under the "Email Settings" menu of the plugin.
- [asp_product] shortcode now supports "class" parameter that allows to assign CSS class to the payment button.
= 1.6.8 =
- Added language text-domain to the plugin file header.
- Hopefully fixed plugin conflict with Yoast SEO (thanks to rogbiz for reporting and helping out).
- Added sanitization to the button output. Thanks to Mikko.
= 1.6.7 =
- Amount in order title is formatted corresponding to Price Display Settings.
- Added [Test Mode] to the order title if payment was made in Test mode.
- Notice added to the settings regarding caching plugins.
- A small bug introduced in previous version has been fixed.
= 1.6.6 =
- Separate fields for Stripe Test keys added to the settings page.
- Plugin will now properly handle buttons with same name but different price (thanks to nourrirsafoi for reporting).
- Fixed "Warning: A non-numeric value encountered" when custom amount is used (thanks to rogbiz for reporting).
= 1.6.5 =
- Fixed improper handling of custom amount feature (thanks to triode33 for reporting).
- Added "Processing.." text to payment button to let user know the payment is being processed.
= 1.6.4 =
- The email related settings options have been moved to a separate tab in the settings menu.
- Added a new configuration option to allow customization of the price display settings in the advanced settings tab.
- The price of the item now gets displayed in the product description.
- The plugin automatically creates a "products" page where all your Stripe items/products are listed in a grid display.
= 1.6.3 =
- Improved the description that gets shown in the stripe checkout window when a product has no "short description" specified for it.
= 1.6.2 =
- Updated the Quantity field box in the product edit interface to add more explanation as to how that field works.
= 1.6.1 =
- Stripe plugin's admin menu interface has been reworked to facilitate the addition of new features.
- Added a new interface to add/edit products from the wp admin dashboard. Usage instructions at the following URL:
https://s-plugins.com/creating-product-stripe-payments-plugin/
- There is a new shortcode to embed a Stripe payment button for the products you create in the admin dashboard.
- The existing shortcodes will continue to work as is (no change there).
- The shortcode inserter (in the post/page editor) has been updated. It will allow you to insert both the shortcodes.
= 1.6.0 =
- Stripe button CSS is now inserted before the form to prevent payment buttons from having default theme style for a second before the CSS file actually loaded.
- Updated the settings menu link slug to make it unique.
= 1.5.9 =
- Added "Turn Off "Remember me" Option" setting. When enabled, "Remember me" checkbox will be removed from Stripe's checkout popup.
- Moved "Settings" menu item from WP Settings to a new independent menu called "Stripe Payments".
- Added "thankyou_page_url" shortcode parameter to specify a custom thank you page URL for an item. This can be used to override the default thank you page URL on a per item basis.
- Extended checkout results page customization using [accept_stripe_payment_checkout] and [accept_stripe_payment_checkout_error] shortcodes.
- Instructions on how to customize the thank you page using tags can be found at the following URL:
https://s-plugins.com/customize-the-thank-page-message-of-stripe-payments-plugin/
= 1.5.8 =
- Zero-decimal currencies (like JPY) are no longer multiplied by 100.
- Added Italian language translation file to the plugin. Translation was submitted by Daniele Oneta.
= 1.5.7 =
- Added "Stripe Checkout Language" option to the settings.
- The 'asp_stripe_payment_completed' hook now passes the order post ID in the $post_data array.
= 1.5.6 =
- The shipping and billing address email merge tags are usable again (if you use the address parameters in the shortcode).
- The address will be stored correctly in the Stripe Orders menu (if you are collecting address).
= 1.5.5 =
- Reworked the TinyMCE shortcode inserter code a little to fix an issue with saving a post in WP v4.8.
= 1.5.4 =
- Added filter hooks for the notification email subject and body.
- Currency Code on settings page changed from input to select.
- Added "Do Not Save Card Data on Stripe" setting to tell Stripe to not save card information.
- Added a shortcode inserter button to the TinyMCE editor ("Visual" tab on Edit Post\Page screen).
- Updated the Stripe Orders dashboard menu icon.
= 1.5.3 =
- Updated the French language translation file.
- Updated the translation POT file.
- The plugin will show an error if the shortcode doesn't have the "name" field present. This is a required field for the plugin to process the checkout.
= 1.5.2 =
- Added a new option to display the Stripe buttons. It makes connection to Stripe website only when button is clicked, this makes the page with Stripe buttons load a little faster.
- Added French language translation file to the plugin. Translation file was submitted by Claudy GALAIS.
= 1.5.1 =
- There is now an option to send a notification email to the buyer and seller after the purchase. You can configure it in the settings menu of this plugin.
- A custom css class can be specified for the Stripe button to customize the button style.
- The "price" parameter can be omitted in the shortcode to allow the visitors to specify a custom price or donation amount for an item.
= 1.4 =
- Added an improvement so the description also gets captured with the stripe charge (so you can see it in your Stripe account).
- It will also save the description in the stripe orders menu of the plugin.
= 1.3 =
- The transaction ID will now get shown on the thank you page also (after the payment).
- Added more CSS classes on the thank you page message.
- Added a new parameter in the shortcode so you can specify a custom description for the item checkout (if you want to).
= 1.2 =
* Added a new option to show the item logo or thumbnail image in the stripe checkout window.
* Added a new filter so you can add extra Stripe checkout data parameters (if you want to customize it).
* Added a new action hook that is triggered after the payment is complete (asp_stripe_payment_completed).
= 1.1 =
* Added new option to show shipping and billing address in the stipe payment popup window. You can specify a parameter in the shortcode to collect the address.
= 1.0.5 =
* Added a new filter so the checkout result page's output can be customized.
* Added extra details to the thank you page that shows the details of the item that was purchased.
= 1.0.4 =
* Added more instructions to the checkout result page explaining what that page is for.
* Added settings link in the plugins listing page.
= 1.0.3 =
* Added some enhanced security in the form submission.
= 1.0.2 =
* Updated the payment shortcode parameter.
= 1.0.1 =
* First Release

View File

@ -0,0 +1,147 @@
<?php
class ASP_Addons_Helper {
public $addon = null;
public $section;
public $asp_admin;
private $auc_plugin_path = 'stripe-payments-addons-update-checker/class-asp-addons-update-checker.php';
private $item_hash = '';
protected $addons = array(
array( 'stripe-payments-country-autodetect', 'stripe-payments-country-autodetect/asp-country-autodetect-main.php', 'stripe-payments-country-autodetect', '' ),
array( 'stripe-payments-custom-messages', 'stripe-payments-custom-messages/asp-custmsg-main.php', 'stripe-payments-custom-messages', 'stripe-custom-messages-addon.png' ),
);
private $icons_path = WP_ASP_PLUGIN_URL . '/admin/assets/images/';
private $icons = array();
public function __construct( $addon ) {
$this->addon = $addon;
if ( is_admin() ) {
$this->asp_admin = AcceptStripePayments_Admin::get_instance();
add_action( 'activate_' . $this->auc_plugin_path, array( $this, 'remove_auc_notice' ) );
}
}
public function remove_auc_notice() {
if ( ! empty( $this->item_hash ) ) {
AcceptStripePayments_Admin::remove_admin_notice_by_hash( $this->item_hash );
}
}
public function init_tasks() {
add_action( 'init', array( $this, 'load_text_domain' ) );
if ( is_admin() ) {
$this->add_settings_link();
$this->check_updates();
}
}
public function log( $msg, $success = true ) {
if ( method_exists( 'ASP_Debug_Logger', 'log' ) ) {
ASP_Debug_Logger::log( $msg, $success, $this->addon->ADDON_SHORT_NAME );
}
}
public function check_updates() {
//Note: This function can get called from an addon before init. So we don't do any translation strings here.
if ( ! is_admin() ) {
//We are not in admin-dashboard area so just return (We only need to check updates in admin area).
return;
}
if ( class_exists( 'ASP_Addons_Update_Checker' ) ) {
if ( empty( $this->addon->SLUG ) || empty( $this->addon->file ) ) {
return;
}
ASP_Addons_Update_Checker::check_updates( $this->addon->SLUG, $this->addon->file );
} else {
// let's display admin notice to install Addons Update Checker (if the message is not yet dismissed)
$user_id = get_current_user_id();
if ( empty( $user_id ) ) {
return;
}
if ( ! current_user_can( 'install_plugins' ) && ! current_user_can( 'activate_plugins' ) ) {
return;
}
$notice_dismissed = get_user_meta( $user_id, 'asp_dismiss_auc_msg', true );
if ( ! empty( $notice_dismissed ) ) {
return;
}
$admin_url = get_admin_url();
$dismiss_url = add_query_arg( 'asp_dismiss_auc_msg', '1', $admin_url );
$dismiss_url = wp_nonce_url( $dismiss_url, 'asp_dismiss_auc_msg' );
$dismiss_msg = '<span class="asp_dismiss_notice_update_checker" style="text-align: right;display:block;"><a style="text-decoration: none; border-bottom: 1px dashed;font-size:0.9em;" href="' . $dismiss_url . '">' . 'Don\'t show this message again' . '</a></span>';
//This function can get called from an addon before init. So we don't do any translation strings here.
$this->item_hash = AcceptStripePayments_Admin::add_admin_notice(
'warning',
'<span><strong>Accept Stripe Payments</strong></span><br>Please install the <a target="_blank" href="https://s-plugins.com/update-checker-plugin-for-the-addons/">Stripe Payments Addons Update Checker</a> plugin to keep your addons upto date.' .
$dismiss_msg,
false
);
}
}
public function check_ver() {
if ( version_compare( WP_ASP_PLUGIN_VERSION, $this->addon->MIN_ASP_VER ) < 0 ) {
add_action( 'admin_notices', array( $this, 'display_min_version_error' ) );
return false;
}
return true;
}
public function add_settings_link() {
add_filter( 'plugin_action_links', array( $this, 'settings_link' ), 10, 2 );
}
public function load_text_domain() {
if ( ! empty( $this->addon->file ) && ! empty( $this->addon->textdomain ) ) {
load_plugin_textdomain( $this->addon->textdomain, false, dirname( plugin_basename( $this->addon->file ) ) . '/languages/' );
}
}
public function settings_link( $links, $file ) {
if ( plugin_basename( $this->addon->file ) === $file && ! empty( $this->addon->SETTINGS_TAB_NAME ) ) {
$settings_link = sprintf( '<a href="edit.php?post_type=' . ASPMain::$products_slug . '&page=stripe-payments-settings#%s">%s</a>', $this->addon->SETTINGS_TAB_NAME, __( 'Settings', 'stripe-payments' ) );
array_unshift( $links, $settings_link );
}
return $links;
}
public function display_min_version_error() {
$class = 'notice notice-error';
// translators: %1$s - plugin name, %2$s - min core plugin version, %3$s - installed core plugin version
$message = sprintf( __( '%1$s requires Stripe Payments plugin minimum version to be %2$s (you have version %3$s installed). Please update Stripe Payments plugin.', 'stripe-payments' ), $this->addon->ADDON_FULL_NAME, $this->addon->MIN_ASP_VER, WP_ASP_PLUGIN_VERSION );
printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
}
public function add_settings_section( $title, $descr_callback = null ) {
//$descr_callback added since 1.9.8
add_settings_section( 'AcceptStripePayments-' . $this->addon->SETTINGS_TAB_NAME . '-section', $title, $descr_callback, $this->asp_admin->plugin_slug . '-' . $this->addon->SETTINGS_TAB_NAME );
$this->section = 'AcceptStripePayments-' . $this->addon->SETTINGS_TAB_NAME . '-section';
}
public function add_settings_field( $name, $title, $desc, $size = 10 ) {
$this->asp_admin = AcceptStripePayments_Admin::get_instance();
add_settings_field(
$name,
$title,
array( $this->asp_admin, 'settings_field_callback' ),
$this->asp_admin->plugin_slug . '-' . $this->addon->SETTINGS_TAB_NAME,
$this->section,
array(
'field' => $name,
'size' => $size,
'desc' => $desc,
)
);
}
}
class_alias( 'ASP_Addons_Helper', 'ASPAddonsHelper' );

View File

@ -0,0 +1,90 @@
<?php
class ASP_Daily_Txn_Counter {
private $asp_main = null;
private $txn_counter_option_name;
//private $txn_counter_limit;
private $today;
public function __construct() {
$this->txn_counter_option_name = 'asp_daily_txn_count_args';
$this->asp_main = AcceptStripePayments::get_instance();
$this->today = date("Y-m-d");
}
//Resets or get the current counter
public function asp_get_daily_txn_counter_args() {
$txn_counter_args = get_option($this->txn_counter_option_name);
if (!$txn_counter_args) {
//If txn_counter don't exists , create and return new as zero
return $this->asp_reset_daily_txn_counter();
} else {
if (isset($txn_counter_args["counter_date"]) == false || $this->today != $txn_counter_args["counter_date"] ) {
return $this->asp_reset_daily_txn_counter();
}
}
return $txn_counter_args;
}
public function asp_increment_daily_txn_counter() {
$txn_counter_args = $this->asp_get_daily_txn_counter_args();
$txn_counter_args["counter"]++;
update_option($this->txn_counter_option_name, $txn_counter_args);
return $txn_counter_args;
}
public function asp_set_txn_counter_value( $count ) {
$txn_counter_args = $this->asp_get_daily_txn_counter_args();
$txn_counter_args["counter"] = $count;
update_option($this->txn_counter_option_name, $txn_counter_args);
}
public function asp_is_daily_txn_limit_reached($is_captcha_enabled=false) {
$txn_counter_args = $this->asp_get_daily_txn_counter_args();
$txn_counter_limit = 0;
if( $is_captcha_enabled == true ) {
$txn_counter_limit = $this->asp_main->get_setting('daily_txn_limit_with_captcha');
} else {
$txn_counter_limit = $this->asp_main->get_setting('daily_txn_limit_without_captcha');
}
if ( !$txn_counter_limit ) {
$txn_counter_limit = 25;
}
if ( $txn_counter_args["counter"] >= $txn_counter_limit ) {
return true;
}
return false;
}
public function asp_is_daily_tnx_limit_with_captcha_enabled()
{
$daily_txn_limit_with_captcha = $this->asp_main->get_setting('daily_txn_limit_with_captcha');
if(empty($daily_txn_limit_with_captcha)){
return true;
}
if($daily_txn_limit_with_captcha && $daily_txn_limit_with_captcha >= 0) {
return true;
}
return false;
}
private function asp_reset_daily_txn_counter() {
$txn_counter_args = array('counter_date' => $this->today, 'counter' => 0);
update_option($this->txn_counter_option_name, $txn_counter_args);
return $txn_counter_args;
}
}

View File

@ -0,0 +1,122 @@
<?php
class ASP_Debug_Logger {
public function __construct() {
}
public static function log( $msg, $success = true, $addon_name = '', $overwrite = false ) {
$opts = get_option( 'AcceptStripePayments-settings' );
if ( ! $opts['debug_log_enable'] && ! $overwrite ) {
return true;
}
$log_file = get_option( 'asp_log_file_name' );
if ( ! $log_file ) {
//let's generate new log file name
$log_file = uniqid() . '_debug_log.txt';
update_option( 'asp_log_file_name', $log_file );
}
$output = '';
//Timestamp it
$output .= '[' . gmdate( 'm/d/Y h:i:s A' ) . '] - ';
//Add the addon's name (if applicable)
if ( ! empty( $addon_name ) ) {
$output .= '[' . $addon_name . '] ';
}
//Flag failure (if applicable)
if ( ! $success ) {
$output .= 'FAILURE: ';
}
//Final debug output msg
$output = $output . $msg;
if ( ! file_put_contents( WP_ASP_PLUGIN_PATH . $log_file, $output . "\r\n", ( ! $overwrite ? FILE_APPEND : 0 ) ) ) {
return false;
}
return true;
}
public static function log_array_data( $array_to_write, $success = true, $addon_name = '', $overwrite = false ) {
$opts = get_option( 'AcceptStripePayments-settings' );
if ( ! $opts['debug_log_enable'] && ! $overwrite ) {
return true;
}
$log_file = get_option( 'asp_log_file_name' );
if ( ! $log_file ) {
//let's generate new log file name
$log_file = uniqid() . '_debug_log.txt';
update_option( 'asp_log_file_name', $log_file );
}
$output = '';
//Timestamp it
$output .= '[' . gmdate( 'm/d/Y g:i:s A' ) . '] - ';
//Add the addon's name (if applicable)
if ( ! empty( $addon_name ) ) {
$output .= '[' . $addon_name . '] ';
}
//Flag failure (if applicable)
if ( ! $success ) {
$output .= 'FAILURE: ';
}
//Put the array content into a string
ob_start();
print_r( $array_to_write );
$var = ob_get_contents();
ob_end_clean();
$output .= $var;
if ( ! file_put_contents( WP_ASP_PLUGIN_PATH . $log_file, $output . "\r\n", ( ! $overwrite ? FILE_APPEND : 0 ) ) ) {
return false;
}
return true;
}
public static function view_log() {
$log_file = get_option( 'asp_log_file_name' );
if ( ! file_exists( WP_ASP_PLUGIN_PATH . $log_file ) ) {
if ( self::log( "Stripe Payments debug log file\r\n" ) === false ) {
wp_die( 'Can\'t write to log file. Check if plugin directory (' . WP_ASP_PLUGIN_PATH . ') is writeable.' );
};
}
$logfile = fopen( WP_ASP_PLUGIN_PATH . $log_file, 'rb' );
if ( ! $logfile ) {
wp_die( 'Can\'t open log file.' );
}
header( 'Content-Type: text/plain' );
fpassthru( $logfile );
die;
}
public static function clear_log() {
if ( ! current_user_can( ASP_MANAGEMENT_PERMISSION ) ) {
//No permission for the current user to do this operation.
wp_die( 0 );
}
if ( ! check_ajax_referer( 'asp_settings_ajax_nonce', 'nonce', false ) ) {
//The nonce check failed
echo 'Error! Nonce security check failed. Could not clear log.';
wp_die( 0 );
}
if ( self::log( "Stripe Payments debug log reset\r\n", true, '', true ) !== false ) {
echo '1';
} else {
echo 'Can\'t clear log - log file is not writeable.';
}
wp_die();
}
}

View File

@ -0,0 +1,211 @@
<?php
class ASP_Order_Item {
protected $id = false;
private $asp_main;
public function __construct() {
$this->asp_main = AcceptStripePayments::get_instance();
}
public function create( $product_id, $pi_id = false ) {
$item = new ASP_Product_Item( $product_id );
$post = array();
$post['post_title'] = '[Incomplete]' . $item->get_name();
if ( ! $this->asp_main->is_live ) {
//Test Mode is on, we should add this to post title
$post['post_title'] = '[Test Mode] ' . $post['post_title'];
}
$post['post_status'] = 'pending';
$post['post_type'] = 'stripe_order';
$this->id = wp_insert_post( $post );
if ( false !== $pi_id ) {
update_post_meta( $this->id, 'pi_id', $pi_id );
}
update_post_meta( $this->id, 'asp_product_id', $product_id );
$this->change_status( 'incomplete' );
//let's insert WP user ID into order details. Can be used to display user's transaction history.
$user_id = get_current_user_id();
if ( $user_id ) {
update_post_meta( $this->id, 'asp_user_id', $user_id );
}
return $this->id;
}
public function find( $meta, $value ) {
$order = get_posts(
array(
'post_type' => 'stripe_order',
'meta_key' => $meta,
'meta_value' => $value,
'post_status' => 'any',
)
);
if ( $order ) {
$this->id = $order[0]->ID;
return $this->id;
}
return false;
}
public function set_id( $id ) {
$this->id = $id;
}
public function change_status( $new_status, $comment = false, $date = false ) {
update_post_meta( $this->id, 'asp_order_status', $new_status );
$order_events = get_post_meta( $this->id, 'asp_order_events', true );
if ( empty( $order_events ) ) {
$order_events = array();
}
$order_events[] = array(
'status' => $new_status,
'comment' => $comment,
'date' => false === $date ? time() : $date,
);
update_post_meta( $this->id, 'asp_order_events', $order_events );
}
public function get_id() {
return $this->id;
}
public function get_status() {
return get_post_meta( $this->id, 'asp_order_status', true );
}
public function can_create( $prod_id = false ) {
$dont_create_order = $this->asp_main->get_setting( 'dont_create_order' );
return ! $dont_create_order;
}
public function update_legacy( $order_details, $charge_details ) {
$post = array();
$post['post_title'] = $order_details['item_quantity'] . ' x ' . $order_details['item_name'] . ' - ' . AcceptStripePayments::formatted_price( $order_details['paid_amount'], $order_details['currency_code'] );
if ( $order_details['is_live'] == 0 ) {
//Test Mode is on, we should add this to post title
$post['post_title'] = '[Test Mode] ' . $post['post_title'];
}
$post['post_status'] = 'pending';
$output = '';
// Add error info in case of failure
if ( ! empty( $charge_details->failure_code ) ) {
$output .= '<h2>Payment Failure Details</h2>' . "\n";
$output .= $charge_details->failure_code . ': ' . $charge_details->failure_message;
$output .= "\n\n";
} else {
$post['post_status'] = 'publish';
}
$order_date = date( 'Y-m-d H:i:s', $charge_details->created );
$order_date = get_date_from_gmt( $order_date, get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) );
$output .= '<h2>' . __( 'Order Details', 'stripe-payments' ) . "</h2>\n";
$output .= __( 'Order Time', 'stripe-payments' ) . ': ' . $order_date . "\n";
$output .= __( 'Transaction ID', 'stripe-payments' ) . ': ' . $charge_details->id . "\n";
$output .= __( 'Description', 'stripe-payments' ) . ': ' . $order_details['charge_description'] . "\n";
$output .= '--------------------------------' . "\n";
$output .= __( 'Product Name', 'stripe-payments' ) . ': ' . $order_details['item_name'] . "\n";
$output .= __( 'Quantity', 'stripe-payments' ) . ': ' . $order_details['item_quantity'] . "\n";
$output .= __( 'Item Price', 'stripe-payments' ) . ': ' . AcceptStripePayments::formatted_price( $order_details['item_price'], $order_details['currency_code'] ) . "\n";
//check if there are any additional items available like tax and shipping cost
$output .= AcceptStripePayments::gen_additional_items( $order_details );
$output .= '--------------------------------' . "\n";
$output .= __( 'Total Amount', 'stripe-payments' ) . ': ' . AcceptStripePayments::formatted_price( ( $order_details['paid_amount'] ), $order_details['currency_code'] ) . "\n";
$output .= "\n\n";
$output .= '<h2>' . __( 'Customer Details', 'stripe-payments' ) . "</h2>\n";
// translators: %s is email address
$output .= sprintf( __( 'E-Mail Address: %s', 'stripe-payments' ), $order_details['stripeEmail'] ) . "\n";
if (isset($order_details['customer_name']) && !empty($order_details['customer_name'])){
$output .= sprintf( __( 'Customer\'s Name: %s', 'stripe-payments' ), $order_details['customer_name'] ) . "\n";
}
// translators: %s is payment source (e.g. 'card' etc)
$output .= sprintf( __( 'Payment Source: %s', 'stripe-payments' ), $order_details['stripeTokenType'] ) . "\n";
if (isset($order_details['logged_in_user_id']) && !empty($order_details['logged_in_user_id'])) {
// translators: %s is ID
$output .= __( 'Logged-in User\'s Type: ', 'stripe-payments' ) . $order_details['logged_in_user_type'] . "\n";
$output .= __( 'Logged-in User\'s User ID: ', 'stripe-payments' ) . $order_details['logged_in_user_id'] . "\n";
}
if (isset($order_details['logged_in_user_name']) && !empty($order_details['logged_in_user_name'])) {
// translators: %s is username
$output .= __( 'Logged-in User\'s Username: ', 'stripe-payments' ) . $order_details['logged_in_user_name'] . "\n";
}
//Custom Fields (if set)
if ( isset( $order_details['custom_fields'] ) ) {
$custom_fields = '';
foreach ( $order_details['custom_fields'] as $cf ) {
$custom_fields .= $cf['name'] . ': ' . $cf['value'] . "\r\n";
}
// $custom_fields = rtrim( $custom_fields, "\r\n" );
$output .= $custom_fields;
}
//Check if we have TOS enabled and need to store customer's IP and timestamp
$tos_enabled = $this->asp_main->get_setting( 'tos_enabled' );
$tos_store = $this->asp_main->get_setting( 'tos_store_ip' );
if ( $tos_enabled && $tos_store ) {
$ip = ! empty( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : __( 'Unknown', 'stripe-payments' );
// translators: %s is IP address
$output .= sprintf( __( 'IP Address: %s', 'stripe-payments' ), $ip ) . "\n";
}
//Billing address data (if any)
if ( isset( $order_details['billing_address'] ) && strlen( $order_details['billing_address'] ) > 5 ) {
$output .= '<h2>' . __( 'Billing Address', 'stripe-payments' ) . "</h2>\n";
$output .= $order_details['billing_address'];
}
//Shipping address data (if any)
if ( isset( $order_details['shipping_address'] ) && strlen( $order_details['shipping_address'] ) > 5 ) {
$output .= '<h2>' . __( 'Shipping Address', 'stripe-payments' ) . "</h2>\n";
$output .= $order_details['shipping_address'];
}
$post['post_content'] = $output;
$post = apply_filters( 'asp_order_before_insert', $post, $order_details, $charge_details );
$c_post = get_post( $this->id );
$c_post->post_title = $post['post_title'];
$c_post->post_status = $post['post_status'];
$c_post->post_content = $post['post_content'];
wp_update_post( $c_post, true );
//let's insert WP user ID into order details. Can be used to display user's transaction history.
$user_id = get_current_user_id();
if ( $user_id ) {
update_post_meta( $this->id, 'asp_user_id', $user_id );
}
return $this->id;
}
}

View File

@ -0,0 +1,303 @@
<?php
class ASP_Payment_Data {
protected $obj_id;
protected $obj;
protected $trans_id = false;
protected $amount = false;
protected $surcharge_data = array();
protected $currency = false;
protected $charge_created = false;
protected $charge_data = false;
protected $last_error = '';
protected $billing_details_obj = false;
protected $shipping_details_obj = false;
protected $customer_obj = false;
protected $last_error_obj;
public $is_zero_value = false;
public function __construct( $obj_id = false, $zero_value = false ) {
if ( false !== $obj_id ) {
$this->obj_id = $obj_id;
}
if ( $zero_value ) {
$this->construct_zero_value();
} else {
$this->load_from_obj();
}
}
public function get_last_error() {
return $this->last_error;
}
public function get_price() {
$price = $this->get_amount();
return $price;
}
public function get_amount() {
if ( false === $this->amount ) {
$this->amount = $this->obj->charges->data[0]->amount;
}
return $this->amount;
}
/**
* Get the surcharge data from payment intent metadata.
*
* @param $key string The key to get the value of.
*
* @return string Get the value as string if found. Otherwise, empty string.
*/
public function get_surcharge_data( string $key )
{
if ( empty($this->surcharge_data) ) {
$metadata = isset($this->obj->charges->data[0]->metadata) ? $this->obj->charges->data[0]->metadata : array();
if (isset($metadata['Surcharge Amount'])){
$this->surcharge_data['amount'] = $metadata['Surcharge Amount'];
}
if (isset($metadata['Surcharge Label'])){
$this->surcharge_data['label'] = $metadata['Surcharge Label'];
}
}
return isset($this->surcharge_data[$key]) ? (string) $this->surcharge_data[$key] : '';
}
public function get_currency() {
if ( false === $this->currency ) {
$this->currency = $this->obj->charges->data[0]->currency;
}
return $this->currency;
}
public function get_charge_data() {
if ( false === $this->charge_data ) {
$this->charge_data = $this->obj->charges->data[0];
}
return $this->charge_data;
}
public function get_charge_created() {
if ( false === $this->charge_created ) {
$this->charge_created = $this->obj->charges->data[0]->created;
}
return $this->charge_created;
}
public function get_trans_id() {
if ( false === $this->trans_id ) {
$this->trans_id = $this->obj->charges->data[0]->id;
}
return $this->trans_id;
}
public function get_billing_details() {
if ( ! empty( $this->billing_details_obj ) ) {
return $this->billing_details_obj;
}
$billing_addr = new stdClass();
$bd = $this->obj->charges->data[0]->billing_details;
$billing_addr->name = ! empty( $bd->name ) ? sanitize_text_field($bd->name) : ( isset( $this->obj->customer->name ) ? sanitize_text_field( $this->obj->customer->name ): '' );
$billing_addr->email = ! empty( $bd->email ) ? sanitize_text_field($bd->email) : ( isset( $this->obj->customer->email ) ? sanitize_text_field( $this->obj->customer->email) : '' );
$billing_addr->line1 = isset( $bd->address->line1 ) ? sanitize_text_field($bd->address->line1) : ( isset( $this->obj->customer->address->line1 ) ? sanitize_text_field($this->obj->customer->address->line1) : '' );
$billing_addr->line2 = isset( $bd->address->line2 ) ? sanitize_text_field($bd->address->line2) : ( isset( $this->obj->customer->address->line2 ) ? sanitize_text_field($this->obj->customer->address->line2) : '' );
$billing_addr->postal_code = isset( $bd->address->postal_code ) ? sanitize_text_field($bd->address->postal_code) : '';
$billing_addr->city = isset( $bd->address->city ) ? sanitize_text_field($bd->address->city) : ( isset( $this->obj->customer->address->city ) ? sanitize_text_field( $this->obj->customer->address->city ): '' );
$billing_addr->state = isset( $bd->address->state ) ? sanitize_text_field($bd->address->state) : ( isset( $this->obj->customer->address->state ) ? sanitize_text_field($this->obj->customer->address->state) : '' );
$billing_addr->country = isset( $bd->address->country ) ? sanitize_text_field( $bd->address->country) : ( isset( $this->obj->customer->address->country ) ? sanitize_text_field($this->obj->customer->address->country) : '' );
$this->billing_details_obj = $billing_addr;
return $this->billing_details_obj;
}
public function set_billing_details(object $billing_addr) {
return $this->billing_details_obj = $billing_addr;
}
public function get_shipping_details() {
if ( ! empty( $this->shipping_details_obj ) ) {
return $this->shipping_details_obj;
}
$shipping_addr = new stdClass();
$sd = $this->obj->charges->data[0]->shipping;
if ( empty( $sd ) ) {
if ( ! empty( $this->obj->customer ) ) {
$sd = $this->obj->customer->shipping;
}
}
$shipping_addr->name = isset( $sd->name ) ? sanitize_text_field($sd->name) : '';
$shipping_addr->line1 = isset( $sd->address->line1 ) ? sanitize_text_field($sd->address->line1) : '';
$shipping_addr->line2 = isset( $sd->address->line2 ) ? sanitize_text_field($sd->address->line2) : '';
$shipping_addr->postal_code = isset( $sd->address->postal_code ) ? sanitize_text_field($sd->address->postal_code) : '';
$shipping_addr->city = isset( $sd->address->city ) ? sanitize_text_field($sd->address->city) : '';
$shipping_addr->state = isset( $sd->address->state ) ? sanitize_text_field($sd->address->state) : '';
$shipping_addr->country = isset( $sd->address->country ) ? sanitize_text_field($sd->address->country) : '';
$this->shipping_details_obj = $shipping_addr;
return $this->shipping_details_obj;
}
public function get_billing_addr_str() {
$this->get_billing_details();
$billing_address = '';
$bd = $this->billing_details_obj;
$billing_address .= ! empty( $bd->name ) ? $bd->name . "\n" : '';
$billing_address .= ! empty( $bd->line1 ) ? $bd->line1 . "\n" : '';
$billing_address .= ! empty( $bd->line2 ) ? $bd->line2 . "\n" : '';
$billing_address .= ! empty( $bd->postal_code ) ? $bd->postal_code . "\n" : '';
$billing_address .= ! empty( $bd->city ) ? $bd->city . "\n" : '';
$billing_address .= ! empty( $bd->state ) ? $bd->state . "\n" : '';
$billing_address .= ! empty( $bd->country ) ? $bd->country . "\n" : '';
return $billing_address;
}
public function get_shipping_addr_str() {
$this->get_shipping_details();
$shipping_address = '';
$bd = $this->shipping_details_obj;
$shipping_address .= ! empty( $bd->name ) ? $bd->name . "\n" : '';
$shipping_address .= ! empty( $bd->line1 ) ? $bd->line1 . "\n" : '';
$shipping_address .= ! empty( $bd->line2 ) ? $bd->line2 . "\n" : '';
$shipping_address .= ! empty( $bd->postal_code ) ? $bd->postal_code . "\n" : '';
$shipping_address .= ! empty( $bd->city ) ? $bd->city . "\n" : '';
$shipping_address .= ! empty( $bd->state ) ? $bd->state . "\n" : '';
$shipping_address .= ! empty( $bd->country ) ? $bd->country . "\n" : '';
return $shipping_address;
}
public function get_customer_details() {
if ( false === $this->customer_obj ) {
$this->customer_obj = $this->obj->customer;
}
return $this->customer_obj;
}
protected function load_from_obj() {
try {
if ( ASP_Utils::use_internal_api() ) {
$api = ASP_Stripe_API::get_instance();
$obj = $api->get( 'payment_intents/' . $this->obj_id . '?expand[]=customer' );
if ( false === $obj ) {
$error = $api->get_last_error();
$this->last_error = $error['message'];
return false;
}
} else {
$obj = \Stripe\PaymentIntent::retrieve(
array(
'id' => $this->obj_id,
'expand' => array( 'customer' ),
)
);
}
} catch ( Exception $e ) {
$this->last_error = $e->getMessage();
$this->last_error_obj = $e;
return false;
}
// Check if associated charges aren't set for this payment intent object.
if( !isset ( $obj->charges ) ){
//Using the new Stripe API version 2022-11-15 or later
ASP_Debug_Logger::log( 'Using the Stripe API version 2022-11-15 or later for Payment Intents object. Need to retrieve the charge object separately.' );
//For Stripe API version 2022-11-15 or later, the charge object is not included in the payment intents object. It needs to be retrieved using the charge ID.
try {
//Retrieve the charges related to this payment intent as Stripe\Collection object.
$charges = \Stripe\Charge::all([
'payment_intent' => $this->obj_id,
]);;
// Add the charges to the payment intent object.
$obj->charges = $charges;
} catch (\Stripe\Exception\ApiErrorException $e) {
// Handle the error
ASP_Debug_Logger::log( 'Stripe error occurred trying to retrieve the associated charges for the payment intent. ' . $e->getMessage(), false );
}
}
$this->obj = $obj;
}
public function get_obj() {
return $this->obj;
}
public function construct_zero_value() {
$this->charge_data = new stdClass();
$this->charge_data->id = $this->obj_id;
$this->trans_id = $this->charge_data->id;
$this->charge_data->created = time();
$this->charge_created = $this->charge_data->created;
$ipn_ng_class = ASP_Process_IPN_NG::get_instance();
$bd = new stdClass();
//Billing details
$b_name = $ipn_ng_class->get_post_var( 'asp_billing_name' );
$bd->name = empty( $b_name ) ? '' : sanitize_text_field( stripslashes ( $b_name ));
$b_email = $ipn_ng_class->get_post_var( 'asp_email' );
$bd->email = empty( $b_email ) ? '' : sanitize_text_field( stripslashes($b_email));
$b_addr = $ipn_ng_class->get_post_var( 'asp_address' );
$bd->line1 = empty( $b_addr ) ? '' : sanitize_text_field( stripslashes($b_addr));
$bd->line2 = '';
$b_postal_code = $ipn_ng_class->get_post_var( 'asp_postcode' );
$bd->postal_code = empty( $b_postal_code ) ? '' : sanitize_text_field( stripslashes($b_postal_code));
$b_city = $ipn_ng_class->get_post_var( 'asp_city' );
$bd->city = empty( $b_city ) ? '' : sanitize_text_field( stripslashes($b_city));
$b_state = $ipn_ng_class->get_post_var( 'asp_state' );
$bd->state = empty( $b_state ) ? '' : sanitize_text_field( stripslashes($b_state));
$b_country = $ipn_ng_class->get_post_var( 'asp_country' );
$bd->country = empty( $b_country ) ? '' : sanitize_text_field( stripslashes($b_country));
$this->billing_details_obj = $bd;
//Shipping details
$same_addr = $ipn_ng_class->get_post_var( 'asp_same-bill-ship-addr' );
if ( ! empty( $same_addr ) ) {
$this->shipping_details_obj = $this->billing_details_obj;
} else {
$sd = new stdClass();
$s_addr = $ipn_ng_class->get_post_var( 'asp_shipping_address' );
$sd->line1 = empty( $s_addr ) ? '' : sanitize_text_field( stripslashes($s_addr));
$sd->line2 = '';
$s_postal_code = $ipn_ng_class->get_post_var( 'asp_shipping_postcode' );
$sd->postal_code = empty( $s_postal_code ) ? '' : sanitize_text_field( stripslashes($s_postal_code));
$s_city = $ipn_ng_class->get_post_var( 'asp_shipping_city' );
$sd->city = empty( $s_city ) ? '' : sanitize_text_field( stripslashes($s_city));
$s_state = $ipn_ng_class->get_post_var( 'asp_shipping_state' );
$sd->state = empty( $s_state ) ? '' : sanitize_text_field( stripslashes($s_state));
$s_country = $ipn_ng_class->get_post_var( 'asp_shipping_country' );
$sd->country = empty( $s_country ) ? '' : sanitize_text_field( stripslashes($s_country));
$this->shipping_details_obj = $sd;
}
$this->amount = 0;
$this->currency = $ipn_ng_class->item->get_currency();
$ipn_ng_class->item->set_shipping( 0 );
$this->is_zero_value = true;
}
}

View File

@ -0,0 +1,709 @@
<?php
/**
* Class ASP_PP_Ajax
* Hanldes various Ajax request for the payment popup.
* 1) The following two files are relevant (these files render hte HTML and handles hte JS code for sending the Ajax request):
* - public/views/templates/payment-popup.php
* - public/js/payment-popup.js
* 2) After the payment intent is confirmed, the "ASP_Process_IPN_NG->process_ipn()" is called which does the post payment processing on our end.
*/
class ASP_PP_Ajax {
protected $asp_main;
public function __construct() {
if ( wp_doing_ajax() ) {
// ASP_Utils::set_custom_lang_if_needed();
$this->asp_main = AcceptStripePayments::get_instance();
add_action( 'init', array( $this, 'add_ajax_handlers' ), 2147483647 );
}
}
public function add_ajax_handlers() {
add_action( 'wp_ajax_asp_pp_create_pi', array( $this, 'handle_create_pi' ) );
add_action( 'wp_ajax_nopriv_asp_pp_create_pi', array( $this, 'handle_create_pi' ) );
add_action( 'wp_ajax_asp_pp_confirm_pi', array( $this, 'handle_confirm_pi' ) );
add_action( 'wp_ajax_nopriv_asp_pp_confirm_pi', array( $this, 'handle_confirm_pi' ) );
add_action( 'wp_ajax_asp_3ds_result', array( $this, 'handle_3ds_result' ) );
add_action( 'wp_ajax_nopriv_asp_3ds_result', array( $this, 'handle_3ds_result' ) );
add_action( 'wp_ajax_asp_pp_save_form_data', array( $this, 'save_form_data' ) );
add_action( 'wp_ajax_nopriv_asp_pp_save_form_data', array( $this, 'save_form_data' ) );
add_action( 'wp_ajax_asp_pp_payment_error', array( $this, 'pp_payment_error' ) );
add_action( 'wp_ajax_nopriv_asp_pp_payment_error', array( $this, 'pp_payment_error' ) );
add_action( 'wp_ajax_asp_pp_check_coupon', array( $this, 'handle_check_coupon' ) );
add_action( 'wp_ajax_nopriv_asp_pp_check_coupon', array( $this, 'handle_check_coupon' ) );
}
public function handle_3ds_result() {
$pi_cs = isset( $_GET['payment_intent_client_secret'] ) ? sanitize_text_field( stripslashes ( $_GET['payment_intent_client_secret'] ) ) : '';
$pi_cs = empty( $pi_cs ) ? '' : $pi_cs;
?>
<!DOCTYPE html>
<html>
<head>
<style>
body,html {
background-color: transparent !important;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script>
parent.ThreeDSCompleted('<?php echo esc_js( $pi_cs ); ?>');
</script>
</body>
</html>
<?php
exit;
}
public function handle_confirm_pi() {
if ( ! check_ajax_referer( 'asp_pp_ajax_nonce', 'nonce', false ) ) {
$out['err'] = __( 'Error occurred: Nonce verification failed.', 'stripe-payments' );
wp_send_json( $out );
}
$asp_daily_txn_counter_obj = new ASP_Daily_Txn_Counter();
$captcha_type = $this->asp_main->get_setting('captcha_type');
if (empty( $captcha_type ) || $captcha_type == 'none' ) {
//Captcha is not enabled. Lets check txn rate limiting.
if($asp_daily_txn_counter_obj->asp_is_daily_txn_limit_reached()) {
$out['err'] = __( 'Error occurred: The transaction limit that you have set in settings has been reached for the day.', 'stripe-payments' );
ASP_Debug_Logger::log($out['err'], false );
if($this->asp_main->get_setting("send_email_on_daily_txn_rate_limit")) {
ASP_Utils::send_daily_txn_rate_limit_email($out['err']);
}
wp_send_json( $out );
}
}
else if($asp_daily_txn_counter_obj->asp_is_daily_tnx_limit_with_captcha_enabled()){
//Captcha is enabled. Lets check txn rate limiting.
if ($asp_daily_txn_counter_obj->asp_is_daily_txn_limit_reached(true)) {
$out['err'] = __('Error occurred: The transaction limit that you have set in settings (with captcha) has been reached for the day.', 'stripe-payments');
ASP_Debug_Logger::log($out['err'], false);
if ($this->asp_main->get_setting("send_email_on_daily_txn_rate_limit")) {
ASP_Utils::send_daily_txn_rate_limit_email($out['err']);
}
wp_send_json($out);
}
}
$product_id = filter_input( INPUT_POST, 'product_id', FILTER_SANITIZE_NUMBER_INT );
$item = new ASP_Product_Item( $product_id );
if ( $item->get_last_error() ) {
$out['err'] = __( 'Error occurred:', 'stripe-payments' ) . ' ' . $item->get_last_error();
wp_send_json( $out );
}
//Log initial confirm_pi debug logging data (if debug feature is enabled).
$txn_counter_args = $asp_daily_txn_counter_obj->asp_get_daily_txn_counter_args();
$txn_counter_val = isset($txn_counter_args['counter'])? $txn_counter_args['counter'] : '-';
$request_ip = ASP_Utils::get_user_ip_address();
$confirm_pi_initial_debug = 'handle_confirm_pi() - Product ID: ' . $product_id . ', Captcha Type: ' . $captcha_type . ', Txn Counter: ' . $txn_counter_val . ', IP: ' . $request_ip;
ASP_Debug_Logger::log( $confirm_pi_initial_debug, true );
//End initial confirm_pi debug logging.
//Check page load signature data
if( !ASP_Utils_Bot_Mitigation::is_page_load_signature_data_valid($product_id) ){
//Signature is invalid.
//Exit out if feature is enabled
$disable_signature_check = $this->asp_main->get_setting( 'disable_page_load_signature_check' );
if ( $disable_signature_check ) {
//The signature check feature is disabled. We will allow this request to go through.
ASP_Debug_Logger::log( 'Notice! The page load signature check feature is disabled in the advanced settings menu so this request will not be blocked.', false );
} else {
$out['err'] = __( 'Error! Page load signature check failed.', 'stripe-payments' );
wp_send_json( $out );
}
}
//Check request limit count per IP address
if( !ASP_Utils_Bot_Mitigation::is_request_limit_reached_for_ip() ){
//Request limit reached for this IP.
//Exit out if feature is enabled
$disable_request_limit_check = $this->asp_main->get_setting( 'disable_request_limit_per_ip_check' );
if ( $disable_request_limit_check ) {
//The request limit check feature is disabled. We will allow this request to go through.
ASP_Debug_Logger::log( 'Notice! The transaction request limit per IP address feature is disabled in the advanced settings menu so this request will not be blocked.', false );
} else {
$out['err'] = __( 'Error! Transaction request limit reached for this IP address.', 'stripe-payments' );
wp_send_json( $out );
}
}
$item = apply_filters( 'asp_ng_pp_product_item_override', $item );
//Trigger some action hooks (useful for other checks).
do_action( 'asp_ng_before_token_request', $item );
//ASP_Debug_Logger::log( 'handle_confirm_pi() - Captcha response checked.', true );
//This hook will be used to do additional captcha (if enabled) parameter checks for bot mitigation.
$params = array();
do_action( 'asp_ng_do_additional_captcha_response_check', $item, $params );
do_action( 'asp_ng_product_mode_keys', $product_id );
$pi_id = isset( $_POST['pi_id'] ) ? sanitize_text_field( stripslashes ( $_POST['pi_id'] ) ) : '';
$opts = isset( $_POST['opts'] ) ? sanitize_text_field( stripslashes ( $_POST['opts'] ) ) : '';
if ( ! empty( $opts ) ) {
$opts = html_entity_decode( $opts );
$opts = json_decode( $opts, true );
} else {
$opts = array();
}
$opts['use_stripe_sdk'] = false;
$home_url = admin_url( 'admin-ajax.php' );
$disable_3ds_iframe = $this->asp_main->get_setting( 'disable_3ds_iframe' );
if ( ! $disable_3ds_iframe ) {
$url_opts = array( 'action' => 'asp_3ds_result' );
} else {
$url_opts = array(
'action' => 'asp_next_action_results',
'is_live' => $this->asp_main->is_live,
);
}
$return_url = add_query_arg( $url_opts, $home_url );
$opts['return_url'] = $return_url;
$opts = apply_filters( 'asp_ng_confirm_pi_opts', $opts, $pi_id );
try {
ASP_Utils::load_stripe_lib();
$key = $this->asp_main->is_live ? $this->asp_main->APISecKey : $this->asp_main->APISecKeyTest;
\Stripe\Stripe::setApiKey( $key );
$api = ASP_Stripe_API::get_instance();
$api->set_param( 'throw_exception', true );
$api->set_api_key( $key );
if ( ! ASP_Utils::use_internal_api() ) {
$pi = \Stripe\PaymentIntent::retrieve( $pi_id );
} else {
$pi = $api->get( 'payment_intents/' . $pi_id );
if ( false === $pi ) {
$err = $api->get_last_error();
throw new \Exception( $err['message'], isset( $err['error_code'] ) ? $err['error_code'] : null );
}
}
if ( 'succeeded' === $pi->status ) {
$out['pi_id'] = $pi->id;
wp_send_json( $out );
}
if ( ! ASP_Utils::use_internal_api() ) {
$pi->confirm( $opts );
} else {
$pi = $api->post(
'payment_intents/' . $pi_id . '/confirm',
$opts
);
if ( false === $pi ) {
$err = $api->get_last_error();
throw new \Exception( $err['message'], isset( $err['error_code'] ) ? $err['error_code'] : null );
}
}
} catch ( \Throwable $e ) {
$out['err'] = __( 'Stripe API error occurred:', 'stripe-payments' ) . ' ' . $e->getMessage();
$order = new ASP_Order_Item();
if ( false !== $order->find( 'pi_id', $pi_id ) ) {
$order->change_status( 'error', $out['err'] );
}
$body = __( 'Following error occurred during payment processing:', 'stripe-payments' ) . "\r\n\r\n";
$body .= $out['err'] . "\r\n\r\n";
$body .= __( 'Debug data:', 'stripe-payments' ) . "\r\n";
$post_data = filter_var( $_POST, FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY );
$post_data_str = http_build_query( $post_data, '', '; ' );
$body .= sanitize_text_field( stripslashes($post_data_str));
ASP_Debug_Logger::log( __( 'Following error occurred during payment processing:', 'stripe-payments' ) . ' ' . $out['err'], false );
ASP_Utils::send_error_email( $body );
wp_send_json( $out );
}
$out['pi_id'] = $pi->id;
if ( isset( $pi->next_action ) ) {
$out['redirect_to'] = $pi->next_action->redirect_to_url->url;
$out['use_iframe'] = ! $disable_3ds_iframe;
}
$out = apply_filters( 'asp_ng_confirm_pi_result_out', $out, $pi_id );
wp_send_json( $out );
}
public function handle_create_pi() {
$out = array();
$out['success'] = false;
$product_id = filter_input( INPUT_POST, 'product_id', FILTER_SANITIZE_NUMBER_INT );
$amount = filter_input( INPUT_POST, 'amount', FILTER_SANITIZE_NUMBER_FLOAT );
$surcharge_amount = filter_input( INPUT_POST, 'surcharge_amount', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
$curr = isset( $_POST['curr'] ) ? sanitize_text_field( stripslashes ( $_POST['curr'] ) ) : '';
$pi_id = isset( $_POST['pi'] ) ? sanitize_text_field( stripslashes ( $_POST['pi'] ) ) : '';
$cust_id = isset( $_POST['cust_id'] ) ? sanitize_text_field( stripslashes ( $_POST['cust_id'] ) ) : '';
$quantity = isset( $_POST['quantity'] ) ? sanitize_text_field( stripslashes ( $_POST['quantity'] ) ) : '';
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( stripslashes ( $_POST['nonce'] ) ) : '';
$coupon_code = isset( $_POST['coupon'] ) ? sanitize_text_field( stripslashes ( $_POST['coupon'] ) ) : '';
$price_variation = isset( $_POST['pvar'] ) ? sanitize_text_field( stripslashes ( $_POST['pvar'] ) ) : '';
$post_billing_details = isset( $_POST['billing_details'] ) ? sanitize_text_field( stripslashes ( $_POST['billing_details'] ) ) : '';
$post_shipping_details = isset( $_POST['shipping_details'] ) ? sanitize_text_field( stripslashes ( $_POST['shipping_details'] ) ) : '';
$post_customer_details = isset( $_POST['customer_details'] ) ? sanitize_text_field( stripslashes ( $_POST['customer_details'] ) ) : '';
//Check create_pi nonce
if ( ! wp_verify_nonce( $nonce, 'asp_pp_ajax_create_pi_nonce' ) ) {
$out['err'] = __( 'Error occurred: Nonce security verification failed.', 'stripe-payments' );
wp_send_json( $out );
}
$asp_daily_txn_counter_obj = new ASP_Daily_Txn_Counter();
$captcha_type = $this->asp_main->get_setting('captcha_type');
if (empty($captcha_type) || $captcha_type == 'none') {
//Captcha is not enabled. Lets check txn rate limiting.
if ($asp_daily_txn_counter_obj->asp_is_daily_txn_limit_reached()) {
$out['err'] = __('Error occurred: The transaction limit that you have set in settings has been reached for the day.', 'stripe-payments');
ASP_Debug_Logger::log($out['err'], false);
if ($this->asp_main->get_setting("send_email_on_daily_txn_rate_limit")) {
ASP_Utils::send_daily_txn_rate_limit_email($out['err']);
}
wp_send_json($out);
}
} else if ($asp_daily_txn_counter_obj->asp_is_daily_tnx_limit_with_captcha_enabled()) {
//Captcha is enabled. Lets check txn rate limiting.
if ($asp_daily_txn_counter_obj->asp_is_daily_txn_limit_reached(true)) {
$out['err'] = __('Error occurred: The transaction limit that you have set in settings (with captcha) has been reached for the day.', 'stripe-payments');
ASP_Debug_Logger::log($out['err'], false);
if ($this->asp_main->get_setting("send_email_on_daily_txn_rate_limit")) {
ASP_Utils::send_daily_txn_rate_limit_email($out['err']);
}
wp_send_json($out);
}
}
//Log initial create_pi debug logging data (if debug feature is enabled).
$txn_counter_args = $asp_daily_txn_counter_obj->asp_get_daily_txn_counter_args();
$txn_counter_val = isset($txn_counter_args['counter'])? $txn_counter_args['counter'] : '-';
$request_ip = ASP_Utils::get_user_ip_address();
$create_pi_initial_debug = 'handle_create_pi() - Product ID: ' . $product_id . ', Captcha Type: ' . $captcha_type . ', Txn Counter: ' . $txn_counter_val . ', IP: ' . $request_ip;
ASP_Debug_Logger::log( $create_pi_initial_debug, true );
//End initial create_pi debug logging.
//Check page load signature data
if( !ASP_Utils_Bot_Mitigation::is_page_load_signature_data_valid($product_id) ){
//Signature is invalid.
//Exit out if feature is enabled
$disable_signature_check = $this->asp_main->get_setting( 'disable_page_load_signature_check' );
if ( $disable_signature_check ) {
//The signature check feature is disabled. We will allow this request to go through.
ASP_Debug_Logger::log( 'Notice! The page load signature check feature is disabled in the advanced settings menu so this request will not be blocked.', false );
} else {
$out['err'] = __( 'Error! Page load signature check failed.', 'stripe-payments' );
wp_send_json( $out );
}
}
//Check request usage count per IP address
if( !ASP_Utils_Bot_Mitigation::is_request_limit_reached_for_ip() ){
//Request limit reached for this IP.
//Exit out if feature is enabled
$disable_request_limit_check = $this->asp_main->get_setting( 'disable_request_limit_per_ip_check' );
if ( $disable_request_limit_check ) {
//The request limit check feature is disabled. We will allow this request to go through.
ASP_Debug_Logger::log( 'Notice! The transaction request limit per IP address feature is disabled in the advanced settings menu so this request will not be blocked.', false );
} else {
$out['err'] = __( 'Error! Transaction request limit reached for this IP address.', 'stripe-payments' );
wp_send_json( $out );
}
}
// >>>> Start of pre API submission validation.
$item_for_validation = new ASP_Product_Item( $product_id );
//Do the API pre-submission price/amount validation.
if ( $item_for_validation->get_type() === 'one_time' ) {
//It's a one-time payment product.
$custom_inputs = array(
'coupon_code' => $coupon_code,
'price_variation' => $price_variation,
'billing_details' => json_decode( html_entity_decode( $post_billing_details ) , true),
'shipping_details' => json_decode( html_entity_decode( $post_shipping_details ) , true),
);
if( ! $item_for_validation->validate_total_amount( $amount, $quantity, $custom_inputs) ){
//Error condition. The validation function already set the error message which we will send back to the client.
$out['err'] = __( 'Error occurred:', 'stripe-payments' ) . ' ' . $item_for_validation->get_last_error();
wp_send_json( $out );
}
//Validation passed.
} else if ( $item_for_validation->get_type() === 'donation' ) {
//It's a donation product. Don't need to validate the amount since the user can enter any amount to donate.
ASP_Debug_Logger::log( "This is a donation type product. API pre-submission amount validation is not required.", true );
}
//Trigger action hook that can be used to do additional API pre-submission validation from an addon.
do_action( 'asp_ng_before_api_pre_submission_validation', $item_for_validation );
// <<<< End of pre API submission validation.
$item = new ASP_Product_Item( $product_id );
if ( $item->get_last_error() ) {
$out['err'] = __( 'Error occurred:', 'stripe-payments' ) . ' ' . $item->get_last_error();
wp_send_json( $out );
}
if ( $item->stock_control_enabled() ) {
$stock_items = $item->get_stock_items();
$out['stock_items'] = $stock_items;
if ( $quantity > $stock_items ) {
// translators: %d is number of items in stock
$msg = apply_filters( 'asp_customize_text_msg', __( 'You cannot order more items than available: %d', 'stripe-payments' ), 'stock_not_available' );
$out['err'] = sprintf( $msg, $stock_items );
wp_send_json( $out );
}
}
$min_amount = $item->get_min_amount( true );
$prod_type = $item->get_type();
$configured_currency = $item->get_currency();
$is_currency_variable = $item->is_currency_variable();
//Check configured currency matches with the request currency.
//Trigger filter that can be used to check this from the subscription addon (if needed).
$configured_currency = apply_filters( 'asp_create_pi_check_currency_configured', $configured_currency, $curr, $item );
if ( $configured_currency !== $curr ) {
//Check if the currency variable option is enabled.
//Trigger filter that can be used to check this from the subscription addon (if needed).
$is_currency_variable = apply_filters( 'asp_create_pi_is_currency_variable', $is_currency_variable, $item );
if ( $is_currency_variable ){
//The currency variable option is enabled. We will allow this request to go through.
ASP_Debug_Logger::log( 'Note: The currency variable option is enabled in the product settings for this product.', true );
} else {
//Error condition
ASP_Debug_Logger::log( 'Currency mismatch. The expected currency is: '.$configured_currency.', Received: '.$curr, false );
$msg = apply_filters( 'asp_customize_text_msg', __( 'Currency mismatch. The product is configured to use', 'stripe-payments' ), 'currency_mismatch' );
$out['err'] = $msg . ' ' . $configured_currency;
wp_send_json( $out );
}
}
//Check minimum amount.
if ( 'donation' === $prod_type && 0 !== $min_amount && $min_amount > $amount ) {
ASP_Debug_Logger::log( 'Minimum amount is: ' . $min_amount . ' ' . $curr, false );
$msg = apply_filters( 'asp_customize_text_msg', __( 'Minimum amount is', 'stripe-payments' ), 'min_amount_is' );
$out['err'] = $msg . ' ' . ASP_Utils::formatted_price( $min_amount, $curr, true );
wp_send_json( $out );
}
//Trigger some action hooks (useful for other checks).
do_action( 'asp_ng_before_token_request', $item );
//ASP_Debug_Logger::log( 'handle_create_pi() - Captcha response checked.', true );
//This hook will be used to do additional captcha (if enabled) parameter checks for bot mitigation.
$params = array();
do_action( 'asp_ng_do_additional_captcha_response_check', $item, $params );
do_action( 'asp_ng_product_mode_keys', $product_id );
try {
ASP_Utils::load_stripe_lib();
$key = $this->asp_main->is_live ? $this->asp_main->APISecKey : $this->asp_main->APISecKeyTest;
\Stripe\Stripe::setApiKey( $key );
$api = ASP_Stripe_API::get_instance();
$api->set_param( 'throw_exception', true );
$api->set_api_key( $key );
} catch ( \Exception $e ) {
$out['err'] = __( 'Stripe API error occurred:', 'stripe-payments' ) . ' ' . $e->getMessage();
wp_send_json( $out );
} catch ( \Throwable $e ) {
$out['err'] = __( 'Stripe API error occurred:', 'stripe-payments' ) . ' ' . $e->getMessage();
wp_send_json( $out );
}
$metadata = array();
try {
$pi_params = array(
'amount' => $amount,
'currency' => $curr,
'confirmation_method' => 'manual',
);
if ( isset( $post_billing_details ) ) {
$post_billing_details = html_entity_decode( $post_billing_details );
$billing_details = json_decode( $post_billing_details );
}
if ( isset( $post_customer_details ) ) {
$post_customer_details = html_entity_decode( $post_customer_details );
$customer_details = json_decode( $post_customer_details );
}
$dont_save_card = $this->asp_main->get_setting( 'dont_save_card' );
if ( ! $dont_save_card ) {
$customer_opts = array();
if ( isset( $billing_details ) ) {
if ( ! empty( $billing_details->name ) ) {
$customer_opts['name'] = $billing_details->name;
}
if ( ! empty( $billing_details->email ) ) {
$customer_opts['email'] = $billing_details->email;
}
if ( isset( $billing_details->address ) && isset( $billing_details->address->line1 ) ) {
//we have address
$addr = array(
'line1' => $billing_details->address->line1,
'state' => isset( $billing_details->address->state ) ? $billing_details->address->state : null,
'city' => isset( $billing_details->address->city ) ? $billing_details->address->city : null,
'country' => isset( $billing_details->address->country ) ? $billing_details->address->country : null,
);
if ( isset( $billing_details->address->postal_code ) ) {
$addr['postal_code'] = $billing_details->address->postal_code;
}
$customer_opts['address'] = $addr;
}
}
if ( isset( $post_shipping_details ) ) {
$post_shipping_details = html_entity_decode( $post_shipping_details );
$shipping_details = json_decode( $post_shipping_details );
$shipping = array();
if ( isset($shipping_details->name) && $shipping_details->name ) {
$shipping['name'] = $shipping_details->name;
} elseif ( ! empty( $customer_opts['name'] ) ) {
$shipping['name'] = $customer_opts['name'];
}
if ( isset( $shipping_details->address ) && isset( $shipping_details->address->line1 ) ) {
//we have address
$addr = array(
'line1' => $shipping_details->address->line1,
'state' => isset( $shipping_details->address->state ) ? $shipping_details->address->state : null,
'city' => isset( $shipping_details->address->city ) ? $shipping_details->address->city : null,
'country' => isset( $shipping_details->address->country ) ? $shipping_details->address->country : null,
);
if ( isset( $shipping_details->address->postal_code ) ) {
$addr['postal_code'] = $shipping_details->address->postal_code;
}
$shipping['address'] = $addr;
if ( ! empty( $shipping['name'] ) ) {
$customer_opts['shipping'] = $shipping;
}
}
}
$is_use_separate_name_fields_enabled = \AcceptStripePayments::get_instance()->get_setting('use_separate_name_fields_enabled', false);
if ($is_use_separate_name_fields_enabled){
$customer_opts['metadata'] = array(
'First Name' => isset($customer_details->firstName) ? sanitize_text_field($customer_details->firstName) : '',
'Last Name' => isset($customer_details->lastName) ? sanitize_text_field($customer_details->lastName) : '',
);
}
$customer_opts = apply_filters( 'asp_ng_before_customer_create_update', $customer_opts, empty( $cust_id ) ? false : $cust_id );
if ( empty( $cust_id ) ) {
if ( ASP_Utils::use_internal_api() ) {
$api = ASP_Stripe_API::get_instance();
$api->set_param( 'throw_exception', true );
$customer = $api->post( 'customers', $customer_opts );
} else {
$customer = \Stripe\Customer::create( $customer_opts );
}
$cust_id = $customer->id;
} else {
if ( ASP_Utils::use_internal_api() ) {
$api = ASP_Stripe_API::get_instance();
$api->set_param( 'throw_exception', true );
$customer = $api->post( 'customers/' . $cust_id, $customer_opts );
} else {
$customer = \Stripe\Customer::update( $cust_id, $customer_opts );
}
}
$pi_params['customer'] = $cust_id;
}
$metadata['Product Name'] = $item->get_name();
$metadata['Product ID'] = $product_id;
$metadata['Surcharge Amount'] = $surcharge_amount;
$metadata['Surcharge Label'] = $item->get_surcharge_label();
$tax_amount = $item->get_tax_amount();
if (!empty($tax_amount)){
$metadata['Tax Amount'] = \ASP_Utils::formatted_price( $tax_amount, $curr );
}
if ( isset( $metadata ) && ! empty( $metadata ) ) {
$pi_params['metadata'] = $metadata;
}
$description = $item->get_description();
if ( ! empty( $description ) ) {
$pi_params['description'] = $description;
} else {
$pi_params['description'] = $item->get_name();
}
$stripe_receipt_email = $this->asp_main->get_setting( 'stripe_receipt_email' );
if ( $stripe_receipt_email ) {
if ( isset( $billing_details ) && isset( $billing_details->email ) && ! empty( $billing_details->email ) ) {
$pi_params['receipt_email'] = $billing_details->email;
}
}
$order = new ASP_Order_Item();
if ( $order->can_create( $product_id ) ) {
if ( ! $pi_id ) {
//create new incomplete order for this payment
$order->create( $product_id, $pi_id );
} else {
//find order for this PaymentIntent
$order->find( 'pi_id', $pi_id );
}
}
$pi_params = apply_filters( 'asp_ng_before_pi_create_update', $pi_params );
if ( $pi_id ) {
if ( ASP_Utils::use_internal_api() ) {
$api = ASP_Stripe_API::get_instance();
$api->set_param( 'throw_exception', true );
$intent = $api->post( 'payment_intents/' . $pi_id, $pi_params );
} else {
$intent = \Stripe\PaymentIntent::update( $pi_id, $pi_params );
}
} else {
if ( ASP_Utils::use_internal_api() ) {
$api = ASP_Stripe_API::get_instance();
$api->set_param( 'throw_exception', true );
$intent = $api->post( 'payment_intents', $pi_params );
} else {
$intent = \Stripe\PaymentIntent::create( $pi_params );
}
}
} catch ( \Exception $e ) {
$out['shipping'] = isset( $shipping ) ? wp_json_encode( $shipping ) : null;
$out['err'] = __( 'Error occurred:', 'stripe-payments' ) . ' ' . $e->getMessage();
wp_send_json( $out );
} catch ( \Throwable $e ) {
$out['shipping'] = isset( $shipping ) ? wp_json_encode( $shipping ) : null;
$out['err'] = __( 'Error occurred:', 'stripe-payments' ) . ' ' . $e->getMessage();
wp_send_json( $out );
}
if ( $order->get_id() ) {
update_post_meta( $order->get_id(), 'pi_id', $intent->id );
}
$out['success'] = true;
$out['clientSecret'] = $intent->client_secret;
$out['pi_id'] = $intent->id;
$out['cust_id'] = $cust_id;
$out = apply_filters( 'asp_ng_before_pi_result_send', $out, $intent );
wp_send_json( $out );
}
public function save_form_data() {
if ( ! check_ajax_referer( 'asp_pp_ajax_nonce', 'nonce', false ) ) {
$out['err'] = __( 'Error occurred: Nonce verification failed on save_form_data().', 'stripe-payments' );
wp_send_json( $out );
}
$out['success'] = true;
$sess = ASP_Session::get_instance();
wp_parse_str( $_POST['form_data'], $form_data );
$filtered_form_data = $this->sanitize_nested_form_data($form_data);
$sess->set_transient_data( 'asp_pp_form_data', $filtered_form_data );
//ASP_Debug_Logger::log( 'Saved form data: ' . json_encode( $filtered_form_data ) );
wp_send_json( $out );
}
public function sanitize_nested_form_data($data) {
foreach ($data as $key => $value) {
if (is_array($value)) {
$data[$key] = $this->sanitize_nested_form_data($value);
} else {
$data[$key] = sanitize_text_field($value);
}
}
return $data;
}
public function handle_check_coupon() {
$product_id = filter_input( INPUT_POST, 'product_id', FILTER_SANITIZE_NUMBER_INT );
$item = new ASP_Product_Item( $product_id );
if ( $item->get_last_error() ) {
$out['err'] = __( 'Error occurred:', 'stripe-payments' ) . ' ' . $item->get_last_error();
wp_send_json( $out );
}
$coupon_code = isset( $_POST['coupon_code'] ) ? sanitize_text_field( stripslashes ( $_POST['coupon_code'] ) ) : '';
$coupon_valid = $item->check_coupon( $coupon_code );
if ( ! $coupon_valid ) {
$out['err'] = $item->get_last_error();
wp_send_json( $out );
}
$coupon = $item->get_coupon();
$zero_value_id = str_replace( '.', '', uniqid( 'free_', true ) );
$coupon['zero_value_id'] = $zero_value_id;
wp_send_json( $coupon );
}
}
new ASP_PP_Ajax();

View File

@ -0,0 +1,719 @@
<?php
class ASP_PP_Display {
protected $tpl_cf;
protected $uniq_id;
protected $asp_main;
public $custom_field;
public $prod_id;
public $variations;
public $item;
private $auth_not_supported = array( 'FPX', 'ALIPAY', 'IDEAL', 'SOFORT' );
public function __construct() {
$action = isset( $_GET['asp_action'] ) ? sanitize_text_field( stripslashes ( $_GET['asp_action'] ) ) : '';
if ( 'show_pp' === $action ) {
// ASP_Utils::set_custom_lang_if_needed();
$process_ipn = filter_input( INPUT_POST, 'asp_process_ipn', FILTER_SANITIZE_NUMBER_INT );
if ( $process_ipn ) {
return;
}
$this->asp_main = AcceptStripePayments::get_instance();
add_action( 'init', array( $this, 'showpp' ), 2147483647 );
} else {
add_action( 'wp', array( $this, 'handle_wp' ) );
}
add_filter( 'pre_handle_404', array( $this, 'pre_handle_404' ), 10, 2 );
}
public function pre_handle_404( $preempt, $wp_query ) {
global $wp;
$custom_pages = array( AcceptStripePayments::$pp_slug );
if ( in_array( $wp->request, $custom_pages, true ) ) {
$preempt = true;
}
return $preempt;
}
public function handle_wp() {
global $wp;
$current_slug = $wp->request;
if ( AcceptStripePayments::$pp_slug === $current_slug ) {
$this->asp_main = AcceptStripePayments::get_instance();
$this->showpp();
}
}
public function showpp() {
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
define( 'DONOTCACHEPAGE', true );
}
if ( ! headers_sent() ) {
status_header( 200 );
// disable WPEngine cache for the page
if ( class_exists( 'WpeCommon' ) ) {
$cookiepath = parse_url( get_home_url( null, AcceptStripePayments::$pp_slug ), PHP_URL_PATH );
$cookie_domain = ! defined( 'COOKIE_DOMAIN' ) ? false : COOKIE_DOMAIN;
setcookie( 'wordpress_wpe_no_cache', 1, 0, $cookiepath, $cookie_domain, true, true );
}
// set no-cache headers
header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
header( 'Cache-Control: post-check=0, pre-check=0', false );
header( 'Pragma: no-cache' );
}
$product_id = filter_input( INPUT_GET, 'product_id', FILTER_SANITIZE_NUMBER_INT );
$this->item = new ASP_Product_Item( $product_id );
$this->item = apply_filters( 'asp_ng_pp_product_item_override', $this->item );
if ( $this->item->get_last_error() ) {
echo esc_html( $this->item->get_last_error() );
exit;
}
$plan_id = get_post_meta( $product_id, 'asp_sub_plan_id', true );
if ( ! empty( $plan_id ) && ! class_exists( 'ASPSUB_main' ) ) {
//Subs addon not installed or disabled. Show corresponding error message
echo ( 'This product requires Stripe Payments Subscription addon.' );
exit;
}
if ( ! empty( $plan_id ) && class_exists( 'ASPSUB_main' ) && version_compare( ASPSUB_main::ADDON_VER, '2.0.0t1' ) < 0 ) {
echo ( 'Stripe Subscriptions addon version 2.0.0 or newer is required.' );
exit;
}
$post_status = get_post_status( $product_id );
if ( 'trash' === $post_status ) {
wp_die( __( 'This product is in the trash. Please restore this product from the trash if you want to use it', 'stripe-payments' ), '', 404 );
}
$a = array();
$a['prod_id'] = $product_id;
do_action( 'asp_ng_product_mode_keys', $product_id );
$a['is_live'] = $this->asp_main->is_live;
$this->uniq_id = uniqid();
$a['page_title'] = $this->item->get_name();
$a['plugin_url'] = WP_ASP_PLUGIN_URL;
$a['item_name'] = $this->item->get_name();
$a['stripe_key'] = $this->asp_main->is_live ? $this->asp_main->APIPubKey : $this->asp_main->APIPubKeyTest;
//Save the payment popup load for this poduct in the temporary transient data (so it can be checked later).
ASP_Utils_Bot_Mitigation::record_page_load_signature_data($product_id);
//Custom Field if needed
$custom_field = get_post_meta( $product_id, 'asp_product_custom_field', true );
$cf_enabled = $this->asp_main->get_setting( 'custom_field_enabled' );
if ( ( '' === $custom_field ) || '2' === $custom_field ) {
$custom_field = $cf_enabled;
} else {
$custom_field = intval( $custom_field );
}
if ( ! $cf_enabled ) {
$custom_field = $cf_enabled;
}
$this->custom_field = $custom_field;
$this->prod_id = $product_id;
$cf_validation_regex = '';
$cf_validation_err_msg = '';
if ( $custom_field ) {
$show_custom_fields_below = $this->asp_main->get_setting( 'acf_show_fields_below' );
if ($show_custom_fields_below){
$a['custom_fields_below'] = $this->tpl_get_cf();
}else{
$a['custom_fields'] = $this->tpl_get_cf();
}
//check if we have custom field validation enabled
$custom_validation = $this->asp_main->get_setting( 'custom_field_validation' );
if ( ! empty( $custom_validation ) ) {
if ( 'num' === $custom_validation ) {
$cf_validation_regex = '^[0-9]+$';
$cf_validation_err_msg = __( 'Only numbers are allowed: 0-9', 'stripe-payments' );
} elseif ( 'custom' === $custom_validation ) {
$cf_validation_regex = $this->asp_main->get_setting( 'custom_field_custom_validation_regex' );
$cf_validation_err_msg = $this->asp_main->get_setting( 'custom_field_custom_validation_err_msg' );
}
}
}
$currency = $this->item->get_currency();
//Currency Display settings
$display_settings = array();
$display_settings['c'] = $this->asp_main->get_setting( 'price_decimals_num', 2 );
$display_settings['d'] = $this->asp_main->get_setting( 'price_decimal_sep' );
$display_settings['t'] = $this->asp_main->get_setting( 'price_thousand_sep' );
$currencies = AcceptStripePayments::get_currencies();
if ( isset( $currencies[ $currency ] ) ) {
$curr_sym = $currencies[ $currency ][1];
} else {
//no currency code found, let's just use currency code instead of symbol
$curr_sym = $currency;
}
$curr_pos = $this->asp_main->get_setting( 'price_currency_pos' );
$display_settings['s'] = $curr_sym;
$display_settings['pos'] = $curr_pos;
$a['amount_variable'] = false;
if ( $this->item->is_variable() ) {
$a['amount_variable'] = true;
}
if ( $this->item->get_price() === 0 ) {
//let's check to see if he have item_price passed via URL parameter
$passed_item_price = isset( $_GET['price'] ) ? sanitize_text_field( stripslashes ( $_GET['price'] ) ) : '';
$passed_item_price = abs( floatval( $passed_item_price ) );
if ( ! empty( $passed_item_price ) ) {
$this->item->set_price( $passed_item_price );
}
}
$a['currency_variable'] = false;
if ( $this->item->is_currency_variable() ) {
$a['currency_variable'] = true;
}
$a['currency'] = $this->item->get_currency();
$billing_address = get_post_meta( $product_id, 'asp_product_collect_billing_addr', true );
$shipping_address = get_post_meta( $product_id, 'asp_product_collect_shipping_addr', true );
$billing_address = empty( $billing_address ) ? false : true;
$shipping_address = empty( $shipping_address ) ? false : true;
if ( ! $billing_address ) {
$shipping_address = false;
}
$tos = $this->asp_main->get_setting( 'tos_enabled' );
if ( $tos ) {
$a['tos'] = true;
$a['tos_text'] = $this->asp_main->get_setting( 'tos_text' );
}
//Is coupon option enabled?
$coupons_enabled = get_post_meta( $product_id, 'asp_product_coupons_setting', true );
if ( ( '' === $coupons_enabled ) || '2' === $coupons_enabled ) {
$coupons_enabled = $this->asp_main->get_setting( 'coupons_enabled' );
}
if ( $a['amount_variable'] ) {
//Allow the coupon option for variable amount as well (in the past it was always disabled for variable amount).
//Commenting it out means it can be disabled via the product specific settings (see the above section of the code).
//$coupons_enabled = false;
}
$coupons_enabled = empty( $coupons_enabled ) ? false : true;
$item_logo = '';
if ( ! get_post_meta( $product_id, 'asp_product_no_popup_thumbnail', true ) ) {
$item_logo = ASP_Utils::get_small_product_thumb( $product_id );
if ( $a['is_live'] ) {
$item_logo = ASP_Utils::url_to_https( $item_logo );
}
}
//stock control
$stock_control_enabled = false;
$show_remaining = false;
$stock_items = 0;
if ( $this->item->stock_control_enabled() ) {
$stock_items = $this->item->get_stock_items();
if ( empty( $stock_items ) ) {
$a['fatal_error'] = __( 'Out of stock', 'stripe-payments' );
} else {
$stock_control_enabled = true;
$stock_items = $stock_items;
$show_remaining = get_post_meta( $product_id, 'asp_product_show_remaining_items', true );
}
}
//variations
$this->variations = array();
$v = new ASPVariations( $product_id );
if ( ! empty( $v->groups ) && empty( $plan_id ) ) {
$this->variations['groups'] = $v->groups;
$variations_names = get_post_meta( $product_id, 'asp_variations_names', true );
$variations_prices_orig = get_post_meta( $product_id, 'asp_variations_prices', true );
$variations_prices = apply_filters( 'asp_variations_prices_filter', $variations_prices_orig, $product_id );
$variations_urls = get_post_meta( $product_id, 'asp_variations_urls', true );
$variations_opts = get_post_meta( $product_id, 'asp_variations_opts', true );
$this->variations['names'] = $variations_names;
$this->variations['prices'] = $variations_prices;
$this->variations['urls'] = $variations_urls;
$this->variations['opts'] = $variations_opts;
}
$thankyou_page = get_post_meta( $product_id, 'asp_product_thankyou_page', true );
$a['thankyou_page'] = $thankyou_page;
$cust_email_hardcoded = get_post_meta( $product_id, 'asp_product_customer_email_hardcoded', true );
$cust_name_hardcoded = get_post_meta( $product_id, 'asp_product_customer_name_hardcoded', true );
$user_id = get_current_user_id();
$prefill_user_details = $this->asp_main->get_setting( 'prefill_wp_user_details' );
if ( $user_id && $prefill_user_details ) {
$user_info = get_userdata( $user_id );
if ( false !== $user_info ) {
if ( empty( $cust_email_hardcoded ) ) {
$cust_email_hardcoded = $user_info->user_email;
}
if ( empty( $cust_name_hardcoded ) ) {
$last_name_first = $this->asp_main->get_setting( 'prefill_wp_user_last_name_first' );
$cust_name_hardcoded = $last_name_first ? $user_info->last_name . ' ' . $user_info->first_name : $user_info->first_name . ' ' . $user_info->last_name;
}
}
}
$default_country = $this->asp_main->get_setting( 'popup_default_country' );
$dont_save_card = $this->asp_main->get_setting( 'dont_save_card' );
$verify_zip = $this->asp_main->get_setting( 'enable_zip_validation' );
$checkout_lang = $this->asp_main->get_setting( 'checkout_lang' );
$checkout_lang = empty( $checkout_lang ) ? 'auto' : $checkout_lang;
$data = array();
$data['initTime'] = time();
$data['product_id'] = $product_id;
$data['item_name'] = $this->item->get_name();
$quantity = get_post_meta( $product_id, 'asp_product_quantity', true );
if ( ! $quantity ) {
$quantity = 1;
}
$data['quantity'] = $quantity;
$data['custom_quantity'] = get_post_meta( $product_id, 'asp_product_custom_quantity', true );
$data['amount_variable'] = $a['amount_variable'];
$data['currency_variable'] = $a['currency_variable'];
$data['currency'] = $a['currency'];
$data['stock_control_enabled'] = $stock_control_enabled;
$data['stock_items'] = $stock_items;
$data['show_remaining'] = $show_remaining;
$data['billing_address'] = $billing_address;
$data['shipping_address'] = $shipping_address;
$data['coupons_enabled'] = $coupons_enabled;
$data['tos'] = $tos;
$data['item_logo'] = $item_logo;
$data['url'] = base64_encode( $this->item->get_download_url() );
$data['client_secret'] = '';
$data['pi_id'] = '';
$data['amount'] = $this->item->get_total( true );
$data['item_price'] = $this->item->get_price( true );
$data['min_amount'] = $this->item->get_min_amount( true );
$data['tax'] = $this->item->get_tax();
$data['shipping'] = $this->item->get_shipping( true );
$data['is_physical_product'] = $this->item->is_physical_product();
$data['surcharge'] = $this->item->get_surcharge();
$data['surcharge_type'] = $this->item->get_surcharge_type();
$data['surcharge_amount'] = $this->item->calculate_total_surcharge( true );
$data['surcharge_label'] = $this->item->get_meta( 'asp_surcharge_label' );
$data['descr'] = $this->item->get_description();
$data['tax_variations'] = $this->item->get_meta( 'asp_product_tax_variations' );
$data['shipping_variations'] = $this->item->get_meta( 'asp_product_shipping_variations' );
$tax_variations_type = $this->item->get_meta( 'asp_product_tax_variations_type' );
$data['tax_variations_type'] = empty( $tax_variations_type ) ? 'b' : $tax_variations_type;
$data['custom_field'] = $custom_field;
$data['custom_field_validation_regex'] = $cf_validation_regex;
$data['custom_field_validation_err_msg'] = $cf_validation_err_msg;
$data['stripe_receipt_email'] = $this->asp_main->get_setting( 'stripe_receipt_email' );
$data['variations'] = $this->variations;
$data['is_live'] = $this->asp_main->is_live;
$data['button_key'] = $this->item->get_button_key();
$data['create_token'] = false;
$data['customer_email'] = $cust_email_hardcoded;
$data['customer_name'] = $cust_name_hardcoded;
$data['dont_save_card'] = ! $dont_save_card ? false : true;
$data['verify_zip'] = ! $verify_zip ? false : true;
$data['checkout_lang'] = $checkout_lang;
$data['customer_default_country'] = $default_country;
$data['hide_amount_input'] = $this->item->get_meta( 'asp_product_hide_amount_input' );
$data['show_your_order'] = get_post_meta( $product_id, 'asp_product_show_your_order', true );
$data['show_your_order'] = $data['show_your_order'] ? 1 : 0;
$data['addons'] = array();
$data['payment_methods'][] = array(
'id' => 'def',
'title' => __( 'Credit or debit card', 'stripe-payments' ),
'before_title' => ' <svg id="i-creditcard" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5px">
<path d="M2 7 L2 25 30 25 30 7 Z M5 18 L9 18 M5 21 L11 21" />
<path d="M2 11 L2 13 30 13 30 11 Z" fill="currentColor" />
</svg>',
);
$data['addonHooks'] = array();
$data = apply_filters( 'asp-button-output-data-ready', $data, array( 'product_id' => $product_id ) );
$data = apply_filters( 'asp_ng_pp_data_ready', $data, array( 'product_id' => $product_id ) );
// Authorize Only
$auth_only = get_post_meta( $product_id, 'asp_product_authorize_only', true );
if ( $auth_only ) {
//disable payment methods that do not support placing a hold on card
foreach ( $data['addons'] as $key => $addon ) {
if ( in_array( strtoupper( $addon['name'] ), $this->auth_not_supported, true ) ) {
unset( $data['addons'][ $key ] );
}
}
$data['addons'] = array_values( $data['addons'] );
foreach ( $data['payment_methods'] as $key => $pm ) {
if ( in_array( strtoupper( $pm['id'] ), $this->auth_not_supported, true ) ) {
unset( $data['payment_methods'][ $key ] );
}
}
$data['payment_methods'] = array_values( $data['payment_methods'] );
}
//APM < 2.0.17 does not support tax variations
if ( ! empty( $data['tax_variations'] )
&& class_exists( 'ASPAPM_main' )
&& version_compare( ASPAPM_main::ADDON_VER, '2.0.17', '<' ) ) {
foreach ( $data['addons'] as $key => $addon ) {
if ( 'APM' === $addon['name'] ) {
unset( $data['addons'][ $key ] );
}
}
$data['addons'] = array_values( $data['addons'] );
foreach ( $data['payment_methods'] as $key => $pm ) {
if ( 'APM' === strtoupper( $pm['id'] ) ) {
unset( $data['payment_methods'][ $key ] );
}
}
$data['payment_methods'] = array_values( $data['payment_methods'] );
ASP_Debug_Logger::log( sprintf( 'APM disabled for product %d: need APM 2.0.17+ for tax variation support.', $data['product_id'] ) );
}
//APM < 2.0.17 does not support checkbox variation type
if ( ! empty( $data['variations'] ) && class_exists( 'ASPAPM_main' ) && version_compare( ASPAPM_main::ADDON_VER, '2.0.17', '<' ) ) {
foreach ( $data['variations']['opts'] as $v_opt ) {
if ( $v_opt['type'] === '2' ) {
foreach ( $data['addons'] as $key => $addon ) {
if ( 'APM' === $addon['name'] ) {
unset( $data['addons'][ $key ] );
}
}
$data['addons'] = array_values( $data['addons'] );
foreach ( $data['payment_methods'] as $key => $pm ) {
if ( 'APM' === strtoupper( $pm['id'] ) ) {
unset( $data['payment_methods'][ $key ] );
}
}
$data['payment_methods'] = array_values( $data['payment_methods'] );
ASP_Debug_Logger::log( sprintf( 'APM disabled for product %d: need APM 2.0.17+ for checkbox variation type support.', $data['product_id'] ) );
break;
}
}
}
if ( empty( $plan_id ) ) {
$this->item->set_currency( $data['currency'] );
$this->item->set_price( $data['item_price'], true );
$data['item_price'] = $this->item->get_price( true );
$this->item->set_shipping( $data['shipping'], true );
$data['shipping'] = $this->item->get_shipping( true );
$tmp_curr = strtoupper( $data['currency'] );
if ( isset( $currencies[ $tmp_curr ] ) ) {
$curr_sym = $currencies[ $tmp_curr ][1];
} else {
//no currency code found, let's just use currency code instead of symbol
$curr_sym = $tmp_curr;
}
$display_settings['s'] = $curr_sym;
}
$data['items'] = $this->item->get_items();
$a['data'] = $data;
if ( isset( $data['fatal_error'] ) ) {
$a['fatal_error'] = $data['fatal_error'];
}
$a['scripts'] = array();
$a['styles'] = array();
$a['vars'] = array();
// Stripe script should come first
$a['scripts'][] = array(
'footer' => true,
'src' => 'https://js.stripe.com/v3/',
);
$site_url = $data['is_live'] ? get_site_url( null, '', 'https' ) : get_site_url();
$a['scripts'][] = array(
'src' => $site_url . '/wp-includes/js/jquery/jquery.js?ver=1.12.4-wp',
'footer' => true,
);
//filters for addons to add styles, scripts and vars
$a['styles'] = apply_filters( 'asp_ng_pp_output_add_styles', $a['styles'] );
$a['scripts'] = apply_filters( 'asp_ng_pp_output_add_scripts', $a['scripts'] );
$a['vars'] = apply_filters( 'asp_ng_pp_output_add_vars', $a['vars'] );
if ( ! defined( 'WP_ASP_DEV_MODE' ) ) {
$a['styles'][] = array(
'footer' => false,
'src' => WP_ASP_PLUGIN_URL . '/public/views/templates/default/pp-combined.min.css?ver=' . WP_ASP_PLUGIN_VERSION,
);
$a['scripts'][] = array(
'footer' => true,
'src' => WP_ASP_PLUGIN_URL . '/public/assets/js/pp-handler.min.js?ver=' . WP_ASP_PLUGIN_VERSION,
);
} else {
$a['styles'][] = array(
'footer' => false,
'src' => WP_ASP_PLUGIN_URL . '/public/views/templates/default/pure.css?ver=' . WP_ASP_PLUGIN_VERSION,
);
$a['styles'][] = array(
'footer' => false,
'src' => WP_ASP_PLUGIN_URL . '/public/views/templates/default/pp-style.css?ver=' . WP_ASP_PLUGIN_VERSION,
);
$a['scripts'][] = array(
'footer' => true,
'src' => WP_ASP_PLUGIN_URL . '/public/assets/js/md5.min.js?ver=' . WP_ASP_PLUGIN_VERSION,
);
$a['scripts'][] = array(
'footer' => true,
'src' => WP_ASP_PLUGIN_URL . '/public/assets/js/add-ons/tax-variations.js?ver=' . WP_ASP_PLUGIN_VERSION,
);
$a['scripts'][] = array(
'footer' => true,
'src' => WP_ASP_PLUGIN_URL . '/public/assets/js/pp-handler.js?ver=' . WP_ASP_PLUGIN_VERSION,
);
}
$a['hide_state_field'] = $this->asp_main->get_setting( 'hide_state_field' );
$pay_btn_text = $this->asp_main->get_setting( 'popup_button_text' );
if ( empty( $pay_btn_text ) ) {
// translators: %s is not a placeholder
$pay_btn_text = __( 'Pay %s', 'stripe-payments' );
} else {
$pay_btn_text = __( $pay_btn_text, 'stripe-payments' );
}
if ( $auth_only ) {
// translators: %s is not a placeholder
$pay_btn_text = __( 'Authorize %s', 'stripe-payments' );
}
if ( isset( $data['is_trial'] ) && $data['is_trial'] ) {
if ( empty( $plan_id ) ) {
$data['amount_variable'] = false;
if ( $this->item->get_price() === 0 ) {
$data['amount_variable'] = false;
}
}
$pay_btn_text = apply_filters( 'asp_customize_text_msg', __( 'Start Free Trial', 'stripe-payments' ), 'start_free_trial' );
}
// Check user has specified any popup-payment button text for individual product.
$per_product_pay_btn_text = $this->item->get_meta( 'asp_product_popup_button_text' );
if (!empty($per_product_pay_btn_text)) {
$pay_btn_text = __( $per_product_pay_btn_text, 'stripe-payments' );
}
//filter to change pay button text
$pay_btn_text = apply_filters( 'asp_ng_pp_pay_button_text', $pay_btn_text );
$a['item'] = $this->item;
$btn_uniq_id = isset( $_GET['btn_uniq_id'] ) ? sanitize_text_field( stripslashes ( $_GET['btn_uniq_id'] ) ) : '';
if ( ! empty( $btn_uniq_id ) ) {
$a['btn_uniq_id'] = $btn_uniq_id;
}
$a['vars']['vars'] = array(
'data' => $data,
'stripe_key' => ! empty( $data['stripe_key'] ) ? $data['stripe_key'] : $a['stripe_key'],
'stripe_api_ver' => ASPMain::$stripe_api_ver,
'minAmounts' => $this->asp_main->minAmounts,
'zeroCents' => $this->asp_main->zeroCents,
'ajaxURL' => admin_url( 'admin-ajax.php' ),
'asp_pp_ajax_nonce' => wp_create_nonce( 'asp_pp_ajax_nonce' ),
'asp_pp_ajax_create_pi_nonce' => wp_create_nonce( 'asp_pp_ajax_create_pi_nonce' ),
'currencyFormat' => $display_settings,
'payBtnText' => $pay_btn_text,
'amountOpts' => array(
'applySepOpts' => $this->asp_main->get_setting( 'price_apply_for_input' ),
'decimalSep' => $this->asp_main->get_setting( 'price_decimal_sep' ),
'thousandSep' => $this->asp_main->get_setting( 'price_thousand_sep' ),
),
'str' => array(
'strEnterValidAmount' => apply_filters( 'asp_customize_text_msg', __( 'Please enter a valid amount', 'stripe-payments' ), 'enter_valid_amount' ),
'strMinAmount' => apply_filters( 'asp_customize_text_msg', __( 'Minimum amount is', 'stripe-payments' ), 'min_amount_is' ),
'strEnterQuantity' => apply_filters( 'asp_customize_text_msg', __( 'Please enter quantity.', 'stripe-payments' ), 'enter_quantity' ),
'strQuantityIsZero' => apply_filters( 'asp_customize_text_msg', __( 'Quantity can\'t be zero.', 'stripe-payments' ), 'quantity_is_zero' ),
'strQuantityIsFloat' => apply_filters( 'asp_customize_text_msg', __( 'Quantity should be integer value.', 'stripe-payments' ), 'quantity_is_float' ),
// translators: %d is number of items in stock
'strStockNotAvailable' => apply_filters( 'asp_customize_text_msg', __( 'You cannot order more items than available: %d', 'stripe-payments' ), 'stock_not_available' ),
'strTax' => apply_filters( 'asp_customize_text_msg', __( 'Tax', 'stripe-payments' ), 'tax_str' ),
'strShipping' => apply_filters( 'asp_customize_text_msg', __( 'Shipping', 'stripe-payments' ), 'shipping_str' ),
'strSurcharge' => apply_filters( 'asp_customize_text_msg', __( 'Surcharge', 'stripe-payments' ), 'surcharge_str' ),
'strTotal' => __( 'Total:', 'stripe-payments' ),
'strPleaseFillIn' => apply_filters( 'asp_customize_text_msg', __( 'Please fill in this field.', 'stripe-payments' ), 'fill_in_field' ),
'strPleaseCheckCheckbox' => __( 'Please check this checkbox.', 'stripe-payments' ),
'strMustAcceptTos' => apply_filters( 'asp_customize_text_msg', __( 'You must accept the terms before you can proceed.', 'stripe-payments' ), 'accept_terms' ),
'strCoupon' => __( 'Coupon', 'stripe-payments' ),
'strRemoveCoupon' => apply_filters( 'asp_customize_text_msg', __( 'Remove coupon', 'stripe-payments' ), 'remove_coupon' ),
'strRemove' => apply_filters( 'asp_customize_text_msg', __( 'Remove', 'stripe-payments' ), 'remove' ),
'strStartFreeTrial' => apply_filters( 'asp_customize_text_msg', __( 'Start Free Trial', 'stripe-payments' ), 'start_free_trial' ),
'strInvalidCFValidationRegex' => __( 'Invalid validation RegEx: ', 'stripe-payments' ),
'strGetForFree' => __( 'Purchase for Free', 'stripe-payments' ),
'strCurrencyNotSupported' => __( 'Currency not supported for this payment method.', 'stripe-payments' ),
'strforRecurringPayments' => __( ' for upcoming recurring payments', 'stripe-payments' ),
'str3DSecureFailed' => __( '3D Secure failed.', 'stripe-payments' ),
'strAbort3DSecure' => __( 'Abort 3D Secure check?', 'stripe-payments' ),
),
);
if ( isset( $a['fatal_error'] ) ) {
$a['vars']['vars']['fatal_error'] = $a['fatal_error'];
}
$a ['pay_btn_text'] = str_replace( '%s', AcceptStripePayments::formatted_price( $this->item->get_total(), $this->item->get_currency() ), $pay_btn_text );
//output custom PP CSS if needed
add_action( 'asp_ng_pp_output_before_closing_body', array( $this, 'output_custom_css' ), 1000 );
require_once WP_ASP_PLUGIN_PATH . 'public/views/templates/default/payment-popup.php';
exit;
}
public function output_custom_css( $a ) {
$pp_additional_css = $this->asp_main->get_setting( 'pp_additional_css' );
if ( empty( $pp_additional_css ) ) {
return;
}
echo sprintf( "<style>%s</style>\r\n", wp_kses( str_replace( array( "\t", "\r\n" ), '', $pp_additional_css ), array() ) );
}
public function tpl_get_cf( $output = '' ) {
if ( empty( $this->tpl_cf ) ) {
$replace_cf = apply_filters(
'asp_ng_button_output_replace_custom_field',
'',
array(
'product_id' => $this->prod_id,
'custom_field' => $this->custom_field,
)
);
if ( ! empty( $replace_cf ) ) {
//we got custom field replaced
$this->tpl_cf = $replace_cf;
$output .= $this->tpl_cf;
$this->tpl_cf = '';
return $output;
}
$field_type = $this->asp_main->get_setting( 'custom_field_type' );
$field_name = $this->asp_main->get_setting( 'custom_field_name' );
$field_name = empty( $field_name ) ? __( 'Custom Field', 'stripe-payments' ) : $field_name;
$field_descr = $this->asp_main->get_setting( 'custom_field_descr' );
$descr_loc = $this->asp_main->get_setting( 'custom_field_descr_location' );
$mandatory = $this->asp_main->get_setting( 'custom_field_mandatory' );
$tpl_cf = '';
$tpl_cf .= "<div class='asp_product_custom_field_input_container'>";
$tpl_cf .= '<fieldset>';
$tpl_cf .= '<input type="hidden" name="stripeCustomFieldName" value="' . esc_attr( $field_name ) . '">';
switch ( $field_type ) {
case 'text':
if ( 'below' !== $descr_loc ) {
$tpl_cf .= sprintf(
'<label class="asp_product_custom_field_label">%s</label><input id="asp-custom-field" name="stripeCustomField" class="pure-input-1 asp_product_custom_field_input" type="text"%s placeholder="%s"%s>',
esc_html( $field_name ),
( $mandatory ? ' data-asp-custom-mandatory' : '' ),
esc_attr( $field_descr ),
( $mandatory ? ' required' : '' )
);
} else {
$tpl_cf .= sprintf(
'<label class="asp_product_custom_field_label">%s</label><input id="asp-custom-field" name="stripeCustomField" class="pure-input-1 asp_product_custom_field_input" type="text"%s%s>',
esc_html( $field_name ),
( $mandatory ? ' data-asp-custom-mandatory' : '' ),
( $mandatory ? ' required' : '' )
);
$tpl_cf .= sprintf( '<div class="asp_product_custom_field_descr">%s</div>', $field_descr );
}
break;
case 'checkbox':
$tpl_cf .= '<label class="pure-checkbox asp_product_custom_field_label"><input id="asp-custom-field" class="asp_product_custom_field_input" type="checkbox"' . ( $mandatory ? ' data-asp-custom-mandatory' : '' ) . ' name="stripeCustomField"' . ( $mandatory ? ' required' : '' ) . '> ' . $field_descr . '</label>';
break;
}
$tpl_cf .= '<div id="custom-field-error" class="form-err" role="alert"></div>' .
'</fieldset>' .
'</div>';
$this->tpl_cf = $tpl_cf;
}
$output .= $this->tpl_cf;
$this->tpl_cf = '';
return $output;
}
}
new ASP_PP_Display();

View File

@ -0,0 +1,926 @@
<?php
class ASP_Process_IPN_NG {
public $asp_redirect_url = '';
public $item;
public $err = '';
public $asp_class;
public $sess;
public $p_data;
//Important Note: This $post_data variable need to be unset so that it does not interfere with the "isset" logic in the get_post_var function.
public $post_data;
protected static $instance = null;
public function __construct() {
self::$instance = $this;
$this->asp_class = AcceptStripePayments::get_instance();
$this->sess = ASP_Session::get_instance();
$this->asp_redirect_url = $this->asp_class->get_setting( 'checkout_url' );
$process_ipn = filter_input( INPUT_POST, 'asp_process_ipn', FILTER_SANITIZE_NUMBER_INT );
if ( $process_ipn ) {
add_action( 'asp_ng_process_ipn_payment_data_item_override', array( $this, 'payment_data_override' ), 10, 2 );
add_action( 'wp_loaded', array( $this, 'process_ipn' ), 2147483647 );
}
if ( wp_doing_ajax() ) {
add_action( 'wp_ajax_asp_next_action_results', array( $this, 'handle_next_action_results' ) );
add_action( 'wp_ajax_nopriv_asp_next_action_results', array( $this, 'handle_next_action_results' ) );
}
}
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public function handle_next_action_results() {
ASP_Debug_Logger::log( 'handle_next_action_results() - processing.', true);
$pi_id = isset( $_GET['payment_intent'] ) ? sanitize_text_field( stripslashes ( $_GET['payment_intent'] ) ) : '';
$is_live = isset( $_GET['is_live'] ) ? sanitize_text_field( stripslashes ( $_GET['is_live'] ) ) : '';
$is_live = 'false' === $is_live ? 0 : 1;
$sess = ASP_Session::get_instance();
$form_data = $sess->get_transient_data( 'asp_pp_form_data' );
foreach ( $form_data as $name => $value ) {
$post_data[ 'asp_' . $name ] = $value;
}
unset( $post_data['asp_process_ipn'] );
$post_data['asp_payment_intent'] = $pi_id;
$_POST = $post_data;
$this->post_data = $post_data;
$product_id = $this->get_post_var( 'asp_product_id', FILTER_SANITIZE_NUMBER_INT );
do_action( 'asp_ng_product_mode_keys', $product_id );
try {
ASPMain::load_stripe_lib();
$key = $is_live ? $this->asp_class->APISecKey : $this->asp_class->APISecKeyTest;
\Stripe\Stripe::setApiKey( $key );
if ( ASP_Utils::use_internal_api() ) {
$api = ASP_Stripe_API::get_instance();
$api->set_api_key( $key );
$intent = $api->get( 'payment_intents/' . $pi_id );
if ( 'succeeded' !== $intent->status ) {
$res = $api->post(
'payment_intents/' . $pi_id . '/confirm',
array()
);
if ( false === $res ) {
$err = $api->get_last_error();
$this->err = $err['message'];
}
}
} else {
$intent = \Stripe\PaymentIntent::retrieve( $pi_id );
if ( 'succeeded' !== $intent->status ) {
$intent->confirm();
}
}
} catch ( \Throwable $e ) {
$this->err = $e->getMessage();
}
$this->process_ipn( $post_data );
}
public function ipn_completed( $err_msg = '' ) {
if ( ! empty( $err_msg ) ) {
$asp_data = array( 'error_msg' => $err_msg );
ASP_Debug_Logger::log( $err_msg, false ); //Log the error
$this->sess->set_transient_data( 'asp_data', $asp_data );
//Trigger an action hook for this error condition.
//The $_POST data is available in the global $_POST variable which may contain additional details.
do_action( 'asp_stripe_process_ipn_error', $err_msg );
//send email to notify site admin (if option enabled)
$opt = get_option( 'AcceptStripePayments-settings' );
if ( isset( $opt['send_email_on_error'] ) && $opt['send_email_on_error'] ) {
$body = '';
$body .= __( 'Following error occurred during payment processing:', 'stripe-payments' ) . "\r\n\r\n";
$body .= $err_msg . "\r\n\r\n";
$body .= __( 'Debug data:', 'stripe-payments' ) . "\r\n";
$post = filter_var( $_POST, FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY );
foreach ( $post as $key => $value ) {
//Make sure the value is not an array.
$value = is_array( $value ) ? wp_json_encode( $value ) : $value;
$key = sanitize_text_field( stripslashes( $key ));
$value = sanitize_text_field( stripslashes( $value ));
$body .= $key . ': ' . $value . "\r\n";
}
ASP_Utils::send_error_email( $body );
}
} else {
ASP_Debug_Logger::log( 'Payment has been processed successfully.' );
}
$structure = get_option( 'permalink_structure' );
$url_host = str_replace( 'www.', '', parse_url( $this->asp_redirect_url, PHP_URL_HOST ) );
$home_url_host = str_replace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
if ( empty( $structure && ( $url_host && $url_host === $home_url_host ) ) ) {
$path = basename( parse_url( $this->asp_redirect_url, PHP_URL_PATH ) );
$r_post = get_page_by_path( $path );
if ( ! empty( $r_post ) ) {
$this->asp_redirect_url = get_permalink( $r_post->ID );
}
}
if ( is_ssl() ) {
$this->asp_redirect_url = ASP_Utils::url_to_https( $this->asp_redirect_url );
}
ASP_Debug_Logger::log( sprintf( 'Redirecting to results page "%s"', $this->asp_redirect_url ) . "\r\n" );
wp_redirect( $this->asp_redirect_url );
exit;
}
public function get_post_var( $var, $filter = FILTER_UNSAFE_RAW, $opts = 0 ) {
if ( isset( $this->post_data ) ) {
if ( isset( $this->post_data[ $var ] ) ) {
return filter_var( $this->post_data[ $var ], $filter, $opts );
} else {
return null;
}
}
$val = filter_input( INPUT_POST, $var, $filter, $opts );
return $val;
}
private function paid_amount_valid( $expected_amount_in_cents, $amount_paid, $item ) {
//Check if paid amount is less than expected amount.
if ( $amount_paid < $expected_amount_in_cents ) {
//Incorrect amount paid. Flag the transaction.
//Check if this is a subs product
if ( method_exists( $item, 'get_plan_id' ) ) {
//This is a subsription product. Let's check if subs addon version is prior to 2.0.1.
if ( version_compare( ASPSUB_main::ADDON_VER, '2.0.1' ) < 0 ) {
//subs addon version is prior to 2.0.1. This means error is most likely not legit.
return true;
}
}
return false;
}
//Paid amount looks good.
return true;
}
private function paid_currency_valid( $p_curr, $configured_currency, $item ){
//$item object can be used to retreive the product details.
//Trigger filter that can be used to check this from the subscription addon (if needed).
$configured_currency = apply_filters( 'asp_ipn_check_currency_configured', $configured_currency, $p_curr, $item );
if ( strtolower($p_curr) !== strtolower($configured_currency) ) {
return false;
}
return true;
}
public function process_ipn( $post_data = array() ) {
ASP_Debug_Logger::log( 'Payment processing started.' );
if ( ! empty( $post_data ) ) {
$post_data = filter_var( $post_data, FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY );
$post_data_str = http_build_query( $post_data, '', '; ' );
ASP_Debug_Logger::log( 'Custom $_POST data: ' . $post_data_str );
$this->post_data = $post_data;
} else {
$post_data = filter_var( $_POST, FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY );
$post_data_str = http_build_query( $post_data, '', '; ' );
//ASP_Debug_Logger::log( 'Original $_POST data: ' . $post_data_str );
}
do_action( 'asp_ng_before_payment_processing', $post_data );
$this->sess = ASP_Session::get_instance();
$post_thankyou_page_url = $this->get_post_var( 'asp_thankyou_page_url' );
$post_thankyou_page_url = sanitize_text_field( stripslashes( $post_thankyou_page_url ) );
$this->asp_redirect_url = empty( $post_thankyou_page_url ) ? $this->asp_class->get_setting( 'checkout_url' ) : base64_decode( $post_thankyou_page_url );
$prod_id = $this->get_post_var( 'asp_product_id', FILTER_SANITIZE_NUMBER_INT );
if ( ! empty( $prod_id ) ) {
ASP_Debug_Logger::log( sprintf( 'Got product ID: %d', $prod_id ) );
}
$item = new ASP_Product_Item( $prod_id );
ASP_Debug_Logger::log( 'Firing asp_ng_process_ipn_product_item_override filter.' );
$item = apply_filters( 'asp_ng_process_ipn_product_item_override', $item );
$err = $item->get_last_error();
if ( ! empty( $err ) ) {
$this->ipn_completed( $err );
}
$this->item = $item;
if ( empty( $this->asp_redirect_url ) && $item->get_redir_url() ) {
$this->asp_redirect_url = $item->get_redir_url();
}
if ( $this->err ) {
$this->ipn_completed( $this->err );
}
$pi = $this->get_post_var( 'asp_payment_intent' );
$pi = sanitize_text_field( stripslashes( $pi ) );
$completed_order = get_posts(
array(
'post_type' => 'stripe_order',
'meta_key' => 'pi_id',
'meta_value' => $pi,
)
);
wp_reset_postdata();
if ( ! empty( $completed_order ) ) {
//already processed - let's redirect to results page
$this->ipn_completed();
exit;
}
$is_live = $this->get_post_var( 'asp_is_live', FILTER_VALIDATE_BOOLEAN );
do_action( 'asp_ng_product_mode_keys', $prod_id );
ASP_Utils::load_stripe_lib();
$key = $is_live ? $this->asp_class->APISecKey : $this->asp_class->APISecKeyTest;
\Stripe\Stripe::setApiKey( $key );
$api = ASP_Stripe_API::get_instance();
$api->set_api_key( $key );
//Get Payment Data
ASP_Debug_Logger::log( 'Firing asp_ng_process_ipn_payment_data_item_override filter.' );
$p_data = apply_filters( 'asp_ng_process_ipn_payment_data_item_override', false, $pi );
if ( false === $p_data ) {
//Payment data override filter did not return any data. Let's get the data from the payment intent object.
//The billing details [example: ASP_Payment_Data->get_billing_details()] and some other transaction data are read from the payment intent object within the ASP_Payment_Data class.
$p_data = new ASP_Payment_Data( $pi );
}
$p_last_err = $p_data->get_last_error();
if ( ! empty( $p_last_err ) ) {
$this->ipn_completed( $p_last_err );
}
$this->p_data = $p_data;
//End retrieval of payment data
//Mechanism to lock the txn that is being processed.
$txn_being_processed = get_option( 'asp_ng_ipn_txn_being_processed' );
$notification_txn_id = $p_data->get_trans_id();
ASP_Debug_Logger::log( 'The transaction ID of this notification is: ' . $notification_txn_id );
if ( ! empty( $txn_being_processed ) && $txn_being_processed === $notification_txn_id ) {
//No need to process this transaction as it is already being processed.
ASP_Debug_Logger::log( 'This transaction (' . $notification_txn_id . ') is already being procesed. This is likely a duplicate notification. Nothing to do.' );
return true;
}
update_option( 'asp_ng_ipn_txn_being_processed', $notification_txn_id );
//End of transaction processing lock mechanism
//Button key
$button_key = $item->get_button_key();
//Item quantity
$post_quantity = $this->get_post_var( 'asp_quantity', FILTER_SANITIZE_NUMBER_INT );
if ( $post_quantity ) {
$item->set_quantity( $post_quantity );
}
//Item price
$price = $item->get_price();
$curr = $item->get_currency();
$shipping = $item->get_shipping();
if ( ! method_exists( $item, 'get_plan_id' ) ) {
$price_arr = apply_filters(
'asp_modify_price_currency_shipping',
array(
'price' => $price,
'currency' => $curr,
'shipping' => empty( $shipping ) ? false : $shipping,
'variable' => empty( $price ) ? true : false,
)
);
$item->set_price( $price_arr['price'] );
$item->set_currency( $price_arr['currency'] );
$item->set_shipping( $price_arr['shipping'] );
}
$tax_variations_arr = $item->get_meta( 'asp_product_tax_variations' );
$tax_variations_type = $this->item->get_meta( 'asp_product_tax_variations_type' );
$tax_variations_type = empty( $tax_variations_type ) ? 'b' : $tax_variations_type;
if ( 'b' === $tax_variations_type ) {
$bs_details = $p_data->get_billing_details();
} else {
$bs_details = $p_data->get_shipping_details();
}
if ( ! empty( $bs_details ) && ! empty( $tax_variations_arr ) ) {
$new_tax = ASP_Utils::get_tax_variations_tax(
$tax_variations_arr,
empty( $bs_details->country ) ? '' : $bs_details->country,
empty( $bs_details->state ) ? '' : $bs_details->state,
empty( $bs_details->city ) ? '' : $bs_details->city
);
if ( false !== $new_tax ) {
$item->set_tax( $new_tax );
}
}
// Check and calculate regional shipping amount if available.
$calculate_shipping_amount = apply_filters('asp_calculate_shipping_amount_on_ipn_process', true, $prod_id); // Useful for subscription addon.
if ($calculate_shipping_amount){
$base_shipping_amount = $item->get_shipping(true);
$total_shipping_amount = $base_shipping_amount;
$collect_shipping_addr_enabled = $item->get_meta('asp_product_collect_shipping_addr');
if ($collect_shipping_addr_enabled == '1' ){
// ASP_Debug_Logger::log('Calculation regional shipping amount.', true);
$shipping_region = get_object_vars($p_data->get_shipping_details());
$regional_shipping_amount = $item->calculate_regional_shipping_amount($shipping_region, true);
$total_shipping_amount += $regional_shipping_amount;
}
$item->set_shipping( $total_shipping_amount, true );
}
if ( empty( $price ) ) {
$post_price = $this->get_post_var( 'asp_amount', FILTER_SANITIZE_NUMBER_FLOAT );
if ( $post_price ) {
$price = $post_price;
} else {
if ( ! $item->get_meta( 'asp_product_hide_amount_input' ) ) {
$price = $p_data->get_price();
} else {
$price = 0;
}
}
$price = AcceptStripePayments::from_cents( $price, $item->get_currency() );
$item->set_price( $price );
}
$item_price = $item->get_price();
//Variatoions
$variations = array();
$posted_variations = $this->get_post_var( 'asp_stripeVariations', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
if ( $posted_variations ) {
// we got variations posted. Let's get variations from product
$v = new ASPVariations( $prod_id );
if ( ! empty( $v->variations ) ) {
//there are variations configured for the product
ASP_Debug_Logger::log( 'Processing variations.' );
foreach ( $posted_variations as $grp_id => $var_id ) {
if ( is_array( $var_id ) && ! empty( $var_id ) ) {
foreach ( $var_id as $p_var ) {
$var = $v->get_variation( $grp_id, $p_var );
if ( ! empty( $var ) ) {
$item->add_item( $var['name'], $var['price'] );
$variations[] = array( $var['group_name'] . ' - ' . $var['name'], $var['price'] );
$var_applied[] = $var;
}
}
}
}
}
}
//Coupon
$coupon_code = $this->get_post_var( 'asp_coupon-code' );
$coupon_valid = false;
if ( isset($coupon_code) && !empty($coupon_code)) {
$coupon_code = sanitize_text_field( stripslashes( $coupon_code ));
ASP_Debug_Logger::log( sprintf( 'Coupon code provided: %s', $coupon_code ) );
$coupon_valid = $item->check_coupon( $coupon_code );
if ( $coupon_valid ) {
ASP_Debug_Logger::log( 'Coupon is valid for the product.' );
} else {
ASP_Debug_Logger::log( 'Coupon is invalid for the product.' );
}
}
$amount_in_cents = intval( $item->get_total( true ) );
$amount_paid = intval( $p_data->get_amount() );
$configured_currency = $item->get_currency();//Currency configured in product/general settings
$is_currency_variable = $item->is_currency_variable();
$p_curr = $p_data->get_currency();//Currency from payment data
//Check currency
$paid_currency_valid = $this->paid_currency_valid( $p_curr, $configured_currency, $item );
//Trigger filter that can be used to check this from the subscription addon (if needed).
$paid_currency_valid = apply_filters( 'asp_process_ipn_paid_currency_valid', $paid_currency_valid, $item );
if ( !$paid_currency_valid ) {
//Check if the currency variable option is enabled.
$is_currency_variable = apply_filters( 'asp_process_ipn_is_currency_variable', $is_currency_variable, $item );
if ( $is_currency_variable ){
//The currency variable option is enabled. We will allow this request to go through.
//ASP_Debug_Logger::log( 'Note! The currency variable option is enabled in the product settings', true );
} else {
$err = sprintf(
// translators: placeholders are expected and received currencies
__( 'Invalid currency received. Expected %1$s, got %2$s.', 'stripe-payments' ),
$configured_currency,
$p_curr
);
//The following function will also log the error to the debug log.
$this->ipn_completed( $err );
}
}
//Check paid amount
$paid_amount_valid = $this->paid_amount_valid( $amount_in_cents, $amount_paid, $item );
if ( ! $paid_amount_valid ) {
$err = sprintf(
// translators: placeholders are expected and received amounts
__( 'Invalid payment amount received. Expected %1$s, got %2$s.', 'stripe-payments' ),
AcceptStripePayments::formatted_price( $amount_in_cents, $p_curr, true ),
AcceptStripePayments::formatted_price( $amount_paid, $p_curr, true )
);
//The following function will also log the error to the debug log.
$this->ipn_completed( $err );
}
$opt = get_option( 'AcceptStripePayments-settings' );
ASP_Debug_Logger::log( 'Constructing checkout result and order data.' );
$p_curr = $p_data->get_currency();
$p_amount = $p_data->get_amount();
$p_charge_data = $p_data->get_charge_data();
$p_charge_created = $p_data->get_charge_created();
$p_trans_id = $p_data->get_trans_id();
$p_billing_details = $p_data->get_billing_details();
$p_customer_details = $p_data->get_customer_details();
if ( empty( $p_billing_details->email ) ) {
$email = $this->get_post_var( 'asp_email', FILTER_SANITIZE_EMAIL );
if ( ! empty( $email ) ) {
$p_billing_details->email = $email;
}
}
if ( empty( $p_billing_details->name ) ) {
$name = $this->get_post_var( 'asp_billing_name' );
$name = sanitize_text_field( stripslashes( $name ));
if ( ! empty( $name ) ) {
$p_billing_details->name = $name;
}
}
$data = array();
$data['product_id'] = $prod_id ? $prod_id : null;
$data['paid_amount'] = AcceptStripePayments::is_zero_cents( $p_curr ) ? $p_amount : AcceptStripePayments::from_cents( $p_amount, $p_curr );
$data['currency_code'] = strtoupper( $p_curr );
$data['item_quantity'] = $item->get_quantity();
$data['charge'] = $p_charge_data;
// $data['stripeToken'] = '';
$data['stripeTokenType'] = 'card';
$data['is_live'] = $is_live;
$data['charge_description'] = $item->get_description();
$data['item_name'] = $item->get_name();
$data['item_price'] = $item->get_price( AcceptStripePayments::is_zero_cents( $data['currency_code'] ) );
$data['stripeEmail'] = $p_billing_details->email;
$data['customer_name'] = $p_billing_details->name;
$purchase_date = gmdate( 'Y-m-d H:i:s', $p_charge_created );
$purchase_date = get_date_from_gmt( $purchase_date, get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) );
$data['purchase_date'] = $purchase_date;
$data['charge_date'] = $purchase_date;
$data['charge_date_raw'] = $p_charge_created;
$data['txn_id'] = $p_trans_id;
$data['button_key'] = $button_key;
//Type casting to an array to prevent any potential PHP warnings.
$customer_metadata = isset($p_customer_details->metadata) ? (array)$p_customer_details->metadata : array();
if ( !empty($customer_metadata) ){
$data['customer_first_name'] = isset($customer_metadata['First Name']) ? sanitize_text_field($customer_metadata['First Name']) : '';
$data['customer_last_name'] = isset($customer_metadata['Last Name']) ? sanitize_text_field($customer_metadata['Last Name']) : '';
}
$item_url = $item->get_download_url();
$data['item_url'] = $item_url;
$data['billing_address'] = $p_data->get_billing_addr_str();
$data['shipping_address'] = $p_data->get_shipping_addr_str();
//Check if there is a logged in user who is making the purchase.
$logged_in_user_info = ASP_Utils::get_logged_in_user_info();
if ( is_array($logged_in_user_info) && !empty($logged_in_user_info) ) {
$data['logged_in_user_type'] = isset($logged_in_user_info['type']) ? $logged_in_user_info['type'] : '';
$data['logged_in_user_id'] = isset($logged_in_user_info['id']) ? $logged_in_user_info['id'] : '';
$data['logged_in_user_name'] = isset($logged_in_user_info['username']) ? $logged_in_user_info['username'] : '';
ASP_Debug_Logger::log( 'Logged-in user\'s Username: ' . $data['logged_in_user_name'] );
}
$data['additional_items'] = array();
ASP_Debug_Logger::log( 'Firing asp_ng_payment_completed filter.' );
$data = apply_filters( 'asp_ng_payment_completed', $data, $prod_id );
$currency_code = $item->get_currency();
$item_price = $item->get_price( AcceptStripePayments::is_zero_cents( $currency_code ) );
$custom_fields = array();
$cf_name = $this->get_post_var( 'asp_stripeCustomFieldName' );
if ( $cf_name ) {
$cf_name = sanitize_text_field( stripslashes( $cf_name ));
$cf_value = $this->get_post_var( 'asp_stripeCustomField' );
$cf_value = sanitize_text_field( stripslashes( $cf_value ));
$custom_fields[] = array(
'name' => $cf_name,
'value' => $cf_value,
);
}
//Compatability with the ACF addon
//Note: This $acf_fields input is now handled directly in the new version of the ACF addon. So it is commented out here.
//$acf_fields = $this->get_post_var( 'asp_stripeCustomFields', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$custom_fields = apply_filters( 'asp_process_custom_fields', $custom_fields, array( 'product_id' => $prod_id ) );
if ( ! empty( $custom_fields ) ) {
$data['custom_fields'] = $custom_fields;
}
if ( ! empty( $var_applied ) ) {
//process variations URLs if needed
foreach ( $var_applied as $key => $var ) {
if ( ! empty( $var['url'] ) ) {
$var = apply_filters( 'asp_variation_url_process', $var, $data );
$var_applied[ $key ] = $var;
}
}
$data['var_applied'] = $var_applied;
foreach ( $variations as $variation ) {
$data['additional_items'][ $variation[0] ] = $variation[1];
}
}
//check if coupon was used
if ( $coupon_valid ) {
$coupon = $item->get_coupon();
}
if ( isset( $coupon ) ) {
// Get subtotal amount
$subtotal = $item->get_price( false, false ) + $item->get_items_total( false, false );
$subtotal = $subtotal < 0 ? 0 : $subtotal;
// Get total coupon discount amount
$coupon_discount_amount = $item->get_coupon_discount_amount();
if(!empty($item->get_quantity()) && is_numeric($item->get_quantity())){
$subtotal = $subtotal * $item->get_quantity();
if (isset($coupon['discount_type']) && $coupon['discount_type'] === 'perc' ){ // NOTE: Flat discount doesn't need to multiply with quantity
$coupon_discount_amount = $coupon_discount_amount * $item->get_quantity();
}
}
// Append subtotal info
$data['additional_items'][ __( 'Subtotal', 'stripe-payments' ) ] = $subtotal;
// Append coupon info
$data['coupon'] = $coupon;
$data['coupon_code'] = $coupon['code'];
$coupon_discount_str = apply_filters( 'asp_ng_coupon_discount_str', floatval( '-' . $coupon_discount_amount ), $coupon );
// translators: %s is coupon code
$data['additional_items'][ sprintf( __( 'Coupon "%s"', 'stripe-payments' ), $coupon['code'] ) ] = $coupon_discount_str;
//increase coupon redeem count
$curr_redeem_cnt = get_post_meta( $coupon['id'], 'asp_coupon_red_count', true );
$curr_redeem_cnt++;
update_post_meta( $coupon['id'], 'asp_coupon_red_count', $curr_redeem_cnt );
}
$tax = $item->get_tax();
if ( ! empty( $tax ) ) {
$tax_str = apply_filters( 'asp_customize_text_msg', __( 'Tax', 'stripe-payments' ), 'tax_str' );
$tax_amt = $item->get_tax_amount( false, true );
$data['additional_items'][ ucfirst( $tax_str ) ] = $tax_amt;
$data['tax_perc'] = $item->get_tax();
$data['tax'] = $tax_amt;
}
$ship = $item->get_shipping();
if ( ! empty( $ship ) ) {
$ship_str = apply_filters( 'asp_customize_text_msg', __( 'Shipping', 'stripe-payments' ), 'shipping_str' );
$data['additional_items'][ ucfirst( $ship_str ) ] = $item->get_shipping();
$data['shipping'] = $item->get_shipping();
}
$product_type = $item->get_type();
//Check if surcharge is enabled for this product (if one-time or donations type product).
if ( in_array($product_type, array('one_time', 'donation')) ){
//Surcharge feature is currently supported for one_time and donation products only.
$surcharge_amount = $p_data->get_surcharge_data('amount');
if ( !empty($surcharge_amount) ){
$surcharge_label = $p_data->get_surcharge_data('label');
$data['additional_items'][$surcharge_label] = $surcharge_amount;
}
}
//custom fields
$custom_fields = $this->sess->get_transient_data( 'custom_fields' );
if ( ! empty( $custom_fields ) ) {
$data['custom_fields'] = $custom_fields;
$this->sess->set_transient_data( 'custom_fields', array() );
}
$metadata = array();
//Check if we need to include custom field in metadata
if ( ! empty( $data['custom_fields'] ) ) {
$cf_str = '';
foreach ( $data['custom_fields'] as $cf ) {
$cf_str .= $cf['name'] . ': ' . $cf['value'] . ' | ';
}
$cf_str = rtrim( $cf_str, ' | ' );
//trim the string as metadata value cannot exceed 500 chars
$cf_str = substr( $cf_str, 0, 499 );
//add custom fields string to metadata
ASP_Debug_Logger::log( 'Adding custom fields string to metadata - ' . $cf_str );
$metadata['Custom Fields'] = $cf_str;
}
//Check if we need to include variations data into metadata
if ( ! empty( $variations ) ) {
$var_str = '';
foreach ( $variations as $variation ) {
$var_str .= '[' . $variation[0] . '], ';
}
$var_str = rtrim( $var_str, ', ' );
//trim the string as metadata value cannot exceed 500 chars
$var_str = substr( $var_str, 0, 499 );
$metadata['Variations'] = $var_str;
}
if ( ! empty( $data['shipping_address'] ) ) {
//add shipping address to metadata
$shipping_address = str_replace( "\n", ', ', $data['shipping_address'] );
$shipping_address = rtrim( $shipping_address, ', ' );
$metadata['Shipping Address'] = $shipping_address;
}
//Save coupon info to metadata if applicable
if ( $coupon_valid ) {
$metadata['Coupon Code'] = strtoupper( $coupon['code'] );
}
$update_opts = array();
if ( ! empty( $metadata ) ) {
ASP_Debug_Logger::log( 'Firing asp_ng_handle_metadata filter.' );
$metadata_handled = apply_filters( 'asp_ng_handle_metadata', $metadata );
if ( true !== $metadata_handled ) {
ASP_Debug_Logger::log( 'Updating payment metadata.' );
$update_opts['metadata'] = $metadata;
}
}
ASP_Debug_Logger::log( 'Firing asp_ng_payment_completed_update_pi filter.' );
$update_opts = apply_filters( 'asp_ng_payment_completed_update_pi', $update_opts, $data );
if ( ! empty( $update_opts && ! $p_data->is_zero_value ) ) {
ASP_Debug_Logger::log( 'Updating payment intent data.' );
if ( ASP_Utils::use_internal_api() ) {
$intent = $api->post( 'payment_intents/' . $pi, $update_opts );
} else {
$intent = \Stripe\PaymentIntent::update( $pi, $update_opts );
}
}
$product_details = __( 'Product Name: ', 'stripe-payments' ) . $data['item_name'] . "\n";
$product_details .= __( 'Quantity: ', 'stripe-payments' ) . $data['item_quantity'] . "\n";
$product_details .= __( 'Item Price: ', 'stripe-payments' ) . AcceptStripePayments::formatted_price( $data['item_price'], $data['currency_code'] ) . "\n";
//check if there are any additional items available like tax and shipping cost
$product_details .= AcceptStripePayments::gen_additional_items( $data );
$product_details .= '--------------------------------' . "\n";
$product_details .= __( 'Total Amount: ', 'stripe-payments' ) . AcceptStripePayments::formatted_price( $data['paid_amount'], $data['currency_code'] ) . "\n";
$data['product_details'] = nl2br( $product_details );
//Insert the order data to the custom post
$order = new ASP_Order_Item();
if ( $order->can_create() ) {
$order_post_id = $order->find( 'pi_id', $pi );
if ( false === $order_post_id ) {
//no order was created. Let's create one
$order->create( $prod_id, $pi );
}
$order_post_id = $order->update_legacy( $data, $data['charge'] );
$intent = $p_data->get_obj();
if ( isset( $intent ) && isset( $intent->status ) && 'requires_capture' === $intent->status ) {
$order->change_status( 'authorized' );
} else {
$order->change_status( 'paid' );
}
$data['order_post_id'] = $order_post_id;
update_post_meta( $order_post_id, 'order_data', $data );
update_post_meta( $order_post_id, 'charge_data', $data['charge'] );
update_post_meta( $order_post_id, 'trans_id', $p_trans_id );
}
//stock control
if ( get_post_meta( $data['product_id'], 'asp_product_enable_stock', true ) ) {
$stock_items = intval( get_post_meta( $data['product_id'], 'asp_product_stock_items', true ) );
$stock_items = $stock_items - $data['item_quantity'];
if ( $stock_items < 0 ) {
$stock_items = 0;
}
update_post_meta( $data['product_id'], 'asp_product_stock_items', $stock_items );
$data['stock_items'] = $stock_items;
}
//Action hook with the checkout post data parameters.
ASP_Debug_Logger::log( 'Firing asp_stripe_payment_completed action.' );
do_action( 'asp_stripe_payment_completed', $data, $data['charge'] );
//Let's handle email sending stuff
$send_emails_to_buyer = apply_filters( 'asp_allow_send_emails_to_buyer', $opt['send_emails_to_buyer'], $prod_id);
if ( ! empty( $send_emails_to_buyer ) ) {
$from = $opt['from_email_address'];
$to = $data['stripeEmail'];
$subj = $opt['buyer_email_subject'];
$body = $opt['buyer_email_body'];
// * since 2.0.47
$email_data = array(
'from' => $from,
'to' => $to,
'subj' => $subj,
'body' => $body,
);
$email_data = apply_filters( 'asp_buyer_email_data', $email_data, $data );
$from = $email_data['from'];
$to = $email_data['to'];
$subj = $email_data['subj'];
$body = $email_data['body'];
// * end since
$body = asp_apply_dynamic_tags_on_email_body( $body, $data );
$subj = apply_filters( 'asp_buyer_email_subject', $subj, $data );
$body = apply_filters( 'asp_buyer_email_body', $body, $data );
$from = apply_filters( 'asp_buyer_email_from', $from, $data );
$headers = array();
if ( ! empty( $opt['buyer_email_type'] ) && 'html' === $opt['buyer_email_type'] ) {
$headers[] = 'Content-Type: text/html; charset=UTF-8';
$body = nl2br( $body );
}
$headers[] = 'From: ' . $from;
//Trigger filter to allow modification of the buyer email headers.
$headers = apply_filters( 'asp_buyer_email_headers', $headers, $email_data, $data );
$schedule_result = ASP_Utils::mail( $to, $subj, $body, $headers );
if ( ! $schedule_result ) {
ASP_Debug_Logger::log( 'Notification email sent to buyer: ' . $to . ', from email address used: ' . $from );
} else {
ASP_Debug_Logger::log( 'Notification email to buyer scheduled: ' . $to . ', from email address used: ' . $from );
}
}
$send_emails_to_seller = apply_filters( 'asp_allow_send_emails_to_seller', $opt['send_emails_to_seller'], $prod_id);
if ( ! empty( $send_emails_to_seller ) ) {
$from = $opt['from_email_address'];
$to = $opt['seller_notification_email'];
$subj = $opt['seller_email_subject'];
$body = $opt['seller_email_body'];
// * since 2.0.47
$email_data = array(
'from' => $from,
'to' => $to,
'subj' => $subj,
'body' => $body,
);
$email_data = apply_filters( 'asp_seller_email_data', $email_data, $data );
$from = $email_data['from'];
$to = $email_data['to'];
$subj = $email_data['subj'];
$body = $email_data['body'];
// * end since
$body = asp_apply_dynamic_tags_on_email_body( $body, $data, true );
$subj = apply_filters( 'asp_seller_email_subject', $subj, $data );
$body = apply_filters( 'asp_seller_email_body', $body, $data );
$from = apply_filters( 'asp_seller_email_from', $from, $data );
$headers = array();
if ( ! empty( $opt['seller_email_type'] ) && 'html' === $opt['seller_email_type'] ) {
$headers[] = 'Content-Type: text/html; charset=UTF-8';
$body = nl2br( $body );
}
$headers[] = 'From: ' . $from;
$headers[] = 'Reply-To: ' . $data['stripeEmail'];//For admin notification emails, we set the reply-to header to the buyer's email address.
//Trigger filter to allow modification of the seller email headers.
$headers = apply_filters( 'asp_seller_email_headers', $headers, $email_data, $data );
//Send the email to the seller
$schedule_result = ASP_Utils::mail( $to, $subj, $body, $headers );
if ( ! $schedule_result ) {
ASP_Debug_Logger::log( 'Notification email sent to seller: ' . $to . ', from email address used: ' . $from );
} else {
ASP_Debug_Logger::log( 'Notification email to seller scheduled: ' . $to . ', from email address used: ' . $from );
}
}
$this->sess->set_transient_data( 'asp_data', $data );
$this->sess->set_transient_data( 'asp_pp_form_data', array() );
//Clear the txn lock
update_option( 'asp_ng_ipn_txn_being_processed', '' );
$this->ipn_completed();
}
public function payment_data_override( $p_data, $pi ) {
//check if this is zero-value transaction
if ( 'free' === substr( $pi, 0, 4 ) ) {
//this is zero-value transaction
$coupon_code = $this->get_post_var( 'asp_coupon-code' );
$coupon_code = sanitize_text_field( stripslashes( $coupon_code ));
if ( empty( $coupon_code ) ) {
return $p_data;
}
$coupon_valid = $this->item->check_coupon( $coupon_code );
if ( ! $coupon_valid ) {
return $p_data;
}
$coupon_discount_amount = $this->item->get_coupon_discount_amount();
$price_no_discount = $this->item->get_price();
if ( $coupon_discount_amount < $price_no_discount ) {
return $p_data;
}
$prod_id = $this->item->get_product_id();
$order = new ASP_Order_Item();
if ( $order->can_create( $prod_id ) ) {
$order->create( $prod_id, $pi );
}
$p_data = new ASP_Payment_Data( $pi, true );
}
return $p_data;
}
}
new ASP_Process_IPN_NG();

View File

@ -0,0 +1,816 @@
<?php
class ASP_Product_Item {
public $currency;
public $name;
public $quantity;
public $description;
public $tax_amount;
protected $post_id = false;
protected $post;
protected $last_error = '';
protected $cust_quantity = false;
protected $tax;
protected $shipping;
protected $zero_cent = false;
protected $price;
protected $asp_main;
protected $coupon = false;
protected $price_with_discount;
protected $button_key = false;
protected $items = array();
protected $sess;
protected $overriden_data = false;
public function __construct( $post_id = false ) {
$this->asp_main = AcceptStripePayments::get_instance();
if ( false !== $post_id ) {
//let's try to load item from product
$this->post_id = $post_id;
$this->load_from_product();
$btn_uniq_id = isset( $_GET['btn_uniq_id'] ) ? sanitize_text_field( stripslashes ( $_GET['btn_uniq_id'] ) ) : '';
if ( ! empty( $btn_uniq_id ) ) {
ASP_Debug_Logger::log( 'Using the btn_uniq_id parameter. Value of btn_uniq_id: ' . $btn_uniq_id, true );
$this->sess = ASP_Session::get_instance();
$this->overriden_data = $this->sess->get_transient_data( 'overriden_data_' . $btn_uniq_id );
}
}
}
private function in_cents( $amount ) {
if ( ! $this->zero_cent ) {
$amount = round( $amount * 100, 2 );
} else {
$amount = round( $amount, 0 );
}
return $amount;
}
private function from_cents( $amount ) {
if ( ! $this->zero_cent ) {
$amount = round( $amount / 100, 2 );
} else {
$amount = round( $amount, 0 );
}
return $amount;
}
public function get_last_error() {
return $this->last_error;
}
public function get_product_id() {
return $this->post_id;
}
public function get_button_text() {
$button_text = get_post_meta( $this->post_id, 'asp_product_button_text', true );
if ( empty( $button_text ) ) {
$button_text = $this->asp_main->get_setting( 'button_text' );
}
return $button_text;
}
public function get_button_class() {
$button_class = get_post_meta( $this->post_id, 'asp_product_button_class', true );
return $button_class;
}
public function get_stock_items() {
$stock_items = get_post_meta( $this->post_id, 'asp_product_stock_items', true );
return $stock_items;
}
public function stock_control_enabled() {
$stock_control_enabled = get_post_meta( $this->post_id, 'asp_product_enable_stock', true );
return $stock_control_enabled;
}
public function get_tax() {
if ( false !== $this->overriden_data && isset( $this->overriden_data['tax'] ) ) {
return $this->overriden_data['tax'];
}
if ( ! empty( $this->tax ) ) {
return $this->tax;
}
$this->tax = get_post_meta( $this->post_id, 'asp_product_tax', true );
if ( empty( $this->tax ) ) {
$this->tax = 0;
}
return $this->tax;
}
public function set_tax( $tax ) {
$this->tax = $tax;
}
public function get_shipping( $in_cents = false ) {
if ( ! isset( $this->shipping ) ) {
$this->shipping = get_post_meta( $this->post_id, 'asp_product_shipping', true );
}
if ( empty( $this->shipping ) ) {
$this->shipping = 0;
}
if ( $in_cents ) {
return $this->in_cents( $this->shipping );
}
return $this->shipping;
}
public function set_shipping( $shipping, $in_cents = false ) {
$this->shipping = $in_cents ? $this->from_cents( $shipping ) : $shipping;
}
public function get_items_total( $in_cents = false, $with_discount = false ) {
$items_total = 0;
if ( ! empty( $this->items ) ) {
foreach ( $this->items as $item ) {
$items_total += $item['price'];
}
} else {
return 0;
}
if ( $with_discount && $this->coupon && 'perc' === $this->coupon['discount_type'] ) {
$items_total = $this->apply_discount_to_amount( $items_total, false );
}
return $in_cents ? $this->in_cents( $items_total ) : $items_total;
}
public function get_items() {
return $this->items;
}
public function add_item( $name, $price ) {
$this->items[] = array(
'name' => $name,
'price' => floatval( $price ),
);
}
public function get_thumb() {
$this->thumb = get_post_meta( $this->post_id, 'asp_product_thumbnail', true );
return $this->thumb;
}
public function get_name() {
$this->name = $this->post->post_title;
return $this->name;
}
public function get_description() {
$this->description = get_post_meta( $this->post_id, 'asp_product_description', true );
return $this->description;
}
public function get_quantity() {
$this->quantity = get_post_meta( $this->post_id, 'asp_product_quantity', true );
if ( ! is_numeric( $this->quantity ) ) {
$this->quantity = absint( $this->quantity );
}
if ( empty( $this->quantity ) ) {
$this->quantity = 1;
}
if ( $this->cust_quantity ) {
$this->quantity = $this->cust_quantity;
}
return $this->quantity;
}
public function get_coupon_discount_amount() {
$price = $this->get_price();
$items_total = $this->get_items_total();
$discount_amount = $this->get_discount_amount( $price + $items_total );
return $discount_amount;
}
public function get_price( $in_cents = false, $price_with_discount = false ) {
if ( is_null( $this->price ) ) {
$this->price = get_post_meta( $this->post_id, 'asp_product_price', true );
$this->price = empty( $this->price ) ? 0 : round( $this->price * 100 ) / 100;
}
if ( $price_with_discount && $this->coupon ) {
$discount_amount = $this->get_discount_amount( $this->price, $in_cents );
$this->price_with_discount = $this->price - $discount_amount;
}
if ( $in_cents ) {
if ( $price_with_discount && $this->coupon ) {
return $this->in_cents( $this->price_with_discount );
}
return $this->in_cents( $this->price );
}
if ( $price_with_discount && $this->coupon ) {
return $this->price_with_discount;
}
return $this->price;
}
public function get_surcharge()
{
$surcharge_amount = get_post_meta( $this->post_id, 'asp_surcharge_amount', true );
return !empty($surcharge_amount) && is_numeric($surcharge_amount) ? $surcharge_amount : 0;
}
public function get_surcharge_label()
{
$surcharge_label = get_post_meta( $this->post_id, 'asp_surcharge_label', true );
return !empty($surcharge_label) ? $surcharge_label : __("Surcharge", 'stripe-payments');
}
public function get_surcharge_type()
{
$surcharge_type = get_post_meta( $this->post_id, 'asp_surcharge_type', true );
return empty($surcharge_type) ? 'flat' : $surcharge_type;
}
/**
* Calculate the total surcharge amount based on the surcharge type and amount.
*
* @param bool $in_cents Whether to return the result in cents.
*
* @return float|int
*/
public function calculate_total_surcharge(bool $in_cents = false)
{
$surcharge_amount = $this->get_surcharge();
$surcharge_type = $this->get_surcharge_type();
if ( $surcharge_type == 'perc' ){
$calculate_from_amount = $this->get_total();
$surcharge_percentage = floatval($surcharge_amount);
$amount = ( $calculate_from_amount / 100 ) * $surcharge_percentage;
} else {
$amount = floatval($surcharge_amount);
}
return $in_cents ? $this->in_cents( $amount ) : $amount;
}
/**
* Returns min amount for donation product
*
* @param bool $in_cents Return amount in cents if set to `true`
*
* @return integer|float
*/
public function get_min_amount( $in_cents = false ) {
$min_amount = get_post_meta( $this->post_id, 'asp_product_min_amount', true );
$min_amount = empty( $min_amount ) ? 0 : $min_amount;
return $in_cents ? $this->in_cents( $min_amount ) : $min_amount;
}
/**
* Returns product type
*
* @return string
*/
public function get_type() {
$type = get_post_meta( $this->post_id, 'asp_product_type', true );
return $type;
}
public function apply_discount_to_amount( $amount, $in_cents = false ) {
if ( $this->coupon ) {
if ( 'perc' === $this->coupon['discount_type'] ) {
$perc = AcceptStripePayments::is_zero_cents( $this->get_currency() ) ? 0 : 2;
$discount_amount = round( $amount * ( $this->coupon['discount'] / 100 ), $perc );
} else {
$discount_amount = $this->coupon['discount'];
if ( $in_cents && ! AcceptStripePayments::is_zero_cents( $this->get_currency() ) ) {
$discount_amount = $discount_amount * 100;
}
}
if ( $in_cents ) {
$discount_amount = round( $discount_amount, 0 );
}
$amount = $amount - $discount_amount;
}
return $amount;
}
public function get_discount_amount( $total, $in_cents = false ) {
$discount_amount = 0;
if ( $this->coupon ) {
if ( 'perc' === $this->coupon['discount_type'] ) {
$perc = AcceptStripePayments::is_zero_cents( $this->get_currency() ) ? 0 : 2;
$discount_amount = round( $total * ( $this->coupon['discount'] / 100 ), $perc );
} else {
$discount_amount = $this->coupon['discount'];
if ( ! $this->coupon['per_order'] ) {
$discount_amount = $discount_amount * $this->get_quantity();
}
if ( $in_cents && ! AcceptStripePayments::is_zero_cents( $this->get_currency() ) ) {
$discount_amount = $discount_amount * 100;
}
}
if ( $in_cents ) {
$discount_amount = round( $discount_amount, 0 );
}
$this->coupon['discountAmount'] = $discount_amount;
}
return $discount_amount;
}
/*
* Returns the total amount for the product (including tax, shipping, item quantity, and discount if any)
*
* @param bool $in_cents Return amount in cents if set to `true`
*/
public function get_total( $in_cents = false ) {
$total = $this->get_price( $in_cents );
$items_total = $this->get_items_total( $in_cents );
$total += $items_total;
$total = $total * $this->get_quantity();
$total = $total - $this->get_discount_amount( $total, $in_cents );
if ( $this->get_tax() ) {
$total = $total + $this->get_tax_amount( $in_cents, true );
}
$shipping = $this->get_shipping( $in_cents );
if ( ! empty( $shipping ) ) {
$total = $total + $this->get_shipping( $in_cents );
}
if ( $total < 0 ) {
$total = 0;
}
return $total;
}
public function set_price( $price, $in_cents = false ) {
//workaround for zero-cents currencies for Sub addon 2.0.10 or less
$this->zero_cent = AcceptStripePayments::is_zero_cents( $this->get_currency() );
if ( $this->zero_cent && class_exists( 'ASPSUB_main' ) && isset( $this->plan ) && version_compare( ASPSUB_main::ADDON_VER, '2.0.10' ) <= 0 ) {
$price = $price * 100;
}
//end workaround
if ( $in_cents ) {
$price = $this->from_cents( $price );
}
$this->price = $price;
}
public function set_quantity( $quantity ) {
$this->cust_quantity = $quantity;
}
public function get_tax_amount( $in_cents = false, $price_with_discount = false ) {
$total = $this->get_price( false );
$items_total = $this->get_items_total( false );
$total += $items_total;
$total = $total * $this->get_quantity();
$total = $total - $this->get_discount_amount( $total, false );
$this->tax_amount = AcceptStripePayments::get_tax_amount( $total, $this->get_tax(), $this->zero_cent );
if ( $in_cents ) {
return $this->in_cents( $this->tax_amount );
}
return $this->tax_amount;
}
public function get_currency() {
if ( empty( $this->currency ) ) {
$this->currency = get_post_meta( $this->post_id, 'asp_product_currency', true );
$this->currency = empty( $this->currency ) ? $this->asp_main->get_setting( 'currency_code' ) : $this->currency;
}
$this->zero_cent = AcceptStripePayments::is_zero_cents( $this->currency );
return $this->currency;
}
public function set_currency( $curr ) {
$this->currency = $curr;
$this->zero_cent = AcceptStripePayments::is_zero_cents( $curr );
}
public function is_variable() {
return $this->get_price() === 0;
}
public function is_currency_variable() {
if ( $this->get_type() !== 'donation' ) {
return false;
}
$currency_variable = get_post_meta( $this->post_id, 'asp_product_currency_variable', true );
return $currency_variable;
}
public function get_redir_url() {
$url = get_post_meta( $this->post_id, 'asp_product_thankyou_page', true );
if ( empty( $url ) ) {
$url = $this->asp_main->get_setting( 'checkout_url' );
}
return $url;
}
public function collect_billing_addr() {
return get_post_meta( $this->post_id, 'asp_product_collect_billing_addr', true );
}
public function gen_item_data() {
$ret = array();
$item_info = array(
'name' => $this->get_name(),
'amount' => $this->get_price( true ),
'currency' => $this->get_currency(),
'quantity' => $this->get_quantity(),
);
$thumb = $this->get_thumb();
if ( ! empty( $thumb ) ) {
$item_info['images'] = array( $this->get_thumb() );
}
$descr = $this->get_description();
if ( ! empty( $descr ) ) {
$item_info['description'] = $this->get_description();
}
$ret[] = $item_info;
$tax = $this->get_tax();
if ( ! empty( $tax ) ) {
$tax_str = apply_filters( 'asp_customize_text_msg', __( 'Tax', 'stripe-payments' ), 'tax_str' );
$tax_info = array(
'name' => sprintf( '%s (%s%%)', $tax_str, $this->get_tax() ),
'amount' => $this->get_tax_amount( true ),
'currency' => $this->get_currency(),
'quantity' => $this->get_quantity(),
);
$ret[] = $tax_info;
}
$ship = $this->get_shipping();
if ( ! empty( $ship ) ) {
$ship_str = apply_filters( 'asp_customize_text_msg', __( 'Shipping', 'stripe-payments' ), 'shipping_str' );
$tax_info = array(
'name' => sprintf( '%s', $ship_str ),
'amount' => $this->get_shipping( true ),
'currency' => $this->get_currency(),
'quantity' => $this->get_quantity(),
);
$ret[] = $tax_info;
}
return $ret;
}
public function get_coupon() {
return $this->coupon;
}
private function load_coupon( $coupon_code ) {
//let's find coupon
$coupon = get_posts(
array(
'meta_key' => 'asp_coupon_code',
'meta_value' => $coupon_code,
'posts_per_page' => 1,
'offset' => 0,
'post_type' => 'asp_coupons',
)
);
wp_reset_postdata();
if ( empty( $coupon ) ) {
//coupon not found
$this->last_error = __( 'Coupon not found.', 'stripe-payments' );
return false;
}
$coupon = $coupon[0];
//check if coupon is active
if ( ! get_post_meta( $coupon->ID, 'asp_coupon_active', true ) ) {
$this->last_error = __( 'Coupon is not active.', 'stripe-payments' );
return false;
}
//check if coupon start date has come
$start_date = get_post_meta( $coupon->ID, 'asp_coupon_start_date', true );
if ( empty( $start_date ) || strtotime( $start_date ) > time() ) {
$this->last_error = __( 'Coupon is not available yet.', 'stripe-payments' );
return false;
}
//check if coupon has expired
$exp_date = get_post_meta( $coupon->ID, 'asp_coupon_exp_date', true );
if ( ! empty( $exp_date ) && strtotime( $exp_date ) < time() ) {
$this->last_error = __( 'Coupon has expired.', 'stripe-payments' );
return false;
}
//check if redemption limit is reached
$red_limit = get_post_meta( $coupon->ID, 'asp_coupon_red_limit', true );
$red_count = get_post_meta( $coupon->ID, 'asp_coupon_red_count', true );
if ( ! empty( $red_limit ) && intval( $red_count ) >= intval( $red_limit ) ) {
$this->last_error = __( 'Coupon redemption limit is reached.', 'stripe-payments' );
return false;
}
$per_order = get_post_meta( $coupon->ID, 'asp_coupon_per_order', true );
$this->coupon = array(
'code' => $coupon_code,
'id' => $coupon->ID,
'discount' => get_post_meta( $coupon->ID, 'asp_coupon_discount', true ),
'discount_type' => get_post_meta( $coupon->ID, 'asp_coupon_discount_type', true ),
'per_order' => empty( $per_order ) ? 0 : 1,
);
return true;
}
public function check_coupon( $coupon_code = false ) {
if ( ! $coupon_code ) {
$this->last_error = 'No coupon code provided';
return false;
}
$coupon_code = trim( $coupon_code );
$this->load_coupon( $coupon_code );
if ( ! $this->coupon ) {
return false;
}
//check if coupon is allowed for the product
$only_for_allowed_products = get_post_meta( $this->coupon['id'], 'asp_coupon_only_for_allowed_products', true );
if ( $only_for_allowed_products ) {
$allowed_products = get_post_meta( $this->coupon['id'], 'asp_coupon_allowed_products', true );
if ( is_array( $allowed_products ) && ! in_array( strval( $this->post_id ), $allowed_products, true ) ) {
$this->last_error = __( 'Coupon is not allowed for this product.', 'stripe-payments' );
$this->coupon = false;
return false;
}
}
return true;
}
public function get_download_url() {
$post_url = isset( $_POST['asp_item_url'] ) ? sanitize_text_field( stripslashes ( $_POST['asp_item_url'] ) ) : '';
if ( $post_url ) {
$item_url = $post_url;
} else {
$item_url = get_post_meta( $this->post_id, 'asp_product_upload', true );
$item_url = $item_url ? $item_url : '';
if ( ! $item_url ) {
return '';
}
$item_url = base64_encode( $item_url );
}
$item_url = apply_filters(
'asp_item_url_process',
$item_url,
array(
'button_key' => $this->get_button_key(),
'product_id' => $this->post_id,
)
);
$item_url = base64_decode( $item_url );
return $item_url;
}
public function get_button_key() {
if ( ! $this->button_key ) {
// ASP_Debug_Logger::log("Get Button Key - Name:". $this->get_name() . ", Price:", $this->get_price(true));
$this->button_key = md5( htmlspecialchars_decode( $this->get_name() ) . $this->get_price( true ) );
}
return $this->button_key;
}
public function is_physical_product() {
if(!empty($this->get_meta('asp_is_physical_product'))) {
return true;
} else if (!empty($this->get_meta('asp_product_shipping'))) {
return true;
} else if (!empty($this->get_meta('asp_product_shipping_variations'))) {
return true;
}
return false;
}
public function load_from_product( $post_id = false ) {
if ( false === $post_id ) {
$post_id = $this->post_id;
}
if ( false === $post_id ) {
$this->last_error = __( 'No product ID provided.', 'stripe-payments' );
return false;
}
$post_id = intval( $post_id );
$this->post = get_post( $post_id );
if ( ! $this->post || ( get_post_type( $post_id ) !== ASPMain::$products_slug && get_post_type( $post_id ) !== ASPMain::$temp_prod_slug ) ) {
// translators: %d is product id
$this->last_error = sprintf( __( "Can't find product with ID %d", 'stripe-payments' ), $post_id );
ASP_Debug_Logger::log( "Can't find product with ID: " . $post_id, false );
return false;
}
$this->zero_cent = AcceptStripePayments::is_zero_cents( $this->get_currency() );
return true;
}
public function get_meta( $meta, $single = true ) {
return get_post_meta( $this->post_id, $meta, $single );
}
/**
* Calculate regional shipping amount by the provided region.
*
* @param $shipping_region array
* @param $in_cents bool
*
* @return float|int
*/
public function calculate_regional_shipping_amount($shipping_region, $in_cents = false) {
$regional_shipping_amount = 0;
$configured_variations = $this->get_meta('asp_product_shipping_variations');
// Evaluate variable shipping if enabled.
if (is_array($configured_variations) && count($configured_variations)) {
// Iterate through the available shipping variation option to find if there is amy matching.
foreach ($configured_variations as $variation) {
$variation['amount'] = (float) $variation['amount'];
$location = strtolower($variation['loc']);
switch ($variation['type']) {
case '0':
if (!empty($shipping_region['country']) && $location == strtolower($shipping_region['country']) )
// Matched by country, get shipping amount for this location.
$regional_shipping_amount += $variation['amount'];
break;
case '1':
if (!empty($shipping_region['state']) && $location == strtolower($shipping_region['state']) )
// Matched by state, get shipping amount for this location.
$regional_shipping_amount += $variation['amount'];
break;
case '2':
if (!empty($shipping_region['city']) && $location == strtolower($shipping_region['city']) )
// Matched by city, get shipping amount for this location.
$regional_shipping_amount += $variation['amount'];
break;
default:
break;
}
}
}
return $in_cents ? $this->in_cents($regional_shipping_amount) : $regional_shipping_amount;
}
/**
* Validates the total checkout amount for a product against amounts from ajax.
*
* @param int $amount The price to validate.
* @param int $quantity Product quantity.
* @param array $custom_inputs Custom input from customer such as applied coupon code, billing/shipping details, price variation etc.
*
* @return bool TRUE if validation is successful, FALSE otherwise.
*/
public function validate_total_amount( $amount, $quantity, $custom_inputs) {
//ASP_Debug_Logger::log("Amount submitted by customer (in cents): ". $amount, true);
$product_price = (float) $this->get_meta('asp_product_price');
$quantity = (int) $quantity;
$product_price_in_cents = $this->in_cents($product_price);
//ASP_Debug_Logger::log("Raw product price: ". $product_price_in_cents , true);
$this->set_price($product_price_in_cents, true);
$this->set_quantity( $quantity );
$price_variation = $custom_inputs['price_variation'];
if ( isset($price_variation) && !empty( $price_variation ) ) {
$variations_groups = $this->get_meta('asp_variations_groups');
$variations_names = $this->get_meta('asp_variations_names');
$variations_prices = $this->get_meta('asp_variations_prices');
$construct_final_price = ! empty( $this->get_meta('asp_product_hide_amount_input') );
$pvars = explode(',', $price_variation ); // Hold data like this: ['<group_name>-<applied_option>', ....]
$variation_price = 0;
foreach ($pvars as $pvar_str) {
$separator = '_';
// Use the last index of the separator to explode the $pvar_str. This is to avoid collision if $pvar_str contains (from the group name) more than one $separator.
$last_separator_index = strrpos($pvar_str, $separator);
$option_group = substr($pvar_str, 0, $last_separator_index); // Group name;
$applied_option = (int) substr($pvar_str, $last_separator_index + strlen($separator));// Applied option
$group_index = array_search($option_group, $variations_groups);
$applied_price = (float) $variations_prices[$group_index][$applied_option];
$applied_price = $this->in_cents( $applied_price );
$variation_price += $applied_price;
// ASP_Debug_Logger::log("Applied variation price for ". $variations_names[$group_index][$applied_option]. ' : ' .$applied_price, true);
}
// ASP_Debug_Logger::log("Applied total variation price : ". $variation_price, true);
$price_with_applied_variation = 0;
if ($construct_final_price) {
$price_with_applied_variation = $variation_price;
}else{
$price_with_applied_variation = $variation_price + $product_price_in_cents;
}
$this->set_price($price_with_applied_variation, true);
// ASP_Debug_Logger::log("Applied total variation price with base price : ". $price_with_applied_variation, true);
}
// ASP_Debug_Logger::log("Amount current total (after price variation): ". $this->get_total(true), true);
$tax_variations_type = $this->get_meta('asp_product_tax_variations_type');
$tax_variations_arr = $this->get_meta('asp_product_tax_variations');
$collect_billing_addr_enabled = $this->get_meta('asp_product_collect_billing_addr');
$collect_shipping_addr_enabled = $this->get_meta('asp_product_collect_shipping_addr');
// ASP_Debug_Logger::log("Applied tax amount (before tax variation apply): ". $this->get_tax_amount(true), true);
// Evaluate variable tax if enabled.
if (is_array($tax_variations_arr) && count($tax_variations_arr) && $collect_billing_addr_enabled === '1') {
$applied_tax_percentage = 0;
$tax_region = ($tax_variations_type === 's' && $collect_shipping_addr_enabled === '1') ? $custom_inputs['shipping_details']['address'] : $custom_inputs['billing_details']['address'];
// Iterate through the available tax variation option to find if there is amy matching.
foreach ($tax_variations_arr as $tax_variation) {
$tax_variation['amount'] = (float) $tax_variation['amount'];
switch ($tax_variation['loc']) {
case $tax_region['city']:
// Matched by city, get tax amount for this location.
$applied_tax_percentage += $tax_variation['amount'];
break;
case $tax_region['state']:
// Matched by state, get tax amount for this location.
$applied_tax_percentage += $tax_variation['amount'];
break;
case $tax_region['country']:
// Matched by country, get tax amount for this location.
$applied_tax_percentage += $tax_variation['amount'];
break;
}
}
if ($applied_tax_percentage > 0) {
$this->set_tax($applied_tax_percentage);
}
}
//ASP_Debug_Logger::log("Applied tax amount (after tax variation): ". $this->get_tax_amount(true), true);
//ASP_Debug_Logger::log("Amount current total (after tax variation): ". $this->get_total(true), true);
$base_shipping_amount = get_post_meta( $this->post_id, 'asp_product_shipping', true );
if (empty($base_shipping_amount)){
$base_shipping_amount = 0;
} else {
$base_shipping_amount = $this->in_cents(floatval($base_shipping_amount));
}
$shipping_amount = $base_shipping_amount;
$collect_shipping_addr_enabled = $this->get_meta('asp_product_collect_shipping_addr');
if ( $collect_shipping_addr_enabled == '1'){
$regional_shipping_amount = $this->calculate_regional_shipping_amount($custom_inputs['shipping_details']['address'], true);
$shipping_amount += $regional_shipping_amount;
}
$this->set_shipping( $shipping_amount, true );
//ASP_Debug_Logger::log("Amount current total (after base shipping): ". $this->get_total(true), true);
$coupon_code = $custom_inputs['coupon_code'];
if ( !empty( $coupon_code ) ) {
// Get the coupon and evaluate it (if submitted).
if ( !$this->load_coupon( $coupon_code ) ) {
// Invalid coupon. The 'load_coupon' method will handle appending appropriate error message.
return false;
};
}
// Calculate the expected total amount.
$expected_total_amount = $this->get_total(true);
// Check if surcharge feature is enabled.
if ( !empty($this->get_surcharge()) ){
// Surcharge is enabled. Calculate the surcharge amount then adjust the expected total.
$surcharge_amount = round($this->calculate_total_surcharge(true));//This is in cents so round it to 0 decimal place.
ASP_Debug_Logger::log("The surcharge feature is enabled. Applied surcharge amount (in cents): ". $surcharge_amount, true);
$expected_total_amount += $surcharge_amount;
}
// Trigger a filter so addons can override it.
$expected_total_amount = apply_filters('asp_pre_api_submission_expected_amount', $expected_total_amount, $amount, $this->post_id);
// Check if the expected total amount matches the given amount.
if ( $amount != $expected_total_amount ){
ASP_Debug_Logger::log("Pre-API Submission validation amount mismatch. Expected amount (in cents): ". $expected_total_amount . ", Submitted amount (in cents): " . $amount, false);
// Set the last error message that will be displayed to the user.
$mismatch_err_msg = __( "Price validation failed. The submitted amount does not match the product's configured price. ", 'stripe-payments' );
$mismatch_err_msg .= "Expected: " . $this->from_cents($expected_total_amount) . ", Submitted: " . $this->from_cents($amount);
$this->last_error = $mismatch_err_msg;
return false;
}
ASP_Debug_Logger::log("Pre-API Submission validation successful. Expected: " . $this->from_cents($expected_total_amount) . ", Submitted: " . $this->from_cents($amount), true);
return true;
}
}

View File

@ -0,0 +1,412 @@
<?php
class ASP_Self_Hooks_Handler {
private $main;
public function __construct() {
$this->main = AcceptStripePayments::get_instance();
add_action( 'asp_ng_product_mode_keys', array( $this, 'ng_product_mode_keys_handler' ) );
add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ), 0 );
add_filter( 'asp_ng_before_pi_create_update', array( $this, 'pi_update' ) );
add_filter( 'asp_ng_available_currencies', array( $this, 'filter_available_currencies' ) );
add_action( 'asp_ng_before_token_request', array( $this, 'check_token' ), 100 );
add_action( 'asp_ng_before_token_request', array( $this, 'check_rate_limit' ), 101 );
add_action( 'asp_ng_before_token_request', array( $this, 'tax_variations' ) );
add_filter( 'asp_ng_pp_data_ready', array( $this, 'tax_variations_addon' ), 100, 2 );
add_action( 'asp_stripe_payment_completed', array( $this, 'daily_txn_limit' ), 102, 2 );
}
public function plugins_loaded() {
//WP eMember integration
if ( function_exists( 'wp_emember_install' ) ) {
add_action( 'asp_stripe_payment_completed', array( $this, 'handle_eMember_signup' ), 10, 2 );
}
//WP PDF Stamper integration
if ( function_exists( 'pdf_stamper_stamp_internal_file' ) ) {
add_action( 'asp_ng_payment_completed', array( $this, 'handle_wp_pdf_stamper' ), 1000, 2 );
}
}
public function pi_update( $pi_params ) {
$product_id = filter_input( INPUT_POST, 'product_id', FILTER_SANITIZE_NUMBER_INT );
$plan_id = get_post_meta( $product_id, 'asp_sub_plan_id', true );
if ( ! empty( $plan_id ) ) {
//ignoring option for Subscription product
return $pi_params;
}
$auth_only = get_post_meta( $product_id, 'asp_product_authorize_only', true );
if ( $auth_only ) {
$pi_params['capture_method'] = 'manual';
$extended_authorization = get_post_meta( $product_id, 'asp_product_extended_authorization', true );
if ( ! empty( $extended_authorization ) ) {
if ( isset( $pi_params['payment_method_options']['card'] ) && is_array( $pi_params['payment_method_options']['card'] ) ) {
$pi_params['payment_method_options']['card']['request_extended_authorization'] = 'if_available';
} else if ( isset( $pi_params['payment_method_options'] ) && is_array( $pi_params['payment_method_options'] ) ) {
$pi_params['payment_method_options']['card'] = array(
'request_extended_authorization' => 'if_available',
);
} else {
$pi_params['payment_method_options'] = array(
'card' => array(
'request_extended_authorization' => 'if_available',
),
);
}
}
}
return $pi_params;
}
public function filter_available_currencies( $curr_arr ) {
$allowed_curr = $this->main->get_setting( 'allowed_currencies' );
$allowed_curr = empty( $allowed_curr ) ? array() : json_decode( html_entity_decode( $allowed_curr ), true );
if ( empty( $allowed_curr ) || empty( array_diff_key( $curr_arr, $allowed_curr ) ) ) {
return $curr_arr;
}
foreach ( $curr_arr as $key => $value ) {
if ( ! isset( $allowed_curr[ $key ] ) ) {
unset( $curr_arr[ $key ] );
}
}
return $curr_arr;
}
public function ng_product_mode_keys_handler( $product_id ) {
if ( empty( $product_id ) ) {
return;
}
$product = get_post( $product_id );
if ( ! $product ) {
return;
}
$prod = new ASP_Product_Item( $product_id );
$type = $prod->get_type();
if ( 'subscription' !== $type ) {
$use_other_acc = get_post_meta( $product_id, 'asp_use_other_stripe_acc', true );
if ( ! empty( $use_other_acc ) ) {
$this->main->APIPubKeyTest = get_post_meta( $product_id, 'asp_stripe_test_pub_key', true );
$this->main->APIPubKeyLive = get_post_meta( $product_id, 'asp_stripe_live_pub_key', true );
$this->main->APISecKeyTest = get_post_meta( $product_id, 'asp_stripe_test_sec_key', true );
$this->main->APISecKeyLive = get_post_meta( $product_id, 'asp_stripe_live_sec_key', true );
$this->main->APIPubKey = $this->main->APIPubKeyLive;
$this->main->APISecKey = $this->main->APISecKeyLive;
}
}
$plan_id = get_post_meta( $product_id, 'asp_sub_plan_id', true );
if ( ! empty( $plan_id ) ) {
//check if Subs addon enabled
if ( class_exists( 'ASPSUB_main' ) ) {
$asp_sub = ASPSUB_main::get_instance();
$plan = $asp_sub->get_plan_data( $plan_id );
if ( ! ( $plan ) || $plan->livemode ) {
return;
}
}
} else {
//check if force test mode option set for the product
$force_test = get_post_meta( $product_id, 'asp_product_force_test_mode', true );
if ( empty( $force_test ) ) {
return;
}
}
$this->main->is_live = false;
$this->main->APIPubKey = $this->main->APIPubKeyTest;
$this->main->APISecKey = $this->main->APISecKeyTest;
}
public function handle_emember_signup( $data, $charge ) {
if ( empty( $data['product_id'] ) ) {
return;
}
//let's check if Membership Level is set for this product
$level_id = get_post_meta( $data['product_id'], 'asp_product_emember_level', true );
if ( empty( $level_id ) ) {
return;
}
//let's form data required for eMember_handle_subsc_signup_stand_alone function and call it
$first_name = '';
$last_name = '';
if ( ! empty( $data['customer_name'] ) ) {
// let's try to create first name and last name from full name
$parts = explode( ' ', $data['customer_name'] );
$last_name = array_pop( $parts );
$first_name = implode( ' ', $parts );
}
$addr_street = isset( $_POST['stripeBillingAddressLine1'] ) ? sanitize_text_field( $_POST['stripeBillingAddressLine1'] ) : '';
$addr_zip = isset( $_POST['stripeBillingAddressZip'] ) ? sanitize_text_field( $_POST['stripeBillingAddressZip'] ) : '';
$addr_city = isset( $_POST['stripeBillingAddressCity'] ) ? sanitize_text_field( $_POST['stripeBillingAddressCity'] ) : '';
$addr_state = isset( $_POST['stripeBillingAddressState'] ) ? sanitize_text_field( $_POST['stripeBillingAddressState'] ) : '';
$addr_country = isset( $_POST['stripeBillingAddressCountry'] ) ? sanitize_text_field( $_POST['stripeBillingAddressCountry'] ) : '';
if ( empty( $addr_street ) && ! empty( $charge->source->address_line1 ) ) {
$addr_street = $charge->source->address_line1;
}
if ( empty( $addr_zip ) && ! empty( $charge->source->address_zip ) ) {
$addr_zip = $charge->source->address_zip;
}
if ( empty( $addr_city ) && ! empty( $charge->source->address_city ) ) {
$addr_city = $charge->source->address_city;
}
if ( empty( $addr_state ) && ! empty( $charge->source->address_state ) ) {
$addr_state = $charge->source->address_state;
}
if ( empty( $addr_country ) && ! empty( $charge->source->address_country ) ) {
$addr_country = $charge->source->address_country;
}
//get address from new API payment data
$ipn = ASP_Process_IPN_NG::get_instance();
if ( isset( $ipn->p_data ) ) {
$addr = $ipn->p_data->get_billing_details();
if ( $addr ) {
if ( empty( $addr_street ) && ! empty( $addr->line1 ) ) {
$addr_street = $addr->line1;
}
if ( empty( $addr_zip ) && ! empty( $addr->postal_code ) ) {
$addr_zip = $addr->postal_code;
}
if ( empty( $addr_city ) && ! empty( $addr->city ) ) {
$addr_city = $addr->city;
}
if ( empty( $addr_state ) && ! empty( $addr->state ) ) {
$addr_state = $addr->state;
}
if ( empty( $addr_country ) && ! empty( $addr->country ) ) {
$addr_country = $addr->country;
}
}
}
if ( ! empty( $addr_country ) ) {
//convert country code to country name
$countries = ASP_Utils::get_countries_untranslated();
if ( isset( $countries[ $addr_country ] ) ) {
$addr_country = $countries[ $addr_country ];
}
}
$ipn_data = array(
'payer_email' => $data['stripeEmail'],
'first_name' => $first_name,
'last_name' => $last_name,
'txn_id' => $data['txn_id'],
'address_street' => $addr_street,
'address_city' => $addr_city,
'address_state' => $addr_state,
'address_zip' => $addr_zip,
'address_country' => $addr_country,
);
ASP_Debug_Logger::log( 'Calling eMember_handle_subsc_signup_stand_alone' );
$emember_id = '';
if ( class_exists( 'Emember_Auth' ) ) {
//Check if the user is logged in as a member.
$emember_auth = Emember_Auth::getInstance();
$emember_id = $emember_auth->getUserInfo( 'member_id' );
}
if ( defined( 'WP_EMEMBER_PATH' ) ) {
require_once WP_EMEMBER_PATH . 'ipn/eMember_handle_subsc_ipn_stand_alone.php';
eMember_handle_subsc_signup_stand_alone( $ipn_data, $level_id, $data['txn_id'], $emember_id );
}
}
public function handle_wp_pdf_stamper( $data, $prod_id ) {
$pdf_stamper_enabled = get_post_meta( $prod_id, 'asp_product_pdf_stamper_enabled', true );
$item_url = get_post_meta( $prod_id, 'asp_product_upload', true );
if ( $pdf_stamper_enabled && ! empty( $item_url ) && strpos( strtolower( basename( $item_url ) ), '.pdf' ) !== false ) {
$ipn = ASP_Process_IPN_NG::get_instance();
$billing_addr = $ipn->p_data->get_billing_details();
$b_addr = $billing_addr->line1 . ', ' . $billing_addr->city . ', ' . ( isset( $billing_addr->state ) ? $billing_addr->state . ', ' : '' ) . $billing_addr->postal_code . ', ' . $billing_addr->country;
$additional_params = array(
'product_name' => $data['item_name'],
'transaction_id' => $data['txn_id'],
);
$res = pdf_stamper_stamp_internal_file( $item_url, $data['customer_name'], $data['stripeEmail'], '', $b_addr, '', '', '', '', $additional_params );
if ( empty( $res ) ) {
return $data;
}
$res_arr = explode( " \n", $res );
if ( isset( $res_arr[0] ) && 'Success!' === $res_arr[0] ) {
$data['item_url'] = $res_arr[1];
}
}
return $data;
}
public function check_token( $item ) {
$disable_token_check = $this->main->get_setting( 'disable_security_token_check' );
if ( $disable_token_check ) {
return;
}
$button_key = $item->get_button_key();
$token = isset( $_POST['token'] ) ? sanitize_text_field( stripslashes ( $_POST['token'] ) ) : '';
$g_token = ASP_Utils::get_visitor_token( $button_key );
if ( empty( $token ) || $g_token !== $token ) {
$out = array();
$out['success'] = false;
$out['err'] = __( 'Invalid security token.', 'stripe-payments' );
wp_send_json( $out );
}
}
public function check_rate_limit() {
//disabled for now
return;
$limit = 5;
$tdata = get_transient( 'asp_ng_throttle_data' );
$tdata = empty( $tdata ) ? array() : $tdata;
array_push( $tdata, time() );
foreach ( $tdata as $key => $req ) {
if ( $req < ( time() + 60 ) ) {
unset( $tdata[ $key ] );
}
}
set_transient( 'asp_ng_throttle_data', $tdata );
if ( count( $tdata ) > $limit ) {
$out = array();
$out['success'] = false;
$out['err'] = __( 'Rate limit exceeded. Please try again later.', 'stripe-payments' );
wp_send_json( $out );
}
}
public function tax_variations( $item ) {
$tax_variations_arr = $item->get_meta( 'asp_product_tax_variations' );
if ( empty( $tax_variations_arr ) ) {
return $item;
}
$this->tax_variations_arr = $tax_variations_arr;
$this->item = $item;
add_filter( 'asp_ng_before_customer_create_update', array( $this, 'tax_variations_check_apply' ), 10, 2 );
add_filter( 'asp_ng_sub_confirm_token_customer_opts', array( $this, 'tax_variations_check_apply' ) );
return $this->item;
}
public function tax_variations_check_apply( $cust_opts ) {
ASP_Debug_Logger::log_array_data( $cust_opts );
if ( empty( $cust_opts['address'] ) ) {
return $cust_opts;
}
if ( empty( $this->tax_variations_arr ) ) {
return $cust_opts;
}
$tax_variations_type = $this->item->get_meta('asp_product_tax_variations_type');
if ($tax_variations_type == 's'){
$new_tax = ASP_Utils::get_tax_variations_tax(
$this->tax_variations_arr,
empty( $cust_opts['shipping']['address']['country'] ) ? '' : $cust_opts['shipping']['address']['country'],
empty( $cust_opts['shipping']['address']['state'] ) ? '' : $cust_opts['shipping']['address']['state'],
empty( $cust_opts['shipping']['address']['city'] ) ? '' : $cust_opts['shipping']['address']['city']
);
} else {
$new_tax = ASP_Utils::get_tax_variations_tax(
$this->tax_variations_arr,
empty( $cust_opts['address']['country'] ) ? '' : $cust_opts['address']['country'],
empty( $cust_opts['address']['state'] ) ? '' : $cust_opts['address']['state'],
empty( $cust_opts['address']['city'] ) ? '' : $cust_opts['address']['city']
);
}
if ( false !== $new_tax ) {
$this->item->set_tax( $new_tax );
}
return $cust_opts;
}
public function tax_variations_addon( $data, $prod_id ) {
if ( empty( $data['tax_variations'] ) ) {
return $data;
}
$addon = array(
'name' => 'aspTaxVariations',
'handler' => 'aspTaxVariationsNG',
);
$data['addons'][] = $addon;
return $data;
}
public function daily_txn_limit($data,$charge)
{
$captcha_type = $this->main->get_setting('captcha_type');
$asp_daily_txn_counter_obj = new ASP_Daily_Txn_Counter();
if (empty( $captcha_type ) || $captcha_type == 'none' ) {
$asp_daily_txn_counter_obj->asp_increment_daily_txn_counter();
}
else if($asp_daily_txn_counter_obj->asp_is_daily_tnx_limit_with_captcha_enabled()){
$asp_daily_txn_counter_obj->asp_increment_daily_txn_counter();
}
}
}
new ASP_Self_Hooks_Handler();

View File

@ -0,0 +1,196 @@
<?php
class ASP_Stripe_API {
protected static $instance;
protected $api_key;
protected $api_url = 'https://api.stripe.com/v1/';
protected $last_error = array();
//Since 2.0.44t2
protected $throw_exception = false;
//If true, throws PHP exception when error occurs
protected $app_info = array(
'name' => 'Stripe Payments',
'partner_id' => 'pp_partner_Fvas9OJ0jQ2oNQ',
'url' => 'https://wordpress.org/plugins/stripe-payments/',
'version' => WP_ASP_PLUGIN_VERSION,
);
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public function set_api_key( $key ) {
$this->api_key = $key;
}
public function set_param( $param, $value ) {
$this->$param = $value;
}
private function encode_params( $d ) {
if ( true === $d ) {
return 'true';
}
if ( false === $d ) {
return 'false';
}
if ( is_array( $d ) ) {
$res = array();
foreach ( $d as $k => $v ) {
$res[ $k ] = $this->encode_params( $v );
}
return $res;
}
return $d;
}
private function before_request() {
$this->last_error = array();
}
private function get_headers() {
$ua_string = 'Stripe/v1 PhpBindings/0.0.0';
$ua_string .= ' ' . $this->format_app_info( $this->app_info );
$lang_version = PHP_VERSION;
$uname_disabled = in_array( 'php_uname', explode( ',', ini_get( 'disable_functions' ) ), true );
$uname = $uname_disabled ? '(disabled)' : php_uname();
$ua = array(
'bindings_version' => '0.0.0',
'lang' => 'php',
'lang_version' => $lang_version,
'publisher' => 'stripe',
'uname' => $uname,
'application' => $this->app_info,
);
$headers = array(
'X-Stripe-Client-User-Agent' => json_encode( $ua ),
'User-Agent' => $ua_string,
'Authorization' => 'Basic ' . base64_encode( $this->api_key . ':' ),
'Stripe-Version' => ASPMain::$stripe_api_ver,
);
return $headers;
}
private function process_result( $res ) {
if ( is_wp_error( $res ) ) {
$this->last_error['message'] = $res->get_error_message();
$this->last_error['error_code'] = $res->get_error_code();
if ( $this->throw_exception ) {
throw new \Exception( $res->get_error_message(), $res->get_error_code() );
}
return false;
}
if ( 200 !== $res['response']['code'] ) {
if ( ! empty( $res['body'] ) ) {
$body = json_decode( $res['body'], true );
if ( isset( $body['error'] ) ) {
$this->last_error = $body['error'];
$this->last_error['http_code'] = $res['response']['code'];
if ( $this->throw_exception ) {
throw new \Exception( $body['error']['message'], $res['response']['code'] );
}
}
}
return false;
}
$return = json_decode( $res['body'] );
return $return;
}
/**
* Make GET API request
*
* @param string $endpoint
* Endpoint to make request to. Example: 'customers/'
* @param array $params
* Parameters to send. Was ignored before 2.0.44
* @return mixed
* `object` on success, `false` on error
*/
public function get( $endpoint, $params = array() ) {
$this->before_request();
$headers = $this->get_headers();
$res = wp_remote_get(
$this->api_url . $endpoint,
array(
'headers' => $headers,
'body' => $this->encode_params( $params ),
)
);
$return = $this->process_result( $res );
return $return;
}
/**
* Make POST API request
*
* @param string $endpoint
* Endpoint to make request to. Example: 'customers/'
* @param array $params
* Parameters to send
* @param string $method
* Since 2.0.51
* Request method. Default is 'POST'
* @return mixed
* `object` on success, `false` on error
*/
public function post( $endpoint, $params = array(), $method = 'POST' ) {
$this->before_request();
$headers = $this->get_headers();
$res = wp_remote_get(
$this->api_url . $endpoint,
array(
'method' => $method,
'headers' => $headers,
'body' => $this->encode_params( $params ),
)
);
$return = $this->process_result( $res );
return $return;
}
public function get_last_error() {
return $this->last_error;
}
private function format_app_info( $app_info ) {
if ( null !== $app_info ) {
$string = $app_info['name'];
if ( null !== $app_info['version'] ) {
$string .= '/' . $app_info['version'];
}
if ( null !== $app_info['url'] ) {
$string .= ' (' . $app_info['url'] . ')';
}
return $string;
}
return null;
}
}

View File

@ -0,0 +1,184 @@
<?php
class ASP_Utils_Bot_Mitigation {
public static function get_asp_hash_private_key_one() {
$hp_key = get_option( 'asp_hash_private_key_one' );
if ( empty( $hp_key ) ) {
$hp_key = uniqid( '', true );
update_option( 'asp_hash_private_key_one', $hp_key );
}
return $hp_key;
}
public static function get_captcha_solve_ip_time_data() {
$solved_ip_time_arr = get_transient('asp_captcha_solve_ip_time');
if (!isset($solved_ip_time_arr) || empty($solved_ip_time_arr)) {
$solved_ip_time_arr = array();
}
return $solved_ip_time_arr;
}
public static function record_captcha_solve_ip_time_data() {
$captcha_solve_ip = ASP_Utils::get_user_ip_address();
$current_wp_time = current_time('mysql');
if (!isset($captcha_solve_ip) || empty($captcha_solve_ip)) {
ASP_Debug_Logger::log('Captcha solved but IP address is missing. Cannot record this captcha solve event. The extra security check later may fail.', false);
return;
}
//ASP_Debug_Logger::log('Captcha solved from IP: ' . $captcha_solve_ip . ', Time: ' . $current_wp_time, true);
$solved_ip_time_arr = ASP_Utils_Bot_Mitigation::get_captcha_solve_ip_time_data();
//ASP_Debug_Logger::log_array_data($solved_ip_time_arr);
$solved_ip_time_arr[$captcha_solve_ip] = $current_wp_time;
//ASP_Debug_Logger::log_array_data($solved_ip_time_arr);
set_transient('asp_captcha_solve_ip_time', $solved_ip_time_arr, 300);
}
public static function is_captcha_solve_ip_data_time_valid() {
$solved_ip_time_arr = get_transient('asp_captcha_solve_ip_time');
if (!isset($solved_ip_time_arr) || empty($solved_ip_time_arr)) {
ASP_Debug_Logger::log( 'Captcha response check - currently there are no entries in the saved data that solved a captcha.', false );
return false;
}
$ip_address_to_check = ASP_Utils::get_user_ip_address();
if (!isset($ip_address_to_check) || empty($ip_address_to_check)) {
ASP_Debug_Logger::log( 'Captcha response check - IP address value for this request is missing.', false );
return false;
}
if (!isset($solved_ip_time_arr[$ip_address_to_check]) || empty ($solved_ip_time_arr[$ip_address_to_check])){
ASP_Debug_Logger::log( 'Captcha response check - cannot find this IP address ('.$ip_address_to_check.') in the saved data that solved a captcha.', false );
return false;
}
$captcha_solved_timestamp = $solved_ip_time_arr[$ip_address_to_check];
$current_wp_time = current_time('mysql');
$time_diff = strtotime($current_wp_time) - strtotime($captcha_solved_timestamp);
if ( $time_diff > 300 ){
//Time expired
ASP_Debug_Logger::log( 'Captcha response check - The captcha solve data for this IP address ('.$ip_address_to_check.') expired. Time difference (seconds): ' . $time_diff, false );
return false;
}
//Entry for the given IP address exists and time is valid.
return true;
}
public static function get_page_load_signature_data() {
$page_load_signature_arr = get_transient('asp_page_load_signature');
if (!isset($page_load_signature_arr) || empty($page_load_signature_arr)) {
$page_load_signature_arr = array();
}
return $page_load_signature_arr;
}
public static function record_page_load_signature_data($product_id) {
$ip_address = ASP_Utils::get_user_ip_address();
//$current_wp_time = current_time('mysql');
if (!isset($ip_address) || empty($ip_address)) {
ASP_Debug_Logger::log('IP address value missing (could not read the IP address of the user). Cannot record this page load signature. The extra security check later may fail.', false);
return;
}
$page_load_signature_arr = ASP_Utils_Bot_Mitigation::get_page_load_signature_data();
//ASP_Debug_Logger::log_array_data($page_load_signature_arr);
$hp_key = ASP_Utils_Bot_Mitigation::get_asp_hash_private_key_one();
$index = $product_id. '_'.$ip_address;
$signature = sha1($hp_key.$product_id.$ip_address);
$page_load_signature_arr[$index] = $signature;
//ASP_Debug_Logger::log('Index: ' . $index . ', Signature: ' . $signature . ', IP Address: ' . $ip_address, true);
//ASP_Debug_Logger::log_array_data($page_load_signature_arr);
//Save the page load signature data with an expiry of 1 hour.
set_transient('asp_page_load_signature', $page_load_signature_arr, 3600);
}
public static function is_page_load_signature_data_valid($product_id) {
$page_load_signature_arr = get_transient('asp_page_load_signature');
if (!isset($page_load_signature_arr) || empty($page_load_signature_arr)) {
ASP_Debug_Logger::log( 'Page load signature check - currently there are no entries in the saved data for page load signature.', false );
return false;
}
$ip_address_to_check = ASP_Utils::get_user_ip_address();
if (!isset($ip_address_to_check) || empty($ip_address_to_check)) {
ASP_Debug_Logger::log( 'Page load signature check - IP address value for this request is missing.', false );
return false;
}
$index = $product_id. '_'.$ip_address_to_check;
if (!isset($page_load_signature_arr[$index]) || empty ($page_load_signature_arr[$index])){
ASP_Debug_Logger::log( 'Page load signature check - cannot find this Product ID and IP address index ('.$index.') in the saved data.', false );
return false;
}
$hp_key = ASP_Utils_Bot_Mitigation::get_asp_hash_private_key_one();
$expected_signature = $page_load_signature_arr[$index];
$received = sha1($hp_key.$product_id.$ip_address_to_check);
//ASP_Debug_Logger::log('Index: ' . $index . ', Signature Received: ' . $received . ', Expected: ' . $expected_signature, true);
//ASP_Debug_Logger::log_array_data($page_load_signature_arr);
if (!hash_equals($expected_signature, $received)){
//Mis-match
ASP_Debug_Logger::log( 'Page load signature check - the signature hash does not match.', false );
return false;
}
//Entry for the received signature exists
ASP_Debug_Logger::log( 'Page load signature check done!', true );
return true;
}
public static function get_request_limit_count_data() {
$asp_request_usage_count = get_transient('asp_request_usage_count');
if (!isset($asp_request_usage_count) || empty($asp_request_usage_count)) {
$asp_request_usage_count = array();
}
return $asp_request_usage_count;
}
public static function is_request_limit_reached_for_ip(){
$ip_address_to_check = ASP_Utils::get_user_ip_address();
if (!isset($ip_address_to_check) || empty($ip_address_to_check)) {
ASP_Debug_Logger::log( 'Request usage count check - IP address value for this request is missing.', false );
return false;
}
//Count and check usage.
$asp_request_usage_count = ASP_Utils_Bot_Mitigation::get_request_limit_count_data();
$index = $ip_address_to_check;
if( !isset($asp_request_usage_count[$index]) ){
//Index not set so initialize with 0 count.
$asp_request_usage_count[$index] = 0;
}
$asp_request_usage_count[$index] = $asp_request_usage_count[$index] + 1;
//ASP_Debug_Logger::log('Index: ' . $index . ', Count: ' . $asp_request_usage_count[$index], true);
//Save the request usage count data with an expiry of 12 hours.
set_transient('asp_request_usage_count', $asp_request_usage_count, 43200);
//Check limit
$limit = apply_filters('asp_request_usage_count_by_ip_limit', 20);//Trigger a filter so this can be customized.
if ($asp_request_usage_count[$index] > $limit){
//Limit reached/exceeded. Reject this.
ASP_Debug_Logger::log( 'Request usage count limit reached for this IP address. IP: ' . $index . ', Request Count: ' . $asp_request_usage_count[$index], false );
return false;
}
ASP_Debug_Logger::log( 'Request usage count is valid for this IP addresss. IP: ' . $index . ', Request Count: ' . $asp_request_usage_count[$index], true );
return true;
}
}

View File

@ -0,0 +1,78 @@
<?php
class ASP_Utils_Misc {
public static function get_current_page_url() {
$pageURL = 'http';
if ( isset( $_SERVER['SCRIPT_URI'] ) && ! empty( $_SERVER['SCRIPT_URI'] ) ) {
$pageURL = $_SERVER['SCRIPT_URI'];
$pageURL = str_replace( ':443', '', $pageURL ); //remove any port number from the URL value (some hosts include the port number with this).
$pageURL = apply_filters( 'asp_get_current_page_url_filter', $pageURL );
return $pageURL;
}
//Check if 'SERVER_NAME' is set. If not, try get the URL from WP.
if ( ! isset( $_SERVER['SERVER_NAME'] ) ) {
global $wp;
if ( is_object( $wp ) && isset( $wp->request ) ) {
//Try to get the URL from WP
$pageURL = home_url( add_query_arg( array(), $wp->request ) );
$pageURL = apply_filters( 'asp_get_current_page_url_filter', $pageURL );
return $pageURL;
}
}
//Construct the URL value from the $_SERVER array values.
if ( isset( $_SERVER['HTTPS'] ) && ( $_SERVER['HTTPS'] == 'on' ) ) {
$pageURL .= 's';
}
$pageURL .= '://';
if ( isset( $_SERVER['SERVER_PORT'] ) && ( $_SERVER['SERVER_PORT'] != '80' ) && ( $_SERVER['SERVER_PORT'] != '443' ) ) {
$pageURL .= ltrim( $_SERVER['SERVER_NAME'], '.*' ) . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'];
} else {
$pageURL .= ltrim( $_SERVER['SERVER_NAME'], '.*' ) . $_SERVER['REQUEST_URI'];
}
//Clean any known port numbers from the URL (some hosts may include these port numbers).
$pageURL = str_replace( ':8080', '', $pageURL );
//Trigger filter
$pageURL = apply_filters( 'asp_get_current_page_url_filter', $pageURL );
return $pageURL;
}
public static function secure_badge_allowed_tags() {
return array(
'img' => array(
'src' => array(),
'alt' => array(),
'class' => array(),
'id' => array(),
),
'ul' => array(
'class' => array(),
'id' => array(),
),
'li' => array(
'class' => array(),
'id' => array(),
),
'p' => array(
'class' => array(),
'id' => array(),
),
'br' => array()
);
}
public static function secure_badge_default_content() {
$output = '<ul>'.PHP_EOL;
$output .= ' <li>100% Secure Checkout</li>'.PHP_EOL;
$output .= ' <li>All transactions are encrypted using SSL/TLS technology.</li>'.PHP_EOL;
$output .= '</ul>';
return $output;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,678 @@
<?php
class AcceptStripePayments {
public $footer_scripts = '';
var $zeroCents = array( 'JPY', 'MGA', 'VND', 'KRW' );
var $minAmounts = array(
'USD' => 50,
'AUD' => 50,
'BGN' => 100,
'BRL' => 50,
'CAD' => 50,
'CHF' => 50,
'COP' => 2000,
'DKK' => 250,
'EUR' => 50,
'GBP' => 30,
'HKD' => 400,
'INR' => 50,
'JPY' => 50,
'MXN' => 1000,
'MYR' => 200,
'NOK' => 300,
'NZD' => 50,
'PLN' => 200,
'RON' => 200,
'SEK' => 300,
'SGD' => 50,
'AED' => 200,
);
public $APISecKey = '';
public $APIPubKey = '';
public $APIPubKeyTest = '';
public $APIPubKeyLive = '';
public $APISecKeyTest = '';
public $APISecKeyLive = '';
public $is_live = false;
public static $pp_slug = 'asp-payment-box';
/**
* Plugin version, used for cache-busting of style and script file references.
*
* @since 1.0.0
*
* @var string
*/
const VERSION = '1.0.0';
/**
*
* Unique identifier for your plugin.
*
* The variable name is used as the text domain when internationalizing strings
* of text. Its value should match the Text Domain file header in the main
* plugin file.
*
* @since 1.0.0
*
* @var string
*/
protected $plugin_slug = 'accept_stripe_payment'; //Do not change this value.
/**
* Instance of this class.
*
* @since 1.0.0
*
* @var object
*/
protected static $instance = null;
private $settings = null;
/**
* Initialize the plugin by setting localization and loading public scripts
* and styles.
*
* @since 1.0.0
*/
private function __construct() {
self::$instance = $this;
add_action( 'asp_send_scheduled_email', array( $this, 'send_scheduled_email' ), 10, 4 );
if ( is_admin() ) {
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . '/wp-admin/includes/plugin.php';
}
if ( is_plugin_active( 'stripe-payments-recaptcha/asp-recaptcha-main.php' ) ) {
deactivate_plugins( 'stripe-payments-recaptcha/asp-recaptcha-main.php' );
}
}
if ( ! class_exists( 'ASP_RECAPTCHA_Main' ) ) {
require_once WP_ASP_PLUGIN_PATH . 'includes/recaptcha/asp-recaptcha-main.php';
}
require_once WP_ASP_PLUGIN_PATH . 'includes/eprecaptcha/asp-eprecaptcha-main.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/hcaptcha/asp-hcaptcha-main.php';
$this->settings = (array) get_option( 'AcceptStripePayments-settings' );
if ( $this->get_setting( 'is_live' ) == 0 ) {
//use test keys
$this->is_live = false;
$this->APIPubKey = $this->get_setting( 'api_publishable_key_test' );
$this->APISecKey = $this->get_setting( 'api_secret_key_test' );
} else {
//use live keys
$this->is_live = true;
$this->APIPubKey = $this->get_setting( 'api_publishable_key' );
$this->APISecKey = $this->get_setting( 'api_secret_key' );
}
$this->APIPubKeyTest = $this->get_setting( 'api_publishable_key_test' );
$this->APIPubKeyLive = $this->get_setting( 'api_publishable_key' );
$this->APISecKeyTest = $this->get_setting( 'api_secret_key_test' );
$this->APISecKeyLive = $this->get_setting( 'api_secret_key' );
// Load plugin text domain
add_action( 'init', array( $this, 'load_asp_plugin_textdomain' ) );
add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
//Can be used to override some of the safe styles allowed in wp_kses function.
add_filter( 'safe_style_css', array( $this, 'customize_safe_style_css' ) );
//handle self hooks
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-self-hooks-handler.php';
//handle IPN stuff if needed
require_once WP_ASP_PLUGIN_PATH . 'includes/process_ipn.php';
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-process-ipn-ng.php';
//handle payment popup display if needed
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-pp-display.php';
//handle payment popup ajax
require_once WP_ASP_PLUGIN_PATH . 'includes/class-asp-pp-ajax.php';
// SWPM integration
require_once WP_ASP_PLUGIN_PATH . 'includes/integrations/class-asp-swpm-integrations.php';
// Activate plugin when new blog is added
add_action( 'wpmu_new_blog', array( $this, 'activate_new_site' ) );
// Load public-facing style sheet and JavaScript.
// add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts_styles' ) );
add_action( 'after_switch_theme', array( $this, 'rewrite_flush' ) );
}
public function plugins_loaded() {
//check if we have view_log request with token
$action = isset( $_GET['asp_action'] ) ? sanitize_text_field( stripslashes ( $_GET['asp_action'] ) ) : '';
$token = isset( $_GET['token'] ) ? sanitize_text_field( stripslashes ( $_GET['token'] ) ) : '';
if ( isset( $action ) && 'view_log' === $action && isset( $token ) ) {
//let's check token
if ( $this->get_setting( 'debug_log_link_enable', false ) && $this->get_setting( 'debug_log_access_token' ) === $token ) {
ASP_Debug_Logger::view_log();
}
}
if ( ! is_admin() ) {
add_action( 'wp_print_footer_scripts', array( $this, 'frontend_print_footer_scripts' ) );
}
}
public function customize_safe_style_css( $styles ) {
$styles[] = 'display';
return $styles;
}
public function send_scheduled_email( $to, $subj, $body, $headers ) {
ASP_Debug_Logger::log( sprintf( 'Sending scheduled email to %s.', $to ) );
wp_mail( $to, $subj, $body, $headers );
}
public function get_setting( $field, $default = false ) {
$this->settings = (array) get_option( 'AcceptStripePayments-settings' );
return isset( $this->settings[ $field ] ) ? $this->settings[ $field ] : $default;
}
/**
* Return the plugin slug.
*
* @since 1.0.0
*
* @return Plugin slug variable.
*/
public function get_plugin_slug() {
return $this->plugin_slug;
}
/**
* Return an instance of this class.
*
* @since 1.0.0
*
* @return object A single instance of this class.
*/
public static function get_instance() {
// If the single instance hasn't been set, set it now.
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Fired when the plugin is activated.
*
* @since 1.0.0
*
* @param boolean $network_wide True if WPMU superadmin uses
* "Network Activate" action, false if
* WPMU is disabled or plugin is
* activated on an individual blog.
*/
public static function activate( $network_wide ) {
if ( function_exists( 'is_multisite' ) && is_multisite() ) {
if ( $network_wide ) {
// Get all blog ids
$blog_ids = self::get_blog_ids();
foreach ( $blog_ids as $blog_id ) {
switch_to_blog( $blog_id );
self::single_activate();
}
restore_current_blog();
} else {
self::single_activate();
}
} else {
self::single_activate();
}
}
/**
* Fired when the plugin is deactivated.
*
* @since 1.0.0
*
* @param boolean $network_wide True if WPMU superadmin uses
* "Network Deactivate" action, false if
* WPMU is disabled or plugin is
* deactivated on an individual blog.
*/
public static function deactivate( $network_wide ) {
if ( function_exists( 'is_multisite' ) && is_multisite() ) {
if ( $network_wide ) {
// Get all blog ids
$blog_ids = self::get_blog_ids();
foreach ( $blog_ids as $blog_id ) {
switch_to_blog( $blog_id );
self::single_deactivate();
}
restore_current_blog();
} else {
self::single_deactivate();
}
} else {
self::single_deactivate();
}
}
/**
* Fired when a new site is activated with a WPMU environment.
*
* @since 1.0.0
*
* @param int $blog_id ID of the new blog.
*/
public function activate_new_site( $blog_id ) {
if ( 1 !== did_action( 'wpmu_new_blog' ) ) {
return;
}
switch_to_blog( $blog_id );
self::single_activate();
restore_current_blog();
}
/**
* Get all blog ids of blogs in the current network that are:
* - not archived
* - not spam
* - not deleted
*
* @since 1.0.0
*
* @return array|false The blog ids, false if no matches.
*/
private static function get_blog_ids() {
global $wpdb;
return $wpdb->get_col(
"SELECT blog_id FROM $wpdb->blogs
WHERE archived = '0' AND spam = '0'
AND deleted = '0'"
);
}
/**
* Fired for each blog when the plugin is activated.
*
* @since 1.0.0
*/
private static function single_activate() {
$admin_email = get_option( 'admin_email' );
if ( ! $admin_email ) {
$admin_email = '';
}
//Generate (if one doesn't exist) and save a private key for hashing purpose
$hp_key = get_option( 'asp_hash_private_key_one' );
if ( empty( $hp_key ) ) {
$hp_key = uniqid( '', true );
update_option( 'asp_hash_private_key_one', $hp_key );
}
//Default settings values
$default = array(
'is_live' => 0,
'debug_log_enable' => 0,
'dont_save_card' => 0,
'currency_code' => 'USD',
'button_text' => __( 'Buy Now', 'stripe-payments' ),
// translators: %s is not a placeholder
'popup_button_text' => __( 'Pay %s', 'stripe-payments' ),
'use_new_button_method' => 0,
'checkout_url' => site_url( 'checkout' ),
'from_email_address' => get_bloginfo( 'name' ) . ' <sales@your-domain.com>',
'buyer_email_subject' => __( 'Thank you for the purchase', 'stripe-payments' ),
'buyer_email_body' => __( 'Hello', 'stripe-payments' ) . "\r\n\r\n"
. __( 'Thank you for your purchase! You ordered the following item(s):', 'stripe-payments' ) . "\r\n\r\n"
. '{product_details}',
'seller_notification_email' => get_bloginfo( 'admin_email' ),
'seller_email_subject' => __( 'Notification of product sale', 'stripe-payments' ),
'seller_email_body' => __( 'Dear Seller', 'stripe-payments' ) . "\r\n\r\n"
. __( 'This mail is to notify you of a product sale.', 'stripe-payments' ) . "\r\n\r\n"
. "{product_details}\r\n\r\n"
. __( 'The sale was made to', 'stripe-payments' ) . " {payer_email}\r\n\r\n"
. __( 'Thanks', 'stripe-payments' ),
'price_currency_pos' => 'left',
'price_decimal_sep' => '.',
'price_thousand_sep' => ',',
'price_decimals_num' => '2',
'api_keys_separated' => true,
'stripe_receipt_email' => 0,
'custom_field_enabled' => 0,
'custom_field_name' => '',
'custom_field_descr' => '',
'custom_field_type' => 'text',
'custom_field_mandatory' => 0,
'send_email_on_error' => 0,
'send_email_on_error_to' => $admin_email,
'send_email_on_daily_txn_rate_limit' => 1,
'send_email_on_daily_txn_rate_limit_to' => $admin_email,
'use_old_checkout_api1' => 0,
'disable_buttons_before_js_loads' => 0,
'tos_text' => __( 'I accept the <a href="https://example.com/terms-and-conditions/" target="_blank">Terms and Conditions</a>', 'stripe-payments' ),
'daily_txn_limit_without_captcha' => 25,
'daily_txn_limit_with_captcha' => 100
);
$opt = get_option( 'AcceptStripePayments-settings' );
// Check if its a first install
$first_install = false;
if ( ! is_array( $opt ) ) {
//this is first install
$first_install = true;
$opt = $default;
}
$opt = array_merge( $default, $opt );
//force remove PHP warning dismissal
delete_option( 'wp_asp_php_warning_dismissed' );
update_option( 'AcceptStripePayments-settings', $opt );
//lets add default values for some settings that were added after plugin update
//let's separate Test and Live API keys (introduced in version 1.6.6)
if ( $opt['is_live'] == 0 && ! isset( $opt['api_keys_separated'] ) ) {
//current keys are test keys. Let's set them and clear the old values
if ( isset( $opt['api_secret_key'] ) ) {
$opt['api_secret_key_test'] = $opt['api_secret_key'];
$opt['api_secret_key'] = '';
}
if ( isset( $opt['api_publishable_key'] ) ) {
$opt['api_publishable_key_test'] = $opt['api_publishable_key'];
$opt['api_publishable_key'] = '';
}
//let's also set an indicator value in order for the plugin to not do that anymore
$opt['api_keys_separated'] = true;
}
//Enabled "Hide State Field" for existing installs, but only if wasn't set before
if ( ! $first_install && ! isset( $opt['hide_state_field'] ) ) {
$opt['hide_state_field'] = 1;
}
// 2.0.53: convert old `recaptcha_enabled` option to `captcha_type` if needed
if ( ! empty( $opt['recaptcha_enabled'] ) ) {
$opt['captcha_type'] = 'recaptcha';
$opt['recaptcha_enabled'] = 0;
}
$opt_diff = array_diff_key( $default, $opt );
if ( ! empty( $opt_diff ) ) {
foreach ( $opt_diff as $key => $value ) {
$opt[ $key ] = $default[ $key ];
}
}
update_option( 'AcceptStripePayments-settings', $opt );
//create checkout page
$args = array(
'post_type' => 'page',
);
$pages = get_pages( $args );
$checkout_page_id = '';
foreach ( $pages as $page ) {
if ( strpos( $page->post_content, 'accept_stripe_payment_checkout' ) !== false ) {
$checkout_page_id = $page->ID;
}
}
if ( '' === $checkout_page_id ) {
$checkout_page_id = self::create_post( 'page', 'Checkout-Result', 'Stripe-Checkout-Result', '[accept_stripe_payment_checkout]' );
$checkout_page = get_post( $checkout_page_id );
$checkout_page_url = $checkout_page->guid;
$asp_settings = get_option( 'AcceptStripePayments-settings' );
if ( ! empty( $asp_settings ) ) {
$asp_settings['checkout_url'] = $checkout_page_url;
$asp_settings['checkout_page_id'] = $checkout_page_id;
update_option( 'AcceptStripePayments-settings', $asp_settings );
}
}
//Create all products/shop page
$args = array(
'post_type' => 'page',
);
$pages = get_pages( $args );
$products_page_id = '';
foreach ( $pages as $page ) {
if ( strpos( $page->post_content, '[asp_show_all_products' ) !== false ) {
$products_page_id = $page->ID;
}
}
if ( '' === $products_page_id ) {
$products_page_id = self::create_post( 'page', 'Products', 'Products', '[asp_show_all_products]' );
//Save the newly created products page ID so it can be used later.
$asp_settings = get_option( 'AcceptStripePayments-settings' );
if ( ! empty( $asp_settings ) ) {
$asp_settings['products_page_id'] = $products_page_id;
update_option( 'AcceptStripePayments-settings', $asp_settings );
}
}
//Flush rewrite rules so new pages and slugs are properly handled
$asp_products = ASP_Admin_Products::get_instance();
$asp_products->register_post_type();
$asp_order = ASPOrder::get_instance();
$asp_order->register_post_type();
flush_rewrite_rules();
}
public static function create_post( $post_type, $title, $name, $content, $parent_id = null ) {
$post = array(
'post_title' => $title,
'post_name' => $name,
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_content' => $content,
'post_status' => 'publish',
'post_type' => $post_type,
);
if ( null !== $parent_id ) {
$post['post_parent'] = $parent_id;
}
$post_id = wp_insert_post( $post );
return $post_id;
}
/**
* Fired for each blog when the plugin is deactivated.
*/
private static function single_deactivate() {
// @TODO: Define deactivation functionality here
}
/**
* Load the plugin text domain for translation.
*/
public function load_asp_plugin_textdomain() {
load_plugin_textdomain( 'stripe-payments', false, dirname( plugin_basename( ASPMain::$file ) ) . '/languages/' );
}
/**
* @since 1.0.0
*/
public function rewrite_flush() {
flush_rewrite_rules();
}
public static function get_currencies() {
$currencies = ASP_Utils::get_currencies();
return $currencies;
}
/**
* Use ASP_Utils::formatted_price() instead.
*/
public static function formatted_price( $price, $curr = '', $price_is_cents = false ) {
return ASP_Utils::formatted_price( $price, $curr, $price_is_cents );
}
public static function apply_tax( $price, $tax, $is_zero_cents = false ) {
if ( ! empty( $tax ) ) {
$prec = 2;
if ( $is_zero_cents ) {
$prec = 0;
}
$tax_amount = round( ( $price * $tax / 100 ), $prec );
$price += $tax_amount;
}
return $price;
}
public static function apply_shipping( $price, $shipping, $is_zero_cents = false ) {
if ( ! empty( $shipping ) ) {
$prec = 2;
if ( $is_zero_cents ) {
$prec = 0;
}
$price += floatval( $shipping );
$price = round( $price, $prec );
}
return $price;
}
public static function get_tax_amount( $price, $tax, $is_zero_cents = false ) {
if ( ! empty( $tax ) ) {
$prec = 2;
if ( $is_zero_cents ) {
$prec = 0;
}
$tax_amount = round( ( $price * $tax / 100 ), $prec );
return $tax_amount;
} else {
return 0;
}
}
public static function is_zero_cents( $curr ) {
$zero_cents = array( 'JPY', 'MGA', 'VND', 'KRW' );
return in_array( strtoupper( $curr ), $zero_cents, true );
}
public static function from_cents( $amount, $currency ) {
$prec = 2;
if ( self::is_zero_cents( $currency ) ) {
$prec = 0;
}
$res = round( $amount / 100, $prec );
return $res;
}
/*
* Generates additional items string for the email body.
* It can be used to display variation data, shipping, tax etc.
*/
public static function gen_additional_items( $data, $sep = "\n" ) {
$out = '';
//Debug logging purposes only.
//ASP_Debug_Logger::log_array_data($data['additional_items'], true);
/*
Example of $data['additional_items'] array:
Array
(
[Size - Medium] => 5
[Download Link - High Res] => 0
[Gift Wrapping - Yes] => 5
[Tax] => 3
[Shipping] => 15
)
*/
if ( ! empty( $data['additional_items'] ) ) {
foreach ( $data['additional_items'] as $item => $price ) {
if ( $price < 0 ) {
$amnt_str = '-' . self::formatted_price( abs( $price ), $data['currency_code'] );
} else {
$amnt_str = self::formatted_price( $price, $data['currency_code'] );
}
//Debug logging purposes only
//ASP_Debug_Logger::log( sprintf( 'Additional item: %s, amount: %s', $item, $amnt_str ) );
//Example output: Additional item: Size - Medium, amount: $5.00
//Apply filter to allow changing the additional items data line.
$additional_items_data_line = apply_filters( 'asp_additional_items_individual_item', $item) . ': ' . $amnt_str . $sep;
$filtered_additional_items_data_line = apply_filters( 'asp_additional_items_data_line', $additional_items_data_line, $data );
$out .= $filtered_additional_items_data_line;
}
}
return $out;
}
public static function tofloat( $num ) {
$dot_pos = strrpos( $num, '.' );
$comma_pos = strrpos( $num, ',' );
$sep = ( ( $dot_pos > $comma_pos ) && $dot_pos ) ? $dot_pos : ( ( ( $comma_pos > $dot_pos ) && $comma_pos ) ? $comma_pos : false );
if ( ! $sep ) {
return floatval( preg_replace( '/[^0-9]/', '', $num ) );
}
return floatval(
preg_replace( '/[^0-9]/', '', substr( $num, 0, $sep ) ) . '.' .
preg_replace( '/[^0-9]/', '', substr( $num, $sep + 1, strlen( $num ) ) )
);
}
public function enqueue_frontend_scripts_styles() {
wp_register_script( 'stripe-handler-ng', WP_ASP_PLUGIN_URL . '/public/assets/js/stripe-handler-ng.js', array( 'jquery' ), WP_ASP_PLUGIN_VERSION, true );
$iframe_url = ASP_Utils::get_base_pp_url();
$prefetch = $this->get_setting( 'frontend_prefetch_scripts' );
$asp_dev_mode = ( defined( 'WP_ASP_DEV_MODE' ) ) ? '1' : '';
wp_localize_script(
'stripe-handler-ng',
'wpASPNG',
array(
'iframeUrl' => $iframe_url,
'ppSlug' => self::$pp_slug,
'prefetch' => $prefetch,
'ckey' => ASP_Utils::get_ckey(),
'aspDevMode' => $asp_dev_mode,
)
);
wp_enqueue_script( 'stripe-handler-ng' );
wp_register_style( 'stripe-handler-ng-style', WP_ASP_PLUGIN_URL . '/public/assets/css/public.css', array(), WP_ASP_PLUGIN_VERSION );
wp_enqueue_style( 'stripe-handler-ng-style' );
}
public function frontend_print_footer_scripts() {
if ( ! empty( $this->footer_scripts ) ) {
$allowed_tags = array(
'a' => array(
'href' => array(),
'title' => array()
),
'link' => array(
'href' => array(),
'rel' => array(),
'as' => array(),
),
);
echo wp_kses( $this->footer_scripts, $allowed_tags );
}
}
}

View File

@ -0,0 +1,104 @@
<?php
class ASP_EPRECAPTCHA_Admin_Menu {
public $plugin_slug;
public $asp_admin;
public function __construct() {
$this->asp_admin = AcceptStripePayments_Admin::get_instance();
$this->plugin_slug = $this->asp_admin->plugin_slug;
add_action( 'admin_init', array( $this, 'register_settings' ) );
add_filter( 'asp-admin-settings-addon-field-display', array( $this, 'field_display' ), 10, 2 );
add_filter( 'apm-admin-settings-sanitize-field', array( $this, 'sanitize_settings' ), 10, 2 );
}
public function sanitize_settings( $output, $input ) {
$output['eprecaptcha_site_key'] = sanitize_text_field( $input['eprecaptcha_site_key'] );
$output['eprecaptcha_api_key'] = sanitize_text_field( $input['eprecaptcha_api_key'] );
$output['eprecaptcha_project_id'] = sanitize_text_field( $input['eprecaptcha_project_id'] );
if ( $output['captcha_type'] === 'eprecaptcha' ) {
if ( empty( $output['eprecaptcha_site_key'] ) ) {
add_settings_error( 'AcceptStripePayments-settings', 'invalid-credentials', __( 'Please enter Enterprise reCaptcha Site Key.', 'stripe-payments' ) );
}
if ( empty( $output['eprecaptcha_api_key'] ) ) {
add_settings_error( 'AcceptStripePayments-settings', 'invalid-credentials', __( 'Please enter Enterprise reCaptcha Api Key.', 'stripe-payments' ) );
}
if ( empty( $output['eprecaptcha_project_id'] ) ) {
add_settings_error( 'AcceptStripePayments-settings', 'invalid-credentials', __( 'Please enter Enterprise reCaptcha Project Id.', 'stripe-payments' ) );
}
}
return $output;
}
public function field_display( $field, $field_value ) {
$ret = array();
switch ( $field ) {
case 'recaptcha_invisible':
$ret['field'] = 'checkbox';
$ret['field_name'] = $field;
break;
default:
break;
}
if ( ! empty( $ret ) ) {
return $ret;
} else {
return $field;
}
}
public function register_settings() {
add_settings_section( 'AcceptStripePayments-eprecaptcha-section', __( 'Enterprise reCAPTCHA Settings', 'stripe-payments' ), array( $this, 'show_settings_description' ), $this->plugin_slug . '-eprecaptcha' );
add_settings_field(
'eprecaptcha_site_key',
__( 'Site Key', 'stripe-payments' ),
array( $this->asp_admin, 'settings_field_callback' ),
$this->plugin_slug . '-eprecaptcha',
'AcceptStripePayments-eprecaptcha-section',
array(
'field' => 'eprecaptcha_site_key',
'size' => 63,
'desc' => __( 'Your Enterprise reCaptcha Site Key.', 'stripe-payments' ),
)
);
add_settings_field(
'eprecaptcha_api_key',
__( 'API Key', 'stripe-payments' ),
array( $this->asp_admin, 'settings_field_callback' ),
$this->plugin_slug . '-eprecaptcha',
'AcceptStripePayments-eprecaptcha-section',
array(
'field' => 'eprecaptcha_api_key',
'size' => 63,
'desc' => __( 'Your Enterprise reCaptcha API Key.', 'stripe-payments' ),
)
);
add_settings_field(
'eprecaptcha_project_id',
__( 'Project Id', 'stripe-payments' ),
array( $this->asp_admin, 'settings_field_callback' ),
$this->plugin_slug . '-eprecaptcha',
'AcceptStripePayments-eprecaptcha-section',
array(
'field' => 'eprecaptcha_project_id',
'size' => 30,
'desc' => __( 'Your Enterprise reCaptcha Project Id.', 'stripe-payments' ),
)
);
}
public function show_settings_description() {
echo __( '<a href="https://s-plugins.com/stripe-payments-enterprise-recaptcha-feature/" target="_blank">Click here</a> to read the documentation to learn how to configure this and get API keys for your website.', 'stripe-payments' );
}
}

View File

@ -0,0 +1,346 @@
<?php
class ASP_EPRECAPTCHA_Main {
public $asp_main;
public $keys_entered = false;
public $enabled = false;
private $max_tokens = 4;
public function __construct() {
add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ), 100 );
}
public function plugins_loaded() {
$this->asp_main = AcceptStripePayments::get_instance();
$this->enabled = $this->asp_main->get_setting( 'captcha_type' ) === 'eprecaptcha';
if ( ! empty( $this->asp_main->get_setting( 'eprecaptcha_project_id' ) ) &&
! empty( $this->asp_main->get_setting( 'eprecaptcha_site_key' ) ) &&
! empty( $this->asp_main->get_setting( 'eprecaptcha_api_key' ) )
) {
$this->keys_entered = true;
}
add_action( 'wp_ajax_asp_eprecaptcha_check', array( $this, 'ajax_eprecaptcha_check' ) );
add_action( 'wp_ajax_nopriv_asp_eprecaptcha_check', array( $this, 'ajax_eprecaptcha_check' ) );
if ( is_admin() ) {
include_once WP_ASP_PLUGIN_PATH . 'includes/eprecaptcha/admin/asp-eprecaptcha-admin-menu.php';
new ASP_EPRECAPTCHA_Admin_Menu();
}
if ( $this->enabled ) {
add_action( 'asp_ng_before_token_request', array( $this, 'ng_before_token_request' ) );
add_action( 'asp_ng_before_payment_processing', array( $this, 'ng_before_payment_processing' ) );
add_action( 'asp_ng_do_additional_captcha_response_check', array( $this, 'ng_do_additional_captcha_response_check' ), 10, 2 );
if ( ! is_admin() ) {
add_filter( 'asp-button-output-data-ready', array( $this, 'data_ready' ), 10, 2 );
add_filter( 'asp-button-output-additional-styles', array( $this, 'output_styles' ) );
add_action( 'asp-button-output-register-script', array( $this, 'register_script' ) );
add_action( 'asp-button-output-enqueue-script', array( $this, 'enqueue_script' ) );
add_filter( 'asp-button-output-after-button', array( $this, 'after_button' ), 10, 3 );
add_filter( 'asp_before_payment_processing', array( $this, 'before_payment_processing' ), 10, 2 );
add_filter( 'asp_ng_pp_data_ready', array( $this, 'ng_data_ready' ), 10, 2 );
add_filter( 'asp_ng_pp_output_before_buttons', array( $this, 'ng_before_buttons' ), 10, 2 );
add_action( 'asp_ng_pp_output_add_scripts', array( $this, 'ng_add_scripts' ) );
add_filter( 'asp_ng_button_output_after_button', array( $this, 'ng_button_output_after_button' ), 10, 3 );
}
}
}
private function check_eprecatpcha( $token ) {
$ret = array();
$projectId = $this->asp_main->get_setting( 'eprecaptcha_project_id' );
$apiKey = $this->asp_main->get_setting( 'eprecaptcha_api_key' );
$obj = new stdClass();
$obj->event = new stdClass();
$obj->event->siteKey = $this->asp_main->get_setting( 'eprecaptcha_site_key' );
$obj->event->token=$token;
$body = json_encode($obj);
$res = wp_remote_post(
'https://recaptchaenterprise.googleapis.com/v1/projects/'.$projectId.'/assessments?key='.$apiKey,
array(
'headers' => array('Content-Type' => 'application/json; charset=utf-8'),
'data_format' => 'body',
'body' => $body,
)
);
if ( is_wp_error( $res ) ) {
$ret['error'] = __( 'Enterprice reCaptcha: error occurred during API request.', 'stripe-payments' ) . ' ' . $res->get_error_message();
return $ret;
}
if ( $res['response']['code'] !== 200 ) {
$ret['error'] = __( 'Enterprise reCaptcha: error occurred during API request. HTTP Error code:', 'stripe-payments' ) . ' ' . $res['response']['code'];
return $ret;
}
$response = json_decode( $res['body'], true );
if ( is_null( $response ) ) {
$ret['error'] = __( 'Enterprise reCaptcha: error occured parsing API response, invalid JSON data.', 'stripe-payments' );
return $ret;
}
if ( $response["tokenProperties"]['valid'] !== true ) {
$err_codes_str = __($response["tokenProperties"]['invalidReason'] , 'stripe-payments' );
$ret['error'] = __( 'Enterprise reCaptcha: check failed. Following error(s) occurred:', 'stripe-payments' ) . ' ' . $err_codes_str;
return $ret;
}
return $ret;
}
public function ajax_eprecaptcha_check() {
$out = array();
$payload = isset( $_POST['eprecaptcha_response'] ) ? sanitize_text_field( stripslashes ( $_POST['eprecaptcha_response'] ) ) : '';
if ( empty( $payload ) ) {
$out['error'] = __( 'Empty Enterprise reCaptcha response received.', 'stripe-payments' );
wp_send_json( $out );
}
$out = $this->check_eprecatpcha( $payload );
$sess = ASP_Session::get_instance();
if ( isset( $out['error'] ) ) {
$sess->set_transient_data( 'epreCaptcha_checked', false );
$sess->set_transient_data( 'epreCaptcha_error', $out['error'] );
} else {
ASP_Utils_Bot_Mitigation::record_captcha_solve_ip_time_data();
$sess->set_transient_data( 'epreCaptcha_checked', true );
$sess->set_transient_data( 'epreCaptcha_tokens', $this->max_tokens );
}
wp_send_json( $out );
}
public function ng_do_additional_captcha_response_check( $item, $params ) {
if ( !ASP_Utils_Bot_Mitigation::is_captcha_solve_ip_data_time_valid() ){
ASP_Debug_Logger::log( 'Enterprise reCAPTCHA - Additional captcha response check failed!', false );
//Exit out silently. Do not go ahead with the request processing.
//If some sites want more relaxed option, we can add an option to extend the expiry timer maybe.
exit;
}
ASP_Debug_Logger::log( 'Enterprise reCAPTCHA - Additional captcha response check done.', true );
return true;
}
public function ng_before_token_request( $item ) {
$sess = ASP_Session::get_instance();
$checked = $sess->get_transient_data( 'epreCaptcha_checked' );
if ( ! $checked ) {
$err = $sess->get_transient_data( 'epreCaptcha_error' );
if ( empty( $err ) ) {
$err = __( 'Enterprise reCaptcha check failed.', 'stripe-payments' );
}
wp_send_json(
array(
'success' => false,
'err' => $err,
)
);
}
$tokens = $sess->get_transient_data( 'epreCaptcha_tokens', 0 );
if ( $tokens <= 0 ) {
wp_send_json(
array(
'success' => false,
'err' => __( 'epreCaptcha tokens expired. Please refresh the page and try again.', 'stripe-payments' ),
)
);
}
$tokens--;
$sess->set_transient_data( 'epreCaptcha_tokens', $tokens );
return true;
}
public function ng_before_payment_processing( $post_data ) {
$sess = ASP_Session::get_instance();
$sess->set_transient_data( 'epreCaptcha_checked', false );
$sess->set_transient_data( 'epreCaptcha_error', false );
}
public function ng_before_buttons( $out, $data ) {
ob_start();
?>
<style>
.asp-eprecaptcha-container {
height: 78px;
margin: 15px 0;
width: auto;
padding: 0 5px;
}
.asp-eprecaptcha-invisible {
height: 0;
margin: 0 auto;
}
.asp-eprecaptcha-container div {
margin: 0 auto;
height: 78px;
}
#eprecaptcha-error {
text-align: center;
}
#asp-eprecaptcha-google-notice {
font-size: 75%;
color: gray;
text-align: center;
margin: 5px 0;
opacity: 0.75;
}
</style>
<div id="asp-eprecaptcha-container" class="asp-eprecaptcha-container"></div>
<div id="eprecaptcha-error" class="form-err" role="alert">
</div>
<?php
$out .= ob_get_clean();
return $out;
}
public function data_ready( $data, $atts ) {
$data['addonHooks'] = isset( $data['addonHooks'] ) ? $data['addonHooks'] : array();
array_push( $data['addonHooks'], 'recaptcha' );
$data['eprecaptchaSiteKey'] = $this->asp_main->get_setting( 'eprecaptcha_site_key' );
return $data;
}
public function ng_data_ready( $data, $atts ) {
if ( $this->enabled && ! $this->keys_entered ) {
$data['fatal_error'] = __( 'Please enter Enterprise reCaptcha keys.', 'stripe-payments' );
}
$addon = array(
'name' => 'epreCaptcha',
'handler' => 'epreCaptchaHandlerNG',
);
$data['addons'][] = $addon;
$data['eprecaptchaSiteKey'] = $this->asp_main->get_setting( 'eprecaptcha_site_key' );
return $data;
}
public function ng_add_scripts( $scripts ) {
$scripts[] = array(
'footer' => true,
'src' => 'https://www.google.com/recaptcha/enterprise.js?onload=onloadCallback&render=explicit',
);
$scripts[] = array(
'footer' => true,
'src' => WP_ASP_PLUGIN_URL . '/includes/eprecaptcha/public/js/asp-eprecaptcha-ng.js?ver=' . WP_ASP_PLUGIN_VERSION,
);
return $scripts;
}
public function ng_button_output_after_button( $output, $data, $class ) {
$prefetch = $this->asp_main->get_setting( 'frontend_prefetch_scripts' );
if ( $prefetch ) {
if ( empty( $this->asp_main->sc_scripts_prefetched ) ) {
if ( ! isset( $this->asp_main->footer_scripts ) ) {
$this->asp_main->footer_scripts = '';
}
$this->asp_main->footer_scripts .= '<link rel="prefetch" as="script" href="https://www.google.com/recaptcha/enterprise.js?onload=onloadCallback&render=explicit" />';
$this->asp_main->footer_scripts .= '<link rel="prefetch" as="script" href="' . WP_ASP_PLUGIN_URL . '/includes/eprecaptcha/public/js/asp-eprecaptcha-ng.js?ver=' . WP_ASP_PLUGIN_VERSION . '" />';
}
}
return $output;
}
public function before_payment_processing( $ret, $post ) {
if ( ! isset( $post['eprecaptchaKey'] ) || empty( $post['eprecaptchaKey'] ) ) {
$ret['error'] = __( 'Enterprise reCaptcha: missing user response data.', 'stripe-payments' );
return $ret;
}
$payload = sanitize_text_field( $post['eprecaptchaKey'] );
$ret = $this->check_eprecatpcha( $payload );
return $ret;
}
public function output_styles( $output ) {
ob_start();
?>
<style>
.asp-recaptcha-modal {
display: none;
max-width: 350px !important;
min-width: 314px;
}
.asp-recaptcha-container {
height: 100px;
margin: 0 auto;
margin-top: 15px;
width: auto;
padding: 0 5px;
}
@media (max-width: 600px) {
/* Scale down the captcha size for mobile devices */
.asp-recaptcha-container {
transform: scale(0.77);
/* if the theme has overflow:auto on body, then the captcha will be cut off, so we need to set overflow to visible */
overflow: visible !important;
}
}
.asp-recaptcha-container div {
margin: 0 auto;
height: 78px;
}
div.asp-recaptcha-modal div.iziModal-header {
background: #3795cb none repeat scroll 0% 0% !important;
}
</style>
<?php
$output .= ob_get_clean();
return $output;
}
public function after_button( $output, $data, $class ) {
ob_start();
?>
<div id="asp-eprecaptcha-modal-<?php echo esc_attr( $data['uniq_id'] ); ?>" class="asp-eprecaptcha-modal">
<div id="asp-eprecaptcha-container-<?php echo esc_attr( $data['uniq_id'] ); ?>" class="asp-eprecaptcha-container"></div>
</div>
<?php
$output .= ob_get_clean();
return $output;
}
public function register_script() {
wp_register_script( 'asp-eprecaptcha-eprecaptcha', 'https://www.google.com/recaptcha/enterprise.js?render=explicit', array(), null, true );
wp_register_script( 'asp-eprecaptcha-handler', WP_ASP_PLUGIN_URL . '/includes/eprecaptcha/public/js/asp-eprecaptcha-script.js', array( 'asp-eprecaptcha-recaptcha', 'jquery' ), WP_ASP_PLUGIN_VERSION, true );
wp_register_script( 'aspapm-iziModal', WP_ASP_PLUGIN_URL . '/includes/eprecaptcha/public/js/iziModal.min.js', 'jquery', WP_ASP_PLUGIN_VERSION, true );
wp_register_style( 'aspapm-iziModal-css', WP_ASP_PLUGIN_URL . '/includes/eprecaptcha/public/css/iziModal.min.css', null, WP_ASP_PLUGIN_VERSION );
}
public function enqueue_script() {
wp_enqueue_script( 'asp-eprecaptcha-eprecaptcha' );
wp_enqueue_script( 'asp-eprecaptcha-handler' );
wp_enqueue_script( 'aspapm-iziModal' );
wp_enqueue_style( 'aspapm-iziModal-css' );
}
}
new ASP_EPRECAPTCHA_Main();

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More