国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Django整合微信h5支付

    終于在踩完了無數(shù)坑之后,發(fā)現(xiàn)這個(gè)流程必須記錄下來。在這之前,本人不僅嘗試過網(wǎng)上各種各樣的帖子,也參考了微信支付的官方文檔,都最后都是發(fā)現(xiàn):要么難以理解,要么甚至按照微信支付的官方文檔也會(huì)遇到問題。

    雖然如果完全參考官方的文檔會(huì)被誤導(dǎo),但是其中一部分還是可以參考的。

    首先來看要準(zhǔn)備的環(huán)境:

    1.認(rèn)證的微信公眾號(hào),并且開通了微信支付

    2.開通商戶平臺(tái)賬號(hào)

    3.帶域名的服務(wù)器

    以上三點(diǎn)是對(duì)接微信h5支付的前提條件,接下來我們可以參考微信支付的官方文檔:由于是h5頁(yè)面調(diào)用的微信支付,所以這里點(diǎn)擊鏈接后選擇JSAPI支付。在統(tǒng)一下單的列表中,微信給出了需要請(qǐng)求的API以及參數(shù)。由于我參考的其他的技術(shù)貼自己請(qǐng)求微信的API一直沒成功,所以最后我還是直接調(diào)用了微信官方對(duì)支付封裝好的代碼,代碼可以在github上下載。下載好之后,需要分別將weixin文件夾中的config.py、lib.py和pay.py腳本文件拷貝到我們的工程目錄下??截愅瓿珊髮?duì)這些腳本文件稍作配置:

    config.py腳本中需要配置的都是些微信公眾號(hào)的信息,像APPID、APPSECRET等,其中都有注釋。登錄到微信公眾平臺(tái),在基本配置中可以看到一下信息:

    

    這里就有APPID、APPSECRET和TOKEN,服務(wù)器地址要配置成服務(wù)器上的一個(gè)接口(服務(wù)器帶上域名),在提交配置的時(shí)候微信會(huì)對(duì)我們配置的這個(gè)接口發(fā)送一個(gè)請(qǐng)求,接口需要接收微信傳來的參數(shù)以及返回正確的響應(yīng)才能配置成功。服務(wù)器上的接口如下:

  1. class WXRest(APIView):
  2. authentication_classes = []
  3. permission_classes = []
  4. def get(self, request):
  5. signature = request.GET.get('signature')
  6. timestamp = request.GET.get('timestamp')
  7. nonce = request.GET.get('nonce')
  8. echostr = request.GET.get('echostr')
  9. wechat_instance = WechatBasic(conf=wxConf)
  10. if not wechat_instance.check_signature(signature=signature, timestamp=timestamp, nonce=nonce):
  11. return HttpResponseBadRequest('Verify Failed')
  12. else:
  13. return HttpResponse(echostr, content_type="application/json")

    wxConf的配置如下:

  1. wxConf = WechatConf(
  2. token='xxxxxx',
  3. appid=SOCIAL_AUTH_WEIXIN_APPID,
  4. appsecret=SOCIAL_AUTH_WEIXIN_SECRET,
  5. encrypt_mode='normal',
  6. encoding_aes_key='xxxxxx'
  7. )

    其中token需要填寫之前公眾號(hào)開發(fā)信息中的令牌(Token),appid就是公眾號(hào)中的開發(fā)者ID,appsecret為開發(fā)者密碼,encoding_aes_key為服務(wù)器配置項(xiàng)中的服務(wù)器加解密密鑰。

    我這里使用的drf的API View,注意其中的

  1. authentication_classes = []
  2. permission_classes = []

    這兩句是取消該接口的token認(rèn)證和登錄認(rèn)證,否則如果接口上有任何的權(quán)限認(rèn)證,微信的請(qǐng)求都是不成功的。

    config.py腳本中剩下的商戶ID MCHID和商戶支付密鑰KEY則需要登錄到微信商戶平臺(tái)中獲取。

    做好這些配置之后,就可以正式開始View的編寫了:

  1. from utils.wechatUtils.pay import JsApi_pub, UnifiedOrder_pub
  2. class WxPayConfig(APIView):
  3. def post(self, request):
  4. money = request.data[u"number"]
  5. admin_user = AdminUser.objects.filter(username=request.user.username)[0]
  6. master = Master.objects.filter(admin_user=admin_user)[0]
  7. socialAccounts = SocialAccounts.objects.filter(admin_user=admin_user)[0]
  8. openid = socialAccounts.openid
  9. money = int(float(money)*100)
  10. out_trade_no = genOrder(master.phone)
  11. jsApi = JsApi_pub()
  12. unifiedOrder = UnifiedOrder_pub()
  13. unifiedOrder.setParameter("openid", openid)
  14. unifiedOrder.setParameter("body", "儲(chǔ)值卡充值")
  15. unifiedOrder.setParameter("out_trade_no", out_trade_no)
  16. unifiedOrder.setParameter("total_fee", str(money))
  17. unifiedOrder.setParameter("notify_url", NOTIFY_URL)
  18. unifiedOrder.setParameter("trade_type", "JSAPI")
  19. prepay_id = unifiedOrder.getPrepayId()
  20. jsApi.setPrepayId(prepay_id)
  21. jsApiParameters = jsApi.getParameters()
  22. conn = redis.StrictRedis()
  23. conn.set("out_trade_no_" + out_trade_no, json.dumps({"type": "儲(chǔ)值卡充值", "admin_user": admin_user.id},
  24. ensure_ascii=False), 60 * 10)
  25. return HttpResponse(json.dumps(json.loads(jsApiParameters)), content_type="application/json")

      這里同樣是使用drf的APIView,number參數(shù)是從前端提交的支付金額,從微信提供的pay.py中導(dǎo)入JsApi_pub和UnifiedOrder_pub,然后設(shè)置所需的參數(shù)。其中參數(shù)openid就是用戶微信的openid,body是商品名稱,out_trade_no為我們自己服務(wù)器生成的訂單號(hào),total_fee就是付款金額,notify_url為微信支付成功后回調(diào)的我們服務(wù)器的URL,trade_type參數(shù)為JSAPI表示支付類型為h5頁(yè)面支付。填寫完這些參數(shù)后,調(diào)用UnifiedOrder_pub類中的getPrepayId函數(shù)獲得prepay_id,并進(jìn)行設(shè)置。最后將調(diào)用jsApi.getParameters()函數(shù)返回的結(jié)果返回到前端。

      生成參數(shù)out_trade_no的函數(shù)如下:

  1. def genOrder(phone="176******"):
  2. id_number = str(phone) + str(time.time())
  3. resId = str(uuid.uuid3(uuid.NAMESPACE_URL, id_number))
  4. resId = u"".join(re.findall("\d+", resId))
  5. return resId

    上面的代碼片段是根據(jù)用戶的手機(jī)生成對(duì)應(yīng)的唯一下單ID。當(dāng)支付成功后,微信會(huì)將支付結(jié)果以post請(qǐng)求的發(fā)送提交到NOTIFY_URL,對(duì)應(yīng)的View接受參數(shù)如下:

  1. class PayResult(APIView):
  2. authentication_classes = []
  3. permission_classes = []
  4. def get(self, request):
  5. self.post(request)
  6. def post(self, request):
  7. if request.body != "":
  8. xmlDict = xmlParse(request.body)
  9. print json.dumps(xmlDict, ensure_ascii=False)
  10. if xmlDict.has_key(u'return_code') and xmlDict[u'return_code'] == u'SUCCESS':
  11. total_fee = xmlDict[u'total_fee']
  12. out_trade_no = xmlDict[u'out_trade_no']
  13. try:
  14. with transaction.atomic():
  15. conn = redis.StrictRedis()
  16. data = conn.get("out_trade_no_" + out_trade_no)
  17. if data is not None:
  18. jsonData = json.loads(data)
  19. admin_user_id = jsonData[u"admin_user"]
  20. if jsonData[u"type"] == u"儲(chǔ)值卡充值":
  21. admin_user = AdminUser.objects.filter(id=admin_user_id)[0]
  22. assets = Assets.objects.filter(admin_user=admin_user)
  23. if len(assets) == 0:
  24. assets = Assets()
  25. assets.assets = float(total_fee) / 100
  26. assets.admin_user = admin_user
  27. else:
  28. assets = assets[0]
  29. assets.assets = float(assets.assets) + float(total_fee) / 100
  30. assets.save()
  31. assetsDetail = AssetsDetail()
  32. assetsDetail.balance = float(total_fee) / 100
  33. assetsDetail.type = 1
  34. assetsDetail.note = jsonData[u"type"]
  35. assetsDetail.admin_user = admin_user
  36. assetsDetail.save()
  37. except BaseException as e:
  38. print e.message
  39. return_data = {"return_code": "SUCCESS", "return_msg": "OK"}
  40. return HttpResponse(trans_dict_to_xml(return_data), content_type="application/xml")

    當(dāng)支付成功時(shí),微信提交的參數(shù)中會(huì)包含return_code并且值為SUCCESS,這里需要注意的是,微信提交的參數(shù)類型為xml,且我們返回給微信的數(shù)據(jù)類型也為xml,若處理成功,需要返回:

  1. <xml>
  2. <return_code><![CDATA[SUCCESS]]></return_code>
  3. <return_msg><![CDATA[OK]]></return_msg>
  4. </xml>

    注意這里的格式并不是常見的xml格式,而是微信它自己的<![CDATA[,這也是讓人很麻煩的地方。將json數(shù)據(jù)封裝成微信的xml格式數(shù)據(jù)函數(shù)如下:

  1. def trans_dict_to_xml(data_dict):
  2. data_xml = []
  3. for k in sorted(data_dict.keys()):
  4. v = data_dict.get(k)
  5. if k == 'detail' and not v.startswith('<![CDATA['):
  6. v = '<![CDATA[{}]]>'.format(v)
  7. data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v))
  8. return '<xml>{}</xml>'.format(''.join(data_xml)).encode('utf-8')

    最后,在前端處理我們后臺(tái)返回的結(jié)果并調(diào)起微信支付:

  1. sendAjax({"number":number},"/wx-pay-config",function (data) {
  2. wx.config({
  3. debug:false,
  4. appId:data["appId"],
  5. timestamp:data["timeStamp"],
  6. nonceStr:data["nonceStr"],
  7. signature:data["paySign"],
  8. package:data["package"]
  9. });
  10. wx.ready(function () {
  11. wx.chooseWXPay({
  12. timestamp: data["timeStamp"], // 支付簽名時(shí)間戳
  13. nonceStr: data["nonceStr"], // 支付簽名隨機(jī)串,不長(zhǎng)于32 位
  14. package: data["package"], // 統(tǒng)一支付接口返回的prepay_id參數(shù)值,提交格式如:prepay_id=***)
  15. signType: "MD5", // 簽名方式,默認(rèn)為'SHA1',使用新版支付需傳入'MD5'
  16. paySign: data["paySign"], // 支付簽名
  17. success: function (res) {
  18. //支付成功
  19. mui.alert("支付成功");
  20. },
  21. cancel: function (res) {
  22. //支付取消
  23. mui.alert("支付已取消");
  24. }
  25. });
  26. });
  27. wx.error(function (res) {
  28. console.log("error:" + res);
  29. });
  30. });

