🆕 #3814 【微信支付】增加实名验证的接口

This commit is contained in:
Copilot
2025-12-20 17:23:55 +08:00
committed by GitHub
parent c8cdfb56e1
commit 3b8d0a8814
8 changed files with 432 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
# 微信支付实名验证接口使用说明
## 概述
微信支付实名验证接口允许商户查询用户的实名认证状态如果用户未实名认证接口会返回引导用户进行实名认证的URL。
## 官方文档
https://pay.wechatpay.cn/doc/v2/merchant/4011987607
## 接口说明
### 查询用户实名认证信息
- **接口地址**`https://api.mch.weixin.qq.com/userinfo/realnameauth/query`
- **请求方式**POST需要使用商户证书
- **请求参数**
- `appid`公众账号ID自动填充
- `mch_id`:商户号(自动填充)
- `openid`用户在商户appid下的唯一标识
- `nonce_str`:随机字符串(自动生成)
- `sign`:签名(自动生成)
- **返回参数**
- `return_code`:返回状态码
- `return_msg`:返回信息
- `result_code`:业务结果
- `openid`:用户标识
- `is_certified`实名认证状态Y-已实名认证N-未实名认证)
- `cert_info`:实名认证信息(加密,仅已实名时返回)
- `guide_url`引导用户进行实名认证的URL仅未实名时返回
## 使用示例
### 1. 获取实名验证服务
```java
// 获取WxPayService实例
WxPayService wxPayService = ... // 根据你的配置初始化
// 获取实名验证服务
RealNameService realNameService = wxPayService.getRealNameService();
```
### 2. 查询用户实名认证状态(完整方式)
```java
import com.github.binarywang.wxpay.bean.realname.RealNameRequest;
import com.github.binarywang.wxpay.bean.realname.RealNameResult;
import com.github.binarywang.wxpay.exception.WxPayException;
try {
// 构建请求对象
RealNameRequest request = RealNameRequest.newBuilder()
.openid("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o") // 用户的openid
.build();
// 调用查询接口
RealNameResult result = realNameService.queryRealName(request);
// 处理返回结果
if ("Y".equals(result.getIsCertified())) {
System.out.println("用户已实名认证");
System.out.println("认证信息:" + result.getCertInfo());
} else {
System.out.println("用户未实名认证");
System.out.println("引导链接:" + result.getGuideUrl());
// 可以将guide_url提供给用户引导其完成实名认证
}
} catch (WxPayException e) {
System.err.println("查询失败:" + e.getMessage());
}
```
### 3. 查询用户实名认证状态(简化方式)
```java
import com.github.binarywang.wxpay.bean.realname.RealNameResult;
import com.github.binarywang.wxpay.exception.WxPayException;
try {
// 直接传入openid进行查询
RealNameResult result = realNameService.queryRealName("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o");
// 处理返回结果
if ("Y".equals(result.getIsCertified())) {
System.out.println("用户已实名认证");
} else {
System.out.println("用户未实名认证,引导链接:" + result.getGuideUrl());
}
} catch (WxPayException e) {
System.err.println("查询失败:" + e.getMessage());
}
```
## 注意事项
1. **证书要求**:本接口需要使用商户证书进行请求,请确保已正确配置商户证书。
2. **OPENID获取**openid是用户在商户appid下的唯一标识需要通过微信公众平台或小程序获取。
3. **认证信息**`cert_info`字段返回的信息是加密的,需要使用相应的解密方法才能获取明文信息。
4. **引导链接**:当用户未实名时,返回的`guide_url`可以用于引导用户完成实名认证建议在小程序或H5页面中使用。
5. **频率限制**:请注意接口调用频率限制,避免频繁查询同一用户的实名状态。
## 业务场景
- **转账前校验**:在进行企业付款到零钱等操作前,可以先查询用户的实名认证状态
- **风控审核**:作为业务风控的一部分,确认用户已完成实名认证
- **用户引导**:发现用户未实名时,引导用户完成实名认证以使用相关功能
## 错误处理
```java
try {
RealNameResult result = realNameService.queryRealName(openid);
// 处理结果...
} catch (WxPayException e) {
// 处理异常
String errorCode = e.getErrCode();
String errorMsg = e.getErrCodeDes();
// 根据错误码进行相应处理
switch (errorCode) {
case "SYSTEMERROR":
// 系统错误,建议稍后重试
break;
case "PARAM_ERROR":
// 参数错误检查openid是否正确
break;
default:
// 其他错误
break;
}
}
```
## 相关链接
- [微信支付官方文档](https://pay.wechatpay.cn/doc/v2/merchant/4011987607)
- [WxJava项目主页](https://github.com/binarywang/WxJava)

View File

@@ -0,0 +1,50 @@
package com.github.binarywang.wxpay.bean.realname;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.*;
import me.chanjar.weixin.common.annotation.Required;
import java.util.Map;
/**
* <pre>
* 微信支付实名验证请求对象.
* 详见文档https://pay.wechatpay.cn/doc/v2/merchant/4011987607
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class RealNameRequest extends BaseWxPayRequest {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:用户标识
* 变量名openid
* 是否必填:是
* 类型String(128)
* 示例值oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
* 描述用户在商户appid下的唯一标识
* </pre>
*/
@Required
@XStreamAlias("openid")
private String openid;
@Override
protected void checkConstraints() {
//do nothing
}
@Override
protected void storeMap(Map<String, String> map) {
map.put("openid", openid);
}
}

View File

@@ -0,0 +1,91 @@
package com.github.binarywang.wxpay.bean.realname;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.w3c.dom.Document;
import java.io.Serializable;
/**
* <pre>
* 微信支付实名验证返回结果.
* 详见文档https://pay.wechatpay.cn/doc/v2/merchant/4011987607
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@XStreamAlias("xml")
public class RealNameResult extends BaseWxPayResult implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:用户标识
* 变量名openid
* 是否必填:否
* 类型String(128)
* 示例值oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
* 描述用户在商户appid下的唯一标识
* </pre>
*/
@XStreamAlias("openid")
private String openid;
/**
* <pre>
* 字段名:实名认证状态
* 变量名is_certified
* 是否必填:是
* 类型String(1)
* 示例值Y
* 描述Y-已实名认证 N-未实名认证
* </pre>
*/
@XStreamAlias("is_certified")
private String isCertified;
/**
* <pre>
* 字段名:实名认证信息
* 变量名cert_info
* 是否必填:否
* 类型String(256)
* 示例值:
* 描述:实名认证的相关信息,如姓名等(加密)
* </pre>
*/
@XStreamAlias("cert_info")
private String certInfo;
/**
* <pre>
* 字段名:引导链接
* 变量名guide_url
* 是否必填:否
* 类型String(256)
* 示例值:
* 描述未实名时引导用户进行实名认证的URL
* </pre>
*/
@XStreamAlias("guide_url")
private String guideUrl;
/**
* 从XML结构中加载额外的属性
*
* @param d Document
*/
@Override
protected void loadXml(Document d) {
openid = readXmlString(d, "openid");
isCertified = readXmlString(d, "is_certified");
certInfo = readXmlString(d, "cert_info");
guideUrl = readXmlString(d, "guide_url");
}
}

