正文
由于最近自己在做小程序的支付,就在這里簡單介紹一下講一下用python做小程序支付這個流程。當(dāng)然在進(jìn)行開發(fā)之前還是建議讀一下具體的流程,清楚支付的過程。
1.支付交互流程
當(dāng)然具體的參數(shù)配置可以參考官方文檔https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1
2.獲取openid(微信用戶標(biāo)識)
import requests from config import APPID, SECRET class OpenidUtils(object): def __init__(self, jscode): self.url = "https://api.weixin.qq.com/sns/jscode2session" self.appid = APPID # 小程序id self.secret = SECRET # 不要跟后面支付的key搞混 self.jscode = jscode # 前端傳回的動態(tài)jscode def get_openid(self): # url一定要拼接,不可用傳參方式 url = self.url + "?appid=" + self.appid + "&secret=" + self.secret + "&js_code=" + self.jscode + "&grant_type=authorization_code" r = requests.get(url) print(r.json()) openid = r.json()['openid'] return openid
3.支付請求
# -*- coding:utf-8 -*- import requests import hashlib import xmltodict import time import random import string import urllib2 import sys class WX_PayToolUtil(): """ 微信支付工具 """ def __init__(self, APP_ID, MCH_ID, API_KEY, NOTIFY_URL): self._APP_ID = APP_ID # 小程序ID self._MCH_ID = MCH_ID # # 商戶號 self._API_KEY = API_KEY self._UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder" # 接口鏈接 self._NOTIFY_URL = NOTIFY_URL # 異步通知 def generate_sign(self, param): '''生成簽名''' stringA = '' ks = sorted(param.keys()) # 參數(shù)排序 for k in ks: stringA += (k + '=' + param[k] + '&') # 拼接商戶KEY stringSignTemp = stringA + "key=" + self._API_KEY # md5加密,也可以用其他方式 hash_md5 = hashlib.md5(stringSignTemp.encode('utf8')) sign = hash_md5.hexdigest().upper() return sign ''' # python2另外一種實現(xiàn)方法 def generate_sign(self, params): ret = [] for k in sorted(params.keys()): if (k != 'sign') and (k != '') and (params[k] is not None): ret.append('%s=%s' % (k, params[k])) params_str = '&'.join(ret) params_str = '%(params_str)s&key=%(partner_key)s' % {'params_str': params_str, 'partner_key': key} reload(sys) sys.setdefaultencoding('utf8') params_str = hashlib.md5(params_str.encode('utf-8')).hexdigest() sign = params_str.upper() return sign ''' def getPayUrl(self, orderid, openid, goodsPrice, **kwargs): """向微信支付端發(fā)出請求,獲取url""" key = self._API_KEY nonce_str = ''.join(random.sample(string.letters + string.digits, 30)) # 生成隨機(jī)字符串,小于32位 params = { 'appid': self._APP_ID, # 小程序ID 'mch_id': self._MCH_ID, # 商戶號 'nonce_str': nonce_str, # 隨機(jī)字符串 "body": '測試訂單', # 支付說明 'out_trade_no': orderid, # 生成的訂單號 'total_fee': str(goodsPrice), # 標(biāo)價金額 'spbill_create_ip': "127.0.0.1", # 小程序不能獲取客戶ip,web用socekt實現(xiàn) 'notify_url': self._NOTIFY_URL, 'trade_type': "JSAPI", # 支付類型 "openid": openid, # 用戶id } # 生成簽名 params['sign'] = self.generate_sign(params) # python3一種寫法 param = {'root': params} xml = xmltodict.unparse(param) response = requests.post(self._UFDODER_URL, data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'}) # xml 2 dict msg = response.text xmlmsg = xmltodict.parse(msg) # 4. 獲取prepay_id if xmlmsg['xml']['return_code'] == 'SUCCESS': if xmlmsg['xml']['result_code'] == 'SUCCESS': prepay_id = xmlmsg['xml']['prepay_id'] # 時間戳 timeStamp = str(int(time.time())) # 5. 五個參數(shù) data = { "appId": self._APP_ID, "nonceStr": nonce_str, "package": "prepay_id=" + prepay_id, "signType": 'MD5', "timeStamp": timeStamp, } # 6. paySign簽名 paySign = self.generate_sign(data) data["paySign"] = paySign # 加入簽名 # 7. 傳給前端的簽名后的參數(shù) return data # python2一種寫法 ''' request_xml_str = '' for key, value in params.items(): if isinstance(value, str): request_xml_str = '%s<%s> ' % (request_xml_str, key, value, key,) else: request_xml_str = '%s<%s>%s' % (request_xml_str, key, value, key,) request_xml_str = '%s ' % request_xml_str # 向微信支付發(fā)出請求,并提取回傳數(shù)據(jù) res = urllib2.Request(self._UFDODER_URL, data=request_xml_str.encode("utf-8")) res_data = urllib2.urlopen(res) res_read = res_data.read() doc = xmltodict.parse(res_read) return_code = doc['xml']['return_code'] if return_code == "SUCCESS": result_code = doc['xml']['result_code'] if result_code == "SUCCESS": doc = doc['xml'] data = { "appId": self._APP_ID, "nonceStr": nonce_str, "package": "prepay_id=" + doc["prepay_id"], "signType": 'MD5', "timeStamp": str(int(time.time())), } # paySign簽名 paySign = self.generate_sign(data) data["paySign"] = paySign # 加入簽名 return data else: err_des = doc['xml']['err_code_des'] return err_des else: fail_des = doc['xml']['return_msg'] return fail_des '''
當(dāng)然你可能會遇到的錯誤有簽名錯誤,一般的情況是你的appSecret和商戶號的API密鑰兩個弄錯了,當(dāng)然如果不是還有可能是其他問題,解決方案鏈接 https://www.jb51.net/article/166176.htm?。
其他的支付方式獲取用戶的ip地址可以通過socket.gethostbyname(socket.gethostname())方法來獲取。
4.支付回調(diào)
# 統(tǒng)一下單回調(diào)處理 import xmltodict from django.http import HttpResponse def payback(request): msg = request.body.decode('utf-8') xmlmsg = xmltodict.parse(msg) return_code = xmlmsg['xml']['return_code'] if return_code == 'FAIL': # 官方發(fā)出錯誤 return HttpResponse("""""", content_type='text/xml', status=200) elif return_code == 'SUCCESS': # 拿到這次支付的訂單號 out_trade_no = xmlmsg['xml']['out_trade_no'] # 根據(jù)需要處理業(yè)務(wù)邏輯 return HttpResponse(""" """, content_type='text/xml', status=200)
當(dāng)然微信回調(diào)的參數(shù)有很多詳細(xì)可以參考https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8
在回調(diào)的時候可能遇到這樣一個問題,支付成功以后沒有調(diào)回調(diào)函數(shù),有可能是回調(diào)地址是https然后改為http就行,遇到過這個坑,具體原因也不知道。服務(wù)器沒有屏蔽https訪問,https證書也沒有問題,把https改為http最后就可以了。
5.安全問題
在使用的過程中商戶系統(tǒng)對于支付結(jié)果通知的內(nèi)容一定要做簽名驗證,并校驗返回的訂單金額是否與商戶側(cè)的訂單金額一致,防止數(shù)據(jù)泄漏導(dǎo)致出現(xiàn)“假通知”,造成資金損失。
我在開發(fā)過程中的解決方式是在向微信支付端發(fā)起請求的時候,把訂單號,金額,簽名等存入數(shù)據(jù)庫,然后在回調(diào)函數(shù)那里進(jìn)行校驗判斷。在確認(rèn)跟前面訂單情況一樣的情況下,才進(jìn)行后續(xù)一系列的操作。
最后送給大家一段祝福
# _oo8oo_ # o8888888o # 88" . "88 # (| -_- |) # 0\ = /0 # ___/'==='\___ # .' \\| |# '. # / \\||| : |||# \ # / _||||| -:- |||||_ \ # | | \\\ - #/ | | # | \_| ''\---/'' |_/ | # \ .-\__ '-' __/-. / # ___'. .' /--.--\ '. .'___ # ."" '< '.___\_<|>_/___.' >' "". # | | : `- \`.:`\ _ /`:.`/ -` : | | # \ \ `-. \_ __\ /__ _/ .-` / / # =====`-.____`.___ \_____/ ___.`____.-`===== # `=---=` # # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # #
總結(jié)
以上所述是小編給大家介紹的Python實現(xiàn)微信小程序支付功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
