iOS微信APP支付V3版本源码

来源:互联网 发布:球球大作战小糖果软件 编辑:程序博客网 时间:2024/05/18 00:15

之前做微信APP支付的时候,发现微信APP支付版本升级 -----> 申请支付能力成功之后,不再提供APP_KEY这个参数。 去网上找了找demo,发现并没有现成的可以拿来用,只好自己去看微信官方提供的API, 不得不说,这文档给的真的是烂~   源码在https://github.com/dawnBefore/WeChatPayV3


一. 调用统一下单API

统一下单API(见下图),这里就是要把所有要传的参数POST到红线标的URL去,然后微信会返回给你XML格式的数据,其中就包括我们要拿的prepay_id


1. 拿到签名sign

// 发送给微信的XML格式- (NSString *)genPackage:(NSMutableDictionary*)packageParams{    NSString *sign;    NSMutableString *reqPars = [NSMutableString string];        // 生成签名    sign = [self genSign:packageParams];        // 生成xml格式的数据, 作为post给微信的数据    NSArray *keys = [packageParams allKeys];    [reqPars appendString:@"<xml>"];    for (NSString *categoryId in keys) {        [reqPars appendFormat:@"<%@>%@</%@>"         , categoryId, [packageParams objectForKey:categoryId],categoryId];    }    [reqPars appendFormat:@"<sign>%@</sign></xml>", sign];        return [NSString stringWithString:reqPars];}

微信给出的必填的参数有十个(注意:sign这个参数是拿其他的参数通过微信的签名算法得到的,得到sign后加上其余的参数一起POST给上面的URL)



这里我是把其余的九个参数放在字典里,准备签名


NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];        [packageParams setObject: WXAppId      forKey:@"appid"];       //开放平台appid    [packageParams setObject: WXPartnerId  forKey:@"mch_id"];      //商户号    [packageParams setObject: noncestr     forKey:@"nonce_str"];   //随机串    [packageParams setObject: orderType    forKey:@"trade_type"];  //支付类型,固定为APP    [packageParams setObject: orderName    forKey:@"body"];        //订单描述,展示给用户    [packageParams setObject: orderNO      forKey:@"out_trade_no"];//商户订单号    [packageParams setObject: orderPrice   forKey:@"total_fee"];   //订单金额,单位为分    [packageParams setObject: [CommonUtil getIPAddress:YES] forKey:@"spbill_create_ip"];//发器支付的机器ip    [packageParams setObject: @"http://weixin.qq.com"  forKey:@"notify_url"];  //支付结果异步通知

下面是微信签名的算法


