From cd829f8e3215c9bde88141e3c961975623bc8f05 Mon Sep 17 00:00:00 2001 From: qiaowei Date: Mon, 22 Apr 2019 14:15:50 +0800 Subject: [PATCH] =?utf8?q?=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98API?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../dlpay/consume/bean/WechatReqResp.java | 472 ++++++++++++++++++ .../dlpay/framework/util/DateUtil.java | 5 +- .../dlpay/framework/util/TradeCode.java | 1 + .../dlpay/framework/util/XmlUtils.java | 144 ++++++ .../supwisdom/dlpay/consume/ThirdPayCall.kt | 145 +++++- .../dlpay/consume/comsume_builder.kt | 3 + .../consume/controller/consume_service.kt | 82 +++ .../consume/controller/notify_controller.kt | 100 ++++ .../consume/service/impl/pay_service_impl.kt | 2 +- .../kotlin/com/supwisdom/dlpay/security.kt | 1 + 10 files changed, 949 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/supwisdom/dlpay/consume/bean/WechatReqResp.java create mode 100644 src/main/java/com/supwisdom/dlpay/framework/util/XmlUtils.java create mode 100644 src/main/kotlin/com/supwisdom/dlpay/consume/controller/notify_controller.kt diff --git a/src/main/java/com/supwisdom/dlpay/consume/bean/WechatReqResp.java b/src/main/java/com/supwisdom/dlpay/consume/bean/WechatReqResp.java new file mode 100644 index 00000000..13f42c48 --- /dev/null +++ b/src/main/java/com/supwisdom/dlpay/consume/bean/WechatReqResp.java @@ -0,0 +1,472 @@ +package com.supwisdom.dlpay.consume.bean; + +import com.supwisdom.dlpay.framework.util.MD5; +import com.supwisdom.dlpay.framework.util.RandomUtils; + +/** + * Created by shuwei on 17/6/12. + */ +public class WechatReqResp { + private int retcode; + private String retmsg; + + private String nonce_str; + private String appid; + private String body; + private String mch_id; + private String openid; + private String out_trade_no; + private String spbill_create_ip; + private String trade_type; + private String key; + private String sign; + private int total_fee; + private String timestamp; + private String auth_code; + + private String out_refund_no; + private int refund_fee; + private String refund_desc; + + private String notify_url; + private String prepay_id; + private String wpackage; + + private String scene_info; + + private String mweb_url; + + public String getScene_info() { + return scene_info; + } + + public void setScene_info(String scene_info) { + this.scene_info = scene_info; + } + + public String getMweb_url() { + return mweb_url; + } + + public void setMweb_url(String mweb_url) { + this.mweb_url = mweb_url; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + 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 getSpbill_create_ip() { + return spbill_create_ip; + } + + public void setSpbill_create_ip(String spbill_create_ip) { + this.spbill_create_ip = spbill_create_ip; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public int getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(int total_fee) { + this.total_fee = total_fee; + } + + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + public String getAuth_code() { + return auth_code; + } + + public void setAuth_code(String auth_code) { + this.auth_code = auth_code; + } + + + public String getNotify_url() { + return notify_url; + } + + public void setNotify_url(String notify_url) { + this.notify_url = notify_url; + } + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public String getWpackage() { + return wpackage; + } + + public void setWpackage(String wpackage) { + this.wpackage = wpackage; + } + + public int getRetcode() { + return retcode; + } + + public void setRetcode(int retcode) { + this.retcode = retcode; + } + + public String getRetmsg() { + return retmsg; + } + + public void setRetmsg(String retmsg) { + this.retmsg = retmsg; + } + + public String getOut_refund_no() { + return out_refund_no; + } + + public void setOut_refund_no(String out_refund_no) { + this.out_refund_no = out_refund_no; + } + + public int getRefund_fee() { + return refund_fee; + } + + public void setRefund_fee(int refund_fee) { + this.refund_fee = refund_fee; + } + + public String getRefund_desc() { + return refund_desc; + } + + public void setRefund_desc(String refund_desc) { + this.refund_desc = refund_desc; + } + + public String generalPaySign() { + this.nonce_str = RandomUtils.getRandomString(30); + StringBuffer str = new StringBuffer() + .append("appid=").append(this.appid) + .append("&auth_code=").append(this.auth_code) + .append("&body=").append(this.body) + .append("&mch_id=").append(this.mch_id) + .append("&nonce_str=").append(nonce_str) + .append("&out_trade_no=").append(this.out_trade_no) + .append("&spbill_create_ip=").append(this.spbill_create_ip) + .append("&total_fee=").append(this.total_fee) + ; + str.append("&key=").append(this.key); + this.sign = MD5.encodeByMD5(str.toString()); + return sign; + } + public String generalCheckSign(){ + this.nonce_str = RandomUtils.getRandomString(30); + StringBuffer str = new StringBuffer() + .append("appid=").append(this.appid) + .append("&auth_code=").append(this.auth_code) + .append("&mch_id=").append(this.mch_id) + .append("&nonce_str=").append(nonce_str); + str.append("&key=").append(this.key); + this.sign = MD5.encodeByMD5(str.toString()); + return sign; + } + public String generalCheckXML(){ + StringBuffer requestStr = new StringBuffer(); + requestStr + .append("") + .append("") + .append(this.appid) + .append("") + .append("") + .append(this.auth_code) + .append("") + .append("") + .append(this.mch_id) + .append("") + .append("") + .append(this.nonce_str) + .append("") + ; + requestStr.append("") + .append(this.sign) + .append("") + .append(""); + return requestStr.toString(); + } + + + public String generaPayXML() { + StringBuffer requestStr = new StringBuffer(); + requestStr + .append("") + .append("") + .append(this.appid) + .append("") + .append("") + .append(this.auth_code) + .append("") + .append("") + .append(this.body) + .append("") + .append("") + .append(this.mch_id) + .append("") + .append("") + .append(this.nonce_str) + .append("") + .append("") + .append(this.out_trade_no) + .append("") + .append("") + .append(this.spbill_create_ip) + .append("") + .append("") + .append(this.total_fee) + .append("") + ; + + requestStr.append("") + .append(this.sign) + .append("") + .append(""); + return requestStr.toString(); + } + public String generaSign() { + this.nonce_str = RandomUtils.getRandomString(30); + StringBuffer str = new StringBuffer() + .append("appid=").append(this.appid) + .append("&body=").append(this.body) + .append("&mch_id=").append(this.mch_id) + .append("&nonce_str=").append(nonce_str) + .append("¬ify_url=").append(this.notify_url); + if ("JSAPI".equals(this.trade_type)) { + str.append("&openid=").append(this.openid); + } + str.append("&out_trade_no=").append(this.out_trade_no); + if ("MWEB".equals(this.trade_type)) { + str.append("&scene_info=").append(this.scene_info); + } + str.append("&spbill_create_ip=").append(this.spbill_create_ip) + .append("&total_fee=").append(this.total_fee) + .append("&trade_type=").append(this.trade_type); + str.append("&key=").append(this.key); + this.sign = MD5.encodeByMD5(str.toString()); + return sign; + } + public String generaReverseSign() { + this.nonce_str = RandomUtils.getRandomString(30); + StringBuffer str = new StringBuffer() + .append("appid=").append(this.appid) + .append("&mch_id=").append(this.mch_id) + .append("&nonce_str=").append(nonce_str) + .append("¬ify_url=").append(this.notify_url) + .append("&out_refund_no=").append(this.out_refund_no) + .append("&out_trade_no=").append(this.out_trade_no) + .append("&refund_desc=").append(this.refund_desc) + .append("&refund_fee=").append(this.refund_fee) + .append("&total_fee=").append(this.total_fee) + ; + str.append("&key=").append(this.key); + this.sign = MD5.encodeByMD5(str.toString()); + return sign; + } + public String generaXML() { + StringBuffer requestStr = new StringBuffer(); + requestStr + .append("") + .append("") + .append(this.appid) + .append("") + .append("") + .append(this.body) + .append("") + .append("") + .append(this.mch_id) + .append("") + .append("") + .append(this.nonce_str) + .append("") + .append("") + .append(this.notify_url) + .append("") + .append("") + .append(this.out_trade_no) + .append("") + .append("") + .append(this.spbill_create_ip) + .append("") + .append("") + .append(this.total_fee) + .append("") + .append("") + .append(this.trade_type) + .append("") + ; + if ("JSAPI".equals(this.trade_type)) { + requestStr.append("") + .append(this.openid) + .append(""); + } + if ("MWEB".equals(this.trade_type)) { + requestStr.append("") + .append(this.scene_info) + .append(""); + } + requestStr.append("") + .append(this.sign) + .append("") + .append(""); + return requestStr.toString(); + } + + public String generaReverseXML() { + StringBuffer requestStr = new StringBuffer(); + requestStr + .append("") + .append("") + .append(this.appid) + .append("") + .append("") + .append(this.mch_id) + .append("") + .append("") + .append(this.nonce_str) + .append("") + .append("") + .append(this.notify_url) + .append("") + .append("") + .append(this.out_refund_no) + .append("") + .append("") + .append(this.out_trade_no) + .append("") + .append("") + .append(this.refund_desc) + .append("") + .append("") + .append(this.refund_fee) + .append("") + .append("") + .append(this.total_fee) + .append("") + ; + requestStr.append("") + .append(this.sign) + .append("") + .append(""); + return requestStr.toString(); + } + + + public String generaAPPSign() { + String signTemp = "appid=" + this.appid + + "&nonce_str=" + this.nonce_str + + "&package=" + this.wpackage + + "&partnerid=" + this.mch_id + + "&prepayid=" + this.prepay_id + + "×tamp=" + this.timestamp + + "&key=" + this.key; + this.sign = MD5.encodeByMD5(signTemp); + return sign; + } + + public String generaJSAPISign() { + String signTemp = "appId=" + this.appid + + "&nonceStr=" + this.nonce_str + + "&package=prepay_id=" + this.prepay_id + + "&signType=MD5" + + "&timeStamp=" + this.timestamp + + "&key=" + this.key; + this.sign = MD5.encodeByMD5(signTemp); + return sign; + } + + public String generaJSAPIParamters() { + String json = "{\"appId\":\"" + this.appid + "\"," + + "\"nonceStr\":\"" + this.nonce_str + "\"," + + "\"packages\":\"prepay_id=" + this.prepay_id + "\"," + + "\"signType\":\"MD5\"," + + "\"timeStamp\":\"" + this.timestamp + "\"," + + "\"paySign\":\"" + this.sign + "\"}"; + return json; + } +} diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/DateUtil.java b/src/main/java/com/supwisdom/dlpay/framework/util/DateUtil.java index 1a70722a..a17a6eeb 100644 --- a/src/main/java/com/supwisdom/dlpay/framework/util/DateUtil.java +++ b/src/main/java/com/supwisdom/dlpay/framework/util/DateUtil.java @@ -299,7 +299,10 @@ public class DateUtil { } - + public static long getNowSecond() { + Calendar calendar = Calendar.getInstance(); + return calendar.getTimeInMillis() / 1000; + } } diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java b/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java index 2c9d7df4..c4dde6e2 100644 --- a/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java +++ b/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java @@ -6,6 +6,7 @@ package com.supwisdom.dlpay.framework.util; public class TradeCode { public static final int TRANSCODE_PAY = 6630; public static final int TRANSCODE_YKTPAY=1000; + public static final int TRANSCODE_WECHAT=1001; public static final int TRANSTYPE_PAY = 311; diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/XmlUtils.java b/src/main/java/com/supwisdom/dlpay/framework/util/XmlUtils.java new file mode 100644 index 00000000..fefbc517 --- /dev/null +++ b/src/main/java/com/supwisdom/dlpay/framework/util/XmlUtils.java @@ -0,0 +1,144 @@ +package com.supwisdom.dlpay.framework.util; + +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import java.io.*; +import java.util.*; + +public class XmlUtils { + public static String getObjectToXml(T object) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + try { + JAXBContext context = JAXBContext.newInstance(object.getClass()); + // 将对象转变为xml Object------XML + // 指定对应的xml文件 + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_ENCODING,"gbk");//编码格式  + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);// 是否格式化生成的xml串 + marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);// 是否省略xml头信息 + + // 将对象转换为对应的XML文件 + marshaller.marshal(object, byteArrayOutputStream); + } catch (JAXBException e) { + + e.printStackTrace(); + } + // 转化为字符串返回 + String xmlContent = new String(byteArrayOutputStream.toByteArray(), + "gbk"); + return xmlContent; + } + + public static T getXmlToObject(String xmlContent, Class clazz) { + try { + JAXBContext context = JAXBContext.newInstance(clazz); + // xml转换为对象 XML------Object + InputStream inputStream; + try { + inputStream = new ByteArrayInputStream( + xmlContent.getBytes("GBK")); + Unmarshaller um = context.createUnmarshaller(); + + return (T) um.unmarshal(inputStream); + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }catch (Exception e) { + e.printStackTrace(); + } + } catch (JAXBException e) { + + e.printStackTrace(); + } + return null; + } + + public static T getXmlToObject(String xmlContent,String charset, Class clazz) { + try { + JAXBContext context = JAXBContext.newInstance(clazz); + // xml转换为对象 XML------Object + InputStream inputStream; + try { + inputStream = new ByteArrayInputStream( + xmlContent.getBytes(charset)); + Unmarshaller um = context.createUnmarshaller(); + + return (T) um.unmarshal(inputStream); + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }catch (Exception e) { + e.printStackTrace(); + } + } catch (JAXBException e) { + + e.printStackTrace(); + } + return null; + } + public static Map parseXml(String xml) throws Exception { + Map map = new HashMap(); + Document document = DocumentHelper.parseText(xml); + Element root = document.getRootElement(); + List elementList = root.elements(); + for (Element e : elementList) + map.put(e.getName(), e.getText()); + return map; + } + /** + * 除去数组中的空值和签名参数 + * + * @param sArray 签名参数组 + * @return 去掉空值与签名参数后的新签名参数组 + */ + public static Map paraFilter(Map sArray) { + Map result = new HashMap(); + if (sArray == null || sArray.size() <= 0) { + return result; + } + for (String key : sArray.keySet()) { + String value = sArray.get(key); + if (value == null || "".equals(value) || "sign".equalsIgnoreCase(key) + || "sign_type".equalsIgnoreCase(key)) { + continue; + } + result.put(key, value); + } + + return result; + } + + /** + * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串 + * + * @param params 需要排序并参与字符拼接的参数组 + * @return 拼接后字符串 + */ + public static String createLinkString(Map params) { + + List keys = new ArrayList(params.keySet()); + Collections.sort(keys); + + String prestr = ""; + + for (int i = 0; i < keys.size(); i++) { + String key = keys.get(i); + String value = params.get(key); + + if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符 + prestr = prestr + key + "=" + value; + } else { + prestr = prestr + key + "=" + value + "&"; + } + } + + return prestr; + } +} diff --git a/src/main/kotlin/com/supwisdom/dlpay/consume/ThirdPayCall.kt b/src/main/kotlin/com/supwisdom/dlpay/consume/ThirdPayCall.kt index 3defd76e..c3f9704d 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/consume/ThirdPayCall.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/consume/ThirdPayCall.kt @@ -6,9 +6,10 @@ import com.sun.jersey.api.client.ClientResponse import com.supwisdom.dlpay.consume.bean.BaseResp import com.supwisdom.dlpay.consume.bean.SupStatusRevResp import com.supwisdom.dlpay.consume.bean.SupYktResp +import com.supwisdom.dlpay.consume.bean.WechatReqResp import com.supwisdom.dlpay.consume.domain.TUserdtl -import com.supwisdom.dlpay.framework.util.MoneyUtil -import com.supwisdom.dlpay.framework.util.HmacUtil +import com.supwisdom.dlpay.framework.util.* +import com.supwisdom.dlpay.util.Code /** * Created by shuwei on 2019/4/11. @@ -16,10 +17,15 @@ import com.supwisdom.dlpay.framework.util.HmacUtil class CallService { companion object { - fun callYktPay(config: Map, paydtl: TUserdtl, time: String,stuempno: String, yktshopid: String, devphyid: String?): BaseResp { + fun callYktPay(config: Map, paydtl: TUserdtl, time: String, stuempno: String, yktshopid: String, devphyid: String?): BaseResp { val code = BaseResp() - val appid = config["appid"] + if (appid.isNullOrEmpty()) { + code.retcode = "1" + code.retmsg = "一卡通支付方式未启用或未配置" + return code + } + val appkey = config["appkey"] val orderurl = config["orderurl"] @@ -90,5 +96,136 @@ class CallService { code.retmsg = "请求失败" return code } + + fun callWechatPay(config: Map, paydtl: TUserdtl, time: String, wechattype: String, + realip: String?, qrcode: String?, openid: String?): BaseResp { + val code = BaseResp() + val appid = config["appid"] + if (appid.isNullOrEmpty()) { + code.retcode = "1" + code.retmsg = "微信支付方式未启用或未配置" + return code + } + val appkey = config["appkey"] + val orderurl = config["orderurl"] + val mchid = config["mchid"] + val wechatReqResp = WechatReqResp() + wechatReqResp.openid = openid + wechatReqResp.appid = appid + wechatReqResp.total_fee = MoneyUtil.YuanToFen(paydtl.amount) + wechatReqResp.body = paydtl.payinfo + wechatReqResp.key = appkey + wechatReqResp.mch_id = mchid + wechatReqResp.notify_url = config["notifyurl"] + "/notify/wechat" + wechatReqResp.out_trade_no = paydtl.refno + wechatReqResp.spbill_create_ip = realip + val c = Client.create() + c.setConnectTimeout(20000) + return when (wechattype) { + "qrcode" -> { + code + } + "app" -> { + wechatReqResp.trade_type = "APP" + code + } + "mp" -> { + wechatReqResp.trade_type = "JSAPI" + wechatReqResp.generaSign() + val xml = wechatReqResp.generaXML() + val r = c.resource(orderurl) + val respClient = r.post(ClientResponse::class.java, xml) + if (200 == respClient.status) { + try { + val ret = respClient.getEntity(String::class.java) + if (ret != null) { + val eleMap = XmlUtils.parseXml(ret) + val retcode = eleMap["return_code"] + val result_code = eleMap["result_code"] + val prepay_id = eleMap["prepay_id"] + if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode + && !result_code.isNullOrEmpty() && "SUCCESS" == result_code + && !prepay_id.isNullOrEmpty()) { + wechatReqResp.retcode = 0 + wechatReqResp.retmsg = "初始化成功" + wechatReqResp.prepay_id = prepay_id + //TODO prepay_id 是否保存 + wechatReqResp.timestamp = DateUtil.getNowSecond().toString() + wechatReqResp.nonce_str = RandomUtils.getRandomString(30) + wechatReqResp.generaJSAPISign() + val params = wechatReqResp.generaJSAPIParamters() + code.setCode(Code.SUCCESS) + code.data = params + } else { + code.retcode = "1" + code.retmsg = eleMap["return_msg"] + } + } else { + code.retcode = "1" + code.retmsg = "微信支付请求失败" + } + } catch (e: Exception) { + e.printStackTrace() + code.retcode = "1" + code.retmsg = "微信支付请求异常" + } + + } else { + code.retcode = "1" + code.retmsg = "微信支付请求返回失败" + } + code + } + "h5" -> { + wechatReqResp.trade_type = "MWEB" + wechatReqResp.scene_info = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"" + config["notifyurl"] + "\",\"wap_name\": \"${paydtl.payinfo}\"}}" + val xml = wechatReqResp.generaXML() + val r = c.resource(orderurl) + val respClient = r.post(ClientResponse::class.java, xml) + if (200 == respClient.status) { + try { + val ret = respClient.getEntity(String::class.java) + if (ret != null) { + val eleMap = XmlUtils.parseXml(ret) + val retcode = eleMap["return_code"] + val result_code = eleMap["result_code"] + val prepay_id = eleMap["prepay_id"] + val mweb_url = eleMap["mweb_url"] + if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode + && !result_code.isNullOrEmpty() && "SUCCESS" == result_code + && !prepay_id.isNullOrEmpty()) { + wechatReqResp.retcode = 0 + wechatReqResp.retmsg = "初始化成功" + wechatReqResp.prepay_id = prepay_id + wechatReqResp.mweb_url = mweb_url + code.setCode(Code.SUCCESS) + code.data = mweb_url + } else { + code.retcode = "1" + code.retmsg = eleMap["return_msg"] + } + } else { + code.retcode = "1" + code.retmsg = "微信支付请求失败" + } + } catch (e: Exception) { + e.printStackTrace() + code.retcode = "1" + code.retmsg = "微信支付请求异常" + } + + } else { + code.retcode = "1" + code.retmsg = "微信支付请求返回失败" + } + code + } + else -> { + code.retcode = "1" + code.retmsg = "未标识的类型:wechattype=$wechattype" + code + } + } + } } } \ No newline at end of file diff --git a/src/main/kotlin/com/supwisdom/dlpay/consume/comsume_builder.kt b/src/main/kotlin/com/supwisdom/dlpay/consume/comsume_builder.kt index a650004c..6c1c8602 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/consume/comsume_builder.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/consume/comsume_builder.kt @@ -340,4 +340,7 @@ class PersonTransBuilder private constructor(accUitl: AccountUtilServcie) { fun done(refno: String, status: String, service: PersonBalancePayService): TUserdtl { return service.finish(refno, status, null) } + fun done(refno: String, status: String, businessData: Map?,service: PersonBalancePayService): TUserdtl { + return service.finish(refno, status, businessData) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/supwisdom/dlpay/consume/controller/consume_service.kt b/src/main/kotlin/com/supwisdom/dlpay/consume/controller/consume_service.kt index 2d2d465f..a8adc8ab 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/consume/controller/consume_service.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/consume/controller/consume_service.kt @@ -3,6 +3,7 @@ package com.supwisdom.dlpay.consume.controller import com.supwisdom.dlpay.consume.AccountHolder import com.supwisdom.dlpay.consume.CallService import com.supwisdom.dlpay.consume.PersonTransBuilder +import com.supwisdom.dlpay.consume.domain.TPaytype import com.supwisdom.dlpay.consume.service.AccountUtilServcie import com.supwisdom.dlpay.consume.service.PaytypeService import com.supwisdom.dlpay.consume.service.PersonBalancePayService @@ -10,6 +11,7 @@ import com.supwisdom.dlpay.consume.service.PersonService import com.supwisdom.dlpay.exception.TransactionException import com.supwisdom.dlpay.framework.ResponseBodyBuilder import com.supwisdom.dlpay.framework.util.* +import com.supwisdom.dlpay.util.ConstUtil import com.supwisdom.dlpay.util.PaytypeUtil import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.ResponseEntity @@ -74,6 +76,11 @@ class ConsumeController { outtradeno: String, payinfo: String, feetype: String): ResponseEntity { //一卡通支付款 112240 return try { + val paytype = paytypeService.getByPaytype(PaytypeUtil.YKTPAY) + if (paytype == null || ConstUtil.ENABLE_YES != paytype.enable) { + ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(1, "支付方式未开启")) + } val person = personService.getPersonByThirdUniqueIdenty(stuempno) val dtl = PersonTransBuilder.newBuilder(accountUtilServcie) .setTransDatetime(transdate, transtime) @@ -101,6 +108,11 @@ class ConsumeController { AccountHolder.shop(shopid), manageFee / 100.0, "优惠折扣") } + else -> { + it.addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_YKT), + AccountHolder.shop(shopid), + amount / 100.0, "一卡通支付") + } } }.done(personBalancePayService, false) ResponseEntity.ok(ResponseBodyBuilder.create() @@ -136,4 +148,74 @@ class ConsumeController { .transException(e, "交易确认失败")) } } + + /** + * 微信支付 + * wechattype + * qrcode-扫微信二维码支付 + * app-原生app微信支付 + * mp-微信公众号支付 + * h5-微信h5支付 + * + * */ + @PostMapping("/wechat/payinit") + fun wechatPayInit(userid: String, amount: Int, manageFee: Int, + stuempno: String, shopid: String, transdate: String, transtime: String, + outtradeno: String, payinfo: String, feetype: String, + wechattype: String, realip: String?, qrcode: String?, openid: String?): ResponseEntity { + return try { + val paytype = paytypeService.getByPaytype(PaytypeUtil.WECHAT) + if (paytype == null || ConstUtil.ENABLE_YES != paytype.enable) { + ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(1, "支付方式未开启")) + } + val person = personService.getPersonByThirdUniqueIdenty(stuempno) + val dtl = PersonTransBuilder.newBuilder(accountUtilServcie) + .setTransDatetime(transdate, transtime) + .selectPaytype(PaytypeUtil.WECHAT, payinfo) + .setOuttradeno(outtradeno) + .setOwner(person) + .tryLock(true) + .setTransinfo(TradeCode.TRANSCODE_WECHAT, "微信支付") + .chooseTradetype(Tradetype.CONSUME) + .also { + when (feetype) { + TradeDict.FEETYPE_CONSUME_MEALER -> { + it.addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_WECHAT), + AccountHolder.shop(shopid), + amount / 100.0, "微信支付") + .addDetail(AccountHolder.transType(TranstypeCode.TT_CONSUUME_MANAGE_FEE) + .with(AccountHolder.shop(shopid)), + manageFee / 100.0) + } + TradeDict.FEETYPE_CONSUME_DISCOUNT -> { + it.addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_WECHAT), + AccountHolder.shop(shopid), + (amount - manageFee) / 100.0, "微信支付") + .addDetail(AccountHolder.subject(Subject.SUBJNO_CONSUME_DISCOUNT), + AccountHolder.shop(shopid), + manageFee / 100.0, "优惠折扣") + } + else -> { + it.addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_WECHAT), + AccountHolder.shop(shopid), + amount / 100.0, "微信支付") + } + } + }.done(personBalancePayService, false) + val code = CallService.callWechatPay(paytypeService.getPaytypeConfigByPaytype(PaytypeUtil.WECHAT), + dtl, DateUtil.getNow(), wechattype, realip, qrcode, openid) + if (code.retcode == "0") { + ResponseEntity.ok(ResponseBodyBuilder.create() + .data("refno", dtl.refno) + .success()) + } else { + ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "交易请求失败-${code.retcode}")) + } + } catch (e: TransactionException) { + ResponseEntity.ok(ResponseBodyBuilder.create() + .transException(e, "交易初始化异常")) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/supwisdom/dlpay/consume/controller/notify_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/consume/controller/notify_controller.kt new file mode 100644 index 00000000..a9fe3fd9 --- /dev/null +++ b/src/main/kotlin/com/supwisdom/dlpay/consume/controller/notify_controller.kt @@ -0,0 +1,100 @@ +package com.supwisdom.dlpay.consume.controller + +import com.supwisdom.dlpay.consume.PersonTransBuilder +import com.supwisdom.dlpay.consume.service.AccountUtilServcie +import com.supwisdom.dlpay.consume.service.PaytypeService +import com.supwisdom.dlpay.consume.service.PersonBalancePayService +import com.supwisdom.dlpay.framework.util.MD5 +import com.supwisdom.dlpay.framework.util.TradeDict +import com.supwisdom.dlpay.framework.util.XmlUtils +import com.supwisdom.dlpay.util.PaytypeUtil +import org.dom4j.io.SAXReader +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.util.StringUtils +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.ResponseBody +import org.springframework.web.bind.annotation.RestController +import java.util.HashMap +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +/** + * Created by shuwei on 2019/4/22. + */ +@RestController +@RequestMapping("/api/notify") +class NotifyController { + private val logger = LoggerFactory.getLogger(NotifyController::class.java) + @Autowired + lateinit var personBalancePayService: PersonBalancePayService + @Autowired + lateinit var paytypeService: PaytypeService + @Autowired + lateinit var accountUtilServcie: AccountUtilServcie + + @RequestMapping(value = "/wechat") + @ResponseBody + fun index(@PathVariable schema: String, request: HttpServletRequest, + response: HttpServletResponse): String { + try { + // 解析结果存储在HashMap + var map: MutableMap = HashMap() + val inputStream = request.inputStream + // 读取输入流 + val reader = SAXReader() + val document = reader.read(inputStream) + // 得到xml根元素 + val root = document.rootElement + // 得到根元素的所有子节点 + val elementList = root.elements() + // 遍历所有子节点 + for (e in elementList) { + map[e.name] = e.text + logger.error("*************" + e.name + "=" + e.text + "************************") + } + // 释放资源 + inputStream.close() + + val sign = map["sign"] + if (StringUtils.isEmpty(sign)) { + logger.error("签名错误") + return "" + } + map = XmlUtils.paraFilter(map) + //TODO 校验签名 + var signStr = XmlUtils.createLinkString(map) + val config = paytypeService.getPaytypeConfigByPaytype(PaytypeUtil.WECHAT) + if (config["appkey"].isNullOrEmpty()) { + logger.error("签名错误") + return "" + } + val key = config["appkey"] + signStr += "&key=$key" + val signRet = MD5.encodeByMD5(signStr) + logger.error("*******signStr=$signStr") + if (!signRet.equals(sign, ignoreCase = true)) { + return "" + } + logger.error("*******signRet=$signRet,sign=$sign*****************") + val return_code = map["return_code"] + val result_code = map["result_code"] + val out_trade_no = map["out_trade_no"] + if (StringUtils.isEmpty(out_trade_no)) { + return "" + } + if (!StringUtils.isEmpty(return_code) && "SUCCESS" == return_code + && !StringUtils.isEmpty(result_code) && "SUCCESS" == result_code) { + //map.get("transaction_id") 第三方流水号 + PersonTransBuilder.newBuilder(accountUtilServcie) + .done(out_trade_no!!, TradeDict.DTL_STATUS_SUCCESS, map, personBalancePayService) + } + return "" + } catch (e: Exception) { + e.printStackTrace() + logger.error("------------step7----------------" + e.message) + return "" + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/supwisdom/dlpay/consume/service/impl/pay_service_impl.kt b/src/main/kotlin/com/supwisdom/dlpay/consume/service/impl/pay_service_impl.kt index ee703a04..1034d855 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/consume/service/impl/pay_service_impl.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/consume/service/impl/pay_service_impl.kt @@ -227,7 +227,7 @@ class PersonBalancePayServiceImpl : PersonBalancePayService { if (TradeDict.DTL_STATUS_SUCCESS == userdtl.status) { return } - + //TODO 校验已经成功的流水,不重复入账 debitCreditDtlDao.findByRefno(userdtl.refno).forEach { detail -> //个人账户入账 if (Subject.SUBJNO_PERSONAL_DEPOSIT == detail.drsubjno) { diff --git a/src/main/kotlin/com/supwisdom/dlpay/security.kt b/src/main/kotlin/com/supwisdom/dlpay/security.kt index 05d87093..6fd99abc 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/security.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/security.kt @@ -78,6 +78,7 @@ class WebSecurityConfig { UsernamePasswordAuthenticationFilter::class.java) .authorizeRequests() .antMatchers("/api/auth/**").permitAll() + .antMatchers("/api/notify/**").permitAll() .antMatchers("/api/common/**").hasAnyRole("THIRD_COMMON", "THIRD_ADMIN") .antMatchers("/api/consume/**").hasRole("THIRD_CONSUME") .antMatchers("/api/deposit/**").hasRole("THIRD_DEPOSIT") -- 2.17.1