I ended up just calling the method directly from my app.  Here is a
modified version of the cancel method:

    def process_recurring_cancel(self, data, testing=False):
        """Post one subscription cancellation request
        Expects data to be a dictionary containing the following:

        data['subscription'] = {'id': 123} #(this is the orderitem.id)
        data['orderpayment'] = {'transaction_id': 4535454}

        """
        self.log_extra('Processing arb_cancel for ARB subscription
(satchmo transaction_id): %s', data['orderpayment']['transaction_id'])

        settings = self.settings
        # set up the base dictionary
        if self.is_live():
            conn = settings.ARB_CONNECTION.value
            self.log_extra('Using live recurring charge connection.')
        else:
            conn = settings.ARB_CONNECTION_TEST.value
            self.log_extra('Using test recurring charge connection.')

        shop_config = Config.objects.get_current()

        data['connection'] = conn
        data['config'] = {
            'merchantID' : settings.LOGIN.value,
            'transactionKey' : settings.TRANKEY.value,
            'shop_name' : shop_config.store_name,
        }

        t = 
loader.get_template('checkout/authorizenet/arb_cancel_subscription.xml')
        ctx = Context(data)
        request = t.render(ctx)

        # no need for redacted post in cancel request...

        headers = {'Content-type':'text/xml'}
        conn = urllib2.Request(data['connection'], request, headers)
        try:
            f = urllib2.urlopen(conn)
            all_results = f.read()
        except urllib2.URLError, ue:
            self.log.error("error opening %s\n%s", data['connection'], ue)
            return (False, 'ERROR', _('Could not talk to Authorize.net
gateway'))

        self.log_extra('Authorize response: %s', all_results)

        try:
            response = minidom.parseString(all_results)
            doc = response.documentElement
            reason = doc.getElementsByTagName('code')[0].firstChild.nodeValue
            response_text =
doc.getElementsByTagName('text')[0].firstChild.nodeValue
            result =
doc.getElementsByTagName('resultCode')[0].firstChild.nodeValue
            success = result == "Ok"

            # if result is successful, then set expire_date for the order
            # this means the user will have no active subscriptions as far as
            # satchmo bookeeping is concerned...
            # only allow cancellation if subscription is live....
            # (True, u'I00001', u'Successful.')
            # (True, u'I00002', u'The subscription has already been canceled.')
            success_string = unicode('Successful.')

            if response_text == success_string:
                order =
OrderItem.objects.get(pk=int((data['subscription']['id'])))
                order.expire_date = datetime.date.today()
                order.save()

        except Exception, e:
            self.log.error("Error %s\nCould not parse response: %s",
e, all_results)
            success = False
            reason = "Parse Error"
            response_text = "Could not parse response"

        return success, reason, response_text




Here is a sample session that cancels an active subscription:

from satchmo.payment.modules.authorizenet.processor import PaymentProcessor
from profiles.models import *
from django.contrib.auth.models import User
user = User.objects.all()[6]
prof = user.get_profile()
from satchmo.configuration import config_get_group
authorize_settings = config_get_group('PAYMENT_AUTHORIZENET')
processor = PaymentProcessor(authorize_settings)
data = {}
data['subscription'] = {'id': prof.satchmo_subscription_id()}
data['orderpayment'] = {'transaction_id': prof.satchmo_transaction_id()}
processor.process_recurring_cancel(data)
# Out[12]: (True, u'I00001', u'Successful.')

On Mon, Dec 29, 2008 at 6:53 PM, Peter Skomoroch
<[email protected]> wrote:
> I'm trying to decipher how Satchmo actually triggers a call to the
> processor.process() method, so I can do something similar for an ARB
> "cancel" method.  In our app, a call to
> HttpResponseRedirect('/store/checkout/') kicks off the
> process_recurring_subscription method, but the chain of intermediate
> events in Satchmo after that is a bit hazy for me
>
>    if form.is_valid():
>            contact = request.user.contact_set.all()[0]
>            cart = form.save(contact=contact)
>            request.session['cart'] = cart.id
>            return HttpResponseRedirect('/store/checkout/')
>
>
> I've added the following cancel hooks in
> payment/modules/authorizenet/processor.py, but need to figure out how
> to execute them from our App.  We can lookup the existing subscription
> order within our app and add it to the request.session dictionary,
> that should have the information needed to cancel the subscription.
> Any suggestions on what to other methods to add or where to look in
> Satchmo to hook these to a url?
>
>   def cancel(self, testing=False):
>       """cancel subscription"""
>       # TODO: need to set subscription end_date for the order
> transaction, and ensure that it is
>       # initially set to NULL when placing an order
>       self.log_extra('cancelling recurring payment')
>       recurlist = self.getRecurringChargeData()
>
>       if recurlist:
>           success, reason, response =
> self.process_recurring_cancel(recurlist, testing)
>           if not success:
>               self.log_extra('cancel of recurring payment failed,
> aborting the rest of the module')
>               return (success, reason, response)
>
>       return success, reason, response
>
>
>   def process_recurring_cancel(self, data, testing=False):
>       """Post one subscription cancellation request"""
>       self.log_extra('Processing arb_cancel for subscription: %s',
> data['product'].slug)
>
>       t = 
> loader.get_template('checkout/authorizenet/arb_cancel_subscription.xml')
>       ctx = Context(data)
>       request = t.render(ctx)
>
>       # no need for redacted post in cancel request...
>
>       headers = {'Content-type':'text/xml'}
>       conn = urllib2.Request(data['connection'], request, headers)
>       try:
>           f = urllib2.urlopen(conn)
>           all_results = f.read()
>       except urllib2.URLError, ue:
>           self.log.error("error opening %s\n%s", data['connection'], ue)
>           return (False, 'ERROR', _('Could not talk to Authorize.net 
> gateway'))
>
>       self.log_extra('Authorize response: %s', all_results)
>
>       try:
>           response = minidom.parseString(all_results)
>           doc = response.documentElement
>           reason = doc.getElementsByTagName('code')[0].firstChild.nodeValue
>           response_text =
> doc.getElementsByTagName('text')[0].firstChild.nodeValue
>           result =
> doc.getElementsByTagName('resultCode')[0].firstChild.nodeValue
>           success = result == "Ok"
>       except Exception, e:
>           self.log.error("Error %s\nCould not parse response: %s", e,
> all_results)
>           success = False
>           reason = "Parse Error"
>           response_text = "Could not parse response"
>
>       return success, reason, response_text
>
> XML template:
>
> <?xml version="1.0" encoding="utf-8"?>
> <ARBCancelSubscriptionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
> <merchantAuthentication>
> <name>{{ config.merchantID }}</name>
> <transactionKey>{{ config.transactionKey }}</transactionKey>
> </merchantAuthentication>
> <refId>{{ subscription.id }}</refId>
> <subscriptionId>{{ orderpayment.transaction_id }}</subscriptionId>
> </ARBCancelSubscriptionRequest>
>
>
> On Thu, Dec 18, 2008 at 12:48 PM, Bruce Kroeze <[email protected]> wrote:
>> On Wed, Dec 17, 2008 at 4:38 PM, Pete Skomoroch <[email protected]>
>> wrote:
>>>
>>> Bruce,
>>>
>>> I'd like to take a stab at adding ARB cancel/modify.  Do you see any
>>> issues with the following logic?
>>>
>>> Add processor.cancel() and processor.modify_recurring_charge_amount()
>>> methods to payment/modules/authorizenet/processor.py , which will
>>> access the Authorize API the same fashion as the existing
>>> process_recurring_subscription().
>>
>> Looks good to me, except lets keep with the naming convention.
>>  "processor.process_type_action"
>> So they'd be:
>> processor.process_recurring_cancel
>> processor.process_recurring_modify
>> --
>> Bruce Kroeze
>> http://solidsitesolutions.com
>> Dynamic Designs, Optimized
>>
>> >>
>>
>
>
>
> --
> Peter N. Skomoroch
> [email protected]
> http://www.datawrangling.com
> http://del.icio.us/pskomoroch
>



-- 
Peter N. Skomoroch
[email protected]
http://www.datawrangling.com
http://del.icio.us/pskomoroch

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Satchmo users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/satchmo-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to