diff --git a/.gitignore b/.gitignore index b40fb55..4ed83a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +<<<<<<< HEAD # Compiled class file *.class @@ -22,3 +23,7 @@ .idea # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +target/ +.idea/ +*.iml + diff --git a/README.md b/README.md index c5d602a..2675b6f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -全能第三方支付对接Java开发工具包.优雅的轻量级支付模块集成支付对接支付整合(微信,支付宝,银联,友店,富友,跨境支付paypal,payoneer(P卡派安盈)易极付)app,扫码,网页支付刷卡付条码付刷脸付转账服务商模式、支持多种支付类型多支付账户,支付与业务完全剥离,简单几行代码即可实现支付,简单快速完成支付模块的开发,可轻松嵌入到任何系统里 目前仅是一个开发工具包(即SDK),只提供简单Web实现,建议使用maven或gradle引用本项目即可使用本SDK提供的各种支付相关的功能 +全能第三方支付对接Java开发工具包.优雅的轻量级支付模块集成支付对接支付整合(微信,支付宝,银联,友店,富友,跨境支付paypal,payoneer(P卡派安盈)易极付)app,扫码,网页支付刷卡付条码付刷脸付转账红包服务商模式、支持多种支付类型多支付账户,支付与业务完全剥离,简单几行代码即可实现支付,简单快速完成支付模块的开发,可轻松嵌入到任何系统里 目前仅是一个开发工具包(即SDK),只提供简单Web实现,建议使用maven或gradle引用本项目即可使用本SDK提供的各种支付相关的功能 ### 特性 diff --git a/pay-java-ali/README.md b/pay-java-ali/README.md index bebaa86..e7a2f5e 100644 --- a/pay-java-ali/README.md +++ b/pay-java-ali/README.md @@ -113,6 +113,18 @@ Map appOrderInfo = service.orderInfo(payOrder); /*-----------/APP-------------------*/ +``` +#### 小程序支付 + +```java + + /*-----------APP-------------------*/ + payOrder.setTransactionType(AliTransactionType.MINAPP); + payOrder.setOpenid("支付宝小程序授权登录成功后获取到的支付宝 user_id") + //获取小程序支付所需的信息组,直接给小程序网页端就可使用 + Map appOrderInfo = service.orderInfo(payOrder); + /*-----------/APP-------------------*/ + ``` #### 即时到帐 WAP 网页支付 diff --git a/pay-java-ali/pom.xml b/pay-java-ali/pom.xml index 229ac85..d909904 100644 --- a/pay-java-ali/pom.xml +++ b/pay-java-ali/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 pay-java-ali diff --git a/pay-java-ali/src/main/java/com/egzosn/pay/ali/api/AliPayService.java b/pay-java-ali/src/main/java/com/egzosn/pay/ali/api/AliPayService.java index b9685c8..9b7aa7d 100644 --- a/pay-java-ali/src/main/java/com/egzosn/pay/ali/api/AliPayService.java +++ b/pay-java-ali/src/main/java/com/egzosn/pay/ali/api/AliPayService.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.egzosn.pay.ali.bean.AliPayMessage; import com.egzosn.pay.ali.bean.AliTransactionType; +import com.egzosn.pay.ali.bean.AliTransferType; import com.egzosn.pay.ali.bean.OrderSettle; import com.egzosn.pay.common.api.BasePayService; import com.egzosn.pay.common.bean.*; @@ -15,7 +16,7 @@ import com.egzosn.pay.common.util.DateUtils; import com.egzosn.pay.common.util.Util; import com.egzosn.pay.common.util.sign.SignUtils; import com.egzosn.pay.common.util.str.StringUtils; -import java.math.BigDecimal; + import java.util.*; /** @@ -36,29 +37,37 @@ public class AliPayService extends BasePayService { * 沙箱测试环境账号 */ private static final String DEV_REQ_URL = "https://openapi.alipaydev.com/gateway.do"; - - public static final String SIGN = "sign"; - - public static final String SUCCESS_CODE = "10000"; - - public static final String CODE = "code"; + + private static final String SIGN = "sign"; + + private static final String SUCCESS_CODE = "10000"; + + private static final String CODE = "code"; /** * 附加参数 */ - public static final String PASSBACK_PARAMS = "passback_params"; + private static final String PASSBACK_PARAMS = "passback_params"; /** * 产品代码 */ - public static final String PRODUCT_CODE = "product_code"; + private static final String PRODUCT_CODE = "product_code"; /** * 返回地址 */ - public static final String RETURN_URL = "return_url"; + private static final String RETURN_URL = "return_url"; /** * 请求内容 */ - public static final String BIZ_CONTENT = "biz_content"; + private static final String BIZ_CONTENT = "biz_content"; + /** + * 应用授权概述 + */ + private static final String APP_AUTH_TOKEN = "app_auth_token"; + /** + * 收款方信息 + */ + private static final String PAYEE_INFO = "payee_info"; /** * 获取对应的请求地址 @@ -190,7 +199,7 @@ public class AliPayService extends BasePayService { orderInfo.put("notify_url", payConfigStorage.getNotifyUrl()); orderInfo.put("format", "json"); - + setAppAuthToken(orderInfo, order.getAttrs()); Map bizContent = new TreeMap<>(); bizContent.put("body", order.getBody()); @@ -213,6 +222,11 @@ public class AliPayService extends BasePayService { bizContent.put(PASSBACK_PARAMS, order.getAddition()); bizContent.put(PRODUCT_CODE, "QUICK_MSECURITY_PAY"); break; + case MINAPP: + bizContent.put("extend_params", order.getAddition()); + bizContent.put("buyer_id", order.getOpenid()); + bizContent.put(PRODUCT_CODE, "FACE_TO_FACE_PAYMENT"); + break; case BAR_CODE: case WAVE_CODE: case SECURITY_CODE: @@ -223,10 +237,10 @@ public class AliPayService extends BasePayService { } if (null != order.getExpirationTime()) { - bizContent.put("timeout_express", DateUtils.minutesRemaining(order.getExpirationTime()) + "m"); + bizContent.put(order.getTransactionType() == AliTransactionType.SWEEPPAY ? "qr_code_timeout_express" : "timeout_express", DateUtils.minutesRemaining(order.getExpirationTime()) + "m"); } + bizContent.putAll(order.getAttrs()); orderInfo.put(BIZ_CONTENT, JSON.toJSONString(bizContent)); - orderInfo.putAll(order.getAttr()); return preOrderHandler(orderInfo, order); } @@ -355,7 +369,10 @@ public class AliPayService extends BasePayService { public Map settle(OrderSettle order){ //获取公共参数 Map parameters = getPublicParameters(AliTransactionType.SETTLE); - parameters.put(BIZ_CONTENT, JSON.toJSONString(order.toBizContent())); + setAppAuthToken(parameters, order.getAttrs()); + final Map bizContent = order.toBizContent(); + bizContent.putAll(order.getAttrs()); + parameters.put(BIZ_CONTENT, JSON.toJSONString(bizContent)); //设置签名 setSign(parameters); return getHttpRequestTemplate().postForObject(getReqUrl() + "?" + UriVariables.getMapToParameters(parameters), null, JSONObject.class); @@ -403,21 +420,13 @@ public class AliPayService extends BasePayService { } /** - * 申请退款接口 - * 废弃 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @return 返回支付方申请退款后的结果 - * @see #refund(RefundOrder, com.egzosn.pay.common.api.Callback) - * @deprecated 版本替代 {@link #refund(RefundOrder, com.egzosn.pay.common.api.Callback)} + * 设置支付宝授权Token + * @param parameters 参数 + * @param attrs 订单属性 + * @return 参数 */ - @Deprecated - @Override - public Map refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) { - return refund(new RefundOrder(tradeNo, outTradeNo, refundAmount, totalAmount)); + private void setAppAuthToken(Map parameters, Map attrs) { + setParameters(parameters, APP_AUTH_TOKEN, (String) attrs.remove(APP_AUTH_TOKEN)); } @@ -431,12 +440,13 @@ public class AliPayService extends BasePayService { public Map refund(RefundOrder refundOrder) { //获取公共参数 Map parameters = getPublicParameters(AliTransactionType.REFUND); - + setAppAuthToken(parameters, refundOrder.getAttrs()); Map bizContent = getBizContent(refundOrder.getTradeNo(), refundOrder.getOutTradeNo(), null); if (!StringUtils.isEmpty(refundOrder.getRefundNo())) { bizContent.put("out_request_no", refundOrder.getRefundNo()); } bizContent.put("refund_amount", Util.conversionAmount(refundOrder.getRefundAmount())); + bizContent.putAll(refundOrder.getAttrs()); //设置请求参数的集合 parameters.put(BIZ_CONTENT, JSON.toJSONString(bizContent)); //设置签名 @@ -444,17 +454,7 @@ public class AliPayService extends BasePayService { return requestTemplate.getForObject(getReqUrl() + "?" + UriVariables.getMapToParameters(parameters), JSONObject.class); } - /** - * 查询退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @return 返回支付方查询退款后的结果 - */ - @Override - public Map refundquery(String tradeNo, String outTradeNo) { - return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.REFUNDQUERY); - } + /** * 查询退款 @@ -464,17 +464,16 @@ public class AliPayService extends BasePayService { */ @Override public Map refundquery(RefundOrder refundOrder) { - //获取公共参数 Map parameters = getPublicParameters(AliTransactionType.REFUNDQUERY); - + setAppAuthToken(parameters, refundOrder.getAttrs()); Map bizContent = getBizContent(refundOrder.getTradeNo(), refundOrder.getOutTradeNo(), null); if (!StringUtils.isEmpty(refundOrder.getRefundNo())) { bizContent.put("out_request_no", refundOrder.getRefundNo()); } + bizContent.putAll(refundOrder.getAttrs()); //设置请求参数的集合 parameters.put(BIZ_CONTENT, JSON.toJSONString(bizContent)); - //设置签名 setSign(parameters); return requestTemplate.getForObject(getReqUrl() + "?" + UriVariables.getMapToParameters(parameters), JSONObject.class); @@ -505,6 +504,7 @@ public class AliPayService extends BasePayService { } + /** * @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请 * 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException} @@ -512,6 +512,7 @@ public class AliPayService extends BasePayService { * @param transactionType 交易类型 * @return 返回支付方对应接口的结果 */ + @Override public Map secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType) { @@ -528,36 +529,38 @@ public class AliPayService extends BasePayService { //获取公共参数 Map parameters = getPublicParameters(transactionType); + //设置请求参数的集合 parameters.put(BIZ_CONTENT, getContentToJson((String) tradeNoOrBillDate, outTradeNoBillType)); //设置签名 setSign(parameters); + return requestTemplate.getForObject(getReqUrl() + "?" + UriVariables.getMapToParameters(parameters), JSONObject.class); } /** - * 转账 + * 新版转账转账 * * @param order 转账订单 * @return 对应的转账结果 */ @Override public Map transfer(TransferOrder order) { + final TransferType transferType = order.getTransferType(); //获取公共参数 - Map parameters = getPublicParameters(AliTransactionType.TRANS); + Map parameters = getPublicParameters(transferType); + setAppAuthToken(parameters, order.getAttrs()); - Map bizContent = new TreeMap(); + Map bizContent = new LinkedHashMap(); bizContent.put("out_biz_no", order.getOutNo()); - //默认 支付宝登录号,支持邮箱和手机号格式。 - bizContent.put("payee_type", "ALIPAY_LOGONID"); - if (null != order.getTransferType()) { - bizContent.put("payee_type", order.getTransferType().getType()); - } - bizContent.put("payee_account", order.getPayeeAccount()); - bizContent.put("amount", Util.conversionAmount(order.getAmount())); - bizContent.put("payer_show_name", order.getPayerName()); - bizContent.put("payee_real_name", order.getPayeeName()); + bizContent.put("trans_amount", order.getAmount()); + transferType.setAttr(bizContent, order); + setParameters(bizContent, "order_title", order); + setParameters(bizContent, "original_order_id", order); + setPayeeInfo(bizContent, order); bizContent.put("remark", order.getRemark()); + setParameters(bizContent, "business_params", order); + //设置请求参数的集合 parameters.put(BIZ_CONTENT, JSON.toJSONString(bizContent)); //设置签名 @@ -565,6 +568,24 @@ public class AliPayService extends BasePayService { return getHttpRequestTemplate().postForObject(getReqUrl() + "?" + UriVariables.getMapToParameters(parameters), null, JSONObject.class); } + private Map setPayeeInfo(Map bizContent, Order order){ + final Object attr = order.getAttr(PAYEE_INFO); + + if (attr instanceof String){ + bizContent.put(PAYEE_INFO, attr); + } + if (attr instanceof TreeMap){ + bizContent.put(PAYEE_INFO, attr); + } + if (attr instanceof Map){ + Map payeeInfo = new TreeMap((Map)attr); + bizContent.put(PAYEE_INFO, payeeInfo); + } + return bizContent; + } + + + /** * 转账查询 * @@ -575,7 +596,7 @@ public class AliPayService extends BasePayService { @Override public Map transferQuery(String outNo, String tradeNo) { //获取公共参数 - Map parameters = getPublicParameters(AliTransactionType.TRANS_QUERY); + Map parameters = getPublicParameters(AliTransferType.TRANS_QUERY); Map bizContent = new TreeMap(); if (StringUtils.isEmpty(outNo)) { diff --git a/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransactionType.java b/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransactionType.java index bb722de..13e4f12 100644 --- a/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransactionType.java +++ b/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransactionType.java @@ -44,6 +44,10 @@ public enum AliTransactionType implements TransactionType { * 声波付 */ WAVE_CODE("alipay.trade.pay"), + /** + * 小程序 + */ + MINAPP("alipay.trade.create"), /** * 刷脸付 */ @@ -84,14 +88,6 @@ public enum AliTransactionType implements TransactionType { * 下载对账单 */ DOWNLOADBILL("alipay.data.dataservice.bill.downloadurl.query"), - /** - * 转账到支付宝 - */ - TRANS("alipay.fund.trans.toaccount.transfer"), - /** - * 转账查询 - */ - TRANS_QUERY("alipay.fund.trans.order.query"), /** * 查询刷脸结果信息 * 暂时未接入 diff --git a/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransferOrder.java b/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransferOrder.java new file mode 100644 index 0000000..31c26e3 --- /dev/null +++ b/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransferOrder.java @@ -0,0 +1,153 @@ +package com.egzosn.pay.ali.bean; + +import com.egzosn.pay.common.bean.TransferOrder; + +import java.math.BigDecimal; +import java.util.TreeMap; + +/** + * 支付转账(红包)订单 + * + * @author egan + * date 2020/5/18 21:08 + * email egzosn@gmail.com + */ +public class AliTransferOrder extends TransferOrder { + + private String identity; + private String identityType; + + /** + * 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。 + * + * @return 商户端的唯一订单号 + */ + public String getOutBizNo() { + return getOutNo(); + } + + public void setOutBizNo(String outBizNo) { + setOutNo(outBizNo); + } + + /** + * 订单总金额,单位为元,精确到小数点后两位,STD_RED_PACKET产品取值范围[0.01,100000000]; + * TRANS_ACCOUNT_NO_PWD产品取值范围[0.1,100000000] + * + * @return 订单总金额 + */ + public BigDecimal getTransAmount() { + return getAmount(); + } + + public void setTransAmount(BigDecimal transAmount) { + setAmount(transAmount); + } + + /** + * 转账业务的标题,用于在支付宝用户的账单里显示 + * + * @return 转账业务的标题 + */ + public String getOrderTitle() { + return (String) getAttr("order_title"); + } + + public void setOrderTitle(String orderTitle) { + addAttr("order_title", orderTitle); + } + + /** + * 描述特定的业务场景,可传的参数如下: + * DIRECT_TRANSFER:单笔无密转账到支付宝/银行卡, B2C现金红包; + * PERSONAL_COLLECTION:C2C现金红包-领红包 + * + * @return 描述特定的业务场景 + */ + public String getBizScene() { + return (String) getAttr("biz_scene"); + } + + public void setBizScene(String bizScene) { + addAttr("biz_scene", bizScene); + } + + /** + * 收款方信息 + * + * @return 收款方信息 + */ + private TreeMap getPayeeinfo() { + Object payeeInfo = getAttr("payee_info"); + if (null != payeeInfo && payeeInfo instanceof TreeMap){ + return (TreeMap) payeeInfo; + } + TreeMap payee = new TreeMap<>(); + addAttr("payee_info", payee); + return payee; + + } + + /** + * 参与方的唯一标识 + * + * @return 参与方的唯一标识 + */ + public String getIdentity() { + return identity; + } + + public void setIdentity(String identity) { + this.identity = identity; + getPayeeinfo().put("identity", identity); + } + + /** + * 参与方的标识类型,目前支持如下类型: + * 1、ALIPAY_USER_ID 支付宝的会员ID + * 2、ALIPAY_LOGON_ID:支付宝登录号,支持邮箱和手机号格式 + * + * @return 参与方的标识类型 + */ + public String getIdentityType() { + return identityType; + } + + public void setIdentityType(String identityType) { + this.identityType = identityType; + getPayeeinfo().put("identity_type", identityType); + } + + + /** + * 参与方真实姓名 + * + * @return 参与方真实姓名 + */ + public String getName() { + return getPayeeName(); + } + + public void setName(String name) { + setPayeeName(name); + getPayeeinfo().put("name", name); + } + + /** + * 转账业务请求的扩展参数,支持传入的扩展参数如下: + * 1、sub_biz_scene 子业务场景,红包业务必传,取值REDPACKET,C2C现金红包、B2C现金红包均需传入; + *

