From 4289bd53501ced5c1c4b9f8690d5917ff7ccacd5 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Wed, 11 Jul 2018 23:30:56 +0800 Subject: [PATCH] =?UTF-8?q?#659=20=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=B8=8A=E6=8A=A5=E7=94=A8=E6=88=B7=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=90=8E=E5=8F=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chanjar/weixin/common/util/SignUtils.java | 40 +++++++++++++++++++ .../wx/miniapp/api/WxMaUserService.java | 12 ++++++ .../miniapp/api/impl/WxMaUserServiceImpl.java | 39 +++++++++++++++++- .../api/impl/WxMaUserServiceImplTest.java | 19 +++++++++ .../binarywang/wxpay/util/SignUtils.java | 32 +++------------ 5 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java new file mode 100644 index 00000000..9ea33b12 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java @@ -0,0 +1,40 @@ +package me.chanjar.weixin.common.util; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Hex; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +/** + *
+ *  签名工具类
+ *  Created by BinaryWang on 2018/7/11.
+ * 
+ * + * @author Binary Wang + */ +@Slf4j +public class SignUtils { + /** + * HmacSHA256 签名算法 + * + * @param message 签名数据 + * @param key 签名密钥 + */ + public static String createHmacSha256Sign(String message, String key) { + try { + Mac sha256 = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + sha256.init(secretKeySpec); + byte[] bytes = sha256.doFinal(message.getBytes()); + return Hex.encodeHexString(bytes).toUpperCase(); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + SignUtils.log.error(e.getMessage(), e); + } + + return null; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java index 8c567218..a4abdc04 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java @@ -5,6 +5,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import me.chanjar.weixin.common.error.WxErrorException; +import java.util.Map; + /** * 用户信息相关操作接口. * @@ -28,6 +30,16 @@ public interface WxMaUserService { */ WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr); + /** + * 上报用户数据后台接口. + *

小游戏可以通过本接口上报key-value数据到用户的CloudStorage。

+ * 文档参考https://developers.weixin.qq.com/minigame/dev/document/open-api/data/setUserStorage.html + * @param kvMap 要上报的数据 + * @param sessionKey 通过wx.login 获得的登录态 + * @param openid + */ + void setUserStorage(Map kvMap, String sessionKey, String openid) throws WxErrorException; + /** * 解密用户手机号信息. * diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java index f1bac75e..f8177bf1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java @@ -1,14 +1,25 @@ package cn.binarywang.wx.miniapp.api.impl; -import org.apache.commons.codec.digest.DigestUtils; - import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.WxMaUserService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; +import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.SignUtils; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.codec.digest.DigestUtils; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Map; /** * @author Binary Wang @@ -30,6 +41,30 @@ public class WxMaUserServiceImpl implements WxMaUserService { return WxMaUserInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)); } + @Override + public void setUserStorage(Map kvMap, String sessionKey, String openid) throws WxErrorException { + final WxMaConfig config = this.service.getWxMaConfig(); + JsonObject param = new JsonObject(); + JsonArray array = new JsonArray(); + for (Map.Entry e : kvMap.entrySet()) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("key", e.getKey()); + jsonObject.addProperty("value", e.getValue()); + array.add(jsonObject); + } + param.add("kv_list", array); + String params = param.toString(); + String signature = SignUtils.createHmacSha256Sign(params, sessionKey); + String url = String.format("https://api.weixin.qq.com/wxa/set_user_storage" + + "?appid=%s&signature=%s&openid=%s&sig_method=%s", + config.getAppid(), signature, openid, "hmac_sha256"); + String result = this.service.post(url, params); + WxError error = WxError.fromJson(result); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + } + @Override public WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr) { return WxMaPhoneNumberInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)); diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java index 33e39a6b..2c478e8f 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java @@ -1,5 +1,9 @@ package cn.binarywang.wx.miniapp.api.impl; +import cn.binarywang.wx.miniapp.test.TestConfig; +import com.google.common.collect.ImmutableMap; +import jdk.nashorn.internal.ir.annotations.Immutable; +import me.chanjar.weixin.common.error.WxErrorException; import org.testng.annotations.*; import cn.binarywang.wx.miniapp.api.WxMaService; @@ -8,6 +12,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import cn.binarywang.wx.miniapp.test.ApiTestModule; import com.google.inject.Inject; +import javax.management.ImmutableDescriptor; + import static org.testng.Assert.*; /** @@ -54,4 +60,17 @@ public class WxMaUserServiceImplTest { assertNotNull(phoneNoInfo); System.out.println(phoneNoInfo.toString()); } + + @Test + public void testGetSessionInfo() { + } + + /** + * TODO 测试数据有问题,需要替换为正确的数据 + */ + @Test + public void testSetUserStorage() throws WxErrorException { + this.wxService.getUserService().setUserStorage(ImmutableMap.of("1","2"), + "r7BXXKkLb8qrSNn05n0qiA",((TestConfig)this.wxService.getWxMaConfig()).getOpenid()); + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java index 10aedfe3..eda47de3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java @@ -6,19 +6,12 @@ import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.thoughtworks.xstream.annotations.XStreamAlias; -import me.chanjar.weixin.common.util.BeanUtils; -import org.apache.commons.codec.binary.Hex; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; import java.util.*; /** @@ -29,9 +22,8 @@ import java.util.*; * * @author binarywang(Binary Wang) */ +@Slf4j public class SignUtils { - private static final Logger log = LoggerFactory.getLogger(SignUtils.class); - /** * 请参考并使用 {@link #createSign(Object, String, String, boolean)}. */ @@ -91,26 +83,12 @@ public class SignUtils { toSign.append("key=").append(signKey); if (SignType.HMAC_SHA256.equals(signType)) { - return createHmacSha256Sign(toSign.toString(), signKey); + return me.chanjar.weixin.common.util.SignUtils.createHmacSha256Sign(toSign.toString(), signKey); } else { return DigestUtils.md5Hex(toSign.toString()).toUpperCase(); } } - private static String createHmacSha256Sign(String message, String key) { - try { - Mac sha256 = Mac.getInstance("HmacSHA256"); - SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); - sha256.init(secretKeySpec); - byte[] bytes = sha256.doFinal(message.getBytes()); - return Hex.encodeHexString(bytes).toUpperCase(); - } catch (NoSuchAlgorithmException | InvalidKeyException e) { - log.error(e.getMessage(), e); - } - - return null; - } - /** * 校验签名是否正确. * @@ -146,11 +124,11 @@ public class SignUtils { Map result = Maps.newHashMap(); List fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields())); fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields())); - if(bean.getClass().getSuperclass().getSuperclass() == BaseWxPayRequest.class){ + if (bean.getClass().getSuperclass().getSuperclass() == BaseWxPayRequest.class) { fields.addAll(Arrays.asList(BaseWxPayRequest.class.getDeclaredFields())); } - if(bean.getClass().getSuperclass().getSuperclass() == BaseWxPayResult.class){ + if (bean.getClass().getSuperclass().getSuperclass() == BaseWxPayResult.class) { fields.addAll(Arrays.asList(BaseWxPayResult.class.getDeclaredFields())); }