当微信和支付宝遇上友盟

前言:

支付,分享,第三方登录,即时通讯这些在现在的APP当中慢慢的变成了最基本,当这些技术已经慢慢的融入到人们的生活中的时候,这些也就成了APP最基本的需求,以前这部分的内容也是经常做,但就是没有好好的总结过,首先说说这几个点,支付的话我们就说说支付宝和微信吧,把我看到的收藏的好点的文章也全都分享出来,第三方登录和分享我用的一直都是友盟的,不为别的,只是友盟的统计和第三方登录分享这些都是一套SDK,就直接用友盟,友盟和微信的回调这里也有一些我们注意的,下面也会和大家说。

微信和支付宝:

其实这些支付麻烦的地方就是这些签名的操作,你要是把这些放在前端App的话的确是不安全的,所以这些最好都放在服务端,这些放在服务端其实你所要写的代码,估计也就十多行了!就像下面一样,下面方法是一个完整的微信请求后台操作,里面的参数你可以不用管,你看一下这个过程,你把后台需要的参数传给后台,你取到后台返回给你的信息,你再把这些信息给微信就OK,可我想说的并不是建议你粘贴这十多行代码就往事大吉了,想说的是希望把这整个过程和当中我们需要注意的一些地方给大家说说;

注意:这里说一点,如果你APP的微信支付功能审核的时候,你是先在微信平台添加了功能再提交申请的,可审核没通过,后来纠结几次才过了的。你在APP当中使用支付功能的时候,先在微信平台APP 的移动支付功能先删除再添加一次!不然它永远都是用不了!

        // 调用微信支付
        [MBPSecondary showMBProgressHUDWithText:@"请稍等..." ToView:self.view];
        [WXPayViewModel RequestWXpayWithBody:@"明星私募网微信支付" andJsonString:bodyString  andTotalfee:priceString withRequestSuccess:^(NSDictionary *payDictionary) {

            [MBPSecondary hideMBProgressHUDWith:self.view];
            NSMutableString * stamp = [payDictionary objectForKey:@"timestamp"];

            //调起微信支付
            PayReq* request             = [[PayReq alloc] init];
            request.openID              = [payDictionary objectForKey:@"appid"];
            request.partnerId           = [payDictionary objectForKey:@"mch_id"];
            request.prepayId            = [payDictionary objectForKey:@"prepay_id"];
            request.nonceStr            = [payDictionary objectForKey:@"nonce_str"];
            request.timeStamp           = stamp.intValue;
            request.package             = @"Sign=WXPay";  // 这个参数可以直接写死
            request.sign                = [payDictionary objectForKey:@"sign"];

            //微信支付
            [WXApi sendReq:request];

        } andRequestFail:^(NSString *message) {

            [MBPSecondary hideMBProgressHUDWith:self.view];
            [MBPSecondary showMBProgressHUDWithText:message andType:FAILED];

        }];

我们先看看微信的整个支付的流程图:

这里需要注意的几个点:

一:签名过程不要放在前端

二:返回结果最好去服务端验证,你要回调之后直接使用。

下面是我们在本地测试微信支付的时候的源码,这个过程就是把服务端做的事放在了我们移动前端,你要想试试我们自己在本地做微信支付,不经过服务端的话里面有些文件比如XML格式数据转字典,MD5加密这些文件你要需要的可以加我Q我发给你!。

