问题
I am developing a shopping website using django-oscar framework, in fact I am using their sandbox site. I want to add payment to the checkout process, but the thing is, I am totally confused!
I've read this link : "Oscar's payment integration docs"
and I got the big picture stuff. I also read the file views.py in the checkout app, But I have a few questions which I couldn't find on the web.
My question is what are the methods/classes I should override or create to handle the following process :
after the user requests to make a payment, I should send a request to the bank and give them the required paramteres ( pay_request_parameters in code )
then, they will send an Id, confirming my access and then I should post that Id to an address and redirect the user to the bank's web page.
After the user has payed the bank successfully, they will inform me with a post to the call back url provided by me in the first step.
with that info, I should verify the payment's success and if it was successful, I should ask for a settlement from the bank, to send me the money.
Now the code I have does the first two steps, but I dont know how to handle the process after the redirection in sandbox. here's my code :
from oscar.apps.checkout import views
from oscar.apps.payment import models
from oscar.apps.payment.exceptions import *
import requests
import datetime
mellat_services_url = 'https://bpm.shaparak.ir/pgwchannel/services/pgw?wsdl'
start_pay_url = 'https://bpm.shaparak.ir/pgwchannel/startpay.mellat'
terminal_id = 'xxx'
username = 'xxx'
password = 'xxx'
# Subclass the core Oscar view so we can customise
class PaymentDetailsView(views.PaymentDetailsView):
def handle_payment(self, order_number, total, **kwargs):
# Talk to payment gateway. If unsuccessful/error, raise a
# PaymentError exception which we allow to percolate up to be caught
# and handled by the core PaymentDetailsView.
# mellat cycle start
local_date = str(datetime.date.today())[0:4] + str(datetime.date.today())[5:7] + str(datetime.date.today())[8:10]
local_time = str(datetime.datetime.now().time())[0:2] + str(datetime.datetime.now().time())[3:5] + str(datetime.datetime.now().time())[6:8]
# call bpPayRequest and get refId
pay_request_parameters = {'terminalId': terminal_id, 'userName': username,
'userPassword': password, 'orderId': order_number,
'amount': total.incl_tax, 'localDate': local_date,
'localTime': local_time, 'additionalData': ""
'callBackUrl': 'mysite.com/checkout/preview/'}
pay_request_answer = requests.post(mellat_services_url, pay_request_parameters)
if not pay_request_answer.split(",")[0] == 0:
response_code = pay_request_answer.split(",")[0]
if response_code[0] == '1':
raise UnableToTakePayment()
else:
raise PaymentError()
requests.post(start_pay_url, pay_request_answer.split(",")[1])
raise RedirectRequired(start_pay_url)
# post the refId to bank and then redirect customer to the bank
# apparently wait for the bank ( like for 10 mins ) to get the payment status
# if the bank responded with success, the you verify the payment with a post to the bank
# if everything was verified, tell the bank for a settlement
# mellat cycle end
#The rest should be implemented but I dont know where I should put this
#All I know is that it should be done after the verification with the data
#sent from the bank.
reference = gateway.pre_auth(order_number, total.incl_tax, kwargs['bankcard'])
# Payment successful! Record payment source
source_type, __ = models.SourceType.objects.get_or_create(
name="SomeGateway")
source = models.Source(
source_type=source_type,
amount_allocated=total.incl_tax,
reference=reference)
self.add_payment_source(source)
# Record payment event
self.add_payment_event('pre-auth', total.incl_tax)
thanks in advance.
回答1:
I had a similar problem, what I did was have the callBackUrl from the bank redirect to a view which is implemented something like this:
class CustomCheckoutDone(OrderPlacementMixin, RedirectView):
"""
here we verify payment was done and place the actual order
then redirect to thank you page
"""
permanent = False
def get_redirect_url(self, pk):
basket = Basket.objects.get(pk=self.checkout_session.get_submitted_basket_id())
basket.strategy = CustomStrategy()
order_number = self.checkout_session.get_order_number()
shipping_address = self.get_shipping_address(basket)
shipping_method = self.get_shipping_method(basket, shipping_address)
shipping_charge = shipping_method.calculate(basket)
billing_address = self.get_billing_address(shipping_address)
order_total = self.get_order_totals(basket, shipping_charge=shipping_charge)
order_kwargs = {}
# make sure payment was actually paid
CustomPayment.objects.get(order_number=order_number, payed_sum=str(float(order_total.incl_tax)))
user = self.request.user
if not user.is_authenticated():
order_kwargs['guest_email'] = self.checkout_session.get_guest_email()
self.handle_order_placement(
order_number, user, basket, shipping_address, shipping_method,
shipping_charge, billing_address, order_total, **order_kwargs
)
return '/checkout/thank-you/'
来源:https://stackoverflow.com/questions/31373028/integrating-a-redirection-included-method-of-payment-in-django-oscar