- (NSString *)genSign:(NSDictionary *)signParams{    // 排序, 因为微信规定 ---> 参数名ASCII码从小到大排序    NSArray *keys = [signParams allKeys];    NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {        return [obj1 compare:obj2 options:NSNumericSearch];    }];        //生成 ---> 微信规定的签名格式    NSMutableString *sign = [NSMutableString string];    for (NSString *key in sortedKeys) {        [sign appendString:key];        [sign appendString:@"="];        [sign appendString:[signParams objectForKey:key]];        [sign appendString:@"&"];    }    NSString *signString = [[sign copy] substringWithRange:NSMakeRange(0, sign.length - 1)];        // 拼接API密钥    NSString *result = [NSString stringWithFormat:@"%@&key=%@", signString, WXAPIKey];    // 打印检查    NSLog(@"result = %@", result);    // md5加密    NSString *signMD5 = [CommonUtil md5:result];    // 微信规定签名英文大写    signMD5 = signMD5.uppercaseString;    // 打印检查    NSLog(@"signMD5 = %@", signMD5);    return signMD5;}


2. 拿到签名后,将数据POST给微信,微信要求POST的数据为XML格式


// 发送给微信的XML格式数据- (NSString *)genPackage:(NSMutableDictionary*)packageParams{    NSString *sign;    NSMutableString *reqPars = [NSMutableString string];        // 生成签名    sign = [self genSign:packageParams];        // 生成xml格式的数据, 作为post给微信的数据    NSArray *keys = [packageParams allKeys];    [reqPars appendString:@"<xml>"];    for (NSString *categoryId in keys) {        [reqPars appendFormat:@"<%@>%@</%@>"         , categoryId, [packageParams objectForKey:categoryId],categoryId];    }    [reqPars appendFormat:@"<sign>%@</sign></xml>", sign];        return [NSString stringWithString:reqPars];}

3. 微信返回的数据也为XML格式,我这里用的GData解析,大家也可以各显神通,返回中的数据就有我们想要的prepay_id


// 获取prePayId- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams{        // 获取提交预支付的xml格式数据    NSString *send = [self genPackage:prePayParams];    // 打印检查, 格式应该是xml格式的字符串    NSLog(@"%@", send);        // 转换成NSData    NSData *data_send = [send dataUsingEncoding:NSUTF8StringEncoding];    NSURL *url = [NSURL URLWithString:getPrePayIdUrl];    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];    [request setHTTPMethod:@"POST"];    [request setHTTPBody:data_send];    NSError *error = nil;    // 拿到data后, 用xml解析, 这里随便用什么方法解析    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];    if (!error) {        // 1.根据data初始化一个GDataXMLDocument对象        GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];        // 2.拿出根节点        GDataXMLElement *rootElement = [document rootElement];        GDataXMLElement *return_code = [[rootElement elementsForName:@"return_code"] lastObject];        GDataXMLElement *return_msg = [[rootElement elementsForName:@"return_msg"] lastObject];        GDataXMLElement *result_code = [[rootElement elementsForName:@"result_code"] lastObject];        GDataXMLElement *prepay_id = [[rootElement elementsForName:@"prepay_id"] lastObject];        // 如果return_code和result_code都为SUCCESS, 则说明成功        NSLog(@"return_code---%@", [return_code stringValue]);        // 返回信息,通常返回一些错误信息        NSLog(@"return_msg---%@", [return_msg stringValue]);        NSLog(@"result_code---%@", [result_code stringValue]);        // 拿到这个就成功一大半啦        NSLog(@"prepay_id---%@", [prepay_id stringValue]);            return [prepay_id stringValue];    } else {        return nil;    }}

二. 拿到prepay_id后就完成了一大半了,接下来就再次签名调起微信支付就好了

if(prePayid){        NSString *timeStamp = [self genTimeStamp];        // 调起微信支付        PayReq *request = [[PayReq alloc] init];        request.partnerId = WXPartnerId;        request.prepayId = prePayid;        request.package = @"Sign=WXPay";        request.nonceStr = noncestr;        request.timeStamp = [timeStamp intValue];        // 这里要注意key里的值一定要填对, 微信官方给的参数名是错误的,不是第二个字母大写        NSMutableDictionary *signParams = [NSMutableDictionary dictionary];        [signParams setObject: WXAppId               forKey:@"appid"];        [signParams setObject: WXPartnerId           forKey:@"partnerid"];        [signParams setObject: request.nonceStr      forKey:@"noncestr"];        [signParams setObject: request.package       forKey:@"package"];        [signParams setObject: timeStamp             forKey:@"timestamp"];        [signParams setObject: request.prepayId      forKey:@"prepayid"];                //生成签名        NSString *sign  = [self genSign:signParams];                //添加签名        request.sign = sign;                [WXApi sendReq:request];                    } else{        NSLog(@"获取prePayId失败!");    }


附:这里有一些重要的参数大家可能不知道去哪拿, 比如:微信支付商户号(mch_id),   API密钥(用于签名拼接在最后面),其实这些应该公司都给好的,大家也不必担心

微信支付商户号:这里有一些申请条件,贴出来给大家看看, 商户号就在申请成功后发给我们的邮件里

API密钥:同时在邮件里面给我们的还有  商户平台登录账号  和  商户平台登录密码  商户平台是另一个平台 这是网址 https://pay.weixin.qq.com/index.php/home/login?return_url=/



好了到这里就结束了,回调什么的按照自己公司的规则来,回调方法微信文档里也都给了,微博没看懂的可以直接下载看源码https://github.com/dawnBefore/WeChatPayV3 ,如果喜欢就随手给个星星吧

2 0
原创粉丝点击