PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 260927
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v260927
260927 260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 All 190 releases
s2member / src / includes / classes / sc-paypal-button-in.inc.php

sc-paypal-button-in.inc.php in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions 260927, at src/includes/classes/sc-paypal-button-in.inc.php

987 lines 85.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 /**
4 * Shortcode `[s2Member-PayPal-Button]` (inner processing routines).
5 *
6 * Copyright: © 2009-2011
7 * {@link http://websharks-inc.com/ WebSharks, Inc.}
8 * (coded in the USA)
9 *
10 * Released under the terms of the GNU General Public License.
11 * You should have received a copy of the GNU General Public License,
12 * along with this software. In the main directory, see: /licensing/
13 * If not, see: {@link http://www.gnu.org/licenses/}.
14 *
15 * @package s2Member\PayPal
16 * @since 3.5
17 */
18 if(!defined('WPINC')) // MUST have WordPress.
19 exit("Do not access this file directly.");
20
21 if (!class_exists ("c_ws_plugin__s2member_sc_paypal_button_in"))
22 {
23 /**
24 * Shortcode `[s2Member-PayPal-Button]` (inner processing routines).
25 *
26 * @package s2Member\PayPal
27 * @since 3.5
28 */
29 class c_ws_plugin__s2member_sc_paypal_button_in
30 {
31 /**
32 * Handles the Shortcode for: `[s2Member-PayPal-Button /]`.
33 *
34 * @package s2Member\PayPal
35 * @since 3.5
36 *
37 * @attaches-to ``add_shortcode("s2Member-PayPal-Button");``
38 *
39 * @param array $attr An array of Attributes.
40 * @param string $content Content inside the Shortcode.
41 * @param string $shortcode The actual Shortcode name itself.
42 * @return string The resulting PayPal Button Code.
43 */
44 public static function sc_paypal_button ($attr = FALSE, $content = FALSE, $shortcode = FALSE)
45 {
46 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
47 do_action("ws_plugin__s2member_before_sc_paypal_button", get_defined_vars ());
48 unset($__refs, $__v);
49
50 c_ws_plugin__s2member_no_cache::no_cache_constants /* No caching on pages that contain this Payment Button. */ (true);
51
52 $attr = /* Force array. Trim quote entities. */ c_ws_plugin__s2member_utils_strings::trim_qts_deep ((array)$attr);
53
54 $attr = shortcode_atts (apply_filters("ws_plugin__s2member_sc_paypal_button_default_attrs", array("ids" => "0", "exp" => "72", "level" => "1", "ccaps" => "", "desc" => "", "ps" => "paypal", "lc" => "", "lang" => "", "cc" => "USD", "dg" => "0", "ns" => "1", "custom" => $_SERVER["HTTP_HOST"], "ta" => "0", "tp" => "0", "tt" => "D", "ra" => "0.01", "rp" => "1", "rt" => "M", "rr" => "1", "rrt" => "", "rra" => "1", "modify" => "0", "cancel" => "0", "sp" => "0", "image" => "default", "output" => "button"), get_defined_vars ()), $attr);
55
56 // "modify" has been deprecated. https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/Appx-websitestandard-htmlvariables/#deprecated-variables
57 $attr["modify"] = "0";
58
59 $attr["lc"] = /* Locale code absolutely must be provided in upper-case format. Only after running shortcode_atts(). */ strtoupper ($attr["lc"]);
60 $attr["tt"] = /* Term lengths absolutely must be provided in upper-case format. Only after running shortcode_atts(). */ strtoupper ($attr["tt"]);
61 $attr["rt"] = /* Term lengths absolutely must be provided in upper-case format. Only after running shortcode_atts(). */ strtoupper ($attr["rt"]);
62 $attr["rr"] = /* Must be provided in upper-case format. Numerical, or BN value. Only after running shortcode_atts(). */ strtoupper ($attr["rr"]);
63 $attr["ccaps"] = /* Custom Capabilities must be typed in lower-case format. Only after running shortcode_atts(). */ strtolower ($attr["ccaps"]);
64 $attr["ccaps"] = /* Custom Capabilities should not have spaces. */ str_replace(" ", "", $attr["ccaps"]);
65 $attr["rr"] = /* Lifetime Subscriptions require Buy Now. Only after running shortcode_atts(). */ ($attr["rt"] === "L") ? "BN" : $attr["rr"];
66 $attr["rr"] = /* Independent Ccaps require Buy Now. Only after running shortcode_atts(). */ ($attr["level"] === "*") ? "BN" : $attr["rr"];
67 $attr["ns"] = /* No shipping directive must be 1 for digital items. After shortcode_atts(). */ ($attr["dg"] === "1") ? "1" : $attr["ns"];
68 $attr["ta"] = /*260228 Normalize trial amount to canonical 2-decimal currency format. */ number_format((float)$attr["ta"], 2, '.', '');
69 $attr["ra"] = /*260228 Normalize recurring/regular amount to canonical 2-decimal currency format. */ number_format((float)$attr["ra"], 2, '.', '');
70
71 //260811 Sanitize custom image URL.
72 if($attr["image"] !== "default")
73 $attr["image"] = esc_url_raw($attr["image"], array('http', 'https'));
74
75 $force_notify_url_scheme = apply_filters("ws_plugin__s2member_during_sc_paypal_button_force_notify_url_scheme", null, get_defined_vars ());
76 $force_return_url_scheme = apply_filters("ws_plugin__s2member_during_sc_paypal_button_force_return_url_scheme", null, get_defined_vars ());
77
78 //260918.2104 TO-DO PayPal Checkout cache hardening: do not embed the one-hour, visitor-specific transaction token in rendered page HTML.
79 // Render a cache-safe encrypted checkout definition instead, then mint the short-lived invoice/IP/user-context transaction token server-side
80 // when checkout actually starts (output="button", "anchor", or "url"), preserving validation, idempotency, subscription context, and return/cancel behavior.
81
82 // PayPal Checkout SDK memoization (per request; shared across all button variants).
83 static $ppco_sdks = array();
84
85 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
86 do_action("ws_plugin__s2member_before_sc_paypal_button_after_shortcode_atts", get_defined_vars ());
87 unset($__refs, $__v);
88
89 if /* Cancellation Buttons. */ ($attr["cancel"])
90 {
91 //260114 PayPal Checkout (REST) cancellation override.
92 // - output="button": on-site cancel via REST API (logged-in users only).
93 // - output="anchor|url": link to PayPal subscription management UI (sandbox/live aware).
94 // Falls back to legacy PayPal cancellation flow when user is not logged in or has no subscription id.
95 if(c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_enabled() && in_array($attr["output"], array("button", "anchor", "url"), true) && is_user_logged_in())
96 {
97 $user_id = (int)get_current_user_id();
98 $subscr_id = (string)get_user_option('s2member_subscr_id', $user_id);
99
100 $ppco_sandbox = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_sandbox();
101 $pp_manage_url = ($ppco_sandbox) ? 'https://www.sandbox.paypal.com/myaccount/autopay/connect/' : 'https://www.paypal.com/myaccount/autopay/'; //260218
102
103 // output="url|anchor": always link to PayPal subscription management UI.
104 if(in_array($attr["output"], array("url", "anchor"), true))
105 {
106 // output="url": return the PayPal management URL.
107 if($attr["output"] === "url")
108 {
109 $code = $_code = $pp_manage_url;
110
111 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
112 do_action("ws_plugin__s2member_during_sc_paypal_cancellation_button", get_defined_vars ());
113 unset($__refs, $__v);
114
115 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
116 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
117 }
118 // output="anchor": real anchor tag to PayPal management UI (no JS).
119 else if($attr["output"] === "anchor")
120 {
121 $default_image = "https://www.paypal.com/" . (($attr["lang"]) ? $attr["lang"] : _x ("en_US", "s2member-front paypal-button-lang-code", "s2member")) . "/i/btn/btn_unsubscribe_LG.gif";
122
123 if($attr["image"] && $attr["image"] !== "default")
124 {
125 $img_src = $attr["image"];
126 $code = $_code = '<a href="'.esc_attr($pp_manage_url).'" target="_blank" rel="nofollow noopener"><img src="'.esc_attr($img_src).'" style="width:auto; height:auto; border:0;" alt="PayPal" /></a>';
127 }
128 else
129 {
130 //260218 Match PayPal Checkout cancellation output="button" styling for output="anchor" (default image).
131 $ppco_cancel_label = esc_html(_x('Unsubscribe', 'paypal cancellation button label', 's2member'));
132 $ppco_a_id = 's2member_ppco_cancel_anchor_'.md5($user_id.$subscr_id);
133
134 $code = '<style type="text/css">a#'.esc_attr($ppco_a_id).'{display:inline-flex;align-items:center;justify-content:center;width:150px;height:40px;padding:10px 0;border-radius:4px;border:1px solid rgba(0,0,0,0.06);background:#ffc439 !important;color:#003087 !important;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:600;cursor:pointer;box-sizing:border-box;white-space:nowrap;text-decoration:none !important;} a#'.esc_attr($ppco_a_id).':link,a#'.esc_attr($ppco_a_id).':visited,a#'.esc_attr($ppco_a_id).':active{color:#003087 !important;background:#ffc439 !important;text-decoration:none !important;} a#'.esc_attr($ppco_a_id).':hover{color:#003087 !important;text-decoration:none !important;filter:brightness(0.98);}</style>'."\n";
135 $code .= '<a id="'.esc_attr($ppco_a_id).'" href="'.esc_attr($pp_manage_url).'" target="_blank" rel="nofollow noopener">'.$ppco_cancel_label.'</a>';
136 $_code = $code;
137 }
138
139 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
140 do_action("ws_plugin__s2member_during_sc_paypal_cancellation_button", get_defined_vars ());
141 unset($__refs, $__v);
142
143 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
144 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
145 }
146 }
147
148 if($subscr_id)
149 {
150
151 // output="button": if Paid Subscr. ID is not a subscription id, fall back to PayPal management UI.
152 if($attr["output"] === "button" && !preg_match('/^I-[A-Z0-9]+$/', $subscr_id))
153 {
154 $default_image = "https://www.paypal.com/" . (($attr["lang"]) ? $attr["lang"] : _x ("en_US", "s2member-front paypal-button-lang-code", "s2member")) . "/i/btn/btn_unsubscribe_LG.gif";
155
156 if($attr["image"] && $attr["image"] !== "default")
157 {
158 $img_src = $attr["image"];
159 $code = $_code = '<a href="'.esc_attr($pp_manage_url).'" target="_blank" rel="nofollow noopener"><img src="'.esc_attr($img_src).'" style="width:auto; height:auto; border:0;" alt="PayPal" /></a>';
160 }
161 else
162 {
163 //260218 Match PayPal Checkout cancellation output="button" styling for fallback output="anchor" (default image).
164 $ppco_cancel_label = esc_html(_x('Unsubscribe', 'paypal cancellation button label', 's2member'));
165 $ppco_a_id = 's2member_ppco_cancel_anchor_'.md5($user_id.$subscr_id);
166
167 $code = '<style type="text/css">a#'.esc_attr($ppco_a_id).'{display:inline-flex;align-items:center;justify-content:center;width:150px;height:40px;padding:10px 0;border-radius:4px;border:1px solid rgba(0,0,0,0.06);background:#ffc439 !important;color:#003087 !important;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:600;cursor:pointer;box-sizing:border-box;white-space:nowrap;text-decoration:none !important;} a#'.esc_attr($ppco_a_id).':link,a#'.esc_attr($ppco_a_id).':visited,a#'.esc_attr($ppco_a_id).':active{color:#003087 !important;background:#ffc439 !important;text-decoration:none !important;} a#'.esc_attr($ppco_a_id).':hover{color:#003087 !important;text-decoration:none !important;filter:brightness(0.98);}</style>'."\n";
168 $code .= '<a id="'.esc_attr($ppco_a_id).'" href="'.esc_attr($pp_manage_url).'" target="_blank" rel="nofollow noopener">'.$ppco_cancel_label.'</a>';
169 $_code = $code;
170 }
171
172 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
173 do_action("ws_plugin__s2member_during_sc_paypal_cancellation_button", get_defined_vars ());
174 unset($__refs, $__v);
175
176 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
177 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
178 }
179
180 // output="button": REST cancel (modern-looking HTML button).
181 $ppco_endpoint = home_url("/?s2member_paypal_checkout=1", $force_notify_url_scheme);
182
183 // Token must satisfy the standard token validator (invoice/ip/item_number/checksum).
184 $ppco_invoice = 'cancel-'.$user_id.'-'.$subscr_id;
185
186 $ppco_token = array(
187 'exp' => time() + 3600,
188 'invoice' => $ppco_invoice,
189 'ip' => c_ws_plugin__s2member_utils_ip::current(),
190 'item_number' => $subscr_id,
191 'checksum' => md5($ppco_invoice.c_ws_plugin__s2member_utils_ip::current().$subscr_id),
192
193 'user_id' => $user_id,
194 'subscr_id' => $subscr_id,
195 );
196
197 $ppco_token = urlencode(c_ws_plugin__s2member_utils_encryption::encrypt(serialize($ppco_token)));
198 $ppco_nonce = wp_create_nonce('s2m_ppco_cancel_'.$user_id);
199
200 $ppco_btn_id = 's2member_ppco_cancel_'.md5($user_id.$subscr_id);
201 $ppco_msg_id = 's2member_ppco_cancel_msg_'.md5($user_id.$subscr_id);
202
203 //260913.1946 Validate Pro's optional success URL before exposing it to cancellation JavaScript; shortcode attributes may be authored by Editors.
204 $ppco_success_url = (c_ws_plugin__s2member_utils_conds::pro_is_installed() && !empty($attr["success"]) && is_string($attr["success"])) ? wp_validate_redirect($attr["success"], '') : '';
205 $ppco_success_json = wp_json_encode($ppco_success_url, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
206
207 $code = '<style type="text/css">#'.esc_attr($ppco_btn_id).'{display:inline-flex;align-items:center;justify-content:center;width:150px;height:40px;padding:10px 0;border-radius:4px;border:1px solid rgba(0,0,0,0.06);background:#ffc439;color:#003087;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:600;cursor:pointer;box-sizing:border-box;white-space:nowrap;}#'.esc_attr($ppco_btn_id).':hover{filter:brightness(0.98);}#'.esc_attr($ppco_btn_id).':disabled{opacity:0.65;cursor:not-allowed;}</style>'."\n";
208 $code .= '<button type="button" id="'.esc_attr($ppco_btn_id).'">'.esc_html(_x('Unsubscribe', 'paypal cancellation button label', 's2member')).'</button>'."\n"; //260218
209 $code .= '<div id="'.esc_attr($ppco_msg_id).'" style="display:none; margin-top:8px;"></div>'."\n";
210 $code .= '<script type="text/javascript">'."\n";
211 $code .= '(function(){'."\n";
212 $code .= 'var b=document.getElementById("'.esc_js($ppco_btn_id).'");'."\n";
213 $code .= 'var m=document.getElementById("'.esc_js($ppco_msg_id).'");'."\n";
214 $code .= 'var u="'.esc_js($pp_manage_url).'";'."\n";
215 $code .= 'var s='.$ppco_success_json.';'."\n";
216 $code .= 'function goManage(){try{var w=window.open(u,"_blank","noopener");if(!w){window.location.href=u;}}catch(e){window.location.href=u;}}'."\n";
217 $code .= 'function show(msg){try{if(m){m.style.display="block";m.innerHTML=msg;}}catch(e){}}'."\n";
218 $code .= 'function enc(o){var s=[];for(var k in o){if(!o.hasOwnProperty(k))continue;s.push(encodeURIComponent(k)+"="+encodeURIComponent(o[k]));}return s.join("&");}'."\n";
219 $code .= 'if(!b){return;}'."\n";
220 $code .= 'b.addEventListener("click",function(e){'."\n";
221 $code .= 'e.preventDefault();'."\n";
222 $code .= 'if(b.disabled){return;}'."\n";
223 $code .= 'if(!window.confirm("'.esc_js(__('Cancel your subscription now?', 's2member')).'")){return;}'."\n"; //260218
224 $code .= 'b.disabled=true;'."\n";
225 $code .= 'fetch("'.esc_js($ppco_endpoint).'",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"cancel_subscription",s2member_paypal_checkout_t:"'.esc_js($ppco_token).'",s2member_paypal_checkout_nonce:"'.esc_js($ppco_nonce).'"} )})'."\n";
226 $code .= '.then(function(r){return r.json();})'."\n";
227 $code .= '.then(function(res){if(res&&res.ok){if(s){window.location.assign(s);}else{show("'.esc_js(__('Subscription cancelled.', 's2member')).'");}}else{goManage(); b.disabled=false;}})'."\n"; //260913.1946 Honor Pro's validated success URL after a confirmed on-site cancellation.
228 $code .= '.catch(function(){goManage(); b.disabled=false;});'."\n";
229 $code .= '});'."\n";
230 $code .= '})();'."\n";
231 $code .= '</script>'."\n";
232 $_code = $code;
233
234 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
235 do_action("ws_plugin__s2member_during_sc_paypal_cancellation_button", get_defined_vars ());
236 unset($__refs, $__v);
237
238 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
239 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
240 }
241 }
242 else if(c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_enabled() && $attr["output"] === "button")
243 {
244 //260505 Guest output="button": show a disabled PayPal-styled button (no action). Guest output="anchor|url" falls through to the PayPal management link.
245 $ppco_btn_id = 's2member_ppco_cancel_disabled_'.md5((string)microtime(true));
246 $code = '<style type="text/css">#'.esc_attr($ppco_btn_id).'{display:inline-flex;align-items:center;justify-content:center;width:150px;height:40px;padding:10px 0;border-radius:4px;border:1px solid rgba(0,0,0,0.06);background:#ffc439;color:#003087;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:600;cursor:not-allowed;box-sizing:border-box;opacity:0.55;white-space:nowrap;}</style>'."\n";
247 $code .= '<button type="button" id="'.esc_attr($ppco_btn_id).'" disabled="disabled">'.esc_html(_x('Unsubscribe', 'paypal cancellation button label', 's2member')).'</button>'."\n"; //260218
248 $_code = $code;
249
250 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
251 do_action("ws_plugin__s2member_during_sc_paypal_cancellation_button", get_defined_vars ());
252 unset($__refs, $__v);
253
254 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
255 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
256 }
257
258 $default_image = "https://www.paypal.com/" . (($attr["lang"]) ? $attr["lang"] : _x ("en_US", "s2member-front paypal-button-lang-code", "s2member")) . "/i/btn/btn_unsubscribe_LG.gif";
259
260 $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.php")));
261 $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/src/images")), $code);
262 $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ())), $code);
263
264 $endpoint_host = ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com";
265 if(c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_enabled())
266 $endpoint_host = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_sandbox() ? "www.sandbox.paypal.com" : "www.paypal.com";
267
268 $autopay_url = (strpos($endpoint_host, 'sandbox') !== false)
269 ? "https://www.sandbox.paypal.com/myaccount/autopay/connect/"
270 : "https://www.paypal.com/myaccount/autopay/"; //260218
271
272 $code = preg_replace ("/%%autopay_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($autopay_url)), $code);
273 $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
274 $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
275
276 $code = $_code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["image"])) . '"', $code) : preg_replace ('/ src\="(.*?)"/', ' src="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($default_image)) . '"', $code);
277
278 $code = ($attr["output"] === "anchor") ? /* Already in anchor format; `button` format is not used in Cancellations. */ $code : $code;
279 if ($attr["output"] === "url" && preg_match ('/ href\="(.*?)"/', $code, $m) && ($href = $m[1]))
280 $code = ($url = c_ws_plugin__s2member_utils_urls::n_amps ($href));
281
282 unset /* Just a little housekeeping */ ($href, $url, $m);
283
284 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
285 do_action("ws_plugin__s2member_during_sc_paypal_cancellation_button", get_defined_vars ());
286 unset($__refs, $__v);
287 }
288 else if /* Specific Post/Page Buttons. */ ($attr["sp"])
289 {
290 $default_image = "https://www.paypal.com/" . (($attr["lang"]) ? $attr["lang"] : _x ("en_US", "s2member-front paypal-button-lang-code", "s2member")) . "/i/btn/btn_xpressCheckout.gif";
291
292 $paypal_on0_input_value = ($referencing = c_ws_plugin__s2member_utils_users::get_user_subscr_or_wp_id ()) ? "Referencing Customer ID" : "Originating Domain";
293 $paypal_os0_input_value = /* Current User's Paid Subscr. ID, or WP User ID, or domain. */ ($referencing) ? $referencing : $_SERVER["HTTP_HOST"];
294
295 $paypal_on1_input_value = /* Identifies the Customer's IP Address for tracking purposes. */ "Customer IP Address";
296 $paypal_os1_input_value = /* Current User's IP Address for tracking purposes. */ c_ws_plugin__s2member_utils_ip::current();
297
298 $paypal_invoice_input_value = /* s2Member's Unique Code~IP combo. */ uniqid () . "~" . c_ws_plugin__s2member_utils_ip::current();
299
300 $attr["sp_ids_exp"] = /* Combined "sp:ids:expiration hours". */ "sp:" . $attr["ids"] . ":" . $attr["exp"];
301
302 $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered. */ home_url ("/?s2member_paypal_return=1", $force_return_url_scheme);
303 $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
304
305 //260114 PayPal Checkout (REST) SP (Specific Post/Page) override.
306 // Uses server-side create + server-side capture, then posts into existing IPN + Return handlers.
307 if(c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_enabled())
308 {
309 $ppco_sandbox = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_sandbox();
310 $ppco_client_id = (string)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"][($ppco_sandbox) ? "paypal_checkout_sandbox_client_id" : "paypal_checkout_client_id"];
311
312 $ppco_cc = strtoupper((string)$attr["cc"]);
313 $ppco_intent = 'capture';
314
315 $ppco_sdk_key = (($ppco_sandbox) ? 'sandbox' : 'live').'|'.$ppco_cc.'|'.$ppco_intent;
316
317 $ppco_sdk_just_loaded = false;
318 if(empty($ppco_sdks[$ppco_sdk_key]) || !is_array($ppco_sdks[$ppco_sdk_key]))
319 {
320 $ppco_sdks[$ppco_sdk_key] = array(
321 'ns' => 's2m_ppco_'.substr(md5($ppco_sdk_key), 0, 10),
322 'id' => 's2member_ppco_sdk_'.substr(md5($ppco_sdk_key), 0, 10),
323 );
324 $ppco_sdk_just_loaded = true;
325 }
326
327 $ppco_sdk_ns = (string)$ppco_sdks[$ppco_sdk_key]['ns'];
328 $ppco_sdk_id = (string)$ppco_sdks[$ppco_sdk_key]['id'];
329
330 $ppco_endpoint = home_url("/?s2member_paypal_checkout=1", $force_notify_url_scheme);
331 $ppco_cancel = home_url("/");
332
333 $ppco_token = array(
334 'exp' => time() + 3600,
335
336 'invoice' => $paypal_invoice_input_value,
337 'ip' => c_ws_plugin__s2member_utils_ip::current(),
338 'item_name' => $attr["desc"],
339 'item_number' => $attr["sp_ids_exp"],
340 'custom' => $attr["custom"],
341
342 'amount' => $attr["ra"],
343 'cc' => $ppco_cc,
344 'ns' => $attr["ns"],
345
346 'rr' => 'BN',
347
348 'on0' => $paypal_on0_input_value,
349 'os0' => $paypal_os0_input_value,
350 'on1' => $paypal_on1_input_value,
351 'os1' => $paypal_os1_input_value,
352
353 'return' => $success_return_url,
354 'cancel' => $ppco_cancel,
355
356 'checksum' => md5($paypal_invoice_input_value.c_ws_plugin__s2member_utils_ip::current().$attr["sp_ids_exp"]),
357 );
358
359 $ppco_token = urlencode(c_ws_plugin__s2member_utils_encryption::encrypt(serialize($ppco_token)));
360
361 // output="anchor|url" support (no JS SDK; redirects through s2Member, then to PayPal approval URL).
362 if($attr["output"] === "anchor" || $attr["output"] === "url")
363 {
364 $ppco_redirect_url = $ppco_endpoint.'&s2member_paypal_checkout_op=redirect&s2member_paypal_checkout_t='.$ppco_token;
365
366 if($attr["output"] === "url")
367 $code = $_code = $ppco_redirect_url;
368
369 else // output="anchor"
370 {
371 $img_src = ($attr["image"] && $attr["image"] !== "default") ? $attr["image"] : $default_image;
372 $code = $_code = '<a class="ws-plugin--s2member-paypal-button ws-plugin--s2member-paypal-anchor" href="'.esc_attr($ppco_redirect_url).'"><img class="ws-plugin--s2member-paypal-button-img" src="'.esc_attr($img_src).'" style="width:auto; height:auto; border:0; margin:0;" alt="PayPal" /></a>';
373 }
374
375 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
376 do_action("ws_plugin__s2member_during_sc_paypal_sp_button", get_defined_vars ());
377 unset($__refs, $__v);
378
379 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
380 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
381 }
382
383 $ppco_div_id = 's2member_ppco_btn_'.md5($paypal_invoice_input_value.$attr["sp_ids_exp"]);
384 $ppco_err_id = 's2member_ppco_err_'.md5($paypal_invoice_input_value.$attr["sp_ids_exp"]);
385
386 $ppco_locale = ($attr["lang"]) ? (string)$attr["lang"] : '';
387 $ppco_lc = ($attr["lc"]) ? (string)$attr["lc"] : '';
388
389 if(!$ppco_locale && $ppco_lc)
390 {
391 $site_locale = (string)get_locale();
392 if(preg_match('/^([a-z]{2})[_-]/i', $site_locale, $m))
393 $ppco_locale = strtolower($m[1]).'_'.strtoupper($ppco_lc);
394 else
395 $ppco_locale = 'en_'.strtoupper($ppco_lc);
396 }
397
398 $ppco_locale_q = ($ppco_locale) ? '&locale='.rawurlencode($ppco_locale) : '';
399 $ppco_buyer_country_q = ($ppco_sandbox && $ppco_lc) ? '&buyer-country='.rawurlencode(strtoupper($ppco_lc)) : '';
400
401 $ppco_sdk_src = ($ppco_sandbox ? 'https://www.sandbox.paypal.com/sdk/js' : 'https://www.paypal.com/sdk/js');
402 //260114 !!! SP is capture-only; conditional subscription path below is dead code (cleanup/refactor later).
403 if($ppco_intent === 'subscription')
404 $ppco_sdk_src = $ppco_sdk_src.'?client-id='.rawurlencode($ppco_client_id).'&currency='.rawurlencode($ppco_cc).'&vault=true&intent=subscription&disable-funding=card'.$ppco_buyer_country_q.$ppco_locale_q;
405 else
406 $ppco_sdk_src = $ppco_sdk_src.'?client-id='.rawurlencode($ppco_client_id).'&currency='.rawurlencode($ppco_cc).'&intent=capture&commit=true&disable-funding=card'.$ppco_buyer_country_q.$ppco_locale_q;
407
408 $code = '<div id="'.esc_attr($ppco_div_id).'" class="ws-plugin--s2member-paypal-button ws-plugin--s2member-ppco-button" style="max-width:145px; width:auto; margin:0;"></div>'."\n";
409 $code .= '<div id="'.esc_attr($ppco_err_id).'" class="ws-plugin--s2member-ppco-message" style="display:none; margin:0;"></div>'."\n";
410
411 $ppco_sdk_src = apply_filters('ws_plugin__s2member_ppco_sdk_src', $ppco_sdk_src, get_defined_vars());
412
413 if($ppco_sdk_just_loaded)
414 {
415 $code .= '<script id="'.esc_attr($ppco_sdk_id).'" data-namespace="'.esc_attr($ppco_sdk_ns).'" src="'.esc_attr($ppco_sdk_src).'"></script>'."\n";
416 }
417
418 $code .= '<script type="text/javascript">'."\n";
419 $code .= '(function(){'."\n";
420 $code .= 'var d="'.esc_js($ppco_div_id).'";'."\n";
421 $code .= 'var e="'.esc_js($ppco_err_id).'";'."\n";
422 $code .= 'var t="'.esc_js($ppco_token).'";'."\n";
423 $code .= 'var u="'.esc_js($ppco_endpoint).'";'."\n";
424 $code .= 'var ns="'.esc_js($ppco_sdk_ns).'";'."\n";
425 $code .= 'var s="'.esc_js($ppco_sdk_src).'";'."\n";
426 $code .= 'var cid="'.esc_js($paypal_invoice_input_value).'";'."\n";
427 //260819.0042 Keep standalone Checkout feedback consistent with Pro-Forms while distinguishing cancellation from errors.
428 $code .= 'function showMsg(m,t){try{var el=document.getElementById(e);if(el){el.style.display="block";el.innerHTML="<span class=\"ws-plugin--s2member-ppco-"+(t==="info"?"info":"error")+"\">"+m+"</span>";}}catch(x){}}function showErr(m){showMsg(m,"error");}function showInfo(m){showMsg(m,"info");}'."\n";
429 $code .= 'function postTo(url, data){var f=document.createElement("form");f.method="post";f.acceptCharset="UTF-8";f.action=url;for(var k in data){if(!data.hasOwnProperty(k))continue;var i=document.createElement("input");i.type="hidden";i.name=k;i.value=data[k];f.appendChild(i);}document.body.appendChild(f);f.submit();}'."\n"; //260817 Keep signed PayPal Checkout returns in UTF-8.
430 $code .= 'function enc(o){var a=[];for(var k in o){if(!o.hasOwnProperty(k))continue;a.push(encodeURIComponent(k)+"="+encodeURIComponent(o[k]));}return a.join("&");}'."\n";
431 $code .= 'function loadSdk(cb){var P=window[ns];if(P&&P.Buttons){cb(P);return;}var id=ns+"_sdk",tag=document.getElementById(id),done=false;function finish(){if(done)return;done=true;cb(window[ns]&&window[ns].Buttons?window[ns]:null);}function ok(){finish();}function fail(){finish();}if(tag){if(window[ns]&&window[ns].Buttons){finish();return;}if(tag.getAttribute("src")!==s){tag.setAttribute("src",s);}if(tag.readyState==="complete"||tag.readyState==="loaded"){setTimeout(finish,0);return;}tag.addEventListener("load",ok);tag.addEventListener("error",fail);setTimeout(finish,3500);return;}tag=document.createElement("script");tag.id=id;tag.setAttribute("data-namespace",ns);tag.src=s;tag.async=true;tag.onload=ok;tag.onerror=fail;(document.head||document.body||document.documentElement).appendChild(tag);setTimeout(finish,3500);}'."\n";
432 if($ppco_intent === 'subscription')
433 {
434 $code .= 'function getPlanId(){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"get_plan_id",s2member_paypal_checkout_t:t})}).then(function(r){return r.json();}).then(function(res){if(res&&res.plan_id)return res.plan_id;throw(res&&res.error?res.error:"plan_get_failed");});}'."\n";
435 $code .= 'var planId=null;'."\n";
436 $code .= 'function createSubscription(data,actions){if(planId)return actions.subscription.create({plan_id:planId,custom_id:cid,application_context:{shipping_preference:"NO_SHIPPING"}});return getPlanId().then(function(pid){planId=pid;return actions.subscription.create({plan_id:planId,custom_id:cid,application_context:{shipping_preference:"NO_SHIPPING"}});});}'."\n";
437 $code .= 'function onApprove(data){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"confirm_subscription",s2member_paypal_checkout_t:t,subscription_id:(data&&data.subscriptionID?data.subscriptionID:"")})}).then(function(r){return r.json();}).then(function(res){if(res&&res.rtn_url&&res.rtn_post){postTo(res.rtn_url,res.rtn_post);return;}throw(res&&res.error?res.error:"subscription_confirm_failed");}).catch(function(e){showErr("Subscription could not be completed. Please try again.");});}'."\n";
438 $code .= 'function onCancel(){showInfo("Subscription cancelled.");}'."\n";
439 $code .= 'function onError(err){var m="PayPal error. Please try again.";try{if(err){if(typeof err==="string")m="PayPal error: "+err;else if(err.message)m="PayPal error: "+err.message;}}catch(x){}showErr(m);}'."\n";
440 $code .= 'function init(){loadSdk(function(P){var el=document.getElementById(d);if(!el){return;}if(el.getAttribute("data-s2m-ppco-rendered")==="1"){return;}if(!P||!P.Buttons){showErr("PayPal SDK failed to load.");return;}el.setAttribute("data-s2m-ppco-rendered","1");try{P.Buttons({fundingSource:P.FUNDING.PAYPAL,style:{layout:"vertical",tagline:false,height:40},createSubscription:createSubscription,onApprove:onApprove,onCancel:onCancel,onError:onError}).render("#"+d);}catch(x){el.removeAttribute("data-s2m-ppco-rendered");showErr("PayPal render failed.");}});}'."\n";
441 }
442 else
443 {
444 $code .= 'function createOrder(){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"create_order",s2member_paypal_checkout_t:t})}).then(function(r){return r.json();}).then(function(res){if(res&&res.order_id)return res.order_id;throw(res&&res.error?res.error:"order_create_failed");});}'."\n";
445 $code .= 'function onApprove(data){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"capture_order",s2member_paypal_checkout_t:t,order_id:(data&&data.orderID?data.orderID:"")})}).then(function(r){return r.json();}).then(function(res){if(res&&res.rtn_url&&res.rtn_post){postTo(res.rtn_url,res.rtn_post);return;}throw(res&&res.error?res.error:"order_capture_failed");}).catch(function(e){showErr("Payment could not be completed. Please try again.");});}'."\n";
446 $code .= 'function onCancel(){showInfo("Payment cancelled.");}'."\n";
447 $code .= 'function onError(err){var m="PayPal error. Please try again.";try{if(err){if(typeof err==="string")m="PayPal error: "+err;else if(err.message)m="PayPal error: "+err.message;}}catch(x){}showErr(m);}'."\n";
448 $code .= 'function init(){loadSdk(function(P){var el=document.getElementById(d);if(!el){return;}if(el.getAttribute("data-s2m-ppco-rendered")==="1"){return;}if(!P||!P.Buttons){showErr("PayPal SDK failed to load.");return;}el.setAttribute("data-s2m-ppco-rendered","1");try{P.Buttons({fundingSource:P.FUNDING.PAYPAL,style:{layout:"vertical",tagline:false,height:40},createOrder:createOrder,onApprove:onApprove,onCancel:onCancel,onError:onError}).render("#"+d);}catch(x){el.removeAttribute("data-s2m-ppco-rendered");showErr("PayPal render failed.");}});}'."\n";
449 }
450 $code .= 'if(document.readyState==="complete"){init();}else{window.addEventListener("load",init);}'."\n";
451 $code .= '})();'."\n";
452 $code .= '</script>'."\n";
453 $_code = $code;
454
455 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
456 do_action("ws_plugin__s2member_during_sc_paypal_sp_button", get_defined_vars ());
457 unset($__refs, $__v);
458
459 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
460 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
461 }
462
463 $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-sp-checkout-button.php")));
464 $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/src/images")), $code);
465 $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ())), $code);
466
467 $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
468 $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
469 $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
470 $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code);
471 $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/?s2member_paypal_notify=1", $force_notify_url_scheme))), $code);
472 $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
473 $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
474
475 $code = preg_replace ('/ name\="lc" value\="(.*?)"/', ' name="lc" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["lc"])) . '"', $code);
476 $code = preg_replace ('/ name\="no_shipping" value\="(.*?)"/', ' name="no_shipping" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ns"])) . '"', $code);
477 $code = preg_replace ('/ name\="item_name" value\="(.*?)"/', ' name="item_name" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["desc"])) . '"', $code);
478 $code = preg_replace ('/ name\="item_number" value\="(.*?)"/', ' name="item_number" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["sp_ids_exp"])) . '"', $code);
479 $code = preg_replace ('/ name\="page_style" value\="(.*?)"/', ' name="page_style" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ps"])) . '"', $code);
480 $code = preg_replace ('/ name\="currency_code" value\="(.*?)"/', ' name="currency_code" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["cc"])) . '"', $code);
481 $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])) . '"', $code);
482
483 $code = preg_replace ('/ name\="invoice" value\="(.*?)"/', ' name="invoice" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_invoice_input_value)) . '"', $code);
484
485 $code = preg_replace ('/ name\="on0" value\="(.*?)"/', ' name="on0" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_on0_input_value)) . '"', $code);
486 $code = preg_replace ('/ name\="os0" value\="(.*?)"/', ' name="os0" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_os0_input_value)) . '"', $code);
487 $code = preg_replace ('/ name\="on1" value\="(.*?)"/', ' name="on1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_on1_input_value)) . '"', $code);
488 $code = preg_replace ('/ name\="os1" value\="(.*?)"/', ' name="os1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_os1_input_value)) . '"', $code);
489
490 $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ra"])) . '"', $code);
491
492 $code = $_code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["image"])) . '"', $code) : preg_replace ('/ src\="(.*?)"/', ' src="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($default_image)) . '"', $code);
493
494 $code = ($attr["output"] === "anchor") ? '<a href="' . esc_attr (c_ws_plugin__s2member_utils_forms::form_whips_2_url ($code)) . '"><img src="' . esc_attr (($attr["image"] && $attr["image"] !== "default") ? $attr["image"] : $default_image) . '" style="width:auto; height:auto; border:0;" alt="PayPal" /></a>' : $code;
495 $code = ($attr["output"] === "url") ? c_ws_plugin__s2member_utils_forms::form_whips_2_url ($code) : $code;
496
497 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
498 do_action("ws_plugin__s2member_during_sc_paypal_sp_button", get_defined_vars ());
499 unset($__refs, $__v);
500 }
501 else if /* Independent Custom Capabilities. */ ($attr["level"] === "*")
502 {
503 $default_image = "https://www.paypal.com/" . (($attr["lang"]) ? $attr["lang"] : _x ("en_US", "s2member-front paypal-button-lang-code", "s2member")) . "/i/btn/btn_xpressCheckout.gif";
504
505 $paypal_on0_input_value = ($referencing = c_ws_plugin__s2member_utils_users::get_user_subscr_or_wp_id ()) ? "Referencing Customer ID" : "Originating Domain";
506 $paypal_os0_input_value = /* Current User's Paid Subscr. ID, or WP User ID, or domain. */ ($referencing) ? $referencing : $_SERVER["HTTP_HOST"];
507
508 $paypal_on1_input_value = /* Identifies the Customer's IP Address for tracking purposes. */ "Customer IP Address";
509 $paypal_os1_input_value = /* Current User's IP Address for tracking purposes. */ c_ws_plugin__s2member_utils_ip::current();
510
511 $paypal_invoice_input_value = /* s2Member's Unique Code~IP combo. */ uniqid () . "~" . c_ws_plugin__s2member_utils_ip::current();
512
513 $attr["level_ccaps_eotper"] = ($attr["rr"] === "BN" && $attr["rt"] !== "L") ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
514 $attr["level_ccaps_eotper"] = /* Clean any trailing separators from this string. */ rtrim ($attr["level_ccaps_eotper"], ":");
515
516 $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered. */ home_url ("/?s2member_paypal_return=1", $force_return_url_scheme);
517 $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
518
519
520 //260114 PayPal Checkout (REST) CCAPS (Independent Custom Capabilities) override.
521 // Uses server-side create + server-side capture, then posts into existing IPN + Return handlers.
522 if(c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_enabled())
523 {
524 $ppco_sandbox = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_sandbox();
525 $ppco_client_id = (string)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"][($ppco_sandbox) ? "paypal_checkout_sandbox_client_id" : "paypal_checkout_client_id"];
526
527 $ppco_cc = strtoupper((string)$attr["cc"]);
528 $ppco_intent = 'capture';
529
530 $ppco_sdk_key = (($ppco_sandbox) ? 'sandbox' : 'live').'|'.$ppco_cc.'|'.$ppco_intent;
531
532 $ppco_sdk_just_loaded = false;
533 if(empty($ppco_sdks[$ppco_sdk_key]) || !is_array($ppco_sdks[$ppco_sdk_key]))
534 {
535 $ppco_sdks[$ppco_sdk_key] = array(
536 'ns' => 's2m_ppco_'.substr(md5($ppco_sdk_key), 0, 10),
537 'id' => 's2member_ppco_sdk_'.substr(md5($ppco_sdk_key), 0, 10),
538 );
539 $ppco_sdk_just_loaded = true;
540 }
541
542 $ppco_sdk_ns = (string)$ppco_sdks[$ppco_sdk_key]['ns'];
543 $ppco_sdk_id = (string)$ppco_sdks[$ppco_sdk_key]['id'];
544
545 $ppco_endpoint = home_url("/?s2member_paypal_checkout=1", $force_notify_url_scheme);
546 $ppco_cancel = home_url("/");
547
548 $ppco_token = array(
549 'exp' => time() + 3600,
550
551 'invoice' => $paypal_invoice_input_value,
552 'ip' => c_ws_plugin__s2member_utils_ip::current(),
553 'item_name' => $attr["desc"],
554 'item_number' => $attr["level_ccaps_eotper"],
555 'custom' => $attr["custom"],
556
557 'amount' => $attr["ra"],
558 'cc' => $ppco_cc,
559 'ns' => $attr["ns"],
560
561 'rr' => 'BN',
562
563 'on0' => $paypal_on0_input_value,
564 'os0' => $paypal_os0_input_value,
565 'on1' => $paypal_on1_input_value,
566 'os1' => $paypal_os1_input_value,
567
568 'return' => $success_return_url,
569 'cancel' => $ppco_cancel,
570
571 'checksum' => md5($paypal_invoice_input_value.c_ws_plugin__s2member_utils_ip::current().$attr["level_ccaps_eotper"]),
572 );
573
574 $ppco_token = urlencode(c_ws_plugin__s2member_utils_encryption::encrypt(serialize($ppco_token)));
575
576 // output="anchor|url" support (no JS SDK; redirects through s2Member, then to PayPal approval URL).
577 if($attr["output"] === "anchor" || $attr["output"] === "url")
578 {
579 $ppco_redirect_url = $ppco_endpoint.'&s2member_paypal_checkout_op=redirect&s2member_paypal_checkout_t='.$ppco_token;
580
581 if($attr["output"] === "url")
582 $code = $_code = $ppco_redirect_url;
583
584 else // output="anchor"
585 {
586 $img_src = ($attr["image"] && $attr["image"] !== "default") ? $attr["image"] : $default_image;
587 $code = $_code = '<a class="ws-plugin--s2member-paypal-button ws-plugin--s2member-paypal-anchor" href="'.esc_attr($ppco_redirect_url).'"><img class="ws-plugin--s2member-paypal-button-img" src="'.esc_attr($img_src).'" style="width:auto; height:auto; border:0; margin:0;" alt="PayPal" /></a>';
588 }
589
590 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
591 do_action("ws_plugin__s2member_during_sc_paypal_ccaps_button", get_defined_vars ());
592 unset($__refs, $__v);
593
594 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
595 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
596 }
597
598 $ppco_div_id = 's2member_ppco_btn_'.md5($paypal_invoice_input_value.$attr["level_ccaps_eotper"]);
599 $ppco_err_id = 's2member_ppco_err_'.md5($paypal_invoice_input_value.$attr["level_ccaps_eotper"]);
600
601 $ppco_locale = ($attr["lang"]) ? (string)$attr["lang"] : '';
602 $ppco_lc = ($attr["lc"]) ? (string)$attr["lc"] : '';
603
604 if(!$ppco_locale && $ppco_lc)
605 {
606 $site_locale = (string)get_locale();
607 if(preg_match('/^([a-z]{2})[_-]/i', $site_locale, $m))
608 $ppco_locale = strtolower($m[1]).'_'.strtoupper($ppco_lc);
609 else
610 $ppco_locale = 'en_'.strtoupper($ppco_lc);
611 }
612
613 $ppco_locale_q = ($ppco_locale) ? '&locale='.rawurlencode($ppco_locale) : '';
614 $ppco_buyer_country_q = ($ppco_sandbox && $ppco_lc) ? '&buyer-country='.rawurlencode(strtoupper($ppco_lc)) : '';
615
616 $ppco_sdk_src = ($ppco_sandbox ? 'https://www.sandbox.paypal.com/sdk/js' : 'https://www.paypal.com/sdk/js');
617 //260114 !!! Independent CCAPS is capture-only; conditional subscription path below is dead code (cleanup/refactor later).
618 if($ppco_intent === 'subscription')
619 $ppco_sdk_src = $ppco_sdk_src.'?client-id='.rawurlencode($ppco_client_id).'&currency='.rawurlencode($ppco_cc).'&vault=true&intent=subscription&disable-funding=card'.$ppco_buyer_country_q.$ppco_locale_q;
620 else
621 $ppco_sdk_src = $ppco_sdk_src.'?client-id='.rawurlencode($ppco_client_id).'&currency='.rawurlencode($ppco_cc).'&intent=capture&commit=true&disable-funding=card'.$ppco_buyer_country_q.$ppco_locale_q;
622
623 $code = '<div id="'.esc_attr($ppco_div_id).'" class="ws-plugin--s2member-paypal-button ws-plugin--s2member-ppco-button" style="max-width:145px; width:auto; margin:0;"></div>'."\n";
624 $code .= '<div id="'.esc_attr($ppco_err_id).'" class="ws-plugin--s2member-ppco-message" style="display:none; margin:0;"></div>'."\n";
625
626 $ppco_sdk_src = apply_filters('ws_plugin__s2member_ppco_sdk_src', $ppco_sdk_src, get_defined_vars());
627
628 if($ppco_sdk_just_loaded)
629 {
630 $code .= '<script id="'.esc_attr($ppco_sdk_id).'" data-namespace="'.esc_attr($ppco_sdk_ns).'" src="'.esc_attr($ppco_sdk_src).'"></script>'."\n";
631 }
632
633 $code .= '<script type="text/javascript">'."\n";
634 $code .= '(function(){'."\n";
635 $code .= 'var d="'.esc_js($ppco_div_id).'";'."\n";
636 $code .= 'var e="'.esc_js($ppco_err_id).'";'."\n";
637 $code .= 'var t="'.esc_js($ppco_token).'";'."\n";
638 $code .= 'var u="'.esc_js($ppco_endpoint).'";'."\n";
639 $code .= 'var ns="'.esc_js($ppco_sdk_ns).'";'."\n";
640 $code .= 'var s="'.esc_js($ppco_sdk_src).'";'."\n";
641 $code .= 'var cid="'.esc_js($paypal_invoice_input_value).'";'."\n";
642 //260819.0042 Keep standalone Checkout feedback consistent with Pro-Forms while distinguishing cancellation from errors.
643 $code .= 'function showMsg(m,t){try{var el=document.getElementById(e);if(el){el.style.display="block";el.innerHTML="<span class=\"ws-plugin--s2member-ppco-"+(t==="info"?"info":"error")+"\">"+m+"</span>";}}catch(x){}}function showErr(m){showMsg(m,"error");}function showInfo(m){showMsg(m,"info");}'."\n";
644 $code .= 'function postTo(url, data){var f=document.createElement("form");f.method="post";f.acceptCharset="UTF-8";f.action=url;for(var k in data){if(!data.hasOwnProperty(k))continue;var i=document.createElement("input");i.type="hidden";i.name=k;i.value=data[k];f.appendChild(i);}document.body.appendChild(f);f.submit();}'."\n"; //260817 Keep signed PayPal Checkout returns in UTF-8.
645 $code .= 'function enc(o){var a=[];for(var k in o){if(!o.hasOwnProperty(k))continue;a.push(encodeURIComponent(k)+"="+encodeURIComponent(o[k]));}return a.join("&");}'."\n";
646 $code .= 'function loadSdk(cb){var P=window[ns];if(P&&P.Buttons){cb(P);return;}var id=ns+"_sdk",tag=document.getElementById(id),done=false;function finish(){if(done)return;done=true;cb(window[ns]&&window[ns].Buttons?window[ns]:null);}function ok(){finish();}function fail(){finish();}if(tag){if(window[ns]&&window[ns].Buttons){finish();return;}if(tag.getAttribute("src")!==s){tag.setAttribute("src",s);}if(tag.readyState==="complete"||tag.readyState==="loaded"){setTimeout(finish,0);return;}tag.addEventListener("load",ok);tag.addEventListener("error",fail);setTimeout(finish,3500);return;}tag=document.createElement("script");tag.id=id;tag.setAttribute("data-namespace",ns);tag.src=s;tag.async=true;tag.onload=ok;tag.onerror=fail;(document.head||document.body||document.documentElement).appendChild(tag);setTimeout(finish,3500);}'."\n";
647 if($ppco_intent === 'subscription')
648 {
649 $code .= 'function getPlanId(){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"get_plan_id",s2member_paypal_checkout_t:t})}).then(function(r){return r.json();}).then(function(res){if(res&&res.plan_id)return res.plan_id;throw(res&&res.error?res.error:"plan_get_failed");});}'."\n";
650 $code .= 'var planId=null;'."\n";
651 $code .= 'function createSubscription(data,actions){if(planId)return actions.subscription.create({plan_id:planId,custom_id:cid,application_context:{shipping_preference:"NO_SHIPPING"}});return getPlanId().then(function(pid){planId=pid;return actions.subscription.create({plan_id:planId,custom_id:cid,application_context:{shipping_preference:"NO_SHIPPING"}});});}'."\n";
652 $code .= 'function onApprove(data){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"confirm_subscription",s2member_paypal_checkout_t:t,subscription_id:(data&&data.subscriptionID?data.subscriptionID:"")})}).then(function(r){return r.json();}).then(function(res){if(res&&res.rtn_url&&res.rtn_post){postTo(res.rtn_url,res.rtn_post);return;}throw(res&&res.error?res.error:"subscription_confirm_failed");}).catch(function(e){showErr("Subscription could not be completed. Please try again.");});}'."\n";
653 $code .= 'function onCancel(){showInfo("Subscription cancelled.");}'."\n";
654 $code .= 'function onError(err){var m="PayPal error. Please try again.";try{if(err){if(typeof err==="string")m="PayPal error: "+err;else if(err.message)m="PayPal error: "+err.message;}}catch(x){}showErr(m);}'."\n";
655 $code .= 'function init(){loadSdk(function(P){var el=document.getElementById(d);if(!el){return;}if(el.getAttribute("data-s2m-ppco-rendered")==="1"){return;}if(!P||!P.Buttons){showErr("PayPal SDK failed to load.");return;}el.setAttribute("data-s2m-ppco-rendered","1");try{P.Buttons({fundingSource:P.FUNDING.PAYPAL,style:{layout:"vertical",tagline:false,height:40},createSubscription:createSubscription,onApprove:onApprove,onCancel:onCancel,onError:onError}).render("#"+d);}catch(x){el.removeAttribute("data-s2m-ppco-rendered");showErr("PayPal render failed.");}});}'."\n";
656 }
657 else
658 {
659 $code .= 'function createOrder(){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"create_order",s2member_paypal_checkout_t:t})}).then(function(r){return r.json();}).then(function(res){if(res&&res.order_id)return res.order_id;throw(res&&res.error?res.error:"order_create_failed");});}'."\n";
660 $code .= 'function onApprove(data){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"capture_order",s2member_paypal_checkout_t:t,order_id:(data&&data.orderID?data.orderID:"")})}).then(function(r){return r.json();}).then(function(res){if(res&&res.rtn_url&&res.rtn_post){postTo(res.rtn_url,res.rtn_post);return;}throw(res&&res.error?res.error:"order_capture_failed");}).catch(function(e){showErr("Payment could not be completed. Please try again.");});}'."\n";
661 $code .= 'function onCancel(){showInfo("Payment cancelled.");}'."\n";
662 $code .= 'function onError(err){var m="PayPal error. Please try again.";try{if(err){if(typeof err==="string")m="PayPal error: "+err;else if(err.message)m="PayPal error: "+err.message;}}catch(x){}showErr(m);}'."\n";
663 $code .= 'function init(){loadSdk(function(P){var el=document.getElementById(d);if(!el){return;}if(el.getAttribute("data-s2m-ppco-rendered")==="1"){return;}if(!P||!P.Buttons){showErr("PayPal SDK failed to load.");return;}el.setAttribute("data-s2m-ppco-rendered","1");try{P.Buttons({fundingSource:P.FUNDING.PAYPAL,style:{layout:"vertical",tagline:false,height:40},createOrder:createOrder,onApprove:onApprove,onCancel:onCancel,onError:onError}).render("#"+d);}catch(x){el.removeAttribute("data-s2m-ppco-rendered");showErr("PayPal render failed.");}});}'."\n";
664 }
665 $code .= 'if(document.readyState==="complete"){init();}else{window.addEventListener("load",init);}'."\n";
666 $code .= '})();'."\n";
667 $code .= '</script>'."\n";
668 $_code = $code;
669
670 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
671 do_action("ws_plugin__s2member_during_sc_paypal_ccaps_button", get_defined_vars ());
672 unset($__refs, $__v);
673
674 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
675 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
676 }
677
678 $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-ccaps-checkout-button.php")));
679 $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/src/images")), $code);
680 $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ())), $code);
681
682 $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
683 $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
684 $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
685 $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code);
686 $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/?s2member_paypal_notify=1", $force_notify_url_scheme))), $code);
687 $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
688 $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
689
690 $code = preg_replace ('/ name\="lc" value\="(.*?)"/', ' name="lc" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["lc"])) . '"', $code);
691 $code = preg_replace ('/ name\="no_shipping" value\="(.*?)"/', ' name="no_shipping" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ns"])) . '"', $code);
692 $code = preg_replace ('/ name\="item_name" value\="(.*?)"/', ' name="item_name" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["desc"])) . '"', $code);
693 $code = preg_replace ('/ name\="item_number" value\="(.*?)"/', ' name="item_number" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["level_ccaps_eotper"])) . '"', $code);
694 $code = preg_replace ('/ name\="page_style" value\="(.*?)"/', ' name="page_style" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ps"])) . '"', $code);
695 $code = preg_replace ('/ name\="currency_code" value\="(.*?)"/', ' name="currency_code" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["cc"])) . '"', $code);
696 $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])) . '"', $code);
697
698 $code = preg_replace ('/ name\="invoice" value\="(.*?)"/', ' name="invoice" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_invoice_input_value)) . '"', $code);
699
700 $code = preg_replace ('/ name\="on0" value\="(.*?)"/', ' name="on0" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_on0_input_value)) . '"', $code);
701 $code = preg_replace ('/ name\="os0" value\="(.*?)"/', ' name="os0" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_os0_input_value)) . '"', $code);
702 $code = preg_replace ('/ name\="on1" value\="(.*?)"/', ' name="on1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_on1_input_value)) . '"', $code);
703 $code = preg_replace ('/ name\="os1" value\="(.*?)"/', ' name="os1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_os1_input_value)) . '"', $code);
704
705 $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ra"])) . '"', $code);
706
707 $code = $_code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["image"])) . '"', $code) : preg_replace ('/ src\="(.*?)"/', ' src="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($default_image)) . '"', $code);
708
709 $code = ($attr["output"] === "anchor") ? '<a href="' . esc_attr (c_ws_plugin__s2member_utils_forms::form_whips_2_url ($code)) . '"><img src="' . esc_attr (($attr["image"] && $attr["image"] !== "default") ? $attr["image"] : $default_image) . '" style="width:auto; height:auto; border:0;" alt="PayPal" /></a>' : $code;
710 $code = ($attr["output"] === "url") ? c_ws_plugin__s2member_utils_forms::form_whips_2_url ($code) : $code;
711
712 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
713 do_action("ws_plugin__s2member_during_sc_paypal_ccaps_button", get_defined_vars ());
714 unset($__refs, $__v);
715 }
716 else // Otherwise, we'll process this Button normally, using Membership routines.
717 {
718 $default_image = "https://www.paypal.com/" . (($attr["lang"]) ? $attr["lang"] : _x ("en_US", "s2member-front paypal-button-lang-code", "s2member")) . "/i/btn/btn_xpressCheckout.gif";
719
720 $paypal_on0_input_value = ($referencing = c_ws_plugin__s2member_utils_users::get_user_subscr_or_wp_id ()) ? "Referencing Customer ID" : "Originating Domain";
721 $paypal_os0_input_value = /* Current User's Paid Subscr. ID, or WP User ID, or domain. */ ($referencing) ? $referencing : $_SERVER["HTTP_HOST"];
722
723 $paypal_on1_input_value = /* Identifies the Customer's IP Address for tracking purposes. */ "Customer IP Address";
724 $paypal_os1_input_value = /* Current User's IP Address for tracking purposes. */ c_ws_plugin__s2member_utils_ip::current();
725
726 $paypal_invoice_input_value = /* s2Member's Unique Code~IP combo. */ uniqid () . "~" . c_ws_plugin__s2member_utils_ip::current();
727
728 $attr["desc"] = (!$attr["desc"]) ? $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"] : $attr["desc"];
729
730 // PayPal Checkout: rr=0 with no trial/initial should behave like Buy Now (one-time),
731 // so s2Member’s standard Buy Now/EOT routines run (mirrors other gateways).
732 if(c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_enabled()
733 && (string)$attr["rr"] === '0'
734 && (float)$attr["ta"] <= 0
735 && (int)$attr["tp"] <= 0)
736 {
737 $attr["rr"] = 'BN';
738 }
739
740 $attr["level_ccaps_eotper"] = ($attr["rr"] === "BN" && $attr["rt"] !== "L") ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
741 $attr["level_ccaps_eotper"] = /* Clean any trailing separators from this string. */ rtrim ($attr["level_ccaps_eotper"], ":");
742
743 $success_return_tra = array("ta" => $attr["ta"], "tp" => $attr["tp"], "tt" => $attr["tt"], "ra" => $attr["ra"], "rp" => $attr["rp"], "rt" => $attr["rt"], "rr" => $attr["rr"], "rrt" => $attr["rrt"], "rra" => $attr["rra"], "invoice" => $paypal_invoice_input_value, "checksum" => md5 ($paypal_invoice_input_value . c_ws_plugin__s2member_utils_ip::current() . $attr["level_ccaps_eotper"]));
744
745 $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered (see below). */ home_url ("/?s2member_paypal_return=1", $force_return_url_scheme);
746 $success_return_url = add_query_arg ("s2member_paypal_return_tra", urlencode (c_ws_plugin__s2member_utils_encryption::encrypt (serialize ($success_return_tra))), $success_return_url);
747 $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
748
749 //260106 PayPal Checkout (REST) Buy Now (rr=BN) override.
750 // Uses server-side create + server-side capture/confirm, then posts into existing IPN + Return handlers.
751 if(c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_enabled())
752 {
753 $ppco_sandbox = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_is_sandbox();
754 $ppco_client_id = (string)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"][($ppco_sandbox) ? "paypal_checkout_sandbox_client_id" : "paypal_checkout_client_id"];
755
756 $ppco_cc = strtoupper((string)$attr["cc"]);
757 $ppco_intent = ($attr["rr"] === "BN") ? 'capture' : 'subscription';
758
759 $ppco_sdk_key = (($ppco_sandbox) ? 'sandbox' : 'live').'|'.$ppco_cc.'|'.$ppco_intent;
760
761 $ppco_sdk_just_loaded = false;
762 if(empty($ppco_sdks[$ppco_sdk_key]) || !is_array($ppco_sdks[$ppco_sdk_key]))
763 {
764 $ppco_sdks[$ppco_sdk_key] = array(
765 'ns' => 's2m_ppco_'.substr(md5($ppco_sdk_key), 0, 10),
766 'id' => 's2member_ppco_sdk_'.substr(md5($ppco_sdk_key), 0, 10),
767 );
768 $ppco_sdk_just_loaded = true;
769 }
770
771 $ppco_sdk_ns = (string)$ppco_sdks[$ppco_sdk_key]['ns'];
772 $ppco_sdk_id = (string)$ppco_sdks[$ppco_sdk_key]['id'];
773
774 $ppco_endpoint = home_url("/?s2member_paypal_checkout=1", $force_notify_url_scheme);
775 $ppco_cancel = home_url("/");
776
777 $ppco_token = array(
778 'exp' => time() + 3600,
779
780 'invoice' => $paypal_invoice_input_value,
781 'ip' => c_ws_plugin__s2member_utils_ip::current(),
782 'item_name' => $attr["desc"],
783 'item_number' => $attr["level_ccaps_eotper"],
784 'custom' => $attr["custom"],
785
786 'amount' => $attr["ra"],
787 'cc' => $ppco_cc,
788 'ns' => $attr["ns"],
789
790 'rr' => $attr["rr"],
791 'rp' => $attr["rp"],
792 'rt' => $attr["rt"],
793
794 'rrt' => $attr["rrt"],
795 'rra' => $attr["rra"],
796
797 'ta' => $attr["ta"],
798 'tp' => $attr["tp"],
799 'tt' => $attr["tt"],
800
801 'on0' => $paypal_on0_input_value,
802 'os0' => $paypal_os0_input_value,
803 'on1' => $paypal_on1_input_value,
804 'os1' => $paypal_os1_input_value,
805
806 'old__subscr_gateway' => get_user_option('s2member_subscr_gateway'),
807 'old__subscr_id' => get_user_option('s2member_subscr_id'),
808 'old__subscr_baid' => get_user_option('s2member_subscr_baid'),
809 'old__subscr_cid' => get_user_option('s2member_subscr_cid'),
810 'old__ipn_signup_vars' => c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(), //260408 Capture the old context before PayPal/webhook processing can update the member's current profile.
811
812 'return' => $success_return_url,
813 'cancel' => $ppco_cancel,
814
815 'checksum' => md5($paypal_invoice_input_value.c_ws_plugin__s2member_utils_ip::current().$attr["level_ccaps_eotper"]),
816 );
817
818 $ppco_token = urlencode(c_ws_plugin__s2member_utils_encryption::encrypt(serialize($ppco_token)));
819
820 // output="anchor|url" support (no JS SDK; redirects through s2Member, then to PayPal approval URL).
821 if($attr["output"] === "anchor" || $attr["output"] === "url")
822 {
823 $ppco_redirect_url = $ppco_endpoint.'&s2member_paypal_checkout_op=redirect&s2member_paypal_checkout_t='.$ppco_token;
824
825 if($attr["output"] === "url")
826 $code = $_code = $ppco_redirect_url;
827
828 else // output="anchor"
829 {
830 $img_src = ($attr["image"] && $attr["image"] !== "default") ? $attr["image"] : $default_image;
831 $code = $_code = '<a class="ws-plugin--s2member-paypal-button ws-plugin--s2member-paypal-anchor" href="'.esc_attr($ppco_redirect_url).'"><img class="ws-plugin--s2member-paypal-button-img" src="'.esc_attr($img_src).'" style="width:auto; height:auto; border:0; margin:0;" alt="PayPal" /></a>';
832 }
833
834 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
835 do_action("ws_plugin__s2member_during_sc_paypal_button", get_defined_vars ());
836 unset($__refs, $__v);
837
838 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
839 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
840 }
841
842 $ppco_div_id = 's2member_ppco_btn_'.md5($paypal_invoice_input_value.$attr["level_ccaps_eotper"]);
843 $ppco_err_id = 's2member_ppco_err_'.md5($paypal_invoice_input_value.$attr["level_ccaps_eotper"]);
844
845 $ppco_locale = ($attr["lang"]) ? (string)$attr["lang"] : '';
846 $ppco_lc = ($attr["lc"]) ? (string)$attr["lc"] : '';
847
848 if(!$ppco_locale && $ppco_lc)
849 {
850 $site_locale = (string)get_locale();
851 if(preg_match('/^([a-z]{2})[_-]/i', $site_locale, $m))
852 $ppco_locale = strtolower($m[1]).'_'.strtoupper($ppco_lc);
853 else
854 $ppco_locale = 'en_'.strtoupper($ppco_lc);
855 }
856
857 $ppco_locale_q = ($ppco_locale) ? '&locale='.rawurlencode($ppco_locale) : '';
858 $ppco_buyer_country_q = ($ppco_sandbox && $ppco_lc) ? '&buyer-country='.rawurlencode(strtoupper($ppco_lc)) : '';
859
860 $ppco_sdk_src = ($ppco_sandbox ? 'https://www.sandbox.paypal.com/sdk/js' : 'https://www.paypal.com/sdk/js');
861 if($ppco_intent === 'subscription')
862 $ppco_sdk_src = $ppco_sdk_src.'?client-id='.rawurlencode($ppco_client_id).'&currency='.rawurlencode($ppco_cc).'&vault=true&intent=subscription&disable-funding=card'.$ppco_buyer_country_q.$ppco_locale_q;
863 else
864 $ppco_sdk_src = $ppco_sdk_src.'?client-id='.rawurlencode($ppco_client_id).'&currency='.rawurlencode($ppco_cc).'&intent=capture&commit=true&disable-funding=card'.$ppco_buyer_country_q.$ppco_locale_q;
865
866 $code = '<div id="'.esc_attr($ppco_div_id).'" class="ws-plugin--s2member-paypal-button ws-plugin--s2member-ppco-button" style="max-width:145px; width:auto; margin:0;"></div>'."\n";
867 $code .= '<div id="'.esc_attr($ppco_err_id).'" class="ws-plugin--s2member-ppco-message" style="display:none; margin:0;"></div>'."\n";
868
869 $ppco_sdk_src = apply_filters('ws_plugin__s2member_ppco_sdk_src', $ppco_sdk_src, get_defined_vars());
870
871 if($ppco_sdk_just_loaded)
872 {
873 $code .= '<script id="'.esc_attr($ppco_sdk_id).'" data-namespace="'.esc_attr($ppco_sdk_ns).'" src="'.esc_attr($ppco_sdk_src).'"></script>'."\n";
874 }
875
876 $code .= '<script type="text/javascript">'."\n";
877 $code .= '(function(){'."\n";
878 $code .= 'var d="'.esc_js($ppco_div_id).'";'."\n";
879 $code .= 'var e="'.esc_js($ppco_err_id).'";'."\n";
880 $code .= 'var t="'.esc_js($ppco_token).'";'."\n";
881 $code .= 'var u="'.esc_js($ppco_endpoint).'";'."\n";
882 $code .= 'var ns="'.esc_js($ppco_sdk_ns).'";'."\n";
883 $code .= 'var s="'.esc_js($ppco_sdk_src).'";'."\n";
884 $code .= 'var cid="'.esc_js($paypal_invoice_input_value).'";'."\n";
885 //260819.0042 Keep standalone Checkout feedback consistent with Pro-Forms while distinguishing cancellation from errors.
886 $code .= 'function showMsg(m,t){try{var el=document.getElementById(e);if(el){el.style.display="block";el.innerHTML="<span class=\"ws-plugin--s2member-ppco-"+(t==="info"?"info":"error")+"\">"+m+"</span>";}}catch(x){}}function showErr(m){showMsg(m,"error");}function showInfo(m){showMsg(m,"info");}'."\n";
887 $code .= 'function postTo(url, data){var f=document.createElement("form");f.method="post";f.acceptCharset="UTF-8";f.action=url;for(var k in data){if(!data.hasOwnProperty(k))continue;var i=document.createElement("input");i.type="hidden";i.name=k;i.value=data[k];f.appendChild(i);}document.body.appendChild(f);f.submit();}'."\n"; //260817 Keep signed PayPal Checkout returns in UTF-8.
888 $code .= 'function enc(o){var a=[];for(var k in o){if(!o.hasOwnProperty(k))continue;a.push(encodeURIComponent(k)+"="+encodeURIComponent(o[k]));}return a.join("&");}'."\n";
889 $code .= 'function loadSdk(cb){var P=window[ns];if(P&&P.Buttons){cb(P);return;}var id=ns+"_sdk",tag=document.getElementById(id),done=false;function finish(){if(done)return;done=true;cb(window[ns]&&window[ns].Buttons?window[ns]:null);}function ok(){finish();}function fail(){finish();}if(tag){if(window[ns]&&window[ns].Buttons){finish();return;}if(tag.getAttribute("src")!==s){tag.setAttribute("src",s);}if(tag.readyState==="complete"||tag.readyState==="loaded"){setTimeout(finish,0);return;}tag.addEventListener("load",ok);tag.addEventListener("error",fail);setTimeout(finish,3500);return;}tag=document.createElement("script");tag.id=id;tag.setAttribute("data-namespace",ns);tag.src=s;tag.async=true;tag.onload=ok;tag.onerror=fail;(document.head||document.body||document.documentElement).appendChild(tag);setTimeout(finish,3500);}'."\n";
890 if($ppco_intent === 'subscription')
891 {
892 $code .= 'function getPlanId(){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"get_plan_id",s2member_paypal_checkout_t:t})}).then(function(r){return r.json();}).then(function(res){if(res&&res.plan_id)return res.plan_id;throw(res&&res.error?res.error:"plan_get_failed");});}'."\n";
893 $code .= 'var planId=null;'."\n";
894 $code .= 'function createSubscription(data,actions){if(planId)return actions.subscription.create({plan_id:planId,custom_id:cid,application_context:{shipping_preference:"NO_SHIPPING"}});return getPlanId().then(function(pid){planId=pid;return actions.subscription.create({plan_id:planId,custom_id:cid,application_context:{shipping_preference:"NO_SHIPPING"}});});}'."\n";
895 $code .= 'function onApprove(data){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"confirm_subscription",s2member_paypal_checkout_t:t,subscription_id:(data&&data.subscriptionID?data.subscriptionID:"")})}).then(function(r){return r.json();}).then(function(res){if(res&&res.rtn_url&&res.rtn_post){postTo(res.rtn_url,res.rtn_post);return;}throw(res&&res.error?res.error:"subscription_confirm_failed");}).catch(function(e){showErr("Subscription could not be completed. Please try again.");});}'."\n";
896 $code .= 'function onCancel(){showInfo("Subscription cancelled.");}'."\n";
897 $code .= 'function onError(err){var m="PayPal error. Please try again.";try{if(err){if(typeof err==="string")m="PayPal error: "+err;else if(err.message)m="PayPal error: "+err.message;}}catch(x){}showErr(m);}'."\n";
898 $code .= 'function init(){loadSdk(function(P){var el=document.getElementById(d);if(!el){return;}if(el.getAttribute("data-s2m-ppco-rendered")==="1"){return;}if(!P||!P.Buttons){showErr("PayPal SDK failed to load.");return;}el.setAttribute("data-s2m-ppco-rendered","1");try{P.Buttons({fundingSource:P.FUNDING.PAYPAL,style:{layout:"vertical",tagline:false,height:40},createSubscription:createSubscription,onApprove:onApprove,onCancel:onCancel,onError:onError}).render("#"+d);}catch(x){el.removeAttribute("data-s2m-ppco-rendered");showErr("PayPal render failed.");}});}'."\n";
899 }
900 else
901 {
902 $code .= 'function createOrder(){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"create_order",s2member_paypal_checkout_t:t})}).then(function(r){return r.json();}).then(function(res){if(res&&res.order_id)return res.order_id;throw(res&&res.error?res.error:"order_create_failed");});}'."\n";
903 $code .= 'function onApprove(data){return fetch(u,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:enc({s2member_paypal_checkout_op:"capture_order",s2member_paypal_checkout_t:t,order_id:(data&&data.orderID?data.orderID:"")})}).then(function(r){return r.json();}).then(function(res){if(res&&res.rtn_url&&res.rtn_post){postTo(res.rtn_url,res.rtn_post);return;}throw(res&&res.error?res.error:"order_capture_failed");}).catch(function(e){showErr("Payment could not be completed. Please try again.");});}'."\n";
904 $code .= 'function onCancel(){showInfo("Payment cancelled.");}'."\n";
905 $code .= 'function onError(err){var m="PayPal error. Please try again.";try{if(err){if(typeof err==="string")m="PayPal error: "+err;else if(err.message)m="PayPal error: "+err.message;}}catch(x){}showErr(m);}'."\n";
906 $code .= 'function init(){loadSdk(function(P){var el=document.getElementById(d);if(!el){return;}if(el.getAttribute("data-s2m-ppco-rendered")==="1"){return;}if(!P||!P.Buttons){showErr("PayPal SDK failed to load.");return;}el.setAttribute("data-s2m-ppco-rendered","1");try{P.Buttons({fundingSource:P.FUNDING.PAYPAL,style:{layout:"vertical",tagline:false,height:40},createOrder:createOrder,onApprove:onApprove,onCancel:onCancel,onError:onError}).render("#"+d);}catch(x){el.removeAttribute("data-s2m-ppco-rendered");showErr("PayPal render failed.");}});}'."\n";
907 }
908 $code .= 'if(document.readyState==="complete"){init();}else{window.addEventListener("load",init);}'."\n";
909 $code .= '})();'."\n";
910 $code .= '</script>'."\n";
911 $_code = $code;
912
913 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
914 do_action("ws_plugin__s2member_during_sc_paypal_button", get_defined_vars ());
915 unset($__refs, $__v);
916
917 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
918 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
919 }
920
921 $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.php")));
922 $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/src/images")), $code);
923 $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ())), $code);
924
925 $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
926 $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
927 $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
928 $code = preg_replace ("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"])), $code);
929 $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code); // This brings them back to Front Page.
930 $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/?s2member_paypal_notify=1", $force_notify_url_scheme))), $code);
931 $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
932 $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
933 $code = preg_replace ("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["level"])), $code);
934
935 $code = preg_replace ('/ \<\!--(\<input type\="hidden" name\="(amount|src|srt|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/', " $1", $code);
936 $code = ($attr["rr"] === "BN") ? preg_replace ('/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/', " $1_xclick$3", $code) : $code;
937 $code = ($attr["rr"] === "BN") ? preg_replace ('/ (\<input type\="hidden" name\="(src|srt|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/', " <!--$1-->", $code) : $code;
938 $code = ($attr["rr"] === "BN" || !$attr["tp"]) ? preg_replace ('/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/', " <!--$1-->", $code) : $code;
939 $code = ($attr["rr"] !== "BN") ? preg_replace ('/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/', " $1_xclick-subscriptions$3", $code) : $code;
940 $code = ($attr["rr"] !== "BN") ? preg_replace ('/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/', " <!--$1-->", $code) : $code;
941
942 $code = preg_replace ('/ name\="lc" value\="(.*?)"/', ' name="lc" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["lc"])) . '"', $code);
943 $code = preg_replace ('/ name\="no_shipping" value\="(.*?)"/', ' name="no_shipping" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ns"])) . '"', $code);
944 $code = preg_replace ('/ name\="item_name" value\="(.*?)"/', ' name="item_name" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["desc"])) . '"', $code);
945 $code = preg_replace ('/ name\="item_number" value\="(.*?)"/', ' name="item_number" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["level_ccaps_eotper"])) . '"', $code);
946 $code = preg_replace ('/ name\="page_style" value\="(.*?)"/', ' name="page_style" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ps"])) . '"', $code);
947 $code = preg_replace ('/ name\="currency_code" value\="(.*?)"/', ' name="currency_code" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["cc"])) . '"', $code);
948 $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])) . '"', $code);
949
950 $code = preg_replace ('/ name\="invoice" value\="(.*?)"/', ' name="invoice" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_invoice_input_value)) . '"', $code);
951
952 $code = preg_replace ('/ name\="on0" value\="(.*?)"/', ' name="on0" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_on0_input_value)) . '"', $code);
953 $code = preg_replace ('/ name\="os0" value\="(.*?)"/', ' name="os0" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_os0_input_value)) . '"', $code);
954 $code = preg_replace ('/ name\="on1" value\="(.*?)"/', ' name="on1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_on1_input_value)) . '"', $code);
955 $code = preg_replace ('/ name\="os1" value\="(.*?)"/', ' name="os1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($paypal_os1_input_value)) . '"', $code);
956
957 $code = preg_replace ('/ name\="modify" value\="(.*?)"/', ' name="modify" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["modify"])) . '"', $code);
958
959 $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ra"])) . '"', $code);
960
961 $code = preg_replace ('/ name\="src" value\="(.*?)"/', ' name="src" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["rr"])) . '"', $code);
962 $code = preg_replace ('/ name\="srt" value\="(.*?)"/', ' name="srt" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["rrt"])) . '"', $code);
963 $code = preg_replace ('/ name\="sra" value\="(.*?)"/', ' name="sra" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["rra"])) . '"', $code);
964
965 $code = preg_replace ('/ name\="a1" value\="(.*?)"/', ' name="a1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ta"])) . '"', $code);
966 $code = preg_replace ('/ name\="p1" value\="(.*?)"/', ' name="p1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["tp"])) . '"', $code);
967 $code = preg_replace ('/ name\="t1" value\="(.*?)"/', ' name="t1" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["tt"])) . '"', $code);
968 $code = preg_replace ('/ name\="a3" value\="(.*?)"/', ' name="a3" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["ra"])) . '"', $code);
969 $code = preg_replace ('/ name\="p3" value\="(.*?)"/', ' name="p3" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["rp"])) . '"', $code);
970 $code = preg_replace ('/ name\="t3" value\="(.*?)"/', ' name="t3" value="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["rt"])) . '"', $code);
971
972 $code = $_code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["image"])) . '"', $code) : preg_replace ('/ src\="(.*?)"/', ' src="' . c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($default_image)) . '"', $code);
973
974 $code = ($attr["output"] === "anchor") ? '<a href="' . esc_attr (c_ws_plugin__s2member_utils_forms::form_whips_2_url ($code)) . '"><img src="' . esc_attr (($attr["image"] && $attr["image"] !== "default") ? $attr["image"] : $default_image) . '" style="width:auto; height:auto; border:0;" alt="PayPal" /></a>' : $code;
975 $code = ($attr["output"] === "url") ? c_ws_plugin__s2member_utils_forms::form_whips_2_url ($code) : $code;
976
977 foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
978 ($attr["modify"]) ? do_action("ws_plugin__s2member_during_sc_paypal_modification_button", get_defined_vars ()) : do_action("ws_plugin__s2member_during_sc_paypal_button", get_defined_vars ());
979 unset($__refs, $__v);
980 }
981 $code = c_ws_plugin__s2member_sc_paypal_button_e::sc_paypal_button_encryption ($code, get_defined_vars ());
982
983 return apply_filters("ws_plugin__s2member_sc_paypal_button", $code, get_defined_vars ());
984 }
985 }
986 }
987