TJoinpayMchServiceImpl.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. package com.szwl.service.impl;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  5. import com.szwl.mapper.TJoinpayMchMapper;
  6. import com.szwl.model.entity.TJoinpayMch;
  7. import com.szwl.model.utils.AESUtil;
  8. import com.szwl.model.utils.Constant;
  9. import com.szwl.model.utils.HttpClientUtils;
  10. import com.szwl.constant.JoinpayConstant;
  11. import com.szwl.model.utils.RSAUtil;
  12. import com.szwl.service.TJoinpayMchService;
  13. import lombok.extern.slf4j.Slf4j;
  14. import org.apache.commons.codec.digest.DigestUtils;
  15. import org.apache.commons.lang.StringUtils;
  16. import org.apache.http.message.BasicNameValuePair;
  17. import org.springframework.stereotype.Service;
  18. import java.io.IOException;
  19. import java.io.UnsupportedEncodingException;
  20. import java.math.BigDecimal;
  21. import java.math.RoundingMode;
  22. import java.net.URLDecoder;
  23. import java.net.URLEncoder;
  24. import java.util.*;
  25. /**
  26. * <p>
  27. * 汇聚支付用户收款信息表 服务实现类
  28. * </p>
  29. *
  30. * @author wuhs
  31. * @since 2022-04-29
  32. */
  33. @Slf4j
  34. @Service
  35. public class TJoinpayMchServiceImpl extends ServiceImpl<TJoinpayMchMapper, TJoinpayMch> implements TJoinpayMchService {
  36. @Override
  37. public String createMch(TJoinpayMch mch) {
  38. Long adminId = mch.getAdminId();
  39. if(null == adminId){
  40. return "找不到对应的管理员";
  41. }
  42. Integer alt_merchant_type = mch.getAltMerchantType();
  43. String url = "https://www.joinpay.com/allocFunds";
  44. JSONObject requestData = new JSONObject(new LinkedHashMap());
  45. String login_name = "test1_" + adminId + "@mianhuatang.com";
  46. // String login_name = mch.getLegal_person();
  47. mch.setLoginName(login_name);
  48. // String alt_mch_name = "test1_" + adminId + "@mianhuatang.com";
  49. // String alt_mch_name = mch.getLegal_person();
  50. String alt_mch_name = mch.getBankAccountName();
  51. mch.setAltMchName(alt_mch_name);
  52. mch.setAltMchShortName("");
  53. // mch.setAlt_mch_short_name("");
  54. // 格式为16 位随机字符串:16 位随机字符串
  55. String aes_key1 = getRandomString(16);
  56. String aes_key2 = getRandomString(16);
  57. requestData.put("login_name", login_name);
  58. requestData.put("alt_mch_name", alt_mch_name);
  59. requestData.put("alt_mch_short_name", "");
  60. requestData.put("alt_merchant_type", mch.getAltMerchantType());
  61. requestData.put("busi_contact_name", mch.getBusiContactName());
  62. requestData.put("busi_contact_mobile_no", mch.getBusiContactMobileNo());
  63. requestData.put("phone_no", mch.getPhoneNo());
  64. requestData.put("manage_scope", mch.getManageScope());
  65. requestData.put("manage_addr", mch.getManageAddr());
  66. requestData.put("legal_person", AESUtil.encrypt(mch.getLegalPerson() , aes_key1 , aes_key2 ));
  67. requestData.put("id_card_no", AESUtil.encrypt(mch.getIdCardNo(), aes_key1 , aes_key2 ));
  68. requestData.put("id_card_expiry", mch.getIdCardExpiry());
  69. // 个体工商户和企业必填:营业执照编号 / 营业执照有效期
  70. if(JoinpayConstant.alt_merchant_type2== alt_merchant_type || JoinpayConstant.alt_merchant_type3== alt_merchant_type){
  71. requestData.put("license_no", mch.getLicenseNo());
  72. requestData.put("license_expiry", mch.getLicenseExpiry());
  73. }
  74. if(mch.getSettMode()!=null){
  75. requestData.put("sett_mode", mch.getSettMode());
  76. }else {
  77. // 由汇聚自动结算
  78. requestData.put("sett_mode", JoinpayConstant.sett_mode1);
  79. }
  80. // 结算周期类型:自然日
  81. requestData.put("sett_date_type", JoinpayConstant.sett_date_type2);
  82. if(mch.getRiskDay()!=null){
  83. requestData.put("risk_day", mch.getRiskDay());
  84. }else{
  85. // 结算周期:1
  86. requestData.put("risk_day", 1);
  87. }
  88. if(JoinpayConstant.alt_merchant_type2== alt_merchant_type || JoinpayConstant.alt_merchant_type3== alt_merchant_type){
  89. // 企业用对公账户
  90. requestData.put("bank_account_type", JoinpayConstant.bank_account_type4);
  91. }else if(JoinpayConstant.alt_merchant_type1== alt_merchant_type){
  92. // 个人用借记卡
  93. requestData.put("bank_account_type", JoinpayConstant.bank_account_type1);
  94. }
  95. requestData.put("bank_account_name", AESUtil.encrypt(mch.getBankAccountName(), aes_key1 , aes_key2 ));
  96. requestData.put("bank_account_no", AESUtil.encrypt(mch.getBankAccountNo(), aes_key1 , aes_key2 ));
  97. requestData.put("bank_channel_no", mch.getBankChannelNo());
  98. JSONObject requestJson = new JSONObject(new TreeMap<String, Object>());
  99. requestJson.put("method", "altmch.add");
  100. requestJson.put("version", "2.0");
  101. requestJson.put("data", requestData);
  102. // 32位随机字符串
  103. String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
  104. requestJson.put("rand_str", uuid);
  105. requestJson.put("sign_type", JoinpayConstant.sign_type_MD5);
  106. requestJson.put("mch_no", JoinpayConstant.mch_no);
  107. String sign = createMD5Sign(requestJson , JoinpayConstant.key);
  108. requestJson.put("sign", sign.toUpperCase());
  109. requestJson.put("aes_key", RSAUtil.encrypt(aes_key1+":"+aes_key2 , JoinpayConstant.publickey ));
  110. // logger.info("请求参数:" + requestJson);
  111. org.json.JSONObject jsonObject;
  112. try {
  113. jsonObject = HttpClientUtils.postJson(url, requestJson.toString());
  114. // logger.info("响应参数:" + jsonObject);
  115. if(jsonObject.has("resp_code")){
  116. mch.setRespCode(jsonObject.getString("resp_code"));
  117. }
  118. if(jsonObject.has("data")){
  119. org.json.JSONObject data = jsonObject.getJSONObject("data");
  120. if(data.has("biz_code")){
  121. mch.setBizCode(data.getString("biz_code"));
  122. }
  123. if (data.has("alt_mch_no")){
  124. mch.setAltMchName(data.getString("alt_mch_no"));
  125. }
  126. if(data.has("order_status")){
  127. mch.setOrderStatus(data.getString("order_status"));
  128. }
  129. }
  130. /**
  131. * 更新一下分销商户的 各种响应码 & login_name
  132. */
  133. mch.setCreateDate(new Date());
  134. mch.setModifyDate(new Date());
  135. save(mch);
  136. if(jsonObject.has("resp_code")){
  137. String resp_code = jsonObject.getString("resp_code");
  138. mch.setRespCode(resp_code);
  139. if(JoinpayConstant.resp_code2.equals(resp_code)){
  140. org.json.JSONObject data = jsonObject.getJSONObject("data");
  141. if(data.has("biz_msg")){
  142. return data.getString("biz_msg");
  143. }
  144. }
  145. }
  146. } catch (IOException e) {
  147. e.printStackTrace();
  148. }
  149. return Constant.correct_code;
  150. }
  151. @Override
  152. public String updateMch(TJoinpayMch mch) {
  153. Long adminId = mch.getAdminId();
  154. if(null == adminId){
  155. return "找不到对应的管理员";
  156. }
  157. if(JoinpayConstant.alt_merchant_type1!=mch.getAltMerchantType()
  158. && JoinpayConstant.alt_merchant_type2!= mch.getAltMerchantType()
  159. && JoinpayConstant.alt_merchant_type3!= mch.getAltMerchantType()){
  160. return "商家类型不正确";
  161. }
  162. String url = "https://www.joinpay.com/allocFunds";
  163. JSONObject requestData = new JSONObject(new LinkedHashMap());
  164. // 格式为16 位随机字符串:16 位随机字符串
  165. String aes_key1 = getRandomString(16);
  166. String aes_key2 = getRandomString(16);
  167. requestData.put("alt_mch_no", mch.getAltMchNo());
  168. // requestData.put("legal_person", AESUtil.encrypt(legal_person, aes_key1 , aes_key2 ));
  169. requestData.put("legal_person", mch.getLegalPerson());
  170. // requestData.put("id_card_no", AESUtil.encrypt(id_card_no, aes_key1 , aes_key2 ));
  171. requestData.put("id_card_no", mch.getIdCardNo());
  172. if(JoinpayConstant.alt_merchant_type2== mch.getAltMerchantType() || JoinpayConstant.alt_merchant_type3== mch.getAltMerchantType()){
  173. // 企业用对公账户
  174. requestData.put("bank_account_type", JoinpayConstant.bank_account_type4);
  175. mch.setBankAccountType(JoinpayConstant.bank_account_type4);
  176. String alt_mch_name = mch.getBankAccountName();
  177. requestData.put("alt_mch_name", alt_mch_name);
  178. requestData.put("license_no", mch.getLicenseNo());
  179. // requestData.put("alt_mch_name", AESUtil.encrypt(alt_mch_name, aes_key1 , aes_key2 ));/**/
  180. }else if(JoinpayConstant.alt_merchant_type1== mch.getAltMerchantType()){
  181. // 个人用借记卡
  182. requestData.put("bank_account_type", JoinpayConstant.bank_account_type1);
  183. mch.setBankAccountType(JoinpayConstant.bank_account_type1);
  184. }
  185. requestData.put("bank_account_name", mch.getBankAccountName());
  186. // requestData.put("bank_account_name", AESUtil.encrypt(bank_account_name, aes_key1 , aes_key2 ));
  187. requestData.put("bank_account_no", mch.getBankAccountNo());
  188. // requestData.put("bank_account_no", AESUtil.encrypt(bank_account_no, aes_key1 , aes_key2 ));
  189. // requestData.put("bank_channel_no", AESUtil.encrypt(bank_channel_no, aes_key1 , aes_key2 ));
  190. requestData.put("bank_channel_no", mch.getBankChannelNo());
  191. if(mch.getSettMode()!=null){
  192. requestData.put("sett_mode", mch.getSettMode());
  193. }else {
  194. // 由汇聚自动结算
  195. requestData.put("sett_mode", JoinpayConstant.sett_mode1);
  196. }
  197. // 结算周期类型:自然日
  198. requestData.put("sett_date_type", JoinpayConstant.sett_date_type2);
  199. if(mch.getRiskDay()!=null){
  200. requestData.put("risk_day", mch.getRiskDay());
  201. }else{
  202. // 结算周期:1
  203. requestData.put("risk_day", 1);
  204. }
  205. // mch.setLegal_person(legal_person);
  206. // mch.setId_card_no(id_card_no);
  207. // mch.setAlt_merchant_type(alt_merchant_type);
  208. // mch.setBank_account_name(bank_account_name);
  209. // mch.setBank_account_no(bank_account_no);
  210. // mch.setBank_channel_no(bank_channel_no);
  211. if(mch.getAltMerchantType()==12){
  212. String alt_mch_name = mch.getBankAccountName();
  213. // mch.setAlt_mch_name(alt_mch_name);
  214. }
  215. JSONObject requestJson = new JSONObject(new TreeMap<String, Object>());
  216. requestJson.put("method", "altmch.modify");
  217. requestJson.put("version", "1.1");
  218. requestJson.put("data", requestData);
  219. // 32位随机字符串
  220. String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
  221. requestJson.put("rand_str", uuid);
  222. requestJson.put("sign_type", JoinpayConstant.sign_type_MD5);
  223. requestJson.put("mch_no", JoinpayConstant.mch_no);
  224. String sign = createMD5Sign(requestJson , JoinpayConstant.key);
  225. requestJson.put("sign", sign.toUpperCase());
  226. requestJson.put("aes_key", RSAUtil.encrypt(aes_key1+":"+aes_key2 , JoinpayConstant.publickey ));
  227. // logger.info("请求参数:" + requestJson);
  228. org.json.JSONObject jsonObject;
  229. try {
  230. jsonObject = HttpClientUtils.postJson(url, requestJson.toString());
  231. // logger.info("响应参数:" + jsonObject);
  232. if(jsonObject.has("resp_code")){
  233. mch.setRespCode(jsonObject.getString("resp_code"));
  234. }
  235. if(jsonObject.has("data")){
  236. org.json.JSONObject data = jsonObject.getJSONObject("data");
  237. if(data.has("biz_code")){
  238. mch.setBizCode(data.getString("biz_code"));
  239. }
  240. if (data.has("alt_mch_no")){
  241. mch.setAltMchNo(data.getString("alt_mch_no"));
  242. }
  243. if(data.has("order_status")){
  244. mch.setOrderStatus(data.getString("order_status"));
  245. }
  246. }
  247. if(jsonObject.has("resp_code")){
  248. String resp_code = jsonObject.getString("resp_code");
  249. mch.setRespCode(resp_code);
  250. if(JoinpayConstant.resp_code2.equals(resp_code)){
  251. org.json.JSONObject data = jsonObject.getJSONObject("data");
  252. if(data.has("biz_msg")){
  253. return data.getString("biz_msg");
  254. }
  255. }
  256. }
  257. } catch (IOException e) {
  258. e.printStackTrace();
  259. }
  260. return Constant.correct_code;
  261. }
  262. /**
  263. * 获取随机字符串
  264. * @return
  265. */
  266. public static String getRandomString(int length){
  267. String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  268. Random random=new Random();
  269. StringBuffer sb=new StringBuffer();
  270. for(int i=0;i<length;i++){
  271. int number=random.nextInt(62);
  272. sb.append(str.charAt(number));
  273. }
  274. return sb.toString();
  275. }
  276. /**
  277. * 签名算法sign , MD5 签名
  278. * @param requestJson
  279. * @return
  280. */
  281. public static String createMD5Sign(JSONObject requestJson , String key){
  282. StringBuffer sb = new StringBuffer();
  283. Set es = requestJson.entrySet();
  284. Iterator it = es.iterator();
  285. while(it.hasNext()) {
  286. Map.Entry entry = (Map.Entry)it.next();
  287. String k = (String)entry.getKey();
  288. Object v = entry.getValue();
  289. if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
  290. sb.append(k + "=" + v + "&");
  291. }
  292. }
  293. sb.append("key=" + key);
  294. // logger.info("签名字符串:"+sb.toString());
  295. String sign = DigestUtils.md5Hex(sb.toString());
  296. return sign;
  297. }
  298. @Override
  299. public String uniPay(String sn, BigDecimal amount, String productName, String productDesc, String commonParameter,
  300. String returnUrl, String notifyUrl, String frpCode, String isShowPic, String openId, String authCode,
  301. String appid, String transactionModel, String tradeMerchantNo, String buyerId, String isAlt, String altType,
  302. JSONArray altInfo, String altUrl, BigDecimal marketingAmount) throws UnsupportedEncodingException {
  303. String url = "https://www.joinpay.com/trade/uniPayApi.action";
  304. List<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();
  305. data.add(new BasicNameValuePair("p0_Version", JoinpayConstant.pay_version));
  306. data.add(new BasicNameValuePair("p1_MerchantNo", JoinpayConstant.mch_no));
  307. data.add(new BasicNameValuePair("p2_OrderNo", sn));
  308. data.add(new BasicNameValuePair("p3_Amount", amount.setScale(2, RoundingMode.HALF_DOWN).toString()));
  309. data.add(new BasicNameValuePair("p4_Cur", JoinpayConstant.Cur_RMB));
  310. data.add(new BasicNameValuePair("p5_ProductName", URLEncoder.encode(productName, "utf-8")));
  311. data.add(new BasicNameValuePair("p6_ProductDesc", URLEncoder.encode(productDesc, "utf-8")));
  312. data.add(new BasicNameValuePair("p7_Mp", URLEncoder.encode(commonParameter, "utf-8")));
  313. data.add(new BasicNameValuePair("p8_ReturnUrl", returnUrl));
  314. data.add(new BasicNameValuePair("p9_NotifyUrl", notifyUrl));
  315. data.add(new BasicNameValuePair("q1_FrpCode", frpCode));
  316. data.add(new BasicNameValuePair("q2_MerchantBankCode", ""));
  317. data.add(new BasicNameValuePair("q4_IsShowPic", isShowPic));
  318. data.add(new BasicNameValuePair("q5_OpenId", openId));
  319. data.add(new BasicNameValuePair("q6_AuthCode", authCode));
  320. data.add(new BasicNameValuePair("q7_AppId", appid));
  321. if(frpCode.equals("ALIPAY_CARD")||frpCode.equals("WEIXIN_CARD")){
  322. if(!StringUtils.isEmpty(tradeMerchantNo)){
  323. if(tradeMerchantNo.equals("777150700323486")){
  324. data.add(new BasicNameValuePair("q8_TerminalNo", "000001EC"));
  325. } else if(tradeMerchantNo.equals("777164600304087")){
  326. data.add(new BasicNameValuePair("q8_TerminalNo", "000001ED"));
  327. } else if(tradeMerchantNo.equals("777138500523174")){ // 七云科技
  328. data.add(new BasicNameValuePair("q8_TerminalNo", "000009F7"));
  329. } else {
  330. data.add(new BasicNameValuePair("q8_TerminalNo", "000001EE"));
  331. }
  332. }else {
  333. data.add(new BasicNameValuePair("q8_TerminalNo", "000001EE"));
  334. }
  335. }
  336. // data.add(new BasicNameValuePair("q8_TerminalNo", ""));
  337. data.add(new BasicNameValuePair("q9_TransactionModel", transactionModel));
  338. if(!StringUtils.isEmpty(tradeMerchantNo)){
  339. if(frpCode.equals("ALIPAY_CARD")||frpCode.equals("WEIXIN_CARD")){
  340. if(!StringUtils.isEmpty(tradeMerchantNo)){
  341. data.add(new BasicNameValuePair("qa_TradeMerchantNo",tradeMerchantNo));
  342. }else {
  343. data.add(new BasicNameValuePair("qa_TradeMerchantNo","777114600391409"));
  344. }
  345. }else{
  346. data.add(new BasicNameValuePair("qa_TradeMerchantNo",tradeMerchantNo));
  347. }
  348. }else {
  349. data.add(new BasicNameValuePair("qa_TradeMerchantNo","777114600391409"));
  350. }
  351. // data.add(new BasicNameValuePair("qa_TradeMerchantNo", tradeMerchantNo));
  352. data.add(new BasicNameValuePair("qb_buyerId", buyerId));
  353. data.add(new BasicNameValuePair("qc_IsAlt", isAlt));
  354. data.add(new BasicNameValuePair("qd_AltType", altType));
  355. data.add(new BasicNameValuePair("qe_AltInfo", altInfo==null?null:altInfo.toString()));
  356. data.add(new BasicNameValuePair("qf_AltUrl", altUrl));
  357. data.add(new BasicNameValuePair("qg_MarketingAmount", marketingAmount==null?null:marketingAmount.setScale(2, RoundingMode.HALF_DOWN).toString()));
  358. // TODO: 2019-04-01 空值不参与签名!!!!!!!!!!!!!!!!!!
  359. if(frpCode.equals("ALIPAY_CARD")||frpCode.equals("WEIXIN_CARD")){
  360. data.add(new BasicNameValuePair("ql_TerminalIp", "47.112.127.131"));
  361. }
  362. String hmac = createHmacSign(data, JoinpayConstant.key);
  363. data.add(new BasicNameValuePair("hmac", hmac));
  364. log.info("请求参数:" + data);
  365. String result = HttpClientUtils.postKeyValue(url, data);
  366. log.info("响应参数:" + result);
  367. return result;
  368. }
  369. /**
  370. * 签名算法sign , hmac 签名
  371. *
  372. * @param data
  373. * @return
  374. */
  375. public static String createHmacSign( List<BasicNameValuePair> data , String key) throws UnsupportedEncodingException {
  376. StringBuffer sb = new StringBuffer();
  377. Iterator<BasicNameValuePair> es = data.iterator();
  378. while (es.hasNext()) {
  379. BasicNameValuePair entry = (BasicNameValuePair) es.next();
  380. String k = (String) entry.getName();
  381. String v = (String) entry.getValue();
  382. if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
  383. sb.append(URLDecoder.decode(String.valueOf(v), "utf-8"));
  384. }
  385. }
  386. sb.append(key);
  387. // logger.info("签名字符串:" + sb.toString());
  388. String sign = DigestUtils.md5Hex(sb.toString());
  389. return sign;
  390. }
  391. }