xubh 5 年 前
コミット
88847d85c3

ファイルの差分が大きいため隠しています
+ 42 - 0
src/main/java/com/minpay/common/constant/PayOSConstant.java


+ 234 - 0
src/main/java/com/minpay/common/pay/bean/PrePay.java

@@ -0,0 +1,234 @@
+package com.minpay.common.pay.bean;
+
+public class PrePay  {
+    /** M 外部交易号。由合作方系统生成,只能包含字母、数字、下划线;需保证合作方系统不重复。*/
+    private String				OutTradeNo;
+    /** M 商品描述。该信息将透传至第三方支付公司系统,并在客户端明细中展示。格式要求:店名-销售商品类目*/
+    private String				Body;
+    /** M 交易总额度。货币最小单位,人民币:分*/
+    private String				TotalAmount;
+    /** M 币种。默认CNY。*/
+    private String				Currency;
+    /** M 商户号。为商户分配的商户号,通过商户入驻结果查询接口获取。*/
+    private String				HlMerchantId;
+    /** M 合作方机构号*/
+    private String				IsvOrgId;
+    /**	M 渠道类型。01:网商 02:随行付 08:汇付天下 09:合利宝*/
+    private String				ProviderType;
+    /** M 签名规则。01:机构,02:商户自身*/
+    private String				RsaType;
+    /** M支付渠道类型。该笔支付走的第三方支付渠道。可选值: WX:微信支付 ALI:支付宝 QPASS:云闪付 QQ:手机QQ(暂未开放) JD:京东钱包(暂未开放*/
+    private String				ChannelType;
+    /** M 消费者用户标识。 备注:1.支付宝支付时,要求上送用户在支付宝唯一用户号user_id,获取流程请参考: 2.微信支付时,要求上送用户在合作方subAppid下唯一标识openid,获取流程请参考: https://open.huilianpay.com/output/openId?redirectUrl=http://www.baidu.com&attach=test*/
+    private String				OpenId;
+    /**终端设备号。门店收银设备ID*/
+    private String				DeviceId;
+    /**订单有效期。指定订单的支付有效时间(以分钟计算),超过有效时间用户将无法支付。若不指定该参数则系统默认设置1小时支付有效时间。参数允许设置范围:1-1440区间的整数值,超过范围报错。*/
+    private String				ExpireExpress;
+    /** M 清算方式。可选值: T0:T+0清算按笔清算,目前仅之前清算到余利宝,不支持清算到银行卡。 T1:T+1汇总清算,可支持清算到余利宝及清算到银行卡。*/
+    private String				SettleType;
+    /**附加信息,原样返回。 */
+    private String				Attach;
+    /**支付异步通知回调地址。通知url必须为直接可访问的url,不能携带参数,支持Post。 */
+    private String				NotifyUrl;
+    /**	商户微信支付时需要指定的微信支付公众号appid。 SubAppId与SubOpenId一一对应, 仅微信渠道传递,用于支付完成获取对应的SubOpenId。 */
+    private String				SubAppId;
+    /** 是否指定微信支付请求的SubMerchId Y:指定 N:不指定 仅微信渠道传递*/
+    private String				SpecifySubMerchId;
+    /** 指定微信支付渠道号,SpecifySubMerchId值为Y时有效, 仅微信渠道传递。*/
+    private String				ChannelId;
+    /** 	微信交易子商户号,SpecifySubMerchId值为Y时有效, 仅微信渠道传递。*/
+    private String				SubMerchId;
+    /** 禁用支付方式。商户禁受理支付方式列表,多个用逗号隔开。可选值: credit:信用卡 pcredit:花呗(仅支付宝)*/
+    private String				PayLimit;
+    /** 	花呗交易分期数,可选值: 3:3期 6:6期 12:12期 每期间隔为一个月。例如,选择3期,所垫付的资金及利息按3个月等额本息还款,每月还款一笔。 该字段2017年9月30日提供线上服务。*/
+    private String				CheckLaterNm;
+    /** 仅微信渠道有效,APPID类型,微信小程序支付时必送,不送则默认为公众号,支持以下枚举值: SUBSCRIPTION: 公众号 MINI_PROGRAM: 小程序*/
+    private String				SubAppIdType;
+    /** 分账规则串*/
+    private String				SplitBunch;
+
+    public String getOutTradeNo() {
+        return OutTradeNo;
+    }
+
+    public void setOutTradeNo(String outTradeNo) {
+        OutTradeNo = outTradeNo;
+    }
+
+    public String getBody() {
+        return Body;
+    }
+
+    public void setBody(String body) {
+        Body = body;
+    }
+
+    public String getTotalAmount() {
+        return TotalAmount;
+    }
+
+    public void setTotalAmount(String totalAmount) {
+        TotalAmount = totalAmount;
+    }
+
+    public String getCurrency() {
+        return Currency;
+    }
+
+    public void setCurrency(String currency) {
+        Currency = currency;
+    }
+
+    public String getHlMerchantId() {
+        return HlMerchantId;
+    }
+
+    public void setHlMerchantId(String hlMerchantId) {
+        HlMerchantId = hlMerchantId;
+    }
+
+    public String getIsvOrgId() {
+        return IsvOrgId;
+    }
+
+    public void setIsvOrgId(String isvOrgId) {
+        IsvOrgId = isvOrgId;
+    }
+
+    public String getProviderType() {
+        return ProviderType;
+    }
+
+    public void setProviderType(String providerType) {
+        ProviderType = providerType;
+    }
+
+    public String getRsaType() {
+        return RsaType;
+    }
+
+    public void setRsaType(String rsaType) {
+        RsaType = rsaType;
+    }
+
+    public String getChannelType() {
+        return ChannelType;
+    }
+
+    public void setChannelType(String channelType) {
+        ChannelType = channelType;
+    }
+
+    public String getOpenId() {
+        return OpenId;
+    }
+
+    public void setOpenId(String openId) {
+        OpenId = openId;
+    }
+
+    public String getDeviceId() {
+        return DeviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        DeviceId = deviceId;
+    }
+
+    public String getExpireExpress() {
+        return ExpireExpress;
+    }
+
+    public void setExpireExpress(String expireExpress) {
+        ExpireExpress = expireExpress;
+    }
+
+    public String getSettleType() {
+        return SettleType;
+    }
+
+    public void setSettleType(String settleType) {
+        SettleType = settleType;
+    }
+
+    public String getAttach() {
+        return Attach;
+    }
+
+    public void setAttach(String attach) {
+        Attach = attach;
+    }
+
+    public String getNotifyUrl() {
+        return NotifyUrl;
+    }
+
+    public void setNotifyUrl(String notifyUrl) {
+        NotifyUrl = notifyUrl;
+    }
+
+    public String getSubAppId() {
+        return SubAppId;
+    }
+
+    public void setSubAppId(String subAppId) {
+        SubAppId = subAppId;
+    }
+
+    public String getSpecifySubMerchId() {
+        return SpecifySubMerchId;
+    }
+
+    public void setSpecifySubMerchId(String specifySubMerchId) {
+        SpecifySubMerchId = specifySubMerchId;
+    }
+
+    public String getChannelId() {
+        return ChannelId;
+    }
+
+    public void setChannelId(String channelId) {
+        ChannelId = channelId;
+    }
+
+    public String getSubMerchId() {
+        return SubMerchId;
+    }
+
+    public void setSubMerchId(String subMerchId) {
+        SubMerchId = subMerchId;
+    }
+
+    public String getPayLimit() {
+        return PayLimit;
+    }
+
+    public void setPayLimit(String payLimit) {
+        PayLimit = payLimit;
+    }
+
+    public String getCheckLaterNm() {
+        return CheckLaterNm;
+    }
+
+    public void setCheckLaterNm(String checkLaterNm) {
+        CheckLaterNm = checkLaterNm;
+    }
+
+    public String getSubAppIdType() {
+        return SubAppIdType;
+    }
+
+    public void setSubAppIdType(String subAppIdType) {
+        SubAppIdType = subAppIdType;
+    }
+
+    public String getSplitBunch() {
+        return SplitBunch;
+    }
+
+    public void setSplitBunch(String splitBunch) {
+        SplitBunch = splitBunch;
+    }
+}

+ 5 - 0
src/main/java/com/minpay/common/pay/bean/Register.java

@@ -0,0 +1,5 @@
+package com.minpay.common.pay.bean;
+
+public class Register {
+
+}

+ 20 - 0
src/main/java/com/minpay/common/service/IPayOsService.java

@@ -0,0 +1,20 @@
+package com.minpay.common.service;
+
+import com.minpay.common.pay.bean.PrePay;
+import com.minpay.common.pay.bean.Register;
+import com.startup.minpay.frame.core.IMINInitializer;
+import com.startup.minpay.frame.exception.MINBusinessException;
+import com.startup.minpay.frame.service.base.IMINLocalService;
+import com.startup.minpay.frame.session.MINSession;
+
+public interface IPayOsService extends IMINLocalService{
+	/**
+	 * 支付
+	 * @param prePay
+	 * @return
+	 * @throws MINBusinessException
+	 */
+	public String prePay(PrePay prePay) throws MINBusinessException;
+
+	public String register(Register register) throws MINBusinessException;
+}

+ 70 - 0
src/main/java/com/minpay/common/service/impl/PayOsServiceImpl.java

@@ -0,0 +1,70 @@
+package com.minpay.common.service.impl;
+
+import com.minpay.common.constant.PayOSConstant;
+import com.minpay.common.pay.bean.PrePay;
+import com.minpay.common.pay.bean.Register;
+import com.minpay.common.service.IPayOsService;
+import com.minpay.common.util.HttpPostUtil;
+import com.minpay.common.util.XMLTools;
+import com.startup.minpay.frame.exception.MINBusinessException;
+import com.startup.minpay.frame.target.MINComponent;
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 订单服务
+ * @author xubh
+ */
+@MINComponent
+public class PayOsServiceImpl implements IPayOsService {
+
+	static Logger logger = Logger.getLogger(PayOsServiceImpl.class);
+	@Override
+	public String prePay(PrePay prePay) throws MINBusinessException {
+
+		Map<String,Object> map = convertToMap(prePay);
+		String xml = XMLTools.generaterXMLString(PayOSConstant.PREPAY ,map, PrePay.class);
+		logger.log(Level.INFO, "支付请求报文内容:" + xml);
+		String result = HttpPostUtil.sendPost(PayOSConstant.PAY_URL, xml);
+		logger.log(Level.INFO, "支付接口请求返回结果:" + result);
+		return result;
+
+	}
+
+	@Override
+	public String register(Register register) throws MINBusinessException {
+		Map<String,Object> map = convertToMap(register);
+		String xml = XMLTools.generaterXMLString(PayOSConstant.PREPAY ,map, PrePay.class);
+		logger.log(Level.INFO, "支付请求报文内容:" + xml);
+		String result = HttpPostUtil.sendPost(PayOSConstant.PAY_URL, xml);
+		logger.log(Level.INFO, "支付接口请求返回结果:" + result);
+		return result;
+	}
+
+
+	/**map转xml*/
+	public static Map<String, Object> convertToMap(Object obj) {
+		try {
+			if (obj instanceof Map) {
+				return (Map)obj;
+			}
+			Map<String, Object> returnMap = BeanUtils.describe(obj);
+			returnMap.remove("class");
+			return returnMap;
+		} catch (IllegalAccessException e1) {
+			e1.getMessage();
+		} catch (InvocationTargetException e2) {
+			e2.getMessage();
+		} catch (NoSuchMethodException e3) {
+			e3.getMessage();
+		}
+		return new HashMap();
+	}
+
+}

