Skip to content

Commit d253bde

Browse files
committed
Merge pull request #269 from liukaitj/develop
Develop
2 parents b5986cf + 5f75a03 commit d253bde

File tree

3 files changed

+416
-10
lines changed

3 files changed

+416
-10
lines changed

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -726,8 +726,9 @@ public interface WxMpService {
726726
* @param parameters
727727
* the required or optional parameters
728728
* @return
729+
* @throws WxErrorException
729730
*/
730-
Map<String, String> getJSSDKPayInfo(Map<String, String> parameters);
731+
Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) throws WxErrorException;
731732

732733
/**
733734
* 该接口调用“统一下单”接口,并拼装JSSDK发起支付请求需要的参数
@@ -740,10 +741,11 @@ public interface WxMpService {
740741
* @param ip 发起支付的客户端IP
741742
* @param notifyUrl 通知地址
742743
* @return
744+
* @throws WxErrorException
743745
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getJSSDKPayInfo(Map<String, String>) instead
744746
*/
745747
@Deprecated
746-
Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String notifyUrl);
748+
Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String notifyUrl) throws WxErrorException;
747749

748750
/**
749751
* 该接口提供所有微信支付订单的查询,当支付通知处理异常戒丢失的情冴,商户可以通过该接口查询订单支付状态。
@@ -761,6 +763,20 @@ public interface WxMpService {
761763
*/
762764
WxMpPayCallback getJSSDKCallbackData(String xmlData);
763765

766+
/**
767+
* 微信支付-申请退款
768+
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
769+
* @param parameters 需要传入的退款参数的Map。以下几项为参数的必须项:<br/>
770+
* <li/> transaction_id
771+
* <li/> out_trade_no (仅在上述transaction_id为空时是必须项)
772+
* <li/> out_refund_no
773+
* <li/> total_fee
774+
* <li/> refund_fee
775+
* @return 退款操作结果
776+
* @throws WxErrorException
777+
*/
778+
public WxMpPayRefundResult refundPay(Map<String, String> parameters) throws WxErrorException;
779+
764780
/**
765781
* <pre>
766782
* 计算Map键值对是否和签名相符,
@@ -812,6 +828,7 @@ public interface WxMpService {
812828
*
813829
* @param optionalSignParam 参与签名的参数数组。
814830
* 可以为下列字段:app_id, card_id, card_type, code, openid, location_id
831+
* </br>注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空
815832
* @return 卡券Api签名对象
816833
*/
817834
public WxCardApiSignature createCardApiSignature(String... optionalSignParam) throws
@@ -839,10 +856,12 @@ public WxMpCardResult queryCardCode(String cardId, String code, boolean checkCon
839856
/**
840857
* 卡券Code核销。核销失败会抛出异常
841858
* @param code 单张卡券的唯一标准
842-
* @return
843-
* @throws WxErrorException
844-
*/
845-
public void consumeCardCode(String code) throws WxErrorException;
859+
* @param cardId 当自定义Code卡券时需要传入card_id
860+
* @return 调用返回的JSON字符串。
861+
* <br>可用 com.google.gson.JsonParser#parse 等方法直接取JSON串中的errcode等信息。
862+
* @throws WxErrorException
863+
*/
864+
public String consumeCardCode(String code, String cardId) throws WxErrorException;
846865

847866
/**
848867
* 卡券Mark接口。
@@ -856,4 +875,15 @@ public WxMpCardResult queryCardCode(String cardId, String code, boolean checkCon
856875
*/
857876
public void markCardCode(String code, String cardId, String openId, boolean isMark) throws
858877
WxErrorException;
878+
879+
/**
880+
* 查看卡券详情接口
881+
* 详见 https://mp.weixin.qq.com/wiki/14/8dd77aeaee85f922db5f8aa6386d385e.html#.E6.9F.A5.E7.9C.8B.E5.8D.A1.E5.88.B8.E8.AF.A6.E6.83.85
882+
* @param cardId 卡券的ID
883+
* @return 返回的卡券详情JSON字符串
884+
* <br> [注] 由于返回的JSON格式过于复杂,难以定义其对应格式的Bean并且难以维护,因此只返回String格式的JSON串。
885+
* <br> 可由 com.google.gson.JsonParser#parse 等方法直接取JSON串中的某个字段。
886+
* @throws WxErrorException
887+
*/
888+
public String getCardDetail(String cardId) throws WxErrorException;
859889
}

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import me.chanjar.weixin.mp.bean.result.WxMpMaterialVideoInfoResult;
5757
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
5858
import me.chanjar.weixin.mp.bean.result.WxMpPayCallback;
59+
import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult;
5960
import me.chanjar.weixin.mp.bean.result.WxMpPayResult;
6061
import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult;
6162
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
@@ -97,6 +98,7 @@
9798
import com.google.gson.JsonArray;
9899
import com.google.gson.JsonElement;
99100
import com.google.gson.JsonObject;
101+
import com.google.gson.JsonParser;
100102
import com.google.gson.internal.Streams;
101103
import com.google.gson.reflect.TypeToken;
102104
import com.google.gson.stream.JsonReader;
@@ -881,7 +883,8 @@ private void checkParameters(Map<String, String> parameters) {
881883
}
882884

