Пошаговое руководство по мини-программе WeChat [1]

Апплет WeChat

В последнее время, поскольку бизнес компании работал над проектом апплета WeChat, я воспользовался этой возможностью, чтобы подвести итоги и записать некоторые из ям, на которые я недавно наступил.

Связано со входом в апплет WeChat

登录流程时序

  1. Внешний интерфейс вызывает wx.login() для получения временных учетных данных для входа.code
  2. Отправьте код на сервер через wx.request() (требуется, чтобы бэкенд создал интерфейс для получения кода)
  3. Серверная часть выполняет проверку учетных данных для входа, а входные параметры (appid, secret, js_code, grant_type)

Объяснение общих терминов:

уникальный идентификатор апплета appid секретное приложение секрет апплета js_code Код, полученный при входе в систему Заполните grant_type как авторизация_код

  1. Если учетные данные для входа проверены, openid и session_key будут обменены с сервера WeChat.

уникальный идентификатор пользователя openid session_key сеансовый ключ

openid — это уникальный идентификатор пользователя, но его не рекомендуется использовать непосредственно в качестве идентификатора внутреннего сервера. session_key — это пароль для шифрования и подписи пользовательских данных. Session_key требуется для проверки файлов и получения информации о пользователе.

Как правило, из соображений безопасности ни один из этих двух данных не будет отправлен клиенту.

  1. После того, как серверная часть обрабатывает session_key, она возвращает обработанную строку во внешний интерфейс в качестве идентификатора входа пользователя, обычно в виде токена. (Пользовательский статус входа связан с openid session_key)
  2. Внешний интерфейс получает токен, сохраняет его в localStorage и берет с собой каждый раз, когда запрашивает данные с сервера в качестве учетных данных сервера для идентификации пользователя.
  3. Когда следующий пользователь входит в апплет, сначала вызовите wx.checkSession(), чтобы проверить статус входа в систему, и, если это не удастся, повторно инициируйте процесс входа.
//app.js
const NOLOGINCODE = 1000003 //未登录
const SUCCESS = 1000001 //成功
App({
  onLaunch: function() {
    var loginFlag = wx.getStorageSync('sessionId')
    var that = this
    if (loginFlag) {
      // 检查 session_key 是否过期
      wx.checkSession({
        // session_key 有效(未过期)
        success: function() {
          var userInfo = wx.getStorageSync('wxUserInfo')
          if (userInfo) {
            that.globalData.hasUserInfo = true
          }
        },
        // session_key 过期
        fail: function() {
          // session_key过期,重新登录
          that.doLogin()
        }
      })
    } else {
      // 无skey,作为首次登录
      this.doLogin()
    }
  },
  doLogin() {
    this.log().then(res => {
      this.$post('/auth', { code: res.code }, false).then(data => {
        wx.setStorageSync('sessionId', data.sessionId)
      })
    })
  },
  /**
   *微信登录 获取code值,并将code传递给服务器
   * @returns
   */
  log() {
    return new Promise(resolve => {
      wx.login({
        success(res) {
          if (res.errMsg === 'login:ok') {
            resolve(res)
          } else {
            wx.showToast({
              title: '微信登录失败',
              icon: 'none',
              duration: 1200
            })
          }
        },
        fail() {
          wx.showToast({
            title: '微信登录接口调用失败',
            icon: 'none',
            duration: 1200
          })
        }
      })
    })
  },
  globalData: {
    baseurl: 'https://www.fake.shop'
  }
})

инкапсуляция сетевых запросов

API сетевого запроса в апплете WeChat — wx.request(), но этот запрос в виде асинхронного обратного вызова, при каждой отправке запроса должна быть написана длинная строка, и если это вложенный запрос , вы обнаружите, что код написан довольно раздутым, поэтому создание Promisefy практически необходимо. код показывает, как показано ниже:

 $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: '提示',
            content: '请求失败',
            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",
        //此处可以根据接口文档设置header头
        // 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: '提示',
                content: e.data.msg,
                showCancel: false,
                success: function (res) {
                  if (res.confirm) {
                    if (e.data.code == TimeOut) { //根据实际业务返回的code码判断是否过期
                      // 登录过期
                      that.doLogin();
                    }
                  }
                }
              })
            }
          } else {
            wx.showModal({
              title: '提示',
              content: e.data.error,
              showCancel: false
            })
            reject(e)
          }
        },
        fail(e) {
          console.log(e)
          wx.showModal({
            title: '提示',
            content: '请求失败',
            showCancel: false
          })
          reject(e)
        },
        complete(e) {
        }
      })

    })
  },

