Несмотря на то, что я новичок, я всё равно хочу поделиться
Сначала дам干货 код
Адрес GitHub для интеграции WeChat JSSDK
Адрес Gitee для интеграции WeChat JSSDK
Причина этого проекта заключается в том, что из-за серьёзной эпидемии руководство потребовало создать специализированную страницу, которая могла бы помочь нуждающимся людям. Итак, я и мой коллега работали до поздней ночи, чтобы завершить проект. После развертывания и запуска страницы, мы поделились ей с помощью встроенного браузера WeChat. В идеальном состоянии она должна была выглядеть так, как показано на следующем рисунке ⬇️
Однако, результат не был таким, каким мы ожидали, и мы оставили слезы от отсутствия технических знаний, как показано на следующем рисунке ⬇️
Оказалось, что нет ключевых слов и изображения для отображения. После неустанных усилий я пришёл к выводу, что у меня недостаточно технических знаний и обратился к экспертам. Они пришли к следующим выводам.- 1. Если вы хотите настроить отображение описания и изображения для встроенного браузера WeChat, вам необходимо интегрировать WeChat JSSDK и иметь соответствующий WeChat публичный аккаунт (appId и appSecret). Обратите внимание, что это невозможно для 小程序 (appId и appSecret).
Таким образом, интеграция WeChat JSSDK становится необходимостью!
Наиболее подробное руководство для новичков по интеграции WeChat JSSDK, в котором полностью описаны шаги по интеграции WeChat JSSDK, конкретный код и проблемы, с которыми вы можете столкнуться, а также показаны итоговые результаты и опубликованы на GitHub. Статья длинная, но самая полная. Прошу не критиковать, это для новичков, проверено на практике и работает!!!
Расслабьтесь и посмотрите постепенно************
Для подключения к любой платформе официальная документация является эталоном, хотя некоторые ключевые моменты упоминаются вскользь. Мы должны внимательно изучить документацию, чтобы иметь общее представление. Нажмите официальную документацию WeChat для открытия документа, как показано ниже ⬇️
Используйте среду разработки IDEA, создайте проект SpringBoot, назовите проект springboot-wexin, структура каталога如下:
AjaxJson.java - пользовательский класс для упаковки формата данных, возвращаемых на фронтенд
/**
* Copyright © 2005-2020 <a href="http://www.jhmis.com/">jhmis</a> All rights reserved.
*/
package net.javadog.springbootwexin.common;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.LinkedHashMap;
import java.util.List;
/**
* JSON, который нужно принять после $.ajax
*
*/
public class AjaxJson {
private boolean success = true; // Успешно ли
private String errorCode = "-1"; // Код ошибки
private String msg = "Операция выполнена успешно"; // Сообщение
private Long count; // Количество записей в таблице
private List<?> data; // Данные таблицы
private LinkedHashMap<String, Object> body = new LinkedHashMap<String, Object>(); // Мап для упаковки JSON
public static AjaxJson ok(){
AjaxJson j = new AjaxJson();
return j;
}
public static AjaxJson ok(String msg){
AjaxJson j = new AjaxJson();
j.setMsg(msg);
return j;
}
``````java
public static AjaxJson ok(String msg, Object object) {
AjaxJson j = new AjaxJson();
j.setMsg(msg);
j.setResult(object);
return j;
}
public static AjaxJson ok(Object object) {
AjaxJson j = new AjaxJson();
j.setResult(object);
return j;
}
public static AjaxJson fail(String errorMsg) {
AjaxJson j = new AjaxJson();
j.setSuccess(false);
j.setErrorCode("999"); // По умолчанию код ошибки
j.setMsg(errorMsg);
return j;
}
public static AjaxJson fail(String errorCode, String errorMsg) {
AjaxJson j = new AjaxJson();
j.setSuccess(false);
j.setErrorCode(errorCode);
j.setMsg(errorMsg);
return j;
}
// Возвращает данные layui-таблицы без пагинации
public static AjaxJson layuiTable(List<?> list) {
AjaxJson j = new AjaxJson();
j.setSuccess(true);
j.setCount(Long.valueOf(list.size()));
j.setData(list);
return j;
}
public LinkedHashMap<String, Object> getBody() {
return body;
}
public void setBody(LinkedHashMap<String, Object> body) {
this.body = body;
}
public void put(String key, Object value) { // Добавляет свойство в JSON, для доступа из JS используйте data.map.key
body.put(key, value);
}
public void remove(String key) {
body.remove(key);
}
/**
* Прямое установление содержимого result
*
* @param result
*/
public void setResult(Object result) {
body.put("result", result);
}
@JsonIgnore // Пропускает это свойство при возврате объекта
public Object getResult() {
return body.get("result");
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) { // Добавляет свойство в JSON, для доступа из JS используйте data.msg
this.msg = msg;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
public Long getCount() {
return count;
}
public void setCount(Long count) {
this.count = count;
}
public List<?> getData() {
return data;
}
``````java
public void setData(List<?> data) {
this.data = data;
}
}
WxInitController.java - Контроллер для инициализации подключения к WeChat
package net.javadog.springbootwexin.controller;
import net.javadog.springbootwexin.common.AjaxJson;
import net.javadog.springbootwexin.service.WxService;
import net.javadog.springbootwexin.utils.WxUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* Программист JavaDog с низким статусом и ограниченными возможностями
* blog.javadog.net
*
* @BelongsProject: springboot-wexin
* @BelongsPackage: net.javadog.springbootwexin.controller
* @Author: hdx
* @CreateTime: 2020-02-14 14:52
* @Description: Контроллер для инициализации входа в WeChat
*/
@RestController
@RequestMapping("/weixin")
public class WxInitController {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private WxService wxService;
}
``` /**
*@Author: hdx
*@CreateTime: 20:39 2020/2/14
*@param: shareUrl адрес для обмена
*@Description: Инициализация конфигурации JSSDK WeChat
1. Сначала запросите адрес WeChat с параметрами appId и appSecret для получения AccessToken
2. Затем используйте полученный AccessToken для запроса адреса WeChat для получения временного билета jsapi_ticket (здесь не учитывается частота запросов, пользователь может использовать кэширование или задачи по расписанию)
3. Используйте полученный JssdkGetticket, timestamp, nonceStr и url для запроса адреса WeChat для получения подписи signature
4. Верните полученные данные signature, jsapi_ticket, nonceStr, timestamp и url на фронтенд для инициализации конфигурации
*/
@RequestMapping("/initWXJSSDKConfigInfo")
public AjaxJson initWXJSConfig (@RequestParam(required = false) String url) throws Exception{
logger.info("url=" + url);
String json = "";
try {
Map map = wxService.initJSSDKConfig(url);
json = WxUtil.mapToJson(map);
}catch (Exception e){
AjaxJson.fail(e.getMessage());
}
return AjaxJson.ok(json);
}}
WxService.java - Инициализация JSSDKConfig
package net.javadog.springbootwexin.service;
import lombok.Getter;
import net.javadog.springbootwexin.utils.WxUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
``````markdown
/**
* Программист JavaDog с низким статусом и ограниченными возможностями
* blog.javadog.net
*
* @BelongsProject: springboot-wexin
* @BelongsPackage: net.javadog.springbootwexin.service
* @Author: hdx
* @CreateTime: 2020-02-14 20:43
* @Description: Сервисы для работы с WeChat
*/
@Service
public class WxService {
@Getter
private static String AppId;
@Value("${wx.appId}")
public void setAppId(String appId) {
AppId = appId;
}
/**
*@Author: hdx
*@CreateTime: 20:46 2020/2/14
*@param: shareUrl URL для раздачи
*@Description: Инициализация конфигурации JSSDK
*/
public Map initJSSDKConfig(String url) throws Exception {
// Получение AccessToken
String accessToken = WxUtil.getJSSDKAccessToken();
// Получение JssdkGetticket
String jsapiTicket = WxUtil.getJssdkGetticket(accessToken);
String timestamp = Long.toString(System.currentTimeMillis() / 1000);
String nonceStr = UUID.randomUUID().toString();
String signature = WxUtil.buildJSSDKSignature(jsapiTicket, timestamp, nonceStr, url);
Map<String, String> map = new HashMap<String, String>();
map.put("url", url);
map.put("jsapi_ticket", jsapiTicket);
map.put("nonceStr", nonceStr);
map.put("timestamp", timestamp);
map.put("signature", signature);
map.put("appid", AppId);
return map;
}
}
WxUtil.java - Утилиты для работы с WeChat
package net.javadog.springbootwexin.utils;
``````markdown
```java
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.security.MessageDigest;
import java.util.Map;
```/**
* Низкокачественный и недорогой программист JavaDog
* blog.javadog.net
*
* @BelongsProject: springboot-wexin
* @BelongsPackage: net.javadog.springbootwexin.utils
* @Author: hdx
* @CreateTime: 2020-02-14 21:19
* @Description: Класс для работы с WeChat
*/
@Component
public class WxUtil {
@Getter
protected static String AppId;
@Getter
protected static String AppSecret;
@Getter
protected static String JssdkAccesstokenUrl;
@Getter
protected static String JssdkGetticketUrl;
@Value("${wx.appId}")
public void setAppId(String appId) {
AppId = appId;
}
@Value("${wx.appSecret}")
public void setAppSecret(String appSecret) {
AppSecret = appSecret;
}
@Value("${wx.jssdk_accesstoken_url}")
public void setJssdkAccesstokenUrl(String jssdkAccesstokenUrl) {
JssdkAccesstokenUrl = jssdkAccesstokenUrl;
}
@Value("${wx.jssdk_getticket_url}")
public void setJssdkGetticketUrl(String jssdkGetticketUrl) {
JssdkGetticketUrl = jssdkGetticketUrl;
}
/**
*@Author: hdx
*@CreateTime: 21:31 2020/2/14
*@param: * @param null
*@Description:
*/
public static String getJSSDKAccessToken() {
String token = null;
String url = JssdkAccesstokenUrl.replaceAll("APPID",
AppId).replaceAll("APPSECRET",
AppSecret);
String json = postRequestForWeiXinService(url);
Map map = jsonToMap(json);
if (map != null) {
token = (String) map.get("access_token");
}
return token;
}```markdown
```java
/**
*@Author: hdx
*@CreateTime: 21:40 2020/2/14
*@param: null
*@Description: Получение JssdkGetticket
*/
public static String getJssdkGetticket(String accessToken) {
String url = JssdkGetticketUrl.replaceAll("ACCESS_TOKEN", accessToken);
String json = postRequestForWeiXinService(url);
Map map = jsonToMap(json);
String jsapi_ticket = null;
if (map != null) {
jsapi_ticket = (String) map.get("ticket");
}
return jsapi_ticket;
}
```markdown
```java
/**
*@Author: hdx
*@CreateTime: 21:41 2020/2/14
*@param:ticket JssdkGetticket, сгенерированный на основе accessToken
*@param:timestamp временная метка для подписи платежа. Обратите внимание, что во всех полях timestamp в jssdk используются строчные буквы. Однако в последней версии платформы для генерации подписи используется поле timeStamp с заглавной S.
*@param:nonceStr случайная строка
*@param:url URL текущей страницы
*@Description: Построение подписи для ссылки на поделиться
*/
*/
public static String buildJSSDKSignature(String ticket, String timestamp, String nonceStr, String url) throws Exception {
String orderedString = "jsapi_ticket=" + ticket
+ "&noncestr=" + nonceStr + "×tamp=" + timestamp
+ "&url=" + url;
return sha1(orderedString);
}
/**
* Шифрование SHA-1 JSSDK параметров конфигурации WeChat для получения подписи.
*
* @return
*/
public static String sha1(String orderedString) throws Exception {
String ciphertext = null;
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(orderedString.getBytes());
ciphertext = byteToStr(digest);
return ciphertext.toLowerCase();
}
/**
* Преобразование массива байтов в шестнадцатеричную строку
*
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* Преобразование байта в шестнадцатеричную строку
*
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
/**
*@Author: hdx
*@CreateTime: 21:49 2020/2/14
*@param: map
*@Description: Преобразование map в json
*/
public static String mapToJson(Map map){
Gson gson = new Gson();
String json = gson.toJson(map);
return json;
}```java
/**
*@Author: hdx
*@CreateTime: 21:37 2020/2/14
*@param: json
*@Description: Преобразование json в map
*/
private static Map jsonToMap(String json) {
Gson gson = new Gson();
Map map = gson.fromJson(json, new TypeToken<Map>(){}.getType());
return map;
}
``````markdown
*****
**postRequestForWeiXinService.java** - Метод для вызова API WeChat
```java
package net.javadog.springbootwexin;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;
/**
*@Author: hdx
*@CreateTime: 21:36 2020/2/14
*@param: null
*@Description: Вызов API WeChat
*/
private static String postRequestForWeiXinService(String getAccessTokenUrl) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> postForEntity = restTemplate.postForEntity(getAccessTokenUrl, null, String.class);
String json = postForEntity.getBody();
return json;
}
```
*****
**SpringbootWexinApplication.java** - Класс запуска SpringBoot
```java
package net.javadog.springbootwexin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootWexinApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootWexinApplication.class, args);
}
}
```
*****
**config/application.yml** - Базовый конфигурационный файл
```yml
spring:
profiles:
#активация конфигурационного файла
active: prod
#конфигурация пути к статическим ресурсам
resources:
static-locations: classpath:/static/
#конфигурация логирования
logging:
#конфигурация пути к файлам логирования
config: classpath:logback-spring.xml
```# Конфигурация WeChat
wx:
# appId (впоследствии замените на свой)
appId: wx4ad618620f8c3528
# appSecret (впоследствии замените на свой)
appSecret: b772c7863b29e270aa86e40f9b9e6215
# ссылка для получения access_token (срок действия Yöntem 7200 секунд, разработчики должны глобально кэшировать access_token в своем сервисе)
jssdk_accesstoken_url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
# ссылка для получения jsapi_ticket (срок действия 7200 секунд, разработчики должны глобально кэшировать jsapi_ticket в своем сервисе)
jssdk_getticket_url: https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
```
**application-dev.yml** - конфигурационный файл для разработки (необязательный)
```yml
# конфигурация для разработки
spring:
profiles: dev
```
# Настройка портов
server:
port: 8000
application-prod.yml - файл конфигурации для продакшена (из-за ограничений безопасности домена для JS-интерфейсов используется конфигурация для продакшена)
# Конфигурация для продакшена
spring:
profiles: prod
# Настройка портов
server:
port: 8002
application-test.yml - файл конфигурации для тестирования (необязательный)
# Конфигурация для тестирования
spring:
profiles: test
# Настройка портов
server:
port: 8003
**demo.html** - тестовая страница H5
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Тестирование jssdk</title>
<!-- Включение JS-файла WeChat -->
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" type="text/javascript"></script>
<!-- Включение jQuery -->
<script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<script>
// Получение текущего URL-адреса страницы
var url = (window.location.href).split('#')[0];
// Вызов API для получения информации о конфигурации jssdk
$.ajax({
type: "get",
/* !!! Важно: замените на свой URL */
url: "http://wxjssdk.javadog.net/weixin/initWXJSSDKConfigInfo? url="+url, // Замените URL на свой
success: function(data){
console.log("Возвращаемое значение равно=" + data);
var msg = "";
if(data.success){
msg = JSON.parse(data.msg);
}
// Внедрение конфигурации проверки прав доступа
wx.config({
debug: true, // Включение режима отладки, вывод всех данных API в консоль
appId: msg.appid,
timestamp: msg.timestamp,
nonceStr: msg.nonceStr,
signature: msg.signature,
/* !!! Важно: выберите необходимые API */
jsApiList: [
"onMenuShareAppMessage", // Поделиться с другом
"chooseImage"
]
});
},
error: function(data){
alert(JSON.stringify(data));
}
});
</script>
</body>
</html>
``````markdown
<!-- Обработка успешной верификации через интерфейс ready -->
wx.ready(function () {
wx.checkJsApi({
jsApiList: ['chooseImage', 'onMenuShareAppMessage'],
success: function (res) {JSON.stringify(res)}
});
});
``` var shareData = {
title: 'Заголовок',
desc: 'Краткое описание', // Здесь следует обратить особое внимание на то, что нужно удалить HTML
link: url,
imgUrl: 'http://b2b.haier.com/shop/userfiles/sys/1/files/201912/af656b3a-8c2c-424d-937b-a8035deb78f5.jpg'
};
wx.onMenuShareAppMessage(shareData);
});
// Выбор изображения из альбома
function wxchooseImage() {
wx.chooseImage({
count: 1, // По умолчанию 9
sizeType: ['original', 'compressed'], // Можно указать, что требуется оригинальное изображение или сжатое
sourceType: ['album', 'camera'], // Можно указать, что источником является альбом или камера
success: function (res) {
var localIds = res.localIds; // Возвращаются локальные идентификаторы выбранных изображений, которые можно использовать в качестве src атрибута img для отображения изображений
}
});
}
</script>
</head>
<body>
<button onclick="wxchooseImage();">Нажмите, чтобы выбрать из альбома</button>
</body>
</html>
? nginx конфигурация, здесь не является частью кода проекта! ! ! nginx.config - конфигурация сервера nginx
server
{
listen 80; # Установите порт прослушивания на 80.
server_name wxjssdk.javadog.net; # Укажите свой собственный префикс домена.
location / {
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8002/;
}
}
MP_verify_B0vMQLCguxRzP1Rc.txt - файл для проверки безопасности домена JS (замените на свой txt файл из вашего публичного аккаунта), должен быть доступен для доступа по корневому пути домена
# Убедитесь, что вы добавили свой собственный txt файл проверки безопасности домена из вашего публичного аккаунта! ! !
B0vMQLCguxRzP1Rc
Откройте документ с шагами по использованию JSSDK, как показано ниже ⬇️

