iOS 之 微信支付

今天给大家说说这个微信支付。当时我写这个的时候的确感觉挺坑的。文档不全不说,还给介绍的不详细,简直是醉了,好了,废话少说 直接上代码。

在这之前,先添加下微信的依赖库

SystemConfiguration.framework     libz.tbd  libsqlite3.0.tbd  libc++.tbd

CoreTelephony.framework(这个库官方文档没说,这就是一个坑,没它还不能行)

把微信的SDK放入项目中

在AppDelegate 中算是注册微信把   

[WXApiregisterApp:@"appid"];   //appid 是你在微信官方申请的ID 当你申请成功之后就会有了

然后在你需要的地方 拉起微信支付 

//调起微信支付

    PayReq* req             = [[PayReqalloc] init];

    req.openID              =APP_ID;//你申请的ID  

    req.partnerId           =MCH_ID;//商户ID

    req.prepayId            = prepayId;//预支付订单 (下面会详细介绍)

    req.nonceStr            = nonce_str;//随机串 防止订单重复

    req.timeStamp           = time_stamp.intValue;//时间戳 同样防止订单重复

    req.package             = @"Sign=WXPay"//固定死值   (目前是死的 不知道以后微信会不会换)

    req.sign                = sign;//二次签名 (下面会详细介绍)

先说一下预支付订单

什么为预支付订单,根据官方的解释是你自己先在微信官网生成一个支付订单,

 //================================

    //预付单参数订单设置

  //================================   

srand( (unsigned)time(0) );

    NSString *noncestr  = [NSStringstringWithFormat:@"%d",rand()];

    

    NSLog(@"%@",noncestr);

    

    NSString *orderno   = [NSStringstringWithFormat:@"%ld",time(0)];

    NSMutableDictionary *packageParams = [NSMutableDictionarydictionary];

    [packageParams setObject:APP_ID             forKey:@"appid"];      //开放平台appid

    [packageParams setObject:MCH_ID             forKey:@"mch_id"];     //商户号

//    [packageParams setObject: @"013467007045764"        forKey:@"device_info"]; //支付设备号或门店号

    [packageParams setObject:@"1add1a30ac87aa2db52f57a2375d8fec"         forKey:@"nonce_str"];  //随机串

    [packageParams setObject:@"APP"            forKey:@"trade_type"]; //支付类型,固定为APP

    [packageParams setObject: order_name       forKey:@"body"];       //订单描述,展示给用户

    [packageParams setObject:@"http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php"       forKey:@"notify_url"]; //支付结果异步通知

    [packageParams setObject:@"1415659991"           forKey:@"out_trade_no"];//商户订单号

    [packageParams setObject: @"255.255.255.255"  forKey:@"spbill_create_ip"];//发器支付的机器ip

    [packageParams setObject: order_price      forKey:@"total_fee"];      //订单金额,单位为分

    [packageParams setObject:@"333"       forKey:@"attach"];

上面这是预支付订单你需要填写的基础参数 这是一个字典 然后把这些参数进行签名  MD5加密 XML解析 等等  

把上面的字典 传入下面

//提交预支付

-(NSString *)sendPrepay:(NSMutableDictionary *)prePayParams

{

    NSString *prepayid =nil;

    

    //获取提交支付

    NSString *send      = [selfgenPackage:prePayParams];        //这个地方是XML解析   

    

    NSLog(@"%@",send);

    payUrl =@"https://api.mch.weixin.qq.com/pay/unifiedorder";       //这是支付统一网址  



    //发送请求post xml数据

    NSData *res = [selfhttpSend:payUrlmethod:@"POST"data:send];

    

    NSLog(@"%@",res);          //在这个地方打印你的XML解析是否有问题   下面我给了XML解析



    

    NSLog(@"%@",[[NSStringalloc] initWithData:resencoding:NSUTF8StringEncoding]);          //转NSUTF8StringEncoding

    

   

       

 //开始解析

    [self startParse:res];

    

    NSMutableDictionary *resParams = [xmlgetDict];

    

    NSLog(@"%@",resParams);



    //判断返回

    NSString *return_code   = [resParamsobjectForKey:@"return_code"];

    NSString *result_code   = [resParamsobjectForKey:@"result_code"];

    if ( [return_codeisEqualToString:@"SUCCESS"] )

    {

        //生成返回数据的签名

        NSString *sign      = [selfcreateMd5Sign:resParams ];

        NSString *send_sign =[resParamsobjectForKey:@"sign"] ;

        

        //验证签名正确性

        if( [signisEqualToString:send_sign]){

            if( [result_codeisEqualToString:@"SUCCESS"]) {

                //验证业务处理状态

                prepayid    = [resParams objectForKey:@"prepay_id"];

                return_code = 0;



            }

        }else{

            last_errcode =1;

        }

    }else{

        last_errcode =2;

    }





//在这个地方成功 恭喜你  你的第一步 预支付订单已经出来了



    return prepayid;

}

//获取package带参数的签名包     拼接XML

-(NSString *)genPackage:(NSMutableDictionary*)packageParams

