1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/javadog-net-springboot-wexin

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Несмотря на то, что я новичок, я всё равно хочу поделиться

Сначала дам干货 код

GitHub

Адрес GitHub для интеграции WeChat JSSDK

Gitee

Адрес Gitee для интеграции WeChat JSSDK

Введение

Причина этого проекта заключается в том, что из-за серьёзной эпидемии руководство потребовало создать специализированную страницу, которая могла бы помочь нуждающимся людям. Итак, я и мой коллега работали до поздней ночи, чтобы завершить проект. После развертывания и запуска страницы, мы поделились ей с помощью встроенного браузера WeChat. В идеальном состоянии она должна была выглядеть так, как показано на следующем рисунке ⬇️

Однако, результат не был таким, каким мы ожидали, и мы оставили слезы от отсутствия технических знаний, как показано на следующем рисунке ⬇️

Оказалось, что нет ключевых слов и изображения для отображения. После неустанных усилий я пришёл к выводу, что у меня недостаточно технических знаний и обратился к экспертам. Они пришли к следующим выводам.- 1. Если вы хотите настроить отображение описания и изображения для встроенного браузера WeChat, вам необходимо интегрировать WeChat JSSDK и иметь соответствующий WeChat публичный аккаунт (appId и appSecret). Обратите внимание, что это невозможно для 小程序 (appId и appSecret).

    1. Для не-WeChat браузеров, таких как QQ Browser, UC Browser и других производителей, они будут использовать собственные определения для получения TDK (title, description, keyword) из HTML-страницы. Например, UC Browser поделится следующим образом ⬇️

Таким образом, интеграция WeChat JSSDK становится необходимостью!


Совет

Наиболее подробное руководство для новичков по интеграции WeChat JSSDK, в котором полностью описаны шаги по интеграции WeChat JSSDK, конкретный код и проблемы, с которыми вы можете столкнуться, а также показаны итоговые результаты и опубликованы на GitHub. Статья длинная, но самая полная. Прошу не критиковать, это для новичков, проверено на практике и работает!!!

Целевая аудитория

  • Студенты, которые хотят интегрировать WeChat JSSDK, но не могут понять документацию
  • Студенты, которые могут понять документацию, но не знают, как начать практическую работу
  • Студенты, которые начали работу, но сталкиваются с ошибками и не знают, как отладить и исправить
  • Студенты, которые уже успешно интегрировали WeChat JSSDK и хотят повторить процесс

Цели статьи

  • Практическая интеграция H5 сайта для самостоятельного поделиться в WeChat
  • Практическая интеграция H5 сайта для выбора изображения из галереи

Расслабьтесь и посмотрите постепенно************

Основной текст

Официальная документация

Для подключения к любой платформе официальная документация является эталоном, хотя некоторые ключевые моменты упоминаются вскользь. Мы должны внимательно изучить документацию, чтобы иметь общее представление. Нажмите официальную документацию WeChat для открытия документа, как показано ниже ⬇️

Обзор
  • 1.x — это ключевые шаги подключения, требующие внимательного изучения, связанные с подключением
  • 2.x - 12.x — конкретные шаги подключения к интерфейсам, которые следует использовать при подключении
  • 13.x — следует обратить внимание, api_ticket — временная квитанция WeChat, связанная с подключением
  • 16-22 — все приложения, которые можно использовать для просмотра списков ошибок и описаний меню интерфейсов

Практические шаги

Используйте среду разработки IDEA, создайте проект SpringBoot, назовите проект springboot-wexin, структура каталога如下:

AjaxJson.java - пользовательский класс для упаковки формата данных, возвращаемых на фронтенд

