Commit c686c559 authored by zhuxiao's avatar zhuxiao
Browse files

升级wx-java版本,新增微信转账、分账支持V3模式

parent bca9cc4c
......@@ -207,8 +207,7 @@ public class WxpayChannelRefundNoticeService extends AbstractChannelRefundNotice
try {
// 核对金额
String refundAmt = result.getAmount().getRefund(); // 退款金额
long wxPayAmt = new BigDecimal(refundAmt).longValue();
long wxPayAmt = result.getAmount().getRefund();
long dbPayAmt = refundOrder.getRefundAmount();
if (dbPayAmt != wxPayAmt) {
throw ResponseException.buildText("AMOUNT ERROR");
......
......@@ -18,6 +18,9 @@ package com.jeequan.jeepay.pay.channel.wxpay;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.profitsharing.*;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingReceiver;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingUnfreezeRequest;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingUnfreezeResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
......@@ -35,6 +38,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
......@@ -65,28 +69,52 @@ public class WxpayDivisionService implements IDivisionService {
try {
ProfitSharingReceiverRequest request = new ProfitSharingReceiverRequest();
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
//放置isv信息
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
if (CS.PAY_IF_VERSION.WX_V2.equals(wxServiceWrapper.getApiVersion())) { //V2
JSONObject receiverJSON = new JSONObject();
ProfitSharingReceiverRequest request = new ProfitSharingReceiverRequest();
// 0-个人, 1-商户 (目前仅支持服务商appI获取个人openId, 即: PERSONAL_OPENID, 不支持 PERSONAL_SUB_OPENID )
receiverJSON.put("type", mchDivisionReceiver.getAccType() == 0 ? "PERSONAL_OPENID" : "MERCHANT_ID");
receiverJSON.put("account", mchDivisionReceiver.getAccNo());
receiverJSON.put("name", mchDivisionReceiver.getAccName());
receiverJSON.put("relation_type", mchDivisionReceiver.getRelationType());
receiverJSON.put("custom_relation", mchDivisionReceiver.getRelationTypeName());
request.setReceiver(receiverJSON.toJSONString());
//放置isv信息
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
JSONObject receiverJSON = new JSONObject();
ProfitSharingReceiverResult profitSharingReceiverResult =
wxServiceWrapper.getWxPayService().getProfitSharingService().addReceiver(request);
// 0-个人, 1-商户 (目前仅支持服务商appI获取个人openId, 即: PERSONAL_OPENID, 不支持 PERSONAL_SUB_OPENID )
receiverJSON.put("type", mchDivisionReceiver.getAccType() == 0 ? "PERSONAL_OPENID" : "MERCHANT_ID");
receiverJSON.put("account", mchDivisionReceiver.getAccNo());
receiverJSON.put("name", mchDivisionReceiver.getAccName());
receiverJSON.put("relation_type", mchDivisionReceiver.getRelationType());
receiverJSON.put("custom_relation", mchDivisionReceiver.getRelationTypeName());
request.setReceiver(receiverJSON.toJSONString());
ProfitSharingReceiverResult profitSharingReceiverResult =
wxServiceWrapper.getWxPayService().getProfitSharingService().addReceiver(request);
// 明确成功
return ChannelRetMsg.confirmSuccess(null);
}else if (CS.PAY_IF_VERSION.WX_V3.equals(wxServiceWrapper.getApiVersion())) {
ProfitSharingReceiver profitSharingReceiver = new ProfitSharingReceiver();
profitSharingReceiver.setType(mchDivisionReceiver.getAccType() == 0 ? "PERSONAL_OPENID" : "MERCHANT_ID");
profitSharingReceiver.setAccount(mchDivisionReceiver.getAccNo());
profitSharingReceiver.setName(mchDivisionReceiver.getAccName());
profitSharingReceiver.setRelationType(mchDivisionReceiver.getRelationType());
profitSharingReceiver.setCustomRelation(mchDivisionReceiver.getRelationTypeName());
profitSharingReceiver.setAppid(WxpayKit.getWxPayConfig(wxServiceWrapper).getAppId());
// 特约商户
if(mchAppConfigContext.isIsvsubMch()){
profitSharingReceiver.setSubMchId(WxpayKit.getWxPayConfig(wxServiceWrapper).getSubMchId());
}
// 明确成功
return ChannelRetMsg.confirmSuccess(null);
ProfitSharingReceiver receiver = wxServiceWrapper.getWxPayService().getProfitSharingV3Service().addProfitSharingReceiver(profitSharingReceiver);
// 明确成功
return ChannelRetMsg.confirmSuccess(null);
} else {
return ChannelRetMsg.sysError("请选择微信V2或V3模式");
}
} catch (WxPayException wxPayException) {
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
......@@ -107,47 +135,94 @@ public class WxpayDivisionService implements IDivisionService {
try {
ProfitSharingRequest request = new ProfitSharingRequest();
request.setTransactionId(payOrder.getChannelOrderNo());
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
//放置isv信息
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
if (CS.PAY_IF_VERSION.WX_V2.equals(wxServiceWrapper.getApiVersion())) { //V2
if(recordList.isEmpty()){
request.setOutOrderNo(SeqKit.genDivisionBatchId()); // 随机生成一个订单号
}else{
request.setOutOrderNo(recordList.get(0).getBatchOrderId()); //取到批次号
}
ProfitSharingRequest request = new ProfitSharingRequest();
request.setTransactionId(payOrder.getChannelOrderNo());
//放置isv信息
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
if(recordList.isEmpty()){
request.setOutOrderNo(SeqKit.genDivisionBatchId()); // 随机生成一个订单号
}else{
request.setOutOrderNo(recordList.get(0).getBatchOrderId()); //取到批次号
}
JSONArray receiverJSONArray = new JSONArray();
JSONArray receiverJSONArray = new JSONArray();
for (int i = 0; i < recordList.size(); i++) {
for (int i = 0; i < recordList.size(); i++) {
PayOrderDivisionRecord record = recordList.get(i);
if(record.getCalDivisionAmount() <= 0){
continue;
}
PayOrderDivisionRecord record = recordList.get(i);
if(record.getCalDivisionAmount() <= 0){
continue;
JSONObject receiverJSON = new JSONObject();
// 0-个人, 1-商户 (目前仅支持服务商appI获取个人openId, 即: PERSONAL_OPENID, 不支持 PERSONAL_SUB_OPENID )
receiverJSON.put("type", record.getAccType() == 0 ? "PERSONAL_OPENID" : "MERCHANT_ID");
receiverJSON.put("account", record.getAccNo());
receiverJSON.put("amount", record.getCalDivisionAmount());
receiverJSON.put("description", record.getPayOrderId() + "分账");
receiverJSONArray.add(receiverJSON);
}
JSONObject receiverJSON = new JSONObject();
// 0-个人, 1-商户 (目前仅支持服务商appI获取个人openId, 即: PERSONAL_OPENID, 不支持 PERSONAL_SUB_OPENID )
receiverJSON.put("type", record.getAccType() == 0 ? "PERSONAL_OPENID" : "MERCHANT_ID");
receiverJSON.put("account", record.getAccNo());
receiverJSON.put("amount", record.getCalDivisionAmount());
receiverJSON.put("description", record.getPayOrderId() + "分账");
receiverJSONArray.add(receiverJSON);
}
//不存在接收账号时,订单完结(解除冻结金额)
if(receiverJSONArray.isEmpty()){
return ChannelRetMsg.confirmSuccess(this.divisionFinish(payOrder, mchAppConfigContext));
}
//不存在接收账号时,订单完结(解除冻结金额)
if(receiverJSONArray.isEmpty()){
return ChannelRetMsg.confirmSuccess(this.divisionFinish(payOrder, mchAppConfigContext));
}
request.setReceivers(receiverJSONArray.toJSONString());
request.setReceivers(receiverJSONArray.toJSONString());
ProfitSharingResult profitSharingResult = wxServiceWrapper.getWxPayService().getProfitSharingService().profitSharing(request);
return ChannelRetMsg.confirmSuccess(profitSharingResult.getOrderId());
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
}else if (CS.PAY_IF_VERSION.WX_V3.equals(wxServiceWrapper.getApiVersion())) {
ProfitSharingResult profitSharingResult = wxServiceWrapper.getWxPayService().getProfitSharingService().profitSharing(request);
return ChannelRetMsg.confirmSuccess(profitSharingResult.getOrderId());
com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingRequest request = new com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingRequest();
request.setTransactionId(payOrder.getChannelOrderNo());
request.setAppid(WxpayKit.getWxPayConfig(wxServiceWrapper).getAppId());
// 特约商户
if(mchAppConfigContext.isIsvsubMch()){
request.setSubMchId(WxpayKit.getWxPayConfig(wxServiceWrapper).getSubMchId());
}
if(recordList.isEmpty()){
request.setOutOrderNo(SeqKit.genDivisionBatchId()); // 随机生成一个订单号
}else{
request.setOutOrderNo(recordList.get(0).getBatchOrderId()); //取到批次号
}
List<ProfitSharingReceiver> receivers = new ArrayList<>();
for (int i = 0; i < recordList.size(); i++) {
PayOrderDivisionRecord record = recordList.get(i);
if(record.getCalDivisionAmount() <= 0){
continue;
}
ProfitSharingReceiver receiver = new ProfitSharingReceiver();
// 0-个人, 1-商户 (目前仅支持服务商appI获取个人openId, 即: PERSONAL_OPENID, 不支持 PERSONAL_SUB_OPENID )
receiver.setType(record.getAccType() == 0 ? "PERSONAL_OPENID" : "MERCHANT_ID");
receiver.setAccount(record.getAccNo());
receiver.setAmount(record.getCalDivisionAmount());
receiver.setDescription(record.getPayOrderId() + "分账");
receivers.add(receiver);
}
//不存在接收账号时,订单完结(解除冻结金额)
if(receivers.isEmpty()){
return ChannelRetMsg.confirmSuccess(this.divisionFinish(payOrder, mchAppConfigContext));
}
request.setReceivers(receivers);
com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingResult profitSharingResult = wxServiceWrapper.getWxPayService().getProfitSharingV3Service().profitSharing(request);
return ChannelRetMsg.confirmSuccess(profitSharingResult.getOrderId());
} else {
return ChannelRetMsg.sysError("请选择微信V2或V3模式");
}
} catch (WxPayException wxPayException) {
......@@ -167,19 +242,40 @@ public class WxpayDivisionService implements IDivisionService {
/** 调用订单的完结接口 (分账对象不存在时) */
private String divisionFinish(PayOrder payOrder,MchAppConfigContext mchAppConfigContext) throws WxPayException {
ProfitSharingFinishRequest request = new ProfitSharingFinishRequest();
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
if (CS.PAY_IF_VERSION.WX_V2.equals(wxServiceWrapper.getApiVersion())) { //V2
ProfitSharingFinishRequest request = new ProfitSharingFinishRequest();
//放置isv信息
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
//放置isv信息
WxpayKit.putApiIsvInfo(mchAppConfigContext, request);
request.setSubAppId(null); // 传入subAppId 将导致签名失败
request.setSubAppId(null); // 传入subAppId 将导致签名失败
request.setTransactionId(payOrder.getChannelOrderNo());
request.setOutOrderNo(SeqKit.genDivisionBatchId());
request.setDescription("完结分账");
request.setTransactionId(payOrder.getChannelOrderNo());
request.setOutOrderNo(SeqKit.genDivisionBatchId());
request.setDescription("完结分账");
return wxServiceWrapper.getWxPayService().getProfitSharingService().profitSharingFinish(request).getOrderId();
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
return wxServiceWrapper.getWxPayService().getProfitSharingService().profitSharingFinish(request).getOrderId();
}else {
ProfitSharingUnfreezeRequest request = new ProfitSharingUnfreezeRequest();
// 特约商户
if(mchAppConfigContext.isIsvsubMch()){
request.setSubMchId(WxpayKit.getWxPayConfig(wxServiceWrapper).getSubMchId());
}
request.setTransactionId(payOrder.getChannelOrderNo());
request.setOutOrderNo(SeqKit.genDivisionBatchId());
request.setSubMchId(null);
request.setDescription("完结分账");
ProfitSharingUnfreezeResult profitSharingUnfreezeResult = wxServiceWrapper.getWxPayService().getProfitSharingV3Service().profitSharingUnfreeze(request);
// 明确成功
return profitSharingUnfreezeResult.getOrderId();
}
}
}
......@@ -17,6 +17,8 @@ package com.jeequan.jeepay.pay.channel.wxpay;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS;
......@@ -34,6 +36,9 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 转账接口: 微信官方
*
......@@ -83,32 +88,57 @@ public class WxpayTransferService implements ITransferService {
try {
EntPayRequest request = new EntPayRequest();
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
request.setMchAppid(wxServiceWrapper.getWxPayService().getConfig().getAppId()); // 商户账号appid
request.setMchId(wxServiceWrapper.getWxPayService().getConfig().getMchId()); //商户号
request.setPartnerTradeNo(transferOrder.getTransferId()); //商户订单号
request.setOpenid(transferOrder.getAccountNo()); //openid
request.setAmount(transferOrder.getAmount().intValue()); //付款金额,单位为分
request.setSpbillCreateIp(transferOrder.getClientIp());
request.setDescription(transferOrder.getTransferDesc()); //付款备注
if(StringUtils.isNotEmpty(transferOrder.getAccountName())){
request.setReUserName(transferOrder.getAccountName());
request.setCheckName("FORCE_CHECK");
}else{
request.setCheckName("NO_CHECK");
}
EntPayResult entPayResult = wxServiceWrapper.getWxPayService().getEntPayService().entPay(request);
// SUCCESS/FAIL,注意:当状态为FAIL时,存在业务结果未明确的情况。如果状态为FAIL,请务必关注错误代码(err_code字段),通过查询接口确认此次付款的结果。
if("SUCCESS".equalsIgnoreCase(entPayResult.getResultCode())){
return ChannelRetMsg.confirmSuccess(entPayResult.getPaymentNo());
}else{
return ChannelRetMsg.waiting();
if (CS.PAY_IF_VERSION.WX_V2.equals(wxServiceWrapper.getApiVersion())) { //V2
EntPayRequest request = new EntPayRequest();
request.setMchAppid(wxServiceWrapper.getWxPayService().getConfig().getAppId()); // 商户账号appid
request.setMchId(wxServiceWrapper.getWxPayService().getConfig().getMchId()); //商户号
request.setPartnerTradeNo(transferOrder.getTransferId()); //商户订单号
request.setOpenid(transferOrder.getAccountNo()); //openid
request.setAmount(transferOrder.getAmount().intValue()); //付款金额,单位为分
request.setSpbillCreateIp(transferOrder.getClientIp());
request.setDescription(transferOrder.getTransferDesc()); //付款备注
if(StringUtils.isNotEmpty(transferOrder.getAccountName())){
request.setReUserName(transferOrder.getAccountName());
request.setCheckName("FORCE_CHECK");
}else{
request.setCheckName("NO_CHECK");
}
EntPayResult entPayResult = wxServiceWrapper.getWxPayService().getEntPayService().entPay(request);
// SUCCESS/FAIL,注意:当状态为FAIL时,存在业务结果未明确的情况。如果状态为FAIL,请务必关注错误代码(err_code字段),通过查询接口确认此次付款的结果。
if("SUCCESS".equalsIgnoreCase(entPayResult.getResultCode())){
return ChannelRetMsg.confirmSuccess(entPayResult.getPaymentNo());
}else{
return ChannelRetMsg.waiting();
}
} else if (CS.PAY_IF_VERSION.WX_V3.equals(wxServiceWrapper.getApiVersion())) {
TransferBatchesRequest request = new TransferBatchesRequest();
request.setAppid(wxServiceWrapper.getWxPayService().getConfig().getAppId());
request.setTotalAmount(transferOrder.getAmount().intValue());
request.setTotalNum(1);
request.setOutBatchNo(transferOrder.getTransferId());
request.setBatchName(transferOrder.getAccountName());
request.setBatchRemark(transferOrder.getTransferDesc());
List<TransferBatchesRequest.TransferDetail> list = new ArrayList<>();
TransferBatchesRequest.TransferDetail transferDetail = new TransferBatchesRequest.TransferDetail();
transferDetail.setOutDetailNo(transferOrder.getTransferId());
transferDetail.setOpenid(transferOrder.getAccountNo());
transferDetail.setTransferAmount(transferOrder.getAmount().intValue()); //付款金额,单位为分
transferDetail.setUserName(transferOrder.getAccountName());
transferDetail.setTransferRemark(transferOrder.getTransferDesc());
request.setTransferDetailList(list);
TransferBatchesResult transferBatchesResult = wxServiceWrapper.getWxPayService().getTransferService().transferBatches(request);
return ChannelRetMsg.confirmSuccess(transferBatchesResult.getBatchId());
} else {
return ChannelRetMsg.sysError("请选择微信V2或V3模式");
}
} catch (WxPayException e) {
......
......@@ -16,10 +16,12 @@
package com.jeequan.jeepay.pay.channel.wxpay.kits;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvsubMchParams;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.pay.model.WxServiceWrapper;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
import com.jeequan.jeepay.pay.service.ConfigContextQueryService;
......@@ -51,6 +53,11 @@ public class WxpayKit {
req.setSubAppId(isvsubMchParams.getSubMchAppId());
}
/** 构造服务商 + 商户配置 wxPayConfig **/
public static WxPayConfig getWxPayConfig(WxServiceWrapper wxServiceWrapper){
return wxServiceWrapper.getWxPayService().getConfig();
}
public static String appendErrCode(String code, String subCode){
return StringUtils.defaultIfEmpty(subCode, code); //优先: subCode
}
......
......@@ -48,7 +48,7 @@
<hutool.util.version>5.7.16</hutool.util.version> <!-- hutool -->
<spring.security.version>5.4.7</spring.security.version> <!-- 用于core的scope依赖 -->
<jjwt.version>0.9.1</jjwt.version>
<binarywang.weixin.java.version>4.1.0</binarywang.weixin.java.version>
<binarywang.weixin.java.version>4.3.9.B</binarywang.weixin.java.version>
<rocketmq.spring.boot.starter.version>2.2.0</rocketmq.spring.boot.starter.version>
<aliyun-openservices-ons-client.version>1.8.8.1.Final</aliyun-openservices-ons-client.version>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment