Здесь не рассматриваются шаги по регистрации в системе qiwi. Здесь рассматривается техническая часть (Хотелось бы только сказать, что в кабинете qiwi нужно включить soap)
Скачиваем и устанавливаем приложение
- Скачиваем отсюда https://github.com/satels/django-qiwi/zipball/master
- Распаковываем
- Устанавливаем
python setup.py install
pip install -e git://github.com/satels/django-qiwi.git#egg=django-qiwi
Делаем установки django-qiwi в ваш проект.
В settings.py django-проектаINSTALLED_APPS = [
...
'django_qiwi',
...
]
#qiwi soap
QIWI_APP = 'qiwi'
QIWI_LOGIN = '12345'
QIWI_PASSWORD = 'SecretPAroli'
QIWI_SOAP_SERVER = ('0.0.0.0', 17555)
Здесь вы указываете QIWI_APP backend-приложение (app), который будет обрабатывать ваши объекты счетов и платежей (про это ниже)
Про логин и пароль все ясно.
Далее, QIWI_SOAP_SERVER - здесь указывается хост и порт, на которых будет запускаться qiwi soap сервер для обработки оповещений со стороны QIWI.
Интегрируем с вашей системой платежей (счета, платежи)
- Прикручиваем форму для создания платежа (Мы сообщаем QIWI о создании счета)
- Делаем Backend-приложение (QIWI сообщает нам - удачно или нет прошел платеж)
Форма создания платежа
Вот как обрабатывается у меня создания платежаfrom django_qiwi import get_status_text
from django_qiwi.soap.client import Client as QiwiClient
...
client = QiwiClient()
code = client.createBill(
phone=client_phone,
amount=sum,
comment=comment,
txn=invoice.id,
lifetime=datetime.now() + timedelta(1),
)
if code in [0, 50]:
return redirect(invoice.get_qiwi_url())
else:
messages.error(request,
MESSAGE_QIWI_ERROR % get_status_text(code)
)
buy_denial_by_invoice(invoice)
...
Видно, что создаем платеж и оповещаем через soap - оповещаем друзей роботов из QIWI,
при удачном исходе - код 0 или 50 - переадресуем клиента на страницу с инструкцией, как оплатить, или же сообщаем о ошибке и отменяем платеж.
Что же такое указано в QIWI_APP?
Теперь, как же будет нас оповещать qiwi о удачном платеже. Будет через backend, который мы создали и указали в переменной QIWI_APP
Указан пакет в вашем проекте django. Структура такая:
qiwi __init__.pyили такая
qiwi.pyСодержание qiwi примерно такое будет у вас (Я взял из своего проекта)
from discounts.utils import buy_denial_by_invoice, buy_paided_by_invoice
from django.conf import settings
from django_qiwi.soap.client import Client as QiwiClient
from invoices.models import Invoice
import datetime
import logging
def update_bill(txn, status):
client = QiwiClient()
response = client.checkBill(txn)
code = response['status']
amount = response['amount']
amount = float(amount)
invoices = Invoice.objects.filter(
id=txn, status=Invoice.STATUS.nopaid, type='qiwi',
)
if invoices.exists():
invoice = invoices[0]
if code == 60:
buy_paided_by_invoice(invoice, amount)
ret = 0
elif code in [150, 160, 161]:
buy_denial_by_invoice(invoice)
ret = 0
else:
ret = -1
else:
ret = 210
logging.basicConfig(filename=settings.QIWI_LOG_FILE, level=logging.DEBUG)
dt = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
message = 'date: %s, txn: %s, code: %s, amount: %s, ret:%s' % (
dt, txn, code, amount, ret
)
logging.debug(message)
return ret
Т.е. вот здесь проверяется при оповещении о платеже - есть ли неоплаченный платеж, то если есть, то оплачиваем его, если пришло оповещение о оплаченном платеже или же не оплачиваем.
Такж же можем сообщить, что платежа не существует
Запускаем тесты
При каждом последующем изменении кода - запускаем тесты, чтобы точно ничего не отвалилось при оплате у клиентаСоздаем подмену для QIWI - мы будем отсылать оповещения ему о создании платежа
#coding:utf-8
from django_qiwi.soap import server
from settings import QIWI_PASSWORD, QIWI_LOGIN
from threading import Thread
import SOAPpy
import qiwi
class QiwiProviderThread(Thread):
def __init__(self):
Thread.__init__(self)
self.setDaemon(True)
self.server = self._createSOAPServer()
self.data = {}
self.paid = False
def _createSOAPServer(self):
server = SOAPpy.SOAPServer(('localhost', 77877))
def createBill(login, password, user, amount, comment, txn, lifetime, alarm, create):
if not all([login==QIWI_LOGIN, password==QIWI_PASSWORD]):
return 150
if len(user) != 10:
return 150
try:
amount = float(amount)
except:
return 150
if amount > 15000:
return 242
if alarm not in [0, 1, 2]:
return 150
if create not in [0, 1]:
return 150
self.data = {
'user': user,
'amount': amount,
'comment': comment,
'txn': txn,
'lifetime': lifetime,
'alarm': alarm,
'create':create,
'date': datetime.now().strftime("%d.%m.%Y %H:%M:%S")
}
return 50
def checkBill(login, password, txn):
if txn != self.data['txn']:
return 210
res = dict(self.data, **{
'status': self.paid and 60 or 52
})
return res
server.registerFunction(createBill)
server.registerFunction(checkBill)
return server
def run(self):
self.server.serve_forever()
def stop(self):
self.server.shutdown()
del self.server
self.join()
def bayWithQiwi(self, txn, amount):
lifetime = self.data['lifetime']
if datetime.strptime(lifetime, '%d.%m.%Y %H:%M:%S') < datetime.now():
raise ValueError(u'Нельзя оплатить. Срок оплаты прошел')
self.paid = True
self.data['amount'] = str(amount)
qiwi.update_bill(txn=txn, status=60)
- запускается поток, который запускает подмену soap серверу системы. Даже есть подмена клиенту, который пошел оплачивать через терминал QIWI! (bayWithQiwi).
Сам тест
class QiwiBayTest(test.TestCase, _InvoiceTest, _BayTest, _QiwiTest):
def setUp(self):
super(QiwiBayTest, self)._setUp()
self.qiwi_provider = QiwiProviderThread()
self.qiwi_provider.start()
initial = self.default_initial
self.default_initial = dict(initial, **{'payment_method': 'qiwi'})
def tearDown(self):
super(QiwiBayTest, self)._tearDown()
self.qiwi_provider.stop()
def testBayWithQiwiAmountLessThenPrice(self):
"""Оплачиваем скидку через QIWI, но кладем меньшую сумму, чем надо"""
response = self._postData(self.default_initial)
invoice = self._assertExistQiwiInvoice()
self._assertFollowToQiwiInvoicePage(response, invoice)
amount = self.discount.price_paid*0.8
self.qiwi_provider.bayWithQiwi(invoice.id, amount)
self._refreshUser()
invoice = self._getRefreshedInvoice(invoice)
self._assertParentInvoiceNoPaid(invoice)
self._assertUserBalance(amount + self.initial_sum)
invoice.delete()
def testBayWithQiwiAmountGreateThenPrice(self):
"""Оплачиваем скидку через QIWI, но кладем большую сумму, чем надо"""
data = self.default_initial
response = self._postData(data)
invoice = self._assertExistQiwiInvoice()
self._assertFollowToQiwiInvoicePage(response, invoice)
amount = self.discount.price_paid*data['number'] - self.initial_sum
self.qiwi_provider.bayWithQiwi(invoice.id, amount)
self._refreshUser()
invoice = self._getRefreshedInvoice(invoice)
self._assertParentInvoicePaid(invoice)
self._assertUserBalance(0.0)
invoice.delete()
def testBayWithQiwiAndBalanceGreateThenPrice(self):
"""Оплачиваем скидку через QIWI, при этом баланс на счете большой"""
data = self.default_initial
sum = self.discount.price_paid*data['number']
update_balance(self.user, sum)
balance_before = self.user.get_profile().get_balance()
response = self._postData(data)
invoice = self._assertExistQiwiInvoice()
self._assertFollowToQiwiInvoicePage(response, invoice)
amount = self.initial_sum
self.qiwi_provider.bayWithQiwi(invoice.id, amount)
self._refreshUser()
invoice = self._getRefreshedInvoice(invoice)
self._assertParentInvoicePaid(invoice)
self._assertUserBalance(balance_before + amount - sum)
invoice.delete()
def testSomeErrorOnQiwiProvider(self):
"""Ошибка на сервере QIWI, например, превышена сумма платежа(> 15000)"""
data = dict(self.default_initial, **{
'number': int(16000.0/self.discount.price_paid)
})
response = self._postData(data)
self._assertFollowToBayPage(response)
self._assertCountMessages(response, 1)
invoice = self._assertExistQiwiInvoice()
self._assertParentInvoiceDenial(invoice)
def _assertExistQiwiInvoice(self):
return self._assertExistInvoiceByType('qiwi')
Не забудьте в файле test_settings.py (настройках settings.py для тестов) указать примерно такое
from settings import *
QIWI_SOAP_ISHOP_URL = 'http://localhost:77877'
QIWI_SOAP_SERVER = ('localhost', 17777)
А потом запускать так ./manage.py test --settings="test_settings.py"
Запускаем сервер soap для взаимодействия с qiwi
Чтобы просто попробовать, как работает - запускаем так: python manage.py run_qiwi_soap В продакшн версии нужно запускать подобное через sv (что такое sv): Используем файл из приложения django_qiwi: https://github.com/satels/django-qiwi/blob/master/qiwi_soap_server.sh.example Далее, создаем/etc/service/qiwi_soap_server/run
и делаем его исполняемым, копируем содержание файла qiwi_soap_server.sh.example в негоЗапускаем
sv u qiwi_soap_server
Все должно работать. Пишите комментарии
Хотелось бы увидеть пример реализации invoice.get_qiwi_url()
ОтветитьУдалитьclass Invoice(models.Model):
ОтветитьУдалитьdef get_qiwi_url(self):
return reverse('invoices_invoice_type', kwargs={
'type': "qiwi", 'invoice_id': self.id
})
Это страница с инструкцией об оплате
ОтветитьУдалитьСпасибо. Я думал что это ссылка на сайт киви, где сразу же можно оплатить одним из предложенных способов. На сайте киви это называется гибридный способ. К примеру form.target как это сделанно в django-robokassa.
ОтветитьУдалитьДолбаёб, научись писать! Учи русский язык, нихуя не понтно, уёбок? тебе прогать нельзя - ты опасен и туп? дибил сраный.!!!!!
ОтветитьУдалитьДолбоёб* понятно* ты опасен и туп!* дебил* (с горяча ошибок понаделал ^^)
ОтветитьУдалитьUndefined Coder = Непонятливый кодер. Если тебе не понятно, то это твое проблемы.
ОтветитьУдалитьНу ты дибил, undefined - значит не определён, и если рассматривать имя и фамилию как переменные, то считай что определил var name = "Coder", surname = undefined;) вот ссыль http://translate.google.ru/#ru|en|%D0%BD%D0%B5%D0%BF%D0%BE%D0%BD%D1%8F%D1%82%D0%BD%D1%8B%D0%B9%0A%D0%BD%D0%B5%D0%BF%D0%BE%D0%BD%D1%8F%D1%82%D0%BB%D0%B8%D0%B2%D1%8B%D0%B9 (или юзай словарь)
ОтветитьУдалитьну ты и мразь. пиздец только у нас есть ёбнутое мудачье которое считает что опен-сорс ему еще че-то должен!! просто феерический мудак
УдалитьНо независимо от перевода, ты остаёшься непонятливым
ОтветитьУдалитьНе надо обвинять людей в чём-либо, если просто не можешь донести свою мысль понятно каждому! И насчёт непонятливости: я программирование понимаю абстрактно и конкретно, а вот твоё пояснение и не абстрактно и не конкретно. В добавок.... мне уже пох, я прочёл нормальные исходники php работы с qiwi через soap (где были комментарии к коду), и вот что скажу, коротких комментариев было достаточно, чтобы хоть что-то понять, и ушло на это буквально минута! так что суди сам, о том, как ты составляешь пост, если исходники на другом языке (php) проще понять, чем твой пост с примерами кода на нужном мне языке (python)
ОтветитьУдалитьТы чего вообще несешь, если тебе не хватает мозгов понять что тут написано, то не надо тебе это читать. Программируй на своем php и не надо оскорблять автора, мне его код очень помог
УдалитьОК.
ОтветитьУдалить