From 06c73ca6abdd0e06c8b4f9b2c3f8debd01b540bc Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sat, 24 Sep 2016 23:45:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8F=91=E9=80=81=E7=BA=A2?= =?UTF-8?q?=E5=8C=85=E7=9A=84=E9=87=8D=E8=BD=BD=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E5=87=86=E5=A4=87=E6=9B=BF=E4=BB=A3=E7=8E=B0=E6=9C=89=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/crypto/WxCryptUtil.java | 3 +- weixin-java-mp/pom.xml | 9 +- .../chanjar/weixin/mp/api/WxMpPayService.java | 13 ++ .../mp/api/impl/WxMpPayServiceImpl.java | 98 ++++++++++--- .../mp/bean/pay/WxSendRedpackRequest.java | 137 ++++++++++++++++++ 5 files changed, 234 insertions(+), 26 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java index eb5df7af4..19424e0b8 100755 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java @@ -85,8 +85,7 @@ public class WxCryptUtil { * @param signKey 加密Key(即 商户Key) * @return 签名字符串 */ - public static String createSign(Map packageParams, - String signKey) { + public static String createSignForPay(Map packageParams, String signKey) { SortedMap sortedMap = new TreeMap<>(); sortedMap.putAll(packageParams); diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index 0cfb10484..0e534d0bc 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 com.github.binarywang @@ -54,6 +54,11 @@ 2.9.4 test + + org.jooq + joor + 0.9.6 + diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java index 4de8332ba..663444a7f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java @@ -7,6 +7,7 @@ import me.chanjar.weixin.mp.bean.pay.WxMpPayCallback; import me.chanjar.weixin.mp.bean.pay.WxMpPayRefundResult; import me.chanjar.weixin.mp.bean.pay.WxMpPayResult; import me.chanjar.weixin.mp.bean.pay.WxRedpackResult; +import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest; import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult; /** @@ -138,5 +139,17 @@ public interface WxMpPayService { * 商户平台设置的API密钥 * */ + @Deprecated WxRedpackResult sendRedpack(Map parameters) throws WxErrorException; + + /** + * 发送微信红包给个人用户 + *
 
+   * 文档详见:
+   * 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
+   * 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
+   * 
+ */ + WxRedpackResult sendRedpack(WxSendRedpackRequest request) throws WxErrorException; + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index 9ff3c4ab4..13ab0781c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -1,6 +1,28 @@ package me.chanjar.weixin.mp.api.impl; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.http.Consts; +import org.apache.http.HttpHost; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.joor.Reflect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.helpers.MessageFormatter; + +import com.beust.jcommander.internal.Maps; import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.annotations.XStreamAlias; + import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.crypto.WxCryptUtil; @@ -11,22 +33,8 @@ import me.chanjar.weixin.mp.bean.pay.WxMpPayCallback; import me.chanjar.weixin.mp.bean.pay.WxMpPayRefundResult; import me.chanjar.weixin.mp.bean.pay.WxMpPayResult; import me.chanjar.weixin.mp.bean.pay.WxRedpackResult; -import me.chanjar.weixin.mp.bean.result.*; -import org.apache.http.Consts; -import org.apache.http.HttpHost; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.helpers.MessageFormatter; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; +import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest; +import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult; /** * Created by Binary Wang on 2016/7/28. @@ -77,7 +85,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { packageParams.put("nonce_str", System.currentTimeMillis() + ""); checkParameters(packageParams); - String sign = WxCryptUtil.createSign(packageParams, + String sign = WxCryptUtil.createSignForPay(packageParams, this.wxMpService.getWxMpConfigStorage().getPartnerKey()); packageParams.put("sign", sign); @@ -211,7 +219,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { payInfo.put("codeUrl", wxMpPrepayIdResult.getCode_url()); } - String finalSign = WxCryptUtil.createSign(payInfo, + String finalSign = WxCryptUtil.createSignForPay(payInfo, this.wxMpService.getWxMpConfigStorage().getPartnerKey()); payInfo.put("paySign", finalSign); return payInfo; @@ -238,7 +246,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { } packageParams.put("nonce_str", nonce_str); - packageParams.put("sign", WxCryptUtil.createSign(packageParams, + packageParams.put("sign", WxCryptUtil.createSignForPay(packageParams, this.wxMpService.getWxMpConfigStorage().getPartnerKey())); StringBuilder request = new StringBuilder(""); @@ -295,7 +303,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { refundParams.put("nonce_str", System.currentTimeMillis() + ""); refundParams.put("op_user_id", this.wxMpService.getWxMpConfigStorage().getPartnerId()); - String sign = WxCryptUtil.createSign(refundParams, + String sign = WxCryptUtil.createSignForPay(refundParams, this.wxMpService.getWxMpConfigStorage().getPartnerKey()); refundParams.put("sign", sign); @@ -354,11 +362,12 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public boolean checkJSSDKCallbackDataSignature(Map kvm, String signature) { - return signature.equals(WxCryptUtil.createSign(kvm, + return signature.equals(WxCryptUtil.createSignForPay(kvm, this.wxMpService.getWxMpConfigStorage().getPartnerKey())); } @Override + @Deprecated public WxRedpackResult sendRedpack(Map parameters) throws WxErrorException { SortedMap packageParams = new TreeMap<>(parameters); @@ -368,7 +377,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { this.wxMpService.getWxMpConfigStorage().getPartnerId()); packageParams.put("nonce_str", System.currentTimeMillis() + ""); - String sign = WxCryptUtil.createSign(packageParams, + String sign = WxCryptUtil.createSignForPay(packageParams, this.wxMpService.getWxMpConfigStorage().getPartnerKey()); packageParams.put("sign", sign); @@ -409,4 +418,49 @@ public class WxMpPayServiceImpl implements WxMpPayService { } } + @Override + public WxRedpackResult sendRedpack(WxSendRedpackRequest request) throws WxErrorException { + XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(WxRedpackResult.class); + + request.setWxAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); + request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); + request.setNonceStr(System.currentTimeMillis() + ""); + + String sign = WxCryptUtil.createSignForPay(xmlBean2Map(request), + this.wxMpService.getWxMpConfigStorage().getPartnerKey()); + request.setSign(sign); + + String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack"; + if (request.getAmtType() != null) { + //裂变红包 + url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack"; + } + + String responseContent = this.wxMpService.post(url, xstream.toXML(request)); + return (WxRedpackResult) xstream.fromXML(responseContent); + } + + private Map xmlBean2Map(Object bean) { + Map result = Maps.newHashMap(); + for (Entry entry : Reflect.on(bean).fields().entrySet()) { + Reflect reflect = entry.getValue(); + if (reflect.get() == null) { + continue; + } + + try { + Field field = WxSendRedpackRequest.class.getDeclaredField(entry.getKey()); + if (field.isAnnotationPresent(XStreamAlias.class)) { + result.put(reflect.get().toString(), field.getAnnotation(XStreamAlias.class).value()); + } + } catch (NoSuchFieldException | SecurityException e) { + e.printStackTrace(); + } + + } + + return result; + } + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxSendRedpackRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxSendRedpackRequest.java index 95ee2bad1..ccf84ae90 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxSendRedpackRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxSendRedpackRequest.java @@ -156,4 +156,141 @@ public class WxSendRedpackRequest { */ @XStreamAlias("consume_mch_id") private String consumeMchId; + + public String getMchBillno() { + return mchBillno; + } + + public void setMchBillno(String mchBillno) { + this.mchBillno = mchBillno; + } + + public String getSendName() { + return sendName; + } + + public void setSendName(String sendName) { + this.sendName = sendName; + } + + public String getReOpenid() { + return reOpenid; + } + + public void setReOpenid(String reOpenid) { + this.reOpenid = reOpenid; + } + + public Integer getTotalAmount() { + return totalAmount; + } + + public void setTotalAmount(Integer totalAmount) { + this.totalAmount = totalAmount; + } + + public Integer getTotalNum() { + return totalNum; + } + + public void setTotalNum(Integer totalNum) { + this.totalNum = totalNum; + } + + public String getAmtType() { + return amtType; + } + + public void setAmtType(String amtType) { + this.amtType = amtType; + } + + public String getWishing() { + return wishing; + } + + public void setWishing(String wishing) { + this.wishing = wishing; + } + + public String getClientIp() { + return clientIp; + } + + public void setClientIp(String clientIp) { + this.clientIp = clientIp; + } + + public String getActName() { + return actName; + } + + public void setActName(String actName) { + this.actName = actName; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String getWxAppid() { + return wxAppid; + } + + public void setWxAppid(String wxAppid) { + this.wxAppid = wxAppid; + } + + public String getMchId() { + return mchId; + } + + public void setMchId(String mchId) { + this.mchId = mchId; + } + + 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 getSceneId() { + return sceneId; + } + + public void setSceneId(String sceneId) { + this.sceneId = sceneId; + } + + public String getRiskInfo() { + return riskInfo; + } + + public void setRiskInfo(String riskInfo) { + this.riskInfo = riskInfo; + } + + public String getConsumeMchId() { + return consumeMchId; + } + + public void setConsumeMchId(String consumeMchId) { + this.consumeMchId = consumeMchId; + } + }