def __init__(self, transaction=None): self.transaction = transaction amount = transaction.amount # make sure transaction hasn't already been executed if transaction.status == TRANSACTION_STATUS_COMPLETE: return used = transaction.user.credit.use_pledge(amount) if used: user_to_pay = transaction.campaign.user_to_pay credited = user_to_pay.credit.add_to_balance(amount, notify=False) transaction.status = TRANSACTION_STATUS_COMPLETE transaction.date_payment = datetime.now() transaction.save() # fire signal for sucessful transaction transaction_charged.send(sender=self, transaction=transaction)
def __init__(self, transaction=None): self.transaction = transaction # make sure transaction hasn't already been executed if transaction.status == TRANSACTION_STATUS_COMPLETE: return # make sure we are dealing with a stripe transaction if transaction.host <> PAYMENT_HOST_STRIPE: raise StripelibError("transaction.host {0} is not the expected {1}".format(transaction.host, PAYMENT_HOST_STRIPE)) sc = StripeClient() # look first for transaction.user.profile.account.account_id try: customer_id = transaction.user.profile.account.account_id except: customer_id = transaction.preapproval_key if customer_id is not None: try: # useful things to put in description: transaction.id, transaction.user.id, customer_id, transaction.amount charge = sc.create_charge(transaction.amount, customer=customer_id, description=json.dumps({"t.id":transaction.id, "email":transaction.user.email if transaction.user else transaction.receipt, "cus.id":customer_id, "tc.id": transaction.campaign.id if transaction.campaign else '0', "amount": float(transaction.amount)})) except stripe.StripeError as e: # what to record in terms of errors? (error log?) # use PaymentResponse to store error r = PaymentResponse.objects.create(api="stripelib.Execute", correlation_id=None, timestamp=now(), info=e.message, status=TRANSACTION_STATUS_ERROR, transaction=transaction) transaction.status = TRANSACTION_STATUS_ERROR self.errorMessage = e.message # manager puts this on transaction transaction.save() # fire off the fact that transaction failed -- should actually do so only if not a transient error # if card_declined or expired card, ask user to update account if isinstance(e, stripe.CardError) and e.code in ('card_declined', 'expired_card', 'incorrect_number', 'processing_error'): transaction_failed.send(sender=self, transaction=transaction) # otherwise, report exception to us else: logger.exception("transaction id {0}, exception: {1}".format(transaction.id, e.message)) # raise StripelibError(e.message, e) else: self.charge = charge transaction.status = TRANSACTION_STATUS_COMPLETE transaction.pay_key = charge.id transaction.date_payment = now() transaction.save() # fire signal for sucessful transaction transaction_charged.send(sender=self, transaction=transaction) else: # nothing to charge raise StripelibError("No customer id available to charge for transaction {0}".format(transaction.id), None)
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])