#pragma mark - 微信支付相关测试方法
- (void)weixinChooseAct {

    NSString *appid,*mch_id,*nonce_str,*sign,*body,*out_trade_no,*total_fee,*spbill_create_ip,*notify_url,*trade_type,*partner,*attach;
    //应用APPID
    appid  = WX_AppID;
    attach = @"test";
    //微信支付商户号
    mch_id = MCH_ID;
    //产生随机字符串,这里最好使用和安卓端一致的生成逻辑
    nonce_str = [self generateTradeNO];
    body = @"test";
    //随机产生订单号用于测试,正式使用请换成你从自己服务器获取的订单号
    out_trade_no = [self generateTradeNO];
    //交易价格1表示0.01元,10表示0.1元
    total_fee = @"1";
    //获取本机IP地址,请再wifi环境下测试,否则获取的ip地址为error,正确格式应该是8.8.8.8
    spbill_create_ip = [getIPhoneIP getIPAddress];
    //spbill_create_ip = @"0.0.0.1";

    //交易结果通知网站此处用于测试,随意填写,正式使用时填写正确网站
    notify_url = @"http://120.76.214.93:8080/mxsm_app_api/common/zfb/callbacks.do";
    trade_type = @"APP";
    //商户密钥
    partner = WX_PartnerKey;
    //获取sign签名
    DataMD5 * data = [[DataMD5 alloc] initWithAppid:appid mch_id:mch_id nonce_str:nonce_str partner_id:partner body:body out_trade_no:out_trade_no total_fee:total_fee spbill_create_ip:spbill_create_ip notify_url:notify_url trade_type:trade_type];
    //
    sign = [data getSignForMD5];

    //设置参数并转化成xml格式
    NSMutableDictionary *  dic = [NSMutableDictionary dictionary];
    [dic setValue:appid            forKey:@"appid"];           //公众账号ID
    [dic setValue:mch_id           forKey:@"mch_id"];          //商户号
    [dic setValue:nonce_str        forKey:@"nonce_str"];       //随机字符串
    [dic setValue:body             forKey:@"body"];            //商品描述
    [dic setValue:out_trade_no     forKey:@"out_trade_no"];    //订单号
    [dic setValue:total_fee        forKey:@"total_fee"];       //金额
    [dic setValue:spbill_create_ip forKey:@"spbill_create_ip"];//终端IP
    [dic setValue:notify_url       forKey:@"notify_url"];      //通知地址
    [dic setValue:trade_type       forKey:@"trade_type"];      //交易类型
    [dic setValue:sign             forKey:@"sign"];            //签名

    // 转换成xml字符串
    NSString * string = [dic XMLString];
    [self http:string];
}

#pragma mark - 拿到转换好的xml发送请求
- (void)http:(NSString *)xml {

    AFHTTPSessionManager * manager = [AFHTTPSessionManager manager];
    // 这里传入的xml字符串只是形似xml,但是不是正确是xml格式,需要使用af方法进行转义
    manager.responseSerializer     = [[AFHTTPResponseSerializer alloc] init];
    [manager.requestSerializer setValue: @"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [manager.requestSerializer setValue: @"https://api.mch.weixin.qq.com/pay/unifiedorder" forHTTPHeaderField:@"SOAPAction"];
    [manager.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error) {
        return xml;
    }];

    // post 请求微信
    [manager POST:@"https://api.mch.weixin.qq.com/pay/unifiedorder" parameters:xml progress:^(NSProgress * _Nonnull uploadProgress) {

    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        NSString *responseString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding] ;
        // 将微信返回的xml数据解析转义成字典
        NSDictionary *dic = [NSDictionary dictionaryWithXMLString:responseString];
        // 判断返回的许可
        if ([[dic objectForKey:@"result_code"] isEqualToString:@"SUCCESS"] && [[dic objectForKey:@"return_code"] isEqualToString:@"SUCCESS"]) {
            // 发起微信支付,设置参数
            PayReq *request   = [[PayReq alloc] init];
            request.openID    = [dic objectForKey:@"appid"];
            request.partnerId = [dic objectForKey:@"mch_id"];
            request.prepayId  = [dic objectForKey:@"prepay_id"];
            request.package   = @"Sign=WXPay";
            request.nonceStr  = [dic objectForKey:@"nonce_str"];
            // 将当前事件转化成时间戳
            NSDate *datenow   = [NSDate date];
            NSString *timeSp  = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];
            UInt32 timeStamp  = [timeSp intValue];
            request.timeStamp = timeStamp;

            // 签名加密
            DataMD5 *md5 = [[DataMD5 alloc] init];
            request.sign = [md5 createMD5SingForPay:request.openID partnerid:request.partnerId prepayid:request.prepayId package:request.package noncestr:request.nonceStr timestamp:request.timeStamp];
            // 调用微信
            [WXApi sendReq:request];

        }else{

            // NSSLog(@"参数不正确,请检查参数");
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

            // NSSLog(@"error is %@",error);
    }];
}

#pragma mark - 产生随机订单号
-(NSString *)generateTradeNO{

    static int kNumber = 15;

    NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    NSMutableString *resultStr = [[NSMutableString alloc] init];
    srand((unsigned)time(0));
    for (int i = 0; i < kNumber; i++){

        unsigned index = rand() % [sourceStr length];
        NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, 1)];
        [resultStr appendString:oneStr];
    }
    return resultStr;
}

上面就是我们说的微信的,再说说这个支付宝的,我们先看看支付宝的一个流程图:

支付宝注意点:

一:如果你是在SDK的接入过程当中有问题的话你可以看看这篇博客  iOS接入支付宝支付(小白都能看懂的支付宝支付)

二:支付宝的一些注意事项和微信的有点相同,该放服务端的放在服务端

