## 微信支付

快应用支持微信支付的两种接入方式：[app 支付](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1) 和 [网页支付](https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20)。

针对微信的 [网页支付](https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20) 接入方式，快应用提供了两种接口调用方式。

快应用支持 3 种微信支付类型：

- app 支付
- 网页支付（ referer 方式）
- 网页支付（中间页方式）

建议开发者同时支持 app 支付和微信网页支付，网页支付只需要实现其中一种即可，建议网页支付使用 referer 方式实现。

默认情况下，所有预置快应用引擎的设备都支持微信网页支付方式接入，大部分设备支持微信 app 支付。根据微信的文档，使用 app 方式支付相比网页方式更加安全，所以快应用引擎在设备支持 app 支付的情况下，优先支持 app 支付。

### 基本流程

在快应用中使用微信支付的基本流程如下：

- 1. 在 app.json 中配置 wxpay 参数
- 2. 使用 qa.getWxPaymentType()获取支付类型
- 3. 根据获取到的支付类型，使用对应的支付参数发起支付调用

### 参数配置

app 支付方式和网页支付方式所需要配置的参数不同，参数内容参考[全局配置](../../reference/configuration/app.html)，具体如下：

| 支付类型          | 微信支付接入方式 | 需配置参数    |
| ----------------- | ---------------- | ------------- |
| app 支付          | 微信 app 支付    | package, sign |
| 网页 referer 方式 | 微信网页支付     | 无            |
| 网页中间页方式    | 微信网页支付     | url           |

### 获取支付类型

快应用中，支付类型由[wxpay 参数](../../reference/configuration/app.html#wxpay) 和 当前设备所支持的支付类型相关。由于开发者无法主动设置，所以在发起支付调用前，应当使用 qa.getWxPaymentType()获取当前快应用微信支付类型。

wxpay 参数和设备支持的关系如下：

| wxpay 参数         | 设备是否支持 app 支付 | qa.getWxPaymentType()返回值 |
| ------------------ | --------------------- | --------------------------- |
| package 或 sign    | 是                    | APP                         |
| package 或 sign    | 否                    | MWEB                        |
| 无 package 或 sign | 是                    | MWEB                        |
| 无 package 或 sign | 否                    | MWEB                        |

### 支付类型说明

#### app 支付

根据 [wxpay 参数](../../reference/configuration/app.html#wxpay)， 还有快应用微信支付接口[qa.getWxPaymentType](../../api/open-api/wxpay/qa.getWxPaymentType.md) 和 [qa.requestWxPayment](../../api/open-api/wxpay/qa.requestWxPayment.md)，在 app.json 中配置相关参数：

```json
  "wxpay": {
    "package": "com.tongwei.toiletGame",
    "sign": "xxxxxxxxx"
  }
```

调用支付接口

```js
var payType = qa.getWxPaymentType()
if (payType === 'APP') {
  qa.requestWxPayment({
    //微信 app支付的prepayId
    prepayid: 'your order prepayid,eg: wx20170101abcdef1234567890',
    extra: {
      app_id: 'your app_id',
      partner_id: 'your partner_id',
      package_value: 'your package_value',
      nonce_str: 'your nonce_str',
      time_stamp: 'your time_stamp',
      order_sign: 'your order sign'
    },
    fail: function(ret) {
      console.log(`WX PAY failed, code = ${ret.errCode}`)
    },
    cancel: function() {
      console.log('WX PAY cancelled by user')
    },
    success: function() {
      console.log('WX PAY success')
    }
  })
}
```

#### 网页支付（referer 方式）

网页支付 referer 方式不需要配置 app.json 参数，和网页支付（中间页方式）的差别在于调用参数，具体可以参考快应用微信支付接口[qa.getWxPaymentType](../../api/open-api/wxpay/qa.getWxPaymentType.md) 和 [qa.requestWxPayment](../../api/open-api/wxpay/qa.requestWxPayment.md)说明。

调用支付接口

```js
var payType = qa.getWxPaymentType()
if (payType === 'MWEB') {
  qa.requestWxPayment({
    // 微信网页支付的prepayId
    prepayid: 'your order prepayid,eg: wx20170101abcdef1234567890',
    referer: 'your host name configured in wechat, eg: https://www.quickapp.cn',
    extra: {
      // 需要将微信返回的MWEB_URL地址配置到这里
      mweb_url: 'https://wx.tenpay.com/cgi-bin/mmpayweb-bin'
    },
    fail: function(ret) {
      console.log(`WX H5 PAY handling fail, code = ${ret.errCode}`)
    },
    cancel: function() {
      console.log('WX H5 PAY handling cancel')
    },
    success: function(data) {
      //H5方式下，支付成功的回调仅仅只是指将订单递交给微信，并不意味着支付已经成功完成
      console.log('WX H5 PAY handling success')
    }
  })
}
```

#### 网页支付（中间页方式）

中间页方式较为复杂，需要在开发者的服务器端实现一个中间页面，用于转发请求。该中间页面的域名需要和配置在微信支付后台的域名一致。

根据 [wxpay 参数](../../reference/configuration/app.html#wxpay) 还有快应用微信支付接口[qa.getWxPaymentType](../../api/open-api/wxpay/qa.getWxPaymentType.md) 和 [qa.requestWxPayment](../../api/open-api/wxpay/qa.requestWxPayment.md)说明，在 app.json 中配置相关参数：

```json
  "wxpay": {
    "url": "https://xxx.xxx"  // 中间页的地址
  }
```

调用支付接口

```js
var payType = qa.getWxPaymentType()
if (payType === 'MWEB') {
    qa.requestWxPayment({
      //微信网页支付的prepayId
      prepayid: 'your order prepayid,eg: wx20170101abcdef1234567890',
      extra: {
        //传递给支付页面的自定义参数, 根据需要进行设置, 会被urlEncode之后拼接在配置的url尾部
        mweb_url: 'https://wx.tenpay.com/cgi-bin/mmpayweb-bin',
        customeKey1: 'customeValue1',
        customeKey2: 'customeValue2'
      },
      fail: function (ret) {
        console.log(`WX H5 PAY handling fail, code = ${ret.errCode}`)
      },
      cancel: function () {
        console.log('WX H5 PAY handling cancel')
      },
      success: function () {
        //H5方式下，支付成功的回调仅仅只是指将订单递交给微信，并不意味着支付已经成功完成
        console.log('WX H5 PAY handling success')
      }
    })
  } else {
    console.log('WX PAY is not avaliable')
  }
}
```

##### 中间页参考实现

```html
<html>
  <head>
    <title>wxpay 中间页</title>
  </head>
  <body>
    <script>
      function parseUrl(url) {
        var result = {}
        var query = url.split('?')[1]
        var queryArr = query.split('&')
        queryArr.forEach(function(item) {
          var value = item.split('=')[1]
          var key = item.split('=')[0]
          result[key] = value
        })
        return result
      }

      var url = location.href
      var result = parseUrl(url)

      if (result.mweb_url) {
        location.href = decodeURIComponent(result.mweb_url)
      }
    </script>
  </body>
</html>
```
