Exemplo n.º 1
0
    def _process_recurring_payment(self, agreement: sdk.BillingAgreement,
                                   transaction):
        when_datetime = parse(transaction["time_stamp"])  # type: datetime
        when_local_date = localtime(when_datetime).date()

        payer_name = transaction["payer_name"]
        payer_email = transaction["payer_email"]
        paid_amount = transaction["amount"]["value"]
        net_amount = transaction["net_amount"]["value"]
        fee_amount = str(
            Decimal(-1.0) * Decimal(transaction["fee_amount"]["value"]))
        trans_id = transaction["transaction_id"]
        fam_count = int((float(paid_amount) - 50.00) / 10.00)

        assert transaction["net_amount"]["currency"] == "USD"
        assert transaction["fee_amount"]["currency"] == "USD"
        assert transaction["amount"]["currency"] == "USD"
        assert transaction["time_zone"] == "GMT"
        assert float(paid_amount) >= 50.00

        sale = Sale()
        sale.payment_method = Sale.PAID_BY_PAYPAL
        sale.payer_email = payer_email
        sale.payer_name = payer_name
        sale.sale_date = when_local_date
        sale.total_paid_by_customer = Decimal(
            paid_amount
        )  # The full amount paid by the person, including payment processing fee IF CUSTOMER PAID IT.
        sale.processing_fee = Decimal(fee_amount)
        sale.ctrlid = "{}:{}".format(self.CTRLID_PREFIX, trans_id)
        django_sale = self.upsert(sale)
        sale.id = django_sale['id']

        if django_sale["protected"]:
            # If the sale is protected then all details are also protected.
            # Otherwise there's no way to protect a deletion.
            return

        self._member_and_family(sale, 1)
Exemplo n.º 2
0
    def _process_checkouts(self, checkouts):
        assert len(checkouts) < self.limit
        for checkout in checkouts:

            # Filter out questionable checkouts

            if not checkout['state'].startswith("captured"):
                continue

            # At this point we know we'll be creating an IncomeTransaction (currently called Sale)

            sale = Sale()
            sale.payment_method = Sale.PAID_BY_WEPAY
            sale.payer_email = checkout['payer_email']
            sale.payer_name = checkout['payer_name']
            sale.sale_date = date.fromtimestamp(int(
                checkout['create_time']))  # TODO: This is UTC timezone.
            sale.total_paid_by_customer = Decimal(
                checkout['gross']
            )  # Docs: "The total dollar amount paid by the payer"
            sale.processing_fee = Decimal(checkout['fee']) + Decimal(
                checkout['app_fee'])
            if checkout['fee_payer'] == 'payer':
                sale.fee_payer = Sale.FEE_PAID_BY_CUSTOMER
            else:
                sale.fee_payer = Sale.FEE_PAID_BY_US
            sale.ctrlid = "{}:{}".format(self.CTRLID_PREFIX,
                                         checkout['checkout_id'])
            django_sale = self.upsert(sale)
            sale.id = django_sale['id']

            desc = checkout['short_description']

            if checkout['checkout_id'] in [1877931854, 390559320]:
                # These are membership purchases that were erroneously entered as donations.
                self._process_membership_sale(sale, checkout, 6, 0)
                continue

            if checkout['amount'] == 20 \
             and desc == "Recurring Payment to Donation" \
             and md5(checkout['payer_name'].encode('utf-8')).hexdigest() == "95c53a5e254c1847ad8526b625862294":
                # Dale says that this recurring donation should be treated as a grandfathered membership.
                # I'm checking against md5 of the payer-name so I don't have personal info in source.
                self._process_membership_sale(sale, checkout, 1, 0)
                continue

            months = None
            if desc.startswith("One Month Membership"): months = 1
            elif desc.startswith("Three Month Membership"): months = 3
            elif desc.startswith("Six Month Membership"): months = 6
            elif desc.startswith("Recurring Payment to Dues-Paying Member"):
                months = 1
            elif desc.startswith("Payment to Dues-Paying Member ONE-TIME"):
                months = 1
            if months is not None:
                if desc.endswith("+ 1 family member"): family = 1
                elif desc.endswith("+ 2 family member"): family = 2
                elif desc.endswith("+ 3 family member"): family = 3
                elif desc.endswith("+ 4 family member"): family = 4
                elif desc.endswith("+ 5 family member"): family = 5
                elif desc.endswith("+ 6 family member"): family = 6
                else: family = 0
                self._process_membership_sale(sale, checkout, months, family)
                continue

            if desc in [
                    "Xerocraft KMKR Radio Donation",
                    "Single Maketopolis Ticket Purchase"
            ]:
                # The Maketopolis tickets were for KMKR's musical portion of the event.
                self._process_donation(sale, checkout, ACCT_KMKR_CAMPAIGN)
                continue

            if desc.endswith("Event Payment") \
             or desc.startswith("Recurring Payment to Donation") \
             or desc.startswith("Payment to Donation at"):
                self._process_donation(sale, checkout)
                continue

            print("Didn't recognize: " + desc)
