12

On this page: https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECRecurringPayments

it says that it's possible to cancel a PayPal subscription using their API. Knowing the SubscriptionId can anyone give me some code example how to do this?

Many thanks.

Anthony
  • 7,210
  • 13
  • 60
  • 70
  • Have you ever received reply other than "*Failure*"/"*Profile ID is invalid*"? As far as I discovered, you can't cancel a subscription created "normally" (without *CreateRecurringPaymentsProfile*) this way. Putting subscription ID there does not do the trick (as for me). – nssmart Mar 21 '11 at 23:00
  • 2
    "A subscription is created via a Website Payments Standard 'Subscribe' button. Before 2009, the subscription profile ID started with S-XXXXXXXX. You are not able to manage these subscriptions via any API calls. After 2009, the subscription profile ID starts with I-XXXXXX. You are able to cancel these subscriptions via the ManageRecurringPaymentsProfileStatus API call." Was having the same problem and just read it by Robert and it works, you can cancel standard website subscription using API. – Usman Zaheer May 04 '12 at 12:01
  • Now is 2012 and my all subscriptions till today start with S- and I am not able to use cancellation method. Maybe someone found a solution? – Tomas Aug 22 '12 at 07:00

2 Answers2

16

Did you manage to find an easy solution ? I'm looking for this as well. Thanks!

Update : After searching, the "ManageRecurringPaymentsProfileStatus" is very easy to use through a simple POST request.

Make sure that your user, password or signature are not visible (in other words, do this on your server and NOT on your client via javascript or html posts).

Below a simple working example in Python. It works and I'm now using it daily.

import urllib
from google.appengine.api import urlfetch

form_fields = {
        "METHOD": "ManageRecurringPaymentsProfileStatus",
        "PROFILEID": "xxx", # put your subscription ID here
        "ACTION": "cancel",
        "USER": "xxx", # Get USER, PWD, and SIGNATURE from your Paypal's account preferences
        "PWD": "xxx",
        "SIGNATURE": "xxx",
        "VERSION": "54.0"
}

api_url = 'https://api-3t.sandbox.paypal.com/nvp' # remove the sandbox part for production

form_data = urllib.urlencode(form_fields)

result = urlfetch.fetch(url=api_url,
                    payload=form_data,
                    method=urlfetch.POST,
                    headers={'Content-Type': 'application/x-www-form-urlencoded'})

The response is a string that looks like this:

TIMESTAMP=2011%2d01%2d28T14%3a47%3a45Z&CORRELATIONID=148ebe1d25566&ACK=Failure&VERSION=54%2e0&BUILD=1704252&L_ERRORCODE0=11552&L_SHORTMESSAGE0=Invalid%20profile%20ID&L_LONGMESSAGE0=The%20profile%20ID%20is%20invalid&L_SEVERITYCODE0=Error

The 'ACK' field indicates 'Failure' or 'Success'.

In answer to comments below, note that it DOES enable me to cancel the subscriptions that have been created through a dynamically created link such as :

<a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_xclick-subscriptions&business=llcpro_1295263400_biz%40jeregle.com&item_name=Abonnement%20mensuel&a3=41.86&t3=M&p3=1&src=1&sra=1&currency_code=EUR&no_note=1&no_shipping=1&lc=FR&custom=xxxxx&notify_url=https%3A%2F%2Fyournotifyurl.com%2Fipn&charset=utf-8&country=FR&a1=0&t1=D&p1=31" target="_blank">Subscribe</a>

Note that I do not use the flag 'modify' at all.

Louis LC
  • 5,454
  • 1
  • 17
  • 13
  • I didn't. I'm still doing it manually. Thanksfully it doesn't happen very often. – Anthony Jan 26 '11 at 09:24
  • Hi Anthony. Found the solution, see my updated post above. Hope it will be useful for you. Cheers. – Louis LC Jan 28 '11 at 15:00
  • 1
    Thanks Louis. I'll try that but can you confirm it works for subscription created manually? See Vitaly's answer below. – Anthony Mar 22 '11 at 08:46
  • Yes, it actually does. I don't know how you create your subscriptions but I have updated my answer above to show the way I'm doing it. – Louis LC May 21 '11 at 12:14
  • If you still have issues cancelling, I'd be interested to know the format of your subscription IDs (e.g. what is their first character in particular). Also make sure to use the version '54.0' when calling ManageRecurringPaymentsProfileStatus. – Louis LC May 21 '11 at 12:39
  • 1
    What subscription ID are you putting into request when you want to cancel subscripton created via Subscribe button? I tried with 'subscr_id" received via IPN (ID is in format I-<12chars>) and it's always invalid. – Xion Aug 26 '11 at 13:32
  • What if I only have a token Id to identify me? I don't have a username, password or signature to identify me – dhalfageme May 27 '15 at 17:19
0

I know this is a really old post, but canceling a subscription is quite simple using the paypal REST API. I'm new to this, but I have been able to figure it out. Here is a method that I use to cancel a subscription. This is written in PHP.

public function cancelSubscription(string $billingID, string $reason) : bool {
    $token = $this->getAccessToken()->access_token; // Authorization
    $url = $this->getCancelURI($billingID); // https://api-m.sandbox.paypal.com/v1/billing/subscriptions/{$billingID}/cancel
    
    $ch = curl_init($url);      
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt( $ch, CURLOPT_POST, 1 );
    curl_setopt( $ch, CURLOPT_POSTFIELDS, "{
        \"reason\":\"{$reason}\"
    }");
    
    $headers = [];
    $headers[] = 'Content-Type: application/json';
    $headers[] = 'Authorization: Bearer ' . $token;
    curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
    
    $result = curl_exec($ch);
    
    if(empty($result)) {
        // Logging results since it runs in background and no output is printed to the browser.
        $fh = fopen('debug_log.php','a+');
        fwrite($fh,PHP_EOL."Result True: {$result}".PHP_EOL);
        fclose($fh);
        return true;
    }
    else {
        // Logging results since it runs in background and no output is printed to the browser.
        $fh = fopen('debug_log.php','a+');
        fwrite($fh,PHP_EOL."Result False: {$result}".PHP_EOL);
        fclose($fh);
        return false;
    }
}

And that is it. I return true or false depending on what is received back and I make db changes per the return value.

Hope this helps

Cavalier
  • 93
  • 9