예제 #1
0
 def test_purchase_should_return_invalid_sandbox_card_error(self):
     data = {
         'custom': '',
         'first_name': '',
         'last_name': '',
         'address_1': '',
         'address_2': '',
         'city': '',
         'state': '',
         'zip': '10101',
         'card_number': '5256486068715680',
         'cvv': '111',
         'expiry_month': '05',
         'expiry_year': '2014',
     }
     token = test_helper.default_payment_method(data).payment_method_token
     purchase = Processor.purchase(token, 1.00)
     self.assertIn(
         {
             'context':
             'system.general',
             'key':
             'default',
             'subclass':
             'error',
             'text':
             'Invalid Sandbox Card Number. For more information, see: https://samurai.feefighters.com/developers/sandbox'
         }, purchase.error_messages)
 def test_cvv_should_return_processor_cvv_result_code_N(self):
     token = test_helper.default_payment_method({'cvv':'222'}).payment_method_token
     purchase = Processor.purchase(token,
                                   1.00,
                                   billing_reference=self.rand)
     self.assertTrue(purchase.success)
     self.assertEqual(purchase.processor_response['cvv_result_code'], 'N')
예제 #3
0
 def test_cvv_should_return_processor_cvv_result_code_N(self):
     token = test_helper.default_payment_method({
         'cvv': '222'
     }).payment_method_token
     purchase = Processor.purchase(token, 1.00, billing_reference=self.rand)
     self.assertTrue(purchase.success)
     self.assertEqual(purchase.processor_response['cvv_result_code'], 'N')
 def test_should_return_processor_avs_result_code_N(self):
     token = test_helper.default_payment_method({'address_1':'123 Main St',
                                                'address_2':'',
                                                'zip':'60610'}).payment_method_token
     purchase = Processor.purchase(token,
                                   1.00,
                                   billing_reference=self.rand)
     self.assertTrue(purchase.success)
     self.assertEqual(purchase.processor_response['avs_result_code'], 'N')
예제 #5
0
 def test_should_return_processor_avs_result_code_N(self):
     token = test_helper.default_payment_method({
         'address_1': '123 Main St',
         'address_2': '',
         'zip': '60610'
     }).payment_method_token
     purchase = Processor.purchase(token, 1.00, billing_reference=self.rand)
     self.assertTrue(purchase.success)
     self.assertEqual(purchase.processor_response['avs_result_code'], 'N')
 def test_purchase_should_return_input_amount_invalid(self):
     token = self.pm.payment_method_token
     purchase = Processor.purchase(token,
                                   1.10,
                                   billing_reference=self.rand)
     self.assertFalse(purchase.success)
     err = {'context': 'input.amount', 'key': 'invalid', 'subclass': 'error'}
     self.assertIn(err, purchase.error_messages)
     self.assertIn('The transaction amount was invalid.', purchase.errors['input.amount'])
 def test_purchase_should_return_processor_transaction_declined(self):
     token = self.pm.payment_method_token
     purchase = Processor.purchase(token,
                                   1.02,
                                   billing_reference=self.rand)
     self.assertFalse(purchase.success)
     err = {'context': 'processor.transaction', 'key': 'declined', 'subclass': 'error'}
     self.assertIn(err, purchase.error_messages)
     self.assertIn('The card was declined.' , purchase.errors['processor.transaction'])
def purchase(request):
    token = request.GET.get('payment_method_token', None)
    trans = Processor.purchase(token, 10)
    if trans.errors:
        errors = parse_error(trans.errors)
        for err in errors:
            messages.error(request, err, fail_silently=True)
        return redirect('/transparent_redirect/payment_form')
    else:
        messages.success(request, 'Purchase Successful.', fail_silently=True)
        return render_to_response('/transparent_redirect/receipt.html')
예제 #9
0
def purchase(request):
    if request.method == 'POST':
        token = request.POST.get('payment_method_token', None)
        trans = Processor.purchase(token, 10)
        if trans.errors:
            success=False
        else:
            success=True
        return_data = simplejson.dumps({'transaction':{'success':success}})
        return HttpResponse(return_data)
    else:
        return redirect('/samurai_js/payment_form')
