微信支付又一次成功的教我做人

時間過得飛快,轉眼間從業前端已經有些年頭了,見了太多的場景,意想不到的的錯誤,以爲自己足夠成熟和冷靜的時候,支付再一次教了我一回,怎麼做一個人。。。

事情的經過大致是這樣子的,公司有一個h5新項目,然後再開發的時候需要對接支付。經過調研,後來只打算上微信支付和支付寶支付,在這裏首先對支付寶支付api的開發者表示致敬,真心好用。然後再說會微信。。。。有h5支付,公衆號支付,還有小程序支付。。。。在這裏奉勸大家,如果是真的設計多方登錄,支付的時候,還是使用微信開放平臺把,畢竟找個屬於少生優生,幸福一生的選擇,不然也有可能會有我接下來的經歷。。。

h5支付寶支付

大概調起支付的過程如下:

  1. 創建訂單信息

  2. 拿到返回表單

  3. 渲染表單

  4. 表單進行提交

<!-- 1. 正常使用ajax提交商品信息,後臺返回內容如下 -->
<form id='alipaysubmit' name='alipaysubmit' action='https://openapi.alipay.com/gateway.do?charset=UTF-8' method='POST'><input type='hidden' name='biz_content' value='{****}'/><input type='hidden' name='app_id' value='*******'/><input type='hidden' name='version' value='1.0'/><input type='hidden' name='format' value='json'/><input type='hidden' name='sign_type' value='RSA2'/><input type='hidden' name='method' value='alipay.trade.wap.pay'/><input type='hidden' name='timestamp' value='2020-06-10 08:56:10'/><input type='hidden' name='alipay_sdk' value='alipay-sdk-php-20161101'/><input type='hidden' name='notify_url' value='******'/><input type='hidden' name='return_url' value='http://starmall.ipxmall.com/order/order-result'/><input type='hidden' name='charset' value='UTF-8'/><input type='hidden' name='sign' value='*****/******+******+****/****+****=='/><input type='submit' value='ok' style='display:none;''></form><script>document.forms['alipaysubmit'].submit();</script>

  1. 客戶端調用, 項目使用vue,直接貼上組件,將上邊的內容當作參數傳入組件就ok

需要注意的是,因爲是表單,所以需要使用v-html進行數據綁定,然後正常調起支付就ok了

<template>
  <div v-html="info">
  </div>
</template>

<script>
export default {
  props: {
    info: String
  },
  data() {
    return {}
  },
  watch: {
    info() {
      this.$nextTick(() => {
        document.querySelector('#alipaysubmit').submit()
      })
    }
  }
}
</script>

<style>

</style>

微信支付之網頁支付

大概步驟和上述相同,需要提一下的是,微信h5支付只能在手機瀏覽器才能測試

  1. 調用後臺接口,創建訂單(微信支付需要初始化jsapi)
  2. 發起支付
// 需要注意的是:判斷是否在微信內置瀏覽器(微信內置瀏覽器使用jsapi調起支付,手機瀏覽器使用url跳轉)
if (!this.isWeiXin) {
let { errorCode, data } = await payInfo(params)
if (errorCode === 0) {
  window.location.href = data
}
return false
}
// 到此爲止,瀏覽器微信支付搞定

微信內置瀏覽器支付調起

  1. 初始化微信支付jsapi
initWxPay() {
  let wxSrc = 'https://res.wx.qq.com/open/js/jweixin-1.2.0.js'
  let script = document.createElement('script')
  script.src = wxSrc
  document.body.append(script)
}

~~2. 返回內容… 等等,居然報錯了 , ~~
發現統一下單需要openid, openId 只能客戶端首先進行getCode,然後服務器通過code拿到openid,然後統一下單。再然後返回客戶端需要的信息
2. getCode

// 需要緩存商品信息,或者將訂單信息的ID通過state攜帶過去,回調處理會簡單很多
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=${state}#wechat_redirect`
  1. 重定向會到我們的頁面,回調的url裏就會有code