三:检测配置好你的公钥和私钥,你可以利用支付宝给的检测工具进行一下验证!确保他们没问题再上传!这一点很重要。

下面是可以本地测试源码,给大家看看:

//**** 重要说明 ****
//这里只是为了方便直接展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
//真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;
//防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;
/*============================================================================*/
/*=============================支付宝流程测试================*/

-(void)doAlipayPay{

    NSString *appID = @"";      // AppId
    NSString *privateKey = @""; // 用户私钥
    //partner和seller获取失败,提示
    if ([appID length] == 0 ||[privateKey length] == 0){

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"缺少appId或者私钥。" delegate:self  cancelButtonTitle:@"确定" otherButtonTitles:nil];
        [alert show];
        return;
    }

    //生成订单信息及签名
    //将商品信息赋予AlixPayOrder的成员变量
    Order * order = [Order new];

    // NOTE: app_id设置
    order.app_id = appID;

    // NOTE: 支付接口名称
    order.method = @"alipay.trade.app.pay";

    // NOTE: 参数编码格式
    order.charset = @"utf-8";

    // NOTE: 当前时间点
    NSDateFormatter* formatter = [NSDateFormatter new];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    order.timestamp = [formatter stringFromDate:[NSDate date]];

    // NOTE: 支付版本,固定格式,暂时不需要修改
    order.version = @"1.0";

    // NOTE: sign_type设置
    order.sign_type = @"RSA";

    // NOTE: 商品数据
    order.biz_content = [BizContent new];
    order.biz_content.body = @"我是测试数据";
    order.biz_content.subject = @"1";
    order.biz_content.out_trade_no = [self generateTradeNO];         //订单ID(由商家自行制定)
    order.biz_content.timeout_express = @"30m";                      //超时时间设置
    order.biz_content.total_amount = [NSString stringWithFormat:@"%.2f", 0.01]; //商品价格

    //将商品信息拼接成字符串
    NSString *orderInfo = [order orderInfoEncoded:NO];
    NSString *orderInfoEncoded = [order orderInfoEncoded:YES];
    NSLog(@"orderSpec = %@",orderInfo);

    // NOTE: 获取私钥并将商户信息签名,外部商户的加签过程请务必放在服务端,防止公私钥数据泄露;
    //       需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
    id<DataSigner> signer = CreateRSADataSigner(privateKey);
    NSString *signedString = [signer signString:orderInfo];

    // NOTE: 如果加签成功,则继续执行支付
    if (signedString != nil) {
        //应用注册scheme,在AliSDKDemo-Info.plist定义URL types
        NSString *appScheme = @"alisdkdemo";

        // NOTE: 将签名成功字符串格式化为订单字符串,请严格按照该格式
        NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@",
                                 orderInfoEncoded, signedString];

        // NOTE: 调用支付结果开始支付
        [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {

            NSLog(@"reslut = %@",resultDic);

        }];
    }
}

// 随机产生一个订单号
- (NSString *)generateTradeNO
{
    static int kNumber = 15;
    NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    NSMutableString *resultStr = [[NSMutableString alloc] init];
    srand((unsigned)time(0));
    for (int i = 0; i < kNumber; i++){

        unsigned index = rand() % [sourceStr length];
        NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, 1)];
        [resultStr appendString:oneStr];
    }
    return resultStr;
}

再说说这篇博客的重点,支付宝、微信和友盟在一起时候的回调!

说说微信和友盟的注意事项,注意下面代理中的注释,那些注意的点全都加载代码的注释里面了;

/******  支付和第三方登录分享回调注意事项

   还有方法不过这个方法的系统版本最低要求是9.0
   (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options

   // NOTE:微信回调在9.0之后还是会进入这里的,但这里就有一个微信回调和友盟回调冲突的问题,按照最开始这样写回调的话会造成微信支付成功不回调的现象,主要原因是微信支付,通过友盟判断,返回的结果是YES
       BOOL UMShareResult = [[UMSocialManager defaultManager] handleOpenURL:url];

   返回的结果示例:
   (lldb) po url 微信支付
   wx47e8322e53c76163://pay/?returnKey=&ret=0

   (lldb) po url 第三方登录
   wx47e8322e53c76163://oauth?code=001J9HPU1SYnGS05xpOU1hpHPU1J9HPS&lang=zh_HK&country=CN&state=

   (lldb) po url 微信分享
   wx47e8322e53c76163://platformId=wechat

   // NOTE:错误方法如下
   -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{

    // 友盟SDK的回调
    BOOL UMShareResult = [[UMSocialManager defaultManager] handleOpenURL:url];
    if (!UMShareResult) {

        // 其他如支付等SDK的回调
        // 微信支付SDK回调
        BOOL WXPauResult = [WXApi handleOpenURL:url delegate:self];

        if (!WXPauResult) {

            //不是微信支付回调,那就是支付宝
            //跳转支付宝钱包进行支付,处理支付结果
            if ([url.host isEqualToString:@"safepay"]) {

                [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {

                    if ([resultDic[@"resultStatus"] isEqualToString:@"9000"]) {
                        // 支付宝支付成功
                    }
                }];

                return YES;
            }
        }

        return WXPauResult;
    }

    return UMShareResult;
}

 END
 *****/

