The “trick” to allowing users to cancel there subscriptions is to use the PayPal ManageRecurringPaymentsProfileStatus API. This is an API that is available to Website Payments Standard users but is not documented in any of the Website Payments Standard documentation. The API is part of a collection of APIs for Express Checkout and Payments Pro. I was made aware of the API by PayPal’s integration support staff.
It is a very simple API that relies on the PayPal Profile ID which is in fact the PayPal subscr_id that IPN returns and the EE SCM module stores. You simple send a request to PayPal with this ID your credentials and the action to complete (CANCEL). That’s it.
Here is my code for a Cancel Tag. It produces a conditional that I can use in my template to display success or failure. The code is very basic but it works.
/** ----------------------------------------
/** Output Item Info for Cancel
/** ----------------------------------------*/
function cancel()
{
if (($paypal_subscriber_id = $this->EE->TMPL->fetch_param("paypal_subscriber_id")) === FALSE) return;
$API_Username="******************";
$API_Password="******************";
$API_Signature="*******************";
$nvpreq="METHOD=ManageRecurringPaymentsProfileStatus&VERSION=65.1&ACTION=cancel";
$nvpreq.="&PWD;=".urlencode($API_Password)."&USER;=".urlencode($API_Username)."&SIGNATURE;=".urlencode($API_Signature);
$nvpreq.="&PROFILEID;=".urlencode($paypal_subscriber_id);
$nvpreq.="&NOTE;=".urlencode("Cancelled by user from MyPlace Profile.");
if ($this->debug === TRUE){
$API_Endpoint = ( ! function_exists('openssl_open')) ? 'http://api-3t.sandbox.paypal.com/nvp' : 'https://api-3t.sandbox.paypal.com/nvp';
} else {
$API_Endpoint = ( ! function_exists('openssl_open')) ? 'http://api-3t.paypal.com/nvp' : 'https://api-3t.paypal.com/nvp';
}
$ch=curl_init();
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_URL,$API_Endpoint);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$nvpreq);
// Start ob to prevent curl_exec from displaying stuff.
ob_start();
curl_exec($ch);
//Get contents of output buffer
$result=ob_get_contents();
curl_close($ch);
//End ob and erase contents.
ob_end_clean();
//Debug Success Return Result
//$result = "PROFILEID=I-3DVFD070GSGJ&TIMESTAMP=2011-11-15T22:23:26Z&CORRELATIONID=c88f57235d57f&ACK=Success&VERSION=65.1&BUILD=2230381";
if(stristr($result,"ACK=Success")){
$cond["cancel_success"] = true;
} else {
$cond["cancel_success"] = false;
}
$tagdata = $this->EE->functions->prep_conditionals($this->EE->TMPL->tagdata, $cond);
return $tagdata;
}