Commit 9f6cb731 authored by zhuxiao's avatar zhuxiao
Browse files

优化微信支付subAppId和subOpenid支持使用子商户的

parent 0c54ea2f
...@@ -29,6 +29,7 @@ import com.github.binarywang.wxpay.v3.auth.WxPayValidator; ...@@ -29,6 +29,7 @@ import com.github.binarywang.wxpay.v3.auth.WxPayValidator;
import com.github.binarywang.wxpay.v3.util.PemUtils; import com.github.binarywang.wxpay.v3.util.PemUtils;
import com.github.binarywang.wxpay.v3.util.SignUtils; import com.github.binarywang.wxpay.v3.util.SignUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
...@@ -228,13 +229,18 @@ public class WxpayV3Util { ...@@ -228,13 +229,18 @@ public class WxpayV3Util {
case WxPayConstants.TradeType.JSAPI: { case WxPayConstants.TradeType.JSAPI: {
Map<String, String> payInfo = new HashMap<>(); // 如果用JsonObject会出现签名错误 Map<String, String> payInfo = new HashMap<>(); // 如果用JsonObject会出现签名错误
payInfo.put("appId", wxPayConfig.getAppId()); String appid = wxPayConfig.getAppId(); // 用户在服务商appid下的唯一标识
if (StringUtils.isNotEmpty(wxPayConfig.getSubAppId())) {
appid = wxPayConfig.getSubAppId(); // 用户在子商户appid下的唯一标识
}
payInfo.put("appId", appid);
payInfo.put("timeStamp", timestamp); payInfo.put("timeStamp", timestamp);
payInfo.put("nonceStr", nonceStr); payInfo.put("nonceStr", nonceStr);
payInfo.put("package", "prepay_id=" + prepayId); payInfo.put("package", "prepay_id=" + prepayId);
payInfo.put("signType", "RSA"); payInfo.put("signType", "RSA");
String beforeSign = String.format("%s\n%s\n%s\n%s\n", wxPayConfig.getAppId(), timestamp, nonceStr, "prepay_id=" + prepayId); String beforeSign = String.format("%s\n%s\n%s\n%s\n", appid, timestamp, nonceStr, "prepay_id=" + prepayId);
payInfo.put("paySign", SignUtils.sign(beforeSign, PemUtils.loadPrivateKey(new FileInputStream(wxPayConfig.getPrivateKeyPath())))); payInfo.put("paySign", SignUtils.sign(beforeSign, PemUtils.loadPrivateKey(new FileInputStream(wxPayConfig.getPrivateKeyPath()))));
// 签名以后在增加prepayId参数 // 签名以后在增加prepayId参数
payInfo.put("prepayId", prepayId); payInfo.put("prepayId", prepayId);
...@@ -246,9 +252,15 @@ public class WxpayV3Util { ...@@ -246,9 +252,15 @@ public class WxpayV3Util {
case WxPayConstants.TradeType.APP: { case WxPayConstants.TradeType.APP: {
Map<String, String> payInfo = new HashMap<>(); Map<String, String> payInfo = new HashMap<>();
// APP支付绑定的是微信开放平台上的账号,APPID为开放平台上绑定APP后发放的参数 // APP支付绑定的是微信开放平台上的账号,APPID为开放平台上绑定APP后发放的参数
String wxAppId = wxPayConfig.getSubAppId(); String wxAppId = wxPayConfig.getAppId();
// 此map用于参与调起sdk支付的二次签名,格式全小写,timestamp只能是10位,格式固定,切勿修改 // 此map用于参与调起sdk支付的二次签名,格式全小写,timestamp只能是10位,格式固定,切勿修改
String partnerId = wxPayConfig.getSubMchId(); String partnerId = wxPayConfig.getMchId();
if (StringUtils.isNotEmpty(wxPayConfig.getSubAppId())) {
wxAppId = wxPayConfig.getSubAppId();
partnerId = wxPayConfig.getSubMchId();
}
String packageValue = "Sign=WXPay"; String packageValue = "Sign=WXPay";
// 此map用于客户端与微信服务器交互 // 此map用于客户端与微信服务器交互
String beforeSign = String.format("%s\n%s\n%s\n%s\n", wxAppId, timestamp, nonceStr, "prepay_id=" + prepayId); String beforeSign = String.format("%s\n%s\n%s\n%s\n", wxAppId, timestamp, nonceStr, "prepay_id=" + prepayId);
...@@ -271,4 +283,15 @@ public class WxpayV3Util { ...@@ -271,4 +283,15 @@ public class WxpayV3Util {
} }
} }
public static String processIsvPayer(String subAppId, String openId) {
JSONObject payer = new JSONObject();
// 子商户subAppId不为空
if (StringUtils.isNotBlank(subAppId)) {
payer.put("sub_openid", openId); // 用户在子商户appid下的唯一标识
}else {
payer.put("sp_openid", openId); // 用户在服务商appid下的唯一标识
}
return payer.toJSONString();
}
} }
...@@ -67,7 +67,11 @@ public class WxJsapi extends WxpayPaymentService { ...@@ -67,7 +67,11 @@ public class WxJsapi extends WxpayPaymentService {
WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchAppConfigContext); WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchAppConfigContext);
req.setTradeType(WxPayConstants.TradeType.JSAPI); req.setTradeType(WxPayConstants.TradeType.JSAPI);
if(mchAppConfigContext.isIsvsubMch() && StringUtils.isBlank(req.getSubAppId())){ // 特约商户 && 传了子商户appId
req.setSubOpenid(bizRQ.getOpenid()); // 用户在子商户appid下的唯一标识
}else {
req.setOpenid(bizRQ.getOpenid()); req.setOpenid(bizRQ.getOpenid());
}
// 构造函数响应数据 // 构造函数响应数据
WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class); WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class);
......
...@@ -34,6 +34,7 @@ import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS; ...@@ -34,6 +34,7 @@ import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder; import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchAppConfigContext; import com.jeequan.jeepay.pay.model.MchAppConfigContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -45,6 +46,7 @@ import org.springframework.stereotype.Service; ...@@ -45,6 +46,7 @@ import org.springframework.stereotype.Service;
* @date 2021/6/8 18:08 * @date 2021/6/8 18:08
*/ */
@Service("wxpayPaymentByLiteService") //Service Name需保持全局唯一性 @Service("wxpayPaymentByLiteService") //Service Name需保持全局唯一性
@Slf4j
public class WxLite extends WxpayPaymentService { public class WxLite extends WxpayPaymentService {
@Override @Override
...@@ -65,7 +67,11 @@ public class WxLite extends WxpayPaymentService { ...@@ -65,7 +67,11 @@ public class WxLite extends WxpayPaymentService {
WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchAppConfigContext); WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchAppConfigContext);
req.setTradeType(WxPayConstants.TradeType.JSAPI); req.setTradeType(WxPayConstants.TradeType.JSAPI);
if(mchAppConfigContext.isIsvsubMch() && StringUtils.isBlank(req.getSubAppId())){ // 特约商户 && 传了子商户appId
req.setSubOpenid(bizRQ.getOpenid()); // 用户在子商户appid下的唯一标识
}else {
req.setOpenid(bizRQ.getOpenid()); req.setOpenid(bizRQ.getOpenid());
}
// 构造函数响应数据 // 构造函数响应数据
WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class); WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class);
...@@ -88,6 +94,7 @@ public class WxLite extends WxpayPaymentService { ...@@ -88,6 +94,7 @@ public class WxLite extends WxpayPaymentService {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING); channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) { } catch (WxPayException e) {
log.error("WxPayException:", e);
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e); WxpayKit.commonSetErrInfo(channelRetMsg, e);
} }
......
...@@ -30,6 +30,7 @@ import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; ...@@ -30,6 +30,7 @@ import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ; import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxAppOrderRS; import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxAppOrderRS;
import com.jeequan.jeepay.pay.util.ApiResBuilder; import com.jeequan.jeepay.pay.util.ApiResBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/* /*
...@@ -57,6 +58,14 @@ public class WxApp extends WxpayPaymentService { ...@@ -57,6 +58,14 @@ public class WxApp extends WxpayPaymentService {
// 构造请求数据 // 构造请求数据
JSONObject reqJSON = buildV3OrderRequest(payOrder, mchAppConfigContext); JSONObject reqJSON = buildV3OrderRequest(payOrder, mchAppConfigContext);
// wxPayConfig 添加子商户参数
if(mchAppConfigContext.isIsvsubMch()){
wxPayService.getConfig().setSubMchId(reqJSON.getString("sub_mchid"));
if (StringUtils.isNotBlank(reqJSON.getString("sub_appid"))) {
wxPayService.getConfig().setSubAppId(reqJSON.getString("sub_appid"));
}
}
String reqUrl; // 请求地址 String reqUrl; // 请求地址
if(mchAppConfigContext.isIsvsubMch()){ // 特约商户 if(mchAppConfigContext.isIsvsubMch()){ // 特约商户
reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.APP); reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.APP);
......
...@@ -31,6 +31,7 @@ import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ; ...@@ -31,6 +31,7 @@ import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRQ; import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS; import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS;
import com.jeequan.jeepay.pay.util.ApiResBuilder; import com.jeequan.jeepay.pay.util.ApiResBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/* /*
...@@ -55,16 +56,23 @@ public class WxJsapi extends WxpayPaymentService { ...@@ -55,16 +56,23 @@ public class WxJsapi extends WxpayPaymentService {
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq; WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext); WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
WxPayService wxPayService = wxServiceWrapper.getWxPayService(); WxPayService wxPayService = wxServiceWrapper.getWxPayService();
wxPayService.getConfig().setTradeType(WxPayConstants.TradeType.JSAPI);
// 构造请求数据 // 构造请求数据
JSONObject reqJSON = buildV3OrderRequest(payOrder, mchAppConfigContext); JSONObject reqJSON = buildV3OrderRequest(payOrder, mchAppConfigContext);
wxPayService.getConfig().setTradeType(WxPayConstants.TradeType.JSAPI); // wxPayConfig 添加子商户参数
if(mchAppConfigContext.isIsvsubMch()){
wxPayService.getConfig().setSubMchId(reqJSON.getString("sub_mchid"));
if (StringUtils.isNotBlank(reqJSON.getString("sub_appid"))) {
wxPayService.getConfig().setSubAppId(reqJSON.getString("sub_appid"));
}
}
String reqUrl; String reqUrl;
if(mchAppConfigContext.isIsvsubMch()){ // 特约商户 if(mchAppConfigContext.isIsvsubMch()){ // 特约商户
reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.JSAPI); reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
JSONObject payer = new JSONObject(); reqJSON.put("payer", WxpayV3Util.processIsvPayer(reqJSON.getString("sub_appid"), bizRQ.getOpenid()));
payer.put("sp_openid", bizRQ.getOpenid());
reqJSON.put("payer", payer);
}else { }else {
reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.JSAPI); reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
JSONObject payer = new JSONObject(); JSONObject payer = new JSONObject();
......
...@@ -31,6 +31,7 @@ import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ; ...@@ -31,6 +31,7 @@ import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRQ; import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS; import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS;
import com.jeequan.jeepay.pay.util.ApiResBuilder; import com.jeequan.jeepay.pay.util.ApiResBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/* /*
...@@ -55,19 +56,23 @@ public class WxLite extends WxpayPaymentService { ...@@ -55,19 +56,23 @@ public class WxLite extends WxpayPaymentService {
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq; WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext); WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
WxPayService wxPayService = wxServiceWrapper.getWxPayService(); WxPayService wxPayService = wxServiceWrapper.getWxPayService();
wxPayService.getConfig().setTradeType(WxPayConstants.TradeType.JSAPI);
// 构造请求数据 // 构造请求数据
JSONObject reqJSON = buildV3OrderRequest(payOrder, mchAppConfigContext); JSONObject reqJSON = buildV3OrderRequest(payOrder, mchAppConfigContext);
wxPayService.getConfig().setTradeType(WxPayConstants.TradeType.JSAPI); // wxPayConfig 添加子商户参数
if(mchAppConfigContext.isIsvsubMch()){
wxPayService.getConfig().setSubMchId(reqJSON.getString("sub_mchid"));
if (StringUtils.isNotBlank(reqJSON.getString("sub_appid"))) {
wxPayService.getConfig().setSubAppId(reqJSON.getString("sub_appid"));
}
}
String reqUrl; // 请求地址 String reqUrl; // 请求地址
if(mchAppConfigContext.isIsvsubMch()){ // 特约商户 if(mchAppConfigContext.isIsvsubMch()){ // 特约商户
reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.JSAPI); reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
reqJSON.put("payer", WxpayV3Util.processIsvPayer(reqJSON.getString("sub_appid"), bizRQ.getOpenid()));
JSONObject payer = new JSONObject();
payer.put("sp_openid", bizRQ.getOpenid());
reqJSON.put("payer", payer);
}else { }else {
reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.JSAPI); reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
......
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