diff --git a/pay-java-demo/src/main/java/in/egan/pay/demo/controller/PayController.java b/pay-java-demo/src/main/java/in/egan/pay/demo/controller/PayController.java index 514c04f..9a47a83 100644 --- a/pay-java-demo/src/main/java/in/egan/pay/demo/controller/PayController.java +++ b/pay-java-demo/src/main/java/in/egan/pay/demo/controller/PayController.java @@ -157,7 +157,7 @@ public class PayController{ PayResponse payResponse = service.getPayResponse(payId); - return payResponse.getService().query("2017012921001004530273937216", "8a2950f959cf08740159ea0666fc04bd"); + return payResponse.getService().query("4009922001201703072549284850", "8a2950f95a8e17e1015aa7a6eb872ccb"); } /** @@ -165,8 +165,8 @@ public class PayController{ * @param payId * @return */ - @RequestMapping("query1") - public Map query1(Integer payId, String transactionType) { + @RequestMapping("secondaryInterface") + public Map secondaryInterface(Integer payId, String transactionType) { PayResponse payResponse = service.getPayResponse(payId); TransactionType type = PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType); return payResponse.getService().secondaryInterface("2017012921001004530273937216", "8a2950f959cf08740159ea0666fc04bd", type, new Callback>() { diff --git a/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayService.java b/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayService.java index 2276846..8455717 100644 --- a/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayService.java +++ b/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayService.java @@ -9,7 +9,9 @@ import in.egan.pay.common.bean.MethodType; import in.egan.pay.common.bean.PayOrder; import in.egan.pay.common.bean.PayOutMessage; import in.egan.pay.common.bean.TransactionType; +import in.egan.pay.common.bean.result.PayException; import in.egan.pay.common.exception.PayErrorException; +import in.egan.pay.common.http.ClientHttpRequest; import in.egan.pay.common.http.HttpConfigStorage; import in.egan.pay.common.util.MatrixToImageWriter; import in.egan.pay.common.util.sign.SignUtils; @@ -22,6 +24,8 @@ import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.*; /** @@ -37,6 +41,8 @@ public class WxPayService extends BasePayService { public final static String httpsVerifyUrl = "https://gw.tenpay.com/gateway"; + + public final static String uri = "https://api.mch.weixin.qq.com/"; public final static String unifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; // public final static String orderqueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; @@ -59,6 +65,11 @@ public class WxPayService extends BasePayService { return httpsVerifyUrl + "/verifynotifyid.xml"; } + private String getUrl(TransactionType transactionType){ + + return uri + transactionType.getMethod(); + } + @Override public boolean verify(Map params) { if (!"SUCCESS".equals(params.get("return_code"))){ @@ -101,6 +112,20 @@ public class WxPayService extends BasePayService { return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, "&key=" + payConfigStorage.getKeyPublic(), payConfigStorage.getInputCharset()); } + /** + * 获取公共参数 + * @return + */ + private Map getPublicParameters() { + + Map parameters = new TreeMap(); + parameters.put("appid", payConfigStorage.getAppid()); + parameters.put("mch_id", payConfigStorage.getPartner()); + parameters.put("nonce_str", SignUtils.randomStr()); + return parameters; + + + } @@ -117,10 +142,10 @@ public class WxPayService extends BasePayService { // Map results = new HashMap(); ////统一下单 - SortedMap parameters = new TreeMap(); - parameters.put("appid", payConfigStorage.getAppid()); + Map parameters = getPublicParameters(); + /* parameters.put("appid", payConfigStorage.getAppid()); parameters.put("mch_id", payConfigStorage.getPartner()); - parameters.put("nonce_str", SignUtils.randomStr()); + parameters.put("nonce_str", SignUtils.randomStr());*/ parameters.put("body", order.getSubject());// 购买支付信息 parameters.put("notify_url", payConfigStorage.getNotifyUrl()); parameters.put("out_trade_no", order.getOutTradeNo());// 订单号 @@ -137,7 +162,7 @@ public class WxPayService extends BasePayService { String requestXML = XML.getMap2Xml(parameters); log.debug("requestXML:" + requestXML); /////////APP端调起支付的参数列表 - JSONObject result = getHttpRequestTemplate().postForObject(unifiedOrderUrl, requestXML, JSONObject.class); + JSONObject result = requestTemplate.postForObject(getUrl(order.getTransactionType()), requestXML, JSONObject.class); if (!"SUCCESS".equals(result.get("return_code"))){ throw new PayErrorException(new WxPayError(result.getString("return_code"), result.getString("return_msg"), result.toJSONString())); @@ -149,7 +174,7 @@ public class WxPayService extends BasePayService { SortedMap params = new TreeMap(); params.put("appid", payConfigStorage.getAppid()); - params.put("partnerid", payConfigStorage.getPartner()); + params.put("partnerid", payConfigStorage.getPid()); params.put("prepayid", result.get("prepay_id")); params.put("timestamp", System.currentTimeMillis() / 1000); params.put("noncestr", result.get("nonce_str")/*WxpayCore.genNonceStr()*/); @@ -167,7 +192,17 @@ public class WxPayService extends BasePayService { } - + /** + * 生成并设置签名 + * @param parameters 请求参数 + * @return + */ + private Map setSign(Map parameters){ + parameters.put("sign_type", payConfigStorage.getSignType()); + String sign = createSign( SignUtils.parameterText(parameters, "&", "sign", "appId"), payConfigStorage.getInputCharset()); + parameters.put("sign", sign); + return parameters; + } /** * 签名 @@ -220,65 +255,152 @@ public class WxPayService extends BasePayService { return MatrixToImageWriter.writeInfoToJpgBuff((String) orderInfo.get("code_url")); } + /** + * 交易查询接口 + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @return + */ @Override public Map query(String tradeNo, String outTradeNo) { - return null; + + return query(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } + /** + * + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @param callback 处理器 + * @param + * @return + */ @Override public T query(String tradeNo, String outTradeNo, Callback callback) { - return null; + + return secondaryInterface(tradeNo, outTradeNo, WxTransactionType.QUERY, callback); } + @Override public Map close(String tradeNo, String outTradeNo) { - return null; + + return close(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } @Override public T close(String tradeNo, String outTradeNo, Callback callback) { - return null; + return secondaryInterface(tradeNo, outTradeNo, WxTransactionType.CLOSE, callback); } @Override public Map refund(String tradeNo, String outTradeNo) { - return null; + + return refund(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } @Override public T refund(String tradeNo, String outTradeNo, Callback callback) { - return null; + return secondaryInterface(tradeNo, outTradeNo, WxTransactionType.REFUND, callback); } @Override public Map refundquery(String tradeNo, String outTradeNo) { - return null; + return refundquery(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } @Override public T refundquery(String tradeNo, String outTradeNo, Callback callback) { - return null; + return secondaryInterface(tradeNo, outTradeNo, WxTransactionType.REFUNDQUERY, callback); } + /** + * 目前只支持日账单 + * @param billDate 账单类型,商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型:trade、signcustomer;trade指商户基于支付宝交易收单的业务账单;signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单; + * @param billType 账单时间:日账单格式为yyyy-MM-dd,月账单格式为yyyy-MM。 + * @return + */ @Override - public Object downloadbill(Date billDate, String billType) { - return null; + public Map downloadbill(Date billDate, String billType) { + return downloadbill(billDate, billType, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } + /** + * 目前只支持日账单 + * @param billDate 账单时间:具体请查看对应支付平台 + * @param billType 账单类型,具体请查看对应支付平台 + * @param callback 处理器 + * @param + * @return + */ @Override public T downloadbill(Date billDate, String billType, Callback callback) { - return null; - } + //获取公共参数 + Map parameters = getPublicParameters(); + + Map bizContent = new TreeMap<>(); + bizContent.put("bill_type", billType); + //目前只支持日账单 + DateFormat df = new SimpleDateFormat("yyyyMMdd"); + df.setTimeZone(TimeZone.getTimeZone("GMT+8")); + bizContent.put("bill_date", df.format(billDate)); + + //设置签名 + setSign(parameters); + return callback.perform(requestTemplate.postForObject(getUrl(WxTransactionType.DOWNLOADBILL), XML.getMap2Xml(parameters), JSONObject.class)); + } @Override - public T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback callback) { - return null; + public T secondaryInterface(Object transactionIdOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback callback) { + + if (transactionType == WxTransactionType.DOWNLOADBILL){ + if (transactionIdOrBillDate instanceof Date){ + return downloadbill((Date) transactionIdOrBillDate, outTradeNoBillType, callback); + } + throw new PayErrorException(new PayException("failure", "非法类型异常:" + transactionIdOrBillDate.getClass())); + } + + if (!(transactionIdOrBillDate instanceof String)){ + throw new PayErrorException(new PayException("failure", "非法类型异常:" + transactionIdOrBillDate.getClass())); + } + + //获取公共参数 + Map parameters = getPublicParameters(); + if (null != transactionIdOrBillDate){ + parameters.put("transaction_id", transactionIdOrBillDate); + }else { + parameters.put("out_trade_no", outTradeNoBillType); + } + //设置签名 + setSign(parameters); + return callback.perform(requestTemplate.postForObject(getUrl(transactionType), XML.getMap2Xml(parameters) , JSONObject.class)); } - @Override - public PayConfigStorage getPayConfigStorage() { - return payConfigStorage; - } } diff --git a/pay-java-wx/src/main/java/in/egan/pay/wx/bean/WxTransactionType.java b/pay-java-wx/src/main/java/in/egan/pay/wx/bean/WxTransactionType.java index 880a0ed..839227d 100644 --- a/pay-java-wx/src/main/java/in/egan/pay/wx/bean/WxTransactionType.java +++ b/pay-java-wx/src/main/java/in/egan/pay/wx/bean/WxTransactionType.java @@ -10,16 +10,40 @@ import in.egan.pay.common.bean.TransactionType; */ public enum WxTransactionType implements TransactionType { //公众号支付 - JSAPI,//暂未接触 + JSAPI("pay/unifiedorder"),//暂未接触 //扫码付 - NATIVE, + NATIVE("pay/unifiedorder"), //移动支付 - APP, - //刷卡付 - MICROPAY;//暂未接触 + APP("pay/unifiedorder"), + //刷卡付,暂未接触 + MICROPAY("pay/unifiedorder"), + // TODO 2017/3/8 19:14 author: egan 交易辅助接口 + //查询订单 + QUERY("pay/orderquery"), + //关闭订单 + CLOSE("pay/closeorder"), + //申请退款 + REFUND("secapi/pay/refund"), + //查询退款 + REFUNDQUERY("pay/refundquery"), + //下载对账单 + DOWNLOADBILL("pay/downloadbill"), + //不知道交易类型,主要用于回调通知,回调后不清楚交易类型,以此定义 + UNAWARE("UNAWARE") + ; + + WxTransactionType(String method) { + this.method = method; + } + + private String method; @Override public String getType() { return this.name(); } + @Override + public String getMethod() { + return this.method; + } }