1
0
mirror of synced 2025-12-20 15:48:01 +08:00

Compare commits

...

8 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
4ff3f1e34f 添加实名验证接口使用文档
Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com>
2025-12-19 17:31:27 +00:00
copilot-swe-agent[bot]
5f9627296d 添加实名验证服务的测试类
Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com>
2025-12-19 17:28:45 +00:00
copilot-swe-agent[bot]
e546bb3ad9 添加微信支付实名验证相关接口的核心实现
Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com>
2025-12-19 17:26:41 +00:00
copilot-swe-agent[bot]
bf4afdc2d4 Initial plan 2025-12-19 17:18:04 +00:00
舍出
b56eddd47b 🎨 #3800 【微信支付】小微商家进件 API 进行参数结构调整 2025-12-15 15:30:31 +08:00
hyf1844
ef5f28cb28 🎨 #3806 【视频号】微信小店订单详情接口新增会员权益等优惠金额字段 2025-12-11 16:32:39 +08:00
Copilot
d26172e393 🎨 #3802 【小程序】修复 WxMaExpressOrderCargo 几个字段类型以支持小数值 2025-12-10 14:27:27 +08:00
buaazyl
c777dc32a8 🎨 #3799 【小程序】发货信息管理功能补充消息推送字段,支持订单发货和结算事件的完整信息接收 2025-12-10 10:07:36 +08:00
15 changed files with 804 additions and 68 deletions

View File

@@ -241,4 +241,16 @@ public class OrderProductInfo implements Serializable {
@JsonProperty("national_subsidy_merchant_discounted_price")
private Integer nationalSubsidyMerchantDiscountedPrice;
/**
* 订单内商品维度活动商家补贴,即参与平台补贴活动时商家通过活动报名价优惠的部分,单位为分
*/
@JsonProperty("platform_activity_merchant_discounted_price")
private Integer platformActivityMerchantDiscountedPrice;
/**
* 订单内商品维度平台券优惠金额,单位为分
*/
@JsonProperty("cash_coupon_discounted_price")
private Integer cashCouponDiscountedPrice;
}

View File