View File

@@ -0,0 +1,43 @@
package com.github.binarywang.wxpay.service;
import com.github.binarywang.wxpay.bean.realname.RealNameRequest;
import com.github.binarywang.wxpay.bean.realname.RealNameResult;
import com.github.binarywang.wxpay.exception.WxPayException;
/**
* <pre>
* 微信支付实名验证相关服务类.
* 详见文档https://pay.wechatpay.cn/doc/v2/merchant/4011987607
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public interface RealNameService {
/**
* <pre>
* 获取用户实名认证信息API.
* 用于商户查询用户的实名认证状态如果用户未实名认证会返回引导用户实名认证的URL
* 文档详见https://pay.wechatpay.cn/doc/v2/merchant/4011987607
* 接口链接https://api.mch.weixin.qq.com/userinfo/realnameauth/query
* </pre>
*
* @param request 请求对象
* @return 实名认证查询结果
* @throws WxPayException the wx pay exception
*/
RealNameResult queryRealName(RealNameRequest request) throws WxPayException;
/**
* <pre>
* 获取用户实名认证信息API简化方法.
* 用于商户查询用户的实名认证状态如果用户未实名认证会返回引导用户实名认证的URL
* 文档详见https://pay.wechatpay.cn/doc/v2/merchant/4011987607
* 接口链接https://api.mch.weixin.qq.com/userinfo/realnameauth/query
* </pre>
*
* @param openid 用户openid
* @return 实名认证查询结果
* @throws WxPayException the wx pay exception
*/
RealNameResult queryRealName(String openid) throws WxPayException;
}

