业务需求:把接口传递的参数先排序并MD5加密 生成一个验签字符串

系统会为每个接入的应用系统提供一个唯一的key, 应用系统需要使用这个key和有效的access_token用于生成加密的验签, 接口参数加密方式详细定义如下:
    第一步: 设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA(access_token作为其中的一个参数参与验签计算)。 
特别注意以下重要规则: 
参数名ASCII码从小到大排序(字典序); 
如果参数的值为空不参与签名; 
版本号参数不参与验签;
参数名区分大小写; 
传送的sign参数不参与签名,将生成的签名与该sign值作校验。 
接口可能增加字段,验证签名时必须支持增加的扩展字段 
    第二步: 在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

例如 signValue="flag=1&isWaitDeal=2&pageNo=1&pageSize=10"

以下为整理好的工具类:

导包:

#define CC_MD5_DIGEST_LENGTH 16
#import <CommonCrypto/CommonCrypto.h>

1.排序工具类

20191023修改: 格式化value  去除无value的key

/** wuxifan
     对字典(Key-Value)排序 区分大小写
     @param dict 要排序的字典
     */
    - (NSString *)sortedDictionary:(NSDictionary *)dict{
        
        //将所有的key放进数组
        NSArray *allKeyArray = [dict allKeys];
        
        //序列化器对数组进行排序的block 返回值为排序后的数组
        NSArray *afterSortKeyArray = [allKeyArray sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id
                                                                                                 _Nonnull obj2) {
            /**
             In the compare: methods, the range argument specifies the
             subrange, rather than the whole, of the receiver to use in the
             comparison. The range is not applied to the search string.  For
             example, [@"AB" compare:@"ABC" options:0 range:NSMakeRange(0,1)]
             compares "A" to "ABC", not "A" to "A", and will return
             NSOrderedAscending. It is an error to specify a range that is
             outside of the receiver's bounds, and an exception may be raised.
             
             - (NSComparisonResult)compare:(NSString *)string;
             
             compare方法的比较原理为,依次比较当前字符串的第一个字母:
             如果不同,按照输出排序结果
             如果相同,依次比较当前字符串的下一个字母(这里是第二个)
             以此类推
             
             排序结果
             NSComparisonResult resuest = [obj1 compare:obj2];为从小到大,即升序;
             NSComparisonResult resuest = [obj2 compare:obj1];为从大到小,即降序;
             
             注意:compare方法是区分大小写的,即按照ASCII排序
             */
            //排序操作
            NSComparisonResult resuest = [obj1 compare:obj2];
            return resuest;
        }];
        //排序好的字典
        NSLog(@"afterSortKeyArray:%@",afterSortKeyArray);
        NSString *tempStr = @"";
        //通过排列的key值获取value
        NSMutableArray *valueArray = [NSMutableArray array];
        for (NSString *sortsing in afterSortKeyArray) {
            //格式化一下 防止有些value不是string
            NSString *valueString = [NSString stringWithFormat:@"%@",[dict objectForKey:sortsing]];
            if(valueString.length>0){
                [valueArray addObject:valueString];
                tempStr=[NSString stringWithFormat:@"%@%@=%@&",tempStr,sortsing,valueString];
            }
        }
        //去除最后一个&符号
        if(tempStr.length>0){
            tempStr=[tempStr substringToIndex:([tempStr length]-1)];
        }
        //排序好的对应值
        //  NSLog(@"valueArray:%@",valueArray);
        //最终参数
        NSLog(@"tempStr:%@",tempStr);
        //md5加密
        // NSLog(@"tempStr:%@",[self getmd5WithString:tempStr]);
        return tempStr;
    }

2.MD5加密工具类

//字符串MD5加密
- (NSString*)getmd5WithString:(NSString *)string
{
    const char* original_str=[string UTF8String];
    unsigned char digist[CC_MD5_DIGEST_LENGTH]; //CC_MD5_DIGEST_LENGTH = 16
    CC_MD5(original_str, (uint)strlen(original_str), digist);
    NSMutableString* outPutStr = [NSMutableString stringWithCapacity:10];
    for(int  i =0; i<CC_MD5_DIGEST_LENGTH;i++){
        [outPutStr appendFormat:@"%02X", digist[i]];//小写x表示输出的是小写MD5,大写X表示输出的是大写MD5
    }
   // return [outPutStr lowercaseString];
    return outPutStr;
}

3.测试调用

 

//生成一个s参数进行验签
            NSString *sStr=[self sortedDictionary:request.parameters];
            //MD5加密
            NSString *sMD5Str=[self getmd5WithString:sStr];
            //放到接口参数里
            [parameters setObject:sMD5Str forKey:@"s"];

4.截图

s为新生成的验签参数(截图未调用MD5)

iOS接口400_验签