| @@ -74,8 +74,12 @@ | ||
| 74 | 74 | |
| 75 | 75 | $force_notify_url_scheme = apply_filters("ws_plugin__s2member_during_sc_paypal_button_force_notify_url_scheme", null, get_defined_vars ()); |
| 76 | 76 | $force_return_url_scheme = apply_filters("ws_plugin__s2member_during_sc_paypal_button_force_return_url_scheme", null, get_defined_vars ()); |
| 77 | 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 | + | |
| 78 | 82 | // PayPal Checkout SDK memoization (per request; shared across all button variants). |
| 79 | 83 | static $ppco_sdks = array(); |
| 80 | 84 | |
| 81 | 85 | foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v; |
| @@ -195,8 +199,12 @@ | ||
| 195 | 199 | |
| 196 | 200 | $ppco_btn_id = 's2member_ppco_cancel_'.md5($user_id.$subscr_id); |
| 197 | 201 | $ppco_msg_id = 's2member_ppco_cancel_msg_'.md5($user_id.$subscr_id); |
| 198 | 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 | + | |
| 199 | 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"; |
| 200 | 208 | $code .= '<button type="button" id="'.esc_attr($ppco_btn_id).'">'.esc_html(_x('Unsubscribe', 'paypal cancellation button label', 's2member')).'</button>'."\n"; //260218 |
| 201 | 209 | $code .= '<div id="'.esc_attr($ppco_msg_id).'" style="display:none; margin-top:8px;"></div>'."\n"; |
| 202 | 210 | $code .= '<script type="text/javascript">'."\n"; |
| @@ -203,8 +211,9 @@ | ||
| 203 | 211 | $code .= '(function(){'."\n"; |
| 204 | 212 | $code .= 'var b=document.getElementById("'.esc_js($ppco_btn_id).'");'."\n"; |
| 205 | 213 | $code .= 'var m=document.getElementById("'.esc_js($ppco_msg_id).'");'."\n"; |
| 206 | 214 | $code .= 'var u="'.esc_js($pp_manage_url).'";'."\n"; |
| 215 | + $code .= 'var s='.$ppco_success_json.';'."\n"; | |
| 207 | 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"; |
| 208 | 217 | $code .= 'function show(msg){try{if(m){m.style.display="block";m.innerHTML=msg;}}catch(e){}}'."\n"; |
| 209 | 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"; |
| 210 | 219 | $code .= 'if(!b){return;}'."\n"; |
| @@ -214,9 +223,9 @@ | ||
| 214 | 223 | $code .= 'if(!window.confirm("'.esc_js(__('Cancel your subscription now?', 's2member')).'")){return;}'."\n"; //260218 |
| 215 | 224 | $code .= 'b.disabled=true;'."\n"; |
| 216 | 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"; |
| 217 | 226 | $code .= '.then(function(r){return r.json();})'."\n"; |
| 218 | - $code .= '.then(function(res){if(res&&res.ok){show("'.esc_js(__('Subscription cancelled.', 's2member')).'");}else{goManage(); b.disabled=false;}})'."\n"; //260218 | |
| 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. | |
| 219 | 228 | $code .= '.catch(function(){goManage(); b.disabled=false;});'."\n"; |
| 220 | 229 | $code .= '});'."\n"; |
| 221 | 230 | $code .= '})();'."\n"; |
| 222 | 231 | $code .= '</script>'."\n"; |