def test_Disputes_ContestDispute(self): self.refreshClientDisputes() notContestedDispute = None for d in self._clientDisputes: if ((d.Status == DisputeStatus.PENDING_CLIENT_ACTION or d.Status == DisputeStatus.REOPENED_PENDING_CLIENT_ACTION) and (d.DisputeType == DisputeType.CONTESTABLE or d.DisputeType == DisputeType.RETRIEVAL)): notContestedDispute = d break self.assertIsNotNone(notContestedDispute, 'Cannot test contesting dispute because there\'s no dispute that can be contested in the disputes list.') result = None contestedFunds = None if (notContestedDispute.Status == DisputeStatus.PENDING_CLIENT_ACTION): contestedFunds = Money() contestedFunds.Amount = 100 contestedFunds.Currency = 'EUR' result = self.sdk.disputes.ContestDispute(contestedFunds, notContestedDispute.Id) self.assertIsNotNone(result) self.assertEqual(result.Id, notContestedDispute.Id)
def getJohnsPayInCardDirect(self, wallet=None): """Creates Pay-In Card Direct object return PayIn """ if wallet == None: wallet = self.getJohnsWallet() cardRegistration = CardRegistration() cardRegistration.UserId = wallet.Owners[0] cardRegistration.Currency = 'EUR' cardRegistration = self.sdk.cardRegistrations.Create(cardRegistration) cardRegistration.RegistrationData = self.getPaylineCorrectRegistartionData( cardRegistration) cardRegistration = self.sdk.cardRegistrations.Update(cardRegistration) card = self.sdk.cards.Get(cardRegistration.CardId) # create pay-in CARD DIRECT payIn = PayIn() payIn.CreditedWalletId = wallet.Id payIn.AuthorId = wallet.Owners[0] payIn.DebitedFunds = Money() payIn.DebitedFunds.Amount = 10000 payIn.DebitedFunds.Currency = 'EUR' payIn.Fees = Money() payIn.Fees.Amount = 0 payIn.Fees.Currency = 'EUR' # payment type as CARD payIn.PaymentDetails = PayInPaymentDetailsCard() payIn.PaymentDetails.CardType = card.CardType # execution type as DIRECT payIn.ExecutionDetails = PayInExecutionDetailsDirect() payIn.ExecutionDetails.CardId = card.Id payIn.ExecutionDetails.SecureModeReturnURL = 'http://test.com' return self.sdk.payIns.Create(payIn)
def payin_bank_wire(db, participant, debit_amount): """Prepare to receive a bank wire payin. The amount should be how much the user intends to send, not how much will arrive in the wallet. """ route = ExchangeRoute.from_network(participant, 'mango-bw') if not route: route = ExchangeRoute.insert(participant, 'mango-bw', 'x') amount, fee, vat = skim_amount(debit_amount, FEE_PAYIN_BANK_WIRE) e_id = record_exchange(db, route, amount, fee, vat, participant, 'pre') payin = PayIn() payin.AuthorId = participant.mangopay_user_id if not participant.mangopay_wallet_id: create_wallet(db, participant) payin.CreditedWalletId = participant.mangopay_wallet_id payin.ExecutionDetails = PayInExecutionDetailsDirect() payin.PaymentDetails = PayInPaymentDetailsBankWire( DeclaredDebitedFunds=Money(int(debit_amount * 100), 'EUR'), DeclaredFees=Money(int(fee * 100), 'EUR'), ) payin.Tag = str(e_id) try: test_hook() payin = mangoapi.payIns.Create(payin) except Exception as e: error = repr_exception(e) return None, record_exchange_result(db, e_id, 'failed', error, participant) e = record_exchange_result(db, e_id, payin.Status.lower(), repr_error(payin), participant) return payin, e
def getJohnsTransfer(self, walletWithMoney=None, wallet=None): """Creates Pay-Out Bank Wire object""" if walletWithMoney == None: walletWithMoney = self.getJohnsWalletWithMoney() if wallet == None: wallet = Wallet() wallet.Owners = [walletWithMoney.Owners[0]] wallet.Currency = 'EUR' wallet.Description = 'WALLET IN EUR' wallet = self.sdk.wallets.Create(wallet) transfer = Transfer() transfer.Tag = 'DefaultTag' transfer.AuthorId = walletWithMoney.Owners[0] transfer.CreditedUserId = walletWithMoney.Owners[0] transfer.DebitedFunds = Money() transfer.DebitedFunds.Currency = 'EUR' transfer.DebitedFunds.Amount = 100 transfer.Fees = Money() transfer.Fees.Currency = 'EUR' transfer.Fees.Amount = 0 transfer.DebitedWalletId = walletWithMoney.Id transfer.CreditedWalletId = wallet.Id return self.sdk.transfers.Create(transfer)
def transfer(db, tipper, tippee, amount, context, **kw): t_id = db.one( """ INSERT INTO transfers (tipper, tippee, amount, context, team, status) VALUES (%s, %s, %s, %s, %s, 'pre') RETURNING id """, (tipper, tippee, amount, context, kw.get('team'))) get = lambda id, col: db.one( "SELECT {0} FROM participants WHERE id = %s".format(col), (id, )) tr = Transfer() tr.AuthorId = kw.get('tipper_mango_id') or get(tipper, 'mangopay_user_id') tr.CreditedUserId = kw.get('tippee_mango_id') or get( tippee, 'mangopay_user_id') tr.CreditedWalletID = kw.get('tippee_wallet_id') or get( tippee, 'mangopay_wallet_id') if not tr.CreditedWalletID: tr.CreditedWalletID = create_wallet(db, Participant.from_id(tippee)) tr.DebitedFunds = Money(int(amount * 100), 'EUR') tr.DebitedWalletID = kw.get('tipper_wallet_id') or get( tipper, 'mangopay_wallet_id') tr.Fees = Money(0, 'EUR') tr.Tag = str(t_id) tr = mangoapi.transfers.Create(tr) return record_transfer_result(db, t_id, tr)
def payout(db, participant, amount): if participant.is_suspicious: raise UserIsSuspicious route = ExchangeRoute.from_network(participant, 'mango-ba') assert route ba = mangoapi.users.GetBankAccount(participant.mangopay_user_id, route.address) # Do final calculations credit_amount, fee = skim_credit(amount, ba) if credit_amount <= 0 or fee / credit_amount > 0.1: raise TransactionFeeTooHigh # Try to dance with MangoPay e_id = record_exchange(db, route, -credit_amount, fee, participant, 'pre') payout = PayOut() payout.AuthorId = participant.mangopay_user_id payout.DebitedFunds = Money(int(credit_amount * 100), 'EUR') payout.DebitedWalletId = participant.mangopay_wallet_id payout.Fees = Money(int(fee * 100), 'EUR') payout.MeanOfPaymentDetails = PayOutPaymentDetailsBankWire( BankAccountId=route.address, BankWireRef=str(e_id), ) payout.Tag = str(e_id) try: test_hook() mangoapi.payOuts.Create(payout) return record_exchange_result(db, e_id, 'created', None, participant) except Exception as e: error = repr_exception(e) return record_exchange_result(db, e_id, 'failed', error, participant)
def test_Disputes_GetSettlementTransfer(self): self.refreshClientDisputes() dispute = None for d in self._clientDisputes: if (d.Status == DisputeStatus.CLOSED and d.DisputeType == DisputeType.NOT_CONTESTABLE): dispute = d break self.assertIsNotNone( dispute, 'Cannot test getting settlement transfer because there\'s no closed and not contestable disputes in the disputes list.' ) repudiationId = self.sdk.disputes.GetTransactions( dispute.Id, Pagination(1, 1))[0].Id repudiation = self.sdk.disputes.GetRepudiation(repudiationId) post = Settlement() post.AuthorId = repudiation.AuthorId post.DebitedFunds = Money(1, 'EUR') post.Fees = Money(0, 'EUR') transfer = self.sdk.disputes.CreateSettlementTransfer( post, repudiationId) self.assertIsNotNone(transfer) result = self.sdk.disputes.GetSettlementTransfer(transfer.Id) self.assertIsNotNone(result) self.assertIsNotNone(result.RepudiationId) self.assertEqual(result.RepudiationId, repudiation.Id)
def test_Disputes_ContestDispute(self): self.refreshClientDisputes() notContestedDispute = None for d in self._clientDisputes: if ((d.Status == DisputeStatus.PENDING_CLIENT_ACTION or d.Status == DisputeStatus.REOPENED_PENDING_CLIENT_ACTION) and (d.DisputeType == DisputeType.CONTESTABLE or d.DisputeType == DisputeType.RETRIEVAL)): notContestedDispute = d break self.assertIsNotNone( notContestedDispute, 'Cannot test contesting dispute because there\'s no dispute that can be contested in the disputes list.' ) result = None contestedFunds = None if (notContestedDispute.Status == DisputeStatus.PENDING_CLIENT_ACTION): contestedFunds = Money() contestedFunds.Amount = 100 contestedFunds.Currency = 'EUR' result = self.sdk.disputes.ContestDispute(contestedFunds, notContestedDispute.Id) self.assertIsNotNone(result) self.assertEqual(result.Id, notContestedDispute.Id)
def getJohnsPayOutBankWire(self): """Creates Pay-Out Bank Wire object""" if self._johnsPayOutBankWire == None: wallet = self.getJohnsWallet() user = self.getJohn() account = self.getJohnsAccount() payOut = PayOut() payOut.Tag = 'DefaultTag' payOut.AuthorId = user.Id payOut.CreditedUserId = user.Id payOut.DebitedFunds = Money() payOut.DebitedFunds.Currency = 'EUR' payOut.DebitedFunds.Amount = 10 payOut.Fees = Money() payOut.Fees.Currency = 'EUR' payOut.Fees.Amount = 5 payOut.DebitedWalletId = wallet.Id payOut.MeanOfPaymentDetails = PayOutPaymentDetailsBankWire() payOut.MeanOfPaymentDetails.BankAccountId = account.Id payOut.MeanOfPaymentDetails.Communication = 'Communication text' self._johnsPayOutBankWire = self.sdk.payOuts.Create(payOut) return self._johnsPayOutBankWire
def test_Idempotency(self): key = random.randrange(100000000000000000, 999999999999999999) wallet = self.getJohnsWallet() user = self.getJohn() account = self.getJohnsAccount() payOutPost = PayOut() payOutPost.AuthorId = user.Id payOutPost.DebitedWalletId = wallet.Id payOutPost.DebitedFunds = Money(10, 'EUR') payOutPost.Fees = Money(5, 'EUR') payOutPost.MeanOfPaymentDetails = PayOutPaymentDetailsBankWire() payOutPost.MeanOfPaymentDetails.BankAccountId = account.Id payOutPost.MeanOfPaymentDetails.BankWireRef = 'Johns bank wire ref' payOutPost.Tag = 'DefaultTag' payOutPost.CreditedUserId = user.Id payOut = self.sdk.payOuts.CreateIdempotent(key, payOutPost) self.assertIsNotNone(payOut) # test existing key result = self.sdk.idempotency.Get(key) self.assertIsNotNone(result) # test non-existing key try: result = self.sdk.idempotency.Get(key + '_no') # expecting a response error self.assertTrue(1 == 0) except: result = None
def test_PayIns_Create_DirectDebitDirect(self): # ! IMPORTANT NOTE ! # # This test needs your manual confirmation on the web page (see note below) # Comment out line below to test payins with a mandate. return wallet = self.getJohnsWallet() user = self.getJohn() bankAccountId = self.getJohnsAccount().Id returnUrl = 'http://test.test' mandatePost = Mandate() mandatePost.BankAccountId = bankAccountId mandatePost.Culture = 'EN' mandatePost.ReturnURL = returnUrl mandate = self.sdk.mandates.Create(mandatePost) # ! IMPORTANT NOTE ! # # In order to make this test pass, at this place you have to set a breakpoint, # navigate to URL the mandate.RedirectURL property points to and click "CONFIRM" button. payIn = PayIn() payIn.CreditedWalletId = wallet.Id payIn.AuthorId = user.Id payIn.DebitedFunds = Money() payIn.DebitedFunds.Amount = 1000 payIn.DebitedFunds.Currency = 'EUR' payIn.Fees = Money() payIn.Fees.Amount = 1 payIn.Fees.Currency = 'EUR' payIn.PaymentDetails = PayInPaymentDetailsDirectDebit() payIn.PaymentDetails.MandateId = mandate.Id payIn.ExecutionDetails = PayInExecutionDetailsDirect() createPayIn = self.sdk.payIns.Create(payIn) self.assertTrue(int(createPayIn.Id) > 0) self.assertEqual(wallet.Id, createPayIn.CreditedWalletId) self.assertEqual('DIRECT_DEBIT', createPayIn.PaymentType) self.assertIsInstance(createPayIn.PaymentDetails, PayInPaymentDetailsDirectDebit) self.assertEqual(createPayIn.PaymentDetails.MandateId, mandate.Id) self.assertEqual('DIRECT', createPayIn.ExecutionType) self.assertIsInstance(createPayIn.ExecutionDetails, PayInExecutionDetailsDirect) self.assertEqual(user.Id, createPayIn.AuthorId) self.assertEqual('CREATED', createPayIn.Status) self.assertEqual('PAYIN', createPayIn.Type) self.assertIsInstance(createPayIn.DebitedFunds, Money) self.assertEqual(1000, createPayIn.DebitedFunds.Amount) self.assertEqual('EUR', createPayIn.DebitedFunds.Currency) self.assertIsInstance(createPayIn.Fees, Money) self.assertEqual(1, createPayIn.Fees.Amount) self.assertEqual('EUR', createPayIn.Fees.Currency)
def test_PayIns_Create_DirectDebitWeb(self): wallet = self.getJohnsWallet() user = self.getJohn() # create pay-in PRE-AUTHORIZED DIRECT payIn = PayIn() payIn.CreditedWalletId = wallet.Id payIn.AuthorId = user.Id payIn.DebitedFunds = Money() payIn.DebitedFunds.Amount = 10000 payIn.DebitedFunds.Currency = 'EUR' payIn.Fees = Money() payIn.Fees.Amount = 100 payIn.Fees.Currency = 'EUR' # payment type as CARD payIn.PaymentDetails = PayInPaymentDetailsDirectDebit() payIn.PaymentDetails.DirectDebitType = 'GIROPAY' payIn.ExecutionDetails = PayInExecutionDetailsWeb() payIn.ExecutionDetails.ReturnURL = 'http://www.mysite.com/returnURL/' payIn.ExecutionDetails.Culture = 'FR' payIn.ExecutionDetails.TemplateURLOptions = PayInTemplateURLOptions() payIn.ExecutionDetails.TemplateURLOptions.PAYLINE = 'https://www.maysite.com/payline_template/' createPayIn = self.sdk.payIns.Create(payIn) self.assertTrue(int(createPayIn.Id) > 0) self.assertEqual(wallet.Id, createPayIn.CreditedWalletId) self.assertEqual('DIRECT_DEBIT', createPayIn.PaymentType) self.assertIsInstance(createPayIn.PaymentDetails, PayInPaymentDetailsDirectDebit) self.assertEqual(createPayIn.PaymentDetails.DirectDebitType, 'GIROPAY') self.assertEqual('WEB', createPayIn.ExecutionType) self.assertIsInstance(createPayIn.ExecutionDetails, PayInExecutionDetailsWeb) self.assertEqual('FR', createPayIn.ExecutionDetails.Culture) self.assertEqual(user.Id, createPayIn.AuthorId) self.assertEqual('CREATED', createPayIn.Status) self.assertEqual('PAYIN', createPayIn.Type) self.assertIsInstance(createPayIn.DebitedFunds, Money) self.assertEqual(10000, createPayIn.DebitedFunds.Amount) self.assertEqual('EUR', createPayIn.DebitedFunds.Currency) self.assertIsInstance(createPayIn.CreditedFunds, Money) self.assertEqual(9900, createPayIn.CreditedFunds.Amount) self.assertEqual('EUR', createPayIn.CreditedFunds.Currency) self.assertIsInstance(createPayIn.Fees, Money) self.assertEqual(100, createPayIn.Fees.Amount) self.assertEqual('EUR', createPayIn.Fees.Currency) self.assertIsNotNone(createPayIn.ExecutionDetails.ReturnURL) self.assertIsNotNone(createPayIn.ExecutionDetails.RedirectURL) self.assertIsNotNone(createPayIn.ExecutionDetails.TemplateURL)
def test_Disputes_CreateSettlementTransfer(self): self.refreshClientDisputes() dispute = None for d in self._clientDisputes: if (d.Status == DisputeStatus.CLOSED and d.DisputeType == DisputeType.NOT_CONTESTABLE): dispute = d break self.assertIsNotNone( dispute, 'Cannot test creating settlement transfer because there\'s no closed dispute in the disputes list.' ) repudiationId = self.sdk.disputes.GetTransactions(dispute.Id)[0].Id repudiation = self.sdk.disputes.GetRepudiation(repudiationId) debitedFunds = Money() fees = Money() debitedFunds.Currency = 'EUR' debitedFunds.Amount = 1 fees.Currency = 'EUR' fees.Amount = 0 post = Transfer() post.AuthorId = repudiation.AuthorId post.DebitedFunds = debitedFunds post.Fees = fees result = self.sdk.disputes.CreateSettlementTransfer( post, repudiationId) self.assertIsNotNone(result)
def getJohnsWalletWithMoney(self, amount=10000): """Creates static JohnsWallet (wallets belonging to John) if not created yet return Wallet """ if self._johnsWalletWithMoney == None: john = self.getJohn() wallet = Wallet() wallet.Owners = [john.Id] wallet.Currency = 'EUR' wallet.Description = 'WALLET IN EUR' wallet = self.sdk.wallets.Create(wallet) cardRegistration = CardRegistration() cardRegistration.UserId = wallet.Owners[0] cardRegistration.Currency = 'EUR' cardRegistration = self.sdk.cardRegistrations.Create( cardRegistration) cardRegistration.RegistrationData = self.getPaylineCorrectRegistartionData( cardRegistration) cardRegistration = self.sdk.cardRegistrations.Update( cardRegistration) card = self.sdk.cards.Get(cardRegistration.CardId) # create pay-in CARD DIRECT payIn = PayIn() payIn.CreditedWalletId = wallet.Id payIn.AuthorId = cardRegistration.UserId payIn.DebitedFunds = Money() payIn.DebitedFunds.Amount = amount payIn.DebitedFunds.Currency = 'EUR' payIn.Fees = Money() payIn.Fees.Amount = 0 payIn.Fees.Currency = 'EUR' # payment type as CARD payIn.PaymentDetails = PayInPaymentDetailsCard() if (card.CardType == 'CB' or card.CardType == 'VISA' or card.CardType == 'MASTERCARD' or card.CardType == CardType.CB_VISA_MASTERCARD): payIn.PaymentDetails.CardType = CardType.CB_VISA_MASTERCARD # elif (card.CardType == CardType.AMEX): # payIn.PaymentDetails.CardType = CardType.AMEX # execution type as DIRECT payIn.ExecutionDetails = PayInExecutionDetailsDirect() payIn.ExecutionDetails.CardId = card.Id payIn.ExecutionDetails.SecureModeReturnURL = 'http://test.com' # create Pay-In self.sdk.payIns.Create(payIn) self._johnsWalletWithMoney = self.sdk.wallets.Get(wallet.Id) return self._johnsWalletWithMoney
def getJohnsRefundForTransfer(self, transfer=None): """Creates refund object for transfer return Refund """ if transfer == None: transfer = self.getJohnsTransfer() refund = Refund() refund.DebitedWalletId = transfer.DebitedWalletId refund.CreditedWalletId = transfer.CreditedWalletId refund.AuthorId = transfer.AuthorId refund.DebitedFunds = Money() refund.DebitedFunds.Amount = transfer.DebitedFunds.Amount refund.DebitedFunds.Currency = transfer.DebitedFunds.Currency refund.Fees = Money() refund.Fees.Amount = transfer.Fees.Amount refund.Fees.Currency = transfer.Fees.Currency return self.sdk.transfers.CreateRefund(transfer.Id, refund)
def getJohnsRefundForPayIn(self, payIn=None): """ Creates refund object for PayIn return Refund """ if payIn == None: payIn = self.getJohnsPayInCardDirect() refund = Refund() refund.CreditedWalletId = payIn.CreditedWalletId refund.AuthorId = payIn.AuthorId refund.DebitedFunds = Money() refund.DebitedFunds.Amount = payIn.DebitedFunds.Amount refund.DebitedFunds.Currency = payIn.DebitedFunds.Currency refund.Fees = Money() refund.Fees.Amount = payIn.Fees.Amount refund.Fees.Currency = payIn.Fees.Currency return self.sdk.payIns.CreateRefund(payIn.Id, refund)
def charge(db, participant, amount, return_url): """Charge the participant's credit card. Amount should be the nominal amount. We'll compute fees below this function and add it to amount to end up with charge_amount. """ typecheck(amount, Decimal) if participant.is_suspicious: raise UserIsSuspicious route = ExchangeRoute.from_network(participant, 'mango-cc') assert route charge_amount, fee = upcharge(amount) amount = charge_amount - fee e_id = record_exchange(db, route, amount, fee, participant, 'pre') payin = PayIn() payin.AuthorId = participant.mangopay_user_id if not participant.mangopay_wallet_id: create_wallet(db, participant) payin.CreditedWalletId = participant.mangopay_wallet_id payin.DebitedFunds = Money(int(charge_amount * 100), 'EUR') payin.ExecutionDetails = PayInExecutionDetailsDirect( CardId=route.address, SecureModeReturnURL=return_url, ) payin.Fees = Money(int(fee * 100), 'EUR') payin.PaymentDetails = PayInPaymentDetailsCard( CardType='CB_VISA_MASTERCARD') payin.Tag = str(e_id) try: test_hook() payin = mangoapi.payIns.Create(payin) except Exception as e: error = repr_exception(e) return record_exchange_result(db, e_id, 'failed', error, participant) if payin.ExecutionDetails.SecureModeRedirectURL: raise Response( 302, headers={'Location': payin.ExecutionDetails.SecureModeRedirectURL}) return record_exchange_result(db, e_id, 'succeeded', None, participant)
def propagate_exchange(cursor, participant, exchange, route, error, amount): """Propagates an exchange's result to the participant's balance and the route's status. """ route.update_error(error or '') new_balance = cursor.one( """ UPDATE participants SET balance=(balance + %s) WHERE id=%s RETURNING balance """, (amount, participant.id)) if amount < 0 and new_balance < 0: raise NegativeBalance if amount < 0: bundles = cursor.all( """ LOCK TABLE cash_bundles IN EXCLUSIVE MODE; SELECT * FROM cash_bundles WHERE owner = %s AND ts < now() - INTERVAL %s ORDER BY ts """, (participant.id, QUARANTINE)) withdrawable = sum(b.amount for b in bundles) x = -amount if x > withdrawable: raise NotEnoughWithdrawableMoney(Money(withdrawable, 'EUR')) for b in bundles: if x >= b.amount: cursor.run("DELETE FROM cash_bundles WHERE id = %s", (b.id, )) x -= b.amount if x == 0: break else: assert x > 0 cursor.run( """ UPDATE cash_bundles SET amount = (amount - %s) WHERE id = %s """, (x, b.id)) break elif amount > 0: cursor.run( """ INSERT INTO cash_bundles (owner, origin, amount, ts) VALUES (%s, %s, %s, %s) """, (participant.id, exchange.id, amount, exchange.timestamp)) participant.set_attributes(balance=new_balance) if amount != 0: participant.update_giving_and_tippees(cursor)
def record_payout_refund(db, payout_refund): orig_payout = mangoapi.payOuts.Get(payout_refund.InitialTransactionId) e_origin = db.one("SELECT * FROM exchanges WHERE id = %s" % (orig_payout.Tag,)) e_refund_id = db.one("SELECT id FROM exchanges WHERE refund_ref = %s", (e_origin.id,)) if e_refund_id: # Already recorded return e_refund_id amount, fee, vat = -e_origin.amount, -e_origin.fee, -e_origin.vat assert payout_refund.DebitedFunds == Money(int(amount * 100), 'EUR') assert payout_refund.Fees == Money(int(fee * 100), 'EUR') route = ExchangeRoute.from_id(e_origin.route) participant = Participant.from_id(e_origin.participant) return db.one(""" INSERT INTO exchanges (amount, fee, vat, participant, status, route, note, refund_ref) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) RETURNING id """, (amount, fee, vat, participant.id, 'created', route.id, None, e_origin.id))
def getJohnsPayInCardWeb(self): """Creates Pay-In Card Web object""" wallet = self.getJohnsWallet() user = self.getJohn() payIn = PayIn() payIn.AuthorId = user.Id payIn.CreditedUserId = user.Id payIn.DebitedFunds = Money() payIn.DebitedFunds.Currency = 'EUR' payIn.DebitedFunds.Amount = 1000 payIn.Fees = Money() payIn.Fees.Currency = 'EUR' payIn.Fees.Amount = 5 payIn.CreditedWalletId = wallet.Id payIn.PaymentDetails = self.getPayInPaymentDetailsCard() payIn.ExecutionDetails = self.getPayInExecutionDetailsWeb() return self.sdk.payIns.Create(payIn)
def payout(db, participant, amount, ignore_high_fee=False): assert amount > 0 if participant.is_suspended: raise AccountSuspended() payday = db.one("SELECT * FROM paydays WHERE ts_start > ts_end") if payday: raise PaydayIsRunning route = ExchangeRoute.from_network(participant, 'mango-ba') assert route ba = mangoapi.users.GetBankAccount(participant.mangopay_user_id, route.address) # Do final calculations credit_amount, fee, vat = skim_credit(amount, ba) if credit_amount <= 0 and fee > 0: raise FeeExceedsAmount fee_percent = fee / amount if fee_percent > FEE_PAYOUT_WARN and not ignore_high_fee: raise TransactionFeeTooHigh(fee_percent, fee, amount) # Try to dance with MangoPay e_id = record_exchange(db, route, -credit_amount, fee, vat, participant, 'pre') payout = PayOut() payout.AuthorId = participant.mangopay_user_id payout.DebitedFunds = Money(int(amount * 100), 'EUR') payout.DebitedWalletId = participant.mangopay_wallet_id payout.Fees = Money(int(fee * 100), 'EUR') payout.MeanOfPaymentDetails = PayOutPaymentDetailsBankWire( BankAccountId=route.address, BankWireRef=str(e_id), ) payout.Tag = str(e_id) try: test_hook() payout = mangoapi.payOuts.Create(payout) return record_exchange_result(db, e_id, payout.Status.lower(), repr_error(payout), participant) except Exception as e: error = repr_exception(e) return record_exchange_result(db, e_id, 'failed', error, participant)
def getJohnsPayInBankWireDirect(self): wallet = self.getJohnsWallet() payIn = PayIn() payIn.CreditedWalletId = wallet.Id payIn.AuthorId = wallet.Owners[0] # payment type as CARD payIn.PaymentDetails = PayInPaymentDetailsBankWire() payIn.PaymentDetails.DeclaredDebitedFunds = Money() payIn.PaymentDetails.DeclaredFees = Money() payIn.PaymentDetails.DeclaredDebitedFunds.Currency = 'EUR' payIn.PaymentDetails.DeclaredFees.Currency = 'EUR' payIn.PaymentDetails.DeclaredDebitedFunds.Amount = 10000 payIn.PaymentDetails.DeclaredFees.Amount = 1000 # execution type as DIRECT payIn.ExecutionDetails = PayInExecutionDetailsDirect() payIn.ExecutionType = ExecutionType.DIRECT return self.sdk.payIns.Create(payIn)
def test_Disputes_CreateSettlementTransfer(self): self.refreshClientDisputes() dispute = None for d in self._clientDisputes: if (d.Status == DisputeStatus.CLOSED and d.DisputeType == DisputeType.NOT_CONTESTABLE): dispute = d break self.assertIsNotNone(dispute, 'Cannot test creating settlement transfer because there\'s no closed dispute in the disputes list.') repudiationId = self.sdk.disputes.GetTransactions(dispute.Id)[0].Id repudiation = self.sdk.disputes.GetRepudiation(repudiationId) debitedFunds = Money() fees = Money() debitedFunds.Currency = 'EUR' debitedFunds.Amount = 1 fees.Currency = 'EUR' fees.Amount = 0 post = Transfer() post.AuthorId = repudiation.AuthorId post.DebitedFunds = debitedFunds post.Fees = fees result = self.sdk.disputes.CreateSettlementTransfer(post, repudiationId) self.assertIsNotNone(result)
def test_PayIns_PreAuthorizedDirect(self): cardPreAuthorization = self.getJohnsCardPreAuthorization() wallet = self.getJohnsWalletWithMoney() user = self.getJohn() # create pay-in PRE-AUTHORIZED DIRECT payIn = PayIn() payIn.CreditedWalletId = wallet.Id payIn.AuthorId = user.Id payIn.DebitedFunds = Money() payIn.DebitedFunds.Amount = 1000 payIn.DebitedFunds.Currency = 'EUR' payIn.Fees = Money() payIn.Fees.Amount = 0 payIn.Fees.Currency = 'EUR' # payment type as CARD payIn.PaymentDetails = PayInPaymentDetailsPreAuthorized() payIn.PaymentDetails.PreauthorizationId = cardPreAuthorization.Id # execution type as DIRECT payIn.ExecutionDetails = PayInExecutionDetailsDirect() payIn.ExecutionDetails.SecureModeReturnURL = 'http://test.com' createPayIn = self.sdk.payIns.Create(payIn) self.assertTrue(len(createPayIn.Id) > 0) self.assertEqual(wallet.Id, createPayIn.CreditedWalletId) self.assertEqual('PREAUTHORIZED', createPayIn.PaymentType) self.assertIsInstance(createPayIn.PaymentDetails, PayInPaymentDetailsPreAuthorized) self.assertEqual('DIRECT', createPayIn.ExecutionType) self.assertIsInstance(createPayIn.ExecutionDetails, PayInExecutionDetailsDirect) self.assertIsInstance(createPayIn.DebitedFunds, Money) self.assertIsInstance(createPayIn.CreditedFunds, Money) self.assertIsInstance(createPayIn.Fees, Money) self.assertEqual(user.Id, createPayIn.AuthorId) self.assertEqual('SUCCEEDED', createPayIn.Status) self.assertEqual('PAYIN', createPayIn.Type)
def getJohnsCardPreAuthorization(self): """Creates card pre authorization object. return CardPreAuthorization """ if (self._johnsCardPreAuthorization == None): user = self.getJohn() payIn = self.getJohnsPayInCardDirect() cardPreAuthorization = CardPreAuthorization() cardPreAuthorization.AuthorId = user.Id cardPreAuthorization.Tag = 'Test Card PreAuthorization' cardPreAuthorization.CardId = payIn.ExecutionDetails.CardId cardPreAuthorization.SecureMode = Mode3DSType.DEFAULT cardPreAuthorization.SecureModeReturnURL = 'https://test.com' cardPreAuthorization.DebitedFunds = Money() cardPreAuthorization.DebitedFunds.Amount = 1000 cardPreAuthorization.DebitedFunds.Currency = 'EUR' self._johnsCardPreAuthorization = self.sdk.cardPreAuthorizations.Create(cardPreAuthorization) return self._johnsCardPreAuthorization
def python_money_to_mangopay_money(python_money): amount = python_money.amount.quantize(Decimal('.01'), rounding=ROUND_FLOOR) * 100 return Money(amount=int(amount), currency=str(python_money.currency))
def Get(self, wallet_id): wallet = Wallet() wallet.id = wallet_id wallet.Balance = Money(10000, currency="EUR") return wallet
def propagate_exchange(cursor, participant, exchange, route, error, amount): """Propagates an exchange's result to the participant's balance and the route's status. """ route.update_error(error or '') new_balance = cursor.one( """ UPDATE participants SET balance=(balance + %s) WHERE id=%s RETURNING balance """, (amount, participant.id)) if amount < 0 and new_balance < 0: raise NegativeBalance if amount < 0: bundles = cursor.all( """ LOCK TABLE cash_bundles IN EXCLUSIVE MODE; SELECT b.* FROM cash_bundles b JOIN exchanges e ON e.id = b.origin WHERE b.owner = %s AND b.ts < now() - INTERVAL %s ORDER BY b.owner = e.participant DESC, b.ts """, (participant.id, QUARANTINE)) withdrawable = sum(b.amount for b in bundles) x = -amount if x > withdrawable: raise NotEnoughWithdrawableMoney(Money(withdrawable, 'EUR')) for b in bundles: if x >= b.amount: cursor.run( """ INSERT INTO e2e_transfers (origin, withdrawal, amount) VALUES (%s, %s, %s) """, (b.origin, exchange.id, b.amount)) cursor.run("DELETE FROM cash_bundles WHERE id = %s", (b.id, )) x -= b.amount if x == 0: break else: assert x > 0 cursor.run( """ INSERT INTO e2e_transfers (origin, withdrawal, amount) VALUES (%s, %s, %s) """, (b.origin, exchange.id, x)) cursor.run( """ UPDATE cash_bundles SET amount = (amount - %s) WHERE id = %s """, (x, b.id)) break elif amount > 0 and exchange.amount < 0: cursor.run( """ LOCK TABLE cash_bundles IN EXCLUSIVE MODE; INSERT INTO cash_bundles (owner, origin, amount, ts) SELECT %(p_id)s, t.origin, t.amount, e.timestamp FROM e2e_transfers t JOIN exchanges e ON e.id = t.origin WHERE t.withdrawal = %(e_id)s; DELETE FROM e2e_transfers WHERE withdrawal = %(e_id)s; """, dict(p_id=participant.id, e_id=exchange.id)) elif amount > 0: cursor.run( """ INSERT INTO cash_bundles (owner, origin, amount, ts) VALUES (%s, %s, %s, %s) """, (participant.id, exchange.id, amount, exchange.timestamp)) participant.set_attributes(balance=new_balance) if amount != 0: participant.update_giving_and_tippees(cursor) merge_cash_bundles(cursor, participant.id)