Version Description
- BUG: Fixed typos in pmpro_memberslist_csv and pmpro_orderscsv capabilities. (Thanks, Arnaud Devic)
- BUG: Only loading the Braintree API when using it now.
- BUG: Fixed fatal error that would occur at checkout if PayPal Standard were used with a discount code. (Thanks, John Zeiger)
- BUG: Fixed issue where discount codes would not work if billing address fields were hidden. (e.g. paying by PayPal or check)
- BUG: Fixed issue with the logic around sending emails when admin's change a member's level or expiration date. Admins will always get an email. Members will only get an email if the checkbox is checked.
- ENHANCEMENT: No longer showing check instructions at checkout if the level is free.
- ENHANCEMENT: Added pmpro_stripe_create_subscription filter. (Thanks, nickd32 on GitHub)
- ENHANCEMENT: Added Czech (cs_CZ) language files and support for using decimals as separators. (Thanks, Martin "shr3k" Koke on GitHub)
Download this release
Release Info
Developer | strangerstudios |
Plugin | ![]() |
Version | 1.8.1 |
Comparing to | |
See all releases |
Code changes from version 1.8 to 1.8.1
- adminpages/orders-csv.php +1 -1
- classes/gateways/class.pmprogateway_braintree.php +17 -4
- classes/gateways/class.pmprogateway_paypalstandard.php +1 -1
- classes/gateways/class.pmprogateway_stripe.php +347 -346
- email/admin_change_admin.html +1 -1
- includes/currencies.php +8 -1
- includes/filters.php +8 -0
- includes/functions.php +12 -8
- includes/profile.php +57 -19
- languages/pmpro-cs_CZ.mo +0 -0
- languages/pmpro-cs_CZ.po +2773 -1324
- languages/pmpro.mo +0 -0
- languages/pmpro.po +139 -121
- languages/pmpro.pot +139 -121
- pages/account.php +4 -4
- pages/checkout.php +7 -7
- paid-memberships-pro.php +3 -3
- readme.txt +10 -1
- services/applydiscountcode.php +11 -0
adminpages/orders-csv.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
//only admins can get this
|
3 |
-
if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("
|
4 |
{
|
5 |
die(__("You do not have permissions to perform this action.", "pmpro"));
|
6 |
}
|
1 |
<?php
|
2 |
//only admins can get this
|
3 |
+
if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_orderscsv")))
|
4 |
{
|
5 |
die(__("You do not have permissions to perform this action.", "pmpro"));
|
6 |
}
|
classes/gateways/class.pmprogateway_braintree.php
CHANGED
@@ -3,17 +3,17 @@
|
|
3 |
require_once(dirname(__FILE__) . "/class.pmprogateway.php");
|
4 |
|
5 |
//load classes init method
|
6 |
-
add_action('init', array('PMProGateway_braintree', 'init'));
|
7 |
|
8 |
-
if(!class_exists("Braintree"))
|
9 |
-
require_once(dirname(__FILE__) . "/../../includes/lib/Braintree/Braintree.php");
|
10 |
class PMProGateway_braintree extends PMProGateway
|
11 |
{
|
12 |
function PMProGateway_braintree($gateway = NULL)
|
13 |
-
{
|
14 |
$this->gateway = $gateway;
|
15 |
$this->gateway_environment = pmpro_getOption("gateway_environment");
|
16 |
|
|
|
|
|
17 |
//convert to braintree nomenclature
|
18 |
$environment = $this->gateway_environment;
|
19 |
if($environment == "live")
|
@@ -27,6 +27,19 @@
|
|
27 |
return $this->gateway;
|
28 |
}
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
/**
|
31 |
* Run on WP init
|
32 |
*
|
3 |
require_once(dirname(__FILE__) . "/class.pmprogateway.php");
|
4 |
|
5 |
//load classes init method
|
6 |
+
add_action('init', array('PMProGateway_braintree', 'init'));
|
7 |
|
|
|
|
|
8 |
class PMProGateway_braintree extends PMProGateway
|
9 |
{
|
10 |
function PMProGateway_braintree($gateway = NULL)
|
11 |
+
{
|
12 |
$this->gateway = $gateway;
|
13 |
$this->gateway_environment = pmpro_getOption("gateway_environment");
|
14 |
|
15 |
+
$this->loadBraintreeLibrary();
|
16 |
+
|
17 |
//convert to braintree nomenclature
|
18 |
$environment = $this->gateway_environment;
|
19 |
if($environment == "live")
|
27 |
return $this->gateway;
|
28 |
}
|
29 |
|
30 |
+
/**
|
31 |
+
* Load the Braintree API library.
|
32 |
+
*
|
33 |
+
* @since 1.8.1
|
34 |
+
* Moved into a method in version 1.8.1 so we only load it when needed.
|
35 |
+
*/
|
36 |
+
function loadBraintreeLibrary()
|
37 |
+
{
|
38 |
+
//load Braintree library if it hasn't been loaded already (usually by another plugin using Braintree)
|
39 |
+
if(!class_exists("Braintree"))
|
40 |
+
require_once(dirname(__FILE__) . "/../../includes/lib/Braintree/Braintree.php");
|
41 |
+
}
|
42 |
+
|
43 |
/**
|
44 |
* Run on WP init
|
45 |
*
|
classes/gateways/class.pmprogateway_paypalstandard.php
CHANGED
@@ -220,7 +220,7 @@
|
|
220 |
*/
|
221 |
static function pmpro_checkout_before_change_membership_level($user_id, $morder)
|
222 |
{
|
223 |
-
global $discount_code_id;
|
224 |
|
225 |
//if no order, no need to pay
|
226 |
if(empty($morder))
|
220 |
*/
|
221 |
static function pmpro_checkout_before_change_membership_level($user_id, $morder)
|
222 |
{
|
223 |
+
global $discount_code_id, $wpdb;
|
224 |
|
225 |
//if no order, no need to pay
|
226 |
if(empty($morder))
|
classes/gateways/class.pmprogateway_stripe.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
<?php
|
2 |
//include pmprogateway
|
3 |
-
require_once(dirname(__FILE__) . "/class.pmprogateway.php");
|
4 |
-
|
5 |
//load classes init method
|
6 |
add_action('init', array('PMProGateway_stripe', 'init'));
|
7 |
-
|
8 |
/**
|
9 |
* PMProGateway_stripe Class
|
10 |
*
|
@@ -16,25 +16,25 @@
|
|
16 |
{
|
17 |
/**
|
18 |
* Stripe Class Constructor
|
19 |
-
*
|
20 |
* @since 1.4
|
21 |
*/
|
22 |
function PMProGateway_stripe($gateway = NULL)
|
23 |
{
|
24 |
$this->gateway = $gateway;
|
25 |
$this->gateway_environment = pmpro_getOption("gateway_environment");
|
26 |
-
|
27 |
-
$this->loadStripeLibrary();
|
28 |
Stripe::setApiKey(pmpro_getOption("stripe_secretkey"));
|
29 |
-
|
30 |
return $this->gateway;
|
31 |
-
}
|
32 |
-
|
33 |
/**
|
34 |
* Load the Stripe API library.
|
35 |
-
*
|
36 |
* @since 1.8
|
37 |
-
* Moved into a method in version
|
38 |
*/
|
39 |
function loadStripeLibrary()
|
40 |
{
|
@@ -42,66 +42,66 @@
|
|
42 |
if(!class_exists("Stripe"))
|
43 |
require_once(dirname(__FILE__) . "/../../includes/lib/Stripe/Stripe.php");
|
44 |
}
|
45 |
-
|
46 |
/**
|
47 |
* Run on WP init
|
48 |
-
*
|
49 |
* @since 1.8
|
50 |
*/
|
51 |
static function init()
|
52 |
-
{
|
53 |
//make sure Stripe is a gateway option
|
54 |
add_filter('pmpro_gateways', array('PMProGateway_stripe', 'pmpro_gateways'));
|
55 |
-
|
56 |
//add fields to payment settings
|
57 |
add_filter('pmpro_payment_options', array('PMProGateway_stripe', 'pmpro_payment_options'));
|
58 |
add_filter('pmpro_payment_option_fields', array('PMProGateway_stripe', 'pmpro_payment_option_fields'), 10, 2);
|
59 |
-
|
60 |
//add some fields to edit user page (Updates)
|
61 |
add_action('pmpro_after_membership_level_profile_fields', array('PMProGateway_stripe', 'user_profile_fields'));
|
62 |
add_action('profile_update', array('PMProGateway_stripe', 'user_profile_fields_save'));
|
63 |
-
|
64 |
//old global RE showing billing address or not
|
65 |
global $pmpro_stripe_lite;
|
66 |
$pmpro_stripe_lite = apply_filters("pmpro_stripe_lite", !pmpro_getOption("stripe_billingaddress")); //default is oposite of the stripe_billingaddress setting
|
67 |
-
|
68 |
//updates cron
|
69 |
add_action('pmpro_activation', array('PMProGateway_stripe', 'pmpro_activation'));
|
70 |
add_action('pmpro_deactivation', array('PMProGateway_stripe', 'pmpro_deactivation'));
|
71 |
add_action('pmpro_cron_stripe_subscription_updates', array('PMProGateway_stripe', 'pmpro_cron_stripe_subscription_updates'));
|
72 |
-
|
73 |
//code to add at checkout if Stripe is the current gateway
|
74 |
$gateway = pmpro_getOption("gateway");
|
75 |
if($gateway == "stripe")
|
76 |
{
|
77 |
-
add_action('pmpro_checkout_preheader', array('PMProGateway_stripe', 'pmpro_checkout_preheader'));
|
78 |
add_filter('pmpro_checkout_order', array('PMProGateway_stripe', 'pmpro_checkout_order'));
|
79 |
add_filter('pmpro_include_billing_address_fields', array('PMProGateway_stripe', 'pmpro_include_billing_address_fields'));
|
80 |
add_filter('pmpro_include_cardtype_field', array('PMProGateway_stripe', 'pmpro_include_billing_address_fields'));
|
81 |
add_filter('pmpro_include_payment_information_fields', array('PMProGateway_stripe', 'pmpro_include_payment_information_fields'));
|
82 |
}
|
83 |
}
|
84 |
-
|
85 |
/**
|
86 |
* Make sure Stripe is in the gateways list
|
87 |
-
*
|
88 |
* @since 1.8
|
89 |
*/
|
90 |
static function pmpro_gateways($gateways)
|
91 |
{
|
92 |
if(empty($gateways['stripe']))
|
93 |
$gateways['stripe'] = __('Stripe', 'pmpro');
|
94 |
-
|
95 |
return $gateways;
|
96 |
}
|
97 |
-
|
98 |
/**
|
99 |
* Get a list of payment options that the Stripe gateway needs/supports.
|
100 |
-
*
|
101 |
* @since 1.8
|
102 |
*/
|
103 |
static function getGatewayOptions()
|
104 |
-
{
|
105 |
$options = array(
|
106 |
'sslseal',
|
107 |
'nuclear_HTTPS',
|
@@ -115,35 +115,35 @@
|
|
115 |
'tax_rate',
|
116 |
'accepted_credit_cards'
|
117 |
);
|
118 |
-
|
119 |
return $options;
|
120 |
}
|
121 |
-
|
122 |
/**
|
123 |
* Set payment options for payment settings page.
|
124 |
-
*
|
125 |
* @since 1.8
|
126 |
*/
|
127 |
static function pmpro_payment_options($options)
|
128 |
-
{
|
129 |
//get stripe options
|
130 |
$stripe_options = PMProGateway_stripe::getGatewayOptions();
|
131 |
-
|
132 |
//merge with others.
|
133 |
$options = array_merge($stripe_options, $options);
|
134 |
-
|
135 |
return $options;
|
136 |
}
|
137 |
-
|
138 |
/**
|
139 |
* Display fields for Stripe options.
|
140 |
-
*
|
141 |
* @since 1.8
|
142 |
*/
|
143 |
static function pmpro_payment_option_fields($values, $gateway)
|
144 |
{
|
145 |
?>
|
146 |
-
<tr class="pmpro_settings_divider gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
|
147 |
<td colspan="2">
|
148 |
<?php _e('Stripe Settings', 'pmpro'); ?>
|
149 |
</td>
|
@@ -171,7 +171,7 @@
|
|
171 |
<td>
|
172 |
<select id="stripe_billingaddress" name="stripe_billingaddress">
|
173 |
<option value="0" <?php if(empty($values['stripe_billingaddress'])) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
|
174 |
-
<option value="1" <?php if(!empty($values['stripe_billingaddress'])) { ?>selected="selected"<?php } ?>><?php _e('Yes', 'pmpro');?></option>
|
175 |
</select>
|
176 |
<small><?php _e("Stripe doesn't require billing address fields. Choose 'No' to hide them on the checkout page.<br /><strong>If No, make sure you disable address verification in the Stripe dashboard settings.</strong>", 'pmpro');?></small>
|
177 |
</td>
|
@@ -183,39 +183,39 @@
|
|
183 |
<td>
|
184 |
<p><?php _e('To fully integrate with Stripe, be sure to set your Web Hook URL to', 'pmpro');?> <pre><?php echo admin_url("admin-ajax.php") . "?action=stripe_webhook";?></pre></p>
|
185 |
</td>
|
186 |
-
</tr>
|
187 |
<?php
|
188 |
}
|
189 |
-
|
190 |
/**
|
191 |
* Code added to checkout preheader.
|
192 |
-
*
|
193 |
* @since 1.8
|
194 |
*/
|
195 |
static function pmpro_checkout_preheader()
|
196 |
-
{
|
197 |
global $gateway, $pmpro_level;
|
198 |
-
|
199 |
if($gateway == "stripe" && !pmpro_isLevelFree($pmpro_level))
|
200 |
{
|
201 |
//stripe js library
|
202 |
wp_enqueue_script("stripe", "https://js.stripe.com/v2/", array(), NULL);
|
203 |
-
|
204 |
//stripe js code for checkout
|
205 |
function pmpro_stripe_javascript()
|
206 |
{
|
207 |
global $pmpro_gateway, $pmpro_level, $pmpro_stripe_lite;
|
208 |
?>
|
209 |
<script type="text/javascript">
|
210 |
-
// this identifies your website in the createToken call below
|
211 |
Stripe.setPublishableKey('<?php echo pmpro_getOption("stripe_publishablekey"); ?>');
|
212 |
-
|
213 |
-
var pmpro_require_billing = true;
|
214 |
-
|
215 |
jQuery(document).ready(function() {
|
216 |
jQuery("#pmpro_form, .pmpro_form").submit(function(event) {
|
217 |
-
|
218 |
-
//double check in case a discount code made the level free
|
219 |
if(pmpro_require_billing)
|
220 |
{
|
221 |
//build array for creating token
|
@@ -231,18 +231,18 @@
|
|
231 |
?>
|
232 |
,address_line1: jQuery('#baddress1').val(),
|
233 |
address_line2: jQuery('#baddress2').val(),
|
234 |
-
address_city: jQuery('#bcity').val(),
|
235 |
-
address_state: jQuery('#bstate').val(),
|
236 |
-
address_zip: jQuery('#bzipcode').val(),
|
237 |
address_country: jQuery('#bcountry').val()
|
238 |
<?php
|
239 |
}
|
240 |
-
?>
|
241 |
};
|
242 |
-
|
243 |
if (jQuery('#bfirstname').length && jQuery('#blastname').length)
|
244 |
args['name'] = jQuery.trim(jQuery('#bfirstname').val() + ' ' + jQuery('#blastname').val());
|
245 |
-
|
246 |
//create token
|
247 |
Stripe.createToken(args, stripeResponseHandler);
|
248 |
|
@@ -261,19 +261,19 @@
|
|
261 |
|
262 |
//hide processing message
|
263 |
jQuery('#pmpro_processing_message').css('visibility', 'hidden');
|
264 |
-
|
265 |
// show the errors on the form
|
266 |
alert(response.error.message);
|
267 |
jQuery(".payment-errors").text(response.error.message);
|
268 |
} else {
|
269 |
-
var form$ = jQuery("#pmpro_form, .pmpro_form");
|
270 |
// token contains id, last4, and card type
|
271 |
-
var token = response['id'];
|
272 |
// insert the token into the form so it gets submitted to the server
|
273 |
form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
|
274 |
-
|
275 |
console.log(response);
|
276 |
-
|
277 |
//insert fields for other card fields
|
278 |
if(jQuery('#CardType[name=CardType]').length)
|
279 |
jQuery('#CardType').val(response['card']['brand']);
|
@@ -281,8 +281,8 @@
|
|
281 |
form$.append("<input type='hidden' name='CardType' value='" + response['card']['brand'] + "'/>");
|
282 |
form$.append("<input type='hidden' name='AccountNumber' value='XXXXXXXXXXXXX" + response['card']['last4'] + "'/>");
|
283 |
form$.append("<input type='hidden' name='ExpirationMonth' value='" + ("0" + response['card']['exp_month']).slice(-2) + "'/>");
|
284 |
-
form$.append("<input type='hidden' name='ExpirationYear' value='" + response['card']['exp_year'] + "'/>");
|
285 |
-
|
286 |
// and submit
|
287 |
form$.get(0).submit();
|
288 |
}
|
@@ -291,20 +291,20 @@
|
|
291 |
<?php
|
292 |
}
|
293 |
add_action("wp_head", "pmpro_stripe_javascript");
|
294 |
-
|
295 |
//don't require the CVV
|
296 |
function pmpro_stripe_dont_require_CVV($fields)
|
297 |
{
|
298 |
-
unset($fields['CVV']);
|
299 |
return $fields;
|
300 |
}
|
301 |
add_filter("pmpro_required_billing_fields", "pmpro_stripe_dont_require_CVV");
|
302 |
}
|
303 |
}
|
304 |
-
|
305 |
/**
|
306 |
* Filtering orders at checkout.
|
307 |
-
*
|
308 |
* @since 1.8
|
309 |
*/
|
310 |
static function pmpro_checkout_order($morder)
|
@@ -314,13 +314,13 @@
|
|
314 |
{
|
315 |
$morder->stripeToken = $_REQUEST['stripeToken'];
|
316 |
}
|
317 |
-
|
318 |
//stripe lite code to get name from other sources if available
|
319 |
global $pmpro_stripe_lite, $current_user;
|
320 |
if(!empty($pmpro_stripe_lite) && empty($morder->FirstName) && empty($morder->LastName))
|
321 |
{
|
322 |
if(!empty($current_user->ID))
|
323 |
-
{
|
324 |
$morder->FirstName = get_user_meta($current_user->ID, "first_name", true);
|
325 |
$morder->LastName = get_user_meta($current_user->ID, "last_name", true);
|
326 |
}
|
@@ -330,19 +330,19 @@
|
|
330 |
$morder->LastName = $_REQUEST['last_name'];
|
331 |
}
|
332 |
}
|
333 |
-
|
334 |
return $morder;
|
335 |
}
|
336 |
-
|
337 |
/**
|
338 |
* Code to run after checkout
|
339 |
-
*
|
340 |
* @since 1.8
|
341 |
*/
|
342 |
-
static function pmpro_after_checkout($user_id, $morder)
|
343 |
{
|
344 |
global $gateway;
|
345 |
-
|
346 |
if($gateway == "stripe")
|
347 |
{
|
348 |
if(!empty($morder) && !empty($morer->Gateway) && !empty($morder->Gateway->customer) && !empty($morder->Gateway->customer->id))
|
@@ -351,7 +351,7 @@
|
|
351 |
}
|
352 |
}
|
353 |
}
|
354 |
-
|
355 |
/**
|
356 |
* Check settings if billing address should be shown.
|
357 |
* @since 1.8
|
@@ -361,24 +361,24 @@
|
|
361 |
//check settings RE showing billing address
|
362 |
if(!pmpro_getOption("stripe_billingaddress"))
|
363 |
$include = false;
|
364 |
-
|
365 |
return $include;
|
366 |
}
|
367 |
-
|
368 |
/**
|
369 |
* Use our own payment fields at checkout. (Remove the name attributes.)
|
370 |
* @since 1.8
|
371 |
*/
|
372 |
static function pmpro_include_payment_information_fields($include)
|
373 |
-
{
|
374 |
//global vars
|
375 |
global $pmpro_requirebilling, $pmpro_show_discount_code, $discount_code, $CardType, $AccountNumber, $ExpirationMonth, $ExpirationYear;
|
376 |
-
|
377 |
//get accepted credit cards
|
378 |
$pmpro_accepted_credit_cards = pmpro_getOption("accepted_credit_cards");
|
379 |
$pmpro_accepted_credit_cards = explode(",", $pmpro_accepted_credit_cards);
|
380 |
-
$pmpro_accepted_credit_cards_string = pmpro_implodeToEnglish($pmpro_accepted_credit_cards);
|
381 |
-
|
382 |
//include ours
|
383 |
?>
|
384 |
<table id="pmpro_payment_information_fields" class="pmpro_checkout top1em" width="100%" cellpadding="0" cellspacing="0" border="0" <?php if(!$pmpro_requirebilling || apply_filters("pmpro_hide_payment_information_fields", false) ) { ?>style="display: none;"<?php } ?>>
|
@@ -388,8 +388,8 @@
|
|
388 |
</tr>
|
389 |
</thead>
|
390 |
<tbody>
|
391 |
-
<tr valign="top">
|
392 |
-
<td>
|
393 |
<?php
|
394 |
$sslseal = pmpro_getOption("sslseal");
|
395 |
if($sslseal)
|
@@ -409,7 +409,7 @@
|
|
409 |
<select id="CardType" class=" <?php echo pmpro_getClassForField("CardType");?>">
|
410 |
<?php foreach($pmpro_accepted_credit_cards as $cc) { ?>
|
411 |
<option value="<?php echo $cc?>" <?php if($CardType == $cc) { ?>selected="selected"<?php } ?>><?php echo $cc?></option>
|
412 |
-
<?php } ?>
|
413 |
</select>
|
414 |
</div>
|
415 |
<?php
|
@@ -419,8 +419,8 @@
|
|
419 |
?>
|
420 |
<input type="hidden" id="CardType" name="CardType" value="<?php echo esc_attr($CardType);?>" />
|
421 |
<script>
|
422 |
-
jQuery(document).ready(function() {
|
423 |
-
jQuery('#AccountNumber').validateCreditCard(function(result) {
|
424 |
var cardtypenames = {
|
425 |
"amex":"American Express",
|
426 |
"diners_club_carte_blanche":"Diners Club Carte Blanche",
|
@@ -433,23 +433,23 @@
|
|
433 |
"visa":"Visa",
|
434 |
"visa_electron":"Visa Electron"
|
435 |
}
|
436 |
-
|
437 |
if(result.card_type)
|
438 |
jQuery('#CardType').val(cardtypenames[result.card_type.name]);
|
439 |
else
|
440 |
jQuery('#CardType').val('Unknown Card Type');
|
441 |
-
});
|
442 |
});
|
443 |
</script>
|
444 |
<?php
|
445 |
}
|
446 |
?>
|
447 |
-
|
448 |
<div class="pmpro_payment-account-number">
|
449 |
<label for="AccountNumber"><?php _e('Card Number', 'pmpro');?></label>
|
450 |
<input id="AccountNumber" class="input <?php echo pmpro_getClassForField("AccountNumber");?>" type="text" size="25" value="<?php echo esc_attr($AccountNumber)?>" autocomplete="off" />
|
451 |
</div>
|
452 |
-
|
453 |
<div class="pmpro_payment-expiration">
|
454 |
<label for="ExpirationMonth"><?php _e('Expiration Date', 'pmpro');?></label>
|
455 |
<select id="ExpirationMonth" class=" <?php echo pmpro_getClassForField("ExpirationMonth");?>">
|
@@ -474,9 +474,9 @@
|
|
474 |
<?php
|
475 |
}
|
476 |
?>
|
477 |
-
</select>
|
478 |
</div>
|
479 |
-
|
480 |
<?php
|
481 |
$pmpro_show_cvv = apply_filters("pmpro_show_cvv", true);
|
482 |
if($pmpro_show_cvv)
|
@@ -489,7 +489,7 @@
|
|
489 |
<?php
|
490 |
}
|
491 |
?>
|
492 |
-
|
493 |
<?php if($pmpro_show_discount_code) { ?>
|
494 |
<div class="pmpro_payment-discount-code">
|
495 |
<label for="discount_code"><?php _e('Discount Code', 'pmpro');?></label>
|
@@ -498,20 +498,20 @@
|
|
498 |
<p id="discount_code_message" class="pmpro_message" style="display: none;"></p>
|
499 |
</div>
|
500 |
<?php } ?>
|
501 |
-
|
502 |
-
</td>
|
503 |
</tr>
|
504 |
</tbody>
|
505 |
</table>
|
506 |
<?php
|
507 |
-
|
508 |
//don't include the default
|
509 |
return false;
|
510 |
}
|
511 |
-
|
512 |
/**
|
513 |
* Fields shown on edit user page
|
514 |
-
*
|
515 |
* @since 1.8
|
516 |
*/
|
517 |
static function user_profile_fields($user)
|
@@ -521,48 +521,48 @@
|
|
521 |
$cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
|
522 |
$current_year = date("Y");
|
523 |
$current_month = date("m");
|
524 |
-
|
525 |
//make sure the current user has privileges
|
526 |
$membership_level_capability = apply_filters("pmpro_edit_member_capability", "manage_options");
|
527 |
if(!current_user_can($membership_level_capability))
|
528 |
return false;
|
529 |
|
530 |
-
//more privelges they should have
|
531 |
$show_membership_level = apply_filters("pmpro_profile_show_membership_level", true, $user);
|
532 |
if(!$show_membership_level)
|
533 |
return false;
|
534 |
-
|
535 |
//check that user has a current subscription at Stripe
|
536 |
$last_order = new MemberOrder();
|
537 |
$last_order->getLastMemberOrder($user->ID);
|
538 |
-
|
539 |
//assume no sub to start
|
540 |
$sub = false;
|
541 |
-
|
542 |
//check that gateway is Stripe
|
543 |
if($last_order->gateway == "stripe")
|
544 |
-
{
|
545 |
//is there a customer?
|
546 |
-
$sub = $last_order->Gateway->getSubscription($last_order);
|
547 |
-
}
|
548 |
-
|
549 |
$customer_id = $user->pmpro_stripe_customerid;
|
550 |
-
|
551 |
if(empty($sub))
|
552 |
{
|
553 |
//make sure we delete stripe updates
|
554 |
update_user_meta($user->ID, "pmpro_stripe_updates", array());
|
555 |
-
|
556 |
//if the last order has a sub id, let the admin know there is no sub at Stripe
|
557 |
if(!empty($last_order) && $last_order->gateway == "stripe" && !empty($last_order->subscription_transaction_id) && strpos($last_order->subscription_transaction_id, "sub_") !== false)
|
558 |
{
|
559 |
?>
|
560 |
<p><strong>Note:</strong> Subscription <strong><?php echo $last_order->subscription_transaction_id;?></strong> could not be found at Stripe. It might have been deleted.</p>
|
561 |
<?php
|
562 |
-
}
|
563 |
}
|
564 |
-
else
|
565 |
-
{
|
566 |
?>
|
567 |
<h3><?php _e("Subscription Updates", "pmpro"); ?></h3>
|
568 |
<p>
|
@@ -578,7 +578,7 @@
|
|
578 |
<th><label for="membership_level"><?php _e("Update", "pmpro"); ?></label></th>
|
579 |
<td id="updates_td">
|
580 |
<?php
|
581 |
-
$old_updates = $user->pmpro_stripe_updates;
|
582 |
if(is_array($old_updates))
|
583 |
{
|
584 |
$updates = array_merge(
|
@@ -588,19 +588,19 @@
|
|
588 |
}
|
589 |
else
|
590 |
$updates = array(array('template'=>true, 'when'=>'now', 'date_month'=>'', 'date_day'=>'', 'date_year'=>'', 'billing_amount'=>'', 'cycle_number'=>'', 'cycle_period'=>'Month'));
|
591 |
-
|
592 |
foreach($updates as $update)
|
593 |
{
|
594 |
?>
|
595 |
<div class="updates_update" <?php if(!empty($update['template'])) { ?>style="display: none;"<?php } ?>>
|
596 |
-
<select class="updates_when" name="updates_when[]">
|
597 |
<option value="now" <?php selected($update['when'], "now");?>>Now</option>
|
598 |
<option value="payment" <?php selected($update['when'], "payment");?>>After Next Payment</option>
|
599 |
<option value="date" <?php selected($update['when'], "date");?>>On Date</option>
|
600 |
</select>
|
601 |
<span class="updates_date" <?php if($uwhen != "date") { ?>style="display: none;"<?php } ?>>
|
602 |
<select name="updates_date_month[]">
|
603 |
-
<?php
|
604 |
for($i = 1; $i < 13; $i++)
|
605 |
{
|
606 |
?>
|
@@ -619,7 +619,7 @@
|
|
619 |
<small><?php _e('per', 'pmpro');?></small>
|
620 |
<input name="updates_cycle_number[]" type="text" size="5" value="<?php echo esc_attr($update['cycle_number']);?>" />
|
621 |
<select name="updates_cycle_period[]">
|
622 |
-
<?php
|
623 |
foreach ( $cycles as $name => $value ) {
|
624 |
echo "<option value='$value'";
|
625 |
if(!empty($update['cycle_period']) && $update['cycle_period'] == $value) echo " selected='selected'";
|
@@ -627,18 +627,18 @@
|
|
627 |
}
|
628 |
?>
|
629 |
</select>
|
630 |
-
</span>
|
631 |
<span>
|
632 |
-
<a class="updates_remove" href="javascript:void(0);">Remove</a>
|
633 |
</span>
|
634 |
</div>
|
635 |
<?php
|
636 |
}
|
637 |
-
?>
|
638 |
<p><a id="updates_new_update" href="javascript:void(0);">+ New Update</a></p>
|
639 |
</td>
|
640 |
-
</tr>
|
641 |
-
</table>
|
642 |
<script>
|
643 |
jQuery(document).ready(function() {
|
644 |
//function to update dropdowns/etc based on when field
|
@@ -648,45 +648,45 @@
|
|
648 |
jQuery(when).parent().children('.updates_date').show();
|
649 |
else
|
650 |
jQuery(when).parent().children('.updates_date').hide();
|
651 |
-
|
652 |
if(jQuery(when).val() == 'no')
|
653 |
jQuery(when).parent().children('.updates_billing').hide();
|
654 |
else
|
655 |
jQuery(when).parent().children('.updates_billing').show();
|
656 |
-
}
|
657 |
|
658 |
//and update on page load
|
659 |
jQuery('.updates_when').each(function() { if(jQuery(this).parent().css('display') != 'none') updateSubscriptionUpdateFields(this); });
|
660 |
-
|
661 |
//add a new update when clicking to
|
662 |
var num_updates_divs = <?php echo count($updates);?>;
|
663 |
jQuery('#updates_new_update').click(function() {
|
664 |
//get updates
|
665 |
updates = jQuery('.updates_update').toArray();
|
666 |
-
|
667 |
//clone the first one
|
668 |
-
new_div = jQuery(updates[0]).clone();
|
669 |
-
|
670 |
//append
|
671 |
new_div.insertBefore('#updates_new_update');
|
672 |
-
|
673 |
//update events
|
674 |
addUpdateEvents()
|
675 |
-
|
676 |
//unhide it
|
677 |
new_div.show();
|
678 |
-
updateSubscriptionUpdateFields(new_div.children('.updates_when'));
|
679 |
});
|
680 |
-
|
681 |
function addUpdateEvents()
|
682 |
{
|
683 |
//update when when changes
|
684 |
jQuery('.updates_when').change(function() {
|
685 |
updateSubscriptionUpdateFields(this);
|
686 |
});
|
687 |
-
|
688 |
//remove updates when clicking
|
689 |
-
jQuery('.updates_remove').click(function() {
|
690 |
jQuery(this).parent().parent().remove();
|
691 |
});
|
692 |
}
|
@@ -696,40 +696,40 @@
|
|
696 |
<?php
|
697 |
}
|
698 |
}
|
699 |
-
|
700 |
/**
|
701 |
* Process fields from the edit user page
|
702 |
-
*
|
703 |
* @since 1.8
|
704 |
*/
|
705 |
static function user_profile_fields_save($user_id)
|
706 |
{
|
707 |
global $wpdb;
|
708 |
-
|
709 |
//check capabilities
|
710 |
$membership_level_capability = apply_filters("pmpro_edit_member_capability", "manage_options");
|
711 |
if(!current_user_can($membership_level_capability))
|
712 |
return false;
|
713 |
-
|
714 |
//make sure some value was passed
|
715 |
if(!isset($_POST['updates_when']) || !is_array($_POST['updates_when']))
|
716 |
return;
|
717 |
-
|
718 |
//vars
|
719 |
$updates = array();
|
720 |
$next_on_date_update = "";
|
721 |
-
|
722 |
//build array of updates (we skip the first because it's the template field for the JavaScript
|
723 |
for($i = 1; $i < count($_POST['updates_when']); $i++)
|
724 |
{
|
725 |
$update = array();
|
726 |
-
|
727 |
//all updates have these values
|
728 |
$update['when'] = $_POST['updates_when'][$i];
|
729 |
$update['billing_amount'] = $_POST['updates_billing_amount'][$i];
|
730 |
$update['cycle_number'] = $_POST['updates_cycle_number'][$i];
|
731 |
$update['cycle_period'] = $_POST['updates_cycle_period'][$i];
|
732 |
-
|
733 |
//these values only for on date updates
|
734 |
if($_POST['updates_when'][$i] == "date")
|
735 |
{
|
@@ -737,17 +737,17 @@
|
|
737 |
$update['date_day'] = str_pad($_POST['updates_date_day'][$i], 2, "0", STR_PAD_LEFT);
|
738 |
$update['date_year'] = $_POST['updates_date_year'][$i];
|
739 |
}
|
740 |
-
|
741 |
//make sure the update is valid
|
742 |
if(empty($update['cycle_number']))
|
743 |
continue;
|
744 |
-
|
745 |
//if when is now, update the subscription
|
746 |
if($update['when'] == "now")
|
747 |
{
|
748 |
//get level for user
|
749 |
$user_level = pmpro_getMembershipLevelForUser($user_id);
|
750 |
-
|
751 |
//get current plan at Stripe to get payment date
|
752 |
$last_order = new MemberOrder();
|
753 |
$last_order->getLastMemberOrder($user_id);
|
@@ -755,30 +755,30 @@
|
|
755 |
$last_order->Gateway->getCustomer($last_order);
|
756 |
|
757 |
$subscription = $last_order->Gateway->getSubscription($last_order);
|
758 |
-
|
759 |
if(!empty($subscription))
|
760 |
-
{
|
761 |
$end_timestamp = $subscription->current_period_end;
|
762 |
-
|
763 |
-
//cancel the old subscription
|
764 |
if(!$last_order->Gateway->cancelSubscriptionAtGateway($subscription))
|
765 |
{
|
766 |
//throw error and halt save
|
767 |
-
function pmpro_stripe_user_profile_fields_save_error($errors, $update, $user)
|
768 |
{
|
769 |
$errors->add('pmpro_stripe_updates',__('Could not cancel the old subscription. Updates have not been processed.', 'pmpro'));
|
770 |
}
|
771 |
add_filter('user_profile_update_errors', 'pmpro_stripe_user_profile_fields_save_error', 10, 3);
|
772 |
-
|
773 |
//stop processing updates
|
774 |
return;
|
775 |
}
|
776 |
}
|
777 |
-
|
778 |
//if we didn't get an end date, let's set one one cycle out
|
779 |
if(empty($end_timestamp))
|
780 |
$end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period'], current_time('timestamp'));
|
781 |
-
|
782 |
//build order object
|
783 |
$update_order = new MemberOrder();
|
784 |
$update_order->setGateway('stripe');
|
@@ -789,14 +789,14 @@
|
|
789 |
$update_order->PaymentAmount = $update['billing_amount'];
|
790 |
$update_order->ProfileStartDate = date("Y-m-d", $end_timestamp);
|
791 |
$update_order->BillingPeriod = $update['cycle_period'];
|
792 |
-
$update_order->BillingFrequency = $update['cycle_number'];
|
793 |
-
|
794 |
//need filter to reset ProfileStartDate
|
795 |
add_filter('pmpro_profile_start_date', create_function('$startdate, $order', 'return "' . $update_order->ProfileStartDate . 'T0:0:0";'), 10, 2);
|
796 |
-
|
797 |
//update subscription
|
798 |
$update_order->Gateway->subscribe($update_order, false);
|
799 |
-
|
800 |
//update membership
|
801 |
$sqlQuery = "UPDATE $wpdb->pmpro_memberships_users
|
802 |
SET billing_amount = '" . esc_sql($update['billing_amount']) . "',
|
@@ -808,13 +808,13 @@
|
|
808 |
AND membership_id = '" . esc_sql($last_order->membership_id) . "'
|
809 |
AND status = 'active'
|
810 |
LIMIT 1";
|
811 |
-
|
812 |
$wpdb->query($sqlQuery);
|
813 |
-
|
814 |
//save order so we know which plan to look for at stripe (order code = plan id)
|
815 |
$update_order->status = "success";
|
816 |
$update_order->saveOrder();
|
817 |
-
|
818 |
continue;
|
819 |
}
|
820 |
elseif($update['when'] == 'date')
|
@@ -824,41 +824,41 @@
|
|
824 |
else
|
825 |
$next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'];
|
826 |
}
|
827 |
-
|
828 |
-
//add to array
|
829 |
-
$updates[] = $update;
|
830 |
}
|
831 |
-
|
832 |
//save in user meta
|
833 |
update_user_meta($user_id, "pmpro_stripe_updates", $updates);
|
834 |
-
|
835 |
//save date of next on-date update to make it easier to query for these in cron job
|
836 |
update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update);
|
837 |
}
|
838 |
-
|
839 |
/**
|
840 |
* Cron activation for subscription updates.
|
841 |
-
*
|
842 |
* @since 1.8
|
843 |
*/
|
844 |
static function pmpro_activation()
|
845 |
{
|
846 |
wp_schedule_event(time(), 'daily', 'pmpro_cron_stripe_subscription_updates');
|
847 |
}
|
848 |
-
|
849 |
/**
|
850 |
* Cron deactivation for subscription updates.
|
851 |
-
*
|
852 |
* @since 1.8
|
853 |
*/
|
854 |
static function pmpro_deactivation()
|
855 |
{
|
856 |
wp_clear_scheduled_hook('pmpro_cron_stripe_subscription_updates');
|
857 |
}
|
858 |
-
|
859 |
/**
|
860 |
* Cron job for subscription updates.
|
861 |
-
*
|
862 |
* @since 1.8
|
863 |
*/
|
864 |
static function pmpro_cron_stripe_subscription_updates()
|
@@ -866,41 +866,41 @@
|
|
866 |
global $wpdb;
|
867 |
|
868 |
//get all updates for today (or before today)
|
869 |
-
$sqlQuery = "SELECT *
|
870 |
-
FROM $wpdb->usermeta
|
871 |
-
WHERE meta_key = 'pmpro_stripe_next_on_date_update'
|
872 |
-
AND meta_value IS NOT NULL
|
873 |
-
AND meta_value < '" . date("Y-m-d", strtotime("+1 day")) . "'";
|
874 |
$updates = $wpdb->get_results($sqlQuery);
|
875 |
-
|
876 |
if(!empty($updates))
|
877 |
-
{
|
878 |
//loop through
|
879 |
foreach($updates as $update)
|
880 |
-
{
|
881 |
//pull values from update
|
882 |
$user_id = $update->user_id;
|
883 |
-
|
884 |
$user = get_userdata($user_id);
|
885 |
$user_updates = $user->pmpro_stripe_updates;
|
886 |
-
$next_on_date_update = "";
|
887 |
-
|
888 |
//loop through updates looking for updates happening today or earlier
|
889 |
foreach($user_updates as $key => $update)
|
890 |
-
{
|
891 |
if($update['when'] == 'date' &&
|
892 |
$update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'] <= date("Y-m-d")
|
893 |
)
|
894 |
{
|
895 |
//get level for user
|
896 |
$user_level = pmpro_getMembershipLevelForUser($user_id);
|
897 |
-
|
898 |
//get current plan at Stripe to get payment date
|
899 |
$last_order = new MemberOrder();
|
900 |
$last_order->getLastMemberOrder($user_id);
|
901 |
$last_order->setGateway('stripe');
|
902 |
$last_order->Gateway->getCustomer($last_order);
|
903 |
-
|
904 |
if(!empty($last_order->Gateway->customer))
|
905 |
{
|
906 |
//find the first subscription
|
@@ -910,10 +910,10 @@
|
|
910 |
$end_timestamp = $first_sub['current_period_end'];
|
911 |
}
|
912 |
}
|
913 |
-
|
914 |
//if we didn't get an end date, let's set one one cycle out
|
915 |
$end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period']);
|
916 |
-
|
917 |
//build order object
|
918 |
$update_order = new MemberOrder();
|
919 |
$update_order->setGateway('stripe');
|
@@ -925,28 +925,28 @@
|
|
925 |
$update_order->ProfileStartDate = date("Y-m-d", $end_timestamp);
|
926 |
$update_order->BillingPeriod = $update['cycle_period'];
|
927 |
$update_order->BillingFrequency = $update['cycle_number'];
|
928 |
-
|
929 |
//update subscription
|
930 |
$update_order->Gateway->subscribe($update_order, false);
|
931 |
-
|
932 |
//update membership
|
933 |
-
$sqlQuery = "UPDATE $wpdb->pmpro_memberships_users
|
934 |
-
SET billing_amount = '" . esc_sql($update['billing_amount']) . "',
|
935 |
-
cycle_number = '" . esc_sql($update['cycle_number']) . "',
|
936 |
-
cycle_period = '" . esc_sql($update['cycle_period']) . "'
|
937 |
-
WHERE user_id = '" . esc_sql($user_id) . "'
|
938 |
-
AND membership_id = '" . esc_sql($last_order->membership_id) . "'
|
939 |
-
AND status = 'active'
|
940 |
LIMIT 1";
|
941 |
-
|
942 |
$wpdb->query($sqlQuery);
|
943 |
-
|
944 |
//save order
|
945 |
$update_order->status = "success";
|
946 |
$update_order->save();
|
947 |
-
|
948 |
//remove update from list
|
949 |
-
unset($user_updates[$key]);
|
950 |
}
|
951 |
elseif($update['when'] == 'date')
|
952 |
{
|
@@ -957,19 +957,19 @@
|
|
957 |
$next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'];
|
958 |
}
|
959 |
}
|
960 |
-
|
961 |
//save updates in case we removed some
|
962 |
update_user_meta($user_id, "pmpro_stripe_updates", $user_updates);
|
963 |
-
|
964 |
//save date of next on-date update to make it easier to query for these in cron job
|
965 |
update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update);
|
966 |
}
|
967 |
}
|
968 |
}
|
969 |
-
|
970 |
/**
|
971 |
* Process checkout and decide if a charge and or subscribe is needed
|
972 |
-
*
|
973 |
* @since 1.4
|
974 |
*/
|
975 |
function process(&$order)
|
@@ -986,7 +986,7 @@
|
|
986 |
if($this->charge($order))
|
987 |
{
|
988 |
if(pmpro_isLevelRecurring($order->membership_level))
|
989 |
-
{
|
990 |
if($this->subscribe($order))
|
991 |
{
|
992 |
//yay!
|
@@ -1001,7 +1001,7 @@
|
|
1001 |
else
|
1002 |
{
|
1003 |
//only a one time charge
|
1004 |
-
$order->status = "success"; //saved on checkout page
|
1005 |
return true;
|
1006 |
}
|
1007 |
}
|
@@ -1011,39 +1011,39 @@
|
|
1011 |
$order->error = __("Unknown error: Initial payment failed.", "pmpro");
|
1012 |
return false;
|
1013 |
}
|
1014 |
-
}
|
1015 |
-
}
|
1016 |
-
|
1017 |
/**
|
1018 |
* Make a one-time charge with Stripe
|
1019 |
-
*
|
1020 |
* @since 1.4
|
1021 |
*/
|
1022 |
function charge(&$order)
|
1023 |
{
|
1024 |
global $pmpro_currency;
|
1025 |
-
|
1026 |
//create a code for the order
|
1027 |
if(empty($order->code))
|
1028 |
$order->code = $order->getRandomCode();
|
1029 |
-
|
1030 |
-
//what amount to charge?
|
1031 |
$amount = $order->InitialPayment;
|
1032 |
-
|
1033 |
//tax
|
1034 |
$order->subtotal = $amount;
|
1035 |
$tax = $order->getTax(true);
|
1036 |
$amount = round((float)$order->subtotal + (float)$tax, 2);
|
1037 |
-
|
1038 |
//create a customer
|
1039 |
$result = $this->getCustomer($order);
|
1040 |
-
|
1041 |
if(empty($result))
|
1042 |
-
{
|
1043 |
//failed to create customer
|
1044 |
return false;
|
1045 |
-
}
|
1046 |
-
|
1047 |
//charge
|
1048 |
try
|
1049 |
{
|
@@ -1063,13 +1063,13 @@
|
|
1063 |
$order->shorterror = $order->error;
|
1064 |
return false;
|
1065 |
}
|
1066 |
-
|
1067 |
if(empty($response["failure_message"]))
|
1068 |
{
|
1069 |
//successful charge
|
1070 |
$order->payment_transaction_id = $response["id"];
|
1071 |
-
$order->updateStatus("success");
|
1072 |
-
return true;
|
1073 |
}
|
1074 |
else
|
1075 |
{
|
@@ -1078,12 +1078,12 @@
|
|
1078 |
$order->error = $response['failure_message'];
|
1079 |
$order->shorterror = $response['failure_message'];
|
1080 |
return false;
|
1081 |
-
}
|
1082 |
}
|
1083 |
-
|
1084 |
/**
|
1085 |
* Get a Stripe customer object.
|
1086 |
-
*
|
1087 |
* If $this->customer is set, it returns it.
|
1088 |
* It first checks if the order has a subscription_transaction_id. If so, that's the customer id.
|
1089 |
* If not, it checks for a user_id on the order and searches for a customer id in the user meta.
|
@@ -1097,42 +1097,42 @@
|
|
1097 |
function getCustomer(&$order = false, $force = false)
|
1098 |
{
|
1099 |
global $current_user;
|
1100 |
-
|
1101 |
//already have it?
|
1102 |
if(!empty($this->customer) && !$force)
|
1103 |
return $this->customer;
|
1104 |
-
|
1105 |
//figure out user_id and user
|
1106 |
if(!empty($order->user_id))
|
1107 |
$user_id = $order->user_id;
|
1108 |
-
|
1109 |
//if no id passed, check the current user
|
1110 |
if(empty($user_id) && !empty($current_user->ID))
|
1111 |
$user_id = $current_user->ID;
|
1112 |
-
|
1113 |
if(!empty($user_id))
|
1114 |
$user = get_userdata($user_id);
|
1115 |
else
|
1116 |
$user = NULL;
|
1117 |
-
|
1118 |
//transaction id?
|
1119 |
if(!empty($order->subscription_transaction_id) && strpos($order->subscription_transaction_id, "cus_") !== false)
|
1120 |
$customer_id = $order->subscription_transaction_id;
|
1121 |
else
|
1122 |
{
|
1123 |
-
//try based on user id
|
1124 |
if(!empty($user_id))
|
1125 |
-
{
|
1126 |
-
$customer_id = get_user_meta($user_id, "pmpro_stripe_customerid", true);
|
1127 |
}
|
1128 |
-
}
|
1129 |
-
|
1130 |
//get name and email values from order in case we update
|
1131 |
$name = trim($order->FirstName . " " . $order->LastName);
|
1132 |
if(empty($name) && !empty($user->ID))
|
1133 |
{
|
1134 |
$name = trim($user->first_name . " " . $user->last_name);
|
1135 |
-
|
1136 |
//still empty?
|
1137 |
if(empty($name))
|
1138 |
$name = $user->user_login;
|
@@ -1140,41 +1140,41 @@
|
|
1140 |
elseif(empty($name))
|
1141 |
$name = "No Name";
|
1142 |
|
1143 |
-
$email = $order->Email;
|
1144 |
if(empty($email) && !empty($user->ID))
|
1145 |
{
|
1146 |
$email = $user->user_email;
|
1147 |
}
|
1148 |
elseif(empty($email))
|
1149 |
$email = "No Email";
|
1150 |
-
|
1151 |
//check for an existing stripe customer
|
1152 |
if(!empty($customer_id))
|
1153 |
{
|
1154 |
try
|
1155 |
{
|
1156 |
$this->customer = Stripe_Customer::retrieve($customer_id);
|
1157 |
-
|
1158 |
//update the customer description and card
|
1159 |
if(!empty($order->stripeToken))
|
1160 |
-
{
|
1161 |
$this->customer->description = $name . " (" . $email . ")";
|
1162 |
$this->customer->email = $email;
|
1163 |
$this->customer->card = $order->stripeToken;
|
1164 |
$this->customer->save();
|
1165 |
}
|
1166 |
-
|
1167 |
return $this->customer;
|
1168 |
}
|
1169 |
catch (Exception $e)
|
1170 |
{
|
1171 |
-
//assume no customer found
|
1172 |
}
|
1173 |
}
|
1174 |
-
|
1175 |
//no customer id, create one
|
1176 |
if(!empty($order->stripeToken))
|
1177 |
-
{
|
1178 |
try
|
1179 |
{
|
1180 |
$this->customer = Stripe_Customer::create(array(
|
@@ -1189,11 +1189,11 @@
|
|
1189 |
$order->shorterror = $order->error;
|
1190 |
return false;
|
1191 |
}
|
1192 |
-
|
1193 |
if(!empty($user_id))
|
1194 |
{
|
1195 |
//user logged in/etc
|
1196 |
-
update_user_meta($user_id, "pmpro_stripe_customerid", $this->customer->id);
|
1197 |
}
|
1198 |
else
|
1199 |
{
|
@@ -1210,29 +1210,29 @@
|
|
1210 |
|
1211 |
return apply_filters('pmpro_stripe_create_customer', $this->customer);
|
1212 |
}
|
1213 |
-
|
1214 |
-
return false;
|
1215 |
}
|
1216 |
-
|
1217 |
/**
|
1218 |
* Get a Stripe subscription from a PMPro order
|
1219 |
-
*
|
1220 |
* @since 1.8
|
1221 |
*/
|
1222 |
-
function getSubscription(&$order)
|
1223 |
{
|
1224 |
global $wpdb;
|
1225 |
-
|
1226 |
//no order?
|
1227 |
if(empty($order) || empty($order->code))
|
1228 |
-
return false;
|
1229 |
-
|
1230 |
$result = $this->getCustomer($order, true); //force so we don't get a cached sub for someone else
|
1231 |
-
|
1232 |
//no customer?
|
1233 |
if(empty($result))
|
1234 |
return false;
|
1235 |
-
|
1236 |
//is there a subscription transaction id pointing to a sub?
|
1237 |
if(!empty($order->subscription_transaction_id) && strpos($order->subscription_transaction_id, "sub_") !== false)
|
1238 |
{
|
@@ -1246,49 +1246,49 @@
|
|
1246 |
$order->shorterror = $order->error;
|
1247 |
return false;
|
1248 |
}
|
1249 |
-
|
1250 |
return $sub;
|
1251 |
-
}
|
1252 |
-
|
1253 |
//find subscription based on customer id and order/plan id
|
1254 |
-
$subscriptions = $this->customer->subscriptions->all();
|
1255 |
-
|
1256 |
//no subscriptions
|
1257 |
if(empty($subscriptions) || empty($subscriptions->data))
|
1258 |
-
return false;
|
1259 |
-
|
1260 |
//we really want to test against the order codes of all orders with the same subscription_transaction_id (customer id)
|
1261 |
$codes = $wpdb->get_col("SELECT code FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . $order->user_id . "' AND subscription_transaction_id = '" . $order->subscription_transaction_id . "' AND status NOT IN('refunded', 'review', 'token', 'error')");
|
1262 |
-
|
1263 |
//find the one for this order
|
1264 |
foreach($subscriptions->data as $sub)
|
1265 |
-
{
|
1266 |
if(in_array($sub->plan->id, $codes))
|
1267 |
{
|
1268 |
return $sub;
|
1269 |
}
|
1270 |
}
|
1271 |
-
|
1272 |
-
//didn't find anything yet
|
1273 |
return false;
|
1274 |
}
|
1275 |
-
|
1276 |
/**
|
1277 |
* Create a new subscription with Stripe
|
1278 |
-
*
|
1279 |
* @since 1.4
|
1280 |
*/
|
1281 |
function subscribe(&$order, $checkout = true)
|
1282 |
{
|
1283 |
global $pmpro_currency;
|
1284 |
-
|
1285 |
//create a code for the order
|
1286 |
if(empty($order->code))
|
1287 |
$order->code = $order->getRandomCode();
|
1288 |
-
|
1289 |
//filter order before subscription. use with care.
|
1290 |
$order = apply_filters("pmpro_subscribe_order", $order, $this);
|
1291 |
-
|
1292 |
//figure out the user
|
1293 |
if(!empty($order->user_id))
|
1294 |
$user_id = $order->user_id;
|
@@ -1297,28 +1297,28 @@
|
|
1297 |
global $current_user;
|
1298 |
$user_id = $current_user->ID;
|
1299 |
}
|
1300 |
-
|
1301 |
//setup customer
|
1302 |
$result = $this->getCustomer($order);
|
1303 |
if(empty($result))
|
1304 |
return false; //error retrieving customer
|
1305 |
-
|
1306 |
//set subscription id to custom id
|
1307 |
$order->subscription_transaction_id = $this->customer['id']; //transaction id is the customer id, we save it in user meta later too
|
1308 |
-
|
1309 |
//figure out the amounts
|
1310 |
$amount = $order->PaymentAmount;
|
1311 |
-
$amount_tax = $order->getTaxForPrice($amount);
|
1312 |
$amount = round((float)$amount + (float)$amount_tax, 2);
|
1313 |
|
1314 |
/*
|
1315 |
There are two parts to the trial. Part 1 is simply the delay until the first payment
|
1316 |
since we are doing the first payment as a separate transaction.
|
1317 |
The second part is the actual "trial" set by the admin.
|
1318 |
-
|
1319 |
Stripe only supports Year or Month for billing periods, but we account for Days and Weeks just in case.
|
1320 |
*/
|
1321 |
-
//figure out the trial length (first payment handled by initial charge)
|
1322 |
if($order->BillingPeriod == "Year")
|
1323 |
$trial_period_days = $order->BillingFrequency * 365; //annual
|
1324 |
elseif($order->BillingPeriod == "Day")
|
@@ -1327,18 +1327,18 @@
|
|
1327 |
$trial_period_days = $order->BillingFrequency * 7; //weekly
|
1328 |
else
|
1329 |
$trial_period_days = $order->BillingFrequency * 30; //assume monthly
|
1330 |
-
|
1331 |
//convert to a profile start date
|
1332 |
$order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
|
1333 |
-
|
1334 |
//filter the start date
|
1335 |
-
$order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
|
1336 |
-
|
1337 |
-
//convert back to days
|
1338 |
$trial_period_days = ceil(abs(strtotime(date("Y-m-d"), current_time("timestamp")) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
|
1339 |
|
1340 |
//for free trials, just push the start date of the subscription back
|
1341 |
-
if(!empty($order->TrialBillingCycles) && $order->TrialAmount == 0)
|
1342 |
{
|
1343 |
$trialOccurrences = (int)$order->TrialBillingCycles;
|
1344 |
if($order->BillingPeriod == "Year")
|
@@ -1354,25 +1354,25 @@
|
|
1354 |
{
|
1355 |
/*
|
1356 |
Let's set the subscription to the trial and give the user an "update" to change the sub later to full price (since v2.0)
|
1357 |
-
|
1358 |
This will force TrialBillingCycles > 1 to act as if they were 1
|
1359 |
-
*/
|
1360 |
$new_user_updates = array();
|
1361 |
$new_user_updates[] = array(
|
1362 |
'when' => 'payment',
|
1363 |
'billing_amount' => $order->PaymentAmount,
|
1364 |
'cycle_period' => $order->BillingPeriod,
|
1365 |
'cycle_number' => $order->BillingFrequency
|
1366 |
-
);
|
1367 |
-
|
1368 |
//now amount to equal the trial #s
|
1369 |
$amount = $order->TrialAmount;
|
1370 |
$amount_tax = $order->getTaxForPrice($amount);
|
1371 |
$amount = round((float)$amount + (float)$amount_tax, 2);
|
1372 |
-
}
|
1373 |
-
|
1374 |
//create a plan
|
1375 |
-
try
|
1376 |
{
|
1377 |
$plan = array(
|
1378 |
"amount" => $amount * 100,
|
@@ -1384,7 +1384,7 @@
|
|
1384 |
"id" => $order->code
|
1385 |
);
|
1386 |
|
1387 |
-
$plan = Stripe_Plan::create(apply_filters('pmpro_stripe_create_plan_array', $plan));
|
1388 |
}
|
1389 |
catch (Exception $e)
|
1390 |
{
|
@@ -1392,54 +1392,55 @@
|
|
1392 |
$order->shorterror = $order->error;
|
1393 |
return false;
|
1394 |
}
|
1395 |
-
|
1396 |
//before subscribing, let's clear out the updates so we don't trigger any during sub
|
1397 |
if(!empty($user_id))
|
1398 |
-
{
|
1399 |
$old_user_updates = get_user_meta($user_id, "pmpro_stripe_updates", true);
|
1400 |
-
update_user_meta($user_id, "pmpro_stripe_updates", array());
|
1401 |
-
}
|
1402 |
-
|
1403 |
if(empty($order->subscription_transaction_id) && !empty($this->customer['id']))
|
1404 |
$order->subscription_transaction_id = $this->customer['id'];
|
1405 |
-
|
1406 |
//subscribe to the plan
|
1407 |
try
|
1408 |
{
|
1409 |
-
$
|
|
|
1410 |
}
|
1411 |
catch (Exception $e)
|
1412 |
{
|
1413 |
//try to delete the plan
|
1414 |
$plan->delete();
|
1415 |
-
|
1416 |
//give the user any old updates back
|
1417 |
if(!empty($user_id))
|
1418 |
update_user_meta($user_id, "pmpro_stripe_updates", $old_user_updates);
|
1419 |
-
|
1420 |
//return error
|
1421 |
$order->error = __("Error subscribing customer to plan with Stripe:", "pmpro") . $e->getMessage();
|
1422 |
$order->shorterror = $order->error;
|
1423 |
return false;
|
1424 |
}
|
1425 |
-
|
1426 |
//delete the plan
|
1427 |
$plan = Stripe_Plan::retrieve($order->code);
|
1428 |
-
$plan->delete();
|
1429 |
|
1430 |
-
//if we got this far, we're all good
|
1431 |
-
$order->status = "success";
|
1432 |
$order->subscription_transaction_id = $result['id'];
|
1433 |
-
|
1434 |
//save new updates if this is at checkout
|
1435 |
if($checkout)
|
1436 |
-
{
|
1437 |
//empty out updates unless set above
|
1438 |
if(empty($new_user_updates))
|
1439 |
$new_user_updates = array();
|
1440 |
-
|
1441 |
//update user meta
|
1442 |
-
if(!empty($user_id))
|
1443 |
update_user_meta($user_id, "pmpro_stripe_updates", $new_user_updates);
|
1444 |
else
|
1445 |
{
|
@@ -1459,33 +1460,33 @@
|
|
1459 |
//give them their old updates back
|
1460 |
update_user_meta($user_id, "pmpro_stripe_updates", $old_user_updates);
|
1461 |
}
|
1462 |
-
|
1463 |
return true;
|
1464 |
-
}
|
1465 |
-
|
1466 |
/**
|
1467 |
* Helper method to update the customer info via getCustomer
|
1468 |
-
*
|
1469 |
* @since 1.4
|
1470 |
*/
|
1471 |
function update(&$order)
|
1472 |
{
|
1473 |
//we just have to run getCustomer which will look for the customer and update it with the new token
|
1474 |
$result = $this->getCustomer($order);
|
1475 |
-
|
1476 |
if(!empty($result))
|
1477 |
{
|
1478 |
return true;
|
1479 |
-
}
|
1480 |
else
|
1481 |
{
|
1482 |
return false; //couldn't find the customer
|
1483 |
}
|
1484 |
}
|
1485 |
-
|
1486 |
/**
|
1487 |
* Cancel a subscription at Stripe
|
1488 |
-
*
|
1489 |
* @since 1.4
|
1490 |
*/
|
1491 |
function cancel(&$order, $update_status = true)
|
@@ -1493,21 +1494,21 @@
|
|
1493 |
//no matter what happens below, we're going to cancel the order in our system
|
1494 |
if($update_status)
|
1495 |
$order->updateStatus("cancelled");
|
1496 |
-
|
1497 |
//require a subscription id
|
1498 |
if(empty($order->subscription_transaction_id))
|
1499 |
return false;
|
1500 |
-
|
1501 |
//find the customer
|
1502 |
-
$result = $this->getCustomer($order);
|
1503 |
-
|
1504 |
if(!empty($result))
|
1505 |
{
|
1506 |
//find subscription with this order code
|
1507 |
-
$subscription = $this->getSubscription($order);
|
1508 |
|
1509 |
if(!empty($subscription))
|
1510 |
-
{
|
1511 |
if($this->cancelSubscriptionAtGateway($subscription))
|
1512 |
{
|
1513 |
//we're okay, going to return true later
|
@@ -1516,17 +1517,17 @@
|
|
1516 |
{
|
1517 |
$order->error = __("Could not cancel old subscription.", "pmpro");
|
1518 |
$order->shorterror = $order->error;
|
1519 |
-
|
1520 |
-
return false;
|
1521 |
-
}
|
1522 |
-
}
|
1523 |
-
|
1524 |
/*
|
1525 |
Clear updates for this user. (But not if checking out, we would have already done that.)
|
1526 |
*/
|
1527 |
if(empty($_REQUEST['submit-checkout']))
|
1528 |
update_user_meta($order->user_id, "pmpro_stripe_updates", array());
|
1529 |
-
|
1530 |
return true;
|
1531 |
}
|
1532 |
else
|
@@ -1534,12 +1535,12 @@
|
|
1534 |
$order->error = __("Could not find the customer.", "pmpro");
|
1535 |
$order->shorterror = $order->error;
|
1536 |
return false; //no customer found
|
1537 |
-
}
|
1538 |
-
}
|
1539 |
-
|
1540 |
/**
|
1541 |
* Helper method to cancel a subscription at Stripe and also clear up any upaid invoices.
|
1542 |
-
*
|
1543 |
* @since 1.8
|
1544 |
*/
|
1545 |
function cancelSubscriptionAtGateway($subscription)
|
@@ -1547,50 +1548,50 @@
|
|
1547 |
//need a valid sub
|
1548 |
if(empty($subscription->id))
|
1549 |
return false;
|
1550 |
-
|
1551 |
//make sure we get the customer for this subscription
|
1552 |
$order = new MemberOrder();
|
1553 |
-
$order->getLastMemberOrderBySubscriptionTransactionID($subscription->id);
|
1554 |
-
|
1555 |
//no order?
|
1556 |
if(empty($order))
|
1557 |
{
|
1558 |
//lets cancel anyway, but this is suspicious
|
1559 |
$r = $subscription->cancel();
|
1560 |
-
|
1561 |
return true;
|
1562 |
}
|
1563 |
-
|
1564 |
//okay have an order, so get customer so we can cancel invoices too
|
1565 |
$this->getCustomer($order);
|
1566 |
-
|
1567 |
//get open invoices
|
1568 |
$invoices = $this->customer->invoices();
|
1569 |
$invoices = $invoices->all();
|
1570 |
-
|
1571 |
//found it, cancel it
|
1572 |
try
|
1573 |
-
{
|
1574 |
//find any open invoices for this subscription and forgive them
|
1575 |
if(!empty($invoices))
|
1576 |
{
|
1577 |
foreach($invoices->data as $invoice)
|
1578 |
-
{
|
1579 |
if(!$invoice->closed && $invoice->subscription == $subscription->id)
|
1580 |
-
{
|
1581 |
$invoice->closed = true;
|
1582 |
$invoice->save();
|
1583 |
}
|
1584 |
}
|
1585 |
-
}
|
1586 |
-
|
1587 |
//cancel
|
1588 |
$r = $subscription->cancel();
|
1589 |
-
|
1590 |
return true;
|
1591 |
}
|
1592 |
catch(Exception $e)
|
1593 |
-
{
|
1594 |
return false;
|
1595 |
}
|
1596 |
}
|
1 |
+
<?php
|
2 |
//include pmprogateway
|
3 |
+
require_once(dirname(__FILE__) . "/class.pmprogateway.php");
|
4 |
+
|
5 |
//load classes init method
|
6 |
add_action('init', array('PMProGateway_stripe', 'init'));
|
7 |
+
|
8 |
/**
|
9 |
* PMProGateway_stripe Class
|
10 |
*
|
16 |
{
|
17 |
/**
|
18 |
* Stripe Class Constructor
|
19 |
+
*
|
20 |
* @since 1.4
|
21 |
*/
|
22 |
function PMProGateway_stripe($gateway = NULL)
|
23 |
{
|
24 |
$this->gateway = $gateway;
|
25 |
$this->gateway_environment = pmpro_getOption("gateway_environment");
|
26 |
+
|
27 |
+
$this->loadStripeLibrary();
|
28 |
Stripe::setApiKey(pmpro_getOption("stripe_secretkey"));
|
29 |
+
|
30 |
return $this->gateway;
|
31 |
+
}
|
32 |
+
|
33 |
/**
|
34 |
* Load the Stripe API library.
|
35 |
+
*
|
36 |
* @since 1.8
|
37 |
+
* Moved into a method in version 1.8 so we only load it when needed.
|
38 |
*/
|
39 |
function loadStripeLibrary()
|
40 |
{
|
42 |
if(!class_exists("Stripe"))
|
43 |
require_once(dirname(__FILE__) . "/../../includes/lib/Stripe/Stripe.php");
|
44 |
}
|
45 |
+
|
46 |
/**
|
47 |
* Run on WP init
|
48 |
+
*
|
49 |
* @since 1.8
|
50 |
*/
|
51 |
static function init()
|
52 |
+
{
|
53 |
//make sure Stripe is a gateway option
|
54 |
add_filter('pmpro_gateways', array('PMProGateway_stripe', 'pmpro_gateways'));
|
55 |
+
|
56 |
//add fields to payment settings
|
57 |
add_filter('pmpro_payment_options', array('PMProGateway_stripe', 'pmpro_payment_options'));
|
58 |
add_filter('pmpro_payment_option_fields', array('PMProGateway_stripe', 'pmpro_payment_option_fields'), 10, 2);
|
59 |
+
|
60 |
//add some fields to edit user page (Updates)
|
61 |
add_action('pmpro_after_membership_level_profile_fields', array('PMProGateway_stripe', 'user_profile_fields'));
|
62 |
add_action('profile_update', array('PMProGateway_stripe', 'user_profile_fields_save'));
|
63 |
+
|
64 |
//old global RE showing billing address or not
|
65 |
global $pmpro_stripe_lite;
|
66 |
$pmpro_stripe_lite = apply_filters("pmpro_stripe_lite", !pmpro_getOption("stripe_billingaddress")); //default is oposite of the stripe_billingaddress setting
|
67 |
+
|
68 |
//updates cron
|
69 |
add_action('pmpro_activation', array('PMProGateway_stripe', 'pmpro_activation'));
|
70 |
add_action('pmpro_deactivation', array('PMProGateway_stripe', 'pmpro_deactivation'));
|
71 |
add_action('pmpro_cron_stripe_subscription_updates', array('PMProGateway_stripe', 'pmpro_cron_stripe_subscription_updates'));
|
72 |
+
|
73 |
//code to add at checkout if Stripe is the current gateway
|
74 |
$gateway = pmpro_getOption("gateway");
|
75 |
if($gateway == "stripe")
|
76 |
{
|
77 |
+
add_action('pmpro_checkout_preheader', array('PMProGateway_stripe', 'pmpro_checkout_preheader'));
|
78 |
add_filter('pmpro_checkout_order', array('PMProGateway_stripe', 'pmpro_checkout_order'));
|
79 |
add_filter('pmpro_include_billing_address_fields', array('PMProGateway_stripe', 'pmpro_include_billing_address_fields'));
|
80 |
add_filter('pmpro_include_cardtype_field', array('PMProGateway_stripe', 'pmpro_include_billing_address_fields'));
|
81 |
add_filter('pmpro_include_payment_information_fields', array('PMProGateway_stripe', 'pmpro_include_payment_information_fields'));
|
82 |
}
|
83 |
}
|
84 |
+
|
85 |
/**
|
86 |
* Make sure Stripe is in the gateways list
|
87 |
+
*
|
88 |
* @since 1.8
|
89 |
*/
|
90 |
static function pmpro_gateways($gateways)
|
91 |
{
|
92 |
if(empty($gateways['stripe']))
|
93 |
$gateways['stripe'] = __('Stripe', 'pmpro');
|
94 |
+
|
95 |
return $gateways;
|
96 |
}
|
97 |
+
|
98 |
/**
|
99 |
* Get a list of payment options that the Stripe gateway needs/supports.
|
100 |
+
*
|
101 |
* @since 1.8
|
102 |
*/
|
103 |
static function getGatewayOptions()
|
104 |
+
{
|
105 |
$options = array(
|
106 |
'sslseal',
|
107 |
'nuclear_HTTPS',
|
115 |
'tax_rate',
|
116 |
'accepted_credit_cards'
|
117 |
);
|
118 |
+
|
119 |
return $options;
|
120 |
}
|
121 |
+
|
122 |
/**
|
123 |
* Set payment options for payment settings page.
|
124 |
+
*
|
125 |
* @since 1.8
|
126 |
*/
|
127 |
static function pmpro_payment_options($options)
|
128 |
+
{
|
129 |
//get stripe options
|
130 |
$stripe_options = PMProGateway_stripe::getGatewayOptions();
|
131 |
+
|
132 |
//merge with others.
|
133 |
$options = array_merge($stripe_options, $options);
|
134 |
+
|
135 |
return $options;
|
136 |
}
|
137 |
+
|
138 |
/**
|
139 |
* Display fields for Stripe options.
|
140 |
+
*
|
141 |
* @since 1.8
|
142 |
*/
|
143 |
static function pmpro_payment_option_fields($values, $gateway)
|
144 |
{
|
145 |
?>
|
146 |
+
<tr class="pmpro_settings_divider gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
|
147 |
<td colspan="2">
|
148 |
<?php _e('Stripe Settings', 'pmpro'); ?>
|
149 |
</td>
|
171 |
<td>
|
172 |
<select id="stripe_billingaddress" name="stripe_billingaddress">
|
173 |
<option value="0" <?php if(empty($values['stripe_billingaddress'])) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
|
174 |
+
<option value="1" <?php if(!empty($values['stripe_billingaddress'])) { ?>selected="selected"<?php } ?>><?php _e('Yes', 'pmpro');?></option>
|
175 |
</select>
|
176 |
<small><?php _e("Stripe doesn't require billing address fields. Choose 'No' to hide them on the checkout page.<br /><strong>If No, make sure you disable address verification in the Stripe dashboard settings.</strong>", 'pmpro');?></small>
|
177 |
</td>
|
183 |
<td>
|
184 |
<p><?php _e('To fully integrate with Stripe, be sure to set your Web Hook URL to', 'pmpro');?> <pre><?php echo admin_url("admin-ajax.php") . "?action=stripe_webhook";?></pre></p>
|
185 |
</td>
|
186 |
+
</tr>
|
187 |
<?php
|
188 |
}
|
189 |
+
|
190 |
/**
|
191 |
* Code added to checkout preheader.
|
192 |
+
*
|
193 |
* @since 1.8
|
194 |
*/
|
195 |
static function pmpro_checkout_preheader()
|
196 |
+
{
|
197 |
global $gateway, $pmpro_level;
|
198 |
+
|
199 |
if($gateway == "stripe" && !pmpro_isLevelFree($pmpro_level))
|
200 |
{
|
201 |
//stripe js library
|
202 |
wp_enqueue_script("stripe", "https://js.stripe.com/v2/", array(), NULL);
|
203 |
+
|
204 |
//stripe js code for checkout
|
205 |
function pmpro_stripe_javascript()
|
206 |
{
|
207 |
global $pmpro_gateway, $pmpro_level, $pmpro_stripe_lite;
|
208 |
?>
|
209 |
<script type="text/javascript">
|
210 |
+
// this identifies your website in the createToken call below
|
211 |
Stripe.setPublishableKey('<?php echo pmpro_getOption("stripe_publishablekey"); ?>');
|
212 |
+
|
213 |
+
var pmpro_require_billing = true;
|
214 |
+
|
215 |
jQuery(document).ready(function() {
|
216 |
jQuery("#pmpro_form, .pmpro_form").submit(function(event) {
|
217 |
+
|
218 |
+
//double check in case a discount code made the level free
|
219 |
if(pmpro_require_billing)
|
220 |
{
|
221 |
//build array for creating token
|
231 |
?>
|
232 |
,address_line1: jQuery('#baddress1').val(),
|
233 |
address_line2: jQuery('#baddress2').val(),
|
234 |
+
address_city: jQuery('#bcity').val(),
|
235 |
+
address_state: jQuery('#bstate').val(),
|
236 |
+
address_zip: jQuery('#bzipcode').val(),
|
237 |
address_country: jQuery('#bcountry').val()
|
238 |
<?php
|
239 |
}
|
240 |
+
?>
|
241 |
};
|
242 |
+
|
243 |
if (jQuery('#bfirstname').length && jQuery('#blastname').length)
|
244 |
args['name'] = jQuery.trim(jQuery('#bfirstname').val() + ' ' + jQuery('#blastname').val());
|
245 |
+
|
246 |
//create token
|
247 |
Stripe.createToken(args, stripeResponseHandler);
|
248 |
|
261 |
|
262 |
//hide processing message
|
263 |
jQuery('#pmpro_processing_message').css('visibility', 'hidden');
|
264 |
+
|
265 |
// show the errors on the form
|
266 |
alert(response.error.message);
|
267 |
jQuery(".payment-errors").text(response.error.message);
|
268 |
} else {
|
269 |
+
var form$ = jQuery("#pmpro_form, .pmpro_form");
|
270 |
// token contains id, last4, and card type
|
271 |
+
var token = response['id'];
|
272 |
// insert the token into the form so it gets submitted to the server
|
273 |
form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
|
274 |
+
|
275 |
console.log(response);
|
276 |
+
|
277 |
//insert fields for other card fields
|
278 |
if(jQuery('#CardType[name=CardType]').length)
|
279 |
jQuery('#CardType').val(response['card']['brand']);
|
281 |
form$.append("<input type='hidden' name='CardType' value='" + response['card']['brand'] + "'/>");
|
282 |
form$.append("<input type='hidden' name='AccountNumber' value='XXXXXXXXXXXXX" + response['card']['last4'] + "'/>");
|
283 |
form$.append("<input type='hidden' name='ExpirationMonth' value='" + ("0" + response['card']['exp_month']).slice(-2) + "'/>");
|
284 |
+
form$.append("<input type='hidden' name='ExpirationYear' value='" + response['card']['exp_year'] + "'/>");
|
285 |
+
|
286 |
// and submit
|
287 |
form$.get(0).submit();
|
288 |
}
|
291 |
<?php
|
292 |
}
|
293 |
add_action("wp_head", "pmpro_stripe_javascript");
|
294 |
+
|
295 |
//don't require the CVV
|
296 |
function pmpro_stripe_dont_require_CVV($fields)
|
297 |
{
|
298 |
+
unset($fields['CVV']);
|
299 |
return $fields;
|
300 |
}
|
301 |
add_filter("pmpro_required_billing_fields", "pmpro_stripe_dont_require_CVV");
|
302 |
}
|
303 |
}
|
304 |
+
|
305 |
/**
|
306 |
* Filtering orders at checkout.
|
307 |
+
*
|
308 |
* @since 1.8
|
309 |
*/
|
310 |
static function pmpro_checkout_order($morder)
|
314 |
{
|
315 |
$morder->stripeToken = $_REQUEST['stripeToken'];
|
316 |
}
|
317 |
+
|
318 |
//stripe lite code to get name from other sources if available
|
319 |
global $pmpro_stripe_lite, $current_user;
|
320 |
if(!empty($pmpro_stripe_lite) && empty($morder->FirstName) && empty($morder->LastName))
|
321 |
{
|
322 |
if(!empty($current_user->ID))
|
323 |
+
{
|
324 |
$morder->FirstName = get_user_meta($current_user->ID, "first_name", true);
|
325 |
$morder->LastName = get_user_meta($current_user->ID, "last_name", true);
|
326 |
}
|
330 |
$morder->LastName = $_REQUEST['last_name'];
|
331 |
}
|
332 |
}
|
333 |
+
|
334 |
return $morder;
|
335 |
}
|
336 |
+
|
337 |
/**
|
338 |
* Code to run after checkout
|
339 |
+
*
|
340 |
* @since 1.8
|
341 |
*/
|
342 |
+
static function pmpro_after_checkout($user_id, $morder)
|
343 |
{
|
344 |
global $gateway;
|
345 |
+
|
346 |
if($gateway == "stripe")
|
347 |
{
|
348 |
if(!empty($morder) && !empty($morer->Gateway) && !empty($morder->Gateway->customer) && !empty($morder->Gateway->customer->id))
|
351 |
}
|
352 |
}
|
353 |
}
|
354 |
+
|
355 |
/**
|
356 |
* Check settings if billing address should be shown.
|
357 |
* @since 1.8
|
361 |
//check settings RE showing billing address
|
362 |
if(!pmpro_getOption("stripe_billingaddress"))
|
363 |
$include = false;
|
364 |
+
|
365 |
return $include;
|
366 |
}
|
367 |
+
|
368 |
/**
|
369 |
* Use our own payment fields at checkout. (Remove the name attributes.)
|
370 |
* @since 1.8
|
371 |
*/
|
372 |
static function pmpro_include_payment_information_fields($include)
|
373 |
+
{
|
374 |
//global vars
|
375 |
global $pmpro_requirebilling, $pmpro_show_discount_code, $discount_code, $CardType, $AccountNumber, $ExpirationMonth, $ExpirationYear;
|
376 |
+
|
377 |
//get accepted credit cards
|
378 |
$pmpro_accepted_credit_cards = pmpro_getOption("accepted_credit_cards");
|
379 |
$pmpro_accepted_credit_cards = explode(",", $pmpro_accepted_credit_cards);
|
380 |
+
$pmpro_accepted_credit_cards_string = pmpro_implodeToEnglish($pmpro_accepted_credit_cards);
|
381 |
+
|
382 |
//include ours
|
383 |
?>
|
384 |
<table id="pmpro_payment_information_fields" class="pmpro_checkout top1em" width="100%" cellpadding="0" cellspacing="0" border="0" <?php if(!$pmpro_requirebilling || apply_filters("pmpro_hide_payment_information_fields", false) ) { ?>style="display: none;"<?php } ?>>
|
388 |
</tr>
|
389 |
</thead>
|
390 |
<tbody>
|
391 |
+
<tr valign="top">
|
392 |
+
<td>
|
393 |
<?php
|
394 |
$sslseal = pmpro_getOption("sslseal");
|
395 |
if($sslseal)
|
409 |
<select id="CardType" class=" <?php echo pmpro_getClassForField("CardType");?>">
|
410 |
<?php foreach($pmpro_accepted_credit_cards as $cc) { ?>
|
411 |
<option value="<?php echo $cc?>" <?php if($CardType == $cc) { ?>selected="selected"<?php } ?>><?php echo $cc?></option>
|
412 |
+
<?php } ?>
|
413 |
</select>
|
414 |
</div>
|
415 |
<?php
|
419 |
?>
|
420 |
<input type="hidden" id="CardType" name="CardType" value="<?php echo esc_attr($CardType);?>" />
|
421 |
<script>
|
422 |
+
jQuery(document).ready(function() {
|
423 |
+
jQuery('#AccountNumber').validateCreditCard(function(result) {
|
424 |
var cardtypenames = {
|
425 |
"amex":"American Express",
|
426 |
"diners_club_carte_blanche":"Diners Club Carte Blanche",
|
433 |
"visa":"Visa",
|
434 |
"visa_electron":"Visa Electron"
|
435 |
}
|
436 |
+
|
437 |
if(result.card_type)
|
438 |
jQuery('#CardType').val(cardtypenames[result.card_type.name]);
|
439 |
else
|
440 |
jQuery('#CardType').val('Unknown Card Type');
|
441 |
+
});
|
442 |
});
|
443 |
</script>
|
444 |
<?php
|
445 |
}
|
446 |
?>
|
447 |
+
|
448 |
<div class="pmpro_payment-account-number">
|
449 |
<label for="AccountNumber"><?php _e('Card Number', 'pmpro');?></label>
|
450 |
<input id="AccountNumber" class="input <?php echo pmpro_getClassForField("AccountNumber");?>" type="text" size="25" value="<?php echo esc_attr($AccountNumber)?>" autocomplete="off" />
|
451 |
</div>
|
452 |
+
|
453 |
<div class="pmpro_payment-expiration">
|
454 |
<label for="ExpirationMonth"><?php _e('Expiration Date', 'pmpro');?></label>
|
455 |
<select id="ExpirationMonth" class=" <?php echo pmpro_getClassForField("ExpirationMonth");?>">
|
474 |
<?php
|
475 |
}
|
476 |
?>
|
477 |
+
</select>
|
478 |
</div>
|
479 |
+
|
480 |
<?php
|
481 |
$pmpro_show_cvv = apply_filters("pmpro_show_cvv", true);
|
482 |
if($pmpro_show_cvv)
|
489 |
<?php
|
490 |
}
|
491 |
?>
|
492 |
+
|
493 |
<?php if($pmpro_show_discount_code) { ?>
|
494 |
<div class="pmpro_payment-discount-code">
|
495 |
<label for="discount_code"><?php _e('Discount Code', 'pmpro');?></label>
|
498 |
<p id="discount_code_message" class="pmpro_message" style="display: none;"></p>
|
499 |
</div>
|
500 |
<?php } ?>
|
501 |
+
|
502 |
+
</td>
|
503 |
</tr>
|
504 |
</tbody>
|
505 |
</table>
|
506 |
<?php
|
507 |
+
|
508 |
//don't include the default
|
509 |
return false;
|
510 |
}
|
511 |
+
|
512 |
/**
|
513 |
* Fields shown on edit user page
|
514 |
+
*
|
515 |
* @since 1.8
|
516 |
*/
|
517 |
static function user_profile_fields($user)
|
521 |
$cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
|
522 |
$current_year = date("Y");
|
523 |
$current_month = date("m");
|
524 |
+
|
525 |
//make sure the current user has privileges
|
526 |
$membership_level_capability = apply_filters("pmpro_edit_member_capability", "manage_options");
|
527 |
if(!current_user_can($membership_level_capability))
|
528 |
return false;
|
529 |
|
530 |
+
//more privelges they should have
|
531 |
$show_membership_level = apply_filters("pmpro_profile_show_membership_level", true, $user);
|
532 |
if(!$show_membership_level)
|
533 |
return false;
|
534 |
+
|
535 |
//check that user has a current subscription at Stripe
|
536 |
$last_order = new MemberOrder();
|
537 |
$last_order->getLastMemberOrder($user->ID);
|
538 |
+
|
539 |
//assume no sub to start
|
540 |
$sub = false;
|
541 |
+
|
542 |
//check that gateway is Stripe
|
543 |
if($last_order->gateway == "stripe")
|
544 |
+
{
|
545 |
//is there a customer?
|
546 |
+
$sub = $last_order->Gateway->getSubscription($last_order);
|
547 |
+
}
|
548 |
+
|
549 |
$customer_id = $user->pmpro_stripe_customerid;
|
550 |
+
|
551 |
if(empty($sub))
|
552 |
{
|
553 |
//make sure we delete stripe updates
|
554 |
update_user_meta($user->ID, "pmpro_stripe_updates", array());
|
555 |
+
|
556 |
//if the last order has a sub id, let the admin know there is no sub at Stripe
|
557 |
if(!empty($last_order) && $last_order->gateway == "stripe" && !empty($last_order->subscription_transaction_id) && strpos($last_order->subscription_transaction_id, "sub_") !== false)
|
558 |
{
|
559 |
?>
|
560 |
<p><strong>Note:</strong> Subscription <strong><?php echo $last_order->subscription_transaction_id;?></strong> could not be found at Stripe. It might have been deleted.</p>
|
561 |
<?php
|
562 |
+
}
|
563 |
}
|
564 |
+
else
|
565 |
+
{
|
566 |
?>
|
567 |
<h3><?php _e("Subscription Updates", "pmpro"); ?></h3>
|
568 |
<p>
|
578 |
<th><label for="membership_level"><?php _e("Update", "pmpro"); ?></label></th>
|
579 |
<td id="updates_td">
|
580 |
<?php
|
581 |
+
$old_updates = $user->pmpro_stripe_updates;
|
582 |
if(is_array($old_updates))
|
583 |
{
|
584 |
$updates = array_merge(
|
588 |
}
|
589 |
else
|
590 |
$updates = array(array('template'=>true, 'when'=>'now', 'date_month'=>'', 'date_day'=>'', 'date_year'=>'', 'billing_amount'=>'', 'cycle_number'=>'', 'cycle_period'=>'Month'));
|
591 |
+
|
592 |
foreach($updates as $update)
|
593 |
{
|
594 |
?>
|
595 |
<div class="updates_update" <?php if(!empty($update['template'])) { ?>style="display: none;"<?php } ?>>
|
596 |
+
<select class="updates_when" name="updates_when[]">
|
597 |
<option value="now" <?php selected($update['when'], "now");?>>Now</option>
|
598 |
<option value="payment" <?php selected($update['when'], "payment");?>>After Next Payment</option>
|
599 |
<option value="date" <?php selected($update['when'], "date");?>>On Date</option>
|
600 |
</select>
|
601 |
<span class="updates_date" <?php if($uwhen != "date") { ?>style="display: none;"<?php } ?>>
|
602 |
<select name="updates_date_month[]">
|
603 |
+
<?php
|
604 |
for($i = 1; $i < 13; $i++)
|
605 |
{
|
606 |
?>
|
619 |
<small><?php _e('per', 'pmpro');?></small>
|
620 |
<input name="updates_cycle_number[]" type="text" size="5" value="<?php echo esc_attr($update['cycle_number']);?>" />
|
621 |
<select name="updates_cycle_period[]">
|
622 |
+
<?php
|
623 |
foreach ( $cycles as $name => $value ) {
|
624 |
echo "<option value='$value'";
|
625 |
if(!empty($update['cycle_period']) && $update['cycle_period'] == $value) echo " selected='selected'";
|
627 |
}
|
628 |
?>
|
629 |
</select>
|
630 |
+
</span>
|
631 |
<span>
|
632 |
+
<a class="updates_remove" href="javascript:void(0);">Remove</a>
|
633 |
</span>
|
634 |
</div>
|
635 |
<?php
|
636 |
}
|
637 |
+
?>
|
638 |
<p><a id="updates_new_update" href="javascript:void(0);">+ New Update</a></p>
|
639 |
</td>
|
640 |
+
</tr>
|
641 |
+
</table>
|
642 |
<script>
|
643 |
jQuery(document).ready(function() {
|
644 |
//function to update dropdowns/etc based on when field
|
648 |
jQuery(when).parent().children('.updates_date').show();
|
649 |
else
|
650 |
jQuery(when).parent().children('.updates_date').hide();
|
651 |
+
|
652 |
if(jQuery(when).val() == 'no')
|
653 |
jQuery(when).parent().children('.updates_billing').hide();
|
654 |
else
|
655 |
jQuery(when).parent().children('.updates_billing').show();
|
656 |
+
}
|
657 |
|
658 |
//and update on page load
|
659 |
jQuery('.updates_when').each(function() { if(jQuery(this).parent().css('display') != 'none') updateSubscriptionUpdateFields(this); });
|
660 |
+
|
661 |
//add a new update when clicking to
|
662 |
var num_updates_divs = <?php echo count($updates);?>;
|
663 |
jQuery('#updates_new_update').click(function() {
|
664 |
//get updates
|
665 |
updates = jQuery('.updates_update').toArray();
|
666 |
+
|
667 |
//clone the first one
|
668 |
+
new_div = jQuery(updates[0]).clone();
|
669 |
+
|
670 |
//append
|
671 |
new_div.insertBefore('#updates_new_update');
|
672 |
+
|
673 |
//update events
|
674 |
addUpdateEvents()
|
675 |
+
|
676 |
//unhide it
|
677 |
new_div.show();
|
678 |
+
updateSubscriptionUpdateFields(new_div.children('.updates_when'));
|
679 |
});
|
680 |
+
|
681 |
function addUpdateEvents()
|
682 |
{
|
683 |
//update when when changes
|
684 |
jQuery('.updates_when').change(function() {
|
685 |
updateSubscriptionUpdateFields(this);
|
686 |
});
|
687 |
+
|
688 |
//remove updates when clicking
|
689 |
+
jQuery('.updates_remove').click(function() {
|
690 |
jQuery(this).parent().parent().remove();
|
691 |
});
|
692 |
}
|
696 |
<?php
|
697 |
}
|
698 |
}
|
699 |
+
|
700 |
/**
|
701 |
* Process fields from the edit user page
|
702 |
+
*
|
703 |
* @since 1.8
|
704 |
*/
|
705 |
static function user_profile_fields_save($user_id)
|
706 |
{
|
707 |
global $wpdb;
|
708 |
+
|
709 |
//check capabilities
|
710 |
$membership_level_capability = apply_filters("pmpro_edit_member_capability", "manage_options");
|
711 |
if(!current_user_can($membership_level_capability))
|
712 |
return false;
|
713 |
+
|
714 |
//make sure some value was passed
|
715 |
if(!isset($_POST['updates_when']) || !is_array($_POST['updates_when']))
|
716 |
return;
|
717 |
+
|
718 |
//vars
|
719 |
$updates = array();
|
720 |
$next_on_date_update = "";
|
721 |
+
|
722 |
//build array of updates (we skip the first because it's the template field for the JavaScript
|
723 |
for($i = 1; $i < count($_POST['updates_when']); $i++)
|
724 |
{
|
725 |
$update = array();
|
726 |
+
|
727 |
//all updates have these values
|
728 |
$update['when'] = $_POST['updates_when'][$i];
|
729 |
$update['billing_amount'] = $_POST['updates_billing_amount'][$i];
|
730 |
$update['cycle_number'] = $_POST['updates_cycle_number'][$i];
|
731 |
$update['cycle_period'] = $_POST['updates_cycle_period'][$i];
|
732 |
+
|
733 |
//these values only for on date updates
|
734 |
if($_POST['updates_when'][$i] == "date")
|
735 |
{
|
737 |
$update['date_day'] = str_pad($_POST['updates_date_day'][$i], 2, "0", STR_PAD_LEFT);
|
738 |
$update['date_year'] = $_POST['updates_date_year'][$i];
|
739 |
}
|
740 |
+
|
741 |
//make sure the update is valid
|
742 |
if(empty($update['cycle_number']))
|
743 |
continue;
|
744 |
+
|
745 |
//if when is now, update the subscription
|
746 |
if($update['when'] == "now")
|
747 |
{
|
748 |
//get level for user
|
749 |
$user_level = pmpro_getMembershipLevelForUser($user_id);
|
750 |
+
|
751 |
//get current plan at Stripe to get payment date
|
752 |
$last_order = new MemberOrder();
|
753 |
$last_order->getLastMemberOrder($user_id);
|
755 |
$last_order->Gateway->getCustomer($last_order);
|
756 |
|
757 |
$subscription = $last_order->Gateway->getSubscription($last_order);
|
758 |
+
|
759 |
if(!empty($subscription))
|
760 |
+
{
|
761 |
$end_timestamp = $subscription->current_period_end;
|
762 |
+
|
763 |
+
//cancel the old subscription
|
764 |
if(!$last_order->Gateway->cancelSubscriptionAtGateway($subscription))
|
765 |
{
|
766 |
//throw error and halt save
|
767 |
+
function pmpro_stripe_user_profile_fields_save_error($errors, $update, $user)
|
768 |
{
|
769 |
$errors->add('pmpro_stripe_updates',__('Could not cancel the old subscription. Updates have not been processed.', 'pmpro'));
|
770 |
}
|
771 |
add_filter('user_profile_update_errors', 'pmpro_stripe_user_profile_fields_save_error', 10, 3);
|
772 |
+
|
773 |
//stop processing updates
|
774 |
return;
|
775 |
}
|
776 |
}
|
777 |
+
|
778 |
//if we didn't get an end date, let's set one one cycle out
|
779 |
if(empty($end_timestamp))
|
780 |
$end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period'], current_time('timestamp'));
|
781 |
+
|
782 |
//build order object
|
783 |
$update_order = new MemberOrder();
|
784 |
$update_order->setGateway('stripe');
|
789 |
$update_order->PaymentAmount = $update['billing_amount'];
|
790 |
$update_order->ProfileStartDate = date("Y-m-d", $end_timestamp);
|
791 |
$update_order->BillingPeriod = $update['cycle_period'];
|
792 |
+
$update_order->BillingFrequency = $update['cycle_number'];
|
793 |
+
|
794 |
//need filter to reset ProfileStartDate
|
795 |
add_filter('pmpro_profile_start_date', create_function('$startdate, $order', 'return "' . $update_order->ProfileStartDate . 'T0:0:0";'), 10, 2);
|
796 |
+
|
797 |
//update subscription
|
798 |
$update_order->Gateway->subscribe($update_order, false);
|
799 |
+
|
800 |
//update membership
|
801 |
$sqlQuery = "UPDATE $wpdb->pmpro_memberships_users
|
802 |
SET billing_amount = '" . esc_sql($update['billing_amount']) . "',
|
808 |
AND membership_id = '" . esc_sql($last_order->membership_id) . "'
|
809 |
AND status = 'active'
|
810 |
LIMIT 1";
|
811 |
+
|
812 |
$wpdb->query($sqlQuery);
|
813 |
+
|
814 |
//save order so we know which plan to look for at stripe (order code = plan id)
|
815 |
$update_order->status = "success";
|
816 |
$update_order->saveOrder();
|
817 |
+
|
818 |
continue;
|
819 |
}
|
820 |
elseif($update['when'] == 'date')
|
824 |
else
|
825 |
$next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'];
|
826 |
}
|
827 |
+
|
828 |
+
//add to array
|
829 |
+
$updates[] = $update;
|
830 |
}
|
831 |
+
|
832 |
//save in user meta
|
833 |
update_user_meta($user_id, "pmpro_stripe_updates", $updates);
|
834 |
+
|
835 |
//save date of next on-date update to make it easier to query for these in cron job
|
836 |
update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update);
|
837 |
}
|
838 |
+
|
839 |
/**
|
840 |
* Cron activation for subscription updates.
|
841 |
+
*
|
842 |
* @since 1.8
|
843 |
*/
|
844 |
static function pmpro_activation()
|
845 |
{
|
846 |
wp_schedule_event(time(), 'daily', 'pmpro_cron_stripe_subscription_updates');
|
847 |
}
|
848 |
+
|
849 |
/**
|
850 |
* Cron deactivation for subscription updates.
|
851 |
+
*
|
852 |
* @since 1.8
|
853 |
*/
|
854 |
static function pmpro_deactivation()
|
855 |
{
|
856 |
wp_clear_scheduled_hook('pmpro_cron_stripe_subscription_updates');
|
857 |
}
|
858 |
+
|
859 |
/**
|
860 |
* Cron job for subscription updates.
|
861 |
+
*
|
862 |
* @since 1.8
|
863 |
*/
|
864 |
static function pmpro_cron_stripe_subscription_updates()
|
866 |
global $wpdb;
|
867 |
|
868 |
//get all updates for today (or before today)
|
869 |
+
$sqlQuery = "SELECT *
|
870 |
+
FROM $wpdb->usermeta
|
871 |
+
WHERE meta_key = 'pmpro_stripe_next_on_date_update'
|
872 |
+
AND meta_value IS NOT NULL
|
873 |
+
AND meta_value < '" . date("Y-m-d", strtotime("+1 day")) . "'";
|
874 |
$updates = $wpdb->get_results($sqlQuery);
|
875 |
+
|
876 |
if(!empty($updates))
|
877 |
+
{
|
878 |
//loop through
|
879 |
foreach($updates as $update)
|
880 |
+
{
|
881 |
//pull values from update
|
882 |
$user_id = $update->user_id;
|
883 |
+
|
884 |
$user = get_userdata($user_id);
|
885 |
$user_updates = $user->pmpro_stripe_updates;
|
886 |
+
$next_on_date_update = "";
|
887 |
+
|
888 |
//loop through updates looking for updates happening today or earlier
|
889 |
foreach($user_updates as $key => $update)
|
890 |
+
{
|
891 |
if($update['when'] == 'date' &&
|
892 |
$update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'] <= date("Y-m-d")
|
893 |
)
|
894 |
{
|
895 |
//get level for user
|
896 |
$user_level = pmpro_getMembershipLevelForUser($user_id);
|
897 |
+
|
898 |
//get current plan at Stripe to get payment date
|
899 |
$last_order = new MemberOrder();
|
900 |
$last_order->getLastMemberOrder($user_id);
|
901 |
$last_order->setGateway('stripe');
|
902 |
$last_order->Gateway->getCustomer($last_order);
|
903 |
+
|
904 |
if(!empty($last_order->Gateway->customer))
|
905 |
{
|
906 |
//find the first subscription
|
910 |
$end_timestamp = $first_sub['current_period_end'];
|
911 |
}
|
912 |
}
|
913 |
+
|
914 |
//if we didn't get an end date, let's set one one cycle out
|
915 |
$end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period']);
|
916 |
+
|
917 |
//build order object
|
918 |
$update_order = new MemberOrder();
|
919 |
$update_order->setGateway('stripe');
|
925 |
$update_order->ProfileStartDate = date("Y-m-d", $end_timestamp);
|
926 |
$update_order->BillingPeriod = $update['cycle_period'];
|
927 |
$update_order->BillingFrequency = $update['cycle_number'];
|
928 |
+
|
929 |
//update subscription
|
930 |
$update_order->Gateway->subscribe($update_order, false);
|
931 |
+
|
932 |
//update membership
|
933 |
+
$sqlQuery = "UPDATE $wpdb->pmpro_memberships_users
|
934 |
+
SET billing_amount = '" . esc_sql($update['billing_amount']) . "',
|
935 |
+
cycle_number = '" . esc_sql($update['cycle_number']) . "',
|
936 |
+
cycle_period = '" . esc_sql($update['cycle_period']) . "'
|
937 |
+
WHERE user_id = '" . esc_sql($user_id) . "'
|
938 |
+
AND membership_id = '" . esc_sql($last_order->membership_id) . "'
|
939 |
+
AND status = 'active'
|
940 |
LIMIT 1";
|
941 |
+
|
942 |
$wpdb->query($sqlQuery);
|
943 |
+
|
944 |
//save order
|
945 |
$update_order->status = "success";
|
946 |
$update_order->save();
|
947 |
+
|
948 |
//remove update from list
|
949 |
+
unset($user_updates[$key]);
|
950 |
}
|
951 |
elseif($update['when'] == 'date')
|
952 |
{
|
957 |
$next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'];
|
958 |
}
|
959 |
}
|
960 |
+
|
961 |
//save updates in case we removed some
|
962 |
update_user_meta($user_id, "pmpro_stripe_updates", $user_updates);
|
963 |
+
|
964 |
//save date of next on-date update to make it easier to query for these in cron job
|
965 |
update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update);
|
966 |
}
|
967 |
}
|
968 |
}
|
969 |
+
|
970 |
/**
|
971 |
* Process checkout and decide if a charge and or subscribe is needed
|
972 |
+
*
|
973 |
* @since 1.4
|
974 |
*/
|
975 |
function process(&$order)
|
986 |
if($this->charge($order))
|
987 |
{
|
988 |
if(pmpro_isLevelRecurring($order->membership_level))
|
989 |
+
{
|
990 |
if($this->subscribe($order))
|
991 |
{
|
992 |
//yay!
|
1001 |
else
|
1002 |
{
|
1003 |
//only a one time charge
|
1004 |
+
$order->status = "success"; //saved on checkout page
|
1005 |
return true;
|
1006 |
}
|
1007 |
}
|
1011 |
$order->error = __("Unknown error: Initial payment failed.", "pmpro");
|
1012 |
return false;
|
1013 |
}
|
1014 |
+
}
|
1015 |
+
}
|
1016 |
+
|
1017 |
/**
|
1018 |
* Make a one-time charge with Stripe
|
1019 |
+
*
|
1020 |
* @since 1.4
|
1021 |
*/
|
1022 |
function charge(&$order)
|
1023 |
{
|
1024 |
global $pmpro_currency;
|
1025 |
+
|
1026 |
//create a code for the order
|
1027 |
if(empty($order->code))
|
1028 |
$order->code = $order->getRandomCode();
|
1029 |
+
|
1030 |
+
//what amount to charge?
|
1031 |
$amount = $order->InitialPayment;
|
1032 |
+
|
1033 |
//tax
|
1034 |
$order->subtotal = $amount;
|
1035 |
$tax = $order->getTax(true);
|
1036 |
$amount = round((float)$order->subtotal + (float)$tax, 2);
|
1037 |
+
|
1038 |
//create a customer
|
1039 |
$result = $this->getCustomer($order);
|
1040 |
+
|
1041 |
if(empty($result))
|
1042 |
+
{
|
1043 |
//failed to create customer
|
1044 |
return false;
|
1045 |
+
}
|
1046 |
+
|
1047 |
//charge
|
1048 |
try
|
1049 |
{
|
1063 |
$order->shorterror = $order->error;
|
1064 |
return false;
|
1065 |
}
|
1066 |
+
|
1067 |
if(empty($response["failure_message"]))
|
1068 |
{
|
1069 |
//successful charge
|
1070 |
$order->payment_transaction_id = $response["id"];
|
1071 |
+
$order->updateStatus("success");
|
1072 |
+
return true;
|
1073 |
}
|
1074 |
else
|
1075 |
{
|
1078 |
$order->error = $response['failure_message'];
|
1079 |
$order->shorterror = $response['failure_message'];
|
1080 |
return false;
|
1081 |
+
}
|
1082 |
}
|
1083 |
+
|
1084 |
/**
|
1085 |
* Get a Stripe customer object.
|
1086 |
+
*
|
1087 |
* If $this->customer is set, it returns it.
|
1088 |
* It first checks if the order has a subscription_transaction_id. If so, that's the customer id.
|
1089 |
* If not, it checks for a user_id on the order and searches for a customer id in the user meta.
|
1097 |
function getCustomer(&$order = false, $force = false)
|
1098 |
{
|
1099 |
global $current_user;
|
1100 |
+
|
1101 |
//already have it?
|
1102 |
if(!empty($this->customer) && !$force)
|
1103 |
return $this->customer;
|
1104 |
+
|
1105 |
//figure out user_id and user
|
1106 |
if(!empty($order->user_id))
|
1107 |
$user_id = $order->user_id;
|
1108 |
+
|
1109 |
//if no id passed, check the current user
|
1110 |
if(empty($user_id) && !empty($current_user->ID))
|
1111 |
$user_id = $current_user->ID;
|
1112 |
+
|
1113 |
if(!empty($user_id))
|
1114 |
$user = get_userdata($user_id);
|
1115 |
else
|
1116 |
$user = NULL;
|
1117 |
+
|
1118 |
//transaction id?
|
1119 |
if(!empty($order->subscription_transaction_id) && strpos($order->subscription_transaction_id, "cus_") !== false)
|
1120 |
$customer_id = $order->subscription_transaction_id;
|
1121 |
else
|
1122 |
{
|
1123 |
+
//try based on user id
|
1124 |
if(!empty($user_id))
|
1125 |
+
{
|
1126 |
+
$customer_id = get_user_meta($user_id, "pmpro_stripe_customerid", true);
|
1127 |
}
|
1128 |
+
}
|
1129 |
+
|
1130 |
//get name and email values from order in case we update
|
1131 |
$name = trim($order->FirstName . " " . $order->LastName);
|
1132 |
if(empty($name) && !empty($user->ID))
|
1133 |
{
|
1134 |
$name = trim($user->first_name . " " . $user->last_name);
|
1135 |
+
|
1136 |
//still empty?
|
1137 |
if(empty($name))
|
1138 |
$name = $user->user_login;
|
1140 |
elseif(empty($name))
|
1141 |
$name = "No Name";
|
1142 |
|
1143 |
+
$email = $order->Email;
|
1144 |
if(empty($email) && !empty($user->ID))
|
1145 |
{
|
1146 |
$email = $user->user_email;
|
1147 |
}
|
1148 |
elseif(empty($email))
|
1149 |
$email = "No Email";
|
1150 |
+
|
1151 |
//check for an existing stripe customer
|
1152 |
if(!empty($customer_id))
|
1153 |
{
|
1154 |
try
|
1155 |
{
|
1156 |
$this->customer = Stripe_Customer::retrieve($customer_id);
|
1157 |
+
|
1158 |
//update the customer description and card
|
1159 |
if(!empty($order->stripeToken))
|
1160 |
+
{
|
1161 |
$this->customer->description = $name . " (" . $email . ")";
|
1162 |
$this->customer->email = $email;
|
1163 |
$this->customer->card = $order->stripeToken;
|
1164 |
$this->customer->save();
|
1165 |
}
|
1166 |
+
|
1167 |
return $this->customer;
|
1168 |
}
|
1169 |
catch (Exception $e)
|
1170 |
{
|
1171 |
+
//assume no customer found
|
1172 |
}
|
1173 |
}
|
1174 |
+
|
1175 |
//no customer id, create one
|
1176 |
if(!empty($order->stripeToken))
|
1177 |
+
{
|
1178 |
try
|
1179 |
{
|
1180 |
$this->customer = Stripe_Customer::create(array(
|
1189 |
$order->shorterror = $order->error;
|
1190 |
return false;
|
1191 |
}
|
1192 |
+
|
1193 |
if(!empty($user_id))
|
1194 |
{
|
1195 |
//user logged in/etc
|
1196 |
+
update_user_meta($user_id, "pmpro_stripe_customerid", $this->customer->id);
|
1197 |
}
|
1198 |
else
|
1199 |
{
|
1210 |
|
1211 |
return apply_filters('pmpro_stripe_create_customer', $this->customer);
|
1212 |
}
|
1213 |
+
|
1214 |
+
return false;
|
1215 |
}
|
1216 |
+
|
1217 |
/**
|
1218 |
* Get a Stripe subscription from a PMPro order
|
1219 |
+
*
|
1220 |
* @since 1.8
|
1221 |
*/
|
1222 |
+
function getSubscription(&$order)
|
1223 |
{
|
1224 |
global $wpdb;
|
1225 |
+
|
1226 |
//no order?
|
1227 |
if(empty($order) || empty($order->code))
|
1228 |
+
return false;
|
1229 |
+
|
1230 |
$result = $this->getCustomer($order, true); //force so we don't get a cached sub for someone else
|
1231 |
+
|
1232 |
//no customer?
|
1233 |
if(empty($result))
|
1234 |
return false;
|
1235 |
+
|
1236 |
//is there a subscription transaction id pointing to a sub?
|
1237 |
if(!empty($order->subscription_transaction_id) && strpos($order->subscription_transaction_id, "sub_") !== false)
|
1238 |
{
|
1246 |
$order->shorterror = $order->error;
|
1247 |
return false;
|
1248 |
}
|
1249 |
+
|
1250 |
return $sub;
|
1251 |
+
}
|
1252 |
+
|
1253 |
//find subscription based on customer id and order/plan id
|
1254 |
+
$subscriptions = $this->customer->subscriptions->all();
|
1255 |
+
|
1256 |
//no subscriptions
|
1257 |
if(empty($subscriptions) || empty($subscriptions->data))
|
1258 |
+
return false;
|
1259 |
+
|
1260 |
//we really want to test against the order codes of all orders with the same subscription_transaction_id (customer id)
|
1261 |
$codes = $wpdb->get_col("SELECT code FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . $order->user_id . "' AND subscription_transaction_id = '" . $order->subscription_transaction_id . "' AND status NOT IN('refunded', 'review', 'token', 'error')");
|
1262 |
+
|
1263 |
//find the one for this order
|
1264 |
foreach($subscriptions->data as $sub)
|
1265 |
+
{
|
1266 |
if(in_array($sub->plan->id, $codes))
|
1267 |
{
|
1268 |
return $sub;
|
1269 |
}
|
1270 |
}
|
1271 |
+
|
1272 |
+
//didn't find anything yet
|
1273 |
return false;
|
1274 |
}
|
1275 |
+
|
1276 |
/**
|
1277 |
* Create a new subscription with Stripe
|
1278 |
+
*
|
1279 |
* @since 1.4
|
1280 |
*/
|
1281 |
function subscribe(&$order, $checkout = true)
|
1282 |
{
|
1283 |
global $pmpro_currency;
|
1284 |
+
|
1285 |
//create a code for the order
|
1286 |
if(empty($order->code))
|
1287 |
$order->code = $order->getRandomCode();
|
1288 |
+
|
1289 |
//filter order before subscription. use with care.
|
1290 |
$order = apply_filters("pmpro_subscribe_order", $order, $this);
|
1291 |
+
|
1292 |
//figure out the user
|
1293 |
if(!empty($order->user_id))
|
1294 |
$user_id = $order->user_id;
|
1297 |
global $current_user;
|
1298 |
$user_id = $current_user->ID;
|
1299 |
}
|
1300 |
+
|
1301 |
//setup customer
|
1302 |
$result = $this->getCustomer($order);
|
1303 |
if(empty($result))
|
1304 |
return false; //error retrieving customer
|
1305 |
+
|
1306 |
//set subscription id to custom id
|
1307 |
$order->subscription_transaction_id = $this->customer['id']; //transaction id is the customer id, we save it in user meta later too
|
1308 |
+
|
1309 |
//figure out the amounts
|
1310 |
$amount = $order->PaymentAmount;
|
1311 |
+
$amount_tax = $order->getTaxForPrice($amount);
|
1312 |
$amount = round((float)$amount + (float)$amount_tax, 2);
|
1313 |
|
1314 |
/*
|
1315 |
There are two parts to the trial. Part 1 is simply the delay until the first payment
|
1316 |
since we are doing the first payment as a separate transaction.
|
1317 |
The second part is the actual "trial" set by the admin.
|
1318 |
+
|
1319 |
Stripe only supports Year or Month for billing periods, but we account for Days and Weeks just in case.
|
1320 |
*/
|
1321 |
+
//figure out the trial length (first payment handled by initial charge)
|
1322 |
if($order->BillingPeriod == "Year")
|
1323 |
$trial_period_days = $order->BillingFrequency * 365; //annual
|
1324 |
elseif($order->BillingPeriod == "Day")
|
1327 |
$trial_period_days = $order->BillingFrequency * 7; //weekly
|
1328 |
else
|
1329 |
$trial_period_days = $order->BillingFrequency * 30; //assume monthly
|
1330 |
+
|
1331 |
//convert to a profile start date
|
1332 |
$order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
|
1333 |
+
|
1334 |
//filter the start date
|
1335 |
+
$order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
|
1336 |
+
|
1337 |
+
//convert back to days
|
1338 |
$trial_period_days = ceil(abs(strtotime(date("Y-m-d"), current_time("timestamp")) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
|
1339 |
|
1340 |
//for free trials, just push the start date of the subscription back
|
1341 |
+
if(!empty($order->TrialBillingCycles) && $order->TrialAmount == 0)
|
1342 |
{
|
1343 |
$trialOccurrences = (int)$order->TrialBillingCycles;
|
1344 |
if($order->BillingPeriod == "Year")
|
1354 |
{
|
1355 |
/*
|
1356 |
Let's set the subscription to the trial and give the user an "update" to change the sub later to full price (since v2.0)
|
1357 |
+
|
1358 |
This will force TrialBillingCycles > 1 to act as if they were 1
|
1359 |
+
*/
|
1360 |
$new_user_updates = array();
|
1361 |
$new_user_updates[] = array(
|
1362 |
'when' => 'payment',
|
1363 |
'billing_amount' => $order->PaymentAmount,
|
1364 |
'cycle_period' => $order->BillingPeriod,
|
1365 |
'cycle_number' => $order->BillingFrequency
|
1366 |
+
);
|
1367 |
+
|
1368 |
//now amount to equal the trial #s
|
1369 |
$amount = $order->TrialAmount;
|
1370 |
$amount_tax = $order->getTaxForPrice($amount);
|
1371 |
$amount = round((float)$amount + (float)$amount_tax, 2);
|
1372 |
+
}
|
1373 |
+
|
1374 |
//create a plan
|
1375 |
+
try
|
1376 |
{
|
1377 |
$plan = array(
|
1378 |
"amount" => $amount * 100,
|
1384 |
"id" => $order->code
|
1385 |
);
|
1386 |
|
1387 |
+
$plan = Stripe_Plan::create(apply_filters('pmpro_stripe_create_plan_array', $plan));
|
1388 |
}
|
1389 |
catch (Exception $e)
|
1390 |
{
|
1392 |
$order->shorterror = $order->error;
|
1393 |
return false;
|
1394 |
}
|
1395 |
+
|
1396 |
//before subscribing, let's clear out the updates so we don't trigger any during sub
|
1397 |
if(!empty($user_id))
|
1398 |
+
{
|
1399 |
$old_user_updates = get_user_meta($user_id, "pmpro_stripe_updates", true);
|
1400 |
+
update_user_meta($user_id, "pmpro_stripe_updates", array());
|
1401 |
+
}
|
1402 |
+
|
1403 |
if(empty($order->subscription_transaction_id) && !empty($this->customer['id']))
|
1404 |
$order->subscription_transaction_id = $this->customer['id'];
|
1405 |
+
|
1406 |
//subscribe to the plan
|
1407 |
try
|
1408 |
{
|
1409 |
+
$subscription = array("plan" => $order->code);
|
1410 |
+
$result = $this->customer->subscriptions->create(apply_filters('pmpro_stripe_create_subscription_array', $subscription));
|
1411 |
}
|
1412 |
catch (Exception $e)
|
1413 |
{
|
1414 |
//try to delete the plan
|
1415 |
$plan->delete();
|
1416 |
+
|
1417 |
//give the user any old updates back
|
1418 |
if(!empty($user_id))
|
1419 |
update_user_meta($user_id, "pmpro_stripe_updates", $old_user_updates);
|
1420 |
+
|
1421 |
//return error
|
1422 |
$order->error = __("Error subscribing customer to plan with Stripe:", "pmpro") . $e->getMessage();
|
1423 |
$order->shorterror = $order->error;
|
1424 |
return false;
|
1425 |
}
|
1426 |
+
|
1427 |
//delete the plan
|
1428 |
$plan = Stripe_Plan::retrieve($order->code);
|
1429 |
+
$plan->delete();
|
1430 |
|
1431 |
+
//if we got this far, we're all good
|
1432 |
+
$order->status = "success";
|
1433 |
$order->subscription_transaction_id = $result['id'];
|
1434 |
+
|
1435 |
//save new updates if this is at checkout
|
1436 |
if($checkout)
|
1437 |
+
{
|
1438 |
//empty out updates unless set above
|
1439 |
if(empty($new_user_updates))
|
1440 |
$new_user_updates = array();
|
1441 |
+
|
1442 |
//update user meta
|
1443 |
+
if(!empty($user_id))
|
1444 |
update_user_meta($user_id, "pmpro_stripe_updates", $new_user_updates);
|
1445 |
else
|
1446 |
{
|
1460 |
//give them their old updates back
|
1461 |
update_user_meta($user_id, "pmpro_stripe_updates", $old_user_updates);
|
1462 |
}
|
1463 |
+
|
1464 |
return true;
|
1465 |
+
}
|
1466 |
+
|
1467 |
/**
|
1468 |
* Helper method to update the customer info via getCustomer
|
1469 |
+
*
|
1470 |
* @since 1.4
|
1471 |
*/
|
1472 |
function update(&$order)
|
1473 |
{
|
1474 |
//we just have to run getCustomer which will look for the customer and update it with the new token
|
1475 |
$result = $this->getCustomer($order);
|
1476 |
+
|
1477 |
if(!empty($result))
|
1478 |
{
|
1479 |
return true;
|
1480 |
+
}
|
1481 |
else
|
1482 |
{
|
1483 |
return false; //couldn't find the customer
|
1484 |
}
|
1485 |
}
|
1486 |
+
|
1487 |
/**
|
1488 |
* Cancel a subscription at Stripe
|
1489 |
+
*
|
1490 |
* @since 1.4
|
1491 |
*/
|
1492 |
function cancel(&$order, $update_status = true)
|
1494 |
//no matter what happens below, we're going to cancel the order in our system
|
1495 |
if($update_status)
|
1496 |
$order->updateStatus("cancelled");
|
1497 |
+
|
1498 |
//require a subscription id
|
1499 |
if(empty($order->subscription_transaction_id))
|
1500 |
return false;
|
1501 |
+
|
1502 |
//find the customer
|
1503 |
+
$result = $this->getCustomer($order);
|
1504 |
+
|
1505 |
if(!empty($result))
|
1506 |
{
|
1507 |
//find subscription with this order code
|
1508 |
+
$subscription = $this->getSubscription($order);
|
1509 |
|
1510 |
if(!empty($subscription))
|
1511 |
+
{
|
1512 |
if($this->cancelSubscriptionAtGateway($subscription))
|
1513 |
{
|
1514 |
//we're okay, going to return true later
|
1517 |
{
|
1518 |
$order->error = __("Could not cancel old subscription.", "pmpro");
|
1519 |
$order->shorterror = $order->error;
|
1520 |
+
|
1521 |
+
return false;
|
1522 |
+
}
|
1523 |
+
}
|
1524 |
+
|
1525 |
/*
|
1526 |
Clear updates for this user. (But not if checking out, we would have already done that.)
|
1527 |
*/
|
1528 |
if(empty($_REQUEST['submit-checkout']))
|
1529 |
update_user_meta($order->user_id, "pmpro_stripe_updates", array());
|
1530 |
+
|
1531 |
return true;
|
1532 |
}
|
1533 |
else
|
1535 |
$order->error = __("Could not find the customer.", "pmpro");
|
1536 |
$order->shorterror = $order->error;
|
1537 |
return false; //no customer found
|
1538 |
+
}
|
1539 |
+
}
|
1540 |
+
|
1541 |
/**
|
1542 |
* Helper method to cancel a subscription at Stripe and also clear up any upaid invoices.
|
1543 |
+
*
|
1544 |
* @since 1.8
|
1545 |
*/
|
1546 |
function cancelSubscriptionAtGateway($subscription)
|
1548 |
//need a valid sub
|
1549 |
if(empty($subscription->id))
|
1550 |
return false;
|
1551 |
+
|
1552 |
//make sure we get the customer for this subscription
|
1553 |
$order = new MemberOrder();
|
1554 |
+
$order->getLastMemberOrderBySubscriptionTransactionID($subscription->id);
|
1555 |
+
|
1556 |
//no order?
|
1557 |
if(empty($order))
|
1558 |
{
|
1559 |
//lets cancel anyway, but this is suspicious
|
1560 |
$r = $subscription->cancel();
|
1561 |
+
|
1562 |
return true;
|
1563 |
}
|
1564 |
+
|
1565 |
//okay have an order, so get customer so we can cancel invoices too
|
1566 |
$this->getCustomer($order);
|
1567 |
+
|
1568 |
//get open invoices
|
1569 |
$invoices = $this->customer->invoices();
|
1570 |
$invoices = $invoices->all();
|
1571 |
+
|
1572 |
//found it, cancel it
|
1573 |
try
|
1574 |
+
{
|
1575 |
//find any open invoices for this subscription and forgive them
|
1576 |
if(!empty($invoices))
|
1577 |
{
|
1578 |
foreach($invoices->data as $invoice)
|
1579 |
+
{
|
1580 |
if(!$invoice->closed && $invoice->subscription == $subscription->id)
|
1581 |
+
{
|
1582 |
$invoice->closed = true;
|
1583 |
$invoice->save();
|
1584 |
}
|
1585 |
}
|
1586 |
+
}
|
1587 |
+
|
1588 |
//cancel
|
1589 |
$r = $subscription->cancel();
|
1590 |
+
|
1591 |
return true;
|
1592 |
}
|
1593 |
catch(Exception $e)
|
1594 |
+
{
|
1595 |
return false;
|
1596 |
}
|
1597 |
}
|
email/admin_change_admin.html
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
<p>An administrator at !!sitename!! has changed a membership level
|
2 |
|
3 |
<p>!!membership_change!!.</p>
|
4 |
|
1 |
+
<p>An administrator at !!sitename!! has changed a membership level for !!name!!.</p>
|
2 |
|
3 |
<p>!!membership_change!!.</p>
|
4 |
|
includes/currencies.php
CHANGED
@@ -23,7 +23,14 @@
|
|
23 |
),
|
24 |
'CAD' => __('Canadian Dollars ($)', 'pmpro'),
|
25 |
'CNY' => __('Chinese Yuan', 'pmpro'),
|
26 |
-
'CZK' =>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
'DKK' => __('Danish Krone', 'pmpro'),
|
28 |
'HKD' => __('Hong Kong Dollar ($)', 'pmpro'),
|
29 |
'HUF' => __('Hungarian Forint', 'pmpro'),
|
23 |
),
|
24 |
'CAD' => __('Canadian Dollars ($)', 'pmpro'),
|
25 |
'CNY' => __('Chinese Yuan', 'pmpro'),
|
26 |
+
'CZK' => array(
|
27 |
+
'name' => __('Czech Koruna', 'pmpro'),
|
28 |
+
'decimals' => '0',
|
29 |
+
'thousands_separator' => ' ',
|
30 |
+
'decimal_separator' => ',',
|
31 |
+
'symbol' => ' Kč',
|
32 |
+
'position' => 'right',
|
33 |
+
),
|
34 |
'DKK' => __('Danish Krone', 'pmpro'),
|
35 |
'HKD' => __('Hong Kong Dollar ($)', 'pmpro'),
|
36 |
'HUF' => __('Hungarian Forint', 'pmpro'),
|
includes/filters.php
CHANGED
@@ -147,4 +147,12 @@ function pmpro_required_billing_fields_stripe_lite($fields)
|
|
147 |
|
148 |
//ship it!
|
149 |
return $fields;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
}
|
147 |
|
148 |
//ship it!
|
149 |
return $fields;
|
150 |
+
}
|
151 |
+
|
152 |
+
//copy other discount code to discount code if latter is not set
|
153 |
+
if(empty($_REQUEST['discount_code']) && !empty($_REQUEST['other_discount_code']))
|
154 |
+
{
|
155 |
+
$_REQUEST['discount_code'] = $_REQUEST['other_discount_code'];
|
156 |
+
$_POST['discount_code'] = $_POST['other_discount_code'];
|
157 |
+
$_GET['discount_code'] = $_GET['other_discount_code'];
|
158 |
}
|
includes/functions.php
CHANGED
@@ -237,7 +237,7 @@ function pmpro_getLevelCost(&$level, $tags = true, $short = false)
|
|
237 |
if(!$short)
|
238 |
$r = sprintf(__('The price for membership is <strong>%s every %d %s</strong>.', 'pmpro'), pmpro_formatPrice($level->initial_payment), $level->cycle_number, pmpro_translate_billing_period($level->cycle_period, $level->cycle_number) );
|
239 |
else
|
240 |
-
$r = sprintf(__('<strong>%s every %d %s</strong>.', 'pmpro'), pmpro_formatPrice($level->initial_payment), $level->cycle_number, pmpro_translate_billing_period($level->cycle_period, $level->cycle_number) );
|
241 |
}
|
242 |
} else {
|
243 |
if($level->cycle_number == '1')
|
@@ -422,6 +422,7 @@ if(!function_exists("formatPhone"))
|
|
422 |
|
423 |
function pmpro_showRequiresMembershipMessage()
|
424 |
{
|
|
|
425 |
//get the correct message
|
426 |
if(is_feed())
|
427 |
{
|
@@ -636,7 +637,7 @@ function pmpro_changeMembershipLevel($level, $user_id = NULL, $old_level_status
|
|
636 |
|
637 |
if(!empty($c_order->error))
|
638 |
$pmpro_error = $c_order->error;
|
639 |
-
}
|
640 |
}
|
641 |
|
642 |
//insert current membership
|
@@ -1804,15 +1805,18 @@ function pmpro_formatPrice($price)
|
|
1804 |
//settings stored in array?
|
1805 |
if(!empty($pmpro_currencies[$pmpro_currency]) && is_array($pmpro_currencies[$pmpro_currency]))
|
1806 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1807 |
//which side is the symbol on?
|
1808 |
if(!empty($pmpro_currencies[$pmpro_currency]['position']) && $pmpro_currencies[$pmpro_currency]['position']== 'left')
|
1809 |
$formatted = $pmpro_currency_symbol . $formatted;
|
1810 |
else
|
1811 |
$formatted = $formatted . $pmpro_currency_symbol;
|
1812 |
-
|
1813 |
-
//commas or periods?
|
1814 |
-
if(!empty($pmpro_currencies[$pmpro_currency]['separator']) && $pmpro_currencies[$pmpro_currency]['separator'])
|
1815 |
-
$formatted = str_replace(array(".",","), $pmpro_currencies[$pmpro_currency]['separator'], $formatted);
|
1816 |
}
|
1817 |
else
|
1818 |
$formatted = $pmpro_currency_symbol . $formatted; //default to symbol on the left
|
@@ -1834,7 +1838,7 @@ function pmpro_getCurrencyPosition()
|
|
1834 |
return $pmpro_currencies[$pmpro_currency]['position'];
|
1835 |
else
|
1836 |
return "left";
|
1837 |
-
}
|
1838 |
|
1839 |
/*
|
1840 |
* What gateway should we be using?
|
@@ -1865,4 +1869,4 @@ function pmpro_getGateway()
|
|
1865 |
$gateway = apply_filters('pmpro_get_gateway', $gateway, $valid_gateways);
|
1866 |
|
1867 |
return $gateway;
|
1868 |
-
}
|
237 |
if(!$short)
|
238 |
$r = sprintf(__('The price for membership is <strong>%s every %d %s</strong>.', 'pmpro'), pmpro_formatPrice($level->initial_payment), $level->cycle_number, pmpro_translate_billing_period($level->cycle_period, $level->cycle_number) );
|
239 |
else
|
240 |
+
$r = sprintf(__('<strong>%s every %d %s</strong>.', 'pmpro'), pmpro_formatPrice($level->initial_payment), $level->cycle_number, pmpro_translate_billing_period($level->cycle_period, $level->cycle_number) );
|
241 |
}
|
242 |
} else {
|
243 |
if($level->cycle_number == '1')
|
422 |
|
423 |
function pmpro_showRequiresMembershipMessage()
|
424 |
{
|
425 |
+
//TODO $current_user $post_membership_levels_names are undefined variables
|
426 |
//get the correct message
|
427 |
if(is_feed())
|
428 |
{
|
637 |
|
638 |
if(!empty($c_order->error))
|
639 |
$pmpro_error = $c_order->error;
|
640 |
+
}
|
641 |
}
|
642 |
|
643 |
//insert current membership
|
1805 |
//settings stored in array?
|
1806 |
if(!empty($pmpro_currencies[$pmpro_currency]) && is_array($pmpro_currencies[$pmpro_currency]))
|
1807 |
{
|
1808 |
+
//format number do decimals, with decimal_separator and thousands_separator
|
1809 |
+
$formatted = number_format($price,
|
1810 |
+
(isset($pmpro_currencies[$pmpro_currency]['decimals']) ? (int)$pmpro_currencies[$pmpro_currency]['decimals'] : 2),
|
1811 |
+
$pmpro_currencies[$pmpro_currency]['decimal_separator'],
|
1812 |
+
$pmpro_currencies[$pmpro_currency]['thousands_separator']
|
1813 |
+
);
|
1814 |
+
|
1815 |
//which side is the symbol on?
|
1816 |
if(!empty($pmpro_currencies[$pmpro_currency]['position']) && $pmpro_currencies[$pmpro_currency]['position']== 'left')
|
1817 |
$formatted = $pmpro_currency_symbol . $formatted;
|
1818 |
else
|