@@ -465,32 +465,40 @@ public class WxConsts {
/**
* 名称审核事件
*/
public static final String WXA_NICKNAME_AUDIT = "wxa_nickname_audit" ;
public static final String WXA_NICKNAME_AUDIT = "wxa_nickname_audit";
/**
*小程序违规记录事件
*/
public static final String WXA_ILLEGAL_RECORD= "wxa_illegal_record";
* 小程序违规记录事件
*/
public static final String WXA_ILLEGAL_RECORD = "wxa_illegal_record";
/**
*小程序申诉记录推送
*/
public static final String WXA_APPEAL_RECORD= "wxa_appeal_record";
* 小程序申诉记录推送
*/
public static final String WXA_APPEAL_RECORD = "wxa_appeal_record";
/**
* 隐私权限审核结果推送
*/
public static final String WXA_PRIVACY_APPLY= "wxa_privacy_apply";
public static final String WXA_PRIVACY_APPLY = "wxa_privacy_apply";
/**
* 类目审核结果事件推送
*/
public static final String WXA_CATEGORY_AUDIT= "wxa_category_audit";
public static final String WXA_CATEGORY_AUDIT = "wxa_category_audit";
/**
* 小程序微信认证支付成功事件
*/
public static final String WX_VERIFY_PAY_SUCC= "wx_verify_pay_succ";
public static final String WX_VERIFY_PAY_SUCC = "wx_verify_pay_succ";
/**
* 小程序微信认证派单事件
*/
public static final String WX_VERIFY_DISPATCH= "wx_verify_dispatch";
}
public static final String WX_VERIFY_DISPATCH = "wx_verify_dispatch";
/**
* 提醒需要上传发货信息事件曾经发过货的小程序订单超过48小时未发货时
*/
public static final String TRADE_MANAGE_REMIND_SHIPPING = "trade_manage_remind_shipping";
/**
* 订单完成发货时、订单结算时
*/
public static final String TRADE_MANAGE_ORDER_SETTLEMENT = "trade_manage_order_settlement";
}
/**
* 上传多媒体(临时素材)文件的类型.

View File

@@ -257,6 +257,62 @@ public class WxMaMessage implements Serializable {
*/
private String context;
/**
* 微信支付订单号
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* 商户号
*/
@XStreamAlias("merchant_id")
private String merchantId;
/**
* 子商户号
*/
@XStreamAlias("sub_merchant_id")
private String subMerchantId;
/**
* 商户订单号
*/
@XStreamAlias("merchant_trade_no")
private String merchantTradeNo;
/**
* 支付成功时间,秒级时间戳
*/
@XStreamAlias("pay_time")
private Long payTime;
/**
* 消息文本内容
*/
@XStreamAlias("msg")
private String msg;
/**
* 发货时间,秒级时间戳
*/
@XStreamAlias("shipped_time")
private Long shippedTime;
/**
* 预计结算时间,秒级时间戳。发货时推送才有该字段
*/
@XStreamAlias("estimated_settlement_time")
private Long estimatedSettlementTime;
/**
* 确认收货方式1. 手动确认收货2. 自动确认收货。结算时推送才有该字段
*/
@XStreamAlias("confirm_receive_method")
private Integer confirmReceiveMethod;
/**
* 确认收货时间,秒级时间戳。结算时推送才有该字段
*/
@XStreamAlias("confirm_receive_time")
private Long confirmReceiveTime;
/**
* 订单结算时间,秒级时间戳。结算时推送才有该字段
*/
@XStreamAlias("settlement_time")
private Long settlementTime;
/**
* 不要直接使用这个字段,
* 这个字段只是为了适配 SubscribeMsgPopupEvent SubscribeMsgChangeEvent SubscribeMsgSentEvent

View File

@@ -34,7 +34,7 @@ public class WxMaExpressOrderCargo implements Serializable {
* 描述: 单位是千克(kg)
* </pre>
*/
private Integer weight;
private Double weight;
/**
* 包裹长度
@@ -44,7 +44,7 @@ public class WxMaExpressOrderCargo implements Serializable {
* </pre>
*/
@SerializedName("space_x")
private Integer spaceLength;
private Double spaceLength;
/**
* 包裹宽度
@@ -54,7 +54,7 @@ public class WxMaExpressOrderCargo implements Serializable {
* </pre>
*/
@SerializedName("space_y")
private Integer spaceWidth;
private Double spaceWidth;
/**
* 包裹高度
@@ -64,7 +64,7 @@ public class WxMaExpressOrderCargo implements Serializable {
* </pre>
*/
@SerializedName("space_z")
private Integer spaceHeight;
private Double spaceHeight;
/**
* 包裹中商品详情列表

View File

@@ -116,10 +116,10 @@ public class WxMaExpressServiceImplTest {
goodsCount ++;
}
cargo.setCount(detailList.size());
cargo.setWeight(5);
cargo.setSpaceHeight(10);
cargo.setSpaceLength(10);
cargo.setSpaceWidth(10);
cargo.setWeight(1.2);
cargo.setSpaceHeight(10.0);
cargo.setSpaceLength(20.0);
cargo.setSpaceWidth(15.0);
cargo.setDetailList(detailList);

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

@@ -424,62 +424,186 @@ public class WxPayApplyment4SubCreateRequest implements Serializable {
private MicroBizTypeEnum microBizType;
/**
* 门店名称
* 1、填写规范
* 门店场所:填写门店名称
* 流动经营/便民服务:填写经营/服务名称
* 线上商品/服务交易:填写线上店铺名称
* 2、格式规范
* 长度为1-50个字符
* 前后不能有空格、制表符、换行符
* 不能仅含数字、特殊字符
* 仅能填写数字、英文字母、汉字及特殊字符
* 仅支持utf-8格式
* 示例值:大郎烧饼
* 门店场所】 经营类型为“门店场所”时填写
*/
@SerializedName("micro_name")
private String microName;
@SerializedName("micro_store_info")
private MicroStoreInfo microStoreInfo;
/**
* 门店省市编码
* 1、只能由数字组成
* 2、详细参见微信支付提供的省市对照表
* 3、填写规范
* 门店场所:填写门店省市编码
* 流动经营/便民服务:填写经营/服务所在地省市编码
* 线上商品/服务交易:填写卖家所在地省市编码
* 示例值440305
* 【流动经营/便民服务】 经营类型为“流动经营/便民服务”时填写
*/
@SerializedName("micro_address_code")
private String microAddressCode;
@SerializedName("micro_mobile_info")
private MicroMobileInfo microMobileInfo;
/**
* 门店地址
* 1、填写规范
* 门店场所:填写店铺详细地址,具体区/县及街道门牌号或大厦楼层
* 流动经营/便民服务:填写"无"
* 线上商品/服务交易:填写电商平台名称
* 2、格式规范
* 长度为4-512个字符
* 前后不能有空格、制表符、换行符
* 不能仅含数字、特殊字符
* 仅能填写数字、英文字母、汉字及特殊字符
* 仅支持utf-8格式
* 示例值广东省深圳市南山区xx大厦x层xxxx室
* 【线上商品/服务交易】 经营场景为“线上商品/服务交易”时填写
*/
@SerializedName("micro_address")
private String microAddress;
@SerializedName("micro_online_info")
private MicroOnlineInfo microOnlineInfo;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public static class MicroOnlineInfo implements Serializable {
private static final long serialVersionUID = -4672635122639034459L;
/**
* 【线上店铺名称】 填写商家的线上店铺名称
* 1、长度为1-50个字符
* 2、前后不能有空格、制表符、换行符
* 3、不能仅含数字、特殊字符
* 4、仅能填写数字、英文字母、汉字及特殊字符
* 5、仅支持utf-8格式。
*/
@SerializedName("micro_online_store")
private String microOnlineStore;
/**
* 【电商平台名称】 填写电商平台名称
* 1、长度为1-50个字符
* 2、前后不能有空格、制表符、换行符
* 3、不能仅含数字、特殊字符
* 4、仅能填写数字、英文字母、汉字及特殊字符
* 5、仅支持utf-8格式。
*/
@SerializedName("micro_ec_name")
private String microEcName;
/**
* 【店铺二维码】
* 1、店铺二维码或店铺链接二选一必填
* 2、若为电商小程序可上传店铺页面的小程序二维码
* 3、可上传1张图片请填写通过图片上传API预先上传图片生成好的MediaID。
*/
@SerializedName("micro_qrcode")
private String microQrcode;
/**
* 【店铺链接】
* 1、店铺二维码或店铺链接二选一必填
* 2、请填写店铺主页链接需符合网站规范。
*/
@SerializedName("micro_link")
private String microLink;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public static class MicroMobileInfo implements Serializable {
private static final long serialVersionUID = -4672635122639034460L;
/**
* 【经营/服务名称】 请填写经营/服务名称
* 1、长度为1-50个字符
* 2、前后不能有空格、制表符、换行符
* 3、不能仅含数字、特殊字符
* 4、仅能填写数字、英文字母、汉字及特殊字符
* 5、仅支持utf-8格式。
*/
@SerializedName("micro_mobile_name")
private String microMobileName;
/**
* 【经营/服务所在地省市】 请填写经营/服务所在地省市编码
*/
@SerializedName("micro_mobile_city")
private String microMobileCity;
/**
* 【经营/服务所在地(不含省市)】 填写“无"
*/
@SerializedName("micro_mobile_address")
private String microMobileAddress;
/**
* 【经营/服务现场照片】
* 1、提交流动经营现场照片如摊位场景应提交摊位全景照片+商品照片。
* 2、可上传多张图片请填写通过图片上传API预先上传图片生成好的MediaID。
*/
@SerializedName("micro_mobile_pics")
private List<String> microMobilePics;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public static class MicroStoreInfo implements Serializable {
private static final long serialVersionUID = -4672635122639034461L;
/**
* 【门店名称】
* 请填写门店名称
* 1、长度为1-50个字符
* 2、前后不能有空格、制表符、换行符
* 3、不能仅含数字、特殊字符
* 4、仅能填写数字、英文字母、汉字及特殊字符
* 5、仅支持utf-8格式。
*/
@SerializedName("micro_name")
private String microName;
/**
* 【门店省市编码】
* 填写门店省市编码,只能由数字组成,详细参见微信支付提供的省市对照表
*/
@SerializedName("micro_address_code")
private String microAddressCode;
/**
* 【门店地址】
* 请填写详细的经营场所信息,如有多个场所,选择一个主要场所填写即可。
* 1、长度为4-512个字符
* 2、前后不能有空格、制表符、换行符
* 3、不能仅含数字、特殊字符
* 4、仅能填写数字、英文字母、汉字及特殊字符
* 5、仅支持utf-8格式。
*/
@SerializedName("micro_address")
private String microAddress;
/**
* 【门店门头照片】
* 1、请上传门头正面照片要求门店招牌、门框完整、清晰、可辨识若为停车场等无固定门头照片的经营场所可上传岗亭/出入闸口。
* 2、可上传1张图片请填写通过图片上传API预先上传图片生成好的MediaID。
*/
@SerializedName("store_entrance_pic")
private String storeEntrancePic;
/**
* 【店内环境照片】
* 1、请上传门店内部环境照片可辨识经营内容。若为停车场等无固定门头的经营场所可上传停车场内部照片。
* 2、可上传1张图片请填写通过图片上传API预先上传图片生成好的MediaID。
*/
@SerializedName("micro_indoor_copy")
private String microIndoorCopy;
/**
* 【门店经度】 数字或小数,商户自定义字段
*/
@SerializedName("store_longitude")
private String storeLongitude;
/**
* 【门店纬度】 纬度,商户自定义字段
*/
@SerializedName("store_latitude")
private String storeLatitude;
}
/**
* 门店门头照片/经营场景照片
* 1、门店场所请上传门头正面照片要求门店招牌、门框完整、清晰、可辨识若为停车场等无固定门头照片的经营场所可上传岗亭/出入闸口;
* 2、流动经营/便民服务填写媒体文件ID列表最多5张
* 3、线上商品/服务交易:请上传线上店铺网页截图(清晰度足够识别店铺名称的首页截图);
* 4、请填写通过《图片上传API》预先上传图片生成好的MediaID
* 示例值0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV-4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo
*/
@SerializedName("micro_pics")
private List<String> microPics;
}
@Data

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

@@ -1706,4 +1706,11 @@ public interface WxPayService {
* @return the partner pay score sign plan service
*/
PartnerPayScoreSignPlanService getPartnerPayScoreSignPlanService();
/**
* 获取实名验证服务类
*
* @return the real name service
*/
RealNameService getRealNameService();
}

View File

@@ -139,6 +139,9 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
@Getter
private final BusinessOperationTransferService businessOperationTransferService = new BusinessOperationTransferServiceImpl(this);
@Getter
private final RealNameService realNameService = new RealNameServiceImpl(this);
protected Map<String, WxPayConfig> configMap = new ConcurrentHashMap<>();
@Override

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,104 @@
package com.github.binarywang.wxpay.bean.applyment;
import java.util.Arrays;
import org.testng.annotations.Test;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
public class WxPayApplyment4SubCreateRequestTest {
@Test
public void testMicroBizInfoSerialization() {
// 1. Test MicroStoreInfo
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo.MicroStoreInfo storeInfo =
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo.MicroStoreInfo.builder()
.microName("门店名称")
.microAddressCode("440305")
.microAddress("详细地址")
.storeEntrancePic("media_id_1")
.microIndoorCopy("media_id_2")
.storeLongitude("113.941046")
.storeLatitude("22.546154")
.build();
// 2. Test MicroMobileInfo
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo.MicroMobileInfo mobileInfo =
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo.MicroMobileInfo.builder()
.microMobileName("流动经营名称")
.microMobileCity("440305")
.microMobileAddress("")
.microMobilePics(Arrays.asList("media_id_3", "media_id_4"))
.build();
// 3. Test MicroOnlineInfo
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo.MicroOnlineInfo onlineInfo =
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo.MicroOnlineInfo.builder()
.microOnlineStore("线上店铺名称")
.microEcName("电商平台名称")
.microQrcode("media_id_5")
.microLink("https://www.example.com")
.build();
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo microBizInfo =
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo.builder()
.microStoreInfo(storeInfo)
.microMobileInfo(mobileInfo)
.microOnlineInfo(onlineInfo)
.build();
Gson gson = new GsonBuilder().create();
String json = gson.toJson(microBizInfo);
// Verify MicroStoreInfo serialization
assertTrue(json.contains("\"micro_name\":\"门店名称\""));
assertTrue(json.contains("\"micro_address_code\":\"440305\""));
assertTrue(json.contains("\"micro_address\":\"详细地址\""));
assertTrue(json.contains("\"store_entrance_pic\":\"media_id_1\""));
assertTrue(json.contains("\"micro_indoor_copy\":\"media_id_2\""));
assertTrue(json.contains("\"store_longitude\":\"113.941046\""));
assertTrue(json.contains("\"store_latitude\":\"22.546154\""));
// Verify MicroMobileInfo serialization
assertTrue(json.contains("\"micro_mobile_name\":\"流动经营名称\""));
assertTrue(json.contains("\"micro_mobile_city\":\"440305\""));
assertTrue(json.contains("\"micro_mobile_address\":\"\""));
assertTrue(json.contains("\"micro_mobile_pics\":[\"media_id_3\",\"media_id_4\"]"));
// Verify MicroOnlineInfo serialization
assertTrue(json.contains("\"micro_online_store\":\"线上店铺名称\""));
assertTrue(json.contains("\"micro_ec_name\":\"电商平台名称\""));
assertTrue(json.contains("\"micro_qrcode\":\"media_id_5\""));
assertTrue(json.contains("\"micro_link\":\"https://www.example.com\""));
// Verify deserialization
WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo deserialized =
gson.fromJson(json, WxPayApplyment4SubCreateRequest.SubjectInfo.MicroBizInfo.class);
// Verify MicroStoreInfo deserialization
assertEquals(deserialized.getMicroStoreInfo().getMicroName(), "门店名称");
assertEquals(deserialized.getMicroStoreInfo().getMicroAddressCode(), "440305");
assertEquals(deserialized.getMicroStoreInfo().getMicroAddress(), "详细地址");
assertEquals(deserialized.getMicroStoreInfo().getStoreEntrancePic(), "media_id_1");
assertEquals(deserialized.getMicroStoreInfo().getMicroIndoorCopy(), "media_id_2");
assertEquals(deserialized.getMicroStoreInfo().getStoreLongitude(), "113.941046");
assertEquals(deserialized.getMicroStoreInfo().getStoreLatitude(), "22.546154");
// Verify MicroMobileInfo deserialization
assertEquals(deserialized.getMicroMobileInfo().getMicroMobileName(), "流动经营名称");
assertEquals(deserialized.getMicroMobileInfo().getMicroMobileCity(), "440305");
assertEquals(deserialized.getMicroMobileInfo().getMicroMobileAddress(), "");
assertEquals(deserialized.getMicroMobileInfo().getMicroMobilePics().size(), 2);
assertEquals(deserialized.getMicroMobileInfo().getMicroMobilePics(), Arrays.asList("media_id_3", "media_id_4"));
// Verify MicroOnlineInfo deserialization
assertEquals(deserialized.getMicroOnlineInfo().getMicroOnlineStore(), "线上店铺名称");
assertEquals(deserialized.getMicroOnlineInfo().getMicroEcName(), "电商平台名称");
assertEquals(deserialized.getMicroOnlineInfo().getMicroQrcode(), "media_id_5");
assertEquals(deserialized.getMicroOnlineInfo().getMicroLink(), "https://www.example.com");
}
}

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);
}
}