微信支付--敏感词加密

本文介绍如何通过微信支付V3接口获取微信平台证书,并利用该证书进行敏感数据的加密处理。详细展示了从获取证书到使用证书进行加密的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

敏感词加密

Map<String, Object> weChatPlatformCertificateMap = payScorePartnerService.getPartnerCertificate(你的商户id, "wechat_platform_certificate");public Map<String, Object> getPartnerCertificate(String 你的商户id, String weChatPlatformCertificateKey) throws ServiceException {
					//存缓存
					Map<String, Object> certificate = wechatPayV3CertificateCache.getPartnerWeChatPlatformCertificate(weChatPlatformCertificateKey);
					if (certificate.get("certificate") != null) {
						return certificate;
					}
					// 当前没有证书,重新拉取拉取微信证书
					String certNo = 你的证书编号;
					String v3Key = 你的v3key;
					你的商户id = properties.getPayscore().getPartnerMchId();
					String uri = WeChatPayV3Constants.PARTNER_GET_PLATFORM_CERTIFICATES;

					JSONObject result = weChatPayV3Template.doGet(uri, 你的商户id, 你的证件编号);public JSONObject doGet(String uri, String 你的商户id, String 你的证件编号) throws ServiceException {
											String url = String.format("%1$s%2$s", WeChatPayV3Constants.DOMAIN, uri);
											// 添加请求头
											MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
											headers.add("Content-Type", "application/json");
											headers.add("Accept", "application/json");
											String certKeyPath = wechatProperties.getCertKeyPath(你的商户id);
									//        String certKeyPath = wechatProperties.getPayscore().getPartnerPrivateKeyUrl();
											// 生成支付签名
											String token = WeChatPayV3Util.getToken("GET", uri, 你的商户id, "", 你的证件编号, certKeyPath);
											String authorization = WeChatPayV3Constants.WECHAT_SCHEMA + " " + token;
											headers.add("Authorization", authorization);
											log.info("#################### 微信支付v3开始请求 url:{} ####################", url);
											HttpEntity httpEntity = new HttpEntity<>(headers);
											ResponseEntity<String> responseEntity = null;
											try {
												responseEntity = reqRestTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
											} catch (HttpStatusCodeException e) {
												log.error("########## 请求错误:code: {}, message: {} ##########", e.getStatusCode(), e.getResponseBodyAsString());
												String body = e.getResponseBodyAsString();
												if (StringUtils.isNotEmpty(body)) {
													Map bodyMap = JsonUtils.toMap(body);
													if (bodyMap != null && bodyMap.containsKey("message")) {
														if ("ORDER_NOT_EXIST".equals(bodyMap.get("code").toString()) || "CONTRACT_NOT_EXIST".equals(bodyMap.get("code").toString())) {
															throw new ServiceException(ErrorCode.ayment_wechat_v3_request_failed_order_not_exist, bodyMap.get("message").toString());
														}
														throw new ServiceException(ErrorCode.payment_wechat_v3_request_error, bodyMap.get("message").toString());
													}
												}
												throw new ServiceException(ErrorCode.payment_wechat_v3_request_error, e.getResponseBodyAsString());
											} catch (RestClientException e) {
												log.error("请求接口失败", e);
												throw new ServiceException(ErrorCode.payment_wechat_v3_request_error, e.getMessage());
											}
											if (!responseEntity.getStatusCode().is2xxSuccessful()) {
												String result = responseEntity.getBody();
												WeChatPayV3ResultEntity wxResultEntity = JSONObject.parseObject(result, WeChatPayV3ResultEntity.class);
												log.error("#################### 微信支付请求失败 statusCode:{},code:{},msg:{}, detail:{} ####################",
														responseEntity.getStatusCode(), wxResultEntity.getCode(), wxResultEntity.getMessage(), wxResultEntity.getDetail());
												throw new ServiceException(ErrorCode.payment_wechat_v3_request_error, wxResultEntity.getMessage());
											}
											HttpHeaders responseHeaders = responseEntity.getHeaders();
											// 微信支付唯一请求Id
											List<String> uniqueReqId = responseHeaders.get("Request-ID");
											log.debug("#################### 微信支付v3收到响应,responseCode:{}, uniqueReqId:{}, data:{} ####################",
													responseEntity.getStatusCode(), uniqueReqId, responseEntity);
											return JSONObject.parseObject(responseEntity.getBody());
										}List<WechatPayCertificatesVo> payCertificatesList = JSONArray.parseArray(result.getString("data"), WechatPayCertificatesVo.class);
					// 拿到最新的微信平台证书
					// 解密微信通知数据
					payCertificatesList.stream().forEach(item -> {
						WechatPayEncryptCertificateDataVo encryptCertificate = item.getEncryptCertificate();
						String associatedData = encryptCertificate.getAssociatedData();
						String nonce = encryptCertificate.getNonce();
						String cipherText = encryptCertificate.getCipherText();
						String certificateInfo = WeChatPayV3Util.decryptToString(associatedData, nonce, cipherText, v3Key);
						// 将证书数据缓存到redis
						String serialNo = item.getSerialNo();
						Date effectiveTime = item.getEffectiveTime();
						Date expireTime = item.getExpireTime();
						wechatPayV3CertificateCache.cacheWeChatPlatformCertificate(weChatPlatformCertificateKey,serialNo, certificateInfo, expireTime, effectiveTime);
					});
					Map<String, Object> certificateMap = wechatPayV3CertificateCache.getPartnerWeChatPlatformCertificate(weChatPlatformCertificateKey);
					if (Objects.isNull(certificate)) {
						throw new ServiceException(ErrorCode.payment_pay_score_get_cert_error);
					}
					return certificateMap;
				}String certEntityString = String.valueOf(weChatPlatformCertificateMap.get("certificate"));
