Paid Memberships Pro - Version 1.8.6

Version Description

  • BUG: The pmpro_membership_level_profile_fields_update() function now only fires on the personal_options_update and edit_user_profile_update hooks instead of the profile_update hook since this function expects to be called from the your-profile or edit-user page.
  • FEATURE: Added the ability to print invoices/orders from the Memberships -> Orders page in the dashboard. (Thanks, AgResources)
  • FEATURE: Added the ability to email invoices/orders from the Memberships -> Orders page in the dashboard. (Thanks, AgResources)
  • ENHANCEMENT: Added pmpro_before_change_membership_level action. Runs before the subscriptions are cancelled and before the SQL executes to change a user's level. Passes $level_id and $user_id.
  • ENHANCEMENT: Updated Stripe Web Hook handler to save event into global $pmpro_stripe_event so filters can act on it.
  • ENHANCEMENT: Added $pmpro_level as a second parameter for the pmpro_setup_new_user filter. (Thanks, David Crabill)
  • ENHANCEMENT: Added Vietnamese language pack. (Thanks, Alex Training Center)
Download this release

Release Info

Developer strangerstudios
Plugin Icon 128x128 Paid Memberships Pro
Version 1.8.6
Comparing to
See all releases

Code changes from version 1.8.5.5 to 1.8.6

Files changed (48) hide show
  1. adminpages/orders-print.php +39 -0
  2. adminpages/orders.php +149 -87
  3. adminpages/templates/orders-print.php +71 -0
  4. classes/class.pmproemail.php +51 -0
  5. classes/gateways/class.pmprogateway_payflowpro.php +42 -0
  6. classes/gateways/class.pmprogateway_stripe.php +8 -4
  7. css/frontend.css +1 -4
  8. email/billable_invoice.html +6 -0
  9. includes/currencies.php +11 -1
  10. includes/functions.php +72 -17
  11. includes/profile.php +2 -1
  12. includes/services.php +24 -0
  13. languages/email/vi_VN/admin_change.html +7 -0
  14. languages/email/vi_VN/admin_change_admin.html +5 -0
  15. languages/email/vi_VN/billing.html +16 -0
  16. languages/email/vi_VN/billing_admin.html +17 -0
  17. languages/email/vi_VN/billing_failure.html +11 -0
  18. languages/email/vi_VN/billing_failure_admin.html +11 -0
  19. languages/email/vi_VN/cancel.html +3 -0
  20. languages/email/vi_VN/cancel_admin.html +8 -0
  21. languages/email/vi_VN/checkout_check.html +17 -0
  22. languages/email/vi_VN/checkout_check_admin.html +17 -0
  23. languages/email/vi_VN/checkout_express.html +14 -0
  24. languages/email/vi_VN/checkout_express_admin.html +14 -0
  25. languages/email/vi_VN/checkout_free.html +8 -0
  26. languages/email/vi_VN/checkout_free_admin.html +8 -0
  27. languages/email/vi_VN/checkout_freetrial.html +19 -0
  28. languages/email/vi_VN/checkout_freetrial_admin.html +19 -0
  29. languages/email/vi_VN/checkout_paid.html +23 -0
  30. languages/email/vi_VN/checkout_paid_admin.html +23 -0
  31. languages/email/vi_VN/checkout_trial.html +23 -0
  32. languages/email/vi_VN/checkout_trial_admin.html +23 -0
  33. languages/email/vi_VN/credit_card_expiring.html +13 -0
  34. languages/email/vi_VN/default.html +1 -0
  35. languages/email/vi_VN/footer.html +4 -0
  36. languages/email/vi_VN/header.html +1 -0
  37. languages/email/vi_VN/invoice.html +19 -0
  38. languages/email/vi_VN/membership_expired.html +7 -0
  39. languages/email/vi_VN/membership_expiring.html +6 -0
  40. languages/email/vi_VN/trial_ending.html +8 -0
  41. languages/pmpro-vi_VN.mo +0 -0
  42. languages/pmpro-vi_VN.po +4556 -0
  43. pages/checkout.php +8 -4
  44. paid-memberships-pro.php +2 -2
  45. preheaders/checkout.php +1 -1
  46. readme.txt +22 -2
  47. services/ipnhandler.php +1 -1
  48. services/stripe-webhook.php +32 -31