// 1. 拿到code, 然後創建訂單信息
const { code } = this.$route.query
// 2. 統一下單,然後,判斷是否在微信內置瀏覽器(微信內置瀏覽器使用jsapi調起支付,手機瀏覽器使用url跳轉)
// 3. 然後創建訂單信息
  1. 發起支付

let { errorCode, data } = await payInfo({ 訂單信息, code })
if (errorCode === 0) { // 判斷後臺返回值正確以後調起支付
    if (typeof WeixinJSBridge == "undefined"){
      if( document.addEventListener ){
          document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
      }else if (document.attachEvent){
          document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
          document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
      }
    }else{
      onBridgeReady();
    }
  }
 // 爲了方便查看,將方法放到後邊,data是後臺統一下單後給的返回信息
function onBridgeReady(){
    WeixinJSBridge.invoke(
        'getBrandWCPayRequest', {
          "appId": data.appId,     //公衆號名稱,由商戶傳入     
          "timeStamp": `${data.timeStamp}`,         //時間戳,自1970年以來的秒數     
          "nonceStr": data.nonceStr, //隨機串     
          "package": data.package,     
          "signType":"MD5",         //微信簽名方式:     
          "paySign": data.paySign //微信簽名 
        },
        function(res){
          if(res.err_msg == "get_brand_wcpay_request:ok" ){
            // 使用以上方式判斷前端返回,微信團隊鄭重提示:
            self.$router.replace('/order/order-result')
          }
    }); 
  }

// 正常輸入密碼,完成支付

微信小程序內嵌網頁調起小程序支付

.小程序新建一個支付頁面,接受參數,完成後續的步驟
支付流程如下:

  1. 從內嵌網頁使用小程序暴露的api跳轉到小程序支付頁面,(講sku信息傳遞過去)
  2. 小程序在onload的時候讀取到信息,然後使用wx.login拿到code,
  3. 將sku信息和code通過結果發送給後臺,後臺統一下單
  4. 拿到後臺統一下下單後的返回信息,調起小程序支付
  5. 輸入密碼,完成支付, 代碼如下
// h5網頁內代碼
if (window.__wxjs_environment === 'miniprogram') {
// 將需要用到的信息都傳遞過去,方便在小程序調用的時候使用
// token id, sku信息 
wx.miniProgram.reLaunch({
  url: `/pages/h5-pay/main?data=${JSON.stringify({params, token})}`
})
return false
}
export default {
  name: 'index',
  data() {
    return {
      // path: 'https://ipxh5.jfshare.com'
    }
  },
  methods: {
  // 完成訂單後跳轉
    reLaunch(status) {
      wx.redirectTo({
        url: `/pages/h5-result/main?status=${status}`
      })
    },
    // 登錄獲取code
    login(options) {
      options = JSON.parse(options)
      let { token, params } = options

      wx.setStorage({
        key:"token",
        data: JSON.stringify(token)
      })

      let self = this
      wx.login({
        success (res) {
          if (res.code) {
            //發起網絡請求
           self.initPayInfo({code: res.code, ...params})
          } else {
            console.log('登錄失敗!' + res.errMsg)
          }
        }
      })
    },
    // 發起支付
    async initPayInfo(params) {
      let self = this
      let { errorCode, data } = await request.post('/order/order/createOrderPayInfo', params)
      if (errorCode === 0 ) {
         wx.requestPayment({
          ...data,
          signType: 'MD5',
          success (res) {
            self.reLaunch(1)
          },
          fail (res) {
            self.reLaunch(0)
          }
        })
      }
    }
  },
// 這裏拿到傳遞過來的參數
  onLoad(options) { 
    if (options.data) {
      this.login(options.data)
    }
    
  }
}

結束語

  1. 在安卓部分機型會在網頁關閉後清空當前頁面用到的所有緩存(cookie, sessionstorage, localstorage), 這裏需要做處理
  2. 關於支付的順序 的處理,減少判斷的嵌套層級
  3. 假如出現以上類似公衆號支付和小程序支付的appid不一樣的情況下的處理(需要後端配合)
  4. 調試,記得一定要用vsconsole, 記得一定要讓後臺在調試過程中一直打開日誌
  5. 小程序調試使用開發者工具即可
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章