Оплата официальной учетной записи WeChat (браузер WeChat)

Хоть я и пишу гайд по ступлению на яму маленькой программы, сходство между оплатой на странице Н5 в WeChat и оплатой в маленькой программе все же есть, так что запишем, кстати.

Сценарии применения

  • Уже существует веб-сайт торгового центра H5.Когда пользователи открывают веб-страницу в WeChat через сообщение или сканируют QR-код, они могут вызвать оплату WeChat, чтобы завершить процесс размещения заказа и покупки.
Подготовить

UnionID: чтобы идентифицировать пользователей, каждый пользователь будет генерировать безопасный OpenID для каждой официальной учетной записи.Если вам нужно разделить пользователей между несколькими официальными учетными записями и мобильными приложениями, вам нужно перейти на открытую платформу WeChat, чтобы связать эти официальные учетные записи и приложения. , Назначенный учетной записи открытой платформы, после привязки, хотя у пользователя есть несколько разных OpenID для нескольких официальных учетных записей и приложений, у него есть только один UnionID для всех этих официальных учетных записей и приложений под одной и той же учетной записью открытой платформы. Авторизация веб-страницы: в некоторых сложных бизнес-сценариях услуги должны предоставляться в виде веб-страниц, и openid пользователя может быть получен через авторизацию веб-страницы (Примечание: согласие пользователя не требуется для получения OpenID пользователя, и согласие пользователя требуется для получения основной информации о пользователе) WeChat JS-SDK: это набор инструментов для разработчиков, позволяющий использовать встроенные функции WeChat на веб-страницах с помощью кода JavaScript. Разработчики могут использовать его для записи и воспроизведения голоса WeChat на веб-страницах, мониторинга совместного использования WeChat, загрузки локальных изображений на мобильные телефоны, фотографирования. , и многие другие возможности.

Диаграмма последовательности бизнес-процессов

业务流程时序图

Основной процесс
  • Есть два основных типа jssdk, представленных на веб-страницах.
    1. Вставьте следующие файлы JS на страницу, которая должна вызывать интерфейс JS:Горячая вода Думаю QQ.com/open/is/price… Шаги использования JSSDK
    2. Импорт модуля: Непосредственно импортировать пакеты npmweixin-js-sdk, который можно установить напрямую через npm, а затем ссылаться непосредственно в необходимых файлах.
  • Авторизация веб-страницы
    • Насколько я понимаю, авторизация веб-страницы в основном предназначена для того, чтобы сторонние веб-страницы, открытые в браузере WeChat, могли выполнять операции, связанные с общедоступной учетной записью WeChat и WeChat пользователя, и, наконец, получать общедоступную учетную запись пользователя под общедоступной учетной записью.openid.
    • Приложение веб-сайта WeChat login — это авторизованная система авторизации WeChat OAuth2.0, основанная на стандарте протокола OAuth2.0. Получение openid разделено на два шага
      1. Внешний интерфейс получает код через URL-адрес перехода, а затем отправляет код на серверную часть.
      2. Затем серверная часть получает openid на основе кода.

получить код

  • Прежде чем официальная учетная запись WeChat запросит авторизацию веб-страницы пользователя, разработчику необходимо перейти к параметру конфигурации «Разработка — Разрешение интерфейса — Веб-служба — Веб-учетная запись — Веб-авторизация для получения основной информации о пользователе» на официальном веб-сайте официальной платформы. и измените доменное имя обратного вызова авторизации. В этом примере имя домена обратного вызоваwww.foo.com
  • Пример бизнес-процесса: Адрес платежной страницы: payUrl => "www.foo.com/pay1. Когда вы хотите перейти на страницу оплаты, если онаБраузер WeChatПерейти непосредственно к href (существует множество способов перенаправления или location.href) на "open.WeChat.QQ.com/connect/OA U…"+ appid +"&redirect_uri="+ URLEncoder.encode(payUrl) +"&response_type=code&scope=snsapi_base&state=123#wechat_redirect" 2. Система автоматически перейдет к payUrl и вернет код параметра, такой как => "Woohoo.ah ah.com/ Боюсь, что есть?code=ah ah...3. Затем прочитать код и отправить бэкенд, чтобы все было в порядке, это должны знать все.
