iOS

iOS微信支付集成

微信支付签名比较麻烦,两次签名把我们后台绕晕了,客户端来说也还是比较简单。

Posted by yasin on April 6, 2016

导入

和支付宝一样拖进去就可以了。报错的话照官方文档拖些库进去。

集成

	//设置微信支付
    [WXApi registerApp:@"你的AppId" withDescription:@"应用附加信息,我写的是bundelID+一些字符"];
    
    如果你用了友盟的分享的话最好把分享的方法放在前面。
    [UMSocialWechatHandler setWXAppId:@"" appSecret:@"" url:@""];

生成订单

有一点要注意的是微信的支付单位为分,要支付1块钱就要传100过去。 同样微信也是应该在服务器进行签名,如果要本地签名就先创建一个字典,设置下面的这些参数。

| 参数名 | 值 | |——–|——–| | appid | 开放平台appid | | mch_id | 商户号 | | nonce_str | 随机串 | | trade_type | 支付类型,固定为APP | | body | 订单描述,展示给用户 | | out_trade_no | 商户订单号 | | total_fee | 订单金额,单位为分 | | spbill_create_ip | 发器支付的机器ip | | notify_url | 支付结果异步通知 | |sign|对上面的参数签名得到的| 把这个字典签名去掉微信的统一下单接口

签名的代码
- (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;
}

第二次签名

微信同意下单接口会返回一个字典,但是我们只需要里面的prepayid这个参数,重新创建一个字典包含下面的参数

参数名
appid 开放平台appid
partnerid 商户号
noncestr 随机串
package Sign=WXPay不变
timestamp 时间戳
prepayid 统一下单接口返回的
sign 对上面的参数签名得到的

调用微信的支付接口

如果你们的后台直接签完名给你,你可以直接从这里开始看,用后台传给你的字典直接调用微信的支付放久就OK了

[WXApi sendReq:request];//request是拥有上面这些值得字典

回调


回调先要在AppDelegate的这个方法里面加入
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
	//先判断是微信支付返回的
	if([url.absoluteString rangeOfString:@"你的WXAppId://pay"].length){
    	//调用代理的方法执行支付完成回调
        return [WXApi handleOpenURL:url delegate:实现了代理方法的对象];
    }
}

代理要实现这个方法
-(void)onResp:(BaseResp*)resp{
    if ([resp isKindOfClass:[PayResp class]]){
        PayResp*response=(PayResp*)resp;
        switch(response.errCode){
            case WXSuccess:
                NSLog(@"支付成功");
                break;
            default:
            	NSLog(@"支付失败");
                break;
        }
    }
}

优化

支付宝和微信属于一个支付管理单例来管理 我对微信的方法进行了封装,变成了下面这个样子

//通过微信的订单类来发起支付
-(void)weixinPayWithPayReq:(PayReq *)payReq andSuc:(weixinSuc)suc andErr:(weixinErr)err{
	self.weixinSuc=suc;
    self.weixinErr=err;
    [WXApi sendReq:payReq];
}
//通过后台返回的数据来发起支付
-(void)weixinPayWithdatePay:(NSDictionary *)datePay andSuc:(weixinSuc)suc andErr:(weixinErr)err{
	PayReq *request = [[PayReq alloc] init];
    request.partnerId = datePay[@"partnerid"];//商户号
    request.prepayId= datePay[@"prepayid"];//预支付交易会话ID
    request.package = @"Sign=WXPay";//扩展字段
    request.nonceStr= datePay[@"noncestr"];//随机字符串
    request.timeStamp= [datePay[@"timestamp"] intValue];//时间戳
    request.sign= datePay[@"sign"];//签名
    [self weixinPayWithPayReq:request andSuc:suc andErr:err];
}

这样在外边只需要把支付完成或失败后的代码写在block里面就可以了