├── README.rst ├── __init__.py ├── accounts ├── __init__.py └── urls.py ├── alipay ├── __init__.py ├── alipay.py ├── config.py └── hashcompat.py ├── db └── sqlite3.db ├── manage.py ├── payment.log ├── payment ├── __init__.py ├── models.py ├── urls.py └── views.py ├── settings.py ├── templates ├── payment │ ├── error.html │ ├── plans.html │ └── success.html └── registration │ └── login.html └── urls.py /README.rst: -------------------------------------------------------------------------------- 1 | 介绍 2 | ============ 3 | 4 | alipay_python 是支付宝接口的python版本,提供了担保交易,即时到帐和自动发货的接口。 5 | 6 | fork自这个版本 `alipay `_. 增加了担保交易,确认发货和简单的测试站点(django)。如果你在你的站点中使用了这个接口,可以考虑告诉我们 ( okidogiii@gmail.com )。 7 | 8 | 使用 9 | --------- 10 | * 下载解压到python_alipay目录 11 | * 修改alipay/config.py配置文件,根据你的支付宝帐号进行相应的设置 12 | * python manage.py syncdb 13 | * python manage.py runserver 14 | 15 | 组成 16 | ---------- 17 | 18 | * alipay/: 包含了支付宝的即时到帐,担保交易和确认发货的接口 19 | * payment/:你的站点订单系统调用接口的简单例子 20 | * accounts/:用户登录 21 | 22 | 接口描述 (alipay/alipay.py) 23 | --------- 24 | 25 | 提供了即时到帐,担保交易和确认发货的接口。 26 | 27 | * 即时到帐 28 | 29 | def create_direct_pay_by_user(tn, subject, body, total_fee) 30 | 31 | tn - 'out_trade_no', 应该是你的网站订单系统中唯一订单匹配号 32 | subject - 'subject', 你的订单名称 33 | body - 'body', 订单描述 34 | total_fee - 'total_fee', 订单的总金额 35 | 36 | 返回应该跳转的支付宝链接 37 | 38 | * 担保交易 39 | 40 | def create_partner_trade_by_buyer (tn, subject, body, price) 41 | 42 | tn - 'out_trade_no', 应该是你的网站订单系统中唯一订单匹配号 43 | subject - 'subject', 你的订单名称 44 | body - 'body', 订单描述 45 | price - 'price', 商品单价 46 | 47 | 返回应该跳转的支付宝链接 48 | 49 | note: 物流的类型等的设置在接口內默认设置,如果你需要每次修改可以扩展这个接口。 50 | 51 | * 确认发货 52 | 53 | def send_goods_confirm_by_platform (tn) 54 | 55 | tn - 'trade_no', 注意这个不是你站点的唯一订单号,而是支付宝返回的在支付宝系统内唯一的订单号。 56 | 57 | 返回确认发货应该跳转的链接。 58 | 59 | 测试接口 (payment/views.py) 60 | ------------------ 61 | 62 | * notify_url_handler (request): 支付宝异步通知的接口。验证并且根据交易状态更新订单。如果用户已经付款等待发货,调用确认发货接口。对应的ALIPAY_NOTIFY_URL设置应该是http://your_domain_name/notify_url 63 | 64 | * return_url_handler (request): 支付宝同步通知的接口。验证并且根据交易状态更新订单。如果用户已经付款等待发货,调用确认发货接口。对应的ALIPAY_RETURN_URL设置应该是http://your_domain_name/return_url 65 | 66 | * upgrade_account (request, acc_type): 根据升级账户的类别ACC_TYPE创建账单。并且跳转至支付宝的付款接口(担保交易)。 67 | 68 | Bring to you by 69 | -------------------- 70 | 71 | * `ikindle杂志订阅 `_:每天推送新鲜的报纸和杂志到你的Kindle. 72 | * `ikindle万卷书 `_: mobi格式和6寸pdf的图书共享站点,可以下载或者直接推送到你的Kindle。 73 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengli/alipay_python/4fbfe625944f0224d343fd0346589a28af6836ed/__init__.py -------------------------------------------------------------------------------- /accounts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengli/alipay_python/4fbfe625944f0224d343fd0346589a28af6836ed/accounts/__init__.py -------------------------------------------------------------------------------- /accounts/urls.py: -------------------------------------------------------------------------------- 1 | # These URLs are normally mapped to /admin/urls.py. This URLs file is 2 | # provided as a convenience to those who want to deploy these URLs elsewhere. 3 | # This file is also used to provide a reliable view deployment for test purposes. 4 | 5 | from django.conf.urls.defaults import * 6 | 7 | urlpatterns = patterns('', 8 | (r'^login/$', 'django.contrib.auth.views.login'), 9 | (r'^logout/$', 'django.contrib.auth.views.logout'), 10 | (r'^password_change/$', 'django.contrib.auth.views.password_change'), 11 | (r'^password_change/done/$', 'django.contrib.auth.views.password_change_done'), 12 | (r'^password_reset/$', 'django.contrib.auth.views.password_reset'), 13 | (r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done'), 14 | (r'^reset/(?P[0-9A-Za-z]{1,13})-(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', 'django.contrib.auth.views.password_reset_confirm'), 15 | (r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete'), 16 | ) 17 | 18 | -------------------------------------------------------------------------------- /alipay/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengli/alipay_python/4fbfe625944f0224d343fd0346589a28af6836ed/alipay/__init__.py -------------------------------------------------------------------------------- /alipay/alipay.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | Created on 2011-4-21 4 | 支付宝接口 5 | @author: Yefe 6 | ''' 7 | import types 8 | from urllib import urlencode, urlopen 9 | from hashcompat import md5_constructor as md5 10 | from config import settings 11 | 12 | def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'): 13 | """ 14 | Returns a bytestring version of 's', encoded as specified in 'encoding'. 15 | 16 | If strings_only is True, don't convert (some) non-string-like objects. 17 | """ 18 | if strings_only and isinstance(s, (types.NoneType, int)): 19 | return s 20 | if not isinstance(s, basestring): 21 | try: 22 | return str(s) 23 | except UnicodeEncodeError: 24 | if isinstance(s, Exception): 25 | # An Exception subclass containing non-ASCII data that doesn't 26 | # know how to print itself properly. We shouldn't raise a 27 | # further exception. 28 | return ' '.join([smart_str(arg, encoding, strings_only, 29 | errors) for arg in s]) 30 | return unicode(s).encode(encoding, errors) 31 | elif isinstance(s, unicode): 32 | return s.encode(encoding, errors) 33 | elif s and encoding != 'utf-8': 34 | return s.decode('utf-8', errors).encode(encoding, errors) 35 | else: 36 | return s 37 | 38 | # 网关地址 39 | _GATEWAY = 'https://mapi.alipay.com/gateway.do?' 40 | 41 | 42 | # 对数组排序并除去数组中的空值和签名参数 43 | # 返回数组和链接串 44 | def params_filter(params): 45 | ks = params.keys() 46 | ks.sort() 47 | newparams = {} 48 | prestr = '' 49 | for k in ks: 50 | v = params[k] 51 | k = smart_str(k, settings.ALIPAY_INPUT_CHARSET) 52 | if k not in ('sign','sign_type') and v != '': 53 | newparams[k] = smart_str(v, settings.ALIPAY_INPUT_CHARSET) 54 | prestr += '%s=%s&' % (k, newparams[k]) 55 | prestr = prestr[:-1] 56 | return newparams, prestr 57 | 58 | 59 | # 生成签名结果 60 | def build_mysign(prestr, key, sign_type = 'MD5'): 61 | if sign_type == 'MD5': 62 | return md5(prestr + key).hexdigest() 63 | return '' 64 | 65 | 66 | # 即时到账交易接口 67 | def create_direct_pay_by_user(tn, subject, body, total_fee): 68 | params = {} 69 | params['service'] = 'create_direct_pay_by_user' 70 | params['payment_type'] = '1' 71 | 72 | # 获取配置文件 73 | params['partner'] = settings.ALIPAY_PARTNER 74 | params['seller_email'] = settings.ALIPAY_SELLER_EMAIL 75 | params['return_url'] = settings.ALIPAY_RETURN_URL 76 | params['notify_url'] = settings.ALIPAY_NOTIFY_URL 77 | params['_input_charset'] = settings.ALIPAY_INPUT_CHARSET 78 | params['show_url'] = settings.ALIPAY_SHOW_URL 79 | 80 | # 从订单数据中动态获取到的必填参数 81 | params['out_trade_no'] = tn # 请与贵网站订单系统中的唯一订单号匹配 82 | params['subject'] = subject # 订单名称,显示在支付宝收银台里的“商品名称”里,显示在支付宝的交易管理的“商品名称”的列表里。 83 | params['body'] = body # 订单描述、订单详细、订单备注,显示在支付宝收银台里的“商品描述”里 84 | params['total_fee'] = total_fee # 订单总金额,显示在支付宝收银台里的“应付总额”里 85 | 86 | # 扩展功能参数——网银提前 87 | params['paymethod'] = 'directPay' # 默认支付方式,四个值可选:bankPay(网银); cartoon(卡通); directPay(余额); CASH(网点支付) 88 | params['defaultbank'] = '' # 默认网银代号,代号列表见http://club.alipay.com/read.php?tid=8681379 89 | 90 | # 扩展功能参数——防钓鱼 91 | params['anti_phishing_key'] = '' 92 | params['exter_invoke_ip'] = '' 93 | 94 | # 扩展功能参数——自定义参数 95 | params['buyer_email'] = '' 96 | params['extra_common_param'] = '' 97 | 98 | # 扩展功能参数——分润 99 | params['royalty_type'] = '' 100 | params['royalty_parameters'] = '' 101 | 102 | params,prestr = params_filter(params) 103 | 104 | params['sign'] = build_mysign(prestr, settings.ALIPAY_KEY, settings.ALIPAY_SIGN_TYPE) 105 | params['sign_type'] = settings.ALIPAY_SIGN_TYPE 106 | 107 | return _GATEWAY + urlencode(params) 108 | 109 | 110 | # 纯担保交易接口 111 | def create_partner_trade_by_buyer (tn, subject, body, price): 112 | params = {} 113 | # 基本参数 114 | params['service'] = 'create_partner_trade_by_buyer' 115 | params['partner'] = settings.ALIPAY_PARTNER 116 | params['_input_charset'] = settings.ALIPAY_INPUT_CHARSET 117 | params['notify_url'] = settings.ALIPAY_NOTIFY_URL 118 | params['return_url'] = settings.ALIPAY_RETURN_URL 119 | 120 | # 业务参数 121 | params['out_trade_no'] = tn # 请与贵网站订单系统中的唯一订单号匹配 122 | params['subject'] = subject # 订单名称,显示在支付宝收银台里的“商品名称”里,显示在支付宝的交易管理的“商品名称”的列表里。 123 | params['payment_type'] = '1' 124 | params['logistics_type'] = 'POST' # 第一组物流类型 125 | params['logistics_fee'] = '0.00' 126 | params['logistics_payment'] = 'BUYER_PAY' 127 | params['price'] = price # 订单总金额,显示在支付宝收银台里的“应付总额”里 128 | params['quantity'] = 1 # 商品的数量 129 | params['seller_email'] = settings.ALIPAY_SELLER_EMAIL 130 | params['body'] = body # 订单描述、订单详细、订单备注,显示在支付宝收银台里的“商品描述”里 131 | params['show_url'] = settings.ALIPAY_SHOW_URL 132 | 133 | params,prestr = params_filter(params) 134 | 135 | params['sign'] = build_mysign(prestr, settings.ALIPAY_KEY, settings.ALIPAY_SIGN_TYPE) 136 | params['sign_type'] = settings.ALIPAY_SIGN_TYPE 137 | 138 | return _GATEWAY + urlencode(params) 139 | 140 | # 确认发货接口 141 | def send_goods_confirm_by_platform (tn): 142 | params = {} 143 | 144 | # 基本参数 145 | params['service'] = 'send_goods_confirm_by_platform' 146 | params['partner'] = settings.ALIPAY_PARTNER 147 | params['_input_charset'] = settings.ALIPAY_INPUT_CHARSET 148 | 149 | # 业务参数 150 | params['trade_no'] = tn 151 | params['logistics_name'] = u'银河列车' # 物流公司名称 152 | params['transport_type'] = u'POST' 153 | 154 | params,prestr = params_filter(params) 155 | 156 | params['sign'] = build_mysign(prestr, settings.ALIPAY_KEY, settings.ALIPAY_SIGN_TYPE) 157 | params['sign_type'] = settings.ALIPAY_SIGN_TYPE 158 | 159 | return _GATEWAY + urlencode(params) 160 | 161 | def notify_verify(post): 162 | # 初级验证--签名 163 | _,prestr = params_filter(post) 164 | mysign = build_mysign(prestr, settings.ALIPAY_KEY, settings.ALIPAY_SIGN_TYPE) 165 | if mysign != post.get('sign'): 166 | return False 167 | 168 | # 二级验证--查询支付宝服务器此条信息是否有效 169 | params = {} 170 | params['partner'] = settings.ALIPAY_PARTNER 171 | params['notify_id'] = post.get('notify_id') 172 | if settings.ALIPAY_TRANSPORT == 'https': 173 | params['service'] = 'notify_verify' 174 | gateway = 'https://mapi.alipay.com/gateway.do' 175 | else: 176 | gateway = 'http://notify.alipay.com/trade/notify_query.do' 177 | veryfy_result = urlopen(gateway, urlencode(params)).read() 178 | if veryfy_result.lower().strip() == 'true': 179 | return True 180 | return False 181 | 182 | -------------------------------------------------------------------------------- /alipay/config.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | 3 | class settings: 4 | # 安全检验码,以数字和字母组成的32位字符 5 | ALIPAY_KEY = '' 6 | 7 | ALIPAY_INPUT_CHARSET = 'utf-8' 8 | 9 | # 合作身份者ID,以2088开头的16位纯数字 10 | ALIPAY_PARTNER = '' 11 | 12 | # 签约支付宝账号或卖家支付宝帐户 13 | ALIPAY_SELLER_EMAIL = '' 14 | 15 | ALIPAY_SIGN_TYPE = 'MD5' 16 | 17 | # 付完款后跳转的页面(同步通知) 要用 http://格式的完整路径,不允许加?id=123这类自定义参数 18 | ALIPAY_RETURN_URL='' 19 | 20 | # 交易过程中服务器异步通知的页面 要用 http://格式的完整路径,不允许加?id=123这类自定义参数 21 | ALIPAY_NOTIFY_URL='' 22 | 23 | ALIPAY_SHOW_URL='' 24 | 25 | # 访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http 26 | ALIPAY_TRANSPORT='https' 27 | -------------------------------------------------------------------------------- /alipay/hashcompat.py: -------------------------------------------------------------------------------- 1 | """ 2 | The md5 and sha modules are deprecated since Python 2.5, replaced by the 3 | hashlib module containing both hash algorithms. Here, we provide a common 4 | interface to the md5 and sha constructors, preferring the hashlib module when 5 | available. 6 | """ 7 | 8 | try: 9 | import hashlib 10 | md5_constructor = hashlib.md5 11 | md5_hmac = md5_constructor 12 | sha_constructor = hashlib.sha1 13 | sha_hmac = sha_constructor 14 | except ImportError: 15 | import md5 16 | md5_constructor = md5.new 17 | md5_hmac = md5 18 | import sha 19 | sha_constructor = sha.new 20 | sha_hmac = sha 21 | -------------------------------------------------------------------------------- /db/sqlite3.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengli/alipay_python/4fbfe625944f0224d343fd0346589a28af6836ed/db/sqlite3.db -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from django.core.management import execute_manager 3 | try: 4 | import settings # Assumed to be in the same directory. 5 | except ImportError: 6 | import sys 7 | sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) 8 | sys.exit(1) 9 | 10 | if __name__ == "__main__": 11 | execute_manager(settings) 12 | -------------------------------------------------------------------------------- /payment.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengli/alipay_python/4fbfe625944f0224d343fd0346589a28af6836ed/payment.log -------------------------------------------------------------------------------- /payment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengli/alipay_python/4fbfe625944f0224d343fd0346589a28af6836ed/payment/__init__.py -------------------------------------------------------------------------------- /payment/models.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | 3 | from django.db import models 4 | from django.contrib.auth.models import User 5 | from django.contrib import admin 6 | import datetime 7 | 8 | ACCOUNT_TYPE={'free':u'免费账户','bronze':u'付费订阅(bronze)','silver':u'付费订阅(silver)','gold':u'付费订阅(gold)'} 9 | 10 | class Bill (models.Model): 11 | user = models.OneToOneField (User) 12 | account_type = models.CharField (max_length=20, default='free', null=True) 13 | upgrade_type = models.CharField (max_length=20, default='free', null=True) 14 | 15 | # It'll be one of the 4 status ('WAIT_BUYER_PAY', 'WAIT_SELLER_SEND_GOODS', 16 | # 'WAIT_BUYER_CONFIRM_GOODS', 'TRADE_FINISHED', 'TRADE_CLOSED'), the inital 17 | # status will be 'INIT'. 18 | trade_status = models.CharField (max_length=50, default='INIT', null=True) 19 | start_date = models.DateTimeField (default=datetime.datetime(1900,1,1)) 20 | expire_date = models.DateTimeField (default=datetime.datetime(1900,1,1)) 21 | 22 | def __unicode__ (self): 23 | return self.user.username+" "+self.account_type 24 | admin.site.register (Bill) 25 | -------------------------------------------------------------------------------- /payment/urls.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from django.conf.urls.defaults import * 4 | from django.views.generic.simple import direct_to_template 5 | 6 | urlpatterns = patterns('', 7 | url(r'^upgrade/(?P\w+)/$', view = 'payment.views.upgrade_account', name="payment_upgrade_account"), 8 | url(r'^$', direct_to_template, {'template':'payment/plans.html'},name="payment_upgrade_plans"), 9 | url(r'^success/$', direct_to_template, {'template':'payment/success.html'}, name="payment_success"), 10 | url(r'^error/$', direct_to_template, {'template':'payment/error.html'}, name="payment_error"), 11 | url(r'^return_url$', view = 'payment.views.return_url_handler', name="payment_return_url"), 12 | url(r'^notify_url$', view = 'payment.views.notify_url_handler', name="payment_notify_url"), 13 | ) 14 | -------------------------------------------------------------------------------- /payment/views.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | 3 | from django.http import HttpResponseRedirect, HttpResponse 4 | from django.contrib.auth.decorators import login_required 5 | from django.core.urlresolvers import reverse 6 | from alipay.alipay import * 7 | from payment.models import Bill 8 | from settings import LOGGING_PAYMENT 9 | import datetime 10 | import logging 11 | import urllib 12 | 13 | logger1 =logging.getLogger(__name__) 14 | logger1.setLevel(logging.INFO) 15 | logger1.addHandler (logging.FileHandler(LOGGING_PAYMENT)) 16 | 17 | def upgrade_bill (bill, valide_days): 18 | """ 19 | Upgrade bill BILL valide for VALIDE_DAYS from today. And update 20 | bill account_type. 21 | """ 22 | bill.account_type = bill.upgrade_type 23 | start_date = datetime.datetime.now() 24 | expire_date=start_date+datetime.timedelta(days=valide_days) 25 | bill.start_date=start_date 26 | bill.expire_date=expire_date 27 | bill.save() 28 | 29 | @login_required 30 | def upgrade_account (request, acc_type): 31 | """ 32 | Request for upgrade account to acc_type. Redirect to alipay 33 | payment web page due to ACC_TYPE. 34 | """ 35 | user = request.user 36 | bill = None 37 | try: bill = user.bill 38 | except: bill = Bill (user=user) 39 | bill.upgrade_type = acc_type 40 | bill.save() 41 | tn = bill.pk 42 | if acc_type == "bronze": 43 | url=create_partner_trade_by_buyer (tn, u'ikindle杂志订阅(4份)', 44 | u'订阅杂志到你的Kindle, 2.99x6个月', '0.01') 45 | return HttpResponseRedirect (url) 46 | elif acc_type == "silver": 47 | url=create_partner_trade_by_buyer (tn, u'ikindle杂志订阅(6份)', 48 | u'订阅杂志到你的Kindle,3.99x6个月', '0.01') 49 | return HttpResponseRedirect (url) 50 | elif acc_type == "gold": 51 | url=create_partner_trade_by_buyer (tn, u'ikindle杂志订阅(无限制)', 52 | u'订阅杂志到你的Kindle,5.99x6个月', '0.01') 53 | return HttpResponseRedirect (url) 54 | else: 55 | return HttpResponseRedirect (reverse ('payment_error')) 56 | 57 | from django.views.decorators.csrf import csrf_exempt 58 | @csrf_exempt 59 | def notify_url_handler (request): 60 | """ 61 | Handler for notify_url for asynchronous updating billing information. 62 | Logging the information. 63 | """ 64 | logger1.info ('>>notify url handler start...') 65 | if request.method == 'POST': 66 | if notify_verify (request.POST): 67 | logger1.info ('pass verification...') 68 | tn = request.POST.get('out_trade_no') 69 | logger1.info('Change the status of bill %s'%tn) 70 | bill = Bill.objects.get (pk=tn) 71 | trade_status = request.POST.get('trade_status') 72 | logger1.info('the status of bill %s changed to %s'% (tn,trade_status)) 73 | bill.trade_status = trade_status 74 | bill.save () 75 | trade_no=request.POST.get('trade_no') 76 | if trade_status == 'WAIT_SELLER_SEND_GOODS': 77 | logger1.info ('It is WAIT_SELLER_SEND_GOODS, so upgrade bill') 78 | upgrade_bill (bill, 6*30+7) 79 | url = send_goods_confirm_by_platform (trade_no) 80 | logger1.info('send goods confirmation. %s'%url) 81 | req=urllib.urlopen (url) 82 | return HttpResponse("success") 83 | else: 84 | logger1.info ('##info: Status of %s' % trade_status) 85 | return HttpResponse ("success") 86 | return HttpResponse ("fail") 87 | 88 | def return_url_handler (request): 89 | """ 90 | Handler for synchronous updating billing information. 91 | """ 92 | logger1.info('>> return url handler start') 93 | if notify_verify (request.GET): 94 | tn = request.GET.get('out_trade_no') 95 | trade_no = request.GET.get('trade_no') 96 | logger1.info('Change the status of bill %s'%tn) 97 | bill = Bill.objects.get (pk=tn) 98 | trade_status = request.GET.get('trade_status') 99 | logger1.info('the status changed to %s'%trade_status) 100 | bill.trade_status = trade_status 101 | upgrade_bill (bill, 30*6+7) 102 | url=send_goods_confirm_by_platform (trade_no) 103 | req=urllib.urlopen (url) 104 | logger1.info('send goods confirmation. %s'%url) 105 | return HttpResponseRedirect (reverse ('payment_success')) 106 | return HttpResponseRedirect (reverse ('payment_error')) 107 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | # Django settings for alipay_python project. 2 | import os 3 | 4 | CUR_DIR = os.path.dirname(__file__) 5 | ROOT_PATH = os.path.dirname (CUR_DIR) 6 | 7 | DEBUG = True 8 | TEMPLATE_DEBUG = DEBUG 9 | 10 | ADMINS = ( 11 | # ('Your Name', 'your_email@domain.com'), 12 | ) 13 | 14 | MANAGERS = ADMINS 15 | 16 | DATABASES = { 17 | 'default': { 18 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 19 | 'NAME': os.path.join (CUR_DIR, 'db/sqlite3.db'), # Or path to database file if using sqlite3. 20 | 'USER': '', # Not used with sqlite3. 21 | 'PASSWORD': '', # Not used with sqlite3. 22 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 23 | 'PORT': '', # Set to empty string for default. Not used with sqlite3. 24 | } 25 | } 26 | 27 | # Local time zone for this installation. Choices can be found here: 28 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 29 | # although not all choices may be available on all operating systems. 30 | # On Unix systems, a value of None will cause Django to use the same 31 | # timezone as the operating system. 32 | # If running in a Windows environment this must be set to the same as your 33 | # system time zone. 34 | TIME_ZONE = 'America/Chicago' 35 | 36 | # Language code for this installation. All choices can be found here: 37 | # http://www.i18nguy.com/unicode/language-identifiers.html 38 | LANGUAGE_CODE = 'en-us' 39 | 40 | SITE_ID = 1 41 | 42 | # If you set this to False, Django will make some optimizations so as not 43 | # to load the internationalization machinery. 44 | USE_I18N = True 45 | 46 | # If you set this to False, Django will not format dates, numbers and 47 | # calendars according to the current locale 48 | USE_L10N = True 49 | 50 | # Absolute path to the directory that holds media. 51 | # Example: "/home/media/media.lawrence.com/" 52 | MEDIA_ROOT = '' 53 | 54 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 55 | # trailing slash if there is a path component (optional in other cases). 56 | # Examples: "http://media.lawrence.com", "http://example.com/media/" 57 | MEDIA_URL = '' 58 | 59 | # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a 60 | # trailing slash. 61 | # Examples: "http://foo.com/media/", "/media/". 62 | ADMIN_MEDIA_PREFIX = '/media/' 63 | 64 | # Make this unique, and don't share it with anybody. 65 | SECRET_KEY = '4@whpmcqsh=o_jn9m-_ysg)-d-qd80pacsd1q-ihhe(89!!i((' 66 | 67 | # List of callables that know how to import templates from various sources. 68 | TEMPLATE_LOADERS = ( 69 | 'django.template.loaders.filesystem.Loader', 70 | 'django.template.loaders.app_directories.Loader', 71 | # 'django.template.loaders.eggs.Loader', 72 | ) 73 | 74 | MIDDLEWARE_CLASSES = ( 75 | 'django.middleware.common.CommonMiddleware', 76 | 'django.contrib.sessions.middleware.SessionMiddleware', 77 | 'django.middleware.csrf.CsrfViewMiddleware', 78 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 79 | 'django.contrib.messages.middleware.MessageMiddleware', 80 | ) 81 | 82 | ROOT_URLCONF = 'alipay_python.urls' 83 | 84 | TEMPLATE_DIRS = ( 85 | os.path.join (ROOT_PATH, "alipay_python/templates") 86 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 87 | # Always use forward slashes, even on Windows. 88 | # Don't forget to use absolute paths, not relative paths. 89 | ) 90 | 91 | INSTALLED_APPS = ( 92 | 'django.contrib.auth', 93 | 'django.contrib.contenttypes', 94 | 'django.contrib.sessions', 95 | 'django.contrib.sites', 96 | 'django.contrib.messages', 97 | # Uncomment the next line to enable the admin: 98 | 'django.contrib.admin', 99 | # Uncomment the next line to enable admin documentation: 100 | # 'django.contrib.admindocs', 101 | 'payment', 102 | 'accounts', 103 | ) 104 | 105 | LOGGING_PAYMENT = 'payment.log' 106 | -------------------------------------------------------------------------------- /templates/payment/error.html: -------------------------------------------------------------------------------- 1 |