+ 178 - 0
src/main/java/com/minpay/common/util/XMLTools.java

@@ -0,0 +1,178 @@
+package com.minpay.common.util;
+
+import com.minpay.common.constant.PayOSConstant;
+import com.minpay.common.service.IPublicService;
+import com.startup.minpay.frame.exception.MINBusinessException;
+import com.startup.minpay.frame.service.base.Service;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+
+
+
+/**
+ * 报文xml工具类
+ * ClassName: XMLTools 
+ * @author xubh
+ * @date 2017年9月7日
+ */
+public class XMLTools {
+
+
+
+	/**
+	 * 组装head
+	 * @param @param 调用的方法
+	 * @param @return
+	 * @return String
+	 * @throws
+	 * @author xubh
+	 * @date 2020年9月7日
+	 */
+	public static StringBuffer getXMLHeader(String function) throws MINBusinessException {
+		String version = PayOSConstant.IS_FORMAL ? PayOSConstant.VERSION : PayOSConstant.LTVERSION;
+		String appid = PayOSConstant.APPID;
+		String sendDate = DateUtil.getCurrentDateTimeString();
+		String inputCharset = "UTF-8";
+		String signType = "RSA";
+		String channelCode = "01";
+		String dlId = Service.lookup(IPublicService.class).getSequence("PAY_OS_ID");
+		String sysId = sendDate.concat(dlId);
+		return new StringBuffer("<head>"
+				+ "<Version>"+version+"</Version>"
+				+ "<Appid>"+appid+"</Appid>"
+				+ "<Function>"+function+"</Function>"
+				+ "<ReqTime>"+sendDate+"</ReqTime>"
+				+ "<ReqTimeZone></ReqTimeZone>"
+				+ "<ReqMsgId>"+sysId+"</ReqMsgId>"
+				+ "<InputCharset>"+inputCharset+"</InputCharset>"
+				/*+ "<ProviderType>"+channelCode+"</ProviderType>"*/
+				+ "</head>");
+	}
+
+	/**
+	 * 组装body
+	 * @param <T>
+	 * @param @param params
+	 * @param @param cla
+	 * @param @return   
+	 * @return String  
+	 * @throws
+	 * @author xubh
+	 * @date 2018年12月12日
+	 */
+	public static <T> StringBuffer getXMLBodyByMap(Map<String, Object> params, Class<T> cla, String nodeName) {
+		StringBuffer body = new StringBuffer("");
+		body.append("<"+nodeName+">");
+		if(params!=null) {
+			Field[] fields = cla.getDeclaredFields();
+			for(Field f : fields){
+				String fieldName = f.getName();
+				String value = params.get(fieldName)!=null?params.get(fieldName).toString():"";
+				body.append("<" + fieldName + ">" + value.replace("-", "") + "</" + fieldName + ">");
+			}
+		}
+		body.append("</"+nodeName+">");
+		return body;
+	}
+	
+	/**
+	 * 组装body
+	 * @param <T>
+	 * @param @param params
+	 * @param @param cla
+	 * @param @return   
+	 * @return String  
+	 * @throws
+	 * @author xubh
+	 * @date 2018年12月12日
+	 */
+	public static <T> StringBuffer getXMLBodyByMapByLowerCase(Map<String, Object> params, Class<T> cla, String nodeName) {
+		StringBuffer body = new StringBuffer("");
+		if(params!=null) {
+			body.append("<"+nodeName+">");
+			Field[] fields = cla.getDeclaredFields();
+			for(Field f : fields){
+				String fieldName = f.getName().toLowerCase();
+				String value = params.get(fieldName)!=null?params.get(fieldName).toString():"";
+				body.append("<" + fieldName + ">" + value.replace("-", "") + "</" + fieldName + ">");
+			}
+			body.append("</"+nodeName+">");
+		}
+		
+		return body;
+	}
+
+
+	/**
+	 * 生成报文
+	 * @Description: TODO
+	 * @param @param code	接口编码
+	 * @param @param params	接口数据
+	 * @param @param cla	接口属性描述
+	 * @param @return
+	 * @return String  		xml报文
+	 * @throws
+	 * @author xubh
+	 * @date 2018年12月12日
+	 */
+	@SuppressWarnings("unchecked")
+	public static String generaterXMLString(String code, Map<String, Object> params, @SuppressWarnings("rawtypes") Class cla) throws MINBusinessException {
+		StringBuffer xmlHeader = XMLTools.getXMLHeader(code);
+		StringBuffer xmlBody = XMLTools.getXMLBodyByMap(params, cla, "body");
+		String signature = XMLTools.getXmlSignature();
+
+		return getXmlContent(xmlHeader, xmlBody,signature);
+	}
+
+
+	/**
+	 * 组装xml
+	 * @param @param head
+	 * @param @param body
+	 * @param @return
+	 * @return String
+	 * @throws Exception
+	 * @throws
+	 * @author xubh
+	 * @date 2018年12月12日
+	 */
+	public static String getXmlContent(StringBuffer head, StringBuffer body,String signature) {
+		StringBuffer xml = new StringBuffer("<document> <request id=\"request\">");
+		StringBuffer headBuffer = new StringBuffer("").append(head).append(body);
+		String signstr = "";
+		headBuffer.append("</request>");
+		headBuffer.append(signature);
+		headBuffer.append("<document>");
+		return xml.toString();
+	}
+
+	public static String getXmlSignature() {
+		String publicKey= PayOSConstant.MY_PUBLIC_KEY;
+
+
+		String str = "<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">"
+		+"<ds:SignedInfo>"
+				+"<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"></ds:CanonicalizationMethod>"
+				+"<ds:SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\"></ds:SignatureMethod>"
+				+"<ds:Reference URI=\"\"><ds:Transforms>"
+				+"<ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"></ds:Transform>"
+		+"</ds:Transforms>"
+				+"<ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></ds:DigestMethod>"
+		+"<ds:DigestValue>X9Q7Xg02nBUcJ3vOTzDnaFNbxN4=</ds:DigestValue>"
+				+"</ds:Reference>"
+				+"</ds:SignedInfo>"
+				+"<ds:SignatureValue>"+publicKey+
+				"</ds:SignatureValue>"
+						+"</ds:Signature>";
+
+		return str;
+	}
+}