开放平台
    开放平台
    • 加解签规则
    • 接口地址
    • 关于小程序
    • 最福利订单状态枚举
    • 供应商
      • 登录相关
        • 外部跳转最福利
          • 个人用户免密登录-代理版本
          • 个人用户免密登录-普通版本
    • 渠道方
      • 最福利收银台-积分在外部系统-渠道方使用
        • 余额查询
        • 发起交易
        • 发起退款
        • 订单状态推送
        • 交易分页查询
      • 订单系统
        • 查询订单信息(用户为公司用户)

    加解签规则

    最福利使用https协议,只需要对请求的参数进行加解签即可.请对所有参数进行验签,最福利后续可能会新增字段

    加签规则(排除sign,signType)#

    请求参数 s=XXXX,b=XXXX,a=XXXX
    1.
    构建签名串:
    对请求参数按照字母升序排序, a=XXXX,b=XXXX,s=XXXX(bizcontext 参数中的值不参与排序)
    对参数名称,参数值utf8 进行URLEncodeing 且使用&拼接成参数串 a=XXXX&b=XXXX&s=XXXX(可能会有特殊用途)
    参数串+appKey
    2.
    使用MD5算法对以上签名串进行加签,从而获取sign.ps:使用UTF8字符集
    3.
    将sign作为请求参数,signType=MD5.

    验签规则(排除sign,signType)#

    请求参数s=YYYY,b=YYYY,a=YYYY,sign=ab6e81f0adc128,signType=MD5
    1.
    构建验签串
    2.
    请求参数除sign按照字母升序排序a=YYYY,b=YYYY,s=YYYY
    3.
    对参数名称,参数值utf8 进行URLEncodeing 且使用&拼接成参数串 a=YYYY&b=YYYY&s=YYYY
    参数串+appKey
    4.
    使用MD5算法对以上签名串进行加签,从而获取targetSign.ps:使用UTF8字符集
    如果sign==targetSign验签成功.
    注意
    各个语言之间 针对特殊字符串的URLEncodeing可能会存在差异,具体需以java URLEncode 后的结果为准。
    以下提供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));
    
        }
    }
    下一页
    接口地址
    Built with