Нажмите для настройки, см. ниже ⬇️

###### Ключевые моменты
- 1. Можно указать только три домена или пути, **китайские имена, IP-адреса, пути с портами и т.д. недопустимы**
- 2. Домен должен быть зарегистрирован в ICP, некоторые пользователи **не могут настроить JS-безопасный домен, используя внутреннюю сеть с помощью花生壳 и подобных сервисов**
- 3. Текстовый файл .txt должен быть размещен в соответствующем каталоге безопасного домена, например wxjssdk.javadog.net/xxx.txt. Это можно настроить с помощью nginx, главное, чтобы файл был доступен, **если файл недоступен, то настройка JS-безопасного домена невозможна**
##### 2. Включение JS-файла

На самом деле, это ссылка в нашем проекте на странице Demo.html, на 9-й строке, см.

##### 3. Внедрение конфигурации проверки прав доступа через метод config
###### Ключевые моменты
Необходимо **открыть доступ к внешнему интерфейсу для получения конфигурации проверки прав доступа**
Это соответствует методу **initWXJSSDKConfigInfo()** в классе **WxInitController.java**, который возвращает обязательные параметры для проверки, такие как **appId, timestamp, nonceStr, signature**
###### Шаги реализации
1. Сначала используя параметры appId и appSecret запросите определенный адрес WeChat для получения **access_token**
2. Затем используя полученный access_token запросите адрес WeChat для получения временного билета jsapi_ticket (здесь не учитывается частота запросов, пользователи могут кэшировать или использовать задачи по расписанию)
3. Используя полученный jsapi_ticket, timestamp, nonceStr и url запросите адрес WeChat для получения подписи signature
4. Верните полученные signature, jsapi_ticket, nonceStr, timestamp и url на фронтенд, как информацию для инициализации конфигурации