예제 #10
0
 def capture(self, amount, credit_card=None, billing_info=None, shipping_info=None):
     # set up the card for charging, obviously
     card_token = self.charge_setup(credit_card, billing_info)
     # start the timer
     start = time.time()
     # send it over for processing
     response = Processor.purchase(card_token, amount)
     # measure time
     end = time.time() # done timing it
     response_time = '%0.2f' % (end-start)
     # return parsed response
     return self.parse(response, response_time)
예제 #11
0
 def purchase(self, money, credit_card):
     if not self.validate_card(credit_card):
         raise InvalidCard("Invalid Card")
     try:
         from samurai.payment_method import PaymentMethod
         from samurai.processor import Processor
         pm = PaymentMethod.create(credit_card.number, credit_card.verification_value,
                                   credit_card.month, credit_card.year)
         payment_method_token = pm.payment_method_token
         response = Processor.purchase(payment_method_token, money)
     except Exception, error:
         return {'status': 'FAILURE', 'response': error}
예제 #12
0
 def capture(self, amount, credit_card=None, billing_info=None, shipping_info=None):
     # set up the card for charging, obviously
     card_token = self.charge_setup(credit_card, billing_info)
     # start the timer
     start = time.time()
     # send it over for processing
     response = Processor.purchase(card_token, amount)
     # measure time
     end = time.time() # done timing it
     response_time = '%0.2f' % (end-start)
     # return parsed response
     return self.parse(response, response_time)
예제 #13
0
 def test_purchase_should_return_processor_transaction_declined(self):
     token = self.pm.payment_method_token
     purchase = Processor.purchase(token, 1.02, billing_reference=self.rand)
     self.assertFalse(purchase.success)
     err = {
         'context': 'processor.transaction',
         'key': 'declined',
         'subclass': 'error'
     }
     self.assertIn(err, purchase.error_messages)
     self.assertIn('The card was declined.',
                   purchase.errors['processor.transaction'])
예제 #14
0
 def test_purchase_should_return_input_amount_invalid(self):
     token = self.pm.payment_method_token
     purchase = Processor.purchase(token, 1.10, billing_reference=self.rand)
     self.assertFalse(purchase.success)
     err = {
         'context': 'input.amount',
         'key': 'invalid',
         'subclass': 'error'
     }
     self.assertIn(err, purchase.error_messages)
     self.assertIn('The transaction amount was invalid.',
                   purchase.errors['input.amount'])
예제 #15
0
 def purchase(self, money, credit_card):
     if not self.validate_card(credit_card):
         raise InvalidCard("Invalid Card")
     try:
         from samurai.payment_method import PaymentMethod
         from samurai.processor import Processor
         pm = PaymentMethod.create(credit_card.number,
                                   credit_card.verification_value,
                                   credit_card.month, credit_card.year)
         payment_method_token = pm.payment_method_token
         response = Processor.purchase(payment_method_token, money)
     except Exception, error:
         return {'status': 'FAILURE', 'response': error}
예제 #16
0
 def purchase(self, money, credit_card):
     # Cases where token is directly sent for e.g. from Samurai.js
     payment_method_token = credit_card
     if isinstance(credit_card, CreditCard):
         if not self.validate_card(credit_card):
             raise InvalidCard("Invalid Card")
         pm = PaymentMethod.create(credit_card.number, credit_card.verification_value,
                                   credit_card.month, credit_card.year)
         payment_method_token = pm.payment_method_token
     response = Processor.purchase(payment_method_token, money)
     if response.errors:
         return {'status': 'FAILURE', 'response': response}
     return {'status': 'SUCCESS', 'response': response}
