django 전자 결제 기능 구현 예시 코드

사고방식:제3자 지불 API 인 터 페 이 스 를 호출 하여 지불 기능 을 실현 한다.알 리 페 이 로 제3자 사이트 의 결제 기능 을 실현 하려 고 했 으 나 실제 작업 에서 알 리 페 이 는 Python 인터페이스 가 없다 는 것 을 알 게 되 었 습 니 다.인터넷 에 다른 사람 이 두 번 째 로 봉 인 된 Python 인터페이스 가 있 지만 저 같은 하 얀 사람 에 게 는 어렵 습 니 다.나중에 PayPal 에 기 존의 Django 모듈 이 있다 는 것 을 알 게 되 었 습 니 다.학습 의 목적 으로 이 기능 을 실현 하려 고 페 이 팔 의 전자 결제 기능 으로 연습 하기 로 했다.
먼저,PayPal 을 설치 한 Django 모듈:django-paypal,구체 적 인 소 개 는 GitHub 의 설명 을 참고 할 수 있 습 니 다.https://github.com/spookylukey/django-paypal

pip install django-paypal
그리고 settings.py 에 있 는 INSTALLEDAPPS 는'paypal.standard.ipn'을 가입 합 니 다.settings.py 에 다음 문 구 를 추가 합 니 다.

#           
PAYPAL_TEST = True
#       PayPal       
PAYPAL_REVEIVER_EMAIL = 'your email'
동기 데이터베이스 작업 을 실행 하 다.

./manage.py migrate
urls.py 에 다음 스타일 을 추가 합 니 다.각각 지불 완료 통지,회계 업 무 를 처리 하고 지불 완료,지불 취소 작업 을 표시 합 니 다.

url(r'^paypal/', include('paypal.standard.ipn.urls')), #       
url(r'^payment/(\d+)/$', views.payment),
url(r'^done/$', views.payment_done),
url(r'^canceled/$', views.payment_canceled),
PayPal 결제 작업,정확 한 데 이 터 를 포함 한 결제 단 추 를 만 듭 니 다.

@login_required
def payment(request, order_id):
 all_categories = models.Category.objects.all()
 try:
  order = models.Order.objects.get(id=order_id)
 except:
  messages.add_message(request, messages.WARNING, "      ,      。")
  return redirect('/myorders/')
 all_order_items = models.OrderItem.objects.filter(order=order)
 items = list()
 total = 0
 for order_item in all_order_items:
  t = dict()
  t['name'] = order_item.product.name
  t['price'] = order_item.product.price
  t['quantity'] = order_item.quantity
  t['subtotal'] = order_item.product.price * order_item.quantity
  total = total + order_item.product.price
  items.append(t)

 host = request.get_host()
 paypal_dict = {
  "business": settings.PAYPAL_REVEIVER_EMAIL,
  "amount": total,
  "item_name": "         :{}".format(order_id),
  "invoice": "invoice-{}".format(order_id),
  "currency_code": 'CNY',
  "notify_url": "http://{}{}".format(host, reverse('paypal-ipn')),
  "return_url": "http://{}/done/".format(host),
  "cancel_return": "http://{}/canceled/".format(host),
  }
 paypal_form = PayPalPaymentsForm(initial=paypal_dict)
 template = get_template('payment.html')
 html = template.render(context=locals(), request=request)
 return HttpResponse(html)
django-paypal 이 제공 하 는 PayPal Payment Form 류 를 사 용 했 기 때 문 입 니 다.따라서 views.py 앞에서 도 이 종 류 를 가 져 와 야 합 니 다.또한 settings.py 의 상수 가 사용 되 었 기 때문에 settings 도 가 져 와 야 합 니 다.문 구 는 다음 과 같 습 니 다.

from django.conf import settings
from paypal.standard.forms import PayPalPaymentsForm
from django.core.urlresolvers import reverse
지불 완료.

@csrf_exempt #csrf   
def payment_done(request):
 template = get_template('payment_done.html')
 html = template.render(context=locals(), request=request)
 return HttpResponse(html)
지불 을 취소 하 다.

@csrf_exempt
def payment_canceled(request):
 template = get_template('payment_canceled.html')
 html = template.render(context=locals(), request=request)
 return HttpResponse(html)
페 이 팔 결제 페이지.