- 1. Сначала используя параметры appId и appSecret запросите определенный адрес WeChat для получения **access_token**
Это соответствует методу getJSSDKAccessToken() на 61-й строке класса **WxUtil.java**. Используйте **свой appId и appSecret из公众号** для вызова **интерфейса получения access_token от сервера WeChat**, адрес如下
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
Замените APPID и APPSECRET на свой appId и appSecret из公众号, после вызова будет возвращен JSON-строковый результат, содержащий access_token
- 2. Используйте полученный access_token из первого шага как параметр для запроса адреса WeChat для получения временного билета jsapi_ticket
Соответствует методу **getJssdkGetticket()** в коде WxUtil.java на строке 81
Используйте полученный **access_token** для вызова **интерфейса получения jsapi_ticket от сервера WeChat**, адрес如下
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
Замените ACCESS_TOKEN на полученный access_token, после вызова будет возвращен JSON-строковый результат, содержащий jsapi_ticket
- 3. Используйте полученный jsapi_ticket, timestamp, nonceStr и url как параметры для запроса адреса WeChat для получения подписи signature
Соответствует методу **buildJSSDKSignature()** в коде WxUtil.java на строке 102

Используйте полученный **jsapi_ticket**, добавьте timestamp (время戳 для оплаты), nonceStr (случайная строка), url (текущий URL страницы), упорядочите по имени полей в алфавитном порядке и используйте sha1 для подписи, чтобы сгенерировать окончательную подпись.
Соответствует методу **sha1()** в коде WxUtil.java на строке 115

