美文网首页
iOS 微信支付(客户端下单)

iOS 微信支付(客户端下单)

作者: lancely | 来源:发表于2017-03-15 11:15 被阅读71次

    一、注册登录微信开放平台账号

    1. 注册登录微信开放平台账号
    2. 添加一个用于支付/分享的移动应用,等待审核通过
    3. 前往管理中心-移动应用,为通过审核的移动应用申请支付功能,并等待审核通过
      申请支付功能

    详细步骤参照微信支付官方文档 微信APP支付接入商户服务中心

    二、集成微信SDK

    • 前往微信资源中心下载 iOS 的 SDK,并添加到项目中

      集成SDK
    • 编辑 info.plist,将微信添加到 APP 跳转白名单

      添加白名单
    • Targets-Info-URL Types 添加微信的 APP_ID

      设置 URL Types
    • AppDelegate 处理相关回调(需要#import "WXApi.h"

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
        // 注册(如果使用了友盟,则先注册友盟)
        [WXApi registerApp:@"wxd930ea5d5a258f4f"];
        
        return YES;
    }
    
    - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
        return [WXApi handleOpenURL:url delegate:self];
    }
    
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
        return [WXApi handleOpenURL:url delegate:self];
    }
    
    // 微信支付结果的回调
    - (void)onResp:(BaseResp *)resp {
        //启动微信支付的response
        NSString *strMsg = [NSString stringWithFormat:@"errcode:%d", resp.errCode];
        BOOL paySuccess = false;
        if([resp isKindOfClass:[PayResp class]]){
            //支付返回结果,实际支付结果需要去微信服务器端查询
            switch (resp.errCode) {
                case 0:
                    strMsg = @"支付结果:成功!";
                    paySuccess = true;
                    break;
                case -1:
                    strMsg = @"支付结果:失败!";
                    break;
                case -2:
                    strMsg = @"用户已经退出支付!";
                    break;
                default:
                    strMsg = [NSString stringWithFormat:@"支付结果:失败!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
                    break;
            }
        }
        NSNotification *nofity = [[NSNotification alloc] initWithName:kNofificationWechatPayCallback object:nil userInfo:@{@"success":paySuccess ? @(YES) : @(NO) ,@"errMsg":paySuccess ? @"" : strMsg}];
        [[NSNotificationCenter defaultCenter] postNotification:nofity];
    }
    
    • 定义几个需要用到的常量
    // 商户号
    static NSString *const kWx_MchId = @"YOUR_MCH_ID";
    // AppId
    static NSString *const kWx_AppId = @"YOUR_WX_AppID";
    // 商户API密钥,商户平台登录账户和密码登录http://pay.weixin.qq.com 平台设置的“API密钥”,为了安全,请设置为以数字和字母组成的32字符串。
    static NSString *const kWx_PartnerKey = @"YOUR_WX_PartnerKey";
    // AppSecret
    static NSString *const kWx_AppSecret = @"YOUR_WX_AppSecret";
    // 服务端接收支付异步通知回调地址
    static NSString *const kWx_NotifyURL = @"http://www.xxx.com/xxx.php";
    
    • 调用微信支付关键代码
    /**
     微信支付
    
     @param orderNo 订单号
     @param orderDesc 订单信息
     @param fee 金额(分)
     */
    - (void)payWithOrderNo:(NSString *)orderNo orderDescription:(NSString *)orderDesc fee:(NSInteger)fee {
        // 请求参数 (参数说明:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1)
        NSMutableDictionary *params = @{}.mutableCopy;
        params[@"appid"] = kWx_AppId; // 应用ID!
        params[@"mch_id"] = kWx_MchId; // 商户号!
        params[@"nonce_str"] = ({ // 随机字符串!
            srand( (unsigned)time(0) );
            [NSString stringWithFormat:@"%d", rand()];
        });
        params[@"body"] = orderDesc; // 商品描述!
        params[@"out_trade_no"] = kWx_AppId; // 商户订单号!
        params[@"total_fee"] = @(fee); // 总金额!
        params[@"spbill_create_ip"] = @"196.168.1.1"; // 终端IP!
        params[@"notify_url"] = kWx_NotifyURL; // 通知地址!
        params[@"trade_type"] = @"APP"; // 交易类型!
        params[@"sign"] = [self getSign:params]; // 签名!
        
        // 转成xml
        NSMutableString *xmlParams = @"".mutableCopy;
        [xmlParams appendString:@"<xml>"];
        [params enumerateKeysAndObjectsUsingBlock:^(NSString *  _Nonnull key, id  _Nonnull value, BOOL * _Nonnull stop) {
            [xmlParams appendFormat:@"<%@>%@</%@>", key, value, key];
        }];
        [xmlParams appendString:@"</xml>"];
        // 发送请求
        NSURLSession *session = [NSURLSession sharedSession];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api.mch.weixin.qq.com/pay/unifiedorder"]];
        request.HTTPMethod = @"POST";
        request.HTTPBody = [xmlParams dataUsingEncoding:NSUTF8StringEncoding];
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (!error) {
                // 返回的是xml
                NSString *respXml = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                // 转换成字典
                NSDictionary *respDict = [[[XEXMLHelper alloc] init] parseXML:respXml];
                NSString *return_code = respDict[@"return_code"];
                NSString *result_code = respDict[@"result_code"];
                if ([return_code isEqualToString:@"SUCCESS"] && [result_code isEqualToString:@"SUCCESS"]) {
                    // 调起微信
                    PayReq *req = [[PayReq alloc] init];
                    req.partnerId = kWx_MchId;
                    req.prepayId = respDict[@"prepayId"];
                    req.nonceStr = respDict[@"nonce_str"];
                    req.timeStamp = (UInt32)[[NSDate date] timeIntervalSince1970];
                    req.package = @"Sign=WXPay";
                    // 传入参数进行二次签名
                    req.sign = [self getSign:@{
                                               @"appid": kWx_AppId,
                                               @"partnerid": req.partnerId,
                                               @"noncestr": req.nonceStr,
                                               @"package": req.package,
                                               @"timestamp": @(req.timeStamp).stringValue,
                                               @"prepayid": req.prepayId
                                               }];
                    [WXApi sendReq:req];
                }
                else {
                    NSLog(@"接口返回错误, %@", respDict);
                }
            }
            else {
                NSLog(@"%@", error);
            }
        }];
        [task resume];
    }
    
    /**
     MD5加密
    
     @param sourceString 源字符串
     @return 加密后的字符串
     */
    - (NSString *)getMD5:(NSString *)sourceString {
        NSData *data = [sourceString dataUsingEncoding:NSUTF8StringEncoding];
        unsigned char result[CC_MD5_DIGEST_LENGTH];
        CC_MD5(data.bytes, (CC_LONG)data.length, result);
        return [NSString stringWithFormat:
                @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                result[0], result[1], result[2], result[3],
                result[4], result[5], result[6], result[7],
                result[8], result[9], result[10], result[11],
                result[12], result[13], result[14], result[15]
                ];
    }
    
    /**
     生成签名参数sign
    
     @param params 参数
     @return sign
     */
    - (NSString *)getSign:(NSDictionary *)params {
        NSMutableString *contentString  =[NSMutableString string];
        NSArray *keys = [params allKeys];
        //按字母顺序排序
        NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            return [obj1 compare:obj2 options:NSNumericSearch];
        }];
        //拼接字符串
        for (NSString *categoryId in sortedArray) {
            if (![[params objectForKey:categoryId] isEqualToString:@""]
                && ![categoryId isEqualToString:@"sign"]
                && ![categoryId isEqualToString:@"key"]
                ) {
                [contentString appendFormat:@"%@=%@&", categoryId, [params objectForKey:categoryId]];
            }
            
        }
        //添加key字段
        [contentString appendFormat:@"key=%@", kWx_PartnerKey];
        //得到MD5 sign签名
        NSString *sign = [self getMD5:contentString];
        return sign;
    }
    
    

    相关文章

      网友评论

          本文标题:iOS 微信支付(客户端下单)

          本文链接:https://www.haomeiwen.com/subject/jkklnttx.html