/**
 * Copyright &copy; 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 + "&timestamp=" + 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

Откройте документ с шагами по использованию JSSDK, как показано ниже ⬇️

1. Привязка домена


![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200223151711529.png)

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

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200223151951781.png)

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

##### 2. Включение JS-файла

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224091726780.png)

На самом деле, это ссылка в нашем проекте на странице Demo.html, на 9-й строке, см.
![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224091137161.png) 

##### 3. Внедрение конфигурации проверки прав доступа через метод config

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224091822341.png)###### Ключевые моменты
Необходимо **открыть доступ к внешнему интерфейсу для получения конфигурации проверки прав доступа**
	Это соответствует методу **initWXJSSDKConfigInfo()** в классе **WxInitController.java**, который возвращает обязательные параметры для проверки, такие как **appId, timestamp, nonceStr, signature**![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224092342176.png)

###### Шаги реализации
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 на фронтенд, как информацию для инициализации конфигурации

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224094803470.png)

- 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![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224095554973.png)

Используйте полученный **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

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224101244262.png)

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

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224153849877.png)

- 4. Фронтенд успешно получает возвращаемое значение

Соответствует методу **$.ajax** в коде demo.html на строке 16

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224160028903.png)

Возвращаемое значение интерфейса
![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224155638274.png)

Преобразуйте JSON-объект с помощью JSON.parse(msg), соответствует строке 24 в коде Demo.html, преобразованные данные используются для вставки в wx.config для проверки прав доступа, соответствует строке 37 в коде demo.html

Исправления:
- "地址如下" переведено как "адрес如下".
- "时间戳" переведено как "время戳".
- "使用JSON.parse(msg)" переведено как "Преобразуйте JSON-объект с помощью JSON.parse(msg)".
- "wx.config" переведено как "wx.config".![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224155914945.png)

##### 4. Обработка успешной проверки с помощью метода ready

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224205700482.png)###### Ключевые моменты
**Если необходимо вызвать соответствующие интерфейсы при загрузке страницы, то их следует поместить в функцию ready для обеспечения правильного выполнения**
В нашем коде в файле demo.html на строке 46 находится пользовательский интерфейс для поделиться, который должен быть помещен в ready при инициализации страницы для вступления в силу.![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224205909331.png)

**Для компонентов, которые не требуют инициализации при загрузке, можно использовать пользовательские события для их выполнения**

В нашем коде, в файле demo.html на строке 63, пользовательский интерфейс для кнопки, который вызывает функцию для съемки фотографии или выбора изображения из галереи мобильного устройства.

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224211957299.png)

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

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224213138387.png)

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224213221413.png)

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

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224213613751.png)

Затем все готово, можно проверить доступность [http://wxjssdk.javadog.net/demo.html](http://wxjssdk.javadog.net/demo.html)

Для отладки рекомендуется использовать **инструменты разработчика WeChat**, то есть

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224214236995.png)

Не забудьте **настроить nginx** и **разрешить доступ к серверу по безопасному порту**!!! В противном случае вы получите ошибку 404!!!

#### Тестирование
- 1. Сначала протестируем интерфейс для съемки фото или выбора изображения из галереи

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224215022360.gif)

Отладка прошла успешно

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

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224215535267.gif)

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

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224215906222.png)

#### Суммарное описание проблем
1. Подписка и сервисный аккаунт имеют разные права доступа, необходимо подробно изучить документацию WeChat для проверки прав доступа аккаунта
2. Если IP-белый список не настроен, будет выдана ошибка 40164

![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224220440497.png)IP-белый список необходимо настроить в центре безопасности аккаунта WeChat![](https://img.javadog.net/blog/java-springboot-wsjssdk/20200224220551848.png)

3. Недействительная подпись

Рекомендуется использовать инструмент [проверки подписи](https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign) из WeChat JSSDK для проверки правильности подписи.

Я JavaDog, спасибо за терпение и прочтение моего поста, загляни в гости [blog.javadog.net](https://blog.javadog.net)

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Программирование на Spring Boot и интеграция с WeChat JSSDK: полное руководство для новичков Развернуть Свернуть
Java и 2 других языков
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/javadog-net-springboot-wexin.git
git@api.gitlife.ru:oschina-mirror/javadog-net-springboot-wexin.git
oschina-mirror
javadog-net-springboot-wexin
javadog-net-springboot-wexin
master