Django小程序微信支付与微信退款
1.微信支付
1.1前期准备
需要准备微信支付的配置参数
client_appid
= ''
client_secret
= ''
Mch_id
= ''
Mch_key
= ''
order_url
= 'https://api.mch.weixin.qq.com/pay/unifiedorder'
1.2用户下单
from django
.db
import transaction
@transaction
.atomic 添加事务
def place_order(request
):
if request
.method
== 'POST':
r
= json
.loads
(request
.body
.decode
())
user
= int(r
['user_id'])
good_id
= r
['good_id']
good_obj
= models
.Goods
.objects
.get
(gid
=good_id
)
unit_price
= float(good_obj
.now_price
)
unit_freight
= float(good_obj
.freight
)
money
= unit_price
*int(num
) + unit_freight
openid
= getOpenid
(user
)
client_ip
= 'xxx.xxx.xxx.xx'
print(request
.get_host
())
url
= order_url
body_data
,out_trade_no
= get_bodyData
(openid
, client_ip
, money
, user
)
timeStamp
= str(int(time
.time
()))
import requests
respone
= requests
.post
(url
, body_data
.encode
("utf-8"), headers
={'Content-Type': 'application/xml'})
content
= xml_to_dict
(respone
.content
)
ret
= {"state": 1000}
sid
= transaction
.savepoint
()
if content
["return_code"] == 'SUCCESS':
prepay_id
= content
.get
("prepay_id")
package
= 'prepay_id='+prepay_id
nonceStr
= content
.get
("nonce_str")
paySign
= get_paysign
(prepay_id
, timeStamp
, nonceStr
)
res_dict
= {'rcode': 200, 'package': package
, 'paysign': paySign
, 'timestamp': timeStamp
,
'nonceStr': nonceStr
, 'appId': client_appid
, 'orderNumber': out_trade_no
}
print('=========', res_dict
)
try:
order
= models
.Goods_Order
.objects
.create
(
good_id
=good_id
,
user_id
=user
,
num
=num
,
unit_price
= unit_price
,
unit_freight
=unit_freight
,
money
=money
,
order_number
=out_trade_no
,
.,
.,
.,
.,
)
order_obj
= models
.Goods_Order
.objects
.get
(order_number
=out_trade_no
)
for v
in avid
:
models
.Order2Attr
.objects
.create
(
order_id
=order
.goid
,
attr_value_id
=int(v
)
)
av_obj
= models
.Attr_Value
.objects
.get
(avid
=int(v
))
av_obj
.stocks
= F
('stocks')-int(num
)
av_obj
.save
()
order_detail
= models
.Order_Detail
.objects
.update_or_create
(
order_id
=order_obj
.goid
,
payment
=0,
receipt
=-1,
aftersale
=0
)
good
= models
.Goods
.objects
.get
(gid
=good_id
)
good
.stocks
= F
('stocks')-int(num
)
good
.save
()
return JsonResponse
(res_dict
,safe
=False)
except Exception
as e
:
print(e
)
transaction
.savepoint_rollback
(sid
)
return JsonResponse
({'msg':'下单失败'},safe
=False)
transaction
.clean_savepoints
()
else:
ret
["rcode"] = 500
ret
["msg"] = "下单失败"
return JsonResponse
(ret
,safe
=False)
def getOpenid(userid
):
userData
= models
.User
.objects
.get
(uid
=int(userid
))
return userData
.openID
def random_str(randomlength
=32):
str = ''
chars
= 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
length
= len(chars
) - 1
random
= Random
()
for i
in range(randomlength
):
str+=chars
[random
.randint
(0, length
)]
return str
def paysign(appid
, body
, mch_id
, nonce_str
, notify_url
, openid
, out_trade_no
, spbill_create_ip
, total_fee
):
ret
= {
"appid": appid
,
"body": body
,
"mch_id": mch_id
,
"nonce_str": nonce_str
,
"notify_url": notify_url
,
"openid": openid
,
"out_trade_no": out_trade_no
,
"spbill_create_ip": spbill_create_ip
,
"total_fee": total_fee
,
"trade_type": 'JSAPI'
}
print(ret
)
stringA
= '&'.join
(["{0}={1}".format(k
, ret
.get
(k
)) for k
in sorted(ret
)])
stringSignTemp
= '{0}&key={1}'.format(stringA
, Mch_key
)
sign
= hashlib
.md5
(stringSignTemp
.encode
("utf-8")).hexdigest
()
print(sign
.upper
())
return sign
.upper
()
def xml_to_dict(xml_data
):
'''
xml to dict
:param xml_data:
:return:
'''
xml_dict
= {}
root
= ET
.fromstring
(xml_data
)
for child
in root
:
xml_dict
[child
.tag
] = child
.text
return xml_dict
def getWxPayOrdrID(user
):
date
= datetime
.datetime
.now
()
payOrdrID
= date
.strftime
("%Y%m%d%H%M%S%f")
payOrdrID
= str(user
)+payOrdrID
return payOrdrID
def get_paysign(prepay_id
, timeStamp
, nonceStr
):
pay_data
= {
'appId': client_appid
,
'nonceStr': nonceStr
,
'package': "prepay_id=" + prepay_id
,
'signType': 'MD5',
'timeStamp': timeStamp
}
stringA
= '&'.join
(["{0}={1}".format(k
, pay_data
.get
(k
)) for k
in sorted(pay_data
)])
stringSignTemp
= '{0}&key={1}'.format(stringA
, Mch_key
)
sign
= hashlib
.md5
(stringSignTemp
.encode
("utf-8")).hexdigest
()
return sign
.upper
()
def get_bodyData(openid
, client_ip
, price
, user
):
body
= 'Mytest'
notify_url
= 'http://www.xxx.com/goodorderNotify/'
nonce_str
= random_str
()
out_trade_no
= getWxPayOrdrID
(user
)
total_fee
= str(int(float(price
)*100))
sign
= paysign
(client_appid
, body
, Mch_id
, nonce_str
, notify_url
, openid
, out_trade_no
, client_ip
, total_fee
)
bodyData
= '<xml>'
bodyData
+= '<appid>' + client_appid
+ '</appid>'
bodyData
+= '<body>' + body
+ '</body>'
bodyData
+= '<mch_id>' + Mch_id
+ '</mch_id>'
bodyData
+= '<nonce_str>' + nonce_str
+ '</nonce_str>'
bodyData
+= '<notify_url>' + notify_url
+ '</notify_url>'
bodyData
+= '<openid>' + openid
+ '</openid>'
bodyData
+= '<out_trade_no>' + out_trade_no
+ '</out_trade_no>'
bodyData
+= '<spbill_create_ip>' + client_ip
+ '</spbill_create_ip>'
bodyData
+= '<total_fee>' + total_fee
+ '</total_fee>'
bodyData
+= '<trade_type>JSAPI</trade_type>'
bodyData
+= '<sign>' + sign
+ '</sign>'
bodyData
+= '</xml>'
return bodyData
, out_trade_no
2.微信退款
1.1前期准备
微信支付平台–》账户中心 – 》API安全 – 》 API证书,弄到手以后解压存放在后端
我放在了和app同级的目录里
1.2用户退款
def refund_api(request
):
if request
.method
== 'POST':
print(111)
order_id
= int(request
.POST
.get
('order_id',''))
refund_fee
= str(request
.POST
.get
('refund_fee',''))
result
= dict()
order_obj
= models
.Goods_Order
.objects
.get
(goid
=order_id
)
out_refund_no
= getWxPayOrdrID
(order_obj
.user_id
)
trade_no
= order_obj
.order_number
now
= datetime
.datetime
.now
().strftime
('%Y-%m-%d %H:%M:%S')
After_obj
= models
.AfterSale
.objects
.filter(order_id
=order_id
).update
(
retund_time
=now
,
refund_number
=out_refund_no
,
)
total_fee
= int(float(order_obj
.money
)*100)
refund_fee
= int(float(refund_fee
)*100)
res
= refund
(trade_no
, out_refund_no
, total_fee
, refund_fee
, order_id
)
if res
['flag'] == True:
result
['flag'] = True
else:
pass
return JsonResponse
(result
,safe
=False)
def refund(trade_no
, out_refund_no
, total_fee
, refund_fee
,order_id
):
'''
:param trade_no: 创建订单时自动生成的订单号
:param out_refund_no: 商户退款单号
:param total_fee: 订单金额
:param refund_fee: 退款金额
:return:
'''
info
= {
'appid':client_appid
,
'mch_id':Mch_id
,
'out_trade_no':trade_no
,
'nonce_str':random_str
(),
'sign_type':'MD5',
'out_refund_no':out_refund_no
,
'total_fee':total_fee
,
'refund_fee':refund_fee
}
key
= Mch_key
string
= "&".join
([f
"{k}={info[k]}" for k
in sorted(info
)] + [f
"{'key'}={key}"])
info
['sign'] = md5
(string
).upper
()
xml
= "<xml>{}</xml>".format("".join
([f
"<{k}>{v}</{k}>" for k
,v
in info
.items
()]))
cert
= f
"{settings.BASE_DIR}/cert/apiclient_cert.pem"
key
= f
"{settings.BASE_DIR}/cert/apiclient_key.pem"
import requests
res
= requests
.post
(
url
= 'https://api.mch.weixin.qq.com/secapi/pay/refund',
data
=xml
.encode
('utf-8'),
headers
={
'Accept-Language':'zh-CN,zh;q=0.9'
},
cert
=(cert
,key
),
verify
=True
)
r
= res
.text
.encode
('ISO-8859-1').decode
('utf-8')
response
= xmltodict
.parse
(r
)
result
= dict()
print(response
)
if response
['xml']['return_code'] == 'SUCCESS':
detail_obj
= models
.Order_Detail
.objects
.filter(order_id
=order_id
).update
(aftersale
=2)
now
= datetime
.datetime
.now
().strftime
('%Y-%m-%d %H:%M:%S')
after_obj
= models
.AfterSale
.objects
.filter(order_id
=order_id
).update
(
received_time
=now
,
refund_result
=3,
refund_fee
=refund_fee
)
result
['flag'] = True
else:
result
['flag'] = False
return result
转载请注明原文地址: https://lol.8miu.com/read-15670.html