adminpages/orders-print.php ADDED
@@ -0,0 +1,39 @@
1
+ <?php
2
+ /**
3
+ * Order - Print View
4
+ *
5
+ * Gets the order and displays the print view template.
6
+ *
7
+ * @since 1.8.6
8
+ */
9
+
10
+ //only admins can get this
11
+ if ( ! function_exists( "current_user_can" ) || ( ! current_user_can( "manage_options" ) && ! current_user_can( "pmpro_ordersprint" ) ) ) {
12
+ die( __( "You do not have permissions to perform this action.", "pmpro" ) );
13
+ }
14
+
15
+ // Do we have an order ID?
16
+ if ( empty( $_REQUEST['order'] ) ) {
17
+ wp_redirect( admin_url( 'admin..php?page=pmpro-orders' ) );
18
+ exit;
19
+ }
20
+
21
+ // Get order and membership level.
22
+ $order = new MemberOrder($_REQUEST['order']);
23
+ $level = pmpro_getLevel($order->membership_id);
24
+
25
+ // Load template
26
+ if ( file_exists( get_stylesheet_directory() . '/paid-memberships-pro/pages/orders-print.php' ) ) {
27
+ $template = get_stylesheet_directory() . '/paid-memberships-pro/pages/orders-print.php';
28
+ } elseif ( file_exists( get_template_directory() . '/paid-memberships-pro/pages/orders-print.php' ) ) {
29
+ $template = get_template_directory() . '/paid-memberships-pro/pages/orders-print.php';
30
+ } else {
31
+ $template = PMPRO_DIR . '/adminpages/templates/orders-print.php';
32
+ }
33
+
34
+ require_once( $template );
35
+ ?>
36
+ <script>
37
+ window.print();
38
+ </script>
39
+
adminpages/orders.php CHANGED
@@ -57,6 +57,109 @@
57
else
58
$status = "";
59
60
61
//deleting?
62
if(!empty($_REQUEST['delete']))
@@ -81,8 +184,6 @@
81
82
$thisyear = date("Y");
83
84
-
85
-
86
//this array stores fields that should be read only
87
$read_only_fields = apply_filters("pmpro_orders_read_only_fields", array("code", "payment_transaction_id", "subscription_transaction_id"));
88
@@ -564,7 +665,42 @@
564
</form>
565
566
<?php } else { ?>
567
-
568
<form id="posts-filter" method="get" action="">
569
<h2>
570
<?php _e('Orders', 'pmpro');?>
@@ -646,8 +782,7 @@
646
647
<?php
648
//Note: only orders belonging to current levels can be filtered. There is no option for orders belonging to deleted levels
649
- $levels = pmpro_getAllLevels();
650
-
651
?>
652
<select id="l" name="l">
653
<?php foreach($levels as $level) { ?>
@@ -781,85 +916,6 @@
781
</p>
782
783
<?php
784
- //some vars for the search
785
- if(isset($_REQUEST['pn']))
786
- $pn = intval($_REQUEST['pn']);
787
- else
788
- $pn = 1;
789
-
790
- if(isset($_REQUEST['limit']))
791
- $limit = intval($_REQUEST['limit']);
792
- else
793
- {
794
- /**
795
- * Filter to set the default number of items to show per page
796
- * on the Orders page in the admin.
797
- *
798
- * @since 1.8.4.5
799
- *
800
- * @param int $limit The number of items to show per page.
801
- */
802
- $limit = apply_filters('pmpro_orders_per_page', 15);
803
- }
804
-
805
- $end = $pn * $limit;
806
- $start = $end - $limit;
807
-
808
- //filters
809
- if($filter == "all" || !$filter)
810
- $condition = "1=1";
811
- elseif($filter == "within-a-date-range")
812
- {
813
- $start_date = $start_year."-".$start_month."-".$start_day;
814
- $end_date = $end_year."-".$end_month."-".$end_day;
815
-
816
- //add times to dates
817
- $start_date = $start_date . " 00:00:00";
818
- $end_date = $end_date . " 23:59:59";
819
-
820
- $condition = "timestamp BETWEEN '".esc_sql($start_date)."' AND '".esc_sql($end_date)."'";
821
- }
822
- elseif($filter == "predefined-date-range")
823
- {
824
- if($predefined_date == "Last Month")
825
- {
826
- $start_date = date("Y-m-d", strtotime("first day of last month", current_time("timestamp")));
827
- $end_date = date("Y-m-d", strtotime("last day of last month", current_time("timestamp")));
828
- }
829
- elseif($predefined_date == "This Month")
830
- {
831
- $start_date = date("Y-m-d", strtotime("first day of this month", current_time("timestamp")));
832
- $end_date = date("Y-m-d", strtotime("last day of this month", current_time("timestamp")));
833
- }
834
- elseif($predefined_date == "This Year")
835
- {
836
- $year = date('Y');
837
- $start_date = date("Y-m-d", strtotime("first day of January $year", current_time("timestamp")));
838
- $end_date = date("Y-m-d", strtotime("last day of December $year", current_time("timestamp")));
839
- }
840
-
841
- elseif($predefined_date == "Last Year")
842
- {
843
- $year = date('Y') - 1;
844
- $start_date = date("Y-m-d", strtotime("first day of January $year", current_time("timestamp")));
845
- $end_date = date("Y-m-d", strtotime("last day of December $year", current_time("timestamp")));
846
- }
847
-
848
- //add times to dates
849
- $start_date = $start_date . " 00:00:00";
850
- $end_date = $end_date . " 23:59:59";
851
-
852
- $condition = "timestamp BETWEEN '".esc_sql($start_date)."' AND '".esc_sql($end_date)."'";
853
- }
854
- elseif($filter == "within-a-level")
855
- {
856
- $condition = "membership_id = " . esc_sql($l);
857
- }
858
- elseif($filter == "within-a-status")
859
- {
860
- $condition = "status = '" . esc_sql($status) . "' ";
861
- }
862
-
863
//string search
864
if($s)
865
{
@@ -904,7 +960,7 @@
904
<?php
905
}
906
?>
907
- <table class="widefat">
908
<thead>
909
<tr class="thead">
910
<th><?php _e('ID', 'pmpro');?></th>
@@ -921,6 +977,8 @@
921
<th></th>
922
<th></th>
923
<th></th>
924
</tr>
925
</thead>
926
<tbody id="orders" class="list:order orders-list">
@@ -997,6 +1055,12 @@
997
<td align="center">
998
<a href="javascript:askfirst('<?php echo str_replace("'", "\'", sprintf(__("Deleting orders is permanent and can affect active users. Are you sure you want to delete order %s?", "pmpro"), str_replace("'", "", $order->code)));?>', 'admin.php?page=pmpro-orders&delete=<?php echo $order->id;?>'); void(0);"><?php _e('delete', 'pmpro');?></a>
999
</td>
1000
</tr>
1001
<?php
1002
}
@@ -1013,7 +1077,6 @@
1013
</tbody>
1014
</table>
1015
</form>
1016
-
1017
<?php
1018
//add normal args
1019
$pagination_url = add_query_arg($url_params, get_admin_url(NULL, "/admin.php?page=pmpro-orders"));
@@ -1021,7 +1084,6 @@
1021
?>
1022
1023
<?php } ?>
1024
-
1025
<?php
1026
require_once(dirname(__FILE__) . "/admin_footer.php");
1027
?>
57
else
58
$status = "";
59
60
+ //some vars for the search
61
+ if(isset($_REQUEST['pn']))
62
+ $pn = intval($_REQUEST['pn']);
63
+ else
64
+ $pn = 1;
65
+
66
+ if(isset($_REQUEST['limit']))
67
+ $limit = intval($_REQUEST['limit']);
68
+ else
69
+ {
70
+ /**
71
+ * Filter to set the default number of items to show per page
72
+ * on the Orders page in the admin.
73
+ *
74
+ * @since 1.8.4.5
75
+ *
76
+ * @param int $limit The number of items to show per page.
77
+ */
78
+ $limit = apply_filters('pmpro_orders_per_page', 15);
79
+ }
80
+
81
+ $end = $pn * $limit;
82
+ $start = $end - $limit;
83
+
84
+ //filters
85
+ if(empty($filter) || $filter === "all")
86
+ {
87
+ $condition = "1=1";
88
+ $filter = "all";
89
+ }
90
+ elseif($filter == "within-a-date-range")
91
+ {
92
+ $start_date = $start_year."-".$start_month."-".$start_day;
93
+ $end_date = $end_year."-".$end_month."-".$end_day;
94
+
95
+ //add times to dates
96
+ $start_date = $start_date . " 00:00:00";
97
+ $end_date = $end_date . " 23:59:59";
98
+
99
+ $condition = "timestamp BETWEEN '".esc_sql($start_date)."' AND '".esc_sql($end_date)."'";
100
+ }
101
+ elseif($filter == "predefined-date-range")
102
+ {
103
+ if($predefined_date == "Last Month")
104
+ {
105
+ $start_date = date("Y-m-d", strtotime("first day of last month", current_time("timestamp")));
106
+ $end_date = date("Y-m-d", strtotime("last day of last month", current_time("timestamp")));
107
+ }
108
+ elseif($predefined_date == "This Month")
109
+ {
110
+ $start_date = date("Y-m-d", strtotime("first day of this month", current_time("timestamp")));
111
+ $end_date = date("Y-m-d", strtotime("last day of this month", current_time("timestamp")));
112
+ }
113
+ elseif($predefined_date == "This Year")
114
+ {
115
+ $year = date('Y');
116
+ $start_date = date("Y-m-d", strtotime("first day of January $year", current_time("timestamp")));
117
+ $end_date = date("Y-m-d", strtotime("last day of December $year", current_time("timestamp")));
118
+ }
119
+
120
+ elseif($predefined_date == "Last Year")
121
+ {
122
+ $year = date('Y') - 1;
123
+ $start_date = date("Y-m-d", strtotime("first day of January $year", current_time("timestamp")));
124
+ $end_date = date("Y-m-d", strtotime("last day of December $year", current_time("timestamp")));
125
+ }
126
+
127
+ //add times to dates
128
+ $start_date = $start_date . " 00:00:00";
129
+ $end_date = $end_date . " 23:59:59";
130
+
131
+ $condition = "timestamp BETWEEN '".esc_sql($start_date)."' AND '".esc_sql($end_date)."'";
132
+ }
133
+ elseif($filter == "within-a-level")
134
+ {
135
+ $condition = "membership_id = " . esc_sql($l);
136
+ }
137
+ elseif($filter == "within-a-status")
138
+ {
139
+ $condition = "status = '" . esc_sql($status) . "' ";
140
+ }
141
+
142
+ //emailing?
143
+ if(!empty($_REQUEST['email']) && !empty($_REQUEST['order']))
144
+ {
145
+ $email = new PMProEmail();
146
+ $user = get_user_by('email', $_REQUEST['email']);
147
+ $order = new MemberOrder($_REQUEST['order']);
148
+ if($email->sendBillableInvoiceEmail($user, $order))
149
+ {
150
+ $pmpro_msg = __("Invoice emailed successfully.", "pmpro");
151
+ $pmpro_msgt = "success";
152
+ }
153
+ else
154
+ {
155
+ $pmpro_msg = __("Error emailing invoice.", "pmpro");
156
+ $pmpro_msgt = "error";
157
+ }
158
+
159
+ //clean up so we stay on the orders list view
160
+ unset($_REQUEST['order']);
161
+ $order = NULL;
162
+ }
163
164
//deleting?
165
if(!empty($_REQUEST['delete']))
184
185
$thisyear = date("Y");
186
187
//this array stores fields that should be read only
188
$read_only_fields = apply_filters("pmpro_orders_read_only_fields", array("code", "payment_transaction_id", "subscription_transaction_id"));
189
665
</form>
666
667
<?php } else { ?>
668
+ <?php
669
+ /**
670
+ * Code to handle emailing billable invoices.
671
+ *
672
+ * @since 1.8.6
673
+ */
674
+ ?>
675
+ <script>
676
+ // Update fields in email modal.
677
+ jQuery(document).ready(function($) {
678
+ var order, order_id;
679
+ $('.email_link').click(function() {
680
+ order_id = $(this).data('order');
681
+ $('input[name=order]').val(order_id);
682
+ // Get email address from order ID
683
+ data = {
684
+ action: 'pmpro_get_order_json',
685
+ order_id: order_id
686
+ };
687
+ $.post(ajaxurl, data, function(response) {
688
+ order = JSON.parse(response);
689
+ $('input[name=email]').val(order.Email);
690
+ });
691
+ });
692
+ });
693
+ </script>
694
+ <?php add_thickbox(); ?>
695
+ <div id="email_invoice" style="display:none;">
696
+ <h3><?php _e('Email Invoice', 'pmpro'); ?></h3>
697
+ <form method="post" action="">
698
+ <input type="hidden" name="order" value="" />
699
+ <?php _e('Send an invoice for this order to: ', 'pmpro'); ?>
700
+ <input type="text" value="" name="email" />
701
+ <button class="button button-primary alignright"><?php _e('Send Email', 'pmpro'); ?></button>
702
+ </form>
703
+ </div>
704
<form id="posts-filter" method="get" action="">
705
<h2>
706
<?php _e('Orders', 'pmpro');?>
782
783
<?php
784
//Note: only orders belonging to current levels can be filtered. There is no option for orders belonging to deleted levels
785
+ $levels = pmpro_getAllLevels(true, true);
786
?>
787
<select id="l" name="l">
788
<?php foreach($levels as $level) { ?>
916
</p>
917
918
<?php
919
//string search
920
if($s)
921
{
960
<?php
961
}
962
?>
963
+ <table class="widefat">
964
<thead>
965
<tr class="thead">
966
<th><?php _e('ID', 'pmpro');?></th>
977
<th></th>
978
<th></th>
979
<th></th>
980
+ <th></th>
981
+ <th></th>
982
</tr>
983
</thead>
984
<tbody id="orders" class="list:order orders-list">
1055
<td align="center">
1056
<a href="javascript:askfirst('<?php echo str_replace("'", "\'", sprintf(__("Deleting orders is permanent and can affect active users. Are you sure you want to delete order %s?", "pmpro"), str_replace("'", "", $order->code)));?>', 'admin.php?page=pmpro-orders&delete=<?php echo $order->id;?>'); void(0);"><?php _e('delete', 'pmpro');?></a>
1057
</td>
1058
+ <td align="center">
1059
+ <a href="admin-ajax.php?action=pmpro_orders_print_view&order=<?php echo $order->id; ?>" target="_blank"><?php _e('print', 'pmpro');?></a>
1060
+ </td>
1061
+ <td align="center">
1062
+ <a href="#TB_inline?width=600&height=200&inlineId=email_invoice" class="thickbox email_link" data-order="<?php echo $order->id; ?>"><?php _e('email', 'pmpro');?></a>
1063
+ </td>
1064
</tr>
1065
<?php
1066
}
1077
</tbody>
1078
</table>
1079
</form>
1080
<?php
1081
//add normal args
1082
$pagination_url = add_query_arg($url_params, get_admin_url(NULL, "/admin.php?page=pmpro-orders"));
1084
?>
1085
1086
<?php } ?>
1087
<?php
1088
require_once(dirname(__FILE__) . "/admin_footer.php");
1089
?>
adminpages/templates/orders-print.php ADDED
@@ -0,0 +1,71 @@
1
+ <?php
2
+ /**
3
+ * Template for Order Print Views
4
+ *
5
+ * @since 1.8.6
6
+ */
7
+ ?>
8
+ <table style="width:600px;margin-left:auto;margin-right:auto;">
9
+ <thead>
10
+ <tr>
11
+ <td rowspan="2" style="width:80%;">
12
+ <h2><?php bloginfo( 'sitename' ); ?></h2>
13
+ </td>
14
+ <td><?php echo __('Invoice #: ', 'pmpro') . '&nbsp;' . $order->code; ?></td>
15
+ </tr>
16
+ <tr>
17
+ <td>
18
+ <?php echo __( 'Date:', 'pmpro' ) . '&nbsp;' . date( 'Y-m-d', $order->timestamp ) ?>
19
+ </td>
20
+ </tr>
21
+ <?php if(!empty($order->billing->name)): ?>
22
+ <tr>
23
+ <td>
24
+ <strong><?php _e( 'Bill to:', 'pmpro' ); ?></strong><br>
25
+ <?php
26
+ echo pmpro_formatAddress(
27
+ $order->billing->name,
28
+ $order->billing->street,
29
+ "",
30
+ $order->billing->city,
31
+ $order->billing->state,
32
+ $order->billing->zip,
33
+ $order->billing->country,
34
+ $order->billing->phone
35
+ );
36
+ ?>
37
+ <?php endif; ?>
38
+ </td>
39
+ </tr>
40
+ </thead>
41
+ <tbody>
42
+ <tr>
43
+ <td colspan="2">
44
+ <table style="width:100%;border-width:1px;border-style:solid;border-collapse:collapse;">
45
+ <tr style="border-width:1px;border-style:solid;border-collapse:collapse;">
46
+ <th style="text-align:center;border-width:1px;border-style:solid;border-collapse:collapse;"><?php _e('ID', 'pmpro'); ?></th>
47
+ <th style="border-width:1px;border-style:solid;border-collapse:collapse;"><?php _e('Item', 'pmpro'); ?></th>
48
+ <th style="border-width:1px;border-style:solid;border-collapse:collapse;"><?php _e('Price', 'pmpro'); ?></th>
49
+ </tr>
50
+ <tr style="border-width:1px;border-style:solid;border-collapse:collapse;">
51
+ <td style="text-align:center;border-width:1px;border-style:solid;border-collapse:collapse;"><?php echo $level->id; ?></td>
52
+ <td style="border-width:1px;border-style:solid;border-collapse:collapse;"><?php echo $level->name; ?></td>
53
+ <td style="text-align:right;"><?php echo $order->subtotal; ?></td>
54
+ </tr>
55
+ <tr style="border-width:1px;border-style:solid;border-collapse:collapse;">
56
+ <th colspan="2" style="text-align:right;border-width:1px;border-style:solid;border-collapse:collapse;"><?php _e('Subtotal', 'pmpro'); ?></th>
57
+ <td style="text-align:right;border-width:1px;border-style:solid;border-collapse:collapse;"><?php echo $order->subtotal; ?></td>
58
+ </tr>
59
+ <tr style="border-width:1px;border-style:solid;border-collapse:collapse;">
60
+ <th colspan="2" style="text-align:right;border-width:1px;border-style:solid;border-collapse:collapse;"><?php _e('Tax', 'pmpro'); ?></th>
61
+ <td style="text-align:right;border-width:1px;border-style:solid;border-collapse:collapse;"><?php echo $order->tax; ?></td>
62
+ </tr>
63
+ <tr style="border-width:1px;border-style:solid;border-collapse:collapse;">
64
+ <th colspan="2" style="text-align:right;border-width:1px;border-style:solid;border-collapse:collapse;"><?php _e('Total', 'pmpro'); ?></th>
65
+ <th style="text-align:right;border-width:1px;border-style:solid;border-collapse:collapse;"><?php echo pmpro_formatPrice($order->total); ?></th>
66
+ </tr>
67
+ </table>
68
+ </td>
69
+ </tr>
70
+ </tbody>
71
+ </table>
classes/class.pmproemail.php CHANGED
@@ -821,4 +821,55 @@
821
822
return $this->sendEmail();
823
}
824
}
821
822
return $this->sendEmail();
823
}
824
+
825
+ /**
826
+ * Send billable invoice email.
827
+ *
828
+ * @since 1.8.6
829
+ *
830
+ * @param WP_User $user
831
+ * @param MemberOrder $order
832
+ *
833
+ * @return bool Whether the email was sent successfully.
834
+ */
835
+ function sendBillableInvoiceEmail($user = NULL, $order = NULL)
836
+ {
837
+ global $current_user;
838
+
839
+ if(!$user)
840
+ $user = $current_user;
841
+
842
+ if(!$user || !$order)
843
+ return false;
844
+
845
+ $level = pmpro_getLevel($order->membership_id);
846
+
847
+ $this->email = $user->user_email;
848
+ $this->subject = __('Invoice for Order #: ', 'pmpro') . $order->code;
849
+ $this->template = "billable_invoice";
850
+
851
+ // Load invoice template
852
+ if ( file_exists( get_stylesheet_directory() . '/paid-memberships-pro/pages/orders-print.php' ) ) {
853
+ $template = get_stylesheet_directory() . '/paid-memberships-pro/pages/orders-print.php';
854
+ } elseif ( file_exists( get_template_directory() . '/paid-memberships-pro/pages/orders-print.php' ) ) {
855
+ $template = get_template_directory() . '/paid-memberships-pro/pages/orders-print.php';
856
+ } else {
857
+ $template = PMPRO_DIR . '/adminpages/templates/orders-print.php';
858
+ }
859
+
860
+ ob_start();
861
+ require_once( $template );
862
+
863
+ $invoice = ob_get_contents();
864
+ ob_end_clean();
865
+
866
+ $this->data = array(
867
+ 'order_code' => $order->code,
868
+ 'login_link' => wp_login_url(pmpro_url("account")),
869
+ 'invoice_link' => wp_login_url(pmpro_url("invoice", "?invoice=" . $order->code)),
870
+ 'invoice' => $invoice
871
+ );
872
+
873
+ return $this->sendEmail();
874
+ }
875
}
classes/gateways/class.pmprogateway_payflowpro.php CHANGED
@@ -242,6 +242,13 @@
242
$nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
243
}
244
245
//for debugging, let's attach this to the class object
246
$this->nvpStr = $nvpStr;
247
@@ -268,6 +275,13 @@
268
//paypal profile stuff
269
$nvpStr="&ORIGID=" . $authorization_id;
270
271
$this->httpParsedResponseAr = $this->PPHttpPost('V', $nvpStr);
272
273
if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
@@ -316,6 +330,13 @@
316
$nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
317
}
318
319
$this->nvpStr = $nvpStr;
320
$this->httpParsedResponseAr = $this->PPHttpPost('S', $nvpStr);
321
@@ -432,6 +453,13 @@
432
$nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
433
}
434
435
$this->nvpStr = $nvpStr;
436
$this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
437
@@ -474,6 +502,13 @@
474
$nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
475
}
476
477
$this->nvpStr = $nvpStr;
478
$this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
479
@@ -499,6 +534,13 @@
499
//paypal profile stuff
500
$nvpStr = "&ORIGPROFILEID=" . $order->subscription_transaction_id . "&ACTION=C";
501
502
$this->nvpStr = $nvpStr;
503
$this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
504
242
$nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
243
}
244
245
+ /**
246
+ * Filter NVP string
247
+ *
248
+ * @since 1.8.5.6
249
+ */
250
+ $nvpStr = apply_filters('pmpro_payflow_authorize_nvpstr', $nvpStr, $this);
251
+
252
//for debugging, let's attach this to the class object
253
$this->nvpStr = $nvpStr;
254
275
//paypal profile stuff
276
$nvpStr="&ORIGID=" . $authorization_id;
277
278
+ /**
279
+ * Filter NVP string
280
+ *
281
+ * @since 1.8.5.6
282
+ */
283
+ $nvpStr = apply_filters('pmpro_payflow_void_nvpstr', $nvpStr, $this);
284
+
285
$this->httpParsedResponseAr = $this->PPHttpPost('V', $nvpStr);
286
287
if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
330
$nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
331
}
332
333
+ /**
334
+ * Filter NVP string
335
+ *
336
+ * @since 1.8.5.6
337
+ */
338
+ $nvpStr = apply_filters('pmpro_payflow_charge_nvpstr', $nvpStr, $this);
339
+
340
$this->nvpStr = $nvpStr;
341
$this->httpParsedResponseAr = $this->PPHttpPost('S', $nvpStr);
342
453
$nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
454
}
455
456
+ /**
457
+ * Filter NVP string
458
+ *
459
+ * @since 1.8.5.6
460
+ */
461
+ $nvpStr = apply_filters('pmpro_payflow_subscribe_nvpstr', $nvpStr, $this);
462
+
463
$this->nvpStr = $nvpStr;
464
$this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
465
502
$nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
503
}
504
505
+ /**
506
+ * Filter NVP string
507
+ *
508
+ * @since 1.8.5.6
509
+ */
510
+ $nvpStr = apply_filters('pmpro_payflow_update_nvpstr', $nvpStr, $this);
511
+
512
$this->nvpStr = $nvpStr;
513
$this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
514
534
//paypal profile stuff
535
$nvpStr = "&ORIGPROFILEID=" . $order->subscription_transaction_id . "&ACTION=C";
536
537
+ /**
538
+ * Filter NVP string
539
+ *
540
+ * @since 1.8.5.6
541
+ */
542
+ $nvpStr = apply_filters('pmpro_payflow_cancel_nvpstr', $nvpStr, $this);
543
+
544
$this->nvpStr = $nvpStr;
545
$this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
546
classes/gateways/class.pmprogateway_stripe.php CHANGED
@@ -231,8 +231,7 @@
231
{
232
//build array for creating token
233
var args = {
234
- number: jQuery('#AccountNumber').val(),
235
- cvc: jQuery('#CVV').val(),
236
exp_month: jQuery('#ExpirationMonth').val(),
237
exp_year: jQuery('#ExpirationYear').val()
238
<?php
@@ -251,6 +250,11 @@
251
?>
252
};
253
254
if (jQuery('#bfirstname').length && jQuery('#blastname').length)
255
args['name'] = jQuery.trim(jQuery('#bfirstname').val() + ' ' + jQuery('#blastname').val());
256
@@ -283,7 +287,7 @@
283
// insert the token into the form so it gets submitted to the server
284
form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
285
286
- console.log(response);
287
288
//insert fields for other card fields
289
if(jQuery('#CardType[name=CardType]').length)
@@ -1268,7 +1272,7 @@
1268
}
1269
catch (Exception $e)
1270
{
1271
- $order->error = __("Error creating plan with Stripe:", "pmpro") . $e->getMessage();
1272
$order->shorterror = $order->error;
1273
return false;
1274
}
231
{
232
//build array for creating token
233
var args = {
234
+ number: jQuery('#AccountNumber').val(),
235
exp_month: jQuery('#ExpirationMonth').val(),
236
exp_year: jQuery('#ExpirationYear').val()
237
<?php
250
?>
251
};
252
253
+ //add CVC if not blank
254
+ if(jQuery('#CVV').val().length)
255
+ args['cvc'] = jQuery('#CVV').val();
256
+
257
+ //add first and last name if not blank
258
if (jQuery('#bfirstname').length && jQuery('#blastname').length)
259
args['name'] = jQuery.trim(jQuery('#bfirstname').val() + ' ' + jQuery('#blastname').val());
260
287
// insert the token into the form so it gets submitted to the server
288
form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
289
290
+ //console.log(response);
291
292
//insert fields for other card fields
293
if(jQuery('#CardType[name=CardType]').length)
1272
}
1273
catch (Exception $e)
1274
{
1275
+ $order->error = __("Error getting subscription with Stripe:", "pmpro") . $e->getMessage();
1276
$order->shorterror = $order->error;
1277
return false;
1278
}
css/frontend.css CHANGED
@@ -67,7 +67,7 @@ form.pmpro_form label {float: left; margin: 3px 10px 0 0; width: 200px; font-wei
67
form.pmpro_form label.pmpro_normal {float: none; margin: 0 0 0 0; width: auto; font-weight: normal; text-align: auto;}
68
.pmpro_clickable {cursor: pointer;}
69
form.pmpro_form .likelabel {font-weight: bold; }
70
- form.pmpro_form .input, form.pmpro_form textarea, .input, form.pmpro_form select {border: 1px solid #AAA; display: inline-block; margin: 0 3px 0 0; padding: 3px; width: auto; max-width: 60%; }
71
form.pmpro_form textarea {font-family: Arial, Helvetica, sans-serif; font-size: 12px; }
72
form.pmpro_form select {margin: 2px 0 0 0 ; font-size: 12px;}
73
form.pmpro_form .lite {color: #666; }
@@ -177,9 +177,6 @@ li.pmpro_more {list-style-type: none; text-align: center; margin-left: -20px; pa
177
178
.pmpro_small {font-size: .8em;}
179
180
- /* Fixes for Twentyfiften and other themes. */
181
- #your-profile input {display: inline-block; width: auto; } /* front end profile via Theme My Login */
182
-
183
@media (max-width:768px){
184
#pmpro_levels_table {border: none; }
185
#pmpro_levels_table th {display: none; }
67
form.pmpro_form label.pmpro_normal {float: none; margin: 0 0 0 0; width: auto; font-weight: normal; text-align: auto;}
68
.pmpro_clickable {cursor: pointer;}
69
form.pmpro_form .likelabel {font-weight: bold; }
70
+ form.pmpro_form .input, form.pmpro_form textarea, form.pmpro_form select {border: 1px solid #AAA; display: inline-block; margin: 0 3px 0 0; padding: 3px; width: auto; max-width: 60%; }
71
form.pmpro_form textarea {font-family: Arial, Helvetica, sans-serif; font-size: 12px; }
72
form.pmpro_form select {margin: 2px 0 0 0 ; font-size: 12px;}
73
form.pmpro_form .lite {color: #666; }
177
178
.pmpro_small {font-size: .8em;}
179
180
@media (max-width:768px){
181
#pmpro_levels_table {border: none; }
182
#pmpro_levels_table th {display: none; }
email/billable_invoice.html ADDED
@@ -0,0 +1,6 @@
1
+ <p>Thank you for your membership to !!sitename!!. Below is your invoice for order #: !!order_code!!</p>
2
+
3
+ !!invoice!!
4
+
5
+ <p>Log in to your membership account here: !!login_link!!</p>
6
+ <p>To view an online version of this invoice, click here: !!invoice_link!!</p>
includes/currencies.php CHANGED
@@ -3,12 +3,22 @@
3
global $pmpro_currencies, $pmpro_default_currency;
4
$pmpro_default_currency = apply_filters("pmpro_default_currency", "USD");
5
6
$pmpro_currencies = array(
7
'USD' => __('US Dollars (&#36;)', 'pmpro'),
8
'EUR' => array(
9
'name' => __('Euros (&euro;)', 'pmpro'),
10
'symbol' => '&euro;',
11
- 'position' => 'right'
12
),
13
'GBP' => array(
14
'name' => __('Pounds Sterling (&pound;)', 'pmpro'),
3
global $pmpro_currencies, $pmpro_default_currency;
4
$pmpro_default_currency = apply_filters("pmpro_default_currency", "USD");
5
6
+ function pmpro_euro_position_from_locale($position = 'right')
7
+ {
8
+ $locale = get_locale();
9
+ if(strpos($locale, 'en_') === 0)
10
+ {
11
+ $position = 'left';
12
+ }
13
+ return $position;
14
+ }
15
+
16
$pmpro_currencies = array(
17
'USD' => __('US Dollars (&#36;)', 'pmpro'),
18
'EUR' => array(
19
'name' => __('Euros (&euro;)', 'pmpro'),
20
'symbol' => '&euro;',
21
+ 'position' => apply_filters("pmpro_euro_position", pmpro_euro_position_from_locale())
22
),
23
'GBP' => array(
24
'name' => __('Pounds Sterling (&pound;)', 'pmpro'),
includes/functions.php CHANGED
@@ -486,18 +486,28 @@ function pmpro_showRequiresMembershipMessage()
486
}
487
}
488
489
- /* pmpro_hasMembershipLevel() checks if the passed user is a member of the passed level
490
*
491
* $level may either be the ID or name of the desired membership_level. (or an array of such)
492
* If $user_id is omitted, the value will be retrieved from $current_user.
493
*
494
- * Return values:
495
- * Success returns boolean true.
496
- * Failure returns a string containing the error message.
497
*/
498
function pmpro_hasMembershipLevel($levels = NULL, $user_id = NULL)
499
{
500
- global $current_user, $all_membership_levels, $wpdb;
501
502
$return = false;
503
@@ -530,13 +540,18 @@ function pmpro_hasMembershipLevel($levels = NULL, $user_id = NULL)
530
531
if(empty($membership_levels))
532
{
533
- //user has no levels just check if 0, L, or -L was sent in one of the levels
534
if(in_array(0, $levels, true) || in_array("0", $levels))
535
$return = true;
536
elseif(in_array("L", $levels) || in_array("l", $levels))
537
$return = (!empty($user_id) && $user_id == $current_user->ID);
538
elseif(in_array("-L", $levels) || in_array("-l", $levels))
539
- $return = (empty($user_id) || $user_id != $current_user->ID);
540
}
541
else
542
{
@@ -554,9 +569,9 @@ function pmpro_hasMembershipLevel($levels = NULL, $user_id = NULL)
554
if(empty($user_id) || $user_id != $current_user->ID)
555
$return = true;
556
}
557
- elseif($level == "0")
558
{
559
- continue; //user with levels so not a "non-member"
560
}
561
else
562
{
@@ -667,6 +682,20 @@ function pmpro_changeMembershipLevel($level, $user_id = NULL, $old_level_status
667
}
668
}
669
670
//should we cancel their gateway subscriptions?
671
$pmpro_cancel_previous_subscriptions = true;
672
if(isset($_REQUEST['cancel_membership']) && $_REQUEST['cancel_membership'] == false)
@@ -749,19 +778,20 @@ function pmpro_changeMembershipLevel($level, $user_id = NULL, $old_level_status
749
}
750
}
751
752
- //get level id
753
- if(is_array($level))
754
- $level_id = $level['membership_id']; //custom level
755
- else
756
- $level_id = $level; //just id
757
-
758
//remove cached level
759
global $all_membership_levels;
760
unset($all_membership_levels[$user_id]);
761
762
//update user data and call action
763
pmpro_set_current_user();
764
- do_action("pmpro_after_change_membership_level", $level_id, $user_id); //$level is the $level_id here
765
return true;
766
}
767
@@ -1367,6 +1397,18 @@ function pmpro_getMembershipLevelForUser($user_id = NULL, $force = false)
1367
JOIN {$wpdb->pmpro_memberships_users} AS mu ON (l.id = mu.membership_id)
1368
WHERE mu.user_id = $user_id AND mu.status = 'active'
1369
LIMIT 1");
1370
return $all_membership_levels[$user_id];
1371
}
1372
}
@@ -1397,7 +1439,8 @@ function pmpro_getMembershipLevelsForUser($user_id = NULL, $include_inactive = f
1397
$user_id = intval($user_id);
1398
1399
global $wpdb;
1400
- return $wpdb->get_results("SELECT
1401
l.id AS ID,
1402
l.id as id,
1403
mu.id as subscription_id,
@@ -1418,6 +1461,18 @@ function pmpro_getMembershipLevelsForUser($user_id = NULL, $include_inactive = f
1418
FROM {$wpdb->pmpro_membership_levels} AS l
1419
JOIN {$wpdb->pmpro_memberships_users} AS mu ON (l.id = mu.membership_id)
1420
WHERE mu.user_id = $user_id".($include_inactive?"":" AND mu.status = 'active'"));
1421
}
1422
1423
/* pmpro_getLevel() returns the level object for a level
486
}
487
}
488
489
+ /**
490
+ * Function to check if a user has specified membership levels.
491
*
492
+ * pmpro_hasMembershipLevel() checks if the passed user is a member of the passed level
493
* $level may either be the ID or name of the desired membership_level. (or an array of such)
494
* If $user_id is omitted, the value will be retrieved from $current_user.
495
*
496
+ * Return values:
497
+ * * Success returns boolean true.
498
+ * * Failure returns a string containing the error message.
499
+ *
500
+ * @since 1.8.5 Added 'e' option for expired members.
501
+ * @since 1.0.0
502
+ *
503
+ * @param mixed $levels The levels to check.
504
+ * @param int $user_id The user ID to check.
505
+ *
506
+ * @return bool Result of membership query.
507
*/
508
function pmpro_hasMembershipLevel($levels = NULL, $user_id = NULL)
509
{
510
+ global $current_user, $wpdb;
511
512
$return = false;
513
540
541
if(empty($membership_levels))
542
{
543
+ //user has no levels just check if 0, L, -1, or e was sent in one of the levels
544
if(in_array(0, $levels, true) || in_array("0", $levels))
545
$return = true;
546
elseif(in_array("L", $levels) || in_array("l", $levels))
547
$return = (!empty($user_id) && $user_id == $current_user->ID);
548
elseif(in_array("-L", $levels) || in_array("-l", $levels))
549
+ $return = (empty($user_id) || $user_id != $current_user->ID);
550
+ elseif(in_array("E", $levels) || in_array("e", $levels)) {
551
+ $sql = "SELECT id FROM $wpdb->pmpro_memberships_users WHERE user_id=$user_id AND status='expired' LIMIT 1";
552
+ $expired = $wpdb->get_var($sql);
553
+ return !empty($expired);
554
+ }
555
}
556
else
557
{
569
if(empty($user_id) || $user_id != $current_user->ID)
570
$return = true;
571
}
572
+ elseif($level == "0" || strtoupper($level) == "E")
573
{
574
+ continue; //user with levels so not a "non-member" or expired
575
}
576
else
577
{
682
}
683
}
684
685
+ //get level id
686
+ if(is_array($level))
687
+ $level_id = $level['membership_id']; //custom level
688
+ else
689
+ $level_id = $level; //just id
690
+
691
+ /**
692
+ * Action to run before the membership level changes.
693
+ *
694
+ * @param int $level_id ID of the level changed to.
695
+ * @param int $user_id ID of the user changed.
696
+ */
697
+ do_action("pmpro_before_change_membership_level", $level_id, $user_id);
698
+
699
//should we cancel their gateway subscriptions?
700
$pmpro_cancel_previous_subscriptions = true;
701
if(isset($_REQUEST['cancel_membership']) && $_REQUEST['cancel_membership'] == false)
778
}
779
}
780
781
//remove cached level
782
global $all_membership_levels;
783
unset($all_membership_levels[$user_id]);
784
785
//update user data and call action
786
pmpro_set_current_user();
787
+
788
+ /**
789
+ * Action to run after the membership level changes.
790
+ *
791
+ * @param int $level_id ID of the level changed to.
792
+ * @param int $user_id ID of the user changed.
793
+ */
794
+ do_action("pmpro_after_change_membership_level", $level_id, $user_id);
795
return true;
796
}
797
1397
JOIN {$wpdb->pmpro_memberships_users} AS mu ON (l.id = mu.membership_id)
1398
WHERE mu.user_id = $user_id AND mu.status = 'active'
1399
LIMIT 1");
1400
+
1401
+ /**
1402
+ * pmpro_get_membership_level_for_user filter.
1403
+ *
1404
+ * Filters the returned level.
1405
+ *
1406
+ * @since 1.8.5.4
1407
+ *
1408
+ * @param object $level Level object.
1409
+ */
1410
+ $all_membership_levels[$user_id] = apply_filters('pmpro_get_membership_level_for_user', $all_membership_levels[$user_id]);
1411
+
1412
return $all_membership_levels[$user_id];
1413
}
1414
}
1439
$user_id = intval($user_id);
1440
1441
global $wpdb;
1442
+
1443
+ $levels = $wpdb->get_results("SELECT
1444
l.id AS ID,
1445
l.id as id,
1446
mu.id as subscription_id,
1461
FROM {$wpdb->pmpro_membership_levels} AS l
1462
JOIN {$wpdb->pmpro_memberships_users} AS mu ON (l.id = mu.membership_id)
1463
WHERE mu.user_id = $user_id".($include_inactive?"":" AND mu.status = 'active'"));
1464
+ /**
1465
+ * pmpro_get_membership_levels_for_user filter.
1466
+ *
1467
+ * Filters the returned levels.
1468
+ *
1469
+ * @since 1.8.5.4
1470
+ *
1471
+ * @param array $levels Array of level objects.
1472
+ */
1473
+ $levels = apply_filters('pmpro_get_membership_levels_for_user', $levels);
1474
+
1475
+ return $levels;
1476
}
1477
1478
/* pmpro_getLevel() returns the level object for a level
includes/profile.php CHANGED
@@ -344,4 +344,5 @@ function pmpro_membership_level_profile_fields_update()
344
}
345
add_action( 'show_user_profile', 'pmpro_membership_level_profile_fields' );
346
add_action( 'edit_user_profile', 'pmpro_membership_level_profile_fields' );
347
- add_action( 'profile_update', 'pmpro_membership_level_profile_fields_update' );
344
}
345
add_action( 'show_user_profile', 'pmpro_membership_level_profile_fields' );
346
add_action( 'edit_user_profile', 'pmpro_membership_level_profile_fields' );
347
+ add_action( 'personal_options_update', 'pmpro_membership_level_profile_fields_update' );
348
+ add_action( 'edit_user_profile_update', 'pmpro_membership_level_profile_fields_update' );
includes/services.php CHANGED
@@ -69,6 +69,30 @@ function pmpro_wp_ajax_orders_csv()
69
}
70
add_action('wp_ajax_orders_csv', 'pmpro_wp_ajax_orders_csv');
71
72
function pmpro_update_level_order() {
73
echo pmpro_setOption('level_order');
74
exit;
69
}
70
add_action('wp_ajax_orders_csv', 'pmpro_wp_ajax_orders_csv');
71
72
+ /**
73
+ * Load the Orders print view.
74
+ *
75
+ * @since 1.8.6
76
+ */
77
+ function pmpro_orders_print_view() {
78
+ require_once(dirname(__FILE__) . "/../adminpages/orders-print.php");
79
+ exit;
80
+ }
81
+ add_action('wp_ajax_pmpro_orders_print_view', 'pmpro_orders_print_view');
82
+
83
+ /**
84
+ * Get order JSON.
85
+ *
86
+ * @since 1.8.6
87
+ */
88
+ function pmpro_get_order_json() {
89
+ $order_id = $_REQUEST['order_id'];
90
+ $order = new MemberOrder($order_id);
91
+ echo json_encode($order);
92
+ exit;
93
+ }
94
+ add_action('wp_ajax_pmpro_get_order_json', 'pmpro_get_order_json');
95
+
96
function pmpro_update_level_order() {
97
echo pmpro_setOption('level_order');
98
exit;
languages/email/vi_VN/admin_change.html ADDED
@@ -0,0 +1,7 @@
1
+ <p>Admin của !!sitename!! đã thay đổi kiểu thành viên của bạn.</p>
2
+
3
+ <p>!!membership_change!!.</p>
4
+
5
+ <p>Nếu bạn không yêu cầu thay đổi kiểu thành viên và muốn biết thêm thông tin xin vui lòng liên hệ với chúng tôi tại !!siteemail!!</p>
6
+
7
+ <p>Đăng nhập vào tài khoản thành viên của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/admin_change_admin.html ADDED
@@ -0,0 +1,5 @@
1
+ <p>Admin của !!sitename!! đã thay đổi kiểu thành viên cho !!name!!.</p>
2
+
3
+ <p>!!membership_change!!.</p>
4
+
5
+ <p>Đăng nhập với WordPress admin ở đây: !!login_link!!</p>
languages/email/vi_VN/billing.html ADDED
@@ -0,0 +1,16 @@
1
+ <p>Thông tin thanh toán của bạn tại !!sitename!! đã thay đổi.</p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>
5
+ Thông tin thanh toán:<br />
6
+ !!billing_address!!
7
+ </p>
8
+
9
+ <p>
10
+ !!cardtype!!: !!accountnumber!!<br />
11
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
12
+ </p>
13
+
14
+ <p>Nếu bạn không yêu cầu thay đổi thông tin thanh toán xin vui lòng liên hệ với chúng tôi tại !!siteemail!!</p>
15
+
16
+ <p>Đăng nhập vào tài khoản thành viên của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/billing_admin.html ADDED
@@ -0,0 +1,17 @@
1
+ <p> cho !!display_name!! tại !!sitename!! đã thay đổi.</p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>
5
+ Thông tin thanh toán:<br />
6
+ !!billing_name!!<br />
7
+ !!billing_street!!<br />
8
+ !!billing_city!!, !!billing_state!! !!billing_zip!! !!billing_country!!
9
+ !!billing_phone!!
10
+ </p>
11
+
12
+ <p>
13
+ !!cardtype!!: !!accountnumber!!<br />
14
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
15
+ </p>
16
+
17
+ <p>Đăng nhập vào bảng điều khiển WordPressZ ở đây: !!login_link!!</p>
languages/email/vi_VN/billing_failure.html ADDED
@@ -0,0 +1,11 @@
1
+ <p>Việc thanh toán tiền cho đăng ký học này tại !!sitename!! đã thất bại. <strong> Vui lòng click vào link dưới đây để đăng nhập và cập nhật thông tin thanh toán để tránh bị ngừng tài khoản. !!login_link!!</strong></p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>Các thông tin tài khoản gần đây nhất mà chúng tôi có trong hồ sơ là:</p>
5
+
6
+ <p>!!billing_address!!</p>
7
+
8
+ <p>
9
+ !!cardtype!!: !!accountnumber!!<br />
10
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
11
+ </p>
languages/email/vi_VN/billing_failure_admin.html ADDED
@@ -0,0 +1,11 @@
1
+ <p>Thanh toán thất bại</p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>Các thông tin tài khoản gần đây nhất mà chúng tôi có trong hồ sơ là is:</p>
5
+
6
+ <p>!!billing_address!!</p>
7
+
8
+ <p>
9
+ !!cardtype!!: !!accountnumber!!<br />
10
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
11
+ </p>
languages/email/vi_VN/cancel.html ADDED
@@ -0,0 +1,3 @@
1
+ <p>Quyền thành viên của bạn !!sitename!! đã bị hủy bỏ.</p>
2
+
3
+ <p>Nếu bạn không yêu cầu hủy bỏ và muốn biết thêm thông tin xin vui lòng liên hệ với chúng tôi tại !!siteemail!!</p>
languages/email/vi_VN/cancel_admin.html ADDED
@@ -0,0 +1,8 @@
1
+ <p>Quyên thành viên của !!user_login!! tại !!sitename!! đã bi hủy.</p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
5
+ <p>Ngày bắt đầu: !!startdate!!</p>
6
+ <p>Ngày hủy bỏ: !!enddate!!</p>
7
+
8
+ <p>Đăng nhập để vào phần quản trị của WordPress của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_check.html ADDED
@@ -0,0 +1,17 @@
1
+ <p>Cám ơn bạn đã đăng ký thành viên tại !!sitename!!. Tài khoản thành viên của bạn được kích hoạt ngay bây giờ.</p>
2
+
3
+ !!instructions!!
4
+
5
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn và biên nhận của hóa đơn cho việc tạo thành viên lần đầu của bạn.</p>
6
+
7
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
8
+ <p>Kiểu thành viên !!membership_level_name!!</p>
9
+ <p>Phí thành viên: !!membership_cost!!</p>
10
+ !!membership_expiration!! !!discount_code!!
11
+
12
+ <p>
13
+ Hóa đơn số!!invoice_id!! on !!invoice_date!!<br />
14
+ Hóa Đơn Tổng: !!invoice_total!!
15
+ </p>
16
+
17
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_check_admin.html ADDED
@@ -0,0 +1,17 @@
1
+ <p>Có một thành viên mới thanh toán tại !!sitename!!.</p>
2
+
3
+ <p><strong>Họ đã chọn thanh toán bằng đánh dấu vào.</strong></p>
4
+
5
+ <p>Dưới đây là chi tiết về tài khoản của thành viên mới và biên nhận cho hóa đơn thành viên lần đầu.</p>
6
+
7
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
8
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
9
+ <p>Phí thành viên: !!membership_cost!!</p>
10
+ !!membership_expiration!! !!discount_code!!
11
+
12
+ <p>
13
+ Số hóa đơn!!invoice_id!! on !!invoice_date!!<br />
14
+ Hóa đơn tổng: $!!invoice_total!!
15
+ </p>
16
+
17
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_express.html ADDED
@@ -0,0 +1,14 @@
1
+ <p>Cảm ơn bạn đã đang ký thành viên tại !!sitename!!. Tài kh oản than9hf viên của bạn sẽ được kishs hoạt ngay.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn và biên nhận cho hóa đơn cho thành viên lần đầu của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ <p>Phí thành viên: !!membership_cost!!</p>
7
+ !!membership_expiration!! !!discount_code!!
8
+
9
+ <p>
10
+ Số hóa đơn!!invoice_id!! on !!invoice_date!!<br />
11
+ Hóa đơn tổng: !!invoice_total!!
12
+ </p>
13
+
14
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_express_admin.html ADDED
@@ -0,0 +1,14 @@
1
+ <p>Có một thành viên mới thanh toán tại !!sitename!!.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn và biên nhận cho hóa đơn cho thành viên lần đầu của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ <p>Phí thành viên: !!membership_cost!!</p>
7
+ !!membership_expiration!! !!discount_code!!
8
+
9
+ <p>
10
+ Số hóa đơn!!invoice_id!! on !!invoice_date!!<br />
11
+ Hóa đơn tổng: !!invoice_total!!
12
+ </p>
13
+
14
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_free.html ADDED
@@ -0,0 +1,8 @@
1
+ <p>Cảm ơn bạn đã đang ký thành viên tại !!sitename!!. Tài khoản thành viên của bạn sẽ được kích hoạt ngay.</p>
2
+ <p>Below are details about your membership Tài khoản.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ !!membership_expiration!! !!discount_code!!
7
+
8
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_free_admin.html ADDED
@@ -0,0 +1,8 @@
1
+ <p>Có một thành viên mới thanh toán tại !!sitename!!.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ !!membership_expiration!! !!discount_code!!
7
+
8
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_freetrial.html ADDED
@@ -0,0 +1,19 @@
1
+ <p>Cảm ơn bạn đã đang ký thành viên tại !!sitename!!. Tài kh oản thành viên của bạn sẽ được kích hoạt ngay.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên !!membership_level_name!!</p>
6
+ <p>Phí thành viên: !!membership_cost!!</p>
7
+ !!membership_expiration!! !!discount_code!!
8
+
9
+ <p>
10
+ Thông t in thanh toán trong hồ sơ:<br />
11
+ !!billing_address!!
12
+ </p>
13
+
14
+ <p>
15
+ !!cardtype!!: !!accountnumber!!<br />
16
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
17
+ </p>
18
+
19
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_freetrial_admin.html ADDED
@@ -0,0 +1,19 @@
1
+ <p>Có một thành viên mới thanh toán tại !!sitename!!.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn và biên nhận cho hóa đơn cho thành viên lần đầu của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ <p>Phí thành viên: !!membership_cost!!</p>
7
+ !!membership_expiration!! !!discount_code!!
8
+
9
+ <p>
10
+ Thông t in thanh toán trong hồ sơ:<br />
11
+ !!billing_address!!
12
+ </p>
13
+
14
+ <p>
15
+ !!cardtype!!: !!accountnumber!!<br />
16
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
17
+ </p>
18
+
19
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_paid.html ADDED
@@ -0,0 +1,23 @@
1
+ <p>Cảm ơn bạn đã đang ký thành viên tại !!sitename!!. Tài kh oản thành viên của bạn sẽ được kích hoạt ngay.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn và biên nhận cho hóa đơn cho thành viên lần đầu của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ <p>Phí thành viên: !!membership_cost!!</p>
7
+ !!membership_expiration!! !!discount_code!!
8
+
9
+ <p>
10
+ Số hóa đơn!!invoice_id!! trong !!invoice_date!!<br />
11
+ Hóa đơn tổng: !!invoice_total!!
12
+ </p>
13
+ <p>
14
+ Thông t in thanh toán:<br />
15
+ !!billing_address!!
16
+ </p>
17
+
18
+ <p>
19
+ !!cardtype!!: !!accountnumber!!<br />
20
+ Expires: !!expirationmonth!!/!!expirationyear!!
21
+ </p>
22
+
23
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_paid_admin.html ADDED
@@ -0,0 +1,23 @@
1
+ <p>Có một thành viên mới thanh toán tại !!sitename!!.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn và biên nhận cho hóa đơn cho thành viên lần đầu của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ <p>Phí thành viên: !!membership_cost!!</p>
7
+ !!membership_expiration!! !!discount_code!!
8
+
9
+ <p>
10
+ Số hóa đơn!!invoice_id!! trong !!invoice_date!!<br />
11
+ Hóa đơn tổng: !!invoice_total!!
12
+ </p>
13
+ <p>
14
+ Thông tin thanh toán:<br />
15
+ !!billing_address!!
16
+ </p>
17
+
18
+ <p>
19
+ !!cardtype!!: !!accountnumber!!<br />
20
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
21
+ </p>
22
+
23
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/checkout_trial.html ADDED
@@ -0,0 +1,23 @@
1
+ 7<p>Cảm ơn bạn đã đang ký thành viên tại !!sitename!!. Tài kh oản thành viên của bạn sẽ được kích hoạt ngay.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn và biên nhận cho hóa đơn cho thành viên lần đầu của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ <p>Phí thành viên: !!membership_cost!!</p>
7
+ !!membership_expiration!! !!discount_code!!
8
+
9
+ <p>
10
+ Số hóa đơn!!invoice_id!! trong !!invoice_date!!<br />
11
+ Hóa đơn tổng: !!invoice_total!!
12
+ </p>
13
+ <p>
14
+ Thông tin thanh toán:<br />
15
+ !!billing_address!!
16
+ </p>
17
+
18
+ <p>
19
+ !!cardtype!!: !!accountnumber!!<br />
20
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
21
+ </p>
22
+
23
+ <p>Log in to your membership account here: !!login_link!!</p>
languages/email/vi_VN/checkout_trial_admin.html ADDED
@@ -0,0 +1,23 @@
1
+ <p>Có một thành viên mới thanh toán tại !!sitename!!.</p>
2
+ <p>Dưới đây là chi tiết về tài khoản thành viên của bạn và biên nhận cho hóa đơn cho thành viên lần đầu của bạn.</p>
3
+
4
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
5
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
6
+ <p>Phí thành viên: !!membership_cost!!</p>
7
+ !!membership_expiration!! !!discount_code!!
8
+
9
+ <p>
10
+ Số hóa đơn!!invoice_id!! on !!invoice_date!!<br />
11
+ Hóa đơn tổng: !!invoice_total!!
12
+ </p>
13
+ <p>
14
+ Thông tin thanh toán:<br />
15
+ !!billing_address!!
16
+ </p>
17
+
18
+ <p>
19
+ !!cardtype!!: !!accountnumber!!<br />
20
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
21
+ </p>
22
+
23
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/credit_card_expiring.html ADDED
@@ -0,0 +1,13 @@
1
+ <p>Phương thức thanh toán cho tài khoản thành viên tại !!sitename!! sẽ sớm hết hạn. <strong>Vui lòng click vào link dưới đây để đăng nhập và cập nhật thông tin thanh toán của bạn để tránh bị ngừng tài khoản. !!login_link!!</strong></p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>Các thông tin tài khoản gần đây nhất mà chúng tôi có trong hồ sơ is:</p>
5
+
6
+ <p>!!billing_name!!</br />
7
+ !!billing_address!!
8
+ </p>
9
+
10
+ <p>
11
+ !!cardtype!!: !!accountnumber!!<br />
12
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
13
+ </p>
languages/email/vi_VN/default.html ADDED
@@ -0,0 +1 @@
1
+ !!body!!
languages/email/vi_VN/footer.html ADDED
@@ -0,0 +1,4 @@
1
+ <p>
2
+ Trân trọng,<br />
3
+ !!sitename!!
4
+ </p>
languages/email/vi_VN/header.html ADDED
@@ -0,0 +1 @@
1
+ <p>Kính gửi !!name!!,</p>
languages/email/vi_VN/invoice.html ADDED
@@ -0,0 +1,19 @@
1
+ <p>Cảm ơn bạn đã đang ký thành viên tại !!sitename!!. Dưới đây là hóa đơn cho đăng ký loại thành viên gần đây nhất của bạn.</p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>
5
+ Số hóa đơn!!invoice_id!! trong !!invoice_date!!<br />
6
+ Hóa đơn tổng: !!invoice_total!!
7
+ </p>
8
+ <p>
9
+ Thông tin thanh toán:<br />
10
+ !!billing_address!!
11
+ </p>
12
+
13
+ <p>
14
+ !!cardtype!!: !!accountnumber!!<br />
15
+ Hết hạn: !!expirationmonth!!/!!expirationyear!!
16
+ </p>
17
+
18
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
19
+ <p>Để xem một phiên bản trực tuyến của hoá đơn này, click vào đây: !!invoice_link!!</p>
languages/email/vi_VN/membership_expired.html ADDED
@@ -0,0 +1,7 @@
1
+ <p>Quyền thành viên tại !!sitename!! đã hết hạn.</p>
2
+
3
+ <p>Cám ơn bạn đã ủng hộ.</p>
4
+
5
+ <p>Xem các loại hội viên hiện tại của chúng tôi tại đây: !!levels_link!!</p>
6
+
7
+ <p>Đăng nhập để quản lý tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/membership_expiring.html ADDED
@@ -0,0 +1,6 @@
1
+ <p>Cảm ơn bạn đã đang ký thành viên tại !!sitename!!. Đây chỉ là nhắc nhở rằng quyền thành viên của bạn sẽ kết thúc vào ngày !!enddate!!.</p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
5
+
6
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/email/vi_VN/trial_ending.html ADDED
@@ -0,0 +1,8 @@
1
+ <p>Cảm ơn bạn đã đang ký thành viên tại !!sitename!!. Thời gian dùng thử của bạn đang kết thucd !!trial_end!!.</p>
2
+
3
+ <p>Tài khoản: !!display_name!! (!!user_email!!)</p>
4
+ <p>Kiểu thành viên: !!membership_level_name!!</p>
5
+
6
+ <p>Lệ phí của bạn sẽ được thay đổi từ !!trial_amount!! tới !!billing_amount!! mỗi !!cycle_number!! !!cycle_period!!(s).</p>
7
+
8
+ <p>Đăng nhập để vào tài khoản của bạn ở đây: !!login_link!!</p>
languages/pmpro-vi_VN.mo ADDED
Binary file
languages/pmpro-vi_VN.po ADDED
@@ -0,0 +1,4556 @@