WeChat pay

H5 payment within wechat (payment by official account)

Adopt a unified introduction of JSSDK new way to achieve payment logic.

  • JSSDKThe documentaddress
  • Web page authorization (obtainaccess_tokenopenid) documentaddress
  • Unified single document address
  • Within the WeChatH5Call up the payment fileaddress

Identify two access_tokens

  • Web page authorizationaccess_tokenBased on:The 2.0, you need tocodeUsed to maintain the login status.
  • ordinaryaccess_token: background can be directly generated for exchangejsapi_ticketAnd then encrypt itsignatureAs awx.configParameters.

The whole process

The unified payment ordering interface requires OpenID, so it must be obtained by authorization. Because only openID is required here, snsapi_base is silent authorization for scope. (For convenience, code walk silent authorization is obtained for each entry here.)

  1. Enter the page and check whether there is code on the link. If there is no code on the link, the request interface will get the URL redirection:

    {
      url: 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx1232123123&redirect_uri= with parameters (including anchor) encoded redirect callback address & response_typ e=code&scope=snsapi_base&connect_redirect=1&state=xxxx#wechat_redirect';
    }
    // connect_redirect=1 Indicates that only one request is triggered
    Copy the code
  2. After multiple internal redirection in wechat, finally with code and state 301 redirection back to the set callback address:

    301: https://www.flqin.com/test.html?id=135price=1322&code=ASDJIAJD13D823D&state=13212313#/
    Copy the code
  3. When the front end detects that the link has a code, it sends the code and some other parameters required by the page to the back end, and the back end gets the code to exchange for web authorization access_token and OpenID. Here, the back end can store access_token/refresh_token in a cookie or maintain the login state by other means JWT without having to retrieve the code repeatedly.

  4. Openid is a mandatory parameter for unified order JSAPI interface, used to obtain the prepay_id parameter value, that is, package parameter. Finally, the interface uniformly returns the parameters required by Wx. confg and Wx. chooseWXPay, and the front end calls JSSDK.

  5. Wx. ChooseWXPay’s successful completion callback only represents payment completion,

Code demo:

  async queryWxCode() {
    / /...
    if(! code) {const { data } = await api.wxToPay({url:'Current page full link'}).catch((e) = > e); // Get redirected link (wechat authorized address)
      data && (window.location.href = data);
      return;
    }
    return api.wxPay({code,url:'Current page contains parameter URL'});  Wx. config, wx.choosepay
  },
  async registerWx() {
    const { data } = await this.queryWxCode().catch((e) = > {});
    this.wxSdkInfo = data;
    wx.config({
      debug: false.// Enable debugging mode
      appId: data.appId, // Mandatory, the unique identifier of the public account
      timestamp: data.timeStamp, // Mandatory to generate the timestamp of the signature
      nonceStr: data.nonceStr, // Mandatory to generate a random string of signatures
      signature: data.signature, // Mandatory. Signatures are generated using common access_token without authorization
      jsApiList: ['chooseWXPay'.'hideMenuItems'] // Mandatory, a list of JS interfaces to be used
    });
    wx.ready(() = > {
      this.hideWxMenus();
      this.createWxpay();
    });
  },
  hideWxMenus() {
    // Disable payment sharing to prevent errors caused by entering the page without order generation
    const menuList = ['menuItem:share:appMessage'.'menuItem:share:timeline'.'menuItem:copyUrl'];
    wx.hideMenuItems({
      menuList // For menu items to be hidden, you can only hide the "Propagate Class" and "Protect Class" buttons. See Appendix 3 for all menu items
    });
  },
  createWxpay() {
    const data = this.wxSdkInfo;
    wx.chooseWXPay({
      timestamp: data.timeStamp, // Payment signature timestamp, note that all use timestamp fields in wechat JSSDK are lowercase. But the latest version of the payment background generated signature timeStamp field name needs to capitalize the S character
      nonceStr: data.nonceStr, // The payment signature is a random string, no longer than 32 bits
      package: `prepay_id=${data.prepayId}`.// The prepay_id parameter returned by the unified payment interface, submitted in the following format: prepay_id=\*\*\*) This parameter requires openID
      signType: data.signType, // Signature mode, default is 'SHA1', use the new version of payment to pass 'MD5'
      paySign: data.paySign, // Payment signature The parameters of the signature are appId, timeStamp, nonceStr, Package and signType
      success: this.queryPayment, // Public query result interface
      fail: this.showFail, // Failed processing
      cancel: this.showRefail, // Cancel processing
      complete({ errMsg }) {
        const SUCCESS = /:ok/gi.test(errMsg);
        const CANCEL = /:cancel/gi.test(errMsg);
        if (SUCCESS) this.queryPayment();
        else if (CANCEL) this.showRefail();
        else this.showFail(); }}); },Copy the code