String serial = String.valueOf(weChatPlatformCertificateMap.get("serial_no"));
//将证书转化成x509格式
InputStream in = new ByteArrayInputStream(certEntityString.getBytes("utf-8"));
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Certificate cert = certFactory.generateCertificate(in);
CertHttpUtil.rsaEncryptOAEP(要加密的值, (X509Certificate) cert);public static String rsaEncryptOAEP(String message, X509Certificate certificate)
						throws IllegalBlockSizeException, IOException {
					try {
						Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
						cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());

						byte[] data = message.getBytes("utf-8");
						byte[] cipherdata = cipher.doFinal(data);
						return Base64.encodeBase64String(cipherdata);
					} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
						throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
					} catch (InvalidKeyException e) {
						throw new IllegalArgumentException("无效的证书", e);
					} catch (IllegalBlockSizeException | BadPaddingException e) {
						throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
					}
				}

大佬勿喷,欢迎提意见建议评论!!!!

### 3 系统需求分析 #### 3.1 功能需求 ##### 3.1.1 用户功能 用户功能模块是系统的核心部分,旨在为旅游者提供全流程的服务支持。通过用例图(图3.1)可以清晰地展示用户与系统之间的交互关系。 **用户注册与登录** - 支持邮箱验证和手机号绑定双重认证机制 - 采用SHA-256加盐哈希算法存储密码 - 集成图形验证码和短信验证码防止恶意注册 **景点浏览与交互** - 多条件复合查询:支持按地理位置、票价区间、景点评分等多维度筛选 - 智能排序:默认按热度排序,可选最新/最优惠等排序方式 - 互动功能: - 收藏夹管理(图3.2展示收藏用例) - 评分评论(支持文字+图片评价) - 分享至社交平台 **订单管理** - 状态机设计:包含待支付/已支付/已取消/已完成等状态 - 支付集成:支持支付宝、微信支付等多种方式 - 退款流程:自动化审核与人工复核相结合 图3.1 用户功能用例图 (此处应插入用户角色与系统功能的用例关系图示) ##### 3.1.2 管理员功能 管理员功能模块侧重系统运维与数据管理,其用例图如图3.3所示。 **数据管理中心** - 批量操作:支持CSV格式数据导入导出 - 审核机制:用户提交的景点信息需经管理员审核 - 数据看板:实时显示系统关键指标(UV、PV、转化率等) **权限管理系统** - 角色分级:超级管理员/内容管理员/客服人员 - 操作日志:记录管理员所有敏感操作 - 权限粒度控制:精确到按钮级别的权限分配 **智能分析模块** - 热力图分析:展示景点访问时空分布 - 用户行为分析:通过埋点数据计算停留时长等指标 - 自动报表:每日/周/月运营报告自动生成 图3.3 管理员功能用例图 (此处应插入管理员角色与后台功能的交互图示) #### 3.2 性能需求 ##### 3.2.1 响应速度 - 核心页面加载时间≤1.5s(包含首屏渲染) - 搜索接口响应时间≤800ms(百万级数据量) - 支付回调处理时间≤300ms ##### 3.2.2 并发处理 - 支持≥5000TPS的订单创建峰值 - 秒杀场景下库存校验耗时≤50ms - 采用分布式锁处理高并发写操作 ##### 3.2.3 缓存策略 - 多级缓存架构: - 本地缓存(Caffeine):存储用户会话 - 分布式缓存(Redis):缓存热门景点数据 - CDN加速:静态资源分发 ##### 3.2.4 容灾能力 - 数据库主从切换时间≤30s - 每日自动备份且支持时间点恢复 - 关键服务有熔断降级机制 ### 4 系统设计 #### 4.1 总体设计 ##### 4.1.1 系统架构 采用改良版的三层架构(图4.1),具有以下特点: **表现层** - 基于Vue3的组件化开发 - 自适应布局支持PC/移动双端 - WebSocket实现实时通知 **业务层** - Spring Cloud微服务划分: - 用户服务 - 订单服务 - 支付服务 - 推荐服务 - 统一网关处理鉴权/限流 **数据层** - 主从复制集群(1主3从) - 读写分离配置 - 冷热数据分离存储 图4.1 系统架构图 (此处应包含架构分层与组件交互示意图) ##### 4.1.2 技术栈增强说明 **后端技术栈** - 容器化:Docker+K8s部署 - 消息队列:RocketMQ处理异步任务 - 监控体系:Prometheus+Grafana **前端技术栈** - 状态管理:Pinia替代Vuex - 构建工具:Vite替代Webpack - 可视化:Apache ECharts 5.0 **数据库优化** - 索引策略: - 联合索引:为高频查询字段建立覆盖索引 - 自适应哈希索引:针对等值查询优化 - 分库分表:订单表按用户ID哈希分片 #### 4.1.3 数据库详细设计 **E-R图关键关系** - 用户-订单:一对多关系 - 景点-标签:多对多关系(通过attraction_tag关联表实现) - 酒店-房型:一对多关系 图4.2 数据库E-R图 (此处应展示完整的实体关系示意图) **扩展表结构设计** 表4.5 收藏表(user_favorite) | 字段名 | 类型 | 约束 | 说明 | |--------|------|------|------| | id | BIGINT | 主键 | 自增ID | | user_id | INT | 外键 | 关联用户 | | resource_type | TINYINT | 非空 | 1-景点/2-酒店 | | resource_id | INT | 非空 | 资源ID | | created_at | TIMESTAMP | 默认当前时间 | 创建时间 | 表4.6 景点标签关联表(attraction_tag) | 字段名 | 类型 | 约束 | 说明 | |--------|------|------|------| | id | BIGINT | 主键 | 关联ID | | attraction_id | INT | 外键 | 景点ID | | tag_id | INT | 外键 | 标签ID | | weight | DECIMAL(3,2) | | 权重分数 | 表4.7 操作日志表(admin_log) | 字段名 | 类型 | 约束 | 说明 | |--------|------|------|------| | log_id | BIGINT | 主键 | 日志ID | | admin_id | INT | 外键 | 操作人 | | operation | VARCHAR(50) | 非空 | 操作类型 | | params | TEXT | | 请求参数 | | ip_address | VARCHAR(50) | | 操作IP | | create_time | DATETIME | | 操作时间 | #### 4.2 功能模块深度设计 ##### 4.2.1 智能推荐模块 采用混合推荐策略: 1. 基于内容的推荐:计算景点标签余弦相似度 2. 协同过滤:使用ALS算法处理用户-景点矩阵 3. 实时推荐:通过Flink处理用户实时行为数据 ##### 4.2.2 支付系统设计 - 状态机设计: ```mermaid stateDiagram [*] --> 待支付 待支付 --> 已支付: 支付成功 待支付 --> 已取消: 用户取消 已支付 --> 已退款: 发起退款 已支付 --> 已完成: 核销使用 ``` - 防重设计: - 订单号使用雪花算法生成 - 支付流水号全局唯一校验 ##### 4.2.3 安全控制 - 接口安全: - HTTPS传输加密 - 敏感数据脱敏处理 - 参数签名验证 - 风控策略: - 异地登录检测 - 高频操作限制 - 敏感操作二次认证 以上设计通过完整的流程图、状态转换图和数据库关系图进行可视化呈现,确保系统设计方案的完整性和可实施性。在具体实现时,将根据实际测试数据进行进一步的调优和迭代。请你将以上内容重新加工补充以下,包括生成相关数据图表供参考
05-13
<think>我们正在解决H5页面在企业微信中禁止分享的问题。根据引用[1]的经验,微信环境有时会限制非官方客户端的操作。企业微信基于微信,但可能有自己的安全策略。常见解决方案包括: 1. 使用企业微信官方JS-SDK的分享接口(需配置可信域名并注入权限) 2. 对于无法调用SDK的情况,引导用户通过浏览器打开 3. 检查页面是否被企业微信识别为不安全内容(如含敏感词、非备案域名等) 具体步骤: 步骤1:在企业微信管理后台配置可信域名(需已完成ICP备案) 步骤2:引入JS-SDK(https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js) 步骤3:通过config接口注入权限验证 步骤4:调用分享接口(如onMenuShareAppMessage) 示例代码: ```javascript wxwork.config({ beta: true, // 必须这么写,否则在微信插件中调用会报错 debug: false, // 调试模式 appId: '', // 企业微信的corpID timestamp: , // 生成签名的时间戳 nonceStr: '', // 生成签名的随机串 signature: '', // 签名 jsApiList: ['onMenuShareAppMessage', 'onMenuShareWechat'] // 需要使用的JS接口列表 }); wxwork.ready(function () { // 分享给朋友 wxwork.onMenuShareAppMessage({ title: '分享标题', desc: '分享描述', link: '分享链接', imgUrl: '分享图标', success: function () { }, cancel: function () { } }); // 分享到微信 wxwork.onMenuShareWechat({ title: '分享标题', desc: '分享描述', link: '分享链接', imgUrl: '分享图标', success: function () { }, cancel: function () { } }); }); ``` 注意:若仍失败,请检查: - 域名是否配置正确(包括协议头,如https) - 签名算法是否正确(使用官方提供的工具校验) - 企业微信版本是否支持(旧版本可能不支持某些接口) 若企业微信完全禁止分享,可考虑在页面内提供“复制链接”按钮,让用户手动分享。 引用[3]提到,微信浏览器有下载限制,同理分享限制也可通过引导外部浏览器解决。但企业微信环境下,外部浏览器可能无法直接打开,因此优先使用官方SDK。 根据引用[4],阻止页面拖动的方法在分享问题中不适用,但需注意避免因阻止默认事件导致分享按钮失效。 综上,使用企业微信JS-SDK是解决分享问题的首选方案。 §§相关问题§§ 1. 如何配置企业微信JS-SDK的签名? 2. 企业微信分享接口报错如何排查? 3. 企业微信中H5页面还有哪些常见限制?</think>### H5页面在企业微信中禁止分享的解决方案 企业微信对H5页面分享的限制主要源于安全策略,以下是已验证的解决方案: #### 1. **使用企业微信JS-SDK(推荐方案)** 企业微信官方提供了JS-SDK实现分享功能,需要完成以下步骤: ```javascript // 1. 引入JS-SDK <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script> // 2. 配置SDK wxwork.config({ beta: true, // 必须开启 debug: false, appId: 'YOUR_CORPID', // 企业ID timestamp: Date.now(), nonceStr: '随机字符串', signature: '加密签名', // 后端生成 jsApiList: ['onMenuShareAppMessage', 'onMenuShareWechat'] }); // 3. 注册分享接口 wxwork.ready(() => { // 分享给同事 wxwork.onMenuShareAppMessage({ title: '分享标题', desc: '分享描述', link: 'https://your-domain.com/page', imgUrl: 'https://your-domain.com/logo.png' }); // 分享到微信 wxwork.onMenuShareWechat({ title: '微信分享标题', link: 'https://your-domain.com/page', imgUrl: 'https://your-domain.com/logo.png' }); }); ``` **关键要求**: - 域名必须备案并在企业微信后台「应用管理」中配置可信域名 - 签名需后端生成([官方签名算法](https://developer.work.weixin.qq.com/document/path/90514)) - 页面必须通过企业微信内置浏览器访问 #### 2. **引导用户手动分享(备选方案)** 当SDK不可用时,添加显式提示: ```html <div class="wechat-share-guide"> <img src="guide-arrow.png"> <p>点击右上角 <span>•••</span> 选择「分享到微信」</p> </div> ``` ```css .wechat-share-guide { position: fixed; top: 20px; right: 10px; background: rgba(0,0,0,0.7); color: white; padding: 10px; border-radius: 4px; z-index: 1000; } ``` #### 3. **解决常见拦截原因** - **域名未备案**:企业微信要求所有H5域名完成ICP备案[^1] - **内容安全检测**:避免页面包含敏感词(如"红包"、"诱导分享"等) - **跨域问题**:确保所有资源(图片/接口)与页面同源或配置CORS - **协议要求**:必须使用HTTPS协议(企业微信强制要求) #### 4. **调试工具推荐** - 使用企业微信[调试工具](https://developer.work.weixin.qq.com/document/path/90502) - 开启`debug: true`模式查看SDK错误码 - 常见错误处理: - `63002`:无效URL(需检查可信域名配置) - `60001`:签名错误(验证生成算法) > **重要提示**:企业微信的分享限制比微信更严格,所有分享功能必须通过官方SDK实现。直接使用微信的JS-SDK在企业微信中无效[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值