Recently because the company’s business has been doing wechat small program projects, take this opportunity to step on some pit summary record recently.

Wechat small program login related

  1. The front end calls wx.login() to get temporary login credentialscode
  2. Send the code to the server via wx.request() (requires the backend creation interface to receive the code)
  3. Verify login credentials at the back end with the input parameters (appID,secret,js_code,grant_type)

Explanation of common nouns:

Appid App that uniquely identifies secret App secret js_code Code obtained during login Grant_type Set this parameter to authorization_code

  1. After the login certificate is verified, exchange openID and session_key from wechat server

Openid Unique id of a user session_key Session key

Openid is the unique identifier of the user, but it is not recommended to be used as the identifier of the back-end server directly. Session_key is used to encrypt and sign user data. Session_key is used to verify files and obtain user information

Generally, for security reasons, neither data is sent to the client.

  1. After processing the session_key, the backend returns a string after processing the session_key as the login id of the user, usually in the form of token. (Custom login state is associated with openID session_key)
  2. The front-end receives the token, stores it in the localStorage, and carries it with it every time it requests data from the server, which serves as the server’s certificate to identify the user.
  3. When the subsequent user enters the applet, wx.checkSession() will be called first to check the login state. If it fails, the login process will be restarted.
//app.js
const NOLOGINCODE = 1000003 / / not logged in
const SUCCESS = 1000001 / / success
App({
  onLaunch: function() {
    var loginFlag = wx.getStorageSync('sessionId')
    var that = this
    if (loginFlag) {
      // Check whether session_key expires
      wx.checkSession({
        // session_key valid (not expired)
        success: function() {
          var userInfo = wx.getStorageSync('wxUserInfo')
          if (userInfo) {
            that.globalData.hasUserInfo = true}},/ / session_key expired
        fail: function() {
          // Session_key expired. Log in again
          that.doLogin()
        }
      })
    } else {
      // If there is no skey, it is the first login
      this.doLogin()
    }
  },
  doLogin() {
    this.log().then(res= > {
      this.$post('/auth', { code: res.code }, false).then(data= > {
        wx.setStorageSync('sessionId', data.sessionId)
      })
    })
  },
  /** * wechat login to get the code value and pass the code to the server * @returns */
  log() {
    return new Promise(resolve= > {
      wx.login({
        success(res) {
          if (res.errMsg === 'login:ok') {
            resolve(res)
          } else {
            wx.showToast({
              title: 'wechat login failed'.icon: 'none'.duration: 1200
            })
          }
        },
        fail() {
          wx.showToast({
            title: 'Failed to call wechat login interface'.icon: 'none'.duration: 1200})}})})},globalData: {
    baseurl: 'https://www.fake.shop'}})Copy the code

Network request encapsulation