+ * 2、withdraw_timeliness为转账到银行卡的预期到账时间,可选(不传入则默认为T1),取值T0表示预期T+0到账,取值T1表示预期T+1到账,因到账时效受银行机构处理影响,支付宝无法保证一定是T0或者T1到账; + * + * @return 转账业务请求的扩展参数 + */ + public String getBusinessParams() { + return (String) getAttr("business_params"); + } + + public void setBusinessParams(String businessParams) { + addAttr("business_params", businessParams); + } + + +} diff --git a/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransferType.java b/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransferType.java index 9f35aec..df10e73 100644 --- a/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransferType.java +++ b/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/AliTransferType.java @@ -1,26 +1,69 @@ package com.egzosn.pay.ali.bean; +import com.egzosn.pay.common.bean.TransferOrder; import com.egzosn.pay.common.bean.TransferType; +import java.util.Map; + /** - * 收款方账户类型 + * 收款方账户类型 + * * @author egan - * email egzosn@gmail.com - * date 2018/9/28.20:32 + * email egzosn@gmail.com + * date 2018/9/28.20:32 */ public enum AliTransferType implements TransferType { /** - * 支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成。 + * 单笔无密转账到支付宝账户固定为 */ - ALIPAY_USERID, + TRANS_ACCOUNT_NO_PWD("alipay.fund.trans.uni.transfer", "DIRECT_TRANSFER"), /** - * 支付宝登录号,支持邮箱和手机号格式。 + * 单笔无密转账到银行卡固定为 */ - ALIPAY_LOGONID - ; + TRANS_BANKCARD_NO_PWD("alipay.fund.trans.uni.transfer", "DIRECT_TRANSFER"), + /** + * 收发现金红包固定为 + */ + STD_RED_PACKET("alipay.fund.trans.uni.transfer", "DIRECT_TRANSFER"), + /** + * 现金红包无线支付接口 + */ + STD_RED_PACKET_APP("alipay.fund.trans.app.pay", "PERSONAL_PAY") { + /** + * 获取转账类型 + * + * @return 转账类型 + */ + @Override + public String getType() { + return STD_RED_PACKET.name(); + } + }, /** - * 获取转账类型 + * 转账查询 + */ + TRANS_QUERY("alipay.fund.trans.order.query"); + /** + * 接口名称 + */ + private String method; + /** + * 业务场景 + */ + private String bizScene; + + AliTransferType(String method) { + this.method = method; + } + + AliTransferType(String method, String bizScene) { + this.method = method; + this.bizScene = bizScene; + } + + /** + * 获取转账类型, product_code 业务产品码 * * @return 转账类型 */ @@ -29,6 +72,10 @@ public enum AliTransferType implements TransferType { return name(); } + public String getBizScene() { + return bizScene; + } + /** * 获取接口 * @@ -36,6 +83,20 @@ public enum AliTransferType implements TransferType { */ @Override public String getMethod() { - return name(); + return method; + } + + /** + * 设置属性 + * + * @param attr 已有属性对象 + * @param order 转账订单 + * @return 属性对象 + */ + @Override + public Map setAttr(Map attr, TransferOrder order) { + attr.put("product_code", getType()); + attr.put("biz_scene", getBizScene()); + return attr; } } diff --git a/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/OrderSettle.java b/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/OrderSettle.java index f4227b9..e111bc1 100644 --- a/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/OrderSettle.java +++ b/pay-java-ali/src/main/java/com/egzosn/pay/ali/bean/OrderSettle.java @@ -1,9 +1,11 @@ package com.egzosn.pay.ali.bean; +import com.egzosn.pay.common.bean.Order; import com.egzosn.pay.common.util.Util; import com.egzosn.pay.common.util.str.StringUtils; import java.math.BigDecimal; +import java.util.HashMap; import java.util.Map; import java.util.TreeMap; @@ -13,7 +15,7 @@ import java.util.TreeMap; * email egzosn@gmail.com * date 2019/4/28.20:29 */ -public class OrderSettle { +public class OrderSettle implements Order { /** * 结算请求流水号 开发者自行生成并保证唯一性 @@ -52,6 +54,11 @@ public class OrderSettle { */ private String operatorId; + /** + * 订单附加信息,可用于预设未提供的参数,这里会覆盖以上所有的订单信息, + */ + private Map attr; + public String getOutRequestNo() { return outRequestNo; } @@ -158,6 +165,28 @@ public class OrderSettle { return bizContent; } + @Override + public Map getAttrs() { + if (null == attr){ + attr = new HashMap<>(); + } + return attr; + } + @Override + public Object getAttr(String key) { + return getAttrs().get(key); + } + + + /** + * 添加订单信息 + * @param key key + * @param value 值 + */ + @Override + public void addAttr(String key, Object value) { + getAttrs().put(key, value); + } } diff --git a/pay-java-baidu/pom.xml b/pay-java-baidu/pom.xml new file mode 100644 index 0000000..9713046 --- /dev/null +++ b/pay-java-baidu/pom.xml @@ -0,0 +1,28 @@ + + + + pay-java-parent + com.egzosn + 2.13.2-SNAPSHOT + + 4.0.0 + pay-java-baidu + + + + + com.egzosn + pay-java-common + + + + org.junit.jupiter + junit-jupiter + test + + + + + \ No newline at end of file diff --git a/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/api/BaiduPayConfigStorage.java b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/api/BaiduPayConfigStorage.java new file mode 100644 index 0000000..f1496e7 --- /dev/null +++ b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/api/BaiduPayConfigStorage.java @@ -0,0 +1,53 @@ +package com.egzosn.pay.baidu.api; + +import com.egzosn.pay.common.api.BasePayConfigStorage; + +public class BaiduPayConfigStorage extends BasePayConfigStorage { + private String appid; + private String dealId; + + @Override + public String getAppid() { + return this.appid; + } + + @Override + public String getPid() { + return getDealId(); + } + + @Override + public String getSeller() { + throw new UnsupportedOperationException("不支持"); + } + + public String getDealId() { + return dealId; + } + + public void setDealId(String dealId) { + this.dealId = dealId; + } + + public String getAppKey() { + return this.getKeyPrivate(); + } + + public void setAppKey(String appKey) { + setKeyPrivate(appKey); + } + + @Override + public String getKeyPublic() { + return super.getKeyPrivate(); + } + + @Override + public void setKeyPublic(String keyPublic) { + super.setKeyPublic(keyPublic); + } + + public void setAppid(String appid) { + this.appid = appid; + } +} diff --git a/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/api/BaiduPayService.java b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/api/BaiduPayService.java new file mode 100644 index 0000000..87e4c1c --- /dev/null +++ b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/api/BaiduPayService.java @@ -0,0 +1,433 @@ +package com.egzosn.pay.baidu.api; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.egzosn.pay.baidu.bean.BaiduPayOrder; +import com.egzosn.pay.baidu.bean.BaiduRefundOrder; +import com.egzosn.pay.baidu.bean.BaiduTransactionType; +import com.egzosn.pay.baidu.bean.type.AuditStatus; +import com.egzosn.pay.baidu.util.Asserts; +import com.egzosn.pay.common.api.BasePayService; +import com.egzosn.pay.common.bean.*; +import com.egzosn.pay.common.http.HttpConfigStorage; +import com.egzosn.pay.common.http.UriVariables; +import com.egzosn.pay.common.util.DateUtils; +import com.egzosn.pay.common.util.Util; +import com.egzosn.pay.common.util.sign.SignUtils; +import com.egzosn.pay.common.util.str.StringUtils; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +public class BaiduPayService extends BasePayService { + public static final String APP_KEY = "appKey"; + public static final String APP_ID = "appId"; + public static final String DEAL_ID = "dealId"; + public static final String TP_ORDER_ID = "tpOrderId"; + public static final String DEAL_TITLE = "dealTitle"; + public static final String TOTAL_AMOUNT = "totalAmount"; + public static final String SIGN_FIELDS_RANGE = "signFieldsRange"; + public static final String BIZ_INFO = "bizInfo"; + public static final String RSA_SIGN = "rsaSign"; + public static final String ORDER_ID = "orderId"; + public static final String USER_ID = "userId"; + public static final String SITE_ID = "siteId"; + public static final String SIGN = "sign"; + public static final String METHOD = "method"; + public static final String TYPE = "type"; + + public static final Integer RESPONSE_SUCCESS = 2; + public static final String RESPONSE_STATUS = "status"; + + + public BaiduPayService(BaiduPayConfigStorage payConfigStorage) { + super(payConfigStorage); + } + + public BaiduPayService(BaiduPayConfigStorage payConfigStorage, + HttpConfigStorage configStorage) { + super(payConfigStorage, configStorage); + } + + /** + * 验证响应 + * + * @param params 回调回来的参数集 + * @return 结果 + */ + @Override + public boolean verify(Map params) { + if (!RESPONSE_SUCCESS.equals(params.get(RESPONSE_STATUS))) { + return false; + } + return signVerify(params, String.valueOf(params.get(RSA_SIGN))) && verifySource(String.valueOf(params.get(TP_ORDER_ID))); + } + + /** + * 验证签名 + * + * @param params 参数集 + * @param sign 签名原文 + * @return 结果 + */ + @Override + public boolean signVerify(Map params, String sign) { + String rsaSign = String.valueOf(params.get(RSA_SIGN)); + String targetRsaSign = getRsaSign(params, RSA_SIGN); + LOG.debug("百度返回的签名: " + rsaSign + " 本地产生的签名: " + targetRsaSign); + return StringUtils.equals(rsaSign, targetRsaSign); + } + + @Override + public boolean verifySource(String id) { + return true; + } + + /** + * 返回创建的订单信息 + * + * @param order 支付订单 + * @return 结果 + */ + @Override + public Map orderInfo(PayOrder order) { + Map params = getUseOrderInfoParams(order); + String rsaSign = getRsaSign(params, RSA_SIGN); + params.put(RSA_SIGN, rsaSign); + return params; + } + + /** + * 获取"查询支付状态"所需参数 + * + * @return 结果 + */ + public Map getUseQueryPay() { + String appKey = payConfigStorage.getAppKey(); + Map result = new HashMap<>(); + result.put(APP_KEY, appKey); + result.put(APP_ID, payConfigStorage.getAppid()); + return result; + } + + /** + * 获取"创建订单"所需参数 + * + * @param order 订单信息 + * @return 结果 + */ + private Map getUseOrderInfoParams(PayOrder order) { + BaiduPayOrder payOrder = (BaiduPayOrder) order; + Map result = new HashMap<>(); + String appKey = payConfigStorage.getAppKey(); + String dealId = payConfigStorage.getDealId(); + result.put(APP_KEY, appKey); + result.put(TP_ORDER_ID, payOrder.getTradeNo()); + result.put(DEAL_ID, dealId); + result.put(DEAL_TITLE, payOrder.getSubject()); + result.put(SIGN_FIELDS_RANGE, payOrder.getSignFieldsRange()); + result.put(BIZ_INFO, JSON.toJSONString(payOrder.getBizInfo())); + result.put(TOTAL_AMOUNT, String.valueOf(Util.conversionAmount(order.getPrice()))); + + return result; + } + + /** + * 获取输出消息,用户返回给支付端 + * + * @param code 状态 + * @param message 消息 + * @return 结果 + */ + @Override + @Deprecated + public PayOutMessage getPayOutMessage(String code, String message) { + throw new UnsupportedOperationException("请使用 " + getClass().getName() + "#getPayOutMessageUseBaidu"); + } + + /** + * 请求业务方退款审核/响应处理 + * http://smartprogram.baidu.com/docs/develop/function/tune_up_examine/ + * + * @param errno 错误代码 + * @param message 消息 + * @param auditStatus 状态 + * @param refundPayMoney 退款金额 + * @return 结果 + */ + public PayOutMessage getApplyRefundOutMessageUseBaidu(Integer errno, + String message, + AuditStatus auditStatus, + BigDecimal refundPayMoney) { + JSONObject data = new JSONObject(); + data.put("auditStatus", auditStatus.getCode()); + JSONObject calculateRes = new JSONObject(); + calculateRes.put("refundPayMoney", refundPayMoney); + data.put("calculateRes", calculateRes); + return PayOutMessage.JSON() + .content("errno", errno) + .content("message", message) + .content("data", data) + .build(); + + } + + /** + * 通知退款状态/响应处理 + * http://smartprogram.baidu.com/docs/develop/function/tune_up_drawback/ + * + * @param errno 错误代码 + * @param message 消息 + * @return 结果 + */ + public PayOutMessage getRefundOutMessageUseBaidu(Integer errno, + String message) { + return PayOutMessage.JSON() + .content("errno", errno) + .content("message", message) + .content("data", "{}") + .build(); + + } + + /** + * 支付通知/响应处理 + * + * @param errno 错误代码 + * @param message 消息 + * @param isConsumed 是否消费 + * @param isErrorOrder 错误订单 + * @return 结果 + */ + public PayOutMessage getPayOutMessageUseBaidu(Integer errno, + String message, + Integer isConsumed, + Integer isErrorOrder) { + Asserts.isNoNull(errno, "errno 是必填的"); + Asserts.isNoNull(message, "message 是必填的"); + Asserts.isNoNull(isConsumed, "isConsumed 是必填的"); + JSONObject data = new JSONObject(); + data.put("isConsumed", isConsumed); + if (isErrorOrder != null) { + data.put("isErrorOrder", isErrorOrder); + } + return PayOutMessage.JSON() + .content("errno", errno) + .content("message", message) + .content("data", data) + .build(); + } + + /** + * 支付通知/响应处理 + * http://smartprogram.baidu.com/docs/develop/function/tune_up_notice/ + * + * @param code 状态码 + * @param message 消息 + * @param isConsumed 是否消费 + * @return 结果 + */ + public PayOutMessage getPayOutMessageUseBaidu(Integer code, + String message, + Integer isConsumed) { + return getPayOutMessageUseBaidu(code, message, isConsumed, null); + } + + /** + * 支付通知/响应处理 + * http://smartprogram.baidu.com/docs/develop/function/tune_up_notice/ + * + * @param payMessage 支付回调消息 + * @return 结果 + */ + @Override + public PayOutMessage successPayOutMessage(PayMessage payMessage) { + return getPayOutMessageUseBaidu(0, "success", 2); + } + + /** + * 获取输出消息,用户返回给支付端, 针对于web端 + * + * @param orderInfo 发起支付的订单信息 + * @param method 请求方式 "post" "get", + * @return 结果 + */ + @Override + public String buildRequest(Map orderInfo, + MethodType method) { + throw new UnsupportedOperationException("百度不支持PC支付"); + } + + + /** + * 百度不支持扫码付 + * + * @param order 发起支付的订单信息 + * @return 结果 + */ + @Override + public String getQrPay(PayOrder order) { + throw new UnsupportedOperationException("百度不支持扫码付"); + } + + /** + * 百度不支持刷卡付 + * + * @param order 发起支付的订单信息 + * @return 结果 + */ + @Override + public Map microPay(PayOrder order) { + throw new UnsupportedOperationException("百度不支持刷卡付"); + } + + /** + * 查询订单 + * + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @return 结果 + */ + @Override + public Map query(String tradeNo, String outTradeNo) { + return secondaryInterface(tradeNo, outTradeNo, BaiduTransactionType.PAY_QUERY); + } + + /** + * 百度不支持该操作 + * + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @return 结果 + */ + @Override + public Map close(String tradeNo, String outTradeNo) { + throw new UnsupportedOperationException("不支持该操作"); + } + + + /** + * 退款 + * + * @param refundOrder 退款订单信息 + * @return 退款结果 + */ + @Override + public Map refund(RefundOrder refundOrder) { + Map parameters = getUseQueryPay(); + BaiduTransactionType transactionType = BaiduTransactionType.APPLY_REFUND; + parameters.put(METHOD, transactionType.getMethod()); + parameters.put(ORDER_ID, refundOrder.getOutTradeNo()); + parameters.put(USER_ID, refundOrder.getUserId()); + setParameters(parameters, "refundType", refundOrder); + parameters.put("refundReason", refundOrder.getDescription()); + parameters.put(TP_ORDER_ID, refundOrder.getTradeNo()); + parameters.put("applyRefundMoney", refundOrder.getRefundAmount()); + parameters.put("bizRefundBatchId", refundOrder.getRefundNo()); + parameters.put(APP_KEY, payConfigStorage.getAppKey()); + parameters.put(RSA_SIGN, getRsaSign(parameters, RSA_SIGN)); + return requestTemplate.getForObject(String.format("%s?%s", getReqUrl(transactionType), UriVariables.getMapToParameters(parameters)), JSONObject.class); + + } + + + /** + * 退费查询 + * + * @param refundOrder 退款订单单号信息 + * @return 退款查询结果 + */ + @Override + public Map refundquery(RefundOrder refundOrder) { + + Map parameters = getUseQueryPay(); + BaiduTransactionType transactionType = BaiduTransactionType.REFUND_QUERY; + parameters.put(METHOD, transactionType.getMethod()); + parameters.put(TYPE, 3); + parameters.put(ORDER_ID, refundOrder.getTradeNo()); + parameters.put(USER_ID, refundOrder.getUserId()); + parameters.put(APP_KEY, payConfigStorage.getAppKey()); + parameters.put(RSA_SIGN, getRsaSign(parameters, RSA_SIGN)); + return requestTemplate.getForObject(String.format("%s?%s", getReqUrl(transactionType), UriVariables.getMapToParameters(parameters)), JSONObject.class); + } + + /** + * 下载资金账单 + * + * @param billDate 账单时间:日账单格式为yyyy-MM-dd + * @param accessToken 用户token + * @return 对账单 + */ + @Override + public Map downloadbill(Date billDate, String accessToken) { + Map parameters = new HashMap<>(); + parameters.put("access_token", accessToken); + parameters.put("billTime", DateUtils.formatDay(billDate)); + return requestTemplate.getForObject(String.format("%s?%s", getReqUrl(BaiduTransactionType.DOWNLOAD_BILL), + UriVariables.getMapToParameters(parameters)), JSONObject.class); + } + + /** + * 下载订单对账单 + * + * @param billDate 账单时间:日账单格式为yyyy-MM-dd + * @param accessToken 用户token + * @return 账单结果 + */ + public Map downloadOrderBill(Date billDate, String accessToken) { + Map parameters = new HashMap<>(); + parameters.put("access_token", accessToken); + parameters.put("billTime", DateUtils.formatDay(billDate)); + return requestTemplate.getForObject(String.format("%s?%s", getReqUrl(BaiduTransactionType.DOWNLOAD_ORDER_BILL), + UriVariables.getMapToParameters(parameters)), JSONObject.class); + } + + /** + * 通用查询接口 + * + * @param orderId 订单id + * @param siteId 用户id + * @param transactionType 交易类型 + * @return 结果 + */ + @Override + public Map secondaryInterface(Object orderId, + String siteId, + TransactionType transactionType) { + if (!BaiduTransactionType.PAY_QUERY.equals(transactionType)) { + throw new UnsupportedOperationException("不支持该操作"); + } + + Map parameters = getUseQueryPay(); + parameters.put(ORDER_ID, orderId); + parameters.put(SITE_ID, siteId); + parameters.put(SIGN, getRsaSign(parameters, SIGN)); + return requestTemplate.getForObject(String.format("%s?%s", getReqUrl(transactionType), UriVariables.getMapToParameters(parameters)), JSONObject.class); + } + + /** + * 获取支付请求地址 + * + * @param transactionType 交易类型 + * @return 请求URL + */ + @Override + public String getReqUrl(TransactionType transactionType) { + return ((BaiduTransactionType) transactionType).getUrl(); + } + + /** + * 签名 + * + * @param params 参数 + * @param ignoreKeys 忽略字段 + * @return 签名结果 + */ + private String getRsaSign(Map params, String... ignoreKeys) { + String waitSignVal = SignUtils.parameterText(params, "&", false, ignoreKeys); + return SignUtils.valueOf(payConfigStorage.getSignType()).createSign(waitSignVal, payConfigStorage.getKeyPrivate(), payConfigStorage.getInputCharset()); + } +} diff --git a/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduPayOrder.java b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduPayOrder.java new file mode 100644 index 0000000..2f82452 --- /dev/null +++ b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduPayOrder.java @@ -0,0 +1,76 @@ +package com.egzosn.pay.baidu.bean; + +import com.alibaba.fastjson.JSONObject; +import com.egzosn.pay.common.bean.PayOrder; +import com.egzosn.pay.common.bean.TransactionType; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; + +import static com.egzosn.pay.baidu.api.BaiduPayService.BIZ_INFO; +import static com.egzosn.pay.baidu.api.BaiduPayService.SIGN_FIELDS_RANGE; + +public class BaiduPayOrder extends PayOrder { + + /** + * 需要隐藏的支付方式 + */ + private List bannedChannels = Collections.emptyList(); + + /** + * 固定值 + */ + private String signFieldsRange; + + /** + * 附加信息 + */ + private JSONObject bizInfo = new JSONObject(); + + public BaiduPayOrder(String dealTitle, + BigDecimal totalAmount, + String tpOrderId, + String signFieldsRange) { + this(dealTitle, totalAmount, tpOrderId, signFieldsRange, Collections.emptyList()); + } + + public BaiduPayOrder(String dealTitle, + BigDecimal totalAmount, + String tpOrderId, + String signFieldsRange, + List bannedChannels) { + setPrice(totalAmount); + setOutTradeNo(tpOrderId); + setSubject(dealTitle); + setSignFieldsRange(signFieldsRange); + setBannedChannels(bannedChannels); + } + + public JSONObject getBizInfo() { + return bizInfo; + } + + public void setBizInfo(JSONObject bizInfo) { + this.bizInfo = bizInfo; + addAttr(BIZ_INFO, bizInfo); + } + + public List getBannedChannels() { + return bannedChannels; + } + + public void setBannedChannels(List bannedChannels) { + this.bannedChannels = bannedChannels; + } + + public String getSignFieldsRange() { + return signFieldsRange; + } + + public void setSignFieldsRange(String signFieldsRange) { + this.signFieldsRange = signFieldsRange; + addAttr(SIGN_FIELDS_RANGE, signFieldsRange); + } + +} diff --git a/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduRefundOrder.java b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduRefundOrder.java new file mode 100644 index 0000000..91d6510 --- /dev/null +++ b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduRefundOrder.java @@ -0,0 +1,71 @@ +package com.egzosn.pay.baidu.bean; + +import com.egzosn.pay.common.bean.RefundOrder; + +import java.math.BigDecimal; + +public class BaiduRefundOrder extends RefundOrder { + + /** + * 退款类型 + */ + private Integer refundType; + + + public BaiduRefundOrder(Long orderId, + String userId, + Integer refundType, + String refundReason, + String tpOrderId) { + super(); + setOutTradeNo(String.valueOf(orderId)); + setUserId(userId); + setRefundType(refundType); + setDescription(refundReason); + setTradeNo(tpOrderId); + } + + /** + * 退款金额,单位:分,发起部分退款时必传 + * + * @return 退款金额 + */ + public BigDecimal getApplyRefundMoney() { + return getRefundAmount(); + } + + /** + * 退款金额,单位:分,发起部分退款时必传 + * + * @param applyRefundMoney 退款金额 + */ + public void setApplyRefundMoney(BigDecimal applyRefundMoney) { + setRefundAmount(applyRefundMoney); + } + + /** + * 业务方退款批次id,退款业务流水唯一编号,发起部分退款时必传 + * + * @return 退款业务流水 + */ + public String getBizRefundBatchId() { + return getRefundNo(); + } + + /** + * 业务方退款批次id,退款业务流水唯一编号,发起部分退款时必传 + */ + public void setBizRefundBatchId(String bizRefundBatchId) { + setRefundNo(bizRefundBatchId); + } + + public void setRefundType(Integer refundType) { + this.refundType = refundType; + addAttr("refundType", refundType); + } + + public Integer getRefundType() { + return refundType; + } + +} diff --git a/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduTransactionType.java b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduTransactionType.java new file mode 100644 index 0000000..7a0cefe --- /dev/null +++ b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/BaiduTransactionType.java @@ -0,0 +1,47 @@ +package com.egzosn.pay.baidu.bean; + +import com.egzosn.pay.common.bean.TransactionType; + +public enum BaiduTransactionType implements TransactionType { + /** + * 查询支付状态 + */ + PAY_QUERY("https://dianshang.baidu.com/platform/entity/openapi/queryorderdetail", null), + /** + * 取消核销 + */ + REFUND_QUERY("https://nop.nuomi.com/nop/server/rest", "nuomi.cashier.syncorderstatus"), + /** + * 下载资金账单 + */ + DOWNLOAD_BILL("https://openapi.baidu.com/rest/2.0/smartapp/pay/paymentservice/capitaBill", null), + /** + * 下载订单对账单 + */ + DOWNLOAD_ORDER_BILL("https://openapi.baidu.com/rest/2.0/smartapp/pay/paymentservice/orderBill", null), + /** + * 申请退款 + */ + APPLY_REFUND("https://nop.nuomi.com/nop/server/rest", "nuomi.cashier.applyorderrefund"); + private final String method; + private final String url; + + BaiduTransactionType( String url, String method) { + this.url = url; + this.method = method; + } + + @Override + public String getType() { + return this.name(); + } + + @Override + public String getMethod() { + return this.method; + } + + public String getUrl() { + return url; + } +} diff --git a/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/type/AuditStatus.java b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/type/AuditStatus.java new file mode 100644 index 0000000..22960bf --- /dev/null +++ b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/bean/type/AuditStatus.java @@ -0,0 +1,22 @@ +package com.egzosn.pay.baidu.bean.type; + +public enum AuditStatus { + SUCCESS(1, "审核通过可退款"), + FAIL(2, "审核不通过,不能退款"), + UNKNOWN(3, "审核结果不确定,待重试"); + private final int code; + private final String desc; + + AuditStatus(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public int getCode() { + return code; + } + + public String getDesc() { + return desc; + } +} diff --git a/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/package-info.java b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/package-info.java new file mode 100644 index 0000000..e9370e2 --- /dev/null +++ b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/package-info.java @@ -0,0 +1 @@ +package com.egzosn.pay.baidu; \ No newline at end of file diff --git a/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/util/Asserts.java b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/util/Asserts.java new file mode 100644 index 0000000..7c94996 --- /dev/null +++ b/pay-java-baidu/src/main/java/com/egzosn/pay/baidu/util/Asserts.java @@ -0,0 +1,16 @@ +package com.egzosn.pay.baidu.util; + +public class Asserts { + + public static void isNoNull(Object object, String message) { + if (object == null) { + throw new IllegalArgumentException(message); + } + } + + public static void isTrue(boolean bool, String message) { + if (!bool) { + throw new IllegalArgumentException(message); + } + } +} diff --git a/pay-java-baidu/src/test/java/com/egzosn/pay/baidu/api/BaiduPayServiceTest.java b/pay-java-baidu/src/test/java/com/egzosn/pay/baidu/api/BaiduPayServiceTest.java new file mode 100644 index 0000000..6f9b5c2 --- /dev/null +++ b/pay-java-baidu/src/test/java/com/egzosn/pay/baidu/api/BaiduPayServiceTest.java @@ -0,0 +1,24 @@ +package com.egzosn.pay.baidu.api; + +import org.junit.jupiter.api.Test; + +/** + * Created by hocgin on 2019/11/24. + * email: hocgin@gmail.com + * + * @author hocgin + */ +public class BaiduPayServiceTest { + + @Test + public void orderInfo() { + BaiduPayConfigStorage configStorage = new BaiduPayConfigStorage(); + configStorage.setAppid("APP ID"); + configStorage.setAppKey("APP KEY"); + configStorage.setDealId("DEAL ID"); + configStorage.setKeyPublic("KEY PUBLIC"); + + BaiduPayService payService = new BaiduPayService(configStorage); + // payService.refund() + } +} diff --git a/pay-java-common/pom.xml b/pay-java-common/pom.xml index 0c6cdfc..9a0d533 100644 --- a/pay-java-common/pom.xml +++ b/pay-java-common/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 jar diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/api/BasePayService.java b/pay-java-common/src/main/java/com/egzosn/pay/common/api/BasePayService.java index c955e04..261c794 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/api/BasePayService.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/api/BasePayService.java @@ -14,7 +14,6 @@ import org.apache.commons.logging.LogFactory; import java.awt.image.BufferedImage; import java.io.InputStream; import java.io.UnsupportedEncodingException; -import java.math.BigDecimal; import java.util.*; /** @@ -126,7 +125,6 @@ public abstract class BasePayService implements Pay * @param characterEncoding 字符编码 * @return 签名 */ - @Override public String createSign(Map content, String characterEncoding) { return SignUtils.valueOf(payConfigStorage.getSignType()).sign(content, payConfigStorage.getKeyPrivate(), characterEncoding); } @@ -142,6 +140,16 @@ public abstract class BasePayService implements Pay Map orderInfo = orderInfo(order); return buildRequest(orderInfo, MethodType.POST); } + /** + * app支付 + * @param order 订单信息 + * @param 预订单类型 + * @return 对应app所需参数信息 + */ + @Override + public Map app(O order) { + return orderInfo(order); + } /** * 生成二维码支付 @@ -242,24 +250,7 @@ public abstract class BasePayService implements Pay return Collections.EMPTY_MAP; } - /** - * 退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @param callback 处理器 - * @param 返回类型 - * @return 处理过后的类型对象, 返回支付方申请退款后的结果 - * @see #refund(RefundOrder, Callback) - */ - @Deprecated - @Override - public T refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount, Callback callback) { - return callback.perform(refund(new RefundOrder(tradeNo, outTradeNo, refundAmount, totalAmount))); - } /** * 申请退款接口 @@ -276,19 +267,6 @@ public abstract class BasePayService implements Pay } - /** - * 查询退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param callback 处理器 - * @param 返回类型 - * @return 处理过后的类型对象,返回支付方查询退款后的结果 - */ - @Override - public T refundquery(String tradeNo, String outTradeNo, Callback callback) { - return callback.perform(refundquery(tradeNo, outTradeNo)); - } /** * 查询退款 @@ -467,4 +445,20 @@ public abstract class BasePayService implements Pay return orderInfo; } + protected Map setParameters(Map parameters, String key, String value) { + if (StringUtils.isNotEmpty(value)) { + parameters.put(key, value); + } + return parameters; + } + + protected Map setParameters(Map parameters, String key, Order order) { + Object attr = order.getAttr(key); + if (null != attr && !"".equals(attr)) { + parameters.put(key, attr); + } + return parameters; + } + + } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayService.java b/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayService.java index ce065ea..910fc7e 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayService.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayService.java @@ -7,7 +7,6 @@ import com.egzosn.pay.common.http.HttpRequestTemplate; import java.awt.image.BufferedImage; import java.io.InputStream; -import java.math.BigDecimal; import java.util.Date; import java.util.Map; @@ -59,25 +58,27 @@ public interface PayService { * @param params 回调回来的参数集 * @return 签名校验 true通过 */ - boolean verify(Map params); + boolean verify(Map params); /** * 签名校验 - * + * 后面版本废弃 * @param params 参数集 * @param sign 签名原文 * @return 签名校验 true通过 */ + @Deprecated boolean signVerify(Map params, String sign); /** * 支付宝需要,微信是否也需要再次校验来源,进行订单查询 * 校验数据来源 - * + * 后面版本废弃 * @param id 业务id, 数据的真实性. * @return true通过 */ + @Deprecated boolean verifySource(String id); @@ -99,6 +100,13 @@ public interface PayService { * @return 对应页面重定向信息 */ String toPay(O order); + /** + * app支付 + * @param order 订单信息 + * @param 预订单类型 + * @return 对应app所需参数信息 + */ + Map app(O order); /** * 创建签名 @@ -109,14 +117,7 @@ public interface PayService { */ String createSign(String content, String characterEncoding); - /** - * 创建签名 - * - * @param content 需要签名的内容 - * @param characterEncoding 字符编码 - * @return 签名 - */ - String createSign(Map content, String characterEncoding); + /** * 将请求参数或者请求流转化为 Map @@ -243,35 +244,7 @@ public interface PayService { */ T cancel(String tradeNo, String outTradeNo, Callback callback); - /** - * 申请退款接口 - * 废弃 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @return 返回支付方申请退款后的结果 - * @see #refund(RefundOrder) - */ - @Deprecated - Map refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount); - /** - * 申请退款接口 - * 废弃 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @param callback 处理器 - * @param 返回类型 - * @return 返回支付方申请退款后的结果 - * @see #refund(RefundOrder, Callback) - */ - @Deprecated - T refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount, Callback callback); /** * 申请退款接口 @@ -291,27 +264,7 @@ public interface PayService { */ T refund(RefundOrder refundOrder, Callback callback); - /** - * 查询退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @return 返回支付方查询退款后的结果 - */ - @Deprecated - Map refundquery(String tradeNo, String outTradeNo); - /** - * 查询退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param callback 处理器 - * @param 返回类型 - * @return 返回支付方查询退款后的结果 - */ - @Deprecated - T refundquery(String tradeNo, String outTradeNo, Callback callback); /** * 查询退款 @@ -354,18 +307,19 @@ public interface PayService { /** * 通用查询接口 - * + * 接下来移除此方法 * @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请 * 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException} * @param outTradeNoBillType 商户单号或者 账单类型 * @param transactionType 交易类型 * @return 返回支付方对应接口的结果 */ + @Deprecated Map secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType); /** * 通用查询接口 - * + * 接下来移除此方法 * @param tradeNoOrBillDate 支付平台订单号或者账单日期, 具体请 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException} * @param outTradeNoBillType 商户单号或者 账单类型 * @param transactionType 交易类型 @@ -373,6 +327,7 @@ public interface PayService { * @param 返回类型 * @return 返回支付方对应接口的结果 */ + @Deprecated T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback callback); diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/Order.java b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/Order.java index 57046df..fd16e1c 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/Order.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/Order.java @@ -15,8 +15,26 @@ public interface Order { /** * 获取订单属性 这里可用做覆盖已设置的订单信息属性,订单信息在签名前进行覆盖。 + * * @return 属性 */ - Map getAttr(); + Map getAttrs(); + + /** + * 获取订单属性 这里可用做覆盖已设置的订单信息属性,订单信息在签名前进行覆盖。 + * + * @param key 属性名 + * @return 属性 + */ + Object getAttr(String key); + + + /** + * 添加订单信息 + * + * @param key key + * @param value 值 + */ + void addAttr(String key, Object value); } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/PayOrder.java b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/PayOrder.java index 57a6842..35987ab 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/PayOrder.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/PayOrder.java @@ -1,12 +1,12 @@ package com.egzosn.pay.common.bean; +import com.egzosn.pay.common.util.str.StringUtils; + import java.math.BigDecimal; import java.util.Date; import java.util.HashMap; import java.util.Map; -import com.egzosn.pay.common.util.str.StringUtils; - /** * 支付订单信息 * @@ -71,6 +71,7 @@ public class PayOrder implements Order { /** * 用户唯一标识 * 微信含 sub_openid 字段 + * 支付宝 buyer_id */ private String openid; /** @@ -258,20 +259,27 @@ public class PayOrder implements Order { } @Override - public Map getAttr() { + public Map getAttrs() { if (null == attr){ attr = new HashMap<>(); } return attr; } + @Override + public Object getAttr(String key) { + return getAttrs().get(key); + } + + /** * 添加订单信息 * @param key key * @param value 值 */ + @Override public void addAttr(String key, Object value) { - getAttr().put(key, value); + getAttrs().put(key, value); } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/RefundOrder.java b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/RefundOrder.java index be5061a..30e5959 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/RefundOrder.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/RefundOrder.java @@ -2,16 +2,19 @@ package com.egzosn.pay.common.bean; import java.math.BigDecimal; import java.util.Date; +import java.util.HashMap; +import java.util.Map; /** * 退款订单信息 - * @author: egan - *

+ *
+ * @author egan
+ * 
  *      email egzosn@gmail.com
  *      date 2018/1/15 21:40
  *   
*/ -public class RefundOrder { +public class RefundOrder implements Order { /** * 退款单号,每次进行退款的单号,此处唯一 */ @@ -46,6 +49,15 @@ public class RefundOrder { * 退款说明 */ private String description; + /** + * 退款用户 + */ + private String userId; + + /** + * 订单附加信息,可用于预设未提供的参数,这里会覆盖以上所有的订单信息, + */ + private Map attr; public String getRefundNo() { return refundNo; @@ -111,6 +123,14 @@ public class RefundOrder { this.description = description; } + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + public RefundOrder() { } @@ -135,5 +155,28 @@ public class RefundOrder { this.totalAmount = totalAmount; } + @Override + public Map getAttrs() { + if (null == attr) { + attr = new HashMap<>(); + } + return attr; + } + @Override + public Object getAttr(String key) { + return getAttrs().get(key); + } + + + /** + * 添加订单信息 + * + * @param key key + * @param value 值 + */ + @Override + public void addAttr(String key, Object value) { + getAttrs().put(key, value); + } } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/TransferOrder.java b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/TransferOrder.java index 2b89117..73a1162 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/TransferOrder.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/TransferOrder.java @@ -1,16 +1,19 @@ package com.egzosn.pay.common.bean; import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; /** * 转账订单 + * * @author egan *
  * email egzosn@gmail.com
  * date 2018/1/31
  * 
*/ -public class TransferOrder { +public class TransferOrder implements Order { /** * 转账批次订单单号 @@ -25,12 +28,12 @@ public class TransferOrder { /** * 收款方账户, 用户openid,卡号等等 */ - private String payeeAccount ; + private String payeeAccount; /** * 转账金额 */ - private BigDecimal amount ; + private BigDecimal amount; /** * 付款人名称 @@ -53,11 +56,11 @@ public class TransferOrder { /** * 收款开户行 - */ + */ private Bank bank; /** - * 收款开户行地址 + * 收款开户行地址 */ private String payeeBankAddress; @@ -79,6 +82,12 @@ public class TransferOrder { */ private String ip; + + /** + * 订单附加信息,可用于预设未提供的参数,这里会覆盖以上所有的订单信息, + */ + private Map attr; + public String getBatchNo() { return batchNo; } @@ -190,4 +199,31 @@ public class TransferOrder { public void setIp(String ip) { this.ip = ip; } + + @Override + public Map getAttrs() { + if (null == attr) { + attr = new HashMap<>(); + } + return attr; + } + + @Override + public Object getAttr(String key) { + return getAttrs().get(key); + } + + + /** + * 添加订单信息 + * + * @param key key + * @param value 值 + */ + @Override + public void addAttr(String key, Object value) { + getAttrs().put(key, value); + } + + } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/TransferType.java b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/TransferType.java index 867acf9..24b34d5 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/TransferType.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/TransferType.java @@ -1,5 +1,7 @@ package com.egzosn.pay.common.bean; +import java.util.Map; + /** * 转账类型 * @author egan @@ -7,6 +9,12 @@ package com.egzosn.pay.common.bean; * date 2018/9/28.19:45 */ public interface TransferType extends TransactionType{ - - + /** + * 设置属性 + * + * @param attr 已有属性对象 + * @param order 转账订单 + * @return 属性对象 + */ + Map setAttr(Map attr, TransferOrder order); } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/util/DateUtils.java b/pay-java-common/src/main/java/com/egzosn/pay/common/util/DateUtils.java index b101b44..f8141d9 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/util/DateUtils.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/util/DateUtils.java @@ -13,7 +13,7 @@ import java.util.*; * 日期转换运算工具 * * @author egan - *
+ * 
  *         email egzosn@gmail.com
  *         date 2018-11-21 16:43:20
  *         
@@ -23,6 +23,7 @@ public final class DateUtils { } private static final Log LOG = LogFactory.getLog(DateUtils.class); + static final class DateFormatHolder { private static final ThreadLocal>> THREADLOCAL_FORMATS = new ThreadLocal>>(); @@ -37,7 +38,7 @@ public final class DateUtils { THREADLOCAL_FORMATS.set(new SoftReference(formats)); } - SimpleDateFormat format = formats.get(pattern); + SimpleDateFormat format = formats.get(pattern); if (format == null) { format = new SimpleDateFormat(pattern); @@ -66,6 +67,7 @@ public final class DateUtils { SimpleDateFormat formatFor = DateFormatHolder.formatFor(pattern); return formatFor.format(date); } + public static Date parseDate(String date, String pattern) { Args.notNull(date, "Date"); Args.notNull(pattern, "Pattern"); @@ -77,9 +79,11 @@ public final class DateUtils { } return null; } + public static Date parse(String date) { return parseDate(date, YYYY_MM_DD_HH_MM_SS); } + public static final String format(Date date) { return formatDate(date, YYYY_MM_DD_HH_MM_SS); } @@ -99,7 +103,7 @@ public final class DateUtils { * @return 分钟数 */ public static final long minutesRemaining(Date date) { - return (date.getTime() - System.currentTimeMillis()) / 1000 / 60; + return (date.getTime() / 1000 / 60 - System.currentTimeMillis() / 1000 / 60); } /** diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/SignUtils.java b/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/SignUtils.java index ae31172..74ade5f 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/SignUtils.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/SignUtils.java @@ -193,7 +193,20 @@ public enum SignUtils implements SignType { * @param ignoreKey 需要忽略添加的key * @return 去掉空值与签名参数后的新签名,拼接后字符串 */ - public static String parameterText(Map parameters, String separator, String... ignoreKey ) { + public static String parameterText(Map parameters, String separator, String... ignoreKey) { + return parameterText(parameters, separator, true, ignoreKey); + } + + /** + * + * 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串 + * @param parameters 参数 + * @param separator 分隔符 + * @param ignoreNullValue 需要忽略NULL值 + * @param ignoreKey 需要忽略添加的key + * @return 去掉空值与签名参数后的新签名,拼接后字符串 + */ + public static String parameterText(Map parameters, String separator, boolean ignoreNullValue, String... ignoreKey ) { if(parameters == null){ return ""; } @@ -225,7 +238,7 @@ public enum SignUtils implements SignType { for (String k : keys) { String valueStr = ""; Object o = parameters.get(k); - if (null == o) { + if (ignoreNullValue && null == o) { continue; } if (o instanceof String[]) { diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/encrypt/RSA.java b/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/encrypt/RSA.java index ca29fea..3bcf772 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/encrypt/RSA.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/encrypt/RSA.java @@ -3,6 +3,7 @@ package com.egzosn.pay.common.util.sign.encrypt; import javax.crypto.Cipher; import java.io.*; +import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; @@ -34,9 +35,9 @@ public class RSA{ */ public static String sign(String content, String privateKey, String signAlgorithms, String characterEncoding) { try { - PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec( Base64.decode(privateKey)); - KeyFactory keyf = KeyFactory.getInstance(ALGORITHM); - PrivateKey priKey = keyf.generatePrivate(priPKCS8); + PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey)); + KeyFactory keyf = KeyFactory.getInstance(ALGORITHM); + PrivateKey priKey = keyf.generatePrivate(priPKCS8); java.security.Signature signature = java.security.Signature.getInstance(signAlgorithms); @@ -111,11 +112,11 @@ public class RSA{ */ public static boolean verify(String content, String sign, String publicKey, String signAlgorithms, String characterEncoding){ try { - PublicKey pubKey = getPublicKey(publicKey, ALGORITHM); + PublicKey pubKey = getPublicKey(publicKey, ALGORITHM); java.security.Signature signature = java.security.Signature.getInstance(signAlgorithms); signature.initVerify(pubKey); - signature.update( content.getBytes(characterEncoding) ); - return signature.verify( Base64.decode(sign) ); + signature.update(content.getBytes(characterEncoding) ); + return signature.verify(Base64.decode(sign) ); } catch (Exception e) { e.printStackTrace(); } @@ -135,8 +136,8 @@ public class RSA{ try { java.security.Signature signature = java.security.Signature.getInstance(signAlgorithms); signature.initVerify(publicKey); - signature.update( content.getBytes(characterEncoding) ); - return signature.verify( Base64.decode(sign) ); + signature.update(content.getBytes(characterEncoding) ); + return signature.verify(Base64.decode(sign) ); } catch (Exception e) { e.printStackTrace(); } @@ -176,9 +177,9 @@ public class RSA{ * @return 解密后的字符串 * @throws Exception 解密异常 */ - public static String decrypt(String content, String privateKey, String characterEncoding) throws Exception { - PrivateKey prikey = getPrivateKey(privateKey); - Cipher cipher = Cipher.getInstance(ALGORITHM); + public static String decrypt(String content, String privateKey, String characterEncoding) throws GeneralSecurityException, IOException { + PrivateKey prikey = getPrivateKey(privateKey); + Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, prikey); try(InputStream ins = new ByteArrayInputStream(Base64.decode(content)); ByteArrayOutputStream writer = new ByteArrayOutputStream();) { @@ -204,14 +205,14 @@ public class RSA{ } } - + /** * 得到私钥 * @param key 密钥字符串(经过base64编码) - * @throws Exception 加密异常 + * @throws GeneralSecurityException 加密异常 * @return 私钥 */ - public static PrivateKey getPrivateKey(String key) throws Exception { + public static PrivateKey getPrivateKey(String key) throws GeneralSecurityException { byte[] keyBytes; keyBytes = Base64.decode(key); @@ -225,26 +226,30 @@ public class RSA{ * 得到公钥 * @param key 密钥字符串(经过base64编码) * @param signAlgorithms 密钥类型 - * @throws Exception 加密异常 + * @throws GeneralSecurityException 加密异常 + * @throws IOException 加密异常 * @return 公钥 */ - public static PublicKey getPublicKey(String key, String signAlgorithms) throws Exception { - return getPublicKey(new ByteArrayInputStream(key.getBytes("ISO8859-1")), signAlgorithms); + public static PublicKey getPublicKey(String key, String signAlgorithms) throws GeneralSecurityException, IOException { + try (ByteArrayInputStream is = new ByteArrayInputStream(key.getBytes("ISO8859-1"))){ + return getPublicKey(is, signAlgorithms); + } } /** * 得到公钥 * @param key 密钥字符串(经过base64编码) - * @throws Exception 加密异常 + * @throws GeneralSecurityException 加密异常 + * @throws IOException 加密异常 * @return 公钥 */ - public static PublicKey getPublicKey(String key) throws Exception { + public static PublicKey getPublicKey(String key) throws GeneralSecurityException, IOException { return getPublicKey(key, ALGORITHM); } - public static PublicKey getPublicKey(InputStream inputStream, String keyAlgorithm) throws Exception { + public static PublicKey getPublicKey(InputStream inputStream, String keyAlgorithm) throws IOException, GeneralSecurityException { try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));) { StringBuilder sb = new StringBuilder(); String readLine = null; @@ -262,14 +267,14 @@ public class RSA{ } } - public static byte[] encrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize, String cipherAlgorithm) throws Exception { + public static byte[] encrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize, String cipherAlgorithm) throws IOException, GeneralSecurityException { int keyByteSize = keyLength / 8; int encryptBlockSize = keyByteSize - reserveSize; int nBlock = plainBytes.length / encryptBlockSize; if ((plainBytes.length % encryptBlockSize) != 0) { nBlock += 1; } - try (ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);) { + try (ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * keyByteSize)) { Cipher cipher = Cipher.getInstance(cipherAlgorithm); cipher.init(Cipher.ENCRYPT_MODE, publicKey); for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) { @@ -284,7 +289,7 @@ public class RSA{ return outbuf.toByteArray(); } } - public static String encrypt(String content, String publicKey, String cipherAlgorithm, String characterEncoding ) throws Exception { + public static String encrypt(String content, String publicKey, String cipherAlgorithm, String characterEncoding ) throws IOException, GeneralSecurityException { return Base64.encode(RSA.encrypt(content.getBytes(characterEncoding), RSA.getPublicKey(publicKey),1024, 11, cipherAlgorithm)); } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/encrypt/RSA2.java b/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/encrypt/RSA2.java index 680b7b0..5aa464d 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/encrypt/RSA2.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/util/sign/encrypt/RSA2.java @@ -1,6 +1,8 @@ package com.egzosn.pay.common.util.sign.encrypt; +import java.io.IOException; +import java.security.GeneralSecurityException; import java.security.PrivateKey; import java.security.PublicKey; @@ -63,11 +65,11 @@ public class RSA2 { * @return 解密后的字符串 * @throws Exception 解密异常 */ - public static String decrypt(String content, String privateKey, String characterEncoding) throws Exception { + public static String decrypt(String content, String privateKey, String characterEncoding) throws GeneralSecurityException, IOException { return RSA.decrypt(content, privateKey, characterEncoding); } - + /** * 得到私钥 * @param key 密钥字符串(经过base64编码) @@ -79,7 +81,7 @@ public class RSA2 { } - public static String encrypt(String content, String publicKey, String cipherAlgorithm, String characterEncoding ) throws Exception { - return Base64.encode(RSA.encrypt(content.getBytes(characterEncoding), RSA.getPublicKey(publicKey),2048, 11, cipherAlgorithm)); + public static String encrypt(String content, String publicKey, String cipherAlgorithm, String characterEncoding ) throws GeneralSecurityException, IOException { + return Base64.encode(RSA.encrypt(content.getBytes(characterEncoding), RSA.getPublicKey(publicKey), 2048, 11, cipherAlgorithm)); } } diff --git a/pay-java-demo/pom.xml b/pay-java-demo/pom.xml index d2a5c0d..c02296e 100644 --- a/pay-java-demo/pom.xml +++ b/pay-java-demo/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 war @@ -90,39 +90,7 @@ - - - port8080 - - 8080 - - - true - - - - port9096 - - 9096 - - - - local - - local - - - true - - - - proc - - proc - - - pay-java-demo @@ -140,7 +108,7 @@ tomcat7-maven-plugin 2.0 - ${port} + 8080 / UTF-8 diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/AliPayController.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/AliPayController.java index 64e235f..7ee3fbf 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/AliPayController.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/AliPayController.java @@ -5,9 +5,11 @@ package com.egzosn.pay.demo.controller; import com.egzosn.pay.ali.api.AliPayConfigStorage; import com.egzosn.pay.ali.api.AliPayService; import com.egzosn.pay.ali.bean.AliTransactionType; +import com.egzosn.pay.ali.bean.AliTransferOrder; import com.egzosn.pay.ali.bean.AliTransferType; import com.egzosn.pay.ali.bean.OrderSettle; -import com.egzosn.pay.common.bean.*; +import com.egzosn.pay.common.bean.PayOrder; +import com.egzosn.pay.common.bean.RefundOrder; import com.egzosn.pay.common.http.HttpConfigStorage; import com.egzosn.pay.common.http.UriVariables; import com.egzosn.pay.common.util.sign.SignUtils; @@ -17,6 +19,7 @@ import com.egzosn.pay.demo.service.interceptor.AliPayMessageInterceptor; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; + import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.imageio.ImageIO; @@ -109,7 +112,7 @@ public class AliPayController { PayOrder order = new PayOrder("订单title", "摘要", new BigDecimal(0.01), UUID.randomUUID().toString().replace("-", "")); //App支付 order.setTransactionType(AliTransactionType.APP); - data.put("orderInfo", UriVariables.getMapToParameters(service.orderInfo(order))); + data.put("orderInfo", UriVariables.getMapToParameters(service.app(order))); return data; } @@ -287,8 +290,8 @@ public class AliPayController { * @return 返回支付方查询退款后的结果 */ @RequestMapping("refundquery") - public Map refundquery(QueryOrder order) { - return service.refundquery(order.getTradeNo(), order.getOutTradeNo()); + public Map refundquery(RefundOrder order) { + return service.refundquery(order); } /** @@ -303,18 +306,6 @@ public class AliPayController { } - /** - * 通用查询接口,根据 AliTransactionType 类型进行实现,此接口不包括退款 - * - * @param order 订单的请求体 - * @return 返回支付方对应接口的结果 - */ - @RequestMapping("secondaryInterface") - public Map secondaryInterface(QueryOrder order) { - TransactionType type = AliTransactionType.valueOf(order.getTransactionType()); - return service.secondaryInterface(order.getTradeNoOrBillDate(), order.getOutTradeNoBillType(), type); - } - /** * 转账 * @@ -323,15 +314,18 @@ public class AliPayController { * @return 对应的转账结果 */ @RequestMapping("transfer") - public Map transfer(TransferOrder order) { -// order.setOutNo("转账单号"); -// order.setPayeeAccount("收款方账户,支付宝登录号,支持邮箱和手机号格式"); -// order.setAmount(new BigDecimal(10)); -// order.setPayerName("付款方姓名, 非必填"); -// order.setPayeeName("收款方真实姓名, 非必填"); -// order.setRemark("转账备注, 非必填"); - //收款方账户类型 ,默认值 ALIPAY_LOGONID:支付宝登录号,支持邮箱和手机号格式。 - order.setTransferType(AliTransferType.ALIPAY_LOGONID); + public Map transfer(AliTransferOrder order) { + order.setOutBizNo("转账单号"); + order.setTransAmount(new BigDecimal(10)); + order.setOrderTitle("转账业务的标题"); + order.setIdentity("参与方的唯一标识"); + order.setIdentityType("参与方的标识类型,目前支持如下类型:"); + order.setName("参与方真实姓名"); + order.setRemark("转账备注, 非必填"); + //单笔无密转账到支付宝账户 + order.setTransferType(AliTransferType.TRANS_ACCOUNT_NO_PWD); + //单笔无密转账到银行卡 +// order.setTransferType(AliTransferType.TRANS_BANKCARD_NO_PWD); return service.transfer(order); } diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayController.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayController.java index 0705246..c7adb42 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayController.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayController.java @@ -167,14 +167,14 @@ public class PayController { * @param price 金额 * @return 支付预订单信息 */ - @RequestMapping("getOrderInfo") + @RequestMapping("app") public Map getOrderInfo(Integer payId, String transactionType, BigDecimal price) { //获取对应的支付账户操作工具(可根据账户id) PayResponse payResponse = service.getPayResponse(payId); Map data = new HashMap<>(); data.put("code", 0); PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType)); - data.put("orderInfo", payResponse.getService().orderInfo(order)); + data.put("orderInfo", payResponse.getService().app(order)); return data; } @@ -436,9 +436,11 @@ public class PayController { * @return 返回支付方查询退款后的结果 */ @RequestMapping("refundquery") - public Map refundquery(QueryOrder order) { - PayResponse payResponse = service.getPayResponse(order.getPayId()); - return payResponse.getService().refundquery(order.getTradeNo(), order.getOutTradeNo()); + public Map refundquery(Integer payId, RefundOrder order) { + PayResponse payResponse = service.getPayResponse(payId); + + + return payResponse.getService().refundquery(order); } /** diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayPalPayController.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayPalPayController.java index c2bee1a..f9a7873 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayPalPayController.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayPalPayController.java @@ -2,7 +2,9 @@ package com.egzosn.pay.demo.controller; import com.egzosn.pay.common.api.PayService; -import com.egzosn.pay.common.bean.*; +import com.egzosn.pay.common.bean.DefaultCurType; +import com.egzosn.pay.common.bean.PayOrder; +import com.egzosn.pay.common.bean.RefundOrder; import com.egzosn.pay.common.http.HttpConfigStorage; import com.egzosn.pay.paypal.api.PayPalConfigStorage; import com.egzosn.pay.paypal.api.PayPalPayService; diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/UnionPayController.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/UnionPayController.java index f751cbe..8bda76f 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/UnionPayController.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/UnionPayController.java @@ -139,7 +139,7 @@ public class UnionPayController { //APPLE支付 苹果付 // order.setTransactionType(UnionTransactionType.APPLE); - data.put("orderInfo", service.orderInfo(order)); + data.put("orderInfo", service.app(order)); return data; } @@ -270,16 +270,6 @@ public class UnionPayController { return service.refund(order); } - /** - * 查询退款 - * - * @param order 订单的请求体 - * @return 返回支付方查询退款后的结果 - */ - @RequestMapping("refundquery") - public Map refundquery(QueryOrder order) { - return service.refundquery(order.getTradeNo(), order.getOutTradeNo()); - } /** * 下载对账单 diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/WxPayController.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/WxPayController.java index 4f72fb3..096f609 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/WxPayController.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/WxPayController.java @@ -2,27 +2,16 @@ package com.egzosn.pay.demo.controller; -import com.egzosn.pay.common.api.Callback; -import com.egzosn.pay.common.api.PayService; import com.egzosn.pay.common.bean.*; import com.egzosn.pay.common.http.HttpConfigStorage; -import com.egzosn.pay.common.http.UriVariables; -import com.egzosn.pay.demo.entity.PayType; import com.egzosn.pay.demo.request.QueryOrder; -import com.egzosn.pay.demo.service.PayResponse; -import com.egzosn.pay.demo.service.handler.AliPayMessageHandler; -import com.egzosn.pay.demo.service.handler.WxPayMessageHandler; import com.egzosn.pay.wx.api.WxPayConfigStorage; import com.egzosn.pay.wx.api.WxPayService; -import com.egzosn.pay.wx.bean.WxBank; -import com.egzosn.pay.wx.bean.WxTransactionType; -import com.egzosn.pay.wx.bean.WxTransferType; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import com.egzosn.pay.wx.bean.*; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.PostConstruct; -import javax.annotation.Resource; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import java.io.ByteArrayOutputStream; @@ -43,7 +32,7 @@ import java.util.UUID; @RequestMapping("wx") public class WxPayController { - private PayService service = null; + private WxPayService service = null; @@ -155,7 +144,7 @@ public class WxPayController { PayOrder order = new PayOrder("订单title", "摘要", new BigDecimal(0.01), UUID.randomUUID().toString().replace("-", "")); //App支付 order.setTransactionType(WxTransactionType.APP); - data.put("orderInfo", service.orderInfo(order)); + data.put("orderInfo", service.app(order)); return data; } @@ -334,8 +323,8 @@ public class WxPayController { * @return 返回支付方查询退款后的结果 */ @RequestMapping("refundquery") - public Map refundquery(QueryOrder order) { - return service.refundquery(order.getTradeNo(), order.getOutTradeNo()); + public Map refundquery(RefundOrder order) { + return service.refundquery(order); } /** @@ -350,18 +339,6 @@ public class WxPayController { } - /** - * 通用查询接口,根据 WxTransactionType 类型进行实现,此接口不包括退款 - * - * @param order 订单的请求体 - * @return 返回支付方对应接口的结果 - */ - @RequestMapping("secondaryInterface") - public Map secondaryInterface(QueryOrder order) { - TransactionType type = WxTransactionType.valueOf(order.getTransactionType()); - return service.secondaryInterface(order.getTradeNoOrBillDate(), order.getOutTradeNoBillType(), type); - } - /** @@ -428,4 +405,51 @@ public class WxPayController { //默认查询银行卡的记录 com.egzosn.pay.wx.bean.WxTransferType#QUERY_BANK return service.transferQuery(outNo, wxTransferType); } + + /** + * 微信发红包 + * @param redpackOrder 红包订单 + * @return 结果 + */ + public Map sendredpack(RedpackOrder redpackOrder) { + redpackOrder.setTransferType(WxSendredpackType.SENDREDPACK); + return service.sendredpack(redpackOrder); + } + + /** + * 发放裂变红包 + * @param redpackOrder 红包订单 + * @return 结果 + */ + public Map sendgroupredpack(RedpackOrder redpackOrder) { + redpackOrder.setTransferType(WxSendredpackType.SENDGROUPREDPACK); + return service.sendredpack(redpackOrder); + } + + + /** + * 小程序发红包 + * @param redpackOrder 红包订单 + * @return 结果 + */ + public Map sendminiprogramhb(RedpackOrder redpackOrder) { + redpackOrder.setTransferType(WxSendredpackType.SENDMINIPROGRAMHB); + return service.sendredpack(redpackOrder); + } + + + /** + * 查询红包记录 + * 用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包 + * 查询红包记录API只支持查询30天内的红包订单,30天之前的红包订单请登录商户平台查询。 + * + * @param mchBillno 商户发放红包的商户订单号 + * @return 返回查询结果 + */ + public Map gethbinfo(String mchBillno) { + return service.gethbinfo(mchBillno); + } + + + } diff --git a/pay-java-demo/src/main/webapp/index.html b/pay-java-demo/src/main/webapp/index.html index 03b359c..6aed160 100644 --- a/pay-java-demo/src/main/webapp/index.html +++ b/pay-java-demo/src/main/webapp/index.html @@ -69,12 +69,12 @@
-
各个支付对应的交易类型可自行查看对应的官方文档,本项目已实现几种交易类型,对应各个支付类型的com.egzosn.pay.common.bean.TransactionType具体实现
新版支付宝(com.egzosn.pay.ali.bean.AliTransactionType): 即时付款=PAGE , app支付=APP , 手机网站支付=WAP , 扫码付=SWEEPPAY, 条码付=BAR_CODE, 声波付=WAVE_CODE
微信(com.egzosn.pay.wx.bean.WxTransactionType): 公众号支付=JSAPI , 移动支付=APP , 扫码付=NATIVE
银联(com.egzosn.pay.union.bean.UnionTransactionType):苹果支付=APPLE,手机控件=APP,WAP支付=WAP,网关支付=WEB,无跳转支付=NO_JUMP,B2B支付=B2B,申码(主扫场景)=APPLY_QR_CODE,消费(被扫场景)=CONSUME
友店微信(com.egzosn.pay.wx.youdian.bean.YoudianTransactionType): 扫码付=NATIVE
富友(com.egzosn.pay.fuiou.bean.FuiouTransactionType): B2B,B2C
+
详情请查看 com.egzosn.pay.common.bean.TransactionType对应的子类


diff --git a/pay-java-fuiou/pom.xml b/pay-java-fuiou/pom.xml index 524b783..b3c1383 100644 --- a/pay-java-fuiou/pom.xml +++ b/pay-java-fuiou/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 pay-java-fuiou diff --git a/pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/api/FuiouPayService.java b/pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/api/FuiouPayService.java index 8a3b4b0..1446463 100644 --- a/pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/api/FuiouPayService.java +++ b/pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/api/FuiouPayService.java @@ -203,7 +203,7 @@ public class FuiouPayService extends BasePayService { parameters.put("rem", ""); //版本号 parameters.put("ver", "1.0.1"); - parameters.putAll(order.getAttr()); + parameters.putAll(order.getAttrs()); return preOrderHandler(parameters, order); } @@ -371,22 +371,6 @@ public class FuiouPayService extends BasePayService { - /** - * 申请退款接口 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @return 退款返回结果集 - */ - @Override - public Map refund (String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) { - return refund(new RefundOrder(tradeNo, outTradeNo, refundAmount, totalAmount)); - } - - - /** * 申请退款接口 @@ -413,20 +397,6 @@ public class FuiouPayService extends BasePayService { } - - /** - * 查询退款 - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @return 空 - * - */ - - @Override - public Map refundquery(String tradeNo, String outTradeNo) { - return Collections.emptyMap(); - } - /** * 查询退款 * diff --git a/pay-java-payoneer/pom.xml b/pay-java-payoneer/pom.xml index 19f68f3..22940d6 100644 --- a/pay-java-payoneer/pom.xml +++ b/pay-java-payoneer/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 pay-java-payoneer diff --git a/pay-java-payoneer/src/main/java/com/egzosn/pay/payoneer/api/PayoneerPayService.java b/pay-java-payoneer/src/main/java/com/egzosn/pay/payoneer/api/PayoneerPayService.java index 29cdb28..8596b7b 100644 --- a/pay-java-payoneer/src/main/java/com/egzosn/pay/payoneer/api/PayoneerPayService.java +++ b/pay-java-payoneer/src/main/java/com/egzosn/pay/payoneer/api/PayoneerPayService.java @@ -18,8 +18,6 @@ import org.apache.http.Header; import org.apache.http.entity.ContentType; import org.apache.http.message.BasicHeader; -import java.awt.image.BufferedImage; -import java.math.BigDecimal; import java.util.*; /** @@ -184,7 +182,7 @@ public class PayoneerPayService extends BasePayService im } params.put("currency", order.getCurType()); params.put("description", order.getSubject()); - params.putAll(order.getAttr()); + params.putAll(order.getAttrs()); return preOrderHandler(params, order); } @@ -314,22 +312,7 @@ public class PayoneerPayService extends BasePayService im return secondaryInterface(tradeNo, outTradeNo, PayoneerTransactionType.CHARGE_CANCEL); } - /** - * 申请退款接口 - * 废弃 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * - * @return 返回支付方申请退款后的结果 - * @see #refund(RefundOrder) - */ - @Override - public Map refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) { - return close(tradeNo, outTradeNo); - } + /** @@ -344,18 +327,6 @@ public class PayoneerPayService extends BasePayService im return close(refundOrder.getTradeNo(), refundOrder.getOutTradeNo()); } - /** - * 查询退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * - * @return 返回支付方查询退款后的结果 - */ - @Override - public Map refundquery(String tradeNo, String outTradeNo) { - return Collections.emptyMap(); - } /** * 查询退款 diff --git a/pay-java-paypal/pom.xml b/pay-java-paypal/pom.xml index f0d8047..7f56a2e 100644 --- a/pay-java-paypal/pom.xml +++ b/pay-java-paypal/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 diff --git a/pay-java-paypal/src/main/java/com/egzosn/pay/paypal/api/PayPalPayService.java b/pay-java-paypal/src/main/java/com/egzosn/pay/paypal/api/PayPalPayService.java index e522814..ea120e7 100644 --- a/pay-java-paypal/src/main/java/com/egzosn/pay/paypal/api/PayPalPayService.java +++ b/pay-java-paypal/src/main/java/com/egzosn/pay/paypal/api/PayPalPayService.java @@ -16,7 +16,7 @@ import com.egzosn.pay.paypal.bean.order.*; import org.apache.http.Header; import org.apache.http.entity.ContentType; import org.apache.http.message.BasicHeader; -import java.awt.image.BufferedImage; + import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.util.*; @@ -239,22 +239,7 @@ public class PayPalPayService extends BasePayService{ public Map close(String tradeNo, String outTradeNo) { return null; } - /** - * 申请退款接口 - * 废弃 - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @return 返回支付方申请退款后的结果 - * @see #refund(RefundOrder) - * @deprecated {@link #refund(RefundOrder)} - */ - @Deprecated - @Override - public Map refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) { - return refund(new RefundOrder( tradeNo, outTradeNo, refundAmount, totalAmount)); - } + /** @@ -284,18 +269,6 @@ public class PayPalPayService extends BasePayService{ JSONObject resp = getHttpRequestTemplate().postForObject(getReqUrl(PayPalTransactionType.REFUND), httpEntity, JSONObject.class, refundOrder.getTradeNo()); return resp; } - /** - * 查询退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @return 返回支付方查询退款后的结果 - */ - @Override - public Map refundquery(String tradeNo, String outTradeNo) { - JSONObject resp = getHttpRequestTemplate().getForObject(getReqUrl(PayPalTransactionType.REFUND_QUERY), authHeader(), JSONObject.class, tradeNo); - return resp; - } /** * 查询退款 @@ -305,7 +278,8 @@ public class PayPalPayService extends BasePayService{ */ @Override public Map refundquery(RefundOrder refundOrder) { - return refundquery(refundOrder.getTradeNo(), refundOrder.getOutTradeNo()); + JSONObject resp = getHttpRequestTemplate().getForObject(getReqUrl(PayPalTransactionType.REFUND_QUERY), authHeader(), JSONObject.class, refundOrder.getTradeNo()); + return resp; } @Override diff --git a/pay-java-union/pom.xml b/pay-java-union/pom.xml index d22f2fd..61cee3e 100644 --- a/pay-java-union/pom.xml +++ b/pay-java-union/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 diff --git a/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java b/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java index 2d33850..6e97c3d 100644 --- a/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java +++ b/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java @@ -9,7 +9,6 @@ import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.http.HttpConfigStorage; import com.egzosn.pay.common.http.UriVariables; import com.egzosn.pay.common.util.DateUtils; -import com.egzosn.pay.common.util.MatrixToImageWriter; import com.egzosn.pay.common.util.Util; import com.egzosn.pay.common.util.sign.CertDescriptor; import com.egzosn.pay.common.util.sign.SignUtils; @@ -20,11 +19,13 @@ import com.egzosn.pay.union.bean.SDKConstants; import com.egzosn.pay.union.bean.UnionPayMessage; import com.egzosn.pay.union.bean.UnionTransactionType; -import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; +import java.security.GeneralSecurityException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; import java.security.cert.*; import java.sql.Timestamp; import java.text.DateFormat; @@ -284,7 +285,7 @@ public class UnionPayService extends BasePayService { params.put(SDKConstants.param_payTimeout, getPayTimeout(order.getExpirationTime())); params.put("orderDesc", order.getSubject()); } - params.putAll(order.getAttr()); + params.putAll(order.getAttrs()); params = preOrderHandler(params, order); return setSign(params); } @@ -361,21 +362,35 @@ public class UnionPayService extends BasePayService { CertPathBuilder builder = CertPathBuilder.getInstance("PKIX"); - @SuppressWarnings("unused") - PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder.build(pkixParams); + /*PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult)*/ builder.build(pkixParams); return cert; } catch (java.security.cert.CertPathBuilderException e) { LOG.error("verify certificate chain fail.", e); } catch (CertificateExpiredException e) { LOG.error(e); - } catch (CertificateNotYetValidException e) { - LOG.error(e); - } catch (Exception e) { + } catch (GeneralSecurityException e) { LOG.error(e); } return null; } + /** + * 发送订单 + * + * @param order 发起支付的订单信息 + * @return 返回支付结果 + */ + + public JSONObject postOrder(PayOrder order) { + Map params = orderInfo(order); + String responseStr = getHttpRequestTemplate().postForObject(this.getBackTransUrl(), params, String.class); + JSONObject response = UriVariables.getParametersToMap(responseStr); + if (response.isEmpty()) { + throw new PayErrorException(new PayException("failure", "响应内容有误!", responseStr)); + } + return response; + } + @Override public String toPay(PayOrder order) { @@ -397,20 +412,15 @@ public class UnionPayService extends BasePayService { @Override public String getQrPay(PayOrder order) { order.setTransactionType(UnionTransactionType.APPLY_QR_CODE); - Map params = orderInfo(order); - String responseStr = getHttpRequestTemplate().postForObject(this.getBackTransUrl(), params, String.class); - Map response = UriVariables.getParametersToMap(responseStr); - if (response.isEmpty()) { - throw new PayErrorException(new PayException("failure", "响应内容有误!", responseStr)); - } + JSONObject response = postOrder(order); if (this.verify(response)) { if (SDKConstants.OK_RESP_CODE.equals(response.get(SDKConstants.param_respCode))) { //成功 return (String) response.get(SDKConstants.param_qrCode); } - throw new PayErrorException(new PayException((String) response.get(SDKConstants.param_respCode), (String) response.get(SDKConstants.param_respMsg), responseStr)); + throw new PayErrorException(new PayException((String) response.get(SDKConstants.param_respCode), (String) response.get(SDKConstants.param_respMsg), response.toJSONString())); } - throw new PayErrorException(new PayException("failure", "验证签名失败", responseStr)); + throw new PayErrorException(new PayException("failure", "验证签名失败", response.toJSONString())); } /** @@ -422,9 +432,8 @@ public class UnionPayService extends BasePayService { @Override public Map microPay(PayOrder order) { order.setTransactionType(UnionTransactionType.CONSUME); - Map params = orderInfo(order); - String responseStr = getHttpRequestTemplate().postForObject(this.getBackTransUrl(), params, String.class); - return UriVariables.getParametersToMap(responseStr); + JSONObject response = postOrder(order); + return response; } @@ -501,17 +510,14 @@ public class UnionPayService extends BasePayService { /** * 功能:将订单信息进行签名并提交请求 - * 业务范围:手机控件支付产品(WAP), + * 业务范围:手机支付控件(含安卓Pay) * @param order 订单信息 * @return 成功:返回支付结果 失败:返回 */ - public Map sendHttpRequest(PayOrder order){ - Map params = orderInfo(order); - String responseStr = getHttpRequestTemplate().postForObject(this.getBackTransUrl(), params, String.class); - Map response = UriVariables.getParametersToMap(responseStr); - if (response.isEmpty()) { - throw new PayErrorException(new PayException("failure", "响应内容有误!", responseStr)); - } + @Override + public Map app(PayOrder order){ + order.setTransactionType(UnionTransactionType.APP); + JSONObject response = postOrder(order); if (this.verify(response)) { if (SDKConstants.OK_RESP_CODE.equals(response.get(SDKConstants.param_respCode))) { // //成功,获取tn号 @@ -519,9 +525,9 @@ public class UnionPayService extends BasePayService { // //TODO return response; } - throw new PayErrorException(new PayException((String) response.get(SDKConstants.param_respCode), (String) response.get(SDKConstants.param_respMsg), responseStr)); + throw new PayErrorException(new PayException((String) response.get(SDKConstants.param_respCode), (String) response.get(SDKConstants.param_respMsg), response.toJSONString())); } - throw new PayErrorException(new PayException("failure", "验证签名失败", responseStr)); + throw new PayErrorException(new PayException("failure", "验证签名失败", response.toJSONString())); } /** @@ -610,40 +616,12 @@ public class UnionPayService extends BasePayService { return Collections.emptyMap(); } - /** - * 申请退款接口 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @return 返回支付方申请退款后的结果 - * @see #refund(RefundOrder) - */ - @Deprecated - @Override - public Map refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) { - return refund(new RefundOrder(tradeNo, outTradeNo, refundAmount, totalAmount)); - } - @Override public Map refund(RefundOrder refundOrder) { return unionRefundOrConsumeUndo(refundOrder, UnionTransactionType.REFUND); } - /** - * 查询退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @return 返回支付方查询退款后的结果 - */ - @Override - public Map refundquery(String tradeNo, String outTradeNo) { - return Collections.emptyMap(); - } - /** * 查询退款 diff --git a/pay-java-union/src/test/java/PayTest.java b/pay-java-union/src/test/java/PayTest.java index f64b70b..ff2f114 100644 --- a/pay-java-union/src/test/java/PayTest.java +++ b/pay-java-union/src/test/java/PayTest.java @@ -93,7 +93,7 @@ public class PayTest { /*-----------退货交易:后台资金类交易,有同步应答和后台通知应答------------------------------*/ payOrder.setTransactionType(UnionTransactionType.REFUND); - params = service.refund("原交易查询流水号", "订单号", null,new BigDecimal("退款金额" )); + params = service.refund(new RefundOrder("原交易查询流水号", "订单号", null, new BigDecimal("退款金额" ))); /*-----------退货交易:后台资金类交易,有同步应答和后台通知应答------------------------------*/ diff --git a/pay-java-wx-youdian/pom.xml b/pay-java-wx-youdian/pom.xml index 0b77a06..7ce65c9 100644 --- a/pay-java-wx-youdian/pom.xml +++ b/pay-java-wx-youdian/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 pay-java-wx-youdian diff --git a/pay-java-wx-youdian/src/main/java/com/egzosn/pay/wx/youdian/api/WxYouDianPayService.java b/pay-java-wx-youdian/src/main/java/com/egzosn/pay/wx/youdian/api/WxYouDianPayService.java index 6fefb92..e28cb10 100644 --- a/pay-java-wx-youdian/src/main/java/com/egzosn/pay/wx/youdian/api/WxYouDianPayService.java +++ b/pay-java-wx-youdian/src/main/java/com/egzosn/pay/wx/youdian/api/WxYouDianPayService.java @@ -7,14 +7,13 @@ import com.egzosn.pay.common.bean.*; import com.egzosn.pay.common.bean.result.PayError; import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.http.HttpConfigStorage; -import com.egzosn.pay.common.util.MatrixToImageWriter; import com.egzosn.pay.common.util.Util; import com.egzosn.pay.common.util.sign.SignUtils; import com.egzosn.pay.common.util.str.StringUtils; import com.egzosn.pay.wx.youdian.bean.WxYoudianPayMessage; import com.egzosn.pay.wx.youdian.bean.YdPayError; import com.egzosn.pay.wx.youdian.bean.YoudianTransactionType; -import java.awt.image.BufferedImage; + import java.io.InputStream; import java.math.BigDecimal; import java.util.*; @@ -227,7 +226,7 @@ public class WxYouDianPayService extends BasePayService data = new TreeMap<>(); data.put("access_token", getAccessToken()); data.put("paymoney", Util.conversionAmount(order.getPrice()).toString()); - data.putAll(order.getAttr()); + data.putAll(order.getAttrs()); data = preOrderHandler(data, order); String apbNonce = SignUtils.randomStr(); String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset()); @@ -385,13 +384,14 @@ public class WxYouDianPayService extends BasePayService refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) { - return refund(new RefundOrder(tradeNo, outTradeNo,refundAmount, totalAmount)); - } - + /** + * 申请退款接口 + * + * @param refundOrder 退款订单信息 + * @return 返回支付方申请退款后的结果 + */ @Override public Map refund(RefundOrder refundOrder) { String apbNonce = SignUtils.randomStr(); @@ -413,11 +413,6 @@ public class WxYouDianPayService extends BasePayService refundquery(String tradeNo, String outTradeNo) { - return Collections.emptyMap(); - } - /** * 查询退款 * diff --git a/pay-java-wx/pom.xml b/pay-java-wx/pom.xml index 9e124f0..a305a8c 100644 --- a/pay-java-wx/pom.xml +++ b/pay-java-wx/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 pay-java-wx diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxPayService.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxPayService.java index f4b67de..feaff86 100644 --- a/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxPayService.java +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxPayService.java @@ -2,29 +2,25 @@ package com.egzosn.pay.wx.api; import com.alibaba.fastjson.JSONObject; import com.egzosn.pay.common.api.BasePayService; -import com.egzosn.pay.common.api.Callback; import com.egzosn.pay.common.bean.*; import com.egzosn.pay.common.bean.result.PayException; import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.http.HttpConfigStorage; import com.egzosn.pay.common.util.DateUtils; -import com.egzosn.pay.common.util.MatrixToImageWriter; import com.egzosn.pay.common.util.Util; +import com.egzosn.pay.common.util.XML; import com.egzosn.pay.common.util.sign.SignUtils; import com.egzosn.pay.common.util.sign.encrypt.RSA2; import com.egzosn.pay.common.util.str.StringUtils; -import com.egzosn.pay.wx.bean.WxPayError; -import com.egzosn.pay.wx.bean.WxPayMessage; -import com.egzosn.pay.wx.bean.WxTransactionType; -import com.egzosn.pay.common.util.XML; -import com.egzosn.pay.wx.bean.WxTransferType; -import java.awt.image.BufferedImage; +import com.egzosn.pay.wx.bean.*; + import java.io.IOException; import java.io.InputStream; -import java.math.BigDecimal; import java.net.URLEncoder; +import java.security.GeneralSecurityException; import java.util.*; +import static com.egzosn.pay.wx.api.WxConst.*; import static com.egzosn.pay.wx.bean.WxTransferType.*; /** @@ -32,34 +28,11 @@ import static com.egzosn.pay.wx.bean.WxTransferType.*; * * @author egan *
- *                 email egzosn@gmail.com
- *                 date 2016-5-18 14:09:01
- *                 
+ * email egzosn@gmail.com + * date 2016-5-18 14:09:01 + *
*/ -public class WxPayService extends BasePayService { - - - /** - * 微信请求地址 - */ - public static final String URI = "https://api.mch.weixin.qq.com/"; - /** - * 沙箱 - */ - public static final String SANDBOXNEW = "sandboxnew/"; - - public static final String SUCCESS = "SUCCESS"; - public static final String RETURN_CODE = "return_code"; - public static final String SIGN = "sign"; - public static final String CIPHER_ALGORITHM = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING"; - public static final String FAILURE = "failure"; - public static final String APPID = "appid"; - private static final String HMAC_SHA256 = "HMAC-SHA256"; - private static final String HMACSHA256 = "HMACSHA256"; - private static final String RETURN_MSG_CODE = "return_msg"; - private static final String RESULT_CODE = "result_code"; - private static final String MCH_ID = "mch_id"; - private static final String NONCE_STR = "nonce_str"; +public class WxPayService extends BasePayService implements WxRedPackService { /** @@ -118,17 +91,21 @@ public class WxPayService extends BasePayService { public boolean verify(Map params) { if (!(SUCCESS.equals(params.get(RETURN_CODE)) && SUCCESS.equals(params.get(RESULT_CODE)))) { - LOG.debug(String.format("微信支付异常:return_code=%s,参数集=%s", params.get(RETURN_CODE), params)); + if (LOG.isErrorEnabled()) { + LOG.error(String.format("微信支付异常:return_code=%s,参数集=%s", params.get(RETURN_CODE), params)); + } return false; } if (null == params.get(SIGN)) { - LOG.debug("微信支付异常:签名为空!out_trade_no=" + params.get("out_trade_no")); + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("微信支付异常:签名为空!%s=%s", OUT_TRADE_NO, params.get(OUT_TRADE_NO))); + } return false; } try { - return signVerify(params, (String) params.get(SIGN)) && verifySource((String) params.get("out_trade_no")); + return signVerify(params, (String) params.get(SIGN)) && verifySource((String) params.get(OUT_TRADE_NO)); } catch (PayErrorException e) { LOG.error(e); } @@ -203,9 +180,9 @@ public class WxPayService extends BasePayService { // 购买支付信息 parameters.put("body", order.getSubject()); // 购买支付信息 -// parameters.put("detail", order.getBody()); + setParameters(parameters, "detail", order); // 订单号 - parameters.put("out_trade_no", order.getOutTradeNo()); + parameters.put(OUT_TRADE_NO, order.getOutTradeNo()); parameters.put("spbill_create_ip", StringUtils.isEmpty(order.getSpbillCreateIp()) ? "192.168.1.150" : order.getSpbillCreateIp()); // 总金额单位为分 parameters.put("total_fee", Util.conversionCentAmount(order.getPrice())); @@ -222,7 +199,13 @@ public class WxPayService extends BasePayService { } ((WxTransactionType) order.getTransactionType()).setAttribute(parameters, order); - parameters.putAll(order.getAttr()); + //可覆盖参数 +/* setParameters(parameters, "notify_url", order); + setParameters(parameters, "goods_tag", order); + setParameters(parameters, "limit_pay", order); + setParameters(parameters, "receipt", order); + setParameters(parameters, "product_id", order);*/ + parameters.putAll(order.getAttrs()); parameters = preOrderHandler(parameters, order); setSign(parameters); @@ -276,7 +259,6 @@ public class WxPayService extends BasePayService { params.put("noncestr", result.get(NONCE_STR)); params.put("package", "Sign=WXPay"); } - params = preOrderHandler(params, order); String paySign = createSign(SignUtils.parameterText(params), payConfigStorage.getInputCharset()); params.put(SIGN, paySign); return params; @@ -495,30 +477,6 @@ public class WxPayService extends BasePayService { return secondaryInterface(transactionId, outTradeNo, WxTransactionType.REVERSE); } - /** - * 退款 - * - * @param transactionId 微信订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @return 返回支付方申请退款后的结果 - * @see #refund(RefundOrder, Callback) - */ - @Deprecated - @Override - public Map refund(String transactionId, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) { - - return refund(new RefundOrder(transactionId, outTradeNo, refundAmount, totalAmount)); - } - - - private Map setParameters(Map parameters, String key, String value) { - if (StringUtils.isNotEmpty(value)) { - parameters.put(key, value); - } - return parameters; - } /** * 申请退款接口 @@ -532,7 +490,7 @@ public class WxPayService extends BasePayService { Map parameters = getPublicParameters(); setParameters(parameters, "transaction_id", refundOrder.getTradeNo()); - setParameters(parameters, "out_trade_no", refundOrder.getOutTradeNo()); + setParameters(parameters, OUT_TRADE_NO, refundOrder.getOutTradeNo()); setParameters(parameters, "out_refund_no", refundOrder.getRefundNo()); parameters.put("total_fee", Util.conversionCentAmount(refundOrder.getTotalAmount())); parameters.put("refund_fee", Util.conversionCentAmount(refundOrder.getRefundAmount())); @@ -547,18 +505,6 @@ public class WxPayService extends BasePayService { } - /** - * 查询退款 - * - * @param transactionId 支付平台订单号 - * @param outTradeNo 商户单号 - * @return 返回支付方查询退款后的结果 - */ - @Override - public Map refundquery(String transactionId, String outTradeNo) { - return secondaryInterface(transactionId, outTradeNo, WxTransactionType.REFUNDQUERY); - } - /** * 查询退款 * @@ -571,7 +517,7 @@ public class WxPayService extends BasePayService { //获取公共参数 Map parameters = getPublicParameters(); setParameters(parameters, "transaction_id", refundOrder.getTradeNo()); - setParameters(parameters, "out_trade_no", refundOrder.getOutTradeNo()); + setParameters(parameters, OUT_TRADE_NO, refundOrder.getOutTradeNo()); setParameters(parameters, "out_refund_no", refundOrder.getRefundNo()); //设置签名 setSign(parameters); @@ -638,7 +584,7 @@ public class WxPayService extends BasePayService { //获取公共参数 Map parameters = getPublicParameters(); - setParameters(parameters, "out_trade_no", outTradeNoBillType); + setParameters(parameters, OUT_TRADE_NO, outTradeNoBillType); setParameters(parameters, "transaction_id", (String) transactionIdOrBillDate); //设置签名 setSign(parameters); @@ -651,13 +597,12 @@ public class WxPayService extends BasePayService { * @param order 转账订单 *
      *
-     *                                        注意事项:
-     *                                        ◆ 当返回错误码为“SYSTEMERROR”时,请不要更换商户订单号,一定要使用原商户订单号重试,否则可能造成重复支付等资金风险。
-     *                                        ◆ XML具有可扩展性,因此返回参数可能会有新增,而且顺序可能不完全遵循此文档规范,如果在解析回包的时候发生错误,请商户务必不要换单重试,请商户联系客服确认付款情况。如果有新回包字段,会更新到此API文档中。
-     *                                        ◆ 因为错误代码字段err_code的值后续可能会增加,所以商户如果遇到回包返回新的错误码,请商户务必不要换单重试,请商户联系客服确认付款情况。如果有新的错误码,会更新到此API文档中。
-     *                                        ◆ 错误代码描述字段err_code_des只供人工定位问题时做参考,系统实现时请不要依赖这个字段来做自动化处理。
-     *
-     *                                        
+ * 注意事项: + * ◆ 当返回错误码为“SYSTEMERROR”时,请不要更换商户订单号,一定要使用原商户订单号重试,否则可能造成重复支付等资金风险。 + * ◆ XML具有可扩展性,因此返回参数可能会有新增,而且顺序可能不完全遵循此文档规范,如果在解析回包的时候发生错误,请商户务必不要换单重试,请商户联系客服确认付款情况。如果有新回包字段,会更新到此API文档中。 + * ◆ 因为错误代码字段err_code的值后续可能会增加,所以商户如果遇到回包返回新的错误码,请商户务必不要换单重试,请商户联系客服确认付款情况。如果有新的错误码,会更新到此API文档中。 + * ◆ 错误代码描述字段err_code_des只供人工定位问题时做参考,系统实现时请不要依赖这个字段来做自动化处理。 + *
* @return 对应的转账结果 */ @Override @@ -760,7 +705,7 @@ public class WxPayService extends BasePayService { public String keyPublic(String content) { try { return RSA2.encrypt(content, payConfigStorage.getKeyPublic(), CIPHER_ALGORITHM, payConfigStorage.getInputCharset()); - } catch (Exception e) { + } catch (GeneralSecurityException | IOException e) { throw new PayErrorException(new WxPayError(FAILURE, e.getLocalizedMessage())); } } @@ -775,4 +720,70 @@ public class WxPayService extends BasePayService { public PayMessage createMessage(Map message) { return WxPayMessage.create(message); } + + /** + * 微信发红包 + * + * @param redpackOrder 红包实体 + * @return 返回发红包实体后的结果 + * @author: faymanwang 1057438332@qq.com + */ + @Override + public Map sendredpack(RedpackOrder redpackOrder) { + Map parameters = new TreeMap(); + redPackParam(redpackOrder, parameters); + if (WxSendredpackType.SENDGROUPREDPACK == redpackOrder.getTransferType()) { + //现金红包,小程序红包默认传1.裂变红包取传入值,且需要大于3 + parameters.put("total_num", Math.max(redpackOrder.getTotalNum(), 3)); + parameters.put("amt_type", "ALL_RAND"); + } else if (WxSendredpackType.SENDMINIPROGRAMHB == redpackOrder.getTransferType()) { + parameters.put("notify_way", "MINI_PROGRAM_JSAPI"); + } + + parameters.put(SIGN, createSign(SignUtils.parameterText(parameters, "&", SIGN), payConfigStorage.getInputCharset())); + return requestTemplate.postForObject(getReqUrl(redpackOrder.getTransferType()), XML.getMap2Xml(parameters), JSONObject.class); + } + + + /** + * 查询红包记录 + * 用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包 + * 查询红包记录API只支持查询30天内的红包订单,30天之前的红包订单请登录商户平台查询。 + * + * @param mchBillno 商户发放红包的商户订单号 + * @return 返回查询结果 + * @author: faymanwang 1057438332@qq.com + */ + @Override + public Map gethbinfo(String mchBillno) { + Map parameters = this.getPublicParameters(); + parameters.put("mch_billno", mchBillno); + parameters.put("bill_type", "MCHT"); + parameters.put(SIGN, createSign(SignUtils.parameterText(parameters, "&", SIGN), payConfigStorage.getInputCharset())); + return requestTemplate.postForObject(getReqUrl(WxSendredpackType.GETHBINFO), XML.getMap2Xml(parameters), JSONObject.class); + } + + /** + * 微信红包构造参数方法 + * + * @param redpackOrder 红包实体 + * @param parameters 接收参数 + */ + private void redPackParam(RedpackOrder redpackOrder, Map parameters) { + parameters.put(NONCE_STR, SignUtils.randomStr()); + parameters.put(MCH_ID, payConfigStorage.getPid()); + parameters.put("wxappid", payConfigStorage.getAppid()); + parameters.put("send_name", redpackOrder.getSendName()); + parameters.put("re_openid", redpackOrder.getReOpenid()); + parameters.put("mch_billno", redpackOrder.getMchBillno()); + parameters.put("total_amount", Util.conversionCentAmount(redpackOrder.getTotalAmount())); + parameters.put("total_num", 1); + parameters.put("wishing", redpackOrder.getWishing()); + parameters.put("client_ip", StringUtils.isNotEmpty(redpackOrder.getIp()) ? redpackOrder.getIp() : "192.168.0.1"); + parameters.put("act_name", redpackOrder.getActName()); + parameters.put("remark", redpackOrder.getRemark()); + if (StringUtils.isNotEmpty(redpackOrder.getSceneId())) { + parameters.put("scene_id", redpackOrder.getSceneId()); + } + } } diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxRedPackService.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxRedPackService.java new file mode 100644 index 0000000..341f3a8 --- /dev/null +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxRedPackService.java @@ -0,0 +1,33 @@ +package com.egzosn.pay.wx.api; + +import com.egzosn.pay.wx.bean.RedpackOrder; + +import java.util.Map; + +/** + * 微信红包服务 + * @author egan + *
+ * email egzosn@gmail.com
+ * date 2020/5/17 22:24
+ * 
+ */ +public interface WxRedPackService { + /** + * 微信发红包 + * + * @param redpackOrder 红包实体 + * @return 返回发红包实体后的结果 + */ + Map sendredpack(RedpackOrder redpackOrder); + + /** + * 查询红包记录 + * 用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包 + * 查询红包记录API只支持查询30天内的红包订单,30天之前的红包订单请登录商户平台查询。 + * + * @param mchBillno 商户发放红包的商户订单号 + * @return 返回查询结果 + */ + Map gethbinfo(String mchBillno); +} diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/RedpackOrder.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/RedpackOrder.java new file mode 100644 index 0000000..300c85e --- /dev/null +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/RedpackOrder.java @@ -0,0 +1,122 @@ +package com.egzosn.pay.wx.bean; + +import com.egzosn.pay.common.bean.TransferOrder; + +import java.math.BigDecimal; + +/** + * @description: 发红包订单 + * @author: 保网 faymanwang 1057438332@qq.com + * @time: 2020/5/15 12:40 + */ +public class RedpackOrder extends TransferOrder { + + + /** + * 商户订单号(每个订单号必须唯一。取值范围:0~9,a~z,A~Z) + * 接口根据商户订单号支持重入,如出现超时可再调用 + * @return 商户订单号 + */ + public String getMchBillno() { + return getOutNo(); + } + + public void setMchBillno(String mchBillno) { + setOutNo(mchBillno); + } + + /** + * 商户名称:红包发送者名称 + * @return 红包发送者名称 + */ + public String getSendName() { + return getPayerName(); + } + + public void setSendName(String sendName) { + super.setPayerName(sendName); + } + + /** + * 用户openid + * @return 用户openid + */ + public String getReOpenid() { + return getPayeeAccount(); + } + + public void setReOpenid(String reOpenid) { + super.setPayeeAccount(reOpenid); + } + + /** + * 付款金额 每个红包金额必须在默认额度内(默认大于1元,小于200元,可在产品设置中自行申请调高额度) + * @return 付款金额 + */ + public BigDecimal getTotalAmount() { + return getAmount(); + } + + public void setTotalAmount(BigDecimal totalAmount) { + super.setAmount(totalAmount); + } + /** + * 红包发放总人数 + * 普通红包:1 + * 裂变:必须介于(包括)3到20之间 + */ + public int getTotalNum() { + Object totalNum = getAttr("total_num"); + return null == totalNum ? 1 : (Integer)totalNum; + } + + public void setTotalNum(int totalNum) { + addAttr("total_num", totalNum); + } + /** + * 红包祝福语 + */ + public String getWishing() { + return (String) getAttr("wishing"); + + } + + public void setWishing(String wishing) { + addAttr("wishing", wishing); + } + + + /** + * 活动名称 + */ + public String getActName() { + return (String) getAttr("act_name"); + } + + public void setActName(String actName) { + addAttr("act_name", actName); + } + + public String getSceneId() { + return (String) getAttr("scene_id"); + } + /** + * 发放红包使用场景,红包金额大于200或者小于1元时必传 + * PRODUCT_1:商品促销 + * PRODUCT_2:抽奖 + * PRODUCT_3:虚拟物品兑奖 + * PRODUCT_4:企业内部福利 + * PRODUCT_5:渠道分润 + * PRODUCT_6:保险回馈 + * PRODUCT_7:彩票派奖 + * PRODUCT_8:税务刮奖 + */ + public void setSceneId(String sceneId) { + addAttr("scene_id", sceneId); + } + + + public void setTransferType(WxSendredpackType transferType) { + super.setTransferType(transferType); + } +} diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/WxSendredpackType.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/WxSendredpackType.java new file mode 100644 index 0000000..248e6f4 --- /dev/null +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/WxSendredpackType.java @@ -0,0 +1,51 @@ +package com.egzosn.pay.wx.bean; + +import com.egzosn.pay.common.bean.TransferOrder; +import com.egzosn.pay.common.bean.TransferType; + +import java.util.Map; + +/** + * @description: 红包交易类型 + * @author faymanwang + * @time: 2020/5/14 20:11 + */ +public enum WxSendredpackType implements TransferType { + /** + * 现金红包-发放红包接口 + */ + SENDREDPACK("mmpaymkttransfers/sendredpack"), + /** + * 现金红包-发放裂变红包 + */ + SENDGROUPREDPACK("mmpaymkttransfers/sendgroupredpack"), + /** + * 现金红包-查询红包记录 + */ + GETHBINFO ("mmpaymkttransfers/gethbinfo"), + /** + * 小程序 + */ + SENDMINIPROGRAMHB ("mmpaymkttransfers/sendminiprogramhb") + + ; + + WxSendredpackType(String method) { + this.method = method; + } + private String method; + + @Override + public String getType() { + return this.name(); + } + @Override + public String getMethod() { + return this.method; + } + + @Override + public Map setAttr(Map attr, TransferOrder order) { + return attr; + } +} diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/WxTransferType.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/WxTransferType.java index e0f2760..1983c55 100644 --- a/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/WxTransferType.java +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/bean/WxTransferType.java @@ -1,7 +1,10 @@ package com.egzosn.pay.wx.bean; +import com.egzosn.pay.common.bean.TransferOrder; import com.egzosn.pay.common.bean.TransferType; +import java.util.Map; + /** * 微信转账类型 * @author egan @@ -41,4 +44,10 @@ public enum WxTransferType implements TransferType{ public String getMethod() { return this.method; } + + + @Override + public Map setAttr(Map attr, TransferOrder order) { + return attr; + } } diff --git a/pay-java-wx/src/test/java/PayTest.java b/pay-java-wx/src/test/java/PayTest.java index d793613..e0a604b 100644 --- a/pay-java-wx/src/test/java/PayTest.java +++ b/pay-java-wx/src/test/java/PayTest.java @@ -1,9 +1,12 @@ -import com.egzosn.pay.common.api.PayService; +import com.egzosn.pay.common.bean.CertStoreType; import com.egzosn.pay.common.bean.MethodType; import com.egzosn.pay.common.bean.PayOrder; +import com.egzosn.pay.common.http.HttpConfigStorage; import com.egzosn.pay.wx.api.WxPayConfigStorage; import com.egzosn.pay.wx.api.WxPayService; +import com.egzosn.pay.wx.bean.RedpackOrder; +import com.egzosn.pay.wx.bean.WxSendredpackType; import com.egzosn.pay.wx.bean.WxTransactionType; import java.awt.image.BufferedImage; @@ -39,7 +42,7 @@ public class PayTest { //是否为测试账号,沙箱环境 此处暂未实现 wxPayConfigStorage.setTest(true); //支付服务 - PayService service = new WxPayService(wxPayConfigStorage); + WxPayService service = new WxPayService(wxPayConfigStorage); //支付订单基础信息 PayOrder payOrder = new PayOrder("订单title", "摘要", new BigDecimal(0.01) , UUID.randomUUID().toString().replace("-", "")); /*-----------扫码付-------------------*/ @@ -84,5 +87,32 @@ public class PayTest { /*-----------回调处理-------------------*/ + + HttpConfigStorage httpConfigStorage = new HttpConfigStorage(); + //ssl 退款证书相关 + httpConfigStorage.setKeystore("D:/work/pay/src/main/resources/certificates/1220429901_apiclient_cert.p12"); + httpConfigStorage.setStorePassword("默认商户号"); + //设置ssl证书对应的存储方式,这里默认为文件地址 + httpConfigStorage.setCertStoreType(CertStoreType.PATH); + service.setRequestTemplateConfigStorage(httpConfigStorage); + + RedpackOrder redpackOrder = new RedpackOrder(); + + redpackOrder.setSendName("测试"); + //faymanwang- opid + redpackOrder.setReOpenid("om3rxjhD1rhGrP6oLydMgLcN5n10"); + //红包流水 + redpackOrder.setMchBillno("red202005181"); + redpackOrder.setTotalAmount(new BigDecimal(1.5)); + redpackOrder.setSceneId("PRODUCT_1"); + //现金红包,小程序默认为1 裂变默认为3 + redpackOrder.setTotalNum(4); + redpackOrder.setWishing("请勿领取"); + redpackOrder.setActName("请勿领取测试红包"); + redpackOrder.setRemark("测试支付-by fayman"); + //设置发红包方式 + redpackOrder.setTransferType(WxSendredpackType.SENDGROUPREDPACK); + Map sendredpack = service.sendredpack(redpackOrder); + System.out.println(sendredpack); } } diff --git a/pay-java-yiji/pom.xml b/pay-java-yiji/pom.xml index bb8b23e..44ba156 100644 --- a/pay-java-yiji/pom.xml +++ b/pay-java-yiji/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.13.1 + 2.13.2-SNAPSHOT 4.0.0 diff --git a/pay-java-yiji/src/main/java/com/egzosn/pay/yiji/api/YiJiPayService.java b/pay-java-yiji/src/main/java/com/egzosn/pay/yiji/api/YiJiPayService.java index 1428b15..232d126 100644 --- a/pay-java-yiji/src/main/java/com/egzosn/pay/yiji/api/YiJiPayService.java +++ b/pay-java-yiji/src/main/java/com/egzosn/pay/yiji/api/YiJiPayService.java @@ -11,8 +11,6 @@ import com.egzosn.pay.common.util.sign.SignUtils; import com.egzosn.pay.common.util.str.StringUtils; import com.egzosn.pay.yiji.bean.YiJiTransactionType; -import java.awt.image.BufferedImage; -import java.math.BigDecimal; import java.util.Collections; import java.util.Date; import java.util.Map; @@ -175,7 +173,7 @@ public class YiJiPayService extends BasePayService { if (null != order.getCurType()){ orderInfo.put("currency", order.getCurType()); } - orderInfo.putAll(order.getAttr()); + orderInfo.putAll(order.getAttrs()); return preOrderHandler(orderInfo, order); } @@ -294,24 +292,6 @@ public class YiJiPayService extends BasePayService { - /** - * 申请退款接口 - * 废弃 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @param refundAmount 退款金额 - * @param totalAmount 总金额 - * @return 返回支付方申请退款后的结果 - * @see #refund(RefundOrder, com.egzosn.pay.common.api.Callback) - * @deprecated 版本替代 {@link #refund(RefundOrder, com.egzosn.pay.common.api.Callback)} - */ - @Deprecated - @Override - public Map refund(String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) { - return refund(new RefundOrder(tradeNo, outTradeNo, refundAmount, totalAmount)); - } - /** * 申请退款接口 @@ -331,18 +311,6 @@ public class YiJiPayService extends BasePayService { return getHttpRequestTemplate().postForObject(getReqUrl(YiJiTransactionType.tradeRefund), orderInfo, JSONObject.class); } - /** - * 查询退款 - * - * @param tradeNo 支付平台订单号 - * @param outTradeNo 商户单号 - * @return 返回支付方查询退款后的结果 - */ - @Override - public Map refundquery(String tradeNo, String outTradeNo) { - return Collections.emptyMap(); - } - /** * 查询退款 * diff --git a/pom.xml b/pom.xml index cb8f1ba..f2ecd1f 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.egzosn pay-java-parent pom - 2.13.1 + 2.13.2-SNAPSHOT Pay Java - Parent Pay Java Parent @@ -34,6 +34,11 @@ zhangchenghui.dev@gmail.com https://github.com/objcoding + + hocgin + hocgin@gmail.com + https://github.com/hocgin + scm:git:https://github.com/egzosn/pay-java-parent.git @@ -52,17 +57,19 @@ pay-java-payoneer pay-java-paypal pay-java-yiji + pay-java-baidu pay-java-demo - 2.13.1 + 2.13.2-SNAPSHOT 4.5.4 1.2.17 1.2.58 3.3.1 + 5.5.1 @@ -103,6 +110,11 @@ core ${zxing.version} + + org.junit.jupiter + junit-jupiter + ${junit.version} + @@ -128,68 +140,85 @@ utf-8 - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.3 - true - - ossrh - https://oss.sonatype.org/ - false - - - - org.apache.maven.plugins - maven-release-plugin - 2.5.1 - - false - false - release - deploy - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.3 - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.1.0 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - install - - sign - - - - + + + + + local + + true + + + + proc + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.3 + true + + ossrh + https://oss.sonatype.org/ + false + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.1 + + false + false + release + deploy + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.3 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.1.0 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + install + + sign + + + + + + + + \ No newline at end of file