소스 검색

Merge pull request #269 from liukaitj/develop

Develop
master
Daniel Qian 9 년 전
부모
커밋
d253bdeba4
3개의 변경된 파일416개의 추가작업 그리고 10개의 파일을 삭제
  1. +36
    -6
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
  2. +102
    -4
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
  3. +278
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpPayRefundResult.java

+ 36
- 6
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java 파일 보기

@@ -726,8 +726,9 @@ public interface WxMpService {
* @param parameters
* the required or optional parameters
* @return
* @throws WxErrorException
*/
Map<String, String> getJSSDKPayInfo(Map<String, String> parameters);
Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) throws WxErrorException;
/**
* 该接口调用“统一下单”接口,并拼装JSSDK发起支付请求需要的参数
@@ -740,10 +741,11 @@ public interface WxMpService {
* @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址
* @return
* @throws WxErrorException
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getJSSDKPayInfo(Map<String, String>) instead
*/
@Deprecated
Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String notifyUrl);
Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String notifyUrl) throws WxErrorException;

/**
* 该接口提供所有微信支付订单的查询,当支付通知处理异常戒丢失的情冴,商户可以通过该接口查询订单支付状态。
@@ -761,6 +763,20 @@ public interface WxMpService {
*/
WxMpPayCallback getJSSDKCallbackData(String xmlData);
/**
* 微信支付-申请退款
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
* @param parameters 需要传入的退款参数的Map。以下几项为参数的必须项:<br/>
* <li/> transaction_id
* <li/> out_trade_no (仅在上述transaction_id为空时是必须项)
* <li/> out_refund_no
* <li/> total_fee
* <li/> refund_fee
* @return 退款操作结果
* @throws WxErrorException
*/
public WxMpPayRefundResult refundPay(Map<String, String> parameters) throws WxErrorException;
/**
* <pre>
* 计算Map键值对是否和签名相符,
@@ -812,6 +828,7 @@ public interface WxMpService {
*
* @param optionalSignParam 参与签名的参数数组。
* 可以为下列字段:app_id, card_id, card_type, code, openid, location_id
* </br>注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空
* @return 卡券Api签名对象
*/
public WxCardApiSignature createCardApiSignature(String... optionalSignParam) throws
@@ -839,10 +856,12 @@ public interface WxMpService {
/**
* 卡券Code核销。核销失败会抛出异常
* @param code 单张卡券的唯一标准
* @return
* @throws WxErrorException
*/
public void consumeCardCode(String code) throws WxErrorException;
* @param cardId 当自定义Code卡券时需要传入card_id
* @return 调用返回的JSON字符串。
* <br>可用 com.google.gson.JsonParser#parse 等方法直接取JSON串中的errcode等信息。
* @throws WxErrorException
*/
public String consumeCardCode(String code, String cardId) throws WxErrorException;

/**
* 卡券Mark接口。
@@ -856,4 +875,15 @@ public interface WxMpService {
*/
public void markCardCode(String code, String cardId, String openId, boolean isMark) throws
WxErrorException;
/**
* 查看卡券详情接口
* 详见 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
* @param cardId 卡券的ID
* @return 返回的卡券详情JSON字符串
* <br> [注] 由于返回的JSON格式过于复杂,难以定义其对应格式的Bean并且难以维护,因此只返回String格式的JSON串。
* <br> 可由 com.google.gson.JsonParser#parse 等方法直接取JSON串中的某个字段。
* @throws WxErrorException
*/
public String getCardDetail(String cardId) throws WxErrorException;
}

+ 102
- 4
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java 파일 보기

@@ -56,6 +56,7 @@ import me.chanjar.weixin.mp.bean.result.WxMpMaterialUploadResult;
import me.chanjar.weixin.mp.bean.result.WxMpMaterialVideoInfoResult;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpPayCallback;
import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult;
import me.chanjar.weixin.mp.bean.result.WxMpPayResult;
import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
@@ -97,6 +98,7 @@ import org.slf4j.helpers.MessageFormatter;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.internal.Streams;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
@@ -881,7 +883,8 @@ public class WxMpServiceImpl implements WxMpService {
}