The API of network request in wechat applet is wx.request(), but this request is in the form of asynchronous callback, each request needs to write a long string, and if it is nested request, it will find that the code is too bloated, so it is necessary to make it Promisefy. The code is as follows:

 $get(url, data = {}, needToken = true) {
    let SUCCESS = 200
    var that = this
    needToken ? (data.token = wx.getStorageSync('ToKen')) : ' '
    return new Promise((resolve, reject) = > {
      wx.request({
        url: that.globalData.baseurl + url,
        method: "GET".header: {
          'content-type': 'application/json'
        },
        data: data,
        success(e) {
          if (e.data.code == SUCCESS) {
            resolve(e.data)
            return
          }

        },
        fail(e) {
          wx.showModal({
            title: 'tip'.content: 'Request failed'.showCancel: false
          })
          reject(e)
        }
      })
    })
  },
  $post(url, data = {}, needToken = true) {
    let that = this
    let SUCCESS = 200
    let TimeOut = 1000
    var that = this
    needToken ? (data.token = wx.getStorageSync('ToKen')) : ' '
    return new Promise((resolve, reject) = > {
      wx.request({
        url: that.globalData.baseurl + url,
        method: "POST".// The header can be set here according to the interface documentation
        // header: {
        // 'content-type': 'application/x-www-form-urlencoded'
        // },
        data: data,
        success(e) {
          if (e.statusCode == SUCCESS) {
            if (e.data.code == SUCCESS) {
              resolve(e.data)
            }
            else {
              reject(e)
              wx.showModal({
                title: 'tip'.content: e.data.msg,
                showCancel: false.success: function (res) {
                  if (res.confirm) {
                    if (e.data.code == TimeOut) { // Determine whether the validity period is expired based on the code returned by actual services
                      // Login expiredthat.doLogin(); }}}})}}else {
            wx.showModal({
              title: 'tip'.content: e.data.error,
              showCancel: false
            })
            reject(e)
          }
        },
        fail(e) {
          console.log(e)
          wx.showModal({
            title: 'tip'.content: 'Request failed'.showCancel: false
          })
          reject(e)
        },
        complete(e) {
        }
      })

    })
  },
Copy the code

Wechat public Account payment (wechat browser)

Although it is to write a small program to step on the pit guide, but in wechat H5 page payment and small program fell out of the payment or there are similarities, by the way record.

Application scenarios

  • H5 Mall website already exists. Users can call wechat Pay to complete the ordering and purchase process when they open the web page in wechat via message or scanning two-dimensional code.
To prepare

UnionID: In order to identify users, each user will generate a secure OpenID for each public account. If users need to share multiple public accounts and mobile applications, they need to go to wechat open platform and bind these public accounts and applications to an open platform account. After binding, Although a user has multiple openids for multiple public accounts and applications, he only has one UnionID webpage authorization for all public accounts and applications under the same open platform account: In some complex business scenarios, services need to be provided in the form of web pages, and users’ OpenID can be obtained through web page authorization (note: users’ consent is not required to obtain users’ OpenID, while users’ basic information needs to be approved) wechat JS-SDK: It is a toolkit for developers to use wechat’s native functions on web pages through JavaScript code. Developers can use it to record and play wechat voice on web pages, monitor wechat sharing, upload mobile phone local pictures, take photos and many other capabilities.

Business process timing diagram

The main process
  • There are two main ways to introduce JSSDK into web pages
    1. Need to call in JS interface pages to introduce the following JS file: res.wx.qq.com/open/js/jwe… How to use JSSDK
    2. Module introduction: Directly introduce NPM package weixin-js-SDK, can be directly installed through NPM, and then directly reference in the required files.
  • Web page authorization
    • My understanding is that webpage authorization is mainly to enable third-party web pages opened in wechat browser to perform operations associated with wechat public account and user’s wechat, and finally obtain user’s OpenID under this public account.
    • Website application wechat login is a wechat OAuth2.0 authorized login system based on OAuth2.0 protocol standard. There are two steps to obtaining openID
      1. The front end gets the code by jumping to the url and then sends the code to the back end
      2. The back end then gets the OpenID according to the code.

The code for

  • Before the wechat public account requests the user’s webpage authorization, the developer needs to modify the authorization callback domain name in the configuration option of “development – interface permission – Webpage service – Webpage account – Webpage authorization to obtain the user’s basic information” in the official website of the public platform. In this example, the callback domain name is www.foo.com
  • Service process Example: Pay page Address: payUrl => “www.foo.com/pay” 1. Want to jump to the payment page, if the browser is WeChat jump straight href (way. There are a lot of can be redirected the location href) to “open.weixin.qq.com/connect/oau…” + appid +”&redirect_uri=”+ URLEncoder.encode(payUrl) +”&response_type=code&scope=snsapi_base&state=123#wechat_redirect” 2. The system automatically jumps to payUrl and returns a code parameter such as => “www.aa.com/pay?code=aa…” 3. Then read the code and send the back end is OK, this should be able to do it.
Note:

URLEncoder. Encode (payUrl) is a very necessary state parameter: it is used to preserve the state of the request and callback, and after authorizing the request it is returned to the third party as is. This parameter can be used to prevent CSRF attacks (cross-site request forgery attacks). It is recommended that the third party wear this parameter and set it to a simple random number plus session for verification. Because I am the front end, do not want to engage in this (joking 😜), in fact, mainly because this part of the logical part of the sensitive public number of the secret key and so on, as well as in order to avoid the front end cross domain problems. The code is the time limit: As an access_token token, the code on the user’s authorization belt is different each time. The code can only be used once and will expire automatically if it is not used within 5 minutes. So this logic needs to be applied every time you make a payment

Wechat H5 switch up payment

  • The OpenID and merchant order number need to be sent to the back end, and the back end call API generates the configuration required by the front end call to pay for the JSAPI (this is mainly the back end logic)

    Without further ado, the code is as follows:

WechaConfig contains the configuration items passed to the front end to call getBrandWCPayRequest after calling the prepayment API.
		let config = {
				appId: this.wechaConfig.appId + ' '.// The public id is passed in by the merchant
				timeStamp: this.wechaConfig.timeStamp + ' '.// Timestamp, the number of seconds since 1970
				nonceStr: this.wechaConfig.nonceStr + ' './ / random string
				package: this.wechaConfig.package + ' '.// The value of prepay_id returned by the single interface is submitted in the format of prepay_id=***
				signType: this.wechaConfig.signType + ' '.// wechat signature:
				paySign: this.wechaConfig.paySign + ' '.// Wechat signature
			}
			// config = JSON.parse(JSON.stringify(config))
			WeixinJSBridge.invoke(
				'getBrandWCPayRequest',
				config,
				function(res) {
					if (res.err_msg == 'get_brand_wcpay_request:ok') {
						// Using the above method to judge the front-end return, the wechat team solemnly reminds: res.err_msg will return OK after the user pays successfully, but it does not guarantee that it is absolutely reliable.
						this.$router.push({
							name: 'payResult'.query: {
								status: true.id: this.addOrder.orderId,
							},
						})
					} else {
						this.$router.push({
							name: 'payResult'.query: {
								status: false,
							},
						})
					}
				}.bind(this))Copy the code

Note:

  1. If wx.choosewxpay () is used, the configuration field is timestamp instead of timestamp
  2. The reason why every variable in config is added ” for example: This.wechaconfig. AppId + “, because it was not added to the previous version of android can normally invoke wechat pay, but when tested on ios, Error: JsAPI appId missing or jsapipackage missing ((m -__-)m) I suspect that for some strange reason the appID value is not being parsed as a String, so I added this to fix it.

    One of the things that’s useful to look up is that the problem with payment is that the JSON parameters have to be all strings. {“timeStamp”:12312312}, the value of the timeStamp is an integer, although Android can pay, but IOS can not, must strictly according to the document said, key and value are all string! {“timeStamp”:”12312312″} > portal

  3. For local debugging, note that wechat uses port 80 by default

The original intention of writing this article was to record the pit I stepped on, so as to avoid repeating the pit step by my friends. Now it seems that the content is less dry goods, will continue to update later…

reference

  • Wechat open interface – applets