Package: django-virtual-pos
Django Virtual PosDjango module that abstracts the flow of several virtual points of sale
including PayPalWhat’s this?This module abstracts the use of the most used virtual points of sale in
Spain.LicenseMIT LICENSE.Implemented payment methodsPaypalPaypalpaypal payment available.BitpayBitpaybitcoin payments, from wallet to checkoutSpanish Virtual Points of SaleCecaCECAis the Spanish confederation of savings banks.RedSySRedSySgives payment services to several Spanish banks like CaixaBank
or Caja Rural.Santander ElavonSantander Elavonis one of the payment methods of the Spanish bank
Santander.Requirements and InstallationRequirementsPython 2.7 (Python 3 not tested, contributors wanted!)DjangoBeautifulSoup4lxmlpycryptoPytzRequestsType:$pipinstalldjangobeautifulsoup4lxmlpycryptopytzInstallationFrom PyPi$pipinstalldjango-virtual-posFrom master branchMaster branch will allways contain a working version of this module.$pipinstallgit+git://github.com/intelligenia/django-virtual-pos.gitsettings.pyAdd the application djangovirtualpos to your settings.py:INSTALLED_APPS=(# ..."djangovirtualpos",)UseSee thismanual(currently only in Spanish).Needed modelsYou will need to implement this skeleton view using your ownPaymentmodel.This model has must have at least the following attributes: -code:
sale code given by our system. -operation_number: bank operation
number. -status: status of the payment: “paid”, “pending”
(pendingis mandatory) or “canceled”. -amount: amount to be
charged.And the following methods: -online_confirm: mark the payment as
paid.Integration examplesdjshopNeeded viewsSale summary viewdefpayment_summary(request,payment_id):"""
    Load a Payment object and show a summary of its contents to the user.
    """payment=get_object_or_404(Payment,id=payment_id,status="pending")replacements={"payment":payment,# ...}returnrender(request,'<sale summary template path>',replacements)Note that this payment summary view should load a JS file calledset_payment_attributes.js.This file is needed to set initial payment attributes according to which
bank have the user selected.Payment_confirm view@csrf_exemptdefpayment_confirmation(request,virtualpos_type):"""
    This view will be called by the bank.
    """# Directly call to confirm_payment view# Or implement the following actions# Checking if the Point of Sale existsvirtual_pos=VirtualPointOfSale.receiveConfirmation(request,virtualpos_type=virtualpos_type)ifnotvirtual_pos:# The VPOS does not exist, inform the bank with a cancel# response if neededreturnVirtualPointOfSale.staticResponseNok(virtualpos_type)# Verify if bank confirmation is indeed from the bankverified=virtual_pos.verifyConfirmation()operation_number=virtual_pos.operation.operation_numberwithtransaction.atomic():try:# Getting your payment object from operation numberpayment=Payment.objects.get(operation_number=operation_number,status="pending")exceptPayment.DoesNotExist:returnvirtual_pos.responseNok("not_exists")ifverified:# Charge the money and answer the bank confirmationtry:response=virtual_pos.charge()# Implement the online_confirm method in your payment# this method will mark this payment as paid and will# store the payment date and time.payment.online_confirm()exceptVPOSCantChargease:returnvirtual_pos.responseNok(extended_status=e)exceptExceptionase:returnvirtual_pos.responseNok("cant_charge")else:# Payment could not be verified# signature is not rightresponse=virtual_pos.responseNok("verification_error")returnresponsePayment ok viewdefpayment_ok(request,sale_code):"""
    Informs the user that the payment has been made successfully
    :param payment_code: Payment code.
    :param request: request.
    """# Load your Payment model given its codepayment=get_object_or_404(Payment,code=sale_code,status="paid")context={'pay_status':"Done","request":request}returnrender(request,'<payment_ok template>',{'context':context,'payment':payment})Payment cancel viewdefpayment_cancel(request,sale_code):"""
    Informs the user that the payment has been canceled
    :param payment_code: Payment code.
    :param request: request.
    """# Load your Payment model given its codepayment=get_object_or_404(Payment,code=sale_code,status="pending")# Mark this payment as canceledpayment.cancel()context={'pay_status':"Done","request":request}returnrender(request,'<payment_canceled template>',{'context':context,'payment':payment})Refund viewdefrefund(request,tpv,payment_code,amount,description):"""
    :param request:
    :param tpv: TPV Id
    :param payment_code: Payment code
    :param amount: Refund Amount (Example 10.89).
    :param description: Description of refund cause.
    :return:
    """amount=Decimal(amount)try:# Checking if the Point of Sale existstpv=VirtualPointOfSale.get(id=tpv)# Checking if the Payment existspayment=Payment.objects.get(code=payment_code,state="paid")exceptPayment.DoesNotExistase:returnhttp_bad_request_response_json_error(message=u"Does not exist payment with code{0}".format(payment_code))refund_status=tpv.refund(payment_code,amount,description)ifrefund_status:message=u"Refund successful"else:message=u"Refund with erros"returnhttp_response_json_ok(message)AuthorsMario BarchéinmarioREMOVETHIS@REMOVETHISintelligenia.comDiego J. RomerodiegoREMOVETHIS@REMOVETHISintelligenia.comRemove REMOVETHIS to contact the authors.