這篇文章主要介紹了微信支付的開發(fā)流程的相關資料,需要的朋友可以參考下
注意,我使用的是微信開放平臺的支付,與手機app相關,而與公眾賬號無關。
微信支付的主要操作流程
1.用戶瀏覽app,選定商品然后下單。
2.服務器處理訂單邏輯,開始正式發(fā)起支付流程
3.首先,后臺服務器向weixin服務器發(fā)起請求,獲取一個token。
4.后臺服務器拿到token,使用和其他參數(shù)加密,再次向weixin服務器發(fā)起請求,獲取一個預支付prepayid
5.后臺服務器將該prepayid返回給app客戶端
6.app調(diào)用手機上的微信控件,完成付款流程。
7.app向后臺服務器發(fā)起一個回調(diào)請求,通知服務器交易完成。
8.weixin服務器處理完所有的流程后,向后臺服務器發(fā)起一個post請求,正式通知后臺服務器交易完畢
上面流程的一些注意點:
1.每次獲取的token是有時效的,默認是7200s,而且每天最多獲取200次,因此最好放到redis中緩存起來,等失效后再去重新獲取
2.app發(fā)起的回調(diào)默認是不可靠的,后臺應該盡可能(不是必須)向微信服務器發(fā)起訂單查詢,查詢本次交易的結果。
3.weixin服務器向后臺發(fā)起的notify,才是確保交易完成的最后屏障。后臺服務器確認后必須返回“success”,否則weixin服務器會嘗試重發(fā)請求。
獲取token
這步很簡單,發(fā)送一個get請求即可。只需配置正確參數(shù)。
‘‘‘從微信服務器獲取token‘‘‘ def _getAccessTokenFromWeixin(self): response = requests.get(self.tokenUrl % (self.appId, self.appSecret)) if response.status_code == 200: text = response.text tokenInfo = json.loads(text) try: token = tokenInfo[‘a(chǎn)ccess_token‘] expires_in = tokenInfo[‘expires_in‘] self._writeWeixinTokenLog(token, self.order_no) return token except KeyError: return None #token獲取失敗 return None #http請求失敗
獲取prepayid
在微信支付的開發(fā)流程中,最繁瑣的就是獲取prepayid。
這一步我們需要組裝這樣一個參數(shù):
{ "appid":"wxd930ea5d5a258f4f", "traceid":"test_1399514976", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb ", "timestamp":1399514976, "package":"bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF% 95&fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_ no=7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1& total_fee=1&sign=7F77B507B755B3262884291517E380F8", "sign_method":"sha1", "app_signature":"7f77b507b755b3262884291517e380f8" }
組裝package
這里的第一步就是組裝package:
"package":"bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF% 95&fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_ no=7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1& total_fee=1&sign=7F77B507B755B3262884291517E380F8",
組裝package需要的參數(shù)如上面代碼所示,所以我們需要準備一個params,然后準備簽名,簽名流程如下:
1.按照key的字典序,對params進行排序,然后拼接成字符串,注意這些key不包括sign
2.在上面的字符串后面拼接key=paternerKey,然后對整個字符串進行md5簽名,然后轉換成大寫,此時我們就得到了簽名
然后我們將所有params的value進行urlencode轉碼,然后后面拼接上sign=signValue,就得到了package字符串。
這里創(chuàng)建MD5的過如下:
def createMD5Signature(self, signParams): ‘‘‘先排序‘‘‘ sortedParams = sorted(signParams.iteritems(), key=lambda d:d[0]) ‘‘‘拼接‘‘‘ stringSignTemp = "&".join(["%s=%s" % (item[0], item[1]) for item in sortedParams if item[0] != ‘sign‘ and ‘‘ != item[1]]) #加上財付通商戶權限密鑰 stringSignTemp += ‘&key=%s‘ % (self.partnerKey) #使用MD5進行簽名,然后轉化為大寫 stringSign = hashlib.md5(stringSignTemp).hexdigest().upper() #Upper return stringSign
組裝package的代碼:
def getPackage(self, packageParams): ‘‘‘先獲取params的sign,然后將params進行urlencode,最后拼接,加上sign‘‘‘ sign = self.createMD5Signature(packageParams) packageParams = sorted(packageParams.iteritems(), key=lambda d:d[0]) stringParams = "&".join(["%s=%s" % (item[0], urllib.quote(str(item[1]))) for item in packageParams]) stringParams += ‘&sign=%s‘ % (sign) return stringParams
繼續(xù)組裝參數(shù)
得到package后,我們繼續(xù)組裝參數(shù):
這里需要的參數(shù)為:
appid=wxd930ea5d5a258f4f appkey=L8LrMqqeGRxST5reouB0K66CaY A WpqhA Vsq7ggKkxHCOastWksvuX1uvmvQcl xaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K noncestr=e7d161ac8d8a76529d39d9f5b4249ccb package=bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF%95 &fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_no =7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1&tot al_fee=1&sign=7F77B507B755B3262884291517E380F8 timestamp=1399514976
traceid=test_1399514976
注意這里有個坑:
參與簽名的是上面的參數(shù),但是最后的參數(shù)中不包括appKey,簽名后要記得刪除。
1.所有參數(shù)按照字典序排序,然后拼接
2.進行sha1簽名,拼接到上面字符串的后面
3.注意這里要刪除appKey,然后加上sign
獲取sha1簽名的代碼如下:
def createSHA1Signature(self, params): ‘‘‘先排序,然后拼接‘‘‘ sortedParams = sorted(params.iteritems(), key=lambda d:d[0]) stringSignTemp = "&".join(["%s=%s" % (item[0], item[1]) for item in sortedParams]) stringSign = hashlib.sha1(stringSignTemp).hexdigest() return stringSign
隨后我們獲取到這樣的參數(shù):
{ "appid":"wxd930ea5d5a258f4f", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb", "package":"Sign=WXpay"; "partnerid":"1900000109" "prepayid":"1101000000140429eb40476f8896f4c9", "sign":"7ffecb600d7157c5aa49810d2d8f28bc2811827b", "timestamp":"1399514976" }
獲取prepayid
代碼如下:
‘‘‘獲取預支付prepayid‘‘‘ def gerPrepayId(self, token, requestParams): ‘‘‘將參數(shù),包括package,進行json化,然后發(fā)起post請求‘‘‘ data = json.dumps(requestParams) response = requests.post(self.gateUrl % (token), data=data) if response.status_code == 200: text = response.text text = json.loads(text) errcode = text[‘errcode‘] if errcode == 0: return text[‘prepayid‘] return None
我們獲取的prepayid格式應該是這樣:
{"prepayid":"1101000000140429eb40476f8896f4c9","errcode":0,"errmsg":"Success"}
再次簽名
這里采用上面sha1的簽名方式再次簽名,獲取到下面的參數(shù):
{ "appid":"wxd930ea5d5a258f4f", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb", "package":"Sign=WXpay"; "partnerid":"1900000109" "prepayid":"1101000000140429eb40476f8896f4c9", "sign":"7ffecb600d7157c5aa49810d2d8f28bc2811827b", "timestamp":"1399514976" }
后臺服務器將該結果返回給app,此時app即可發(fā)起支付。
上面的流程代碼為:
‘‘‘接收app的請求,返回prepayid‘‘‘ class WeixinRequirePrePaidHandler(BasicTemplateHandler): ‘‘‘這個方法在OrdersAddHandler中被調(diào)用‘‘‘ @staticmethod def getPrePaidResult(order_no, total_pay, product_name, client_ip): ‘‘‘封裝了常用的簽名算法‘‘‘ weixinRequestHandler = WeixinRequestHandler(order_no) ‘‘‘收集訂單相關信息‘‘‘ addtion = str(random.randint(10, 100)) #產(chǎn)生一個兩位的數(shù)字,拼接在訂單號的后面 out_trade_no = str(order_no) + addtion order_price = float(total_pay) #這里必須允許浮點數(shù),后面轉化成分之后轉化為int #order_price = 0.01 #測試 remote_addr = client_ip #客戶端的IP地址 print remote_addr current_time = int(time.time()) order_create_time = str(current_time) order_deadline = str(current_time + 20*60) ‘‘‘這里的一些參數(shù)供下面使用‘‘‘ noncestr = hashlib.md5(str(random.random())).hexdigest() timestamp = str(int(time.time())) pack = ‘Sign=WXPay‘ ‘‘‘獲取token‘‘‘ access_token = weixinRequestHandler.getAccessToken() logging.info("get token: %s" % access_token) if access_token: ‘‘‘設置package參數(shù)‘‘‘ packageParams = {} packageParams[‘bank_type‘] = ‘WX‘ #支付類型 packageParams[‘body‘] = product_name #商品名稱 packageParams[‘fee_type‘] = ‘1‘ #人民幣 fen packageParams[‘input_charset‘] = ‘GBK‘ #GBK packageParams[‘notify_url‘] = config[‘notify_url‘] #post異步消息通知 packageParams[‘out_trade_no‘] = str(out_trade_no) #訂單號 packageParams[‘partner‘] = config[‘partnerId‘] #商戶號 packageParams[‘total_fee‘] = str(int(order_price*100)) #訂單金額,單位是分 packageParams[‘spbill_create_ip‘] = remote_addr #IP packageParams[‘time_start‘] = order_create_time #訂單生成時間 packageParams[‘time_expire‘] = order_deadline #訂單失效時間 ‘‘‘獲取package‘‘‘ package = weixinRequestHandler.getPackage(packageParams) ‘‘‘設置支付參數(shù)‘‘‘ signParams = {} signParams[‘a(chǎn)ppid‘] = config[‘a(chǎn)ppId‘] signParams[‘a(chǎn)ppkey‘] = config[‘paySignKey‘] #delete signParams[‘noncestr‘] = noncestr signParams[‘package‘] = package signParams[‘timestamp‘] = timestamp signParams[‘traceid‘] = ‘mytraceid_001‘ ‘‘‘生成支付簽名‘‘‘ app_signature = weixinRequestHandler.createSHA1Signature(signParams) ‘‘‘增加不參與簽名的額外參數(shù)‘‘‘ signParams[‘sign_method‘] = ‘sha1‘ signParams[‘a(chǎn)pp_signature‘] = app_signature ‘‘‘剔除appKey‘‘‘ del signParams[‘a(chǎn)ppkey‘] ‘‘‘獲取prepayid‘‘‘ prepayid = weixinRequestHandler.gerPrepayId(access_token, signParams) if prepayid: ‘‘‘使用拿到的prepayid再次準備簽名‘‘‘ pack = ‘sign=WXPay‘ prepayParams = {} prepayParams[‘a(chǎn)ppid‘] = config[‘a(chǎn)ppId‘] prepayParams[‘a(chǎn)ppkey‘] = config[‘paySignKey‘] prepayParams[‘noncestr‘] = noncestr prepayParams[‘package‘] = pack prepayParams[‘partnerid‘] = config[‘partnerId‘] prepayParams[‘prepayid‘] = prepayid prepayParams[‘timestamp‘] = timestamp ‘‘‘生成簽名‘‘‘ sign = weixinRequestHandler.createSHA1Signature(prepayParams) ‘‘‘準備輸出參數(shù)‘‘‘ returnParams = {} returnParams[‘status‘] = 0 returnParams[‘retmsg‘] = ‘success‘ returnParams[‘a(chǎn)ppid‘] = config[‘a(chǎn)ppId‘] returnParams[‘noncestr‘] = noncestr returnParams[‘package‘] = pack returnParams[‘prepayid‘] = prepayid returnParams[‘timestamp‘] = timestamp returnParams[‘sign‘] = sign returnParams[‘partnerId‘] = config[‘partnerId‘] returnParams[‘a(chǎn)ddtion‘] = addtion else: ‘‘‘prepayid獲取失敗‘‘‘ returnParams = {} returnParams[‘status‘] = -1 returnParams[‘retmsg‘] = ‘prepayid獲取失敗‘ else: ‘‘‘token獲取失敗‘‘‘ returnParams = {} returnParams[‘status‘] = -1 returnParams[‘retmsg‘] = ‘token獲取失敗‘ ‘‘‘生成json格式文本,然后返回給APP‘‘‘ return returnParams
后臺異步通知
微信服務器發(fā)來的notify異步通知,才是支付成功的最終標志,這一步處于安全起見,我們必須進行延簽:
延簽代碼如下:
def isTenpaySign(self, params): helper = WeixinRequestHandler() sign = helper.createMD5Signature(params) return params[‘sign‘] == sign
整體流程如下:
‘‘‘微信服務器向后臺發(fā)送的異步通知‘‘‘ class WeixinAppNotifyHandler(BasicTemplateHandler): def initialize(self): self.weixinResponseHandler = WeixinResponseHandler() def post(self): ‘‘‘解析參數(shù)‘‘‘ params = self.parseQueryString() ‘‘‘驗證是否是weixin服務器發(fā)回的消息‘‘‘ verifyWeixinSign = self.weixinResponseHandler.isTenpaySign(params) ‘‘‘處理訂單‘‘‘ if verifyWeixinSign: ‘‘‘訂單邏輯‘‘‘ order_no = str(params[‘out_trade_no‘]) order_no = order_no[0:-2] print ‘%s paied successfully‘ % order_no self.saveWeixinReceipt(params) updateOrdersPaidByWeixin(order_no) #更新訂單使用狀態(tài) consumeCouponByOrderNo(order_no) #優(yōu)惠券已經(jīng)使用 self.write("success") else: self.write("fail") def parseQueryString(self): ‘‘‘獲取url中所有的參數(shù)‘‘‘ uri = self.request.uri ‘‘‘解析出URI中的query字符串‘‘‘ parseResult = urlparse.urlparse(uri) query = parseResult.query ‘‘‘解析query字符串‘‘‘ params = urlparse.parse_qs(query) for item in params: params[item] = params[item][0].strip() return params
最后說明一點,用戶在手機上付完款,并不算支付成功,只有weixin服務器收到notify通知返回的success時,才算交易最終成功,此時我們的手機可以收到微信官方發(fā)來的一條消息。
以上就是對微信支付開發(fā)流程的資料整理,后續(xù)繼續(xù)補充相關資料,謝謝大家對本站的支持!
以上是微信支付的開發(fā)流程詳細介紹的詳細內(nèi)容。更多信息請關注PHP中文網(wǎng)其他相關文章!

熱AI工具

Undress AI Tool
免費脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動的應用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線人工智能工具。

Clothoff.io
AI脫衣機

Video Face Swap
使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級代碼編輯軟件(SublimeText3)

PHP是一種開源的腳本語言,廣泛應用于Web開發(fā)和服務器端編程,尤其在微信開發(fā)中得到了廣泛的應用。如今,越來越多的企業(yè)和開發(fā)者開始使用PHP進行微信開發(fā),因為它成為了一款真正的易學易用的開發(fā)語言。在微信開發(fā)中,消息的加密和解密是一個非常重要的問題,因為它們涉及到數(shù)據(jù)的安全性。對于沒有加密和解密方式的消息,黑客可以輕松獲取到其中的數(shù)據(jù),對用戶造成威脅

在微信公眾號開發(fā)中,投票功能經(jīng)常被運用。投票功能是讓用戶快速參與互動的好方式,也是舉辦活動和調(diào)查意見的重要工具。本文將為您介紹如何使用PHP實現(xiàn)微信投票功能。獲取微信公眾號授權首先,你需要獲取微信公眾號的授權。在微信公眾平臺上,你需要配置微信公眾號的api地址、官方賬號和公眾號對應的token。在我們使用PHP語言開發(fā)的過程中,我們需要使用微信官方提供的PH

隨著微信的普及,越來越多的企業(yè)開始將其作為營銷工具。而微信群發(fā)功能,則是企業(yè)進行微信營銷的重要手段之一。但是,如果只依靠手動發(fā)送,對于營銷人員來說是一件極為費時費力的工作。所以,開發(fā)一款微信群發(fā)工具就顯得尤為重要。本文將介紹如何使用PHP開發(fā)微信群發(fā)工具。一、準備工作開發(fā)微信群發(fā)工具,我們需要掌握以下幾個技術點:PHP基礎知識微信公眾平臺開發(fā)開發(fā)工具:Sub

微信是目前全球用戶規(guī)模最大的社交平臺之一,隨著移動互聯(lián)網(wǎng)的普及,越來越多的企業(yè)開始意識到微信營銷的重要性。在進行微信營銷時,客服服務是至關重要的一環(huán)。為了更好地管理客服聊天窗口,我們可以借助PHP語言進行微信開發(fā)。一、PHP微信開發(fā)簡介PHP是一種開源的服務器端腳本語言,廣泛運用于Web開發(fā)領域。結合微信公眾平臺提供的開發(fā)接口,我們可以使用PHP語言進行微信

在微信公眾號開發(fā)中,用戶標簽管理是一個非常重要的功能,可以讓開發(fā)者更好地了解和管理自己的用戶。本篇文章將介紹如何使用PHP實現(xiàn)微信用戶標簽管理功能。一、獲取微信用戶openid在使用微信用戶標簽管理功能之前,我們首先需要獲取用戶的openid。在微信公眾號開發(fā)中,通過用戶授權的方式獲取openid是比較常見的做法。在用戶授權完成后,我們可以通過以下代碼獲取用

隨著微信成為了人們生活中越來越重要的一個通訊工具,其敏捷的消息傳遞功能迅速受到廣大企業(yè)和個人的青睞。對于企業(yè)而言,將微信發(fā)展為一個營銷平臺已經(jīng)成為趨勢,而微信開發(fā)的重要性也逐漸凸顯。在其中,群發(fā)功能更是被廣泛使用,那么,作為PHP程序員,如何實現(xiàn)群發(fā)消息發(fā)送記錄呢?下面將為大家簡單介紹一下。1.了解微信公眾號相關開發(fā)知識在了解如何實現(xiàn)群發(fā)消息發(fā)送記錄之前,我

如何使用PHP實現(xiàn)微信公眾號開發(fā)微信公眾號已經(jīng)成為了很多企業(yè)推廣和互動的重要渠道,而PHP作為一種常用的Web語言,也可以用來進行微信公眾號的開發(fā)。本文將介紹一下使用PHP實現(xiàn)微信公眾號開發(fā)的具體步驟。第一步:獲取微信公眾號的開發(fā)者賬號在開始微信公眾號開發(fā)之前,需要先去申請一個微信公眾號的開發(fā)者賬號。具體的注冊流程可以參見微信公眾平臺的官方網(wǎng)

隨著互聯(lián)網(wǎng)和移動智能設備的發(fā)展,微信成為了社交和營銷領域不可或缺的一部分。在這個越來越數(shù)字化的時代,如何使用PHP進行微信開發(fā)已經(jīng)成為了很多開發(fā)者的關注點。本文主要介紹如何使用PHP進行微信開發(fā)的相關知識點,以及其中的一些技巧和注意事項。一、開發(fā)環(huán)境準備在進行微信開發(fā)之前,首先需要準備好相應的開發(fā)環(huán)境。具體來說,需要安裝PHP的運行環(huán)境,以及微信公眾平臺提