ops...出了点儿问题

2 | -------------------------------------------------------------------------------- /templates/payment/plans.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PLANS 5 | 6 | 7 |
8 |

订阅我们的付费服务

9 |

支付宝担保交易,你可以在 7 天内随时取消订阅

10 |
11 |

一杯咖啡的价格, 订阅半年

12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 33 | 34 | 35 |
订阅 不限量 份杂志 ¥5.99/月 17 | 订阅 18 |
19 | 半年起定: ¥0.01 20 |
订阅 6 份杂志 ¥3.99/月订阅
半年起定: ¥0.01
订阅 4 份杂志 ¥2.99/月 29 | 订阅 30 |
31 | 半年起定: ¥0.01 32 |
36 |
37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /templates/payment/success.html: -------------------------------------------------------------------------------- 1 |

付款成功!

2 | -------------------------------------------------------------------------------- /templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base_site.html" %} 2 | {% load i18n %} 3 | 4 | {% block extrastyle %}{% load adminmedia %}{{ block.super }}{% endblock %} 5 | 6 | {% block bodyclass %}login{% endblock %} 7 | 8 | {% block content_title %}{% endblock %} 9 | 10 | {% block breadcrumbs %}{% endblock %} 11 | 12 | {% block content %} 13 | {% if error_message %} 14 |

{{ error_message }}

15 | {% endif %} 16 |
17 |
{% csrf_token %} 18 |
19 | 20 |
21 |
22 | 23 | 24 |
25 |
26 | 27 |
28 |
29 | 30 | 33 |
34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | import settings 3 | 4 | from django.contrib import admin 5 | 6 | admin.autodiscover() 7 | 8 | urlpatterns = patterns('', 9 | # Example: 10 | (r'^', include('alipay_python.payment.urls')), 11 | # (r'^media/(?P.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }), 12 | (r'^admin/', include(admin.site.urls)), 13 | (r'^accounts/', include('alipay_python.accounts.urls')), 14 | ) 15 | --------------------------------------------------------------------------------