🎨 完善部分注释文档和相关单元测试
This commit is contained in:
@@ -60,6 +60,12 @@ public interface WxMaUserService {
|
||||
/**
|
||||
* 获取手机号信息,基础库:2.21.2及以上或2023年8月28日起
|
||||
*
|
||||
* <p>若已配置 {@code apiSignatureAesKey} 及 {@code apiSignatureRsaPrivateKey} 开启服务端 API 签名,
|
||||
* 该接口请求将自动走加密 + RSA 签名路径(见
|
||||
* <a href="https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html">API签名文档</a>)。
|
||||
* 签名串格式为 {@code urlpath\nappid\ntimestamp\npostdata}(4 个字段),
|
||||
* RSA 私钥序列号通过请求头 {@code Wechatmp-Serial} 传递,不包含在签名串中。
|
||||
*
|
||||
* @param code 每个code只能使用一次,code的有效期为5min。code获取方式参考<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html">手机号快速验证组件</a>
|
||||
* @return 用户手机号信息
|
||||
* @throws WxErrorException .
|
||||
|
||||
@@ -915,11 +915,17 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH
|
||||
* {@code urlpath\nappid\ntimestamp\npostdata}<br>
|
||||
* 字段之间使用换行符 {@code \n} 分隔,共 4 个字段,末尾无额外回车符。
|
||||
*
|
||||
* @param urlPath 当前请求 API 的 URL,不含 Query 参数
|
||||
* @param appId 小程序 AppId
|
||||
* @param timestamp 签名时的时间戳
|
||||
* @param postData 加密后的请求 POST 数据(JSON 字符串)
|
||||
* <p><b>注意:</b>RSA 私钥序列号(rsaKeySn)<b>不应</b>包含在待签名串中,它应通过请求头
|
||||
* {@code Wechatmp-Serial} 传递。4.8.0 曾错误地将 rsaKeySn 插入签名串(产生 5 个字段),
|
||||
* 导致所有走 API 签名路径的接口(包括 {@code getPhoneNumber}、同城配送等)返回 40234
|
||||
* {@code invalid signature}。此方法明确使用 4 字段格式以确保签名正确。
|
||||
*
|
||||
* @param urlPath 当前请求 API 的 URL,不含 Query 参数
|
||||
* @param appId 小程序 AppId
|
||||
* @param timestamp 签名时的时间戳
|
||||
* @param postData 加密后的请求 POST 数据(JSON 字符串)
|
||||
* @return 拼接好的待签名串
|
||||
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html">微信服务端API签名指南</a>
|
||||
*/
|
||||
static String buildSignaturePayload(String urlPath, String appId, long timestamp, String postData) {
|
||||
return urlPath + "\n" + appId + "\n" + timestamp + "\n" + postData;
|
||||
|
||||
@@ -3,16 +3,21 @@ package cn.binarywang.wx.miniapp.api.impl;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* 验证同城配送 API 签名 payload 格式的单元测试。
|
||||
* 验证小程序 API 签名 payload 格式的单元测试。
|
||||
*
|
||||
* <p>直接测试 {@link BaseWxMaServiceImpl#buildSignaturePayload} 生产方法,
|
||||
* 确保待签名串格式符合微信官方规范:<br>
|
||||
* {@code urlpath\nappid\ntimestamp\npostdata}<br>
|
||||
* 共 4 个字段,字段间以换行符 {@code \n} 分隔,末尾无额外回车符。
|
||||
*
|
||||
* <p>修复说明:4.8.0 版本在计算签名时错误地将 rsaKeySn 添加到签名串(5 个字段),
|
||||
* 导致微信服务端返回 40234(invalid signature)。此测试验证修复后签名串格式正确(4 个字段,
|
||||
* 不含 rsaKeySn),适用于所有走加密访问路径的接口(包括 getPhoneNumber、同城配送等)。
|
||||
*
|
||||
* @author GitHub Copilot
|
||||
* @see <a
|
||||
* href="https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html">
|
||||
@@ -22,39 +27,43 @@ public class WxMaSignaturePayloadTest {
|
||||
|
||||
private static final String URL_PATH =
|
||||
"https://api.weixin.qq.com/cgi-bin/express/intracity/createstore";
|
||||
private static final String GET_PHONE_NUMBER_URL_PATH =
|
||||
"https://api.weixin.qq.com/wxa/business/getuserphonenumber";
|
||||
private static final String APP_ID = "wx1234567890abcdef";
|
||||
private static final long TIMESTAMP = 1700000000L;
|
||||
private static final String POST_DATA = "{\"iv\":\"abc\",\"data\":\"xyz\",\"authtag\":\"tag\"}";
|
||||
private static final String RSA_KEY_SN = "some_serial_number";
|
||||
|
||||
/**
|
||||
* 验证 buildSignaturePayload 返回的待签名串恰好包含 4 个字段,
|
||||
* 格式为:urlpath\nappid\ntimestamp\npostdata
|
||||
* 提供不同 API 接口 URL 作为测试数据,用于验证签名串格式在各接口中均符合规范。
|
||||
*/
|
||||
@Test
|
||||
public void testPayloadHasExactlyFourFields() {
|
||||
String payload =
|
||||
BaseWxMaServiceImpl.buildSignaturePayload(URL_PATH, APP_ID, TIMESTAMP, POST_DATA);
|
||||
|
||||
String[] parts = payload.split("\n", -1);
|
||||
assertEquals(parts.length, 4, "待签名串应恰好包含 4 个字段(urlpath、appid、timestamp、postdata)");
|
||||
assertEquals(parts[0], URL_PATH, "第 1 段应为 urlpath");
|
||||
assertEquals(parts[1], APP_ID, "第 2 段应为 appid");
|
||||
assertEquals(parts[2], String.valueOf(TIMESTAMP), "第 3 段应为 timestamp");
|
||||
assertEquals(parts[3], POST_DATA, "第 4 段应为 postdata");
|
||||
@DataProvider(name = "apiUrlPaths")
|
||||
public Object[][] apiUrlPaths() {
|
||||
return new Object[][] {
|
||||
{URL_PATH, "同城配送 createstore"},
|
||||
{GET_PHONE_NUMBER_URL_PATH, "getPhoneNumber"}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 buildSignaturePayload 返回的待签名串不包含 rsaKeySn。
|
||||
* rsaKeySn 应通过请求头 Wechatmp-Serial 传递,而不应出现在签名 payload 中。
|
||||
* 验证 buildSignaturePayload 返回的待签名串恰好包含 4 个字段,
|
||||
* 格式为:urlpath\nappid\ntimestamp\npostdata。
|
||||
* 使用多个 URL 验证,覆盖同城配送及 getPhoneNumber 等接口(issue 4.8.0 升级后 40234 错误)。
|
||||
*/
|
||||
@Test
|
||||
public void testPayloadDoesNotContainRsaKeySn() {
|
||||
@Test(dataProvider = "apiUrlPaths")
|
||||
public void testPayloadHasExactlyFourFields(String urlPath, String description) {
|
||||
String payload =
|
||||
BaseWxMaServiceImpl.buildSignaturePayload(URL_PATH, APP_ID, TIMESTAMP, POST_DATA);
|
||||
BaseWxMaServiceImpl.buildSignaturePayload(urlPath, APP_ID, TIMESTAMP, POST_DATA);
|
||||
|
||||
String[] parts = payload.split("\n", -1);
|
||||
assertEquals(parts.length, 4,
|
||||
description + " 签名串应恰好包含 4 个字段(urlpath、appid、timestamp、postdata)");
|
||||
assertEquals(parts[0], urlPath, description + " 第 1 段应为 urlpath");
|
||||
assertEquals(parts[1], APP_ID, description + " 第 2 段应为 appid");
|
||||
assertEquals(parts[2], String.valueOf(TIMESTAMP), description + " 第 3 段应为 timestamp");
|
||||
assertEquals(parts[3], POST_DATA, description + " 第 4 段应为 postdata");
|
||||
assertFalse(payload.contains(RSA_KEY_SN),
|
||||
"待签名串不应包含 rsaKeySn,rsaKeySn 应通过请求头 Wechatmp-Serial 传递");
|
||||
description + " 签名串不应包含 rsaKeySn,rsaKeySn 应通过请求头 Wechatmp-Serial 传递");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user