<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從前端的角度來梳理微信支付的流程

          共 6960字,需瀏覽 14分鐘

           ·

          2020-11-22 18:41

          作者:張優(yōu)秀

          來源:SegmentFault 思否社區(qū)




          因業(yè)務(wù)需要,開發(fā)微信支付功能,涉及三種支付方式:


          • JSAPI 支付:微信內(nèi)網(wǎng)頁支付,需要開通微信服務(wù)號
          • 小程序支付:在小程序中支付,需要開通小程序
          • H5 支付:在手機(jī)瀏覽器(出微信內(nèi)網(wǎng)爺)中網(wǎng)頁支付

          使用微信支付的前提必開通微信商戶號,要使用到那種的支付方式要前需在商戶平臺(tái)開通(要審核)。

          支付的錢最終都會(huì)到商戶號里(一般由公司財(cái)務(wù)開通)。

          開發(fā)微信支付的過程中大大小小坑還是踩了不少,終于做完了,整理下開發(fā)流程。

          參考:

          • 微信支付-接入指引
          • 微信支付-開發(fā)文檔



          小程序支付


          開發(fā)流程


          1. 小程序端請求創(chuàng)建訂單接口,后端統(tǒng)一下單獲取?orderId?并返回
          2. 小程序端獲取通過wx.login()獲取code
          3. 小程序端拿這code和orderId請求后端接口,獲取支付所需數(shù)據(jù)
          4. 獲取支付所需數(shù)據(jù)之后,小程序端調(diào)用wx.requestPayment()接口,直接調(diào)用起支付頁面
          5. 判斷是否支付成功后的邏輯

          偽代碼


          async?function?wxPay(goodId)?{
          ??//?1.?創(chuàng)建訂單?獲取orderId
          ??let?orderId?=?await?ajax("POST",?"/api/OrderProgram/CreateTheOrder",?{
          ????goodId,?//?商品id
          ??});
          ??//?2.?獲得?code
          ??let?code?=?await?wxlogin();?//?基于pr封裝的wx.login()方法
          ??//?3.?獲取支付的數(shù)據(jù)
          ??let?payData?=?await?ajax("POST",?"/api/OrderProgram/WxXcxPay",?{
          ????orderId,
          ????code,
          ??});
          ??//?4.?發(fā)起支付
          ??let?res?=?await?payment(payData);?//?基于pr封裝的wx.requestPayment()方法
          ??//?5.?判斷是否支付成功
          ??let?payResult?=?res.errMsg;
          ??if?(payResult?==?"requestPayment:ok")?{
          ????console.log("支付成功");
          ??}?else?if?(payResult?==?"requestPayment:fail?cancel")?{
          ????console.log("用戶取消支付");
          ??}?else?{
          ????console.log("支付失敗");
          ??}
          }

          注意事項(xiàng)


          1. 申請微信小程序賬號
            申請成功可拿到 AppID(小程序 id)和 AppSecret(小程序密鑰)
            申請類型為企業(yè)性質(zhì),否則無法接入微信支付
          2. 微信小程序認(rèn)證
            通過認(rèn)證的小程序才能接入微信支付和綁定商戶平臺(tái)
          3. 申請商戶平臺(tái)賬號
            需要第一步申請的 AppID
            申請成功可拿到 MchID(商戶 id)和 MchKey(商戶密鑰)
          4. 信小程序關(guān)聯(lián)商戶號
            微信和商戶都認(rèn)證成功后,在微信后臺(tái)微信支付菜單中進(jìn)行關(guān)聯(lián)
          5. 接入微信支付
            在微信后臺(tái)微信支付菜單中進(jìn)行接入


          參考


          • 小程序支付文檔
          • 小程序開發(fā)文檔



          H5 支付


          開發(fā)流程


          1. 前端端請求創(chuàng)建訂單接口,后端統(tǒng)一下單獲取?orderId?并返回
          2. 前端帶著?orderId?請求支付接口,獲得?mweb_url,
          3. 然后跳轉(zhuǎn)?mweb_url?會(huì)跳轉(zhuǎn)微信自動(dòng)調(diào)用微信支付
          4. 支付后返回支付頁,判斷是否支付成功(需發(fā)送請求后端查詢)
            4.1 刷新頁面,獲取最新的支付(訂單)狀態(tài)。
            4.2 設(shè)置一個(gè)的按鈕"我已支付",讓用戶點(diǎn)擊自動(dòng)查詢狀態(tài)。


          偽代碼


          async?function?wxH5Pay(goodId)?{
          ??//?1.?創(chuàng)建訂單?獲取orderId
          ??let?orderId?=?await?ajax("POST",?"/api/OrderProgram/CreateTheOrder",?{
          ????goodId,?//?商品id
          ??});
          ??//?2.?獲取支付跳轉(zhuǎn)的URL
          ??let?mweb_url?=?await?ajax("POST",?"/api/OrderProgram/WxH5Pay",?{?orderId?});
          ??//?3.?跳轉(zhuǎn)URL去微信支付
          ??if?(mweb_url)?{
          ????location.href?=?mweb_url;
          ??}?else?{
          ????console.log("回調(diào)地址出錯(cuò)");
          ??}
          ??//?4.?支付后返回支付頁,判斷是否支付成功
          ??// 4.1 刷新頁面,獲取最新的訂單(商品)狀態(tài)。
          ??//?4.2?設(shè)置一個(gè)"我已支付"的按鈕,讓用戶點(diǎn)擊之后查詢狀態(tài)。
          }

          注意事項(xiàng)


          • 在商戶平臺(tái)設(shè)置正確的支付域名
          • 調(diào)試需要在線上,如果嫌麻煩可以使用內(nèi)網(wǎng)穿透(Ngrok 或花生殼)
          • 需對redirect_url進(jìn)行urlencode處理
          • H5 支付不能直接在微信客戶端內(nèi)調(diào)起,請?jiān)谕獠繛g覽器調(diào)起。


          參考


          • 微信支付-H5 支付-開發(fā)步驟




          JSAPI 支付(微信內(nèi)網(wǎng)頁支付)


          開發(fā)流程


          • 商品頁
          1. 前端商品頁創(chuàng)建訂單,在后端統(tǒng)一下單后獲取?orderId
          2. 前端帶著?orderId?跳轉(zhuǎn)到支付頁,

          • 支付頁
          1. 獲取?code
            1. 第一次進(jìn)入頁面,判斷是否路徑中有?code
            2. 沒有?code,請求數(shù)據(jù)跳轉(zhuǎn)授權(quán)頁面,code?會(huì)通過回調(diào)地址一起返回回來
            3. 拿到 code,發(fā)送給后端,后端解析到 openid,保存好。
          2. 點(diǎn)擊確定支付按鈕,觸發(fā)?wxPay()?方法
            1. 發(fā)送?orderId?給后端,獲取?wxData
            2. wxData 中包含 wx.config 和 wx.chooseWXPay 兩個(gè)接口的數(shù)據(jù)。
            3. 先調(diào)用 wx.config()然后在調(diào)用 wx.chooseWXPay(),如果一切正常,支付頁面就會(huì)彈出。
          3. 支付狀態(tài)通過后端去查詢

          偽代碼

          • 商品頁
          //?1.?創(chuàng)建訂單?獲取orderId
          let?orderId?=?await?ajax("POST",?"/api/OrderProgram/CreateTheOrder",?{
          ??goodId,?//?商品id
          });
          //?2.?攜帶id?跳轉(zhuǎn)到支付頁
          this.$router.push({?name:?"wx_pay_page",?params:?{?orderId:?id?}?});

          • 入口文件(main.js)
          //?main.js?引入?js-sdk
          import?wx?from?"weixin-js-sdk";

          • 支付頁 HTML


          支付頁 JS
          //?Vue
          data(){
          ????return?{
          ????????orderId:?this.$route.params.orderId,?//?訂單id
          ????????url:?'',//?獲取code的url
          ????????wxData:?null,//?js-sdk接口所需的數(shù)據(jù)
          ????}
          },
          mounted(){
          ????//?判斷是否有code
          ????this.getCode()
          }
          methods:?{
          ????getCode()?{
          ????????var?code?=?this.getUrlPram("code");
          ????????if?(code?!=?null)?{
          ????????????this.code?=?code;
          ????????????//?拿到?code?發(fā)給?后端
          ????????????this.sendCode(code);
          ????????}?else?{
          ????????????//?去拿code
          ????????????this.getUrl();
          ????????}
          ????},
          ????getUrl()?{
          ????????//?請求后端拿到url所需數(shù)據(jù),然后跳轉(zhuǎn)頁面在通過回調(diào)地址返回,獲取code.
          ????????this.axios
          ????????????.post("/api/OrderProgram/GetOpenidAndAccessToken",?{
          ????????????????orderId:?this.orderId,
          ????????????})
          ????????????.then((data)?=>?{
          ????????????????this.url?=?`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${data.appId}&redirect_uri=${data.redirect_uri}&response_type=${data.response_type}&scope=${data.scope}&state=${data.state}`;
          ????????????????window.location.href?=?this.url;
          ????????????})
          ????????????.catch((err)?=>?{
          ????????????????console.log(err);
          ????????????});
          ????},
          ????sendCode(code)?{
          ????????//?發(fā)送code給后端?后端解析出openid
          ????????this.axios
          ????????????.post("/api/OrderProgram/GetOpenidAndAccessTokenFromCode",?{
          ????????????????code:?code,
          ????????????})
          ????????????.then((res)?=>?{
          ????????????????console.log(res);
          ????????????})
          ????????????.catch((err)?=>?{
          ????????????????console.log(err);
          ????????????});
          ????},
          ????wxPay:?async?function()?{
          ????????//?發(fā)送orderid,獲取wx.chooseWXPay和wx.config所需的參數(shù)
          ????????this.wxData?=?await?this.axios.post(
          ????????????"/api/OrderProgram/WxJSAPIPay",
          ????????????{?orderId:?this.orderId?}
          ????????);
          ????????let?wxConfigData?=?this.wxData.wxConfigData?//?獲取wx.chooseWXPay()所需數(shù)據(jù)
          ????????let?wxPayData?=?this.wxData.wxPayData;//?獲取wx.config()所需數(shù)據(jù)
          ????????this.$wx.config({
          ????????????debug:?false,?//?開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來,若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會(huì)通過log打出,僅在pc端時(shí)才會(huì)打印。
          ????????????appId:?wxConfigData.appId,?//?必填,公眾號的唯一標(biāo)識
          ????????????timestamp:?wxConfigData.timeStamp,?//?必填,生成簽名的時(shí)間戳
          ????????????nonceStr:?wxConfigData.nonceStr,?//?必填,生成簽名的隨機(jī)串
          ????????????signature:?wxConfigData.paySign,?//?必填,簽名
          ????????????jsApiList:?[
          ????????????????"chooseWXPay",
          ????????????],
          ????????});
          ????????//?執(zhí)行支付
          ????????this.$wx.chooseWXPay({
          ??????????? timestamp: wxPayData.timeStamp, //?支付簽名時(shí)間戳,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付后臺(tái)生成簽名使用的timeStamp字段名需大寫其中的S字符
          ????????????nonceStr:?wxPayData.nonceStr,?//?支付簽名隨機(jī)串,不長于?32?位
          ??????????? package: wxPayData.package, //?統(tǒng)一支付接口返回的prepay_id參數(shù)值,提交格式如:prepay_id=\*\*\*)
          ????????????signType:?wxPayData.signType,?//?簽名方式,默認(rèn)為'SHA1',使用新版支付需傳入'MD5'
          ????????????paySign:?wxPayData.paySign,?//?支付簽名
          ????????????success:?(res)?=>?{
          ????????????????this.$toast("支付成功");
          ????????????},
          ????????????fail:?(err)?=>?{
          ????????????????this.$toast("支付失敗");
          ????????????},
          ????????});
          ????},
          }

          同時(shí)支持 H5 支付和 JSAPI 支付

          //?在創(chuàng)建訂單之后,就判斷環(huán)境使用哪種方法支付。
          if?(isWx())?{
          ??this.WXPay(orderId);?//?帶著orderId跳轉(zhuǎn)到支付頁邏輯
          }?else?{
          ??this.H5Pay(orderId);?//?執(zhí)行上面H5支付中的創(chuàng)建訂單之后的邏輯
          }
          //?判斷是否是微信瀏覽器
          function?isWx()?{
          ??let?uAgent?=?navigator.userAgent.toLowerCase();
          ??reutrn(/micromessenger/.test(uAgent))???true?:?false;
          }

          注意事項(xiàng)


          • 開通微信商戶號 - 設(shè)置支付目錄(如果是 Vue 這類 SPA 頁面,到根目錄即可,也就是#號之前的地址)


          • 開通微信公眾號(服務(wù)號) - 設(shè)置安全域名、設(shè)置授權(quán)域名


          • 收集參數(shù):appId 和 AppSecret
          • 添加 Web 開發(fā)工具開發(fā)者(需要開發(fā)者同時(shí)開發(fā)者關(guān)注開發(fā)的微信公眾號和微信公眾賬號安全助手)參考文檔
            [圖片上傳失敗...(image-b07878-1605777597831)]
          • 設(shè)置回調(diào)域名(例如:www.xx.com/pay,最后獲取的 code 會(huì)拼在此回調(diào)地址后返回,返回后如www.xx.com/pay?code=xxxx)參考 1
          • 獲取 code
            • 參考獲取 code 文檔
            • 在微信客戶端網(wǎng)頁打開授權(quán)地址,跳轉(zhuǎn)之后,在返回的回調(diào)地址之后拿到 code:

          https://open.weixin.qq.com/connect/oauth2/authorize
          ?appid=你的appid
          &redirect_uri=你的回調(diào)地址(拿到code后返回)
          &response_type=code(返回類型,默認(rèn)code)
          &scope=snsapi_base(授權(quán)范圍,靜默授權(quán)拿到openid)
          &state=STATE(自定義狀態(tài),非必填)
          #wechat_redirect(重定向使用必須攜帶)

          redirect_uri參數(shù)要和你在微信公眾號里設(shè)置的回調(diào)域名一致(例如:www.xx.com/pay),需要注意的是這 url 需要urlEncode。

          請求這個(gè)地址之后,code 會(huì)以你設(shè)置的redirect_uri地址里的參數(shù)帶回來,拿到之后傳給后端就行了。

          • 前端引入 js-skd
            • 使用script引入js-sdk
            • 下載使用?npm?包weixin-js-sdk
          • 獲取?wx.config?的參數(shù)

          • 獲取?wx.chooseWXPay?所需的參數(shù)




          總結(jié)


          整個(gè)流程走下來,給我的體驗(yàn)是:小程序支付最方面(因?yàn)榕渲蒙伲?,其次?H5,JSAPI 支付最麻煩(文章一多半都在寫它)

          在微信支付功能開發(fā)過程中,其實(shí)最麻煩的不是開發(fā)流程,而是他的各種配置和授權(quán)流程,為了拿到所需的參數(shù)而來回折騰。

          開發(fā)過程中的一些參數(shù)是經(jīng)常用到的,如 appid、openid、orderId

          支付流程大徑相同,先獲取到用戶的 openid,知道你是誰,然后統(tǒng)一下單拿到 orderId 再去處理不同平臺(tái)的支付方式

          開發(fā)時(shí)候用到的相關(guān)文檔,一定要仔細(xì)閱讀二遍以上為止?。?/span>

          遇到問題不要死剛,多百度多 Google,說不準(zhǔn)你遇到的問題已經(jīng)有無數(shù)的人遇到過并且已經(jīng)有成熟的解決方案了。




          點(diǎn)擊左下角閱讀原文,到?SegmentFault 思否社區(qū)?和文章作者展開更多互動(dòng)和交流。

          -?END -

          瀏覽 43
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  护士AV无码A片在线观看 | 色电影在线 | 国产AV毛片| 国产精品扒开腿做爽爽爽网站免费 | 亚洲国产AV网站 |