<!-- payment.html (mshop project) -->
{% extends "base.html" %}
{% block title %}        {% endblock %}
{% block content %}
<div class='container'>
{% for message in messages %}
 <div class='alert alert-{{message.tags}}'>{{ message }}</div>
{% endfor %}
 <div class='row'>
  <div class='col-md-12'>
   <div class='panel panel-default'>
    <div class='panel-heading' align=center>
     <h3>         </h3>
      {% if user.socialaccount_set.all.0.extra_data.name %}
       {{user.socialaccount_set.all.0.extra_data.name}}<br/>
       <img src='{{user.socialaccount_set.all.0.get_avatar_url}}' width='100'>
      {% else %}
       Welcome: {{ user.username }}
      {% endif %}
    </div>
   </div>
  </div>
 </div>
 <div class='row'>
  <div class='col-sm-12'>
   <div class='panel panel-info'>
    <div class='panel panel-heading'>
     <h4>    (    :{{order.id}})</h4>
    </div>
    <div class='panel panel-body'>
     {% for item in items %}
     {% if forloop.first %}
     <table border=1>
      <tr>
       <td width=300 align=center>    </td>
       <td width=100 align=center>  </td>
       <td width=100 align=center>  </td>
       <td width=100 align=center>  </td>
      </tr>
     {% endif %}
      <div class='listgroup'>
       <div class='listgroup-item'>
        <tr>
         <td>{{ item.name }}</td>
         <td align=right>{{ item.price }}</td>
         <td align=center>{{ item.quantity }}</td>
         <td align=right>{{ item.subtotal }}</td>
        </tr>
       </div>
      </div>
     {% if forloop.last %}
     </table>
     {% endif %}
     {% empty %}
      <em>      </em>
     {% endfor %}
     
     {{ paypal_form.render }}
    </div>
    <div class='panel panel-footer'>
     NT$:{{ total }} 
    </div>
   </div>
  </div>
 </div>
</div>
{% endblock %}
결제 완료 페이지.

<!-- payment_done.html (mshop project) -->
{% extends "base.html" %}
{% block title %}Pay using PayPal{% endblock %}
{% block content %}
<div class='container'>
{% for message in messages %}
 <div class='alert alert-{{message.tags}}'>{{ message }}</div>
{% endfor %}
 <div class='row'>
  <div class='col-md-12'>
   <div class='panel panel-default'>
    <div class='panel-heading' align=center>
     <h3>         </h3>
      {% if user.socialaccount_set.all.0.extra_data.name %}
       {{user.socialaccount_set.all.0.extra_data.name}}<br/>
       <img src='{{user.socialaccount_set.all.0.get_avatar_url}}' width='100'>
      {% else %}
       Welcome: {{ user.username }}
      {% endif %}
    </div>
   </div>
  </div>
 </div>
 <div class='row'>
  <div class='col-sm-12'>
   <div class='panel panel-info'>
    <div class='panel panel-heading'>
     <h4> PayPal    </h4>
    </div>
    <div class='panel panel-body'>
           ,           。
    </div>
    <div class='panel panel-footer'>
    </div>
   </div>
  </div>
 </div>
</div>
{% endblock %}
결제 취소 페이지.

<!-- payment_canceled.html (mshop project) -->
{% extends "base.html" %}
{% block title %}PayPal       {% endblock %}
{% block content %}
<div class='container'>
{% for message in messages %}
 <div class='alert alert-{{message.tags}}'>{{ message }}</div>
{% endfor %}
 <div class='row'>
  <div class='col-md-12'>
   <div class='panel panel-default'>
    <div class='panel-heading' align=center>
     <h3>         </h3>
      {% if user.socialaccount_set.all.0.extra_data.name %}
       {{user.socialaccount_set.all.0.extra_data.name}}<br/>
       <img src='{{user.socialaccount_set.all.0.get_avatar_url}}' width='100'>
      {% else %}
       Welcome: {{ user.username }}
      {% endif %}
    </div>
   </div>
  </div>
 </div>
 <div class='row'>
  <div class='col-sm-12'>
   <div class='panel panel-info'>
    <div class='panel panel-heading'>
     <h4>      PayPal   </h4>
    </div>
    <div class='panel panel-body'>
     <p>         ,    <a href='/myorders/'>    </a>        。</p>
    </div>
    <div class='panel panel-footer'>
    </div>
   </div>
  </div>
 </div>
</div>
{% endblock %}
PayPal 은 온라인 결제 절 차 를 처리 한 후에 우리 사이트 에 HTTP 데 이 터 를 따로 보 냅 니 다.우 리 는 이 신 호 를 처리 하 는 함 수 를 만들어 서 데이터베이스 에 있 는 내용 을 변경 해 야 합 니 다.우리 가 설정 한 감청 함수 가 시스템 에 불 러 오고 운 행 될 수 있 도록 views.py 의 동급 디 렉 터 리 에 signal.py 파일 을 만들어 야 합 니 다.

from mysite import models
from paypal.standard.models import ST_PP_COMPLETED
from paypal.standard.ipn.signals import valid_ipn_received