//  APP跳转完之后的回调,这个回调接口是所有的系统类型都适用的
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{

    // 首先判断是不是微信支付的回调
    // NOTE:上面的回调示例可以看住出,微信的支付回调就是按下面格式开头的,前面是APPId,判断URL是不是这个开头
    if ([[url absoluteString]hasPrefix:@"wx47e8322e53c76163://pay"]) {

        BOOL WXPauResult = [WXApi handleOpenURL:url delegate:self];
        return WXPauResult;

    }else{

    // 友盟SDK的回调
    BOOL UMShareResult = [[UMSocialManager defaultManager] handleOpenURL:url];
    if (!UMShareResult) {

            //跳转支付宝钱包进行支付,处理支付结果
            if ([url.host isEqualToString:@"safepay"]) {

            [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {

                //NSLog(@"result = %@",resultDic);
                if ([resultDic[@"resultStatus"] isEqualToString:@"9000"]) {

                    // 后台验证支付结果
                    [[NSNotificationCenter defaultCenter]postNotificationName:ALIPAYRESULT object:nil userInfo:@{@"result":resultDic[@"result"]}];
                }
            }];
            return YES;
            }
        }
       return UMShareResult;
   }
}

最后说说支付宝回调的注意事项:

支付宝和微信相比,支付宝要是客户没有安装APP它是可以调用网页版本的,微信却不行!所以这里要特别注意支付宝网页版本的回调。在支付宝的SDK里面,有这两连个方法大家注意:

/**
 *  支付接口
 *
 *  @param orderStr       订单信息
 *  @param schemeStr      调用支付的app注册在info.plist中的scheme
 *  @param compltionBlock 支付结果回调Block,用于wap支付结果回调(非跳转钱包支付)
 */
- (void)payOrder:(NSString *)orderStr
      fromScheme:(NSString *)schemeStr
        callback:(CompletionBlock)completionBlock;

/**
 *  处理钱包或者独立快捷app支付跳回商户app携带的支付结果Url
 *
 *  @param resultUrl        支付结果url
 *  @param completionBlock  支付结果回调
 */
- (void)processOrderWithPaymentResult:(NSURL *)resultUrl
                      standbyCallback:(CompletionBlock)completionBlock;

注意点:

一:支付宝网页版本的回调就是在支付接口completionBlock里面回调的,不会去SDK里面的 processOrderWithPaymentResult 方法回调。

二:App通过支付宝App支付完成之后的回调缺恰恰是在 processOrderWithPaymentResult 里面。

时间: 2024-12-29 10:27:49

当微信和支付宝遇上友盟的相关文章

分享微信及朋友圈(基于友盟)

添加微信及朋友圈 2.1  注册应用 使用微信分享首先需要在微信开放平台(点击链接)申请, 按照要求填写应用信息,审核通过后获取到微信APPID和APPsecret 2.2  添加相关文件 在UMSocial_Sdk_Extra_Frameworks目录下,添加Wechat文件夹到工程 2.3  添加微信 2.3.1  添加微信及朋友圈到分享列表 在你的程序APPdelegate入口方法添加下面的代码 #import "UMSocialWechatHandler.h" //设置微信Ap

当微信小程序遇上filter~

在微信小程序的开发过程中,当你想要实现不同页面间的数据绑定,却为此抓耳饶腮时,不妨让微信小程序与filter 来一场完美的邂逅,相信会给你带来别样的惊喜~ 前段时间被安利了一个很实用的公众号-前端早读课,它简洁.大方的页面和方便.实用的功能深深地吸引着我~(^U^)ノ 恰好这段时间学了小程序,就自己仿着写了个前端早读课的小程序. 实现的功能 不同页面间的数据绑定 随机显示数组里的元素 实时显示系统的日期 鼠标点击和页面跳转等基本功能 swiper组件和template样式模板的使用 使用easy