View File

@@ -1707,6 +1707,13 @@ public interface WxPayService {
*/
PartnerPayScoreSignPlanService getPartnerPayScoreSignPlanService();
/**
* 获取实名验证服务类
*
* @return the real name service
*/
RealNameService getRealNameService();
/**
* 获取医保支付服务类
*

View File

@@ -137,6 +137,9 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
@Getter
private final BusinessOperationTransferService businessOperationTransferService = new BusinessOperationTransferServiceImpl(this);
@Getter
private final RealNameService realNameService = new RealNameServiceImpl(this);
@Getter
private final MiPayService miPayService = new MiPayServiceImpl(this);

View File

@@ -0,0 +1,41 @@
package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.wxpay.bean.realname.RealNameRequest;
import com.github.binarywang.wxpay.bean.realname.RealNameResult;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.RealNameService;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.RequiredArgsConstructor;
/**
* <pre>
* 微信支付实名验证相关服务实现类.
* 详见文档https://pay.wechatpay.cn/doc/v2/merchant/4011987607
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@RequiredArgsConstructor
public class RealNameServiceImpl implements RealNameService {
private final WxPayService payService;
@Override
public RealNameResult queryRealName(RealNameRequest request) throws WxPayException {
request.checkAndSign(this.payService.getConfig());
String url = this.payService.getPayBaseUrl() + "/userinfo/realnameauth/query";
String responseContent = this.payService.post(url, request.toXML(), true);
RealNameResult result = BaseWxPayResult.fromXML(responseContent, RealNameResult.class);
result.checkResult(this.payService, request.getSignType(), true);
return result;
}
@Override
public RealNameResult queryRealName(String openid) throws WxPayException {
RealNameRequest request = RealNameRequest.newBuilder()
.openid(openid)
.build();
return this.queryRealName(request);
}
}

View File

@@ -0,0 +1,54 @@
package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.wxpay.bean.realname.RealNameRequest;
import com.github.binarywang.wxpay.bean.realname.RealNameResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.testbase.ApiTestModule;
import com.google.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
/**
* <pre>
* 实名验证测试类.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Test
@Guice(modules = ApiTestModule.class)
@Slf4j
public class RealNameServiceImplTest {
@Inject
private WxPayService payService;
/**
* 测试查询用户实名认证信息.
*
* @throws WxPayException the wx pay exception
*/
@Test
public void testQueryRealName() throws WxPayException {
RealNameRequest request = RealNameRequest.newBuilder()
.openid("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o")
.build();
RealNameResult result = this.payService.getRealNameService().queryRealName(request);
log.info("实名认证查询结果:{}", result);
}
/**
* 测试查询用户实名认证信息(简化方法).
*
* @throws WxPayException the wx pay exception
*/
@Test
public void testQueryRealNameSimple() throws WxPayException {
RealNameResult result = this.payService.getRealNameService()
.queryRealName("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o");
log.info("实名认证查询结果:{}", result);
}
}