param = new HashMap<>(2);
+ param.put("pre_auth_code", preAuthCode.getPreAuthCode());
+ param.put("session_info", sessionInfo);
+ String postData = new Gson().toJson(param);
+
+ post(setSessionUrl, postData);
+
+ String preAuthUrl = "https://open.work.weixin.qq.com/3rdapp/install?suite_id=" + configStorage.getSuiteId() +
+ "&pre_auth_code=" + preAuthCode.getPreAuthCode() + "&redirect_uri=" + URLEncoder.encode(redirectUri, "utf-8");
+ if (StringUtils.isNotBlank(state)) {
+ preAuthUrl += "&state=" + state;
+ }
+ return preAuthUrl;
+ }
+
@Override
public WxCpTpAuthInfo getAuthInfo(String authCorpId, String permanentCode) throws WxErrorException {
JsonObject jsonObject = new JsonObject();
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entwxpay/EntWxEmpPayRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entwxpay/EntWxEmpPayRequest.java
new file mode 100644
index 000000000..37c0d038d
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entwxpay/EntWxEmpPayRequest.java
@@ -0,0 +1,229 @@
+package com.github.binarywang.wxpay.bean.entwxpay;
+
+import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import lombok.*;
+import me.chanjar.weixin.common.annotation.Required;
+
+import java.util.Map;
+
+/**
+ * Created on 2020/11/29.
+ * 向员工付款请求对象
+ * @author 拎小壶冲
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Builder(builderMethodName = "newBuilder")
+@NoArgsConstructor
+@AllArgsConstructor
+@XStreamAlias("xml")
+public class EntWxEmpPayRequest extends BaseWxPayRequest {
+
+ /**
+ *
+ * 字段名:商户订单号.
+ * 变量名:partner_trade_no
+ * 是否必填:是
+ * 示例值:10000098201411111234567890
+ * 类型:String
+ * 描述:商户订单号
+ *
+ */
+ @Required
+ @XStreamAlias("partner_trade_no")
+ private String partnerTradeNo;
+
+ /**
+ *
+ * 字段名:需保持唯一性 用户openid.
+ * 变量名:openid
+ * 是否必填:是
+ * 示例值:oxTWIuGaIt6gTKsQRLau2M0yL16E
+ * 类型:String
+ * 描述:商户appid下,某用户的openid
+ *
+ */
+ @Required
+ @XStreamAlias("openid")
+ private String openid;
+
+ /**
+ *
+ * 字段名:设备号.
+ * 变量名:device_info
+ * 是否必填:否
+ * 示例值:13467007045764
+ * 类型:String(32)
+ * 描述:微信支付分配的终端设备号
+ *
+ */
+ @XStreamAlias("device_info")
+ private String deviceInfo;
+
+ /**
+ *
+ * 字段名:校验用户姓名选项.
+ * 变量名:check_name
+ * 是否必填:是
+ * 示例值:OPTION_CHECK
+ * 类型:String
+ * 描述:NO_CHECK:不校验真实姓名
+ * FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账)
+ * OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
+ *
+ */
+ @Required
+ @XStreamAlias("check_name")
+ private String checkName;
+
+ /**
+ *
+ * 字段名:收款用户姓名.
+ * 变量名:re_user_name
+ * 是否必填:可选
+ * 示例值:马花花
+ * 类型:String
+ * 描述:收款用户真实姓名。
+ * 如果check_name设置为FORCE_CHECK或OPTION_CHECK, 则必填用户真实姓名
+ *
+ */
+ @XStreamAlias("re_user_name")
+ private String reUserName;
+
+ /**
+ *
+ * 字段名:金额.
+ * 变量名:amount
+ * 是否必填:是
+ * 示例值:10099
+ * 类型:int
+ * 描述:企业付款金额, 单位为分
+ *
+ */
+ @Required
+ @XStreamAlias("amount")
+ private Integer amount;
+
+ /**
+ *
+ * 字段名:企业付款描述信息.
+ * 变量名:desc
+ * 是否必填:是
+ * 示例值:理赔
+ * 类型:String
+ * 描述:企业付款操作说明信息。必填。
+ *
+ */
+ @Required
+ @XStreamAlias("desc")
+ private String description;
+
+ /**
+ *
+ * 字段名:Ip地址.
+ * 变量名:spbill_create_ip
+ * 是否必填:是
+ * 示例值:192.168.0.1
+ * 类型:String(32)
+ * 描述:调用接口的机器Ip地址
+ *
+ */
+ @Required
+ @XStreamAlias("spbill_create_ip")
+ private String spbillCreateIp;
+
+ /**
+ *
+ * 字段名: 付款消息类型
+ * 变量名: ww_msg_type
+ * 是否必填: 是
+ * 示例值:NORMAL_MSG
+ * 描述:NORMAL_MSG:普通付款消息 APPROVAL _MSG:审批付款消息
+ *
+ */
+ @Required
+ @XStreamAlias("ww_msg_type")
+ private String wwMsgType;
+
+ /**
+ *
+ * 字段名: 审批单号
+ * 变量名: approval_number
+ * 是否必填: 否
+ * 示例值: 201705160008
+ * 描述:ww_msg_type为APPROVAL _MSG时,需要填写approval_number
+ *
+ */
+ @XStreamAlias("approval_number")
+ private String approvalNumber;
+
+ /**
+ *
+ * 字段名: 审批类型
+ * 变量名: approval_type
+ * 是否必填: 否
+ * 示例值: 1
+ * 描述:ww_msg_type为APPROVAL _MSG时,需要填写1
+ *
+ */
+ @XStreamAlias("approval_type")
+ private Integer approvalType;
+
+
+ /**
+ *
+ * 字段名: 项目名称
+ * 变量名: act_name
+ * 是否必填: 是
+ * 示例值: 产品部门报销
+ * 描述:项目名称,最长50个utf8字符
+ *
+ */
+ @Required
+ @XStreamAlias("act_name")
+ private String actName;
+
+ /**
+ *
+ * 字段名: 付款的应用id
+ * 变量名: agentid
+ * 是否必填: 否
+ * 示例值: 1
+ * 描述:以企业应用的名义付款,企业应用id,整型,可在企业微信管理端应用的设置页面查看。
+ *
+ */
+ @XStreamAlias("agentid")
+ private Integer agentId;
+
+
+ @Override
+ protected void checkConstraints() throws WxPayException {
+
+ }
+
+ @Override
+ protected boolean isWxWorkSign() {
+ return true;
+ }
+
+ @Override
+ protected void storeMap(Map map) {
+ map.put("appid", appid);
+ map.put("mch_id", mchId);
+ map.put("device_info", deviceInfo);
+ map.put("partner_trade_no", partnerTradeNo);
+ map.put("openid", openid);
+ map.put("check_name", checkName);
+ map.put("re_user_name", reUserName);
+ map.put("amount", amount.toString());
+ map.put("desc", description);
+ map.put("spbill_create_ip", spbillCreateIp);
+ map.put("act_name", actName);
+ map.put("ww_msg_type", wwMsgType);
+ map.put("approval_number", approvalNumber);
+ map.put("approval_type", approvalType.toString());
+ map.put("agentid", agentId.toString());
+ }
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EntPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EntPayService.java
index 1b1b76b15..ed159275b 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EntPayService.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EntPayService.java
@@ -1,6 +1,7 @@
package com.github.binarywang.wxpay.service;
import com.github.binarywang.wxpay.bean.entpay.*;
+import com.github.binarywang.wxpay.bean.entwxpay.EntWxEmpPayRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
/**
@@ -143,4 +144,15 @@ public interface EntPayService {
* @throws WxPayException the wx pay exception
*/
EntPayRedpackQueryResult queryEnterpriseRedpack(EntPayRedpackQueryRequest request) throws WxPayException;
+
+ /**
+ * 向员工付款
+ * 文档详见 https://work.weixin.qq.com/api/doc/90000/90135/90278
+ * 接口链接 https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/paywwsptrans2pocket
+ *
+ * @param request 请求对象
+ * @return EntPayResult the ent pay result
+ * @throws WxPayException the wx pay exception
+ */
+ EntPayResult toEmpPay(EntWxEmpPayRequest request) throws WxPayException;
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImpl.java
index be823c8da..db464936c 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImpl.java
@@ -1,6 +1,7 @@
package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.wxpay.bean.entpay.*;
+import com.github.binarywang.wxpay.bean.entwxpay.EntWxEmpPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayDefaultRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
@@ -151,6 +152,24 @@ public class EntPayServiceImpl implements EntPayService {
return result;
}
+ @Override
+ public EntPayResult toEmpPay(EntWxEmpPayRequest request) throws WxPayException {
+ //企业微信签名,需要在请求签名之前
+ request.setNonceStr(String.valueOf(System.currentTimeMillis()));
+ request.setWorkWxSign(SignUtils.createEntSign(request.getAmount(), request.getAppid(), request.getDescription(),
+ request.getMchId(), request.getNonceStr(), request.getOpenid(), request.getPartnerTradeNo(),
+ request.getWwMsgType(), payService.getConfig().getEntPayKey(), WxPayConstants.SignType.MD5));
+
+ request.checkAndSign(this.payService.getConfig());
+
+ String url = this.payService.getPayBaseUrl() + "/mmpaymkttransfers/promotion/paywwsptrans2pocket";
+ String responseContent = this.payService.post(url, request.toXML(), true);
+ final EntPayResult result = BaseWxPayResult.fromXML(responseContent, EntPayResult.class);
+
+ result.checkResult(this.payService, request.getSignType(), true);
+ return result;
+ }
+
private String encryptRSA(File publicKeyFile, String srcString) throws WxPayException {
try {
Security.addProvider(new BouncyCastleProvider());
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java
index 0ce39a731..9e005a813 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java
@@ -127,6 +127,30 @@ public class SignUtils {
sortedMap.put("total_amount", totalAmount + "");
sortedMap.put("wxappid", wxAppId);
+ return toSignBuilder(sortedMap, signKey, signType);
+ }
+
+ /**
+ * 企业微信签名
+ * @param signType md5 目前接口要求使用的加密类型
+ */
+ public static String createEntSign(Integer totalAmount, String appId, String description, String mchId,
+ String nonceStr, String openid, String partnerTradeNo, String wwMsgType,
+ String signKey, String signType) {
+ Map sortedMap = new HashMap<>(8);
+ sortedMap.put("amount", String.valueOf(totalAmount));
+ sortedMap.put("appid", appId);
+ sortedMap.put("desc", description);
+ sortedMap.put("mch_id", mchId);
+ sortedMap.put("nonce_str", nonceStr);
+ sortedMap.put("openid", openid);
+ sortedMap.put("partner_trade_no", partnerTradeNo);
+ sortedMap.put("ww_msg_type", wwMsgType);
+
+ return toSignBuilder(sortedMap, signKey, signType);
+ }
+
+ private static String toSignBuilder(Map sortedMap, String signKey, String signType) {
Iterator> iterator = new TreeMap<>(sortedMap).entrySet().iterator();
StringBuilder toSign = new StringBuilder();
while (iterator.hasNext()) {
@@ -148,7 +172,6 @@ public class SignUtils {
} else {
return DigestUtils.md5Hex(toSign.toString()).toUpperCase();
}
-
}
/**