예제 #17
0
def purchase(request):
    if request.method == "POST":
        data = request.POST
        token = PaymentMethod.create(data.get('card_number'), data.get('cvv'), data.get('expiry_month'),
                                     data.get('expiry_year'), first_name=data.get('first_name'),
                                     last_name=data.get('last_name'))
        trans = Processor.purchase(token.payment_method_token, 10)
        if trans.errors:
            errors = parse_error(trans.errors)
            for err in errors:
                messages.error(request, err, fail_silently=True)
            return redirect('/server_to_server/payment_form')
        else:
            messages.success(request, 'Purchase Successful.', fail_silently=True)
            return render_to_response('/server_to_server/receipt.html')
    else:
        return redirect('/server_to_server/payment_form')
 def test_purchase_should_be_successful(self):
     options = {'description':'description',
                'descriptor_name':'descriptor_name',
                'descriptor_phone':'descriptor_phone',
                'custom':'custom',
                'billing_reference':'ABC123%s' % self.rand,
                'customer_reference':'Customer (123)'}
     token = self.pm.payment_method_token
     purchase = Processor.purchase(token, 10.0, None, **options)
     self.assertTrue(purchase.success)
     self.assertEquals(purchase.error_messages, [])
     self.assertEqual(purchase.description, 'description')
     self.assertEqual(purchase.descriptor_name, 'descriptor_name')
     self.assertEqual(purchase.descriptor_phone, 'descriptor_phone')
     self.assertEqual(purchase.custom, 'custom')
     self.assertEqual(purchase.billing_reference, 'ABC123%s' % self.rand)
     self.assertEqual(purchase.customer_reference, 'Customer (123)')
 def test_purchase_should_return_invalid_sandbox_card_error(self):
     data = {
         'custom' : '',
         'first_name' : '',
         'last_name' : '',
         'address_1' : '',
         'address_2' : '',
         'city' : '',
         'state' : '',
         'zip' : '10101',
         'card_number' : '5256486068715680',
         'cvv' : '111',
         'expiry_month' : '05',
         'expiry_year' : '2014',
       }
     token = test_helper.default_payment_method(data).payment_method_token
     purchase = Processor.purchase(token, 1.00)
     self.assertIn({'context': 'system.general', 'key': 'default', 'subclass': 'error', 'text': 'Invalid Sandbox Card Number. For more information, see: https://samurai.feefighters.com/developers/sandbox'}, purchase.error_messages)
예제 #20
0
 def test_purchase_should_be_successful(self):
     options = {
         'description': 'description',
         'descriptor_name': 'descriptor_name',
         'descriptor_phone': 'descriptor_phone',
         'custom': 'custom',
         'billing_reference': 'ABC123%s' % self.rand,
         'customer_reference': 'Customer (123)'
     }
     token = self.pm.payment_method_token
     purchase = Processor.purchase(token, 10.0, None, **options)
     self.assertTrue(purchase.success)
     self.assertEquals(purchase.error_messages, [])
     self.assertEqual(purchase.description, 'description')
     self.assertEqual(purchase.descriptor_name, 'descriptor_name')
     self.assertEqual(purchase.descriptor_phone, 'descriptor_phone')
     self.assertEqual(purchase.custom, 'custom')
     self.assertEqual(purchase.billing_reference, 'ABC123%s' % self.rand)
     self.assertEqual(purchase.customer_reference, 'Customer (123)')
 def test_purchase_should_return_payment_method_errors_on_blank_pm(self):
     data = {
         'custom' : '',
         'first_name' : '',
         'last_name' : '',
         'address_1' : '',
         'address_2' : '',
         'city' : '',
         'state' : '',
         'zip' : '',
         'card_number' : '',
         'cvv' : '',
         'expiry_month' : '05',
         'expiry_year' : '2014',
       }
     token = test_helper.default_payment_method(data).payment_method_token
     purchase = Processor.purchase(token, 1.00)
     self.assertFalse(purchase.success)
     self.assertIn({'context': 'input.card_number', 'key': 'not_numeric', 'subclass': 'error'}, purchase.error_messages)
     self.assertIn({'context': 'input.card_number', 'key': 'too_short', 'subclass': 'error'}, purchase.error_messages)
     self.assertIn({'context': 'input.card_number', 'key': 'is_blank', 'subclass': 'error'}, purchase.error_messages)