Alipay Payment

Alipay inside H5 payment

Alipay JSAPI must be accessed.

  • H5Development of the documentaddress
  • Alipay JSSDK address
  • Payment document address

Note:

  • Do not involve reading user coupons and so on, go ordinary no single number payment, that is, without authorization.
  • The authorization process is roughly the same as wechat.

Code demo:

    async registerAlipay() {
      const alipayInit = async() = > {await this.queryAliOrder().catch((e) = > e);
        this.createAlipay();
      };
      if (window.AlipayJSBridge) alipayInit();
      else document.addEventListener('AlipayJSBridgeReady', alipayInit, false);
    },
    async queryAliOrder() {
      // No tracking number
      const {data: orderStr } = await api.aliPayH5({orderId:1}).catch((e) = > e);// Request the interface to get orderStr
    },
    async queryAliCode() {
      // Pay tradeNo with single number (pay in person when the background opens), the same as wechat authorization process
      const { href, search } = window.location;
      const query = search && search.replace(/[?\/]/g.' ');
      const { auth_code: code } = qs.parse(query);
      if(! code) {const { data } = await api.aliToPay(href).catch((e) = > e); // Request the interface to obtain the authorized address of Alipay
        data && (window.location.href = data);
        return;
      }
      const {data: tradeNO }  = await api.aliPayH5({orderId:1,code}).catch((e) = > e); // Request the interface to get tradeNO
    },
    async createAlipay() {
      AlipayJSBridge.call('tradePay', { 'orderStr/tradeNO' }, ({ resultCode }) = > {
        const SUCCESS_CODES = ['9000'.'8000'.'6004'];
        const UNKNOW_CODES = ['7001'.'6001'.'6002'];
        if (~SUCCESS_CODES.indexOf(resultCode)) _this.queryPayment(); // Payment query
        else if (~UNKNOW_CODES.indexOf(resultCode)) _this.showRefail();
        else _this.showFail();
      });
    },
Copy the code

Third-party browser alipay payment

  • Payment document address
  • Parameter Description Address

Without authorization, the URL and order number are directly sent to the back end, and the back end returns a form and adds it to the page to evoke alipay APP. After the payment is completed, Alipay will automatically jump back to the payment result page and carry a bunch of parameters according to the back end configuration. At this point, you need to query the common results interface to determine whether the payment was successful.

Note:

  • Whether there are parameters on the linkalipay.trade.wap.pay.returnTo determine if the payment callback is back to the page.

Code demo:

  registerH5() {
    const { origin, pathname, search } = window.location;
    const { method } = qs.parse(search.replace(/[?\/]/g.' '));
    if (method === 'alipay.trade.wap.pay.return') {
      this.queryPayment(); // Execute the public query result interface
      return;
    }
    const { data: form } = await api.aliPayH5(orderId,url).catch((e) = > e); // Request the interface to return the form form
    if(! form)return;
    const div = document.createElement('div');
    div.innerHTML = form;
    document.body.appendChild(div);
    document.forms[0].submit();
  }
Copy the code

Public query result queryPayment

The payment results need to be polled.

Code demo:

async queryPayment() {
  const TIMES_REACH = 0;
  const TIMES_MAX = 5;
  const SUCCESS_CODE = '1'; 1 The payment is successful. -1 Is abnormal
  const WAITING_CODE = '0';
  if (this.qTimes === TIMES_REACH) { //qTimes indicates the maximum number of queries
    this.qTimes = TIMES_MAX;
    return;
  }
  const { data } = await api.payStatus(orderId).catch((e) = > e); // Query the payment result
  if (data == SUCCESS_CODE) { // Success status
    this.showSuccess();
    this.qTimes = TIMES_MAX;
  } else if (data == WAITING_CODE) { // Wait state
    console.log('Query payment result... ');
    clearTimeout(this.timer);
    this.timer = setTimeout(async() = > {await this.queryPayment(); // Recursive polling
      this.qTimes -= 1;
    }, 1000);
  } else {
    this.showFail(); }},Copy the code