友盟分享(微信分享,微博分享,Facebook分享)

最近写了友盟分享,已经完全实现了,从最一开始的申请APPID到最后分享成功,跟大家细致的分享一下,希望对读者有帮住 一.  分享流程介绍 1.下载友盟分享的SDK并导入 需要注意的是要导入很多头文件:(具体步骤移步:http://dev.umeng.com/social/ios/quick-integration) Security.framework libiconv.dylib SystemConfiguration.framework CoreGraphics.Framework libs

2017年第一篇博客--关于集成友盟和微信支付等遇到的坑

前几天刚完工的一个定制单,需要用到分享,第三方登录,微信支付功能.因为一直都是用友盟去集成分享和第三方登录,所以项目初期就使用cocopads导入了友盟库. 上个月开始做支付功能,支付宝支付没有什么问题,按照官方文档顺利实现.到微信支付时候,下载了微信包,导入项目,顺利完成支付功能.然后开始做第三方登录,QQ登录和微信登录我打算直接使用友盟,QQ登录顺利完成,但微信登录就没那么顺利了.第一个坑,微信登录不走友盟回调,无限重新拉起授权.起初我以为是bundleid和appkey不对的问题,仔细校验

友盟发布第一期国内主要社交平台活跃度数据,微信超越QQ领跑社交平台

“Be Social”已成为移动应用设计和运营的重中之重,社交平台的选择更是应用开发过程中的重要一环.友盟通过“社会化组件”产品服务开发者,同时长期观察和研究App的社会化行为和市场趋势.2014年第一季度,通过友盟在全国覆盖的7.8亿活跃的移动设备,我们发现,在国内开发者认知中,包括新浪微博.QQ空间在内的“老牌”社交平台仍有一定优势,但微信作为社交平台,其数据表现及重要性已整体超越QQ. 国内主要社交平台均有增长,微信整体超越QQ 根据友盟数据,自2014年1月中旬起,微信的整体用户(包括微

抢鲜看:微信、支付宝、高德地图在Apple Watch上是酱紫玩啊!

3月9日凌晨消息,苹果公司2015年春季发布会在美国旧金山芳草地艺术中心召开.伴随首次亮相的Apple Watch还有其首批定制的APP,国内知名应用微信.支付宝均上榜. 本次发布会对Apple Watch进行了真机演示.演示中展示了多个Apple Watch应用,包括微信.支付宝,微博-- 而3月13日(本周五)苹果地图的中国合作商高德公司将在北京召开发布会,今日据高德论坛曝光的Apple Watch展示图判断,本次高德发布产品或与Apple Watch相关. 下面一起看看首批亮相Apple

友盟iOS sdk整理

文档中心 :http://dev.umeng.com 集成文档:http://dev.umeng.com/analytics/ios-doc/integration 报表中心:http://www.umeng.com/apps/download_center 分享:微信,微博,qq 友盟统计:1. appkey ,channel ID, ReportPolicy ,version 2.页面分析,日志加密, 后台模式设置 3.点击行为统计 次数,商品购买类型数量 4.崩溃次数,社交统计,集成测试,

#发福利#【友盟给“咱爸妈”送智能健康硬件!】

中秋节将至,很多开发者还要忙运营.搞推广.修bug……,不能回家看望父母.”举头拍月发微博,低头码字想爹娘“!对于这种做法,我们不仅要发扬光大,还要给予物!质!奖!励!没错!我们要发福利了!凡是“拍月亮寄托相思之情”的小伙伴,都有机会得到由友盟统计平台开发商麦开网.糖护科技.PICOOC 提供的智能健康硬件!帮你寄给家中父母.先来一睹硬件的真容 ↓ ↓ ↓ 活动规则:1. 拍个月亮2. 将你拍的月亮发给友盟君的微信(微信号:umengcom)即可.微博粉丝则将拍图发微博并@友盟 即可.注:听说局

集成友盟的意见反馈功能

最近一直在开发毕业设计的项目,其中用到了很多自己没接触过的东西,就包括集成友盟SDK的意见反馈模块的内容了.确实用了一点心思在里面,捣鼓了一阵子,中间也遇到了一些问题,关键这问题也不好解决,问大神大神也不一定有去接触这一块,然后网上是有很多资料,但总感觉对我的帮助不是很大,所以,当完成了友盟的这块功能后,就特别想贡献出来,一是为以后方便自己重温这块知识点,二是顺便 发布出来帮助像我这样遇到问题一直寻求解决办法的人.好了,废话不多说了,直接上效果图,然后PO代码! 效果图如下: 当然顺便也po上友