예제 #22
0
 def test_purchase_should_return_payment_method_errors_on_blank_pm(self):
     data = {
         'custom': '',
         'first_name': '',
         'last_name': '',
         'address_1': '',
         'address_2': '',
         'city': '',
         'state': '',
         'zip': '',
         'card_number': '',
         'cvv': '',
         'expiry_month': '05',
         'expiry_year': '2014',
     }
     token = test_helper.default_payment_method(data).payment_method_token
     purchase = Processor.purchase(token, 1.00)
     self.assertFalse(purchase.success)
     self.assertIn(
         {
             'context': 'input.card_number',
             'key': 'not_numeric',
             'subclass': 'error'
         }, purchase.error_messages)
     self.assertIn(
         {
             'context': 'input.card_number',
             'key': 'too_short',
             'subclass': 'error'
         }, purchase.error_messages)
     self.assertIn(
         {
             'context': 'input.card_number',
             'key': 'is_blank',
             'subclass': 'error'
         }, purchase.error_messages)
 def test_purchase_failure(self):
     token = self.pm.payment_method_token
     trans = Processor.purchase(token, 10.02)
     errors = [{'context': 'processor.transaction', 'key': 'declined', 'subclass': 'error'}]
     self.assertEquals(trans.errors, errors)
예제 #24
0
def charge(participant_id, pmt, amount):
    """Given two unicodes and a Decimal, return a boolean indicating success.

    This is the only place where we actually charge credit cards. Amount should
    be the nominal amount. We compute Gittip's fee in this function and add
    it to amount.

    """
    typecheck( pmt, (unicode, None)
             , participant_id, unicode
             , amount, decimal.Decimal
              )

    if pmt is None:
        STATS = """\

            UPDATE paydays 
               SET npmt_missing = npmt_missing + 1
             WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz
         RETURNING id
        
        """
        assert_one_payday(db.fetchone(STATS))
        return False 


    # We have a purported payment method token. Try to use it.
    # ========================================================

    charge_amount = (amount + FEE[0]) * FEE[1]
    charge_amount = charge_amount.quantize(FEE[0], rounding=decimal.ROUND_UP)
    fee = charge_amount - amount
    log("Charging %s $%s + $%s fee = $%s." 
       % (participant_id, amount, fee, charge_amount))
    transaction = Processor.purchase(pmt, charge_amount, custom=participant_id)

    # XXX If the power goes out at this point then Postgres will be out of sync
    # with Samurai. We'll have to resolve that manually be reviewing the
    # Samurai transaction log and modifying Postgres accordingly.

    with db.get_connection() as conn:
        cur = conn.cursor()

        if transaction.errors:
            last_bill_result = json.dumps(transaction.errors)
            amount = decimal.Decimal('0.00')

            STATS = """\

                UPDATE paydays 
                   SET npmt_failing = npmt_failing + 1
                 WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz
             RETURNING id
            
            """
            cur.execute(STATS)
            assert_one_payday(cur.fetchone())

        else:
            last_bill_result = ''

            EXCHANGE = """\

            INSERT INTO exchanges
                   (amount, fee, participant_id)
            VALUES (%s, %s, %s)

            """
            cur.execute(EXCHANGE, (amount, fee, participant_id))

            STATS = """\

                UPDATE paydays 
                   SET nexchanges = nexchanges + 1
                     , exchange_volume = exchange_volume + %s
                     , exchange_fees_volume = exchange_fees_volume + %s
                 WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz
             RETURNING id
            
            """
            cur.execute(STATS, (charge_amount, fee))
            assert_one_payday(cur.fetchone())


        # Update the participant's balance.
        # =================================
        # Credit card charges go immediately to balance, not to pending.

        RESULT = """\

        UPDATE participants
           SET last_bill_result=%s 
             , balance=(balance + %s)
         WHERE id=%s

        """
        cur.execute(RESULT, (last_bill_result, amount, participant_id))

        conn.commit()

    return not bool(last_bill_result)  # True indicates success
