From a8f324ee5c3ca01355a4c60b3265d0d528eff568 Mon Sep 17 00:00:00 2001 From: hanrenchun Date: Fri, 28 Nov 2025 14:35:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=AE=9D=E5=92=8C=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E7=99=BB=E5=BD=95=E4=B8=8E=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../database/service/AlipayPhoneService.java | 132 ++++++++++++++---- .../src/main/resources/application.yml | 2 +- 2 files changed, 107 insertions(+), 27 deletions(-) diff --git a/gather-app/src/main/java/com/ruoyi/database/service/AlipayPhoneService.java b/gather-app/src/main/java/com/ruoyi/database/service/AlipayPhoneService.java index 35bb0ee..e2b8986 100644 --- a/gather-app/src/main/java/com/ruoyi/database/service/AlipayPhoneService.java +++ b/gather-app/src/main/java/com/ruoyi/database/service/AlipayPhoneService.java @@ -1,13 +1,23 @@ package com.ruoyi.database.service; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; +import com.alibaba.fastjson.parser.Feature; +import com.alipay.api.AlipayApiException; +import com.alipay.api.internal.util.AlipayEncrypt; +import com.alipay.api.internal.util.AlipaySignature; import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.database.exception.BusinessException; import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.KeyFactory; @@ -36,53 +46,127 @@ public class AlipayPhoneService { @Value("${alipay.gateway}") private String gateway; - /** - * 通过授权码获取用户手机号 - */ + + private final String AES_STR = "LoKBapEj35+bRnC/Rrhe8g=="; + public String getPhoneNumber(String authCode) { try { - // 1. 构建请求参数 + // 1. 使用auth_code获取access_token +// String accessToken = getAccessToken(authCode); + System.out.println("authCode:" + authCode); + String charset = "UTF-8"; + String encryptType = "AES"; + //判断是否为加密内容 + boolean isDataEncrypted = !authCode.startsWith("{"); + //3. 解密 + String plainData = null; + if (isDataEncrypted) { + try { + plainData = AlipayEncrypt.decryptContent(authCode, encryptType, AES_STR, charset); + System.out.println("解密:" + plainData); + } catch (AlipayApiException e) { + //解密异常, 记录日志 + throw new Exception("解密异常"); + } + } else { + plainData = authCode; + } + // 2. 使用access_token获取用户信息(包含手机号) + Map responseMap = objectMapper.readValue(plainData, Map.class); + return responseMap.get("mobile").toString(); + + } catch (Exception e) { + log.error("获取支付宝手机号异常", e); + throw new BusinessException("ALIPAY_PHONE_ERROR", "获取支付宝手机号异常: " + e.getMessage()); + } + } + + /** + * 第一步:使用授权码获取访问令牌 + */ + private String getAccessToken(String authCode) { + try { Map params = buildBaseParams(); params.put("method", "alipay.system.oauth.token"); params.put("grant_type", "authorization_code"); params.put("code", authCode); - log.info("请求参数构建完成: {}", params); + log.info("获取access_token请求参数: {}", params); - // 2. 生成签名 String sign = generateSign(params); params.put("sign", sign); - log.info("签名生成完成"); - - // 3. 调用支付宝接口 - 使用修复后的方法 String responseBody = callAlipayApiWithCharset(params); + log.info("获取access_token响应: {}", responseBody); - log.info("支付宝手机号接口响应: {}", responseBody); - - // 4. 解析响应 Map responseMap = objectMapper.readValue(responseBody, Map.class); Map tokenResponse = (Map) responseMap.get("alipay_system_oauth_token_response"); if (tokenResponse == null) { - // 检查错误响应 Map errorResponse = (Map) responseMap.get("error_response"); if (errorResponse != null) { String subCode = (String) errorResponse.get("sub_code"); String subMsg = (String) errorResponse.get("sub_msg"); - throw new BusinessException("ALIPAY_PHONE_ERROR", - String.format("支付宝接口错误[%s]: %s", subCode, subMsg)); + throw new BusinessException("ALIPAY_ACCESS_TOKEN_ERROR", + String.format("获取access_token失败[%s]: %s", subCode, subMsg)); } - throw new BusinessException("ALIPAY_PHONE_ERROR", "支付宝接口响应格式错误"); + throw new BusinessException("ALIPAY_ACCESS_TOKEN_ERROR", "获取access_token失败: 响应格式错误"); } - // 5. 提取手机号 - String mobile = (String) tokenResponse.get("mobile"); + String accessToken = (String) tokenResponse.get("access_token"); + if (accessToken == null || accessToken.trim().isEmpty()) { + throw new BusinessException("ALIPAY_ACCESS_TOKEN_ERROR", "获取access_token失败: access_token为空"); + } + + log.info("成功获取access_token: {}", accessToken); + return accessToken; + + } catch (Exception e) { + log.error("获取access_token异常", e); + throw new BusinessException("ALIPAY_ACCESS_TOKEN_ERROR", "获取access_token异常: " + e.getMessage()); + } + } + + /** + * 第二步:使用access_token获取用户信息(包含手机号) + */ + private String getUserPhoneNumber(String accessToken) { + try { + Map params = buildBaseParams(); + params.put("method", "alipay.user.info.share"); + params.put("auth_token", accessToken); + + log.info("获取用户信息请求参数: {}", params); + + String sign = generateSign(params); + params.put("sign", sign); + + String responseBody = callAlipayApiWithCharset(params); + log.info("获取用户信息响应: {}", responseBody); + + Map responseMap = objectMapper.readValue(responseBody, Map.class); + Map userResponse = (Map) responseMap.get("alipay_user_info_share_response"); + + if (userResponse == null) { + Map errorResponse = (Map) responseMap.get("error_response"); + if (errorResponse != null) { + String subCode = (String) errorResponse.get("sub_code"); + String subMsg = (String) errorResponse.get("sub_msg"); + throw new BusinessException("ALIPAY_USER_INFO_ERROR", + String.format("获取用户信息失败[%s]: %s", subCode, subMsg)); + } + throw new BusinessException("ALIPAY_USER_INFO_ERROR", "获取用户信息失败: 响应格式错误"); + } + + // 提取手机号 + String mobile = (String) userResponse.get("mobile"); if (mobile == null || mobile.trim().isEmpty()) { - throw new BusinessException("ALIPAY_PHONE_ERROR", "获取手机号失败: 手机号为空"); + // 有些用户可能没有绑定手机号 + log.warn("用户未绑定手机号或手机号为空"); + throw new BusinessException("ALIPAY_PHONE_EMPTY", "用户未绑定手机号"); } - // 6. 验证手机号格式 + // 验证手机号格式 if (!validatePhoneNumber(mobile)) { log.warn("获取到的手机号格式可能不正确: {}", mobile); } @@ -90,11 +174,9 @@ public class AlipayPhoneService { log.info("成功获取用户手机号: {}", mobile); return mobile; - } catch (BusinessException e) { - throw e; } catch (Exception e) { - log.error("获取支付宝手机号异常", e); - throw new BusinessException("ALIPAY_PHONE_ERROR", "获取支付宝手机号异常: " + e.getMessage()); + log.error("获取用户信息异常", e); + throw new BusinessException("ALIPAY_USER_INFO_ERROR", "获取用户信息异常: " + e.getMessage()); } } @@ -202,7 +284,6 @@ public class AlipayPhoneService { } - /** * 获取当前时间戳 */ @@ -213,7 +294,6 @@ public class AlipayPhoneService { } - /** * 获取私钥 */ diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index ddd7587..45c4dac 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -143,7 +143,7 @@ wx: alipay: appId: 2021006113615353 - privateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7yP787s/Qr36GMnfAb/Blj9NR9voGYfGT/AsC0BGKE+NcymBhA55i27I+QfiXSsb/f/kz1ByMtZxoYHwz7Ha/la5FPps3SgwQNp+CnMIo0DpiP+3i5eVWb+Tffh8C0uL/LzfZKNxaGya68hkG9TitHf7XvBt+Z0Fdy2zKNZZn3xAhr0F6lEmZ645jp8cetDvqpemv95FCJ/2oTB5QDjy65+beOdeES1uvx0HopA+MJyMlJ08K/gopCfNYRqgOnmcDFb6kixUcajdAn8+pjaDpX0RIHnxmOmbcgDUOZS8pakfzbtc/NaSZa25FxXVer5LHR8dNIPKyZKslOHV+MvCtAgMBAAECggEAc/rfKh7hMXXCgmXXOn6ojkG3dc9BewGxMAIiVtlli89exKelwSV4BHzGaNdcDy07HQDQTGd8PpfIg1rcO0GX0hpDaTcSrKJKMxVZjVT+QjDhbl8nsNTmwW0YgcSmqJrRYmSqbLBk8C4GzL3MIVUBbUKybFIc9QQXBjQm+/j+7SV0Kr9hKTA/q4hk4gguem8Cg2+z752uM31eEExD71UlauTvAyj9C4kuhYOnSThpz1UeWZxhOl9n0ij/guEVXhMjlnYf9fvE/gV6yxuTxKWa4NWhTpqDHv6hwm0kjvL3spfTRorAfM7yeXmFYe1grVs5v4GVGPRQLP3/e71CMhGLTQKBgQDgcngshP07uht37yoXbX3bl4E15QU5FKQ7AhU+ZTCTJrmHIJFyBew7oEq34FnM4HPut8V/6BT3PfQJoAgLfNprieuXDiLa/ngdlmBmh5ywITnwC9aCLpwtJjN+bCU7mraQkd7X7ZTo0uiiHYGLTbBWcVAZ/0/zy32C0tsJVe5WWwKBgQDWLx0Z4FMAq4B4pdQfAD3DgqVaxBZAD6Pd4pFXCYBqFgw/RRYE44Gp1KqyfdP1f/JwoFdF/UtOWMe+RUdoU86Iqm2657/PWMSDjCPuYJ2KlIV5cqReXR/XycyIg64Gz+4wGjO788SzGG7oV9V++VZeZtVC2GKkxLlNIeha3SPTlwKBgQCQAAEoFv7dlg7PiOtJcp8gBvkIWfJa5+piTXjRulxK3LqFfpiyPiiNLM8jX9Zdgtf+nXsiEAV7hw0OK9VdgXIlMqyrEo+8Ty1DVlptDa6yte6VGxM6HKtosCyzfLD6p81fvabqhGxYYBCPCj014dcz7qlEtLBYKwNQrvWG7NHoJwKBgEcGxqq/FidhuC/KJibFqLW+DGGmJw7FYP0C1lm7n+cOOq98lIm4fFY6XQTl7zU5YcdxlJ90GNX5YPu686woJpRxmAPkOFplQH2zKnMxfOzoxb55gwJ79URU+kvHBx3hNEalWcSZWQBfOOA5yGXb/4U8qroJEeU8C4sFlI0VSn0vAoGBANOfx8geSo22AuqQKmX27cE4aw8YSPAbiGmjMb4K6wDVeiH2CjO1/boG0D+0F8CO9JDR4llIB8YixgkwFlhuVMk1jouTkOqH+TLE1gqZC5iE7lMCnL1K/OsOH+zGoQ4dP6MRBfcMEG8HyCZw5Uo180fHSwPYLSushxbOG3sHaffJ + privateKey: MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCiRzdzmuqvz4ohvOacFyKJIKyfyI22HkNgCJV8gWYNn5oR1wFjyt+3/mf1RAYV0yA4YVmnJkiGxtNdTRFQoOJU21NTDutN8MdjY3KgGFAmAffX1uZrLWn37A5SS/Lo6Ym7PSvqUI/dqMl2RY2Bs8BEMABmD4vwonEvBfPjiX3QhQG0NupfsAX6k5eVAsp4OwfWwgA1IY2dLihzLhWT12hElvRKlf5cdoTP8gDiAMLxLy4UbhLiUj4wimrTl5/UruTo+WBwY3E/abxLIx6UvoU6BwJKh+oF2Po5TMRFWq6KDv+nQskDeB296rNGSa45UXxKy4qnDy6Wwut81Ma0Ja1dAgMBAAECggEAVUpS9brNcHwHILZVCmMKbsIymIRjHv4G8VlxoA+uoKhq5Md5XobJUL4wy3LmM+BURe28niJ76gJkItyXpiX47xqbT8M+nydW1ID3RPeiYGeWaOX1Ew26bWivGkf6srnT/womo6+V/a1xvWzO9AWSnwQPoZS4O1BVZp6dUdD4xHfdZDaChnD0avXRMZrBe9HQjhcev6A+nKJyTGFDbooHSi4bzixcaaE595D/Fp9hxvW7V6rpY9pfgYFr/KgRwEgX+LooHCigYXVEi4ckf/JfH0HKYm0nWrcajal5nlUPq5PG6QMqNDl5m6R6llUl/LhM6JjEeMhmqPCHYGZWG/nIbQKBgQDPpn9o4KGdl3a/Jl5ACQVsk5S146sJ3hRkcmamQsXY/Dmxi+DMyBM5PRRRDiWpx9icZ1AdjPlU/aB81waJdExS/EfBACrf3I2KMA9lfYm5J9cMtsrAyFCLFOgcnGUb1apLe6PGafxYhLm4y3OhMhP71i02ofF1WqxpKewBo0bZ9wKBgQDIEDMrz8IgFoPrraU1gMqnvd57KgNhsX3xpSTfgZq+TeQOua6zeJ/EHfk7nxlatdx6pB1kn7zCUJkpMqZmVhXS6ZvJ1DUdinJCDJn/zokmwsDYE8xPNk41cr4ZPy4WR0svhe2xTc3tL2UmfKbLg9SZk7HUYj/KCUfKC2Y8QLY+SwKBgQDHGubgMUPGUA1Ui/2jeQLycTAOmBbQh1kWV3uFwFDlFjRbwbvzn4SPRbnNXrtOaImSrp1rOFl63RadnbBu7Eyi5bQHo5l4vYoaDqs0rYL5PvI9Bqiy4WAZfBp0FKH+Zom7hvoqrkWAuwM55hshXVs8BsmjsPRNinv2+nOJvn2ZUQKBgQCPR8reHbUR9g4UxBAF+W8qIzkrTDOPy+Y/Id7+k3uXv4ENar5LmqARfMX6hT9LT+PPkanbXut43vBSKQwzToPiwZvpOCmyNm0OEKhaJDjloaUrG0K/mEz6ymqK+kyvd+/I4UoSKX7J15/BqJRsPMYOF1DMonC86ViYwwE9NbtPcQKBgQCM7pHhGZJMUz0KKffzCWjqY9NHZjs7JMAexWjboGuaaS2JkGFV8d/4nWBPiFRqK3whhtZ9MeE3Af6SusQAGQ9Guu45PxiAWa8VVeWYEVm+I4MNGN2C/PC4SqdWqluWiUGhg0zFpwzf/eHvFxdxrutUMADF0X6vL2ZxZcHmZdXoXg== apppublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAokc3c5rqr8+KIbzmnBciiSCsn8iNth5DYAiVfIFmDZ+aEdcBY8rft/5n9UQGFdMgOGFZpyZIhsbTXU0RUKDiVNtTUw7rTfDHY2NyoBhQJgH319bmay1p9+wOUkvy6OmJuz0r6lCP3ajJdkWNgbPARDAAZg+L8KJxLwXz44l90IUBtDbqX7AF+pOXlQLKeDsH1sIANSGNnS4ocy4Vk9doRJb0SpX+XHaEz/IA4gDC8S8uFG4S4lI+MIpq05ef1K7k6PlgcGNxP2m8SyMelL6FOgcCSofqBdj6OUzERVquig7/p0LJA3gdveqzRkmuOVF8SsuKpw8ulsLrfNTGtCWtXQIDAQAB publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhHGI9i9ewOf1lKHkLy8rQS2eLgYwheyzhrfi0fX1BDB7CWKoKu4kqDT52CYP6438K7NvANzh+aSaXvi1vZEAf2ociyjozKypj2qKynL6nW/sLyXWDbCU2u41WJv9iDvm8l/AF6qcanoKSSzZPUFsXHD+ZDsGj/3EyLF+FUN7vQw1Bj9BmYnushjTL/0KQWQNbrZeSHtEPYkhiVGKRD63ZETQPqcTU4vOncmNSb879Z40dAHxob2qUzh7743hk8PnTMkDpacfolMTeeRdDrdsLgmaLypyWtKXe8DASKXE92YnW5Yq8Vkb3aZiS+u903WWNfatOoOGIn0XyuA6T5OCbwIDAQAB notifyUrl: https://tingche.csckl.com/alipay/notify