Exemplo n.º 3
0
    def _process_checkouts(self, checkouts):
        assert len(checkouts) < self.limit
        for checkout in checkouts:

            # Filter out questionable checkouts

            if not checkout['state'].startswith("captured"):
                continue

            # At this point we know we'll be creating an IncomeTransaction (currently called Sale)

            sale = Sale()
            sale.payment_method = Sale.PAID_BY_WEPAY
            sale.payer_email = checkout['payer_email']
            sale.payer_name = checkout['payer_name']
            sale.sale_date = date.fromtimestamp(int(checkout['create_time']))  # TODO: This is UTC timezone.
            sale.total_paid_by_customer = Decimal(checkout['gross'])  # Docs: "The total dollar amount paid by the payer"
            sale.processing_fee = Decimal(checkout['fee']) + Decimal(checkout['app_fee'])
            sale.ctrlid = "{}:{}".format(self.CTRLID_PREFIX, checkout['checkout_id'])
            django_sale = self.upsert(sale)
            sale.id = django_sale['id']

            desc = checkout['short_description']

            if checkout['checkout_id'] in [1877931854, 390559320]:
                # These are membership purchases that were erroneously entered as donations.
                self._process_membership_sale(sale, checkout, 6, 0)
                continue

            if checkout['amount'] == 20 \
             and desc == "Recurring Payment to Donation" \
             and md5(checkout['payer_name'].encode('utf-8')).hexdigest() == "95c53a5e254c1847ad8526b625862294":
                # Dale says that this recurring donation should be treated as a grandfathered membership.
                # I'm checking against md5 of the payer-name so I don't have personal info in source.
                self._process_membership_sale(sale, checkout, 1, 0)
                continue

            months = None
            if desc.startswith("One Month Membership"): months = 1
            elif desc.startswith("Three Month Membership"): months = 3
            elif desc.startswith("Six Month Membership"): months = 6
            elif desc.startswith("Recurring Payment to Dues-Paying Member"): months = 1
            elif desc.startswith("Payment to Dues-Paying Member ONE-TIME"): months = 1
            if months is not None:
                if desc.endswith("+ 1 family member"): family = 1
                elif desc.endswith("+ 2 family member"): family = 2
                elif desc.endswith("+ 3 family member"): family = 3
                elif desc.endswith("+ 4 family member"): family = 4
                elif desc.endswith("+ 5 family member"): family = 5
                elif desc.endswith("+ 6 family member"): family = 6
                else: family = 0
                self._process_membership_sale(sale, checkout, months, family)
                continue

            if desc.endswith("Event Payment") \
             or desc.startswith("Recurring Payment to Donation") \
             or desc.startswith("Payment to Donation at"):
                self._process_donation(sale, checkout)
                continue

            print("Didn't recognize: "+desc)
Exemplo n.º 4
0
    def _process_payment(self, payment: sdk.Payment):
        payment_id = payment['id']
        if payment_id in self.PAYMENTS_TO_IGNORE:
            return
        state = payment['state']  # e.g. 'approved'
        when_datetime = parse(payment['create_time'])  # type: datetime
        when_local_date = localtime(when_datetime).date()
        if 'payer' not in payment:
            print(payment)
            return
        if 'payer_info' not in payment['payer']:
            print(payment)
            return
        who_fname = payment['payer']['payer_info']['first_name']
        who_lname = payment['payer']['payer_info']['last_name']
        try:
            who_email = payment['payer']['payer_info']['email']
        except:
            who_email = ""

        assert len(
            payment['transactions']
        ) == 1, "Code can't yet deal with multiple transactions payment."
        transaction = payment['transactions'][0]
        payment_amount = transaction['amount']['total']
        if 'custom' in transaction:  # Xerocraft.org puts an indication of what was paid for in "custom"
            what = transaction['custom']
        else:
            what = None

        resources = transaction['related_resources']
        sale_amt = None
        refund_amt = None
        if len(resources) == 0:
            # This has only been observed in a test transaction generated by Kyle
            print("K", end="")
            return
        for resource in resources:
            if 'sale' in resource:
                sale = resource['sale']
                if sale_amt is not None:
                    print(
                        "WARNING (not handled): Multiple sale resources in sale to "
                        + who_email + " on " + str(when_local_date))
                sale_amt = float(sale['amount']['total'])
                pay_mode = sale['payment_mode']  # e.g. 'INSTANT_TRANSFER'
                trans_fee = float(sale['transaction_fee']['value'])
            if 'refund' in resource:
                refund = resource['refund']
                if refund['state'] is "failed":
                    continue
                if refund_amt is not None:
                    print(
                        "WARNING (not handled): Multiple refunds in sale to " +
                        who_email + " on " + str(when_local_date))
                refund_amt = float(refund['amount']['total'])
            if sale_amt is not None and refund_amt is not None:
                # NOTE: Refunds will require manual processing. Adjusted transactions should be marked "protected".
                if sale_amt == refund_amt:
                    print("R", end="")
                    return
                else:
                    print(
                        "Code doesn't yet deal with partial refunds. Sale was to "
                        + who_email + " on " + str(when_local_date))
                    return

        sale = Sale()
        sale.payment_method = Sale.PAID_BY_PAYPAL
        sale.payer_email = who_email
        sale.payer_name = "{} {}".format(who_fname, who_lname)
        sale.sale_date = when_local_date
        sale.total_paid_by_customer = Decimal(
            sale_amt
        )  # The full amount paid by the person, including payment processing fee IF CUSTOMER PAID IT.
        sale.processing_fee = Decimal(trans_fee)
        sale.ctrlid = "{}:{}".format(self.CTRLID_PREFIX, payment_id)
        django_sale = self.upsert(sale)
        sale.id = django_sale['id']

        if django_sale["protected"] == True:
            # If the sale is protected then all details are also protected.
            # Otherwise there's no way to protect a deletion.
            return

        if what is None:
            self._process_unknown_item(sale)
        elif what.startswith("DON_"):
            self._process_donation_item(sale, what)
        elif what.startswith("MSHIP_"):
            self._process_non_recurring_membership_item(sale, what)
        else:
            print("Unkown item: " + what)