增加分账接口

dev-discount
袁野 4 years ago
parent 94f2a489e0
commit 9e4740027f
  1. 2
      hai-bweb/src/main/resources/dev/application.yml
  2. 43
      hai-cweb/src/main/java/com/cweb/controller/pay/WechatPayController.java
  3. 48
      hai-service/src/main/java/com/hai/common/utils/HttpsUtils.java
  4. 203
      hai-service/src/main/java/com/hai/common/utils/WxUtils.java
  5. 162
      hai-service/src/main/java/com/hai/model/WxSharingOrderRequestModel.java
  6. 147
      hai-service/src/main/java/com/hai/model/WxSharingOrderResp.java
  7. 71
      hai-service/src/main/java/com/hai/model/WxSharingReceiversVO.java

@ -9,7 +9,7 @@ debug: false
#datasource数据源设置 #datasource数据源设置
spring: spring:
datasource: datasource:
url: jdbc:mysql://139.159.177.244:3306/hsg_pre?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 url: jdbc:mysql://139.159.177.244:3306/hsg_pre?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root username: root
password: HF123456. password: HF123456.
type: com.alibaba.druid.pool.DruidDataSource type: com.alibaba.druid.pool.DruidDataSource

@ -1,14 +1,21 @@
package com.cweb.controller.pay; package com.cweb.controller.pay;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cweb.config.SysConst; import com.cweb.config.SysConst;
import com.hai.common.pay.WechatPayUtil; import com.hai.common.pay.WechatPayUtil;
import com.hai.common.pay.util.IOUtil; import com.hai.common.pay.util.IOUtil;
import com.hai.common.pay.util.SignatureUtil; import com.hai.common.pay.util.SignatureUtil;
import com.hai.common.pay.util.XmlUtil; import com.hai.common.pay.util.XmlUtil;
import com.hai.common.utils.HttpsUtils;
import com.hai.common.utils.WxUtils;
import com.hai.model.WxSharingOrderRequestModel;
import com.hai.model.WxSharingReceiversVO;
import com.hai.service.pay.NotifyService; import com.hai.service.pay.NotifyService;
import com.hai.service.pay.PayRecordService; import com.hai.service.pay.PayRecordService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import net.sf.cglib.beans.BeanMap;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -19,6 +26,8 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap; import java.util.SortedMap;
@Controller @Controller
@ -148,4 +157,38 @@ public class WechatPayController {
return key; return key;
}*/ }*/
@RequestMapping(value = "/addLedgerReceiver", method = RequestMethod.POST)
@ApiOperation(value = "微信支付 -> 添加分账接收方")
public void addLedgerReceiver(HttpServletRequest request, HttpServletResponse response) {
try {
WxSharingOrderRequestModel wxSharingOrderRequest = new WxSharingOrderRequestModel();
wxSharingOrderRequest.setMch_id("1289663601");
wxSharingOrderRequest.setSub_mch_id("1609882817");
wxSharingOrderRequest.setAppid("wx637bd6f7314daa46");
wxSharingOrderRequest.setNonce_str(WxUtils.makeNonStr());
List<WxSharingReceiversVO> list = new ArrayList<>();
WxSharingReceiversVO receiversVO = new WxSharingReceiversVO();
receiversVO.setAccount(wxSharingOrderRequest.getSub_mch_id());
receiversVO.setType("MERCHANT_ID");
receiversVO.setRelation_type("SERVICE_PROVIDER");
list.add(receiversVO);
wxSharingOrderRequest.setReceivers(JSONObject.toJSONString(list));
BeanMap beanMap = BeanMap.create(wxSharingOrderRequest);
wxSharingOrderRequest.setSign(WxUtils.makeSign(beanMap, "SHA256" ,"SHA256"));
String url = "https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver";
String xm = XmlUtil.toSplitXml(wxSharingOrderRequest);
JSONObject jsonObject = HttpsUtils.postData(url, xm);
System.out.println(jsonObject);
log.info("微信支付 -> 添加分账接收方:处理开始");
} catch (Exception e) {
log.error("WechatPayController --> wechatNotify() error!", e);
}
}
} }