def payment_notfication(sender, **kwargs):
 ipn_obj = sender
 if ipn_obj.payment_status == ST_PP_COMPLETED:
  order_id = ipn_obj.invocie.split('-')[-1]
  order = models.Order.objects.get(id = order_id)
  order_id.paid = True
  order.save()

valid_ipn_received.connect(payment_notfication)
같은 폴 더 아래 에 apps.py 라 는 파일 을 만 들 고 위 에서 작성 한 함수 가 처음부터 불 러 올 수 있 도록 합 니 다.

from django.apps import AppConfig

class PaymentConfig(AppConfig):
 name = 'mysite'
 verbose_name = 'Mysite'

 def ready(self):
  import mysite.signal
같은 폴 더 아래init__.py 에 다음 문 구 를 추가 하여 프로그램 이 로 딩 을 초기 화 할 때 사용자 정의 프로그램 환경 을 사용자 정의 작업 으로 설정 할 수 있 도록 합 니 다.

default_app_config = 'mysite.apps.PaymentConfig'
상기 설정 을 통 해 저희 사 이 트 는 주문 서 를 정확하게 받 아들 이 고 PayPal 로 지불 할 수 있 습 니 다.저 희 는 PayPal 개발 자 사이트https://developer.paypal.com/에서 테스트 계 정 을 신청 하여 결제 테스트 를 할 수 있 습 니 다.
dashboard 인터페이스 에 들 어가 기 를 누 르 고 Sandbox 의 account 옵션 을 누 르 면 테스트 계 정 을 만 들 수 있 습 니 다.

계 정 만 들 기 아래 profflee 옵션 을 클릭 하고 자세 한 페이지 에 들 어가 이 계 정의 비밀 번 호 를 설정 하고 Payment Review 기능 을 Off 로 설정 합 니 다.

그 다음 에 우 리 는 우리 사이트 에서 이 테스트 계 정 을 사용 하여 돈 을 지불 할 수 있 습 니 다.지불 하 러 가 려 면 payment 함 수 를 호출 하고 정확 한 데 이 터 를 포함 한 지불 단 추 를 불 러 옵 니 다.클릭 한 후에 paypal 의 샌 드 박스 결제 페이지 로 이동 합 니 다.우 리 는 그 중에서 우리 가 이전에 만 든 테스트 계 정 정 정 정 정 보 를 입력 하고 로그 인 한 후에 지불 할 수 있 습 니 다.

지불 이 성공 한 후에 우리 가 작성 한 지불 성공 페이지 로 돌아 갑 니 다.

주의:중국 대륙의 paypal 계 정 은 실제 지불 을 테스트 하 는 데 사용 할 수 없 으 며,대륙 이외 의 paypal 계 정 이 있어 야 실제 지불 을 테스트 할 수 있 습 니 다.(정말 구덩이 다...)
그렇지 않 으 면 지불 할 때 아래 화면 이 나타 날 것 이다.

여기까지 우리 의 지불 은 이미 성공 적 이 었 다.그러나... PayPal 은 결제 상 태 를 Google 애플 리 케 이 션 에 알 릴 수 없습니다.이것 은 Google 프로젝트 가 외부 에서 접근 할 수 없 는 127.0.0.1 에서 실행 되 기 때 문 입 니 다.우 리 는 인터넷 방문 개발 환경 을 실현 하기 위해 Ngrok 을 사용한다.
...에 있다 Nguk 홈 페이지  https://ngrok.com/압축 해제 파일 을 다운로드 하고 계 정 을 연결 한 후 다음 명령 을 실행 합 니 다.

./ngrok http 8000
이 명령 은 8000 포트 는 로 컬 호스트 에 채널 을 만 들 고 네트워크 에 접근 할 수 있 는 호스트 이름 을 설정 하여 다음 과 같은 출력 을 얻 을 수 있 습 니 다.

우 리 는 Forwarding 의 인터넷 주 소 를 방문 하여 우리 가 로 컬 에 구축 한 사 이 트 를 연결 할 수 있 습 니 다.
그리고 돈 을 지불 한 후에 자신의 로 컬 사이트 의 배경 관리 에서 paypal ipn 의 정 보 를 볼 수 있 습 니 다.제 가 여기 표시 한 상 태 는 pending 입 니 다.이치 상 completed 일 것 입 니 다.paypal 설정 에서 변경 이 필요 할 수도 있 습 니 다.그러면 signal.py 에서 STPP_COMPLETED 를 ST 로 변경PP_PENDING,이렇게 signal.py 는 paypal 이 돌아 오 는 정 보 를 정상적으로 처리 하고 주문 상 태 를 완 료 된 것 으로 변경 할 수 있 습 니 다.

이로써 우 리 는 paypal 을 호출 하여 제3자 사이트 결 제 를 실현 하 는 기능 을 완성 했다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기