您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

how_to_integrate_payment.rst 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. .. spelling::
  2. DataCash
  3. ========================
  4. How to integrate payment
  5. ========================
  6. Oscar is designed to be very flexible around payment. It supports paying for an
  7. order with multiple payment sources and settling these sources at different
  8. times.
  9. Models
  10. ------
  11. The payment app provides several models to track payments:
  12. * ``SourceType`` - This is the type of payment source used (e.g. PayPal, DataCash). As part of setting up
  13. a new Oscar site you would create a SourceType for each of the payment
  14. gateways you are using.
  15. * ``Source`` - A source of payment for a single order. This tracks how an order
  16. was paid for. The source object distinguishes between allocations, debits and
  17. refunds to allow for two-phase payment model. When an order is paid for by
  18. multiple methods, you create multiple sources for the order.
  19. * ``Transaction`` - A transaction against a source. These models provide better
  20. audit for all the individual transactions associated with an order.
  21. Example
  22. -------
  23. Consider a simple situation where all orders are paid for by PayPal using their
  24. 'SALE' mode where the money is settled immediately (one-phase payment model).
  25. The project would have a 'PayPal' SourceType and, for each order, create a new
  26. ``Source`` instance where the ``amount_debited`` would be the order total. A
  27. ``Transaction`` model with ``txn_type=Transaction.DEBIT`` would normally also be
  28. created (although this is optional).
  29. This situation is implemented within the sandbox site for the
  30. django-oscar-paypal_ extension. Please use that as a reference.
  31. See also the sandbox for django-oscar-datacash_ which follows a similar pattern.
  32. .. _django-oscar-paypal: https://github.com/django-oscar/django-oscar-paypal/tree/master/sandbox
  33. .. _django-oscar-datacash: https://github.com/django-oscar/django-oscar-datacash/tree/master/sandbox
  34. Integration into checkout
  35. -------------------------
  36. By default, Oscar's checkout does not provide any payment integration as it is
  37. domain-specific. However, the core checkout classes provide methods for
  38. communicating with payment gateways and creating the appropriate payment models.
  39. Payment logic is normally implemented by using a customised version of
  40. ``PaymentDetailsView``, where the ``handle_payment`` method is overridden. This
  41. method will be given the order number and order total plus any custom keyword
  42. arguments initially passed to ``submit`` (as ``payment_kwargs``). If payment is
  43. successful, then nothing needs to be returned. However, Oscar defines a few
  44. common exceptions which can occur:
  45. * ``oscar.apps.payment.exceptions.RedirectRequired`` For payment integrations
  46. that require redirecting the user to a 3rd-party site. This exception class
  47. has a ``url`` attribute that needs to be set.
  48. * ``oscar.apps.payment.exceptions.UnableToTakePayment`` For *anticipated* payment
  49. problems such as invalid bankcard number, not enough funds in account - that kind
  50. of thing.
  51. * ``oscar.apps.payment.exceptions.UserCancelled`` During many payment flows,
  52. the user is able to cancel the process. This should often be treated
  53. differently from a payment error, e.g. it might not be appropriate to offer
  54. to retry the payment.
  55. * ``oscar.apps.payment.exceptions.PaymentError`` For *unanticipated* payment
  56. errors such as the payment gateway not responding or being badly configured.
  57. When payment has completed, there's a few things to do:
  58. * Create the appropriate ``oscar.apps.payment.models.Source`` instance and pass
  59. it to ``add_payment_source``. The instance is passed unsaved as it requires a
  60. valid order instance to foreign key to. Once the order is placed (and an
  61. order instance is created), the payment source instances will be saved.
  62. * Record a 'payment event' so your application can track which lines have been
  63. paid for. The ``add_payment_event`` method assumes all lines are paid for by
  64. the passed event type, as this is the normal situation when placing an order.
  65. Note that payment events don't distinguish between different sources.
  66. For example::
  67. from oscar.apps.checkout import views
  68. from oscar.apps.payment import models
  69. # Subclass the core Oscar view so we can customise
  70. class PaymentDetailsView(views.PaymentDetailsView):
  71. def handle_payment(self, order_number, total, **kwargs):
  72. # Talk to payment gateway. If unsuccessful/error, raise a
  73. # PaymentError exception which we allow to percolate up to be caught
  74. # and handled by the core PaymentDetailsView.
  75. reference = gateway.pre_auth(order_number, total.incl_tax, kwargs['bankcard'])
  76. # Payment successful! Record payment source
  77. source_type, __ = models.SourceType.objects.get_or_create(
  78. name="SomeGateway")
  79. source = models.Source(
  80. source_type=source_type,
  81. amount_allocated=total.incl_tax,
  82. reference=reference)
  83. self.add_payment_source(source)
  84. # Record payment event
  85. self.add_payment_event('pre-auth', total.incl_tax)