@ -342,8 +342,6 @@ public class HttpsUtils {
* 发送 POST 请求JSON形式 * 发送 POST 请求JSON形式
* *
* @param apiUrl * @param apiUrl
* @param json
* json对象
* @return * @return
*/ */
public static JSONObject doPost(String apiUrl, String str) { public static JSONObject doPost(String apiUrl, String str) {
@ -421,6 +419,52 @@ public class HttpsUtils {
return null; return null;
} }
/**
*
* @param url API地址
* @return
*/
public static JSONObject postData(String url, String str) {
CloseableHttpClient httpClient = null;
if (url.startsWith("https")) {
httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
.setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
} else {
httpClient = HttpClients.createDefault();
}
String httpStr = null;
CloseableHttpResponse response = null;
try {
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
StringEntity stringEntity = new StringEntity(str, "UTF-8");// 解决中文乱码问题
stringEntity.setContentEncoding("UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
stringEntity.setContentType("application/json");
httpPost.setEntity(stringEntity);
response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
httpStr = EntityUtils.toString(entity, "UTF-8");
return JSON.parseObject(httpStr);
} catch (Exception e) {
log.error(e.getMessage(),e);
} finally {
if (response != null) {
try {
EntityUtils.consume(response.getEntity());
} catch (IOException e) {
log.error(e.getMessage(),e);
}
}
}
return null;
}
/** /**
* 创建SSL安全连接 * 创建SSL安全连接
* *

@ -0,0 +1,203 @@
package com.hai.common.utils;
import com.google.common.collect.Maps;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import net.sf.cglib.beans.BeanMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.*;
public class WxUtils {
private static final Random RANDOM = new SecureRandom();
private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 生成签名
*
* @param signMaps
* @return
* @throws Exception
*/
public static String generateSign(SortedMap<String, String> signMaps, String mchKey) {
StringBuffer sb = new StringBuffer();
// 字典序
for (Map.Entry signMap : signMaps.entrySet()) {
String key = (String) signMap.getKey();
String value = (String) signMap.getValue();
// 为空不参与签名、参数名区分大小写
if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) {
sb.append(key).append("=").append(value).append("&");
}
}
// 拼接key
sb.append("key=").append(mchKey);
// MD5加密
String sign = MD5Encode(sb.toString(), "UTF-8").toUpperCase();
return sign;
}
public static String generateSignSHA256(SortedMap<String, String> signMaps,String mchKey)throws Exception{
StringBuffer sb = new StringBuffer();
// 字典序
for (Map.Entry signMap : signMaps.entrySet()) {
String key = (String) signMap.getKey();
String value = (String) signMap.getValue();
// 为空不参与签名、参数名区分大小写
if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) {
sb.append(key).append("=").append(value).append("&");
}
}
// 拼接key
sb.append("key=").append(mchKey);
// MD5加密
String sign = HMACSHA256(sb.toString(), mchKey).toUpperCase();
return sign;
}
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
private static final String[] hexDigits = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
private static HashMap<String, String> sortAsc(Map<String, String> map) {
HashMap<String, String> tempMap = new LinkedHashMap<String, String>();
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
//排序
infoIds.sort(new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return o1.getKey().compareTo(o2.getKey());
}
});
for (int i = 0; i < infoIds.size(); i++) {
Map.Entry<String, String> item = infoIds.get(i);
tempMap.put(item.getKey(), item.getValue());
}
return tempMap;
}
/**
* 生成 HMACSHA256
* @param data 待处理数据
* @param key 密钥
* @return 加密结果
* @throws Exception
*/
public static String HMACSHA256(String data, String key) throws Exception {
String hash = "";
try {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] bytes = sha256_HMAC.doFinal(data.getBytes());
hash = byteArrayToHexString(bytes);
} catch (Exception e) {
System.out.println("Error HmacSHA256 ===========" + e.getMessage());
}
return hash.toUpperCase();
}
/**
* 获取随机字符串 Nonce Str
*
* @return String 随机字符串
*/
public static String makeNonStr() {
char[] nonceChars = new char[32];
for (int index = 0; index < nonceChars.length; ++index) {
nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
}
return new String(nonceChars);
}
/**
* 拼接签名数据
*
*/
public static String makeSign(BeanMap beanMap, String mchKey, String signType)throws Exception {
SortedMap<String, String> signMaps = Maps.newTreeMap();
for (Object key : beanMap.keySet()) {
Object value = beanMap.get(key);
// 排除空数据
if (value == null) {
continue;
}
signMaps.put(key + "", String.valueOf(value));
}
if(signType.equals("MD5")) {
// 生成签名
return generateSign(signMaps, mchKey);
}else if(signType.equals("SHA256")){
return generateSignSHA256(signMaps, mchKey);
}else{
return null;
}
}
/**
* 数据转换为xml格式
*
* @param object
* @param obj
* @return
*/
public static String truncateDataToXML(Class<?> object, Object obj) {
XStream xStream = new XStream(new XppDriver(new NoNameCoder()));
xStream.alias("xml", object);
return xStream.toXML(obj);
}
}