sendAjax是我自己封裝的一個(gè)提交POST形式的ajax函數(shù),大家使用普通的ajax發(fā)送post請(qǐng)求就可以了。這里需要注意的是,最后我調(diào)用了一個(gè)wx.error的函數(shù),我原以為是在支付出錯(cuò)時(shí)調(diào)用的,但經(jīng)過測(cè)試后發(fā)現(xiàn):即使支付成功了,這個(gè)error函數(shù)依然會(huì)被執(zhí)行,很容易被誤導(dǎo),以為支付沒成功。這里值得一提的是,在微信官方文檔中,前端調(diào)起支付的代碼如下:

  1. function onBridgeReady(){
  2. WeixinJSBridge.invoke(
  3. 'getBrandWCPayRequest', {
  4. "appId":"wx2421b1c4370ec43b", //公眾號(hào)名稱,由商戶傳入
  5. "timeStamp":"1395712654", //時(shí)間戳,自1970年以來的秒數(shù)
  6. "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //隨機(jī)串
  7. "package":"prepay_id=u802345jgfjsdfgsdg888",
  8. "signType":"MD5", //微信簽名方式:
  9. "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名
  10. },
  11. function(res){
  12. if(res.err_msg == "get_brand_wcpay_request:ok" ){
  13. // 使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示:
  14. //res.err_msg將在用戶支付成功后返回ok,但并不保證它絕對(duì)可靠。
  15. }
  16. });
  17. }
  18. if (typeof WeixinJSBridge == "undefined"){
  19. if( document.addEventListener ){
  20. document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
  21. }else if (document.attachEvent){
  22. document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
  23. document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
  24. }
  25. }else{
  26. onBridgeReady();
  27. }

經(jīng)過測(cè)試后發(fā)現(xiàn),這樣寫并不能調(diào)起支付,是一個(gè)完全沒反應(yīng)的狀態(tài)。這是微信文檔很坑的地方,需要大家特別注意。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Flask 微信卡券小項(xiàng)目:從開發(fā)到上線
微信支付開發(fā)流程
ThinkPHP微信支付接口開發(fā)完整例子
java微信公共賬號(hào)支付(JS支付)
PHP調(diào)用微信JSSDK接口 選擇相冊(cè)及拍照、圖片上傳
微信JSSDK分享功能詳解
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服