883885
@Override
884-
public Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String callbackUrl) {
886+
public Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String callbackUrl)
887+
throws WxErrorException {
885888
Map<String, String> packageParams = new HashMap<String, String>();
886889
packageParams.put("appid", wxMpConfigStorage.getAppId());
887890
packageParams.put("mch_id", wxMpConfigStorage.getPartnerId());
@@ -897,8 +900,21 @@ public Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, dou
897900
}
898901

899902
@Override
900-
public Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) {
903+
public Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) throws WxErrorException {
901904
WxMpPrepayIdResult wxMpPrepayIdResult = getPrepayId(parameters);
905+
906+
if (!"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getReturn_code())
907+
||!"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getResult_code())) {
908+
WxError error = new WxError();
909+
error.setErrorCode(-1);
910+
error.setErrorMsg("return_code:" + wxMpPrepayIdResult.getReturn_code() +
911+
";return_msg:" + wxMpPrepayIdResult.getReturn_msg() +
912+
";result_code:" + wxMpPrepayIdResult.getResult_code() +
913+
";err_code" + wxMpPrepayIdResult.getErr_code() +
914+
";err_code_des" + wxMpPrepayIdResult.getErr_code_des());
915+
throw new WxErrorException(error);
916+
}
917+
902918
String prepayId = wxMpPrepayIdResult.getPrepay_id();
903919
if (prepayId == null || prepayId.equals("")) {
904920
throw new RuntimeException(String.format("Failed to get prepay id due to error code '%s'(%s).", wxMpPrepayIdResult.getErr_code(), wxMpPrepayIdResult.getErr_code_des()));
@@ -971,6 +987,59 @@ public WxMpPayCallback getJSSDKCallbackData(String xmlData) {
971987
return new WxMpPayCallback();
972988
}
973989

990+
@Override
991+
public WxMpPayRefundResult refundPay(Map<String, String> parameters) throws WxErrorException {
992+
SortedMap<String, String> refundParams = new TreeMap<String, String>(parameters);
993+
refundParams.put("appid", wxMpConfigStorage.getAppId());
994+
refundParams.put("mch_id", wxMpConfigStorage.getPartnerId());
995+
refundParams.put("nonce_str", System.currentTimeMillis() + "");
996+
refundParams.put("op_user_id", wxMpConfigStorage.getPartnerId());
997+
String sign = WxCryptUtil.createSign(refundParams, wxMpConfigStorage.getPartnerKey());
998+
refundParams.put("sign", sign);
999+
1000+
StringBuilder request = new StringBuilder("<xml>");
1001+
for (Entry<String, String> para : refundParams.entrySet()) {
1002+
request.append(String.format("<%s>%s</%s>", para.getKey(), para.getValue(), para.getKey()));
1003+
}
1004+
request.append("</xml>");
1005+
1006+
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
1007+
if (httpProxy != null) {
1008+
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
1009+
httpPost.setConfig(config);
1010+
}
1011+
1012+
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
1013+
httpPost.setEntity(entity);
1014+
try(
1015+
CloseableHttpResponse response = getHttpclient().execute(httpPost)) {
1016+
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
1017+
XStream xstream = XStreamInitializer.getInstance();
1018+
xstream.processAnnotations(WxMpPayRefundResult.class);
1019+
WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream.fromXML(responseContent);
1020+
1021+
if (!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getResultCode())
1022+
||!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getReturnCode())) {
1023+
WxError error = new WxError();
1024+
error.setErrorCode(-1);
1025+
error.setErrorMsg("return_code:" + wxMpPayRefundResult.getReturnCode() +
1026+
";return_msg:" + wxMpPayRefundResult.getReturnMsg() +
1027+
";result_code:" + wxMpPayRefundResult.getResultCode() +
1028+
";err_code" + wxMpPayRefundResult.getErrCode() +
1029+
";err_code_des" + wxMpPayRefundResult.getErrCodeDes());
1030+
throw new WxErrorException(error);
1031+
}
1032+
1033+
return wxMpPayRefundResult;
1034+
} catch (IOException e) {
1035+
log.error(MessageFormatter.format("The exception was happened when sending refund '{}'.", request.toString()).getMessage(), e);
1036+
WxError error = new WxError();
1037+
error.setErrorCode(-1);
1038+
error.setErrorMsg("incorrect response.");
1039+
throw new WxErrorException(error);
1040+
}
1041+
}
1042+
9741043
@Override
9751044
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) {
9761045
return signature.equals(WxCryptUtil.createSign(kvm, wxMpConfigStorage.getPartnerKey()));
@@ -1074,6 +1143,7 @@ public String getCardApiTicket(boolean forceRefresh) throws WxErrorException {
10741143
*
10751144
* @param optionalSignParam 参与签名的参数数组。
10761145
* 可以为下列字段:app_id, card_id, card_type, code, openid, location_id
1146+
* </br>注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空
10771147
* @return 卡券Api签名对象
10781148
*/
10791149
@Override
@@ -1148,11 +1218,17 @@ public WxMpCardResult queryCardCode(String cardId, String code, boolean checkCon
11481218
* @throws WxErrorException
11491219
*/
11501220
@Override
1151-
public void consumeCardCode(String code) throws WxErrorException {
1221+
public String consumeCardCode(String code, String cardId) throws WxErrorException {
11521222
String url = "https://api.weixin.qq.com/card/code/consume";
11531223
JsonObject param = new JsonObject();
11541224
param.addProperty("code", code);
1155-
post(url, param.toString());
1225+
1226+
if (cardId != null && !"".equals(cardId)) {
1227+
param.addProperty("card_id", cardId);
1228+
}
1229+
1230+
String responseContent = post(url, param.toString());
1231+
return responseContent;
11561232
}
11571233

11581234
/**
@@ -1183,4 +1259,26 @@ public void markCardCode(String code, String cardId, String openId, boolean isMa
11831259
log.warn("朋友的券mark失败:{}", cardResult.getErrorMsg());
11841260
}
11851261
}
1262+
1263+
@Override
1264+
public String getCardDetail(String cardId) throws WxErrorException {
1265+
String url = "https://api.weixin.qq.com/card/get";
1266+
JsonObject param = new JsonObject();
1267+
param.addProperty("card_id", cardId);
1268+
String responseContent = post(url, param.toString());
1269+
1270+
// 判断返回值
1271+
JsonObject json = (new JsonParser()).parse(responseContent).getAsJsonObject();
1272+
String errcode = json.get("errcode").getAsString();
1273+
if (!"0".equals(errcode)) {
1274+
String errmsg = json.get("errmsg").getAsString();
1275+
WxError error = new WxError();
1276+
error.setErrorCode(Integer.valueOf(errcode));
1277+
error.setErrorMsg(errmsg);
1278+
throw new WxErrorException(error);
1279+
}
1280+
1281+
return responseContent;
1282+
}
1283+
11861284
}

0 commit comments

Comments
 (0)