微信app支付python代碼(使用weixin-python==0.5.4)
微信app支付python代碼(python2)
python3應該差不多,
官方文檔:
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1
業務流程:
商戶系統和微信支付系統主要交互說明:
#步驟1:用戶在商戶APP中選擇商品,提交訂單,選擇微信支付。
用戶在app頁面選擇商品,確定數量,提交訂單,提供必要的參數
app支付需要的前端參數
1. body 商品描述
2. total_fee 商品價格
#步驟2: 商戶后台生成本地訂單
生成訂單號,保證唯一性
order_sn = "%s%s%s" % (request.user.id, datetime.datetime.now().strftime('%Y%m%d%H%M%S'),
random.randint(1, 99))
根據訂單號,生成本地訂單(生成訂單對象,訂單狀態肯定是未支付,支付成功的回調時再改為支付成功狀態)
def generate_order(user, post_data, order_sn, nickname, openid):
good_kind = post_data.get("good_kind")
good_id = post_data.get('good_id')
paid_amount = post_data.get('paid_amount', 0)
try:
good_kind = int(good_kind)
good_id = int(good_id)
paid_amount = float(paid_amount)
#1 課程 2 會員卡
if good_kind == 1:
course = Course.objects.get(pk=good_id)
record = Record.objects.create(
user=user, course=course, telephone=user.phone, center=get_center_for_appid(),
price=paid_amount, order_sn=order_sn, nickname=nickname, openid=openid)
if not paid_amount:
record.status = 2
record.save()
elif good_kind == 2:
card = Vip.objects.get(pk=good_id)
record = Record.objects.create(
user=user, card=card, price=paid_amount, center=get_center_for_appid(),
order_sn=order_sn, nickname=nickname, telephone=user.phone, openid=openid)
else:
record = None
except Exception as e:
record = None
return record
#步驟3:調用微信支付統一下單接口。參見【統一下單API】。
使用pip install weixin-python==0.5.4(模塊)
1.導入from weixin import Weixin
2.初始化(https://www.cnblogs.com/gjh99/p/10536905.html)
we_chat = Weixin(dict(
#app_id 微信開放平台審核通過的應用APPID(請登錄open.weixin.qq.com查看,注意與公眾號的APPID不同)
WEIXIN_APP_ID=WECHAT_APP_ID,
#mch_id 微信支付分配的商戶號
WEIXIN_MCH_ID=WECHAT_MCH_ID,
#mch_key 微信支付密鑰
WEIXIN_MCH_KEY=WECHAT_MCH_KEY,
#回調url
WEIXIN_NOTIFY_URL=WECHAT_NOTIFY_URL,
#公鑰文件
WEIXIN_MCH_KEY_FILE='',
#私鑰文件
WEIXIN_MCH_CERT_FILE=''
))
3.調用模塊封裝好的方法
必傳的參數如下,微信的支付為分
jsdict = we_chat.jsapi(
#訂單號
out_trade_no=order_sn,
#商品描述
body=body,
#支付金額
total_fee=int(float(total_fee)*100),
#交易類型
trade_type='APP'
)
4.接收微信后台返回的數據字典jsdict,需要返回給前台
{
"status": 1,
"data": {
"appId": "你的appid",
"package": "prepay_id=wx11162703519516e69f7864b91520314800",
"prepay_id": "wx11162703519516e69f7864b91520314800",
"timeStamp": "1576052824",
"nonceStr": "pqfQOyiMs8d9aAqhS7g8n9WCCyjHPYc6",
"signType": "MD5",
"sign": "396451156447F8DB4590E4ADE5C041AD"
}
}
5.微信app支付需要重新生成簽名
統一下單接口返回正常的prepay_id,再按簽名規范重新生成簽名后,將數據傳輸給APP。參與簽名的字段名為appid,partnerid,prepayid,noncestr,timestamp,package。注意:package的值格式為Sign=WXPay
new_sign = app_pay_sign(jsdict, we_chat)
#注意 字典的參數要跟微信要求的一模一樣,就是data的key要完全和下面的代碼一樣
def app_pay_sign(jsdict, we_chat):
try:
data = dict()
data["appid"] = jsdict["appId"]
data["partnerid"] = WECHAT_MCH_ID
data["prepayid"] = jsdict["prepay_id"]
data["noncestr"] = jsdict["nonceStr"]
data["timestamp"] = jsdict["timeStamp"]
data["package"] = jsdict["package"]
return we_chat.sign(data)
except KeyError:
return
6. 重新簽名后將數據返回給前端,后台就算完成了
jsdict["sign"] = new_sign
7. 寫回調函數
@api_view(['POST'])
@permission_classes([AllowAny])
def wechat_callback(request):
if request.method == 'POST':
try:
data = we_chat.to_dict(request.body)
order_sn = data.get('out_trade_no', '')
# 支付結果,用戶正常支付,會返回SUCCESS
result_code = data.get('result_code', '')
# check 檢查微信回傳數據是否可靠
if not we_chat.check(data):
return HttpResponse(we_chat.reply("簽名驗證失敗", False))
if result_code == 'SUCCESS':
return HttpResponse(we_chat.reply("OK", True), content_type='text/xml')
except Exception as e:
return HttpResponse(we_chat.reply("簽名驗證失敗", False), content_type='text/xml')
#后台python代碼
class WeChatPayViewSet(viewsets.ViewSet):
permission_classes = (IsAuthenticated,)
@list_route(methods=["POST"])
def app_pay(self, request, *args, **kwargs):
try:
post_data = request.DATA
body = post_data.get('body', '微信支付測試')
total_fee = post_data.get('total_fee', 0.01)
if not total_fee:
return Response({"status": 0, "errormsg": "缺少參數"})
# 訂單號生成規則:用戶id+當前時間+隨機數
order_sn = "%s%s%s" % (request.user.id, datetime.datetime.now().strftime('%Y%m%d%H%M%S'),
random.randint(1, 99))
# 生成本地訂單
order = generate_order()
jsdict = we_chat.jsapi(out_trade_no=order_sn, body=body, total_fee=int(float(total_fee)*100),
trade_type='APP')
jsdict["prepay_id"] = jsdict.get("package").split("=")[-1]
new_sign = app_pay_sign(jsdict, we_chat)
if not new_sign:
return Response({"status": 0, "errormsg": "調用微信統一下單接口失敗,缺少必要參數"})
jsdict["sign"] = new_sign
return Response({"status": 1, "data": jsdict})
except Exception as e:
return Response({"status": 0, "errormsg": e})
#步驟4:商戶APP調起微信支付。api參見本章節【app端開發步驟說明】
#步驟5:商戶后台接收支付通知。api參見【支付結果通知API】
#步驟6:商戶后台查詢支付結果。,api參見【查詢訂單API】