def set_credit_approved(self, amount): self.amount = amount self.host = PAYMENT_HOST_CREDIT self.type = PAYMENT_TYPE_AUTHORIZATION self.status = TRANSACTION_STATUS_ACTIVE self.approved = True now_val = now() self.date_authorized = now_val self.date_expired = now_val + datetime.timedelta(days=settings.PREAPPROVAL_PERIOD) self.save() pledge_created.send(sender=self, transaction=self)
def process_transaction(self, currency, amount, host=PAYMENT_HOST_NONE, campaign=None, user=None, return_url=None, paymentReason="unglue.it Pledge", pledge_extra=None, donation=False, modification=False): ''' process saves and processes a proposed transaction; decides if the transaction should be processed immediately. currency: a 3-letter currency code, i.e. USD amount: the amount to authorize host: the name of the processing module; if none, send user back to decide! campaign: required campaign object user: optional user object return_url: url to redirect supporter to after a successful transaction paymentReason: a memo line that will show up in the Payer's Amazon (and Paypal?) account modification: whether this authorize call is part of a modification of an existing pledge pledge_extra: extra pledge stuff return value: a tuple of the new transaction object and a re-direct url. If the process fails, the redirect url will be None donation: transaction is a donation ''' # set the expiry date based on the campaign deadline if campaign and campaign.deadline: expiry = campaign.deadline + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN) else: expiry = now() + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN) t = Transaction.create( amount=0, host=host, max_amount=amount, currency=currency, campaign=campaign, user=user, pledge_extra=pledge_extra, donation=donation, ) t.save() # does user have enough credit to transact now? if user.is_authenticated() and user.credit.available >= amount: # YES! return_path = "{0}?{1}".format(reverse('pledge_complete'), urllib.urlencode({'tid': t.id})) return_url = urlparse.urljoin(settings.BASE_URL_SECURE, return_path) if campaign.is_pledge(): success = credit.pledge_transaction(t, user, amount) if success: pledge_created.send(sender=self, transaction=t) else: success = credit.pay_transaction(t, user, t.campaign.user_to_pay, amount) if success: t.amount = amount t.host = PAYMENT_HOST_CREDIT t.execution = EXECUTE_TYPE_INSTANT t.date_executed = now() t.status = TRANSACTION_STATUS_COMPLETE t.save() transaction_charged.send(sender=self, transaction=t) if success: return t, return_url else: # shouldn't happen logger.error('could not use credit for transaction %s' % t.id) # send user to choose payment path return t, reverse('fund', args=[t.id])
def authorize(self, transaction, expiry=None, return_url=None, paymentReason="unglue.it Pledge", modification=False): ''' authorize authorizes a set amount of money to be collected at a later date return_url: url to redirect supporter to after a successful transaction paymentReason: a memo line that will show up in the unglue.it accounting modification: whether this authorize call is part of a modification of an existing pledge return value: a tuple of the new transaction object and a re-direct url. If the process fails, the redirect url will be None ''' if transaction.host == PAYMENT_HOST_NONE: #TODO send user to select a payment processor -- for now, set to a system setting transaction.host = settings.PAYMENT_PROCESSOR # we might want to not allow for a return_url to be passed in but calculated # here because we have immediate access to the Transaction object. if return_url is None: return_path = "{0}?{1}".format( reverse('pledge_complete'), urllib.urlencode({'tid': transaction.id})) return_url = urlparse.urljoin(settings.BASE_URL_SECURE, return_path) p = transaction.get_payment_class().Preapproval( transaction, transaction.max_amount, expiry, return_url=return_url, paymentReason=paymentReason) # Create a response for this envelope = p.envelope() if envelope: r = PaymentResponse.objects.create( api=p.url, correlation_id=p.correlation_id(), timestamp=p.timestamp(), info=p.raw_response, transaction=transaction) if p.success() and not p.error(): transaction.preapproval_key = p.key() transaction.save() # it make sense for the payment processor library to calculate next_url when # user is redirected there. But if no redirection is required, send user # straight on to the return_url url = p.next_url() if url is None: url = return_url logger.info("Authorize Success: " + url if url is not None else '') # modification and initial pledge use different notification templates -- # decide which to send # we need to fire notifications at the first point at which we are sure # that the transaction has successfully completed; triggering notifications # when the transaction is initiated risks sending notifications on transactions # that for whatever reason fail. will need other housekeeping to handle those. # sadly this point is not yet late enough in the process -- needs to be moved # until after we are certain. if not modification: # BUGBUG: # send the notice here for now # this is actually premature since we're only about to send the user off to the payment system to # authorize a charge pledge_created.send(sender=self, transaction=transaction) return transaction, url else: transaction.error = p.error_string() transaction.save() logger.info("Authorize Error: " + p.error_string()) return transaction, None