iOS - 微信支付详解

在iOS开发中,常常会涉及到支付功能,这里对常见的微信支付做一下详细说明

1. 微信支付

1.1 微信开放平台账号的注册

微信开放平台(微信支付需要付费的,注册成功后使用的主要为AppKey/SecretKey,其中SecrectKey交由后台完成集成)
微信开放平台是商户APP接入微信支付开放接口的申请入口,通过此平台可申请微信APP支付。
平台入口:http://open.weixin.qq.com

1.2 项目的修改与设置

1)首先应该下载SDK并导入项目(这里以友盟自带微信支付说明,具体内容相似)
如果项目中使用了友盟社会化分享SDK,那么你将不需要重复导入SDK,友盟中已经集成了微信支付。具体SDK如下:
iOS - 微信支付详解
如果你的项目没有使用友盟,请到开放平台下载最新的SDK,然后倒入您的项目。具体的SDK如下:
iOS - 微信支付详解
2)在添加完SDK后需要添加相应的库以及文件
iOS - 微信支付详解
3)然后是添加对应的url用于调起
iOS - 微信支付详解
4) 添加白名单、关闭Bitcode(对于http/https适配iOS9.0自行修改)
iOS - 微信支付详解
iOS - 微信支付详解

1.3 SDK的注册与回调

在完成了上面的操作之后,我们所导入的SDK就可以使用了,很简单
1) 首先我们要进行注册
导入#import “WXApi.h”

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    ViewController *userGuideViewController = [[ViewController alloc] init];
    self.window.rootViewController = userGuideViewController;
    [WXApi registerApp:@"这里添加APPKey"];
    return YES;
}

2)接着我们要写一个调起

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
    // 跳转到URL scheme中配置的地址
    //NSLog(@"跳转到URL scheme中配置的地址-->%@",url);
    return [WXApi handleOpenURL:url delegate:(id<WXApiDelegate>)self];
}

3)然后是回调

//支付成功时调用,回到第三方应用中
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    //    NSLog(@"****************url.host -- %@",url.host);
    if ([url.scheme isEqualToString:@"这里添加AppKey"])
    {
        return  [WXApi handleOpenURL:url delegate:(id<WXApiDelegate>)self];
    }
    return YES;
}
- (void) onResp:(BaseResp*)resp
{
    NSString *strMsg = [NSString stringWithFormat:@"errcode:%d", resp.errCode];
    NSString *strTitle = @"支付结果";

    if([resp isKindOfClass:[PayResp class]]){

        switch (resp.errCode) {
            case WXSuccess:
                strMsg = @"支付结果:成功!";

                break;
            case WXErrCodeUserCancel:
                strMsg = @"支付结果:用户点击取消!";

                break;
            case WXErrCodeSentFail:
                strMsg = @"支付结果:发送失败!";

                break;
            case WXErrCodeAuthDeny:
                strMsg = @"支付结果:授权失败!";

                break;

            default:
                strMsg = @"支付结果:微信不支持!";

                break;
        }
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }
}

1.4 SDK的使用

1) 最后是在项目中需要进行微信支付的地方使用支付(这是完成整个支付流程中最重要的一部分,也是最需要注意的地方
首先要进行一次网络请求,后台接口,将你的商品信息发送到后台,生成订单后返回,返回信息中最少要包含六个参数,通过这些参数调起支付。
导入#import “WXApi.h”

//返回参数调起支付
PayReq* req             = [[PayReq alloc] init];
            NSMutableDictionary *dict=[result objectForKey:@"resultCode"];

            req.openID              = [dict objectForKey:@"appid"];
            req.partnerId           = [dict objectForKey:@"mch_id"];
            req.prepayId            = [dict objectForKey:@"prepay_id"];
            req.nonceStr            = [self md5:time_stamp];
            req.timeStamp           = [time_stamp intValue];
            req.package             = @"Sign=WXpay";

            //签名(这个签名可以自己进行签名,也可以后台操作,由后台返回)
            NSMutableDictionary *signParams=[[NSMutableDictionary alloc] init];
            [signParams setObject: req.openID        forKey:@"appid"];
            [signParams setObject: req.nonceStr    forKey:@"noncestr"];
            [signParams setObject: req.package      forKey:@"package"];
            [signParams setObject: req.partnerId        forKey:@"partnerid"];
            [signParams setObject: time_stamp   forKey:@"timestamp"];
            [signParams setObject: req.prepayId     forKey:@"prepayid"];
            req.sign                = [self createMd5Sign:signParams];

            //调起支付(**参数有一个错误,将不能完成调起**)
            [WXApi sendReq:req];

2) 自行加密处理(这部分可以由后台完成)

//微信支付加密
-(NSString *) md5:(NSString *)str
{
    const char *cStr = [str UTF8String];
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5( cStr, (unsigned int)strlen(cStr), digest );

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

    for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
        [output appendFormat:@"%02X", digest[i]];

    return output;
}

-(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字段
    [contentString appendFormat:@"key=%@", @"这里添加SecretKey"];

    NSString *md5Sign =[WXUtil md5:contentString];

    return md5Sign;
}

1.5常见异常Bug处理

1) 常见问题为微信支付调起不成功,每次调起只能调起一个带有你返回确认按钮的页面。
原因:参数错误,特别注意参数(签名),后台的返回的参数不正确。
解决方案:逐个校验参数,签名可以本地加密处理,不要依赖后台的返回签名,有的时候后台返回的是不正确的。

iOS - 微信支付详解

上一篇:模仿微信图片点击全屏效果


下一篇:微信支付开发(6) 收货地址共享接口 【转发收藏】