微信官方支付接口地址:https://pay.weixin.qq.com/wiki/doc/api/index.html
com.github.wxpay
wxpay-sdk
0.0.3
/**
*func :微信统一支付接口
*
*date:2019-11-11
*作者:lijinquan
**//
public ResultVO<Map<String,String>> wechatProfitSharingPay( WechatPayVo payVo) throws Exception{
logger.info("微信分账支付请求预订单号===>>>wechatProfitSharingPay");
Message message = PhaseInterceptorChain.getCurrentMessage();
HttpServletRequest httpServletRequest = (HttpServletRequest) message.get(AbstractHTTPDestination.HTTP_REQUEST);
String realIp =httpServletRequest.getRemoteAddr();
ResultVO<Map<String,String>> result=new ResultVO<Map<String,String>>();
Map<String,String> repData = new HashMap<String,String>();
result.setData(repData);
//1.参数封装
Map param=new HashMap();
//公众账号ID
param.put("appid", wechatAppId);
//商户号
param.put("mch_id", wechatMerchantId);
//随机字符串
param.put("nonce_str", WXPayUtil.generateNonceStr());
param.put("body", imName);
//交易订单号
param.put("out_trade_no", outTradeNo.trim());
//金额(分)
param.put("total_fee",actualAmount.toString());
param.put("spbill_create_ip",realIp);
param.put("notify_url", wechatNotifyUrl);
//交易类型
param.put("trade_type", "JSAPI");
param.put("sign_type", "HMAC-SHA256");//分账必须只支持HMAC-SHA256,不分账可以不设置这个参数默认就为md5
param.put("profit_sharing","Y");
//用户标示
param.put("openid", payVo.getOpenid());
try {
//根据接口文档的案例要求,微信服务器接收参数方式是xml格式,所以将参数转换为xml
//WXPayConstants.SignType.HMACSHA256这个参数不传默认为MD5,可查看源码了解详情
String xmlParam = WXPayUtil.generateSignedXml(param, wechatApiKey, WXPayConstants.SignType.HMACSHA256);
logger.info("请求的参数:"+xmlParam);
xmlParam = new String(xmlParam.getBytes("UTF-8"),"ISO8859-1");
//2.发送请求
String xmlResult = HttpClientUtil.PostXml(WXPayConstants.UNIFIEDORDER_URL, xmlParam);
System.out.println(xmlResult);
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
logger.info("微信返回结果:"+mapResult);
//返回前端数据
if (mapResult.get("return_code").equals("SUCCESS")){
//返回给APP端的参数,APP端再调起支付接口
String prepay_id= mapResult.get("prepay_id");
//签名
String sign = WXPayUtil.generateSignature(repData,wechatApiKey);
repData.put("prepayId",prepay_id);
result.setData(repData);
}
} catch (Exception e) {
e.printStackTrace();
}
// return new HashMap();
return result;
}
?SADA V-196 é?????èé???±??°é? ????¨??é??????è?°????é??? USB???? 3.5mmé?é?è??? é?è? ?
?
?
?
?
?
?
?
?
以上控制台打印的参数看着有乱码,其实不是
是这句代码
xmlParam = new String(xmlParam.getBytes("UTF-8"),"ISO8859-1");
的作用,因为中文需要处理过微信才能接收,不知其他朋友有没有尝试过中文不做编码处理就能成功调用的
官方api地址:https://pay.weixin.qq.com/wiki/doc/api/allocation_sl.php?chapter=25_1&index=1
单次分账地址https://api.mch.weixin.qq.com/secapi/pay/profitsharing
按照官方文档
进去按照流程申请得到
上微信单次分账代码,多次及其他可以仿照这个写法可以调通
/**
*@func :微信单次分账
*@data: 2019-11-11
*@auther :lijinquan
*/
public ResultVO<Map<String,Object>> wechatProfitSharing(WechatPayVo payVo){
ResultVO<Map<String,Object>> result=new ResultVO<Map<String,Object>>();
Map<String,Object> m=new HashedMap();
result.setData(m);
//1.参数封装
Map param=new HashMap();
//公众账号ID
param.put("appid", wechatAppId);
//商户号
param.put("mch_id", wechatMerchantId);
//微信支付分配的子商户号,即分账的出资商户号。
param.put("sub_mch_id", wechatMerchantId);
//随机字符串
param.put("nonce_str", WXPayUtil.generateNonceStr());
//签名类型,目前只支持HMAC-SHA256
param.put("sign_type", "HMAC-SHA256");
//微信支付订单号
param.put("transaction_id", "4200001042202104228993583353");
/**
* 服务商系统内部的分账单号,在服务商系统内部唯一
* (单次分账、多次分账、完结分账应使用不同的商户分账单号),
* 同一分账单号多次请求等同一次。只能是数字、大小写字母_-|*@
*/
param.put("out_order_no", "P001001001");
/**
* 分账接收方列表,不超过50个json对象,不能设置出资子商户作为分账接受方
点击行前的+展开字段详情
*/
List<Map> receivers=new ArrayList<Map>();
for(int i=0 ;i<1;i++){
Map receiver=new HashedMap();
/**
* -分账接收方类型
* MERCHANT_ID:商户号(mch_id或者sub_mch_id)
PERSONAL_OPENID:个人openid(由父商户APPID转换得到)
PERSONAL_SUB_OPENID: 个人sub_openid(由子商户APPID转换得到)
*/
receiver.put("type","PERSONAL_OPENID");
/**
* 类型是MERCHANT_ID时,是商户号(mch_id或者sub_mch_id)
类型是PERSONAL_OPENID时,是个人openid
类型是PERSONAL_SUB_OPENID时,是个人sub_openid
*/
receiver.put("account","oLPst4xXiA9m-MVGJBcacj1190ww");
/**
* -分账金额
* 分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额
*/
receiver.put("amount",1);
/**
* -分账描述
*
* 分账的原因描述,分账账单中需要体现
*/
receiver.put("description","微信文档值得吐槽");
/**
* -分账个人接收方姓名
* 可选项,在接收方类型为个人的时可选填,若有值,会检查与 name 是否实名匹配,不匹配会拒绝分账请求
1、分账接收方类型是PERSONAL_OPENID时,是个人姓名(选传,传则校验)
*/
receiver.put("name","这人很强");
receivers.add(receiver);
}
param.put("receivers", JSON.toJSONString(receivers));
try {
String xmlParam = WXPayUtil.generateSignedXml(param, wechatApiKey, WXPayConstants.SignType.HMACSHA256);
logger.info("请求的参数:"+xmlParam);
xmlParam = new String(xmlParam.getBytes("UTF-8"),"ISO8859-1");
//2.发送请求
// String xmlResult = HttpClientUtil.PostXml(url, xmlParam);
// String s = WxUtils.httpPostRequest(url, xmlParam);
// System.out.println(xmlResult);
CloseableHttpClient httpClient = null;
CloseableHttpResponse httpResponse = null;
KeyStore keyStore = getCertificate(wechatMerchantId);
SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, wechatMerchantId.toCharArray()).build();
SSLConnectionSocketFactory sslf = new SSLConnectionSocketFactory(sslContext);
httpClient = HttpClients.custom().setSSLSocketFactory(sslf).build();
HttpPost httpPost = new HttpPost(profitsharingUrl);
StringEntity reqEntity = new StringEntity(xmlParam);
// 设置类型
reqEntity.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(reqEntity);
// String result = null;
httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
String resultStr = EntityUtils.toString(httpEntity, "UTF-8");
System.out.println("微信响应报文:"+resultStr);
EntityUtils.consume(httpEntity);
// m.put("xmlResult",xmlResult);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
*
* @description: 获取微信证书
* @param mch_id
* @auther: lijinquan
* @date: 2019-11-11
*/
public static KeyStore getCertificate(String mch_id){
//try-with-resources 关流
try{
FileInputStream inputStream = new FileInputStream(new File("E:\\wxtest\\wxpaySecurKey\\apiclient_cert.p12"));
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(inputStream, mch_id.toCharArray());
return keyStore;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
问题一:分账接收方列表格式错误,一般情况是分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额
receiver.put("amount",1);//这个金额不能写成“1”,要直接写int类型
如果写“1”会返回以下结果
服务商和分账方无受理关系:返回信息如下
处理办法:需要添加添加分账接收方https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver
注意签名与必填参数
java代码示例:
参数WechatPayVo 可以按照自己的需要添加属性
/**
* @function 添加分账账号
* @auther lijinuquan
* @param splitSharings
* @param wxPayVo
*/
@Override
public ResultVO<Map<String, String>> profitSharingAddReceiver(WechatPayVo wxPayVo) throws Exception {
ResultVO<Map<String, String>> result = new ResultVO<Map<String, String>>();
Map<String, Object> m = new HashedMap();
//1.参数封装
Map param = new HashMap();
//商户号
param.put("mch_id", wechatMerchantId);
//微信支付分配的子商户号,即分账的出资商户号。
param.put("appid", wechatAppId);
//随机字符串
param.put("nonce_str", WXPayUtil.generateNonceStr());
//签名类型,目前只支持HMAC-SHA256
param.put("sign_type", "HMAC-SHA256");
Map receiver = new HashedMap();
//分账接收方类型:MERCHANT_ID:商户号(mch_id或者sub_mch_id)PERSONAL_OPENID:个人openid
receiver.put("type", "Y".equals(wxPayVo.getIsMechat()) ? "MERCHANT_ID" : "PERSONAL_OPENID");
receiver.put("account", wxPayVo.getOpenid());
//否
// receiver.put("name", "名字");
receiver.put("relation_type", WechatConstants.USER);
//自定义分账关系
// receiver.put("custom_relation", WechatConstants.USER);
param.put("receiver", JSON.toJSONString(receiver));
try {
String xmlParam = WXPayUtil.generateSignedXml(param, wechatApiKey, WXPayConstants.SignType.HMACSHA256);
logger.info("请求的参数:" + xmlParam);
xmlParam = new String(xmlParam.getBytes("UTF-8"), "ISO8859-1");
//2.发送请求
String xmlResult = HttpClientUtil.PostXml(profitSharingAddReceiverUrl, xmlParam);
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
logger.info("返回报文:" + xmlResult);
//返回前端数据
if (mapResult.get("return_code").equals("SUCCESS")) {
//返回前端的参数,APP端再调起支付接口
String mch_id = mapResult.get("mch_id");
String appid = mapResult.get("appid");
String rcer = mapResult.get("receiver");
String nonce_str = mapResult.get("nonce_str");
String sign = mapResult.get("sign");
JSONObject rs = JSONObject.parseObject(rcer);
if (rs != null) {
String type = rs.getString("type");
String account = rs.getString("account");
String relation_type = rs.getString("relation_type");
}
result.setData(mapResult);
} else {
result.setErrorMsg(mapResult.get("err_code_des"));
result.setAck(EnumAck.Failure);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
其他接口地址https://pay.weixin.qq.com/wiki/doc/api/external/declarecustom.php?chapter=18_2
代码可参考以上