예제 #25
0
 def setUp(self):
     self.pm = test_helper.default_payment_method()
     self.rand = randint(100, 999)
     self.auth = Processor.authorize(self.pm.payment_method_token, 100.0)
     self.purchase = Processor.purchase(self.pm.payment_method_token, 100.0)
 def test_purchase(self):
     token = self.pm.payment_method_token
     trans = Processor.purchase(token, 10.0)
     self.assertTrue(trans.success)
     self.assertEquals(trans.errors, [])
 def test_purchase_partial_reverse(self):
     purchase = Processor.purchase(self.pm.payment_method_token, 10.0)      
     trans = purchase.reverse(5.0)
     self.assertTrue(trans.success)
     self.assertEquals(trans.errors, [])
     self.assertEquals(trans.amount, '5.0')
 def setUp(self):
     self.pm = test_helper.default_payment_method()
     self.rand = randint(100, 999)
     self.auth = Processor.authorize(self.pm.payment_method_token, 100.0)
     self.purchase = Processor.purchase(self.pm.payment_method_token, 100.0)
예제 #29
0
def charge(participant_id, pmt, amount):
    """Given two unicodes and a Decimal, return a boolean indicating success.

    This is the only place where we actually charge credit cards. Amount should
    be the nominal amount. We compute Gittip's fee in this function and add
    it to amount.

    """
    typecheck(pmt, (unicode, None), participant_id, unicode, amount,
              decimal.Decimal)

    if pmt is None:
        STATS = """\

            UPDATE paydays 
               SET npmt_missing = npmt_missing + 1
             WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz
         RETURNING id
        
        """
        assert_one_payday(db.fetchone(STATS))
        return False

    # We have a purported payment method token. Try to use it.
    # ========================================================

    charge_amount = (amount + FEE[0]) * FEE[1]
    charge_amount = charge_amount.quantize(FEE[0], rounding=decimal.ROUND_UP)
    fee = charge_amount - amount
    log("Charging %s $%s + $%s fee = $%s." %
        (participant_id, amount, fee, charge_amount))
    transaction = Processor.purchase(pmt, charge_amount, custom=participant_id)

    # XXX If the power goes out at this point then Postgres will be out of sync
    # with Samurai. We'll have to resolve that manually be reviewing the
    # Samurai transaction log and modifying Postgres accordingly.

    with db.get_connection() as conn:
        cur = conn.cursor()

        if transaction.errors:
            last_bill_result = json.dumps(transaction.errors)
            amount = decimal.Decimal('0.00')

            STATS = """\

                UPDATE paydays 
                   SET npmt_failing = npmt_failing + 1
                 WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz
             RETURNING id
            
            """
            cur.execute(STATS)
            assert_one_payday(cur.fetchone())

        else:
            last_bill_result = ''

            EXCHANGE = """\

            INSERT INTO exchanges
                   (amount, fee, participant_id)
            VALUES (%s, %s, %s)

            """
            cur.execute(EXCHANGE, (amount, fee, participant_id))

            STATS = """\

                UPDATE paydays 
                   SET nexchanges = nexchanges + 1
                     , exchange_volume = exchange_volume + %s
                     , exchange_fees_volume = exchange_fees_volume + %s
                 WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz
             RETURNING id
            
            """
            cur.execute(STATS, (charge_amount, fee))
            assert_one_payday(cur.fetchone())

        # Update the participant's balance.
        # =================================
        # Credit card charges go immediately to balance, not to pending.

        RESULT = """\

        UPDATE participants
           SET last_bill_result=%s 
             , balance=(balance + %s)
         WHERE id=%s

        """
        cur.execute(RESULT, (last_bill_result, amount, participant_id))

        conn.commit()

    return not bool(last_bill_result)  # True indicates success
 def test_purchase_partial_reverse(self):
     purchase = Processor.purchase(self.pm.payment_method_token, 10.0)
     trans = purchase.reverse(5.0)
     self.assertTrue(trans.success)
     self.assertEquals(trans.errors, [])
     self.assertEquals(trans.amount, '5.0')