Примечание:

URLEncoder.encode(payUrl) очень нужен Параметр состояния: используется для поддержания состояния запроса и обратного вызова, а также для передачи его третьей стороне в том виде, в каком оно есть после авторизации запроса. Этот параметр можно использовать для предотвращения csrf-атак (атаки с подделкой межсайтовых запросов). Рекомендуется, чтобы этот параметр привносили третьи лица. Для проверки можно установить простое случайное число плюс сессию. Причина, по которой бэкэнд получает openid: Поскольку я являюсь фронтендом, я не хочу этого делать (шучу 😜), на самом деле это может быть в основном потому, что эта часть логики чувствительнаоткрытый ключи т. д., а также во избежание междоменных проблем с внешним интерфейсом. Код является ограничением по времени: код используется в качестве билета в обмен на access_token, и код при авторизации каждого пользователя будет разным.Код можно использовать только один раз, и срок его действия автоматически истечет, если он не используется в течение 5 минут.Таким образом, каждый раз, когда вы совершаете платеж, вам нужно выполнять описанную выше логику.

Оплата перевода H5 в WeChat

  • Openid и номер заказа продавца должны быть отправлены на серверную часть, и серверная часть вызывает API для генерации конфигурации, необходимой интерфейсу для вызова платежного jsapi (в основном это логика серверной части)
    配置
    Без лишних слов, код выглядит следующим образом:
//this.wechaConfig 里面保存的是后端调用预支付api 以后传递给前端用来调用getBrandWCPayRequest 的配置项。
		let config = {
				appId: this.wechaConfig.appId + '', // 公众号名称,由商户传入
				timeStamp: this.wechaConfig.timeStamp + '', // 时间戳,自 1970 年以来的秒数
				nonceStr: this.wechaConfig.nonceStr + '', // 随机串
				package: this.wechaConfig.package + '', //	统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
				signType: this.wechaConfig.signType + '', // 微信签名方式:
				paySign: this.wechaConfig.paySign + '', // 微信签名
			}
			// config = JSON.parse(JSON.stringify(config))
			WeixinJSBridge.invoke(
				'getBrandWCPayRequest',
				config,
				function(res) {
					if (res.err_msg == 'get_brand_wcpay_request:ok') {
						// 使用以上方式判断前端返回, 微信团队郑重提示:res.err_msg 将在用户支付成功后返回    ok,但并不保证它绝对可靠。
						this.$router.push({
							name: 'payResult',
							query: {
								status: true,
								id: this.addOrder.orderId,
							},
						})
					} else {
						this.$router.push({
							name: 'payResult',
							query: {
								status: false,
							},
						})
					}
				}.bind(this)
			)

Уведомление:

  1. Если вы используете wx.choosewxpay(), то в поле конфигурации указывается TimeStamp вместо TimeStamp
  2. Причина, по которой каждая переменная в переменной конфигурации добавляется с помощью «», например: this.wechaconfig.Appid + '', поскольку до того, как она была добавлена, платеж WeChat можно нормально вызывать на Android, но при тестировании на iOS это будет Сообщите о отсутствии jsapi appid или отсутствия jsapackage (что, черт возьми, в моем сердце в то время (((m -__-) m я явно передал его), поэтому плюс много информации, искал, сказала, что это был json Задача формата, я думаю, это может быть, потому что это очень странно, причина (рассужденный и чистый большой парень прокомментировал область комментариев), значение APPID не анализируется как тип строки, поэтому я добавил это, чтобы это было справиться с этим.

    Один из наиболее полезных найденных заключается в том, что проблема заключается в том, что при оплате параметры JSON должны быть полностью строковыми. Например, моя ошибка в том, что в параметре {"timeStamp":12312312} значение timestamp целое число. Хотя на Android это можно оплатить, на IOS нельзя. Это должно быть строго по документ.Ключи и значения - все символы.строка! Так что {"timeStamp":"12312312"} > правильно!портал

  3. Если вы выполняете локальную отладку, обратите внимание, что интерфейс WeChat по умолчанию использует порт 80.

Первоначальной целью написания этой статьи было записать ямы, на которые я наступал, чтобы мои друзья не наступали на ямы повторно. Похоже, что контента все еще относительно мало, и он будет обновляться в будущем. . .

Ссылаться на