@Override
public Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String callbackUrl) {
public Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String callbackUrl)
throws WxErrorException {
Map<String, String> packageParams = new HashMap<String, String>();
packageParams.put("appid", wxMpConfigStorage.getAppId());
packageParams.put("mch_id", wxMpConfigStorage.getPartnerId());
@@ -897,8 +900,21 @@ public class WxMpServiceImpl implements WxMpService {
}

@Override
public Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) {
public Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) throws WxErrorException {
WxMpPrepayIdResult wxMpPrepayIdResult = getPrepayId(parameters);
if (!"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getReturn_code())
||!"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getResult_code())) {
WxError error = new WxError();
error.setErrorCode(-1);
error.setErrorMsg("return_code:" + wxMpPrepayIdResult.getReturn_code() +
";return_msg:" + wxMpPrepayIdResult.getReturn_msg() +
";result_code:" + wxMpPrepayIdResult.getResult_code() +
";err_code" + wxMpPrepayIdResult.getErr_code() +
";err_code_des" + wxMpPrepayIdResult.getErr_code_des());
throw new WxErrorException(error);
}
String prepayId = wxMpPrepayIdResult.getPrepay_id();
if (prepayId == null || prepayId.equals("")) {
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 class WxMpServiceImpl implements WxMpService {
return new WxMpPayCallback();
}
@Override
public WxMpPayRefundResult refundPay(Map<String, String> parameters) throws WxErrorException {
SortedMap<String, String> refundParams = new TreeMap<String, String>(parameters);
refundParams.put("appid", wxMpConfigStorage.getAppId());
refundParams.put("mch_id", wxMpConfigStorage.getPartnerId());
refundParams.put("nonce_str", System.currentTimeMillis() + "");
refundParams.put("op_user_id", wxMpConfigStorage.getPartnerId());
String sign = WxCryptUtil.createSign(refundParams, wxMpConfigStorage.getPartnerKey());
refundParams.put("sign", sign);

StringBuilder request = new StringBuilder("<xml>");
for (Entry<String, String> para : refundParams.entrySet()) {
request.append(String.format("<%s>%s</%s>", para.getKey(), para.getValue(), para.getKey()));
}
request.append("</xml>");
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
if (httpProxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
httpPost.setConfig(config);
}
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
httpPost.setEntity(entity);
try(
CloseableHttpResponse response = getHttpclient().execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpPayRefundResult.class);
WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream.fromXML(responseContent);
if (!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getResultCode())
||!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getReturnCode())) {
WxError error = new WxError();
error.setErrorCode(-1);
error.setErrorMsg("return_code:" + wxMpPayRefundResult.getReturnCode() +
";return_msg:" + wxMpPayRefundResult.getReturnMsg() +
";result_code:" + wxMpPayRefundResult.getResultCode() +
";err_code" + wxMpPayRefundResult.getErrCode() +
";err_code_des" + wxMpPayRefundResult.getErrCodeDes());
throw new WxErrorException(error);
}
return wxMpPayRefundResult;
} catch (IOException e) {
log.error(MessageFormatter.format("The exception was happened when sending refund '{}'.", request.toString()).getMessage(), e);
WxError error = new WxError();
error.setErrorCode(-1);
error.setErrorMsg("incorrect response.");
throw new WxErrorException(error);
}
}
@Override
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) {
return signature.equals(WxCryptUtil.createSign(kvm, wxMpConfigStorage.getPartnerKey()));
@@ -1074,6 +1143,7 @@ public class WxMpServiceImpl implements WxMpService {
*
* @param optionalSignParam 参与签名的参数数组。
* 可以为下列字段:app_id, card_id, card_type, code, openid, location_id
* </br>注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空
* @return 卡券Api签名对象
*/
@Override
@@ -1148,11 +1218,17 @@ public class WxMpServiceImpl implements WxMpService {
* @throws WxErrorException
*/
@Override
public void consumeCardCode(String code) throws WxErrorException {
public String consumeCardCode(String code, String cardId) throws WxErrorException {
String url = "https://api.weixin.qq.com/card/code/consume";
JsonObject param = new JsonObject();
param.addProperty("code", code);
post(url, param.toString());
if (cardId != null && !"".equals(cardId)) {
param.addProperty("card_id", cardId);
}
String responseContent = post(url, param.toString());
return responseContent;
}

/**
@@ -1183,4 +1259,26 @@ public class WxMpServiceImpl implements WxMpService {
log.warn("朋友的券mark失败:{}", cardResult.getErrorMsg());
}
}

@Override
public String getCardDetail(String cardId) throws WxErrorException {
String url = "https://api.weixin.qq.com/card/get";
JsonObject param = new JsonObject();
param.addProperty("card_id", cardId);
String responseContent = post(url, param.toString());
// 判断返回值
JsonObject json = (new JsonParser()).parse(responseContent).getAsJsonObject();
String errcode = json.get("errcode").getAsString();
if (!"0".equals(errcode)) {
String errmsg = json.get("errmsg").getAsString();
WxError error = new WxError();
error.setErrorCode(Integer.valueOf(errcode));
error.setErrorMsg(errmsg);
throw new WxErrorException(error);
}
return responseContent;
}

}

+ 278
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpPayRefundResult.java 파일 보기

@@ -0,0 +1,278 @@
package me.chanjar.weixin.mp.bean.result;

import java.io.Serializable;

import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
* 微信支付-申请退款返回结果
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
* @author liukaitj
*
*/
@XStreamAlias("xml")
public class WxMpPayRefundResult implements Serializable {

private static final long serialVersionUID = 1L;

@XStreamAlias("return_code")
private String returnCode;
@XStreamAlias("return_msg")
private String returnMsg;
@XStreamAlias("result_code")
private String resultCode;
@XStreamAlias("err_code")
private String errCode;
@XStreamAlias("err_code_des")
private String errCodeDes;
@XStreamAlias("appid")
private String appid;
@XStreamAlias("mch_id")
private String mchId;
@XStreamAlias("device_info")
private String deviceInfo;
@XStreamAlias("nonce_str")
private String nonceStr;
@XStreamAlias("sign")
private String sign;
@XStreamAlias("transaction_id")
private String transactionId;
@XStreamAlias("out_trade_no")
private String outTradeNo;
@XStreamAlias("out_refund_no")
private String outRefundNo;
@XStreamAlias("refund_id")
private String refundId;
@XStreamAlias("refund_channel")
private String refundChannel;
@XStreamAlias("refund_fee")
private String refundFee;
@XStreamAlias("total_fee")
private String totalFee;
@XStreamAlias("fee_type")
private String feeType;
@XStreamAlias("cash_fee")
private String cashFee;
@XStreamAlias("cash_refund_fee")
private String cashRefundfee;
@XStreamAlias("coupon_refund_fee")
private String couponRefundFee;
@XStreamAlias("coupon_refund_count")
private String couponRefundCount;
@XStreamAlias("coupon_refund_id")
private String couponRefundId;

public String getReturnCode() {
return returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrCodeDes() {
return errCodeDes;
}
public void setErrCodeDes(String errCodeDes) {
this.errCodeDes = errCodeDes;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMchId() {
return mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getOutRefundNo() {
return outRefundNo;
}
public void setOutRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
}
public String getRefundId() {
return refundId;
}
public void setRefundId(String refundId) {
this.refundId = refundId;
}
public String getRefundChannel() {
return refundChannel;
}
public void setRefundChannel(String refundChannel) {
this.refundChannel = refundChannel;
}
public String getRefundFee() {
return refundFee;
}
public void setRefundFee(String refundFee) {
this.refundFee = refundFee;
}
public String getTotalFee() {
return totalFee;
}
public void setTotalFee(String totalFee) {
this.totalFee = totalFee;
}
public String getFeeType() {
return feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public String getCashFee() {
return cashFee;
}
public void setCashFee(String cashFee) {
this.cashFee = cashFee;
}
public String getCashRefundfee() {
return cashRefundfee;
}
public void setCashRefundfee(String cashRefundfee) {
this.cashRefundfee = cashRefundfee;
}
public String getCouponRefundFee() {
return couponRefundFee;
}
public void setCouponRefundFee(String couponRefundFee) {
this.couponRefundFee = couponRefundFee;
}
public String getCouponRefundCount() {
return couponRefundCount;
}
public void setCouponRefundCount(String couponRefundCount) {
this.couponRefundCount = couponRefundCount;
}
public String getCouponRefundId() {
return couponRefundId;
}
public void setCouponRefundId(String couponRefundId) {
this.couponRefundId = couponRefundId;
}
@Override
public String toString() {
return "[" +
"return_code:" + returnCode + ";" +
"return_msg" + returnMsg + ";";
}

}

불러오는 중...
취소
저장