Skip to content

Commit

Permalink
add payment
Browse files Browse the repository at this point in the history
  • Loading branch information
elfgzp committed Aug 21, 2017
1 parent b9f4f6c commit ad81c3b
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.pyc
odoo-bin.py
1 change: 1 addition & 0 deletions __manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
'views/wechat_mall_deliver_wizard_views.xml',
'views/webclient_templates.xml',
'data/order_num_sequence.xml',
'data/payment_num_sequence.xml',
'data/mail_template.xml',
],
# only loaded in demonstration mode
Expand Down
1 change: 1 addition & 0 deletions controllers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
from . import wechat_user
from . import address
from . import order
from . import payment
137 changes: 137 additions & 0 deletions controllers/payment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# -*- coding: utf-8 -*-

import json
import xmltodict

from odoo import http, exceptions
from odoo.http import request

from .error_code import error_code
from .. import defs

from weixin.pay import WeixinPay

import logging

_logger = logging.getLogger(__name__)


class MakePayment(http.Controller):
@http.route('/<string:sub_domain>/pay/wxapp/get-pay-data',
auth='public', methods=['POST'], csrf=False, type='http')
def post(self, sub_domain, **kwargs):
try:
user = request.env['res.users'].sudo().search([('sub_domain', '=', sub_domain)])
if not user:
return request.make_response(json.dumps({'code': 404, 'msg': error_code[404]}))

config = self.env['wechat_mall.config.settings']
app_id = config.get_config('app_id', uid=user.id)
wechat_pay_id = config.get_config('wechat_pay_id', uid=user.id)
wechat_pay_secret = config.get_config('wechat_pay_id', uid=user.id)

if not app_id:
return request.make_response(json.dumps({'code': 404, 'msg': error_code[404]}))

if not wechat_pay_id or wechat_pay_secret:
return request.make_response(json.dumps({'code': 404, 'msg': '未设置wechat_pay_id和wechat_pay_secret'}))

if 'token' not in kwargs.keys():
return request.make_response(json.dumps({'code': 300, 'msg': error_code[300].format('token')}))

token = kwargs.pop('token')

args_key_set = {'token', 'order_id', 'money'}

missing_args_key = args_key_set - set(kwargs.keys())
if missing_args_key:
return request.make_response(json.dumps({'code': 600, 'msg': error_code[600]}))

access_token = request.env(user=user.id)['wechat_mall.access_token'].search([
('token', '=', token),
('create_uid', '=', user.id)
])

if not access_token:
return request.make_response(json.dumps({'code': 901, 'msg': error_code[901]}))

wechat_user = request.env(user=user.id)['wechat_mall.user'].search([
('open_id', '=', access_token.open_id),
('create_uid', '=', user.id)
])

if not wechat_user:
return request.make_response(json.dumps({'code': 10000, 'msg': error_code[10000]}))

wxpay = WeixinPay(appid=app_id, mch_id=wechat_pay_id, partner_key=wechat_pay_secret)

except Exception as e:
_logger.exception(e)
return request.make_response(json.dumps({'code': -1, 'msg': error_code[-1], 'data': e.message}))


class WechatPaymentNotify(http.Controller):
@http.route('/<string:sub_domain>/pay/notify',
auth='public', methods=['POST', 'GET'], csrf=False, type='http')
def post(self, sub_domain, **kwargs):
try:
user = request.env['res.users'].sudo().search([('sub_domain', '=', sub_domain)])
if not user:
response = request.make_response(
headers={
"Content-Type": "application/xml"
},
data=xmltodict.unparse({
'xml': {
'return_code': 'FAIL',
'return_msg': '参数格式校验错误'
}
})
)
return response

xml_data = request.httprequest.stream.read()
data = xmltodict.parse(xml_data)['xml']
if data['return_code'] == 'SUCCESS':
data.update({'status': defs.PaymentStatus.success})
payment = request.env(user=user.id)['wechat_mall.payment'].search([
('payment_number', '=', data['out_trade_no'])
])
payment.write(data)
payment.order_id.write({'status': defs.OrderStatus.pending})
mail_template = request.env.ref('wechat_mall.wechat_mall_order_paid')
mail_template.sudo().send_mail(payment.order_id.id, force_send=True, raise_exception=False)
else:
data.update({'status': defs.PaymentStatus.fail})
payment = request.env(user=user.id)['wechat_mall.payment'].search([
('payment_number', '=', data['out_trade_no'])
])
payment.write(data)

response = request.make_response(
headers={
"Content-Type": "application/xml"
},
data=xmltodict.unparse({
'xml': {
'return_code': 'SUCCESS',
'return_msg': 'SUCCESS'
}
})
)
return response