{

    NSString *sign;

    NSMutableString *reqPars=[NSMutableStringstring];

    //生成签名

    sign        = [selfcreateMd5Sign:packageParams];

    //生成xml的package

    NSArray *keys = [packageParamsallKeys];

    [reqPars appendString:@"<xml>\n"];

    for (NSString *categoryIdin keys) {

        [reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParamsobjectForKey:categoryId],categoryId];

    }

    [reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];

    

    return [NSStringstringWithString:reqPars];

}



//package 参数



-(NSString*) createMd5Sign:(NSMutableDictionary*)dict

{

    NSMutableString *contentString  =[NSMutableString string];

    NSArray *keys = [dict allKeys];

    //按字母顺序排序

    NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {

        return [obj1 compare:obj2 options:NSNumericSearch];

    }];

    //拼接字符串

    for (NSString *categoryId in sortedArray) {

        if (   ![[dict objectForKey:categoryId] isEqualToString:@""]

            && ![categoryId isEqualToString:@"sign"]

            && ![categoryId isEqualToString:@"key"]

            )

        {

            [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];

        }

        

    }

    //添加key字段

    NSLog(@"%@",spkey);

    

    [contentString appendFormat:@"key=%@", spkey];

    //得到MD5 sign签名

    NSString *md5Sign =[self md5:contentString];

    

    //输出Debug Info

    [debugInfo appendFormat:@"MD5签名字符串:\n%@\n\n",contentString];



    return md5Sign;

}



//MD5加密

-(NSString *) md5:(NSString *)str

{

    constchar *cStr = [str UTF8String];

    unsignedchar digest[CC_MD5_DIGEST_LENGTH];

    CC_MD5( cStr, (unsignedint)strlen(cStr), digest );

    

    NSMutableString *output = [NSMutableStringstringWithCapacity:CC_MD5_DIGEST_LENGTH *2];

    

    for(int i =0; i < CC_MD5_DIGEST_LENGTH; i++)

        [output appendFormat:@"%02X", digest[i]];

    

    return output;

}

//http 请求

-(NSData *) httpSend:(NSString *)url method:(NSString *)method data:(NSString *)data

{

    NSMutableURLRequest *request = [[NSMutableURLRequestalloc] initWithURL:[NSURLURLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheDatatimeoutInterval:5];

    //设置提交方式

    [request setHTTPMethod:method];

    //设置数据类型

    [request addValue:@"text/xml"forHTTPHeaderField:@"Content-Type"];

    //设置编码

    [request setValue:@"UTF-8"forHTTPHeaderField:@"charset"];

    //如果是POST

    [request setHTTPBody:[datadataUsingEncoding:NSUTF8StringEncoding]];

    

    NSError *error;

    //将请求的url数据放到NSData对象中

    NSData *response = [NSURLConnectionsendSynchronousRequest:request returningResponse:nilerror:&error];

    return response;

    //return [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];

}
//解析XML

-(void) startParse:(NSData *)data{



    dictionary =[NSMutableDictionarydictionary];

    contentString=[NSMutableStringstring];

    

    xmlElements = [[NSMutableArrayalloc] init];

    

    xmlParser = [[NSXMLParseralloc] initWithData:data];



    [xmlParsersetDelegate:self];

    [xmlParserparse];



}

============================================上面的就是你第一步需要做的事==========================================

如果下面的步骤你都成功了  恭喜  离成功就不远了  接下来进行第二次签名  也就是验证签名

//这个地方的prePayid 是你的预支付订单号 就是上面成功之后会出来一个订单号

if ( prePayid != nil) {

        //获取到prepayid后进行第二次签名

        

        NSString    *package, *time_stamp, *nonce_str;

        //设置支付参数

        time_t now;

        time(&now);

        time_stamp  = [NSStringstringWithFormat:@"%ld", now];

        nonce_str = [WXUtilmd5:time_stamp];

        //重新按提交格式组包,微信客户端暂只支持package=Sign=WXPay格式,须考虑升级后支持携带package具体参数的情况

        //package       = [NSString stringWithFormat:@"Sign=%@",package];

        package         = @"Sign=WXPay";

        //第二次签名参数列表

        NSMutableDictionary *signParams = [NSMutableDictionarydictionary];

        [signParams setObject:APP_ID        forKey:@"appid"];

        [signParams setObject: nonce_str   forKey:@"noncestr"];

        [signParams setObject: package     forKey:@"package"];

        [signParams setObject:MCH_ID        forKey:@"partnerid"];

        [signParams setObject: time_stamp  forKey:@"timestamp"];

        [signParams setObject: prePayid    forKey:@"prepayid"];

        //[signParams setObject: @"MD5"       forKey:@"signType"];

        //生成签名

          NSString *sign = [self  createMd5Sign:signParams];    //上面的package 参数

        

        //添加签名

        [signParams setObject: sign  forKey:@"sign"];

        

        NSLog(@"%@",sign);//这个地方出来的就是sign   二次验证的签名

          

        

        //返回参数列表

        return ;

        

    }else{

//获取订单号失败

    }

恭喜你到了这个地方说明上面的参数都对了 你就可以返回最上面我写的   拉起微信支付 把刚才拼出来的东西对应的填写进去,你就可以进行微信支付了

小弟写的比较陋  如果发现什么不妥之处  请告诉我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值