- 4. Фронтенд успешно получает возвращаемое значение
Соответствует методу **$.ajax** в коде demo.html на строке 16

Возвращаемое значение интерфейса

Преобразуйте JSON-объект с помощью JSON.parse(msg), соответствует строке 24 в коде Demo.html, преобразованные данные используются для вставки в wx.config для проверки прав доступа, соответствует строке 37 в коде demo.html
Исправления:
- "地址如下" переведено как "адрес如下".
- "时间戳" переведено как "время戳".
- "使用JSON.parse(msg)" переведено как "Преобразуйте JSON-объект с помощью JSON.parse(msg)".
- "wx.config" переведено как "wx.config".
##### 4. Обработка успешной проверки с помощью метода ready
###### Ключевые моменты
**Если необходимо вызвать соответствующие интерфейсы при загрузке страницы, то их следует поместить в функцию ready для обеспечения правильного выполнения**
В нашем коде в файле demo.html на строке 46 находится пользовательский интерфейс для поделиться, который должен быть помещен в ready при инициализации страницы для вступления в силу.
**Для компонентов, которые не требуют инициализации при загрузке, можно использовать пользовательские события для их выполнения**
В нашем коде, в файле demo.html на строке 63, пользовательский интерфейс для кнопки, который вызывает функцию для съемки фотографии или выбора изображения из галереи мобильного устройства.