except Exception as e:
_logger.exception(e)
response = request.make_response(
headers={
"Content-Type": "application/xml"
},
data=xmltodict.unparse({
'xml': {
'return_code': 'FAIL',
'return_msg': '服务器内部错误'
}
})
)
return response
13 changes: 13 additions & 0 deletions data/payment_num_sequence.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">

<record id="seq_wechat_mall_payment_payment_num" model="ir.sequence">
<field name="name">Wechat mall payment num</field>
<field name="code">wechat_mall.payment_num</field>
<field name="padding">4</field>
<field name="prefix">PY%(y)s%(month)s%(day)s%(h24)s%(min)s%(sec)s</field>
</record>

</data>
</odoo>
6 changes: 6 additions & 0 deletions defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,9 @@ class OrderResponseStatus(Const):
unconfirmed = ('unconfirmed', 2)
unevaluated = ('unevaluated', 3)
completed = ('completed', 4)


class PaymentStatus(Const):
unpaid = ('unpaid', '未支付')
success = ('success', '成功')
fail = ('fail', '失败')
1 change: 1 addition & 0 deletions models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
from . import confirm_wizard
from . import shipper
from . import mail_template
from . import payment
6 changes: 6 additions & 0 deletions models/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ class Order(models.Model):
display_traces = fields.Html('物流信息', compute='_compute_display_traces')
traces = fields.Text('物流信息', compute='_compute_traces')

_sql_constraints = [(
'wechat_mall_order_order_num_unique',
'UNIQUE (order_num)',
'wechat order order_num is existed!'
)]

@api.model
def create(self, vals):
vals['order_num'] = self.env['ir.sequence'].next_by_code('wechat_mall.order_num')
Expand Down
43 changes: 43 additions & 0 deletions models/payment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-

from odoo import models, fields, api

from .. import defs


class Payment(models.Model):
_name = 'wechat_mall.payment'
_description = u'支付记录'

order_id = fields.Many2one('wechat_mall.order', string='订单')
payment_number = fields.Char('支付单号', index=True)
wechat_user_id = fields.Many2one('wechat_mall.user', string='微信用户')
price = fields.Float('支付金额')
status = fields.Selection(defs.PaymentStatus.attrs.items(), '状态',
default=defs.PaymentStatus.unpaid)

# 微信notify返回参数
openid = fields.Char('openid')
result_code = fields.Char('业务结果')
err_code = fields.Char('错误代码')
err_code_des = fields.Char('错误代码描述')
transaction_id = fields.Char('微信订单号')
bank_type = fields.Char('付款银行')
fee_type = fields.Char('货币种类')
total_fee = fields.Integer('订单金额(分)')
settlement_total_fee = fields.Integer('应结订单金额(分)')
cash_fee = fields.Integer('现金支付金额')
cash_fee_type = fields.Char('现金支付货币类型')
coupon_fee = fields.Integer('代金券金额(分)')
coupon_count = fields.Integer('代金券使用数量')

_sql_constraints = [(
'wechat_mall_payment_payment_number_unique',
'UNIQUE (payment_number)',
'wechat payment payment_number is existed!'
)]

@api.model
def create(self, vals):
vals['payment_num'] = self.env['ir.sequence'].next_by_code('wechat_mall.payment_num')
return super(Payment, self).create(vals)
34 changes: 0 additions & 34 deletions tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,37 +36,3 @@ def get_wechat_user_info(app_id, secret, code, encrypted_data, iv):
user_info = crypt.decrypt(encrypted_data, iv)
return session_key, user_info

# def verify_wxapp(encrypted_data, iv, code):
# user_info = get_wechat_user_info(encrypted_data, iv, code)
# # 获取 openid
# openid = user_info.get('openId', None)
# if openid:
# auth = Account.get_by_wxapp(openid)
# if not auth:
# raise Unauthorized('wxapp_not_registered')
# return auth
# raise Unauthorized('invalid_wxapp_code')
#
# def create_token(request):
# # verify basic token
# approach = request.json.get('auth_approach')
# username = request.json['username']
# password = request.json['password']
# if approach == 'password':
# account = verify_password(username, password)
# elif approach == 'wxapp':
# account = verify_wxapp(username, password, request.args.get('code'))
# if not account:
# return False, {}
# payload = {
# "iss": Config.ISS,
# "iat": int(time.time()),
# "exp": int(time.time()) + 86400 * 7,
# "aud": Config.AUDIENCE,
# "sub": str(account['_id']),
# "nickname": account['nickname'],
# "scopes": ['open']
# }
# token = jwt.encode(payload, 'secret', algorithm='HS256')
# # 由于 account 中 _id 是一个 object 需要转化成字符串
# return True, {'access_token': token, 'account_id': str(account['_id'])}

0 comments on commit ad81c3b

Please sign in to comment.