@ -0,0 +1,162 @@
package com.hai.model;
/**
* 分账请求类
*/
public class WxSharingOrderRequestModel {
/**
* 服务商商户号
*/
private String mch_id;
/**
* 子商户号
*/
private String sub_mch_id;
/**
* 服务商appid
*/
private String appid;
/**
* 子商户appid
*/
private String sub_appid;
/**
* 随机字符串
*/
private String nonce_str;
/**
* 签名
*/
private String sign;
/**
* 签名类型只支持HMAC-SHA256
*/
private String sign_type;
/**
* 微信订单号
*/
private String transaction_id;
/**
* 商家订单号
*/
private String out_trade_no;
/**
* 商户分账单号同一个单号多次提交只算一次
*/
private String out_order_no;
/**
* 商户分账金额小于等于订单金额*1-手续费*最大分账比例
*/
private Integer amount;
/**
* 分账接收方列表单次分账不能即是支付商户又是接收商户多次分账没有限制
*/
private String receivers;
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getSub_mch_id() {
return sub_mch_id;
}
public void setSub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_mch_id;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getSub_appid() {
return sub_appid;
}
public void setSub_appid(String sub_appid) {
this.sub_appid = sub_appid;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getSign_type() {
return sign_type;
}
public void setSign_type(String sign_type) {
this.sign_type = sign_type;
}
public String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getOut_order_no() {
return out_order_no;
}
public void setOut_order_no(String out_order_no) {
this.out_order_no = out_order_no;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public String getReceivers() {
return receivers;
}
public void setReceivers(String receivers) {
this.receivers = receivers;
}
}

@ -0,0 +1,147 @@
package com.hai.model;
// 分账返回
public class WxSharingOrderResp {
//返回状态码,通信标识,SUCCESS/FAIL
private String return_code;
//返回信息,通信标识OK
private String return_msg;
//业务结果,交易标识,SUCCESS/FAIL
private String result_code;
//错误代码
private String err_code;
//错误代码描述
private String err_code_des;
//商户号
private String mch_id;
//子商户号
private String sub_mch_id;
//公众账号id
private String appid;
private String sub_appid;
//随机字符串
private String nonce_str;
//签名
private String sign;
//微信支付订单号
private String transaction_id;
//商户分账单号(商户订单号)
private String out_order_no;
//商户分账单号
private String order_id;
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getSub_mch_id() {
return sub_mch_id;
}
public void setSub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_mch_id;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getSub_appid() {
return sub_appid;
}
public void setSub_appid(String sub_appid) {
this.sub_appid = sub_appid;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_order_no() {
return out_order_no;
}
public void setOut_order_no(String out_order_no) {
this.out_order_no = out_order_no;
}
public String getOrder_id() {
return order_id;
}
public void setOrder_id(String order_id) {
this.order_id = order_id;
}
}

@ -0,0 +1,71 @@
package com.hai.model;
/**
* 分账接收方
*/
public class WxSharingReceiversVO {
/**
* 分账接收方类型
*/
private String type;
/**
* 分账接收方帐号
*/
private String account;
/**
* 分账金额
*/
private Integer amount;
/**
* 分账描述
*/
private String description;
/**
* 与分账方的关系类型
*/
private String relation_type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getRelation_type() {
return relation_type;
}
public void setRelation_type(String relation_type) {
this.relation_type = relation_type;
}
}
Loading…
Cancel
Save