#### Развертывание
Я использую плагин Alibaba Cloud Toolkit в IDE IntelliJ IDEA для однокнопочного развертывания локального приложения на сервер ECS, подробнее можно найти в интернете или в следующей статье.


Целевой сервер ECS: если я купил сервер от Alibaba, то я могу найти его поисковиком.
Целевой каталог: каталог, куда нужно загрузить собранный jar-файл, например: /usr/local/hdx/web/
Команда: команда, которая будет выполнена после загрузки, например: nohup java -jar /usr/local/hdx/web/springboot-wexin.jarПосле успешного развертывания, на терминале появится сообщение об успехе.

Затем все готово, можно проверить доступность [http://wxjssdk.javadog.net/demo.html](http://wxjssdk.javadog.net/demo.html)
Для отладки рекомендуется использовать **инструменты разработчика WeChat**, то есть

Не забудьте **настроить nginx** и **разрешить доступ к серверу по безопасному порту**!!! В противном случае вы получите ошибку 404!!!
#### Тестирование
- 1. Сначала протестируем интерфейс для съемки фото или выбора изображения из галереи

Отладка прошла успешно
- 2. Теперь протестируем встроенную функцию поделиться в WeChat

Отладка завершилась ошибкой, это небольшой "котлован". Я проводил отладку довольно долго, причина заключалась в том, что **подписка не имеет права на пользовательскую настройку функции поделиться**!!!

#### Суммарное описание проблем
1. Подписка и сервисный аккаунт имеют разные права доступа, необходимо подробно изучить документацию WeChat для проверки прав доступа аккаунта
2. Если IP-белый список не настроен, будет выдана ошибка 40164
IP-белый список необходимо настроить в центре безопасности аккаунта WeChat
3. Недействительная подпись
Рекомендуется использовать инструмент [проверки подписи](https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign) из WeChat JSSDK для проверки правильности подписи.
Я JavaDog, спасибо за терпение и прочтение моего поста, загляни в гости [blog.javadog.net](https://blog.javadog.net)
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )