加解签规则
加签规则(排除sign,signType)
1.
2.
3.
验签规则(排除sign,signType)
1.
2.
3.
参数串+appKey
4.
如果sign==targetSign验签成功.
注意
以下提供java针对某些特殊字符串的URLEncode结果:
String str = "!\"#$%&'()*+,-./0123456789:;<=>?@ABC[\\]^_`abc{|}~江 西【】「」()北极。;‘《》背景";
System.out.println(URLEncoder.encode(str, "UTF-8"));
结果:
%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABC%5B%5C%5D%5E_%60abc%7B%7C%7D%7E%E6%B1%9F+%E8%A5%BF%E3%80%90%E3%80%91%E3%80%8C%E3%80%8D%EF%BC%88%EF%BC%89%E5%8C%97%E6%9E%81%E3%80%82%EF%BC%9B%E2%80%98%E3%80%8A%E3%80%8B%E8%83%8C%E6%99%AF
加签demo python版
_SIGN='sign'
_SIGNTYPE='signType'
def icareSign(params,appKey):
#先排序
params = {k: v for k, v in sorted(params.items(), key=lambda x: x[0])}
#去除不需要参与加签的字符串
for k in list(params.keys()):
if (k.casefold() == _SIGN.casefold() or k.casefold() == _SIGNTYPE.casefold()):
del params[k]
continue
# 计算MD5前的字符串
md5Str = urllib.parse.urlencode(params) + appKey
print("md5Str--括号内字符串-->(%s)" % ( md5Str))
# 计算签名
sign = hashlib.md5(md5Str.encode(encoding='utf-8')).hexdigest()
return sign
加签demo java版本
public void doWork(Config config) {
Map<String, String> map = new HashMap<>();
map.put("channelCode", config.getChannelCode());
map.put("thirdUserId", config.getThirdUserId());
map.put("charset", "UTF8");
map.put("nonce", UUID.randomUUID().toString());
map.put("name", "我爱吃西瓜");
map.put("phone", "15112121234");
map.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
//扩展信息======================start
Map<String, Object> bizContentMap = new HashMap<>();
//当redirect 填入指定值后,免密登录成功由最福利跳转到该指定的页面,不填入则默认跳转到最福利首页
bizContentMap.put("redirect", "https://t-ord.zuifuli.com/m/customer");
map.put("bizContent", JSON.toJSONString(bizContentMap));
//扩展信息======================end
String sign = ZflSignUtil.sign(map, ImmutableSet.of("sign", "signType"), config.getAppKey(), false);
map.put("sign", sign);
map.put("signtType", "MD5");
String query = ZflSignUtil.buildQuery(map, null, StandardCharsets.UTF_8.name(), true);
String requestUrl = String.format("%s?%s", config.getLoginUrlPersonalV2(), query);
System.out.println(String.format("联合登录的请求的地址:%s", requestUrl));
}
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
public class ZflSignUtil {
/**
* @param params 请求参数
* @param excludSet ImmutableSet.of("sign", "signType")
* @param appKey
* @param isLowerCase 是否转小写
* @return
*/
public static String sign(Map<String, String> params, Set<String> excludSet, String appKey, boolean isLowerCase) {
params = exclude(params, excludSet);
String s = buildQuery(params, null, "UTF-8", true);
if (isLowerCase) {
s = s.toLowerCase();
}
return string2MD52(s + appKey);
}
/**
* 构建加密参数
*
* @param params
* @param paramsSortSet
* @param charset
* @param emptyIgnore
* @return
*/
public static String buildQuery(Map<String, String> params, Set<String> paramsSortSet, String charset, boolean emptyIgnore) {
StringBuffer sb = new StringBuffer();
if (paramsSortSet == null) {
paramsSortSet = new TreeSet<>(params.keySet());
}
for (String paraName : paramsSortSet) {
try {
String value = params.get(paraName);
if (StringUtils.isEmpty(value) && emptyIgnore)
continue;
sb.append(URLEncoder.encode(paraName, charset));
sb.append("=");
sb.append(URLEncoder.encode(value == null ? "" : value, charset));
sb.append("&");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
if (sb.length() > 0) {
sb.delete(sb.length() - 1, sb.length());
}
return sb.toString();
}
/**
* md5
*/
private static String string2MD52(String md5) {
System.out.println("MD5前的字符串:"+md5);
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] array = md.digest(md5.getBytes());
return Hex.encodeHexString(array);
} catch (java.security.NoSuchAlgorithmException e) {
}
return null;
}
/**
* 排除指定的字段
* @param params
* @param paramExclude
* @return
*/
private static Map<String, String> exclude(Map<String, String> params, Set<String> paramExclude) {
if (paramExclude != null) {
for (String key : paramExclude) {
params.remove(key);
}
}
return params;
}
}
c#版本urlEncode
// 这个方法是为了跟java的encode相兼容
public static string Encode(string s)
{
StringBuilder sb = new StringBuilder(s.Length * 2);
byte[] arr = Encoding.UTF8.GetBytes(s);
for (int i = 0; i < arr.Length; i++)
{
byte c = arr[i];
if (c == '*' || c == '_' || c == '-' || c == '.')
sb.Append((char)c);
else if(c == ' ')
sb.Append((char)'+');
else if (c >= 0x41 && c <= 0x5A)//A-Z
sb.Append((char)c);
else if (c >= 0x61 && c <= 0x7A)//a-z
sb.Append((char)c);
else if (c >= 0x30 && c <= 0x39)//123456789
sb.Append((char)c);
else
{
sb.Append('%');
sb.Append(Convert.ToString(c, 16).ToUpper());//转成 16进制
}
}
return sb.ToString();
}
}
自用工具使用Demo(工具类使用上文的ZflSignUtil)
public class DemoAction {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now = sdf.format(new Date());
String nonce = UUID.randomUUID().toString().replace("-", "").toLowerCase();
Map<String,String> params = new HashMap<>();
params.put("merchantCode","yonghuichaoshi");
params.put("timestamp",now);
params.put("charset","UTF8");
params.put("nonce",nonce);
Set<String> exclude = new HashSet<>();
exclude.add("sign");
exclude.add("signType");
String sign = ZuifuliSignUtil.sign(params, exclude, "nOjRu2V4FDjNyCqkMJSpQMuXEUxYoj", true);
params.put("sign",sign);
params.put("signType","MD5");
log.info("---------------------------" + JSON.toJSONString(params));
}
}