Payment summary

  • Wechat alipay all need to configure a legitimate domain name, can be accurate to the folder path.
  • Development available wechat development tools, combined with alert debugging, directly send the code to the test environment has configured the best domain name test.
  • Pay attention to the case of parameters and the content passed. The main complexity of payment is concentrated in the back end, and the front end needs to coordinate with the back end.

share

Wechat – > wechat (wechat contacts, wechat moments, QQ Contacts, QQ space)

The JSSDK must be introduced, otherwise the description and image cannot be set.

  • JSSDKDocuments:address
  • For ordinaryaccess_tokenDocuments:address

We need to pass the current page URL with parameters to the back end (no encoding required) and let the back end return the parameters required by wx.config:

const { data } = await api.getWxConfig({ url: 'Current page contains parameter URL' }); // The interface returns appId, timeStamp, nonceStr, signature.
wx.config({
  debug: true.appId: data.appId, // Mandatory, the unique identifier of the public account
  timestamp: data.timeStamp, // Mandatory to generate the timestamp of the signature
  nonceStr: data.nonceStr, // Mandatory to generate a random string of signatures
  signature: data.signature, // Mandatory, signature
  jsApiList: ['onMenuShareTimeline'.'onMenuShareAppMessage'.'onMenuShareQQ'.'onMenuShareQZone'].// Mandatory, a list of JS interfaces to be used
});
wx.ready(() = > {
  const shareList = ['onMenuShareTimeline'.'onMenuShareAppMessage'.'onMenuShareQQ'.'onMenuShareQZone'];
  shareList.forEach((item) = > {
    wx[item]({
      title: this.shareInfo.title, // Share the title
      desc: this.shareInfo.description, // Share the description
      link: window.location.href,
      imgUrl: this.shareInfo.image, // Share ICONS
      success: function () {
        // The setting succeeded}}); }); });Copy the code

Note:

  • First of all, we need to set the interface security domain name in wechat background:www.xxxx.com, do not need to specific path and parameters.
  • The front end only needs to pass the current page with parameters to the backgroundurlThe interface can even fetch the request page with parametersurl, the front end does not need to pass.
  • Pay attention totimeStampThe case of.
  • Pay attention tojsApiListIf you select a share interface that is about to be abandoned, the new share interface is not easy to use.
  • Share without authorization, because: parameternonceStr <- jsapi_ticket <- access_token <- appid,secret. thisaccess_tokenFor ordinaryaccess_token.appidsecretAll obtained in wechat background. Different from payment and other web authorizationaccess_token.

QQ(TIM) -> QQ(QQ contact, QQ Space, wechat contact, wechat moments)

Need to introduce apis:

<script src="//open.mobile.qq.com/sdk/qqapi.js"></script>
Copy the code

Js:

const share = {
  title: 'Share title, maximum 45 bytes'.desc: 'Share content, Max. 60 bytes'.image_url: 'Image URL, minimum 200 * 200'.share_url: 'Share link with page URL'}; mqq.data.setShareInfo(share, callback);Copy the code

The MQQ. UI. ShowShareMenu (); Can directly evoke QQ sharing panel.

Alipay -> Alipay (Friends, contacts)

Set meta as follows:

<meta name="Alipay:title" content="Share title" />
<meta name="Alipay:imgUrl" content="Share image URL" />
<meta name="Alipay:desc" content="Share description" />
<meta name="Alipay:link" content="Share links" />
Copy the code

Weibo, Toutiao, Zhihu and other platforms browser -> wechat, QQ

Micro-blog can register light application using JS-SDK to complete sharing Settings. I didn’t do it for a lot of money. Zhihu test IOS can write dead description and dynamic title, picture can not be set, Android can only set the title.

For sharing on other platforms, the unified bottom-saving treatment is as follows:

Share title and description set head element:

<head>
  <title>Share the title</title>
  <meta name="description" content="Share description" />
</head>
Copy the code

Sharing picture and description Settings (generally, the first picture and the description in the first paragraph of the page are taken by default) :

<body>
  <div style="display: none;">
    <p>Share the description</p>
    <img src="Image url" />
  </div>
</body>
Copy the code

Use the ogp:

<meta Property ="og:type" content="website"> <meta property="og:type" content="website" <meta property="og:description" content=" description" > Content =" full share page address "> </head>Copy the code