美文网首页支付上海恩美路演学无止境
支付宝支付以及微信支付集成

支付宝支付以及微信支付集成

作者: 一铭_ | 来源:发表于2016-01-30 15:15 被阅读740次

    1.支付宝集成
    第一步:先签约支付宝,申请应用(别忘了生成的 RSA 密钥的上传)
    https://doc.open.alipay.com/doc2/detail.htm?spm=0.0.0.0.6i3qlX&treeId=58&articleId=103542&docType=1
    第二步:下载支付宝官方的 SDK, 把第一步申请得到的 sellID,partnerID,私钥(privateKey)放到代码中,为了测试我们配置的 key 是否正确,如果支付宝 demo 能支付成功,就代表我们配置的 key 成功了,反之去重复第一步吧

    L:148
        NSString *partner = @"xxxxxxx";
        NSString *seller = @"xxxxxxx";
        NSString *privateKey = @"xxxxxxx" ;//注意空格!!
    

    第三步:配置支付宝到 app
    1>配置库,看支付宝官方的就好,比哪都详细
    https://doc.open.alipay.com/doc2/detail.htm?spm=0.0.0.0.l0wbHb&treeId=59&articleId=103676&docType=1
    但要注意: "Header Search Paths”增加头文件路径:$(SRCROOT)/项目名称!!!!
    还有记得设置回调
    2>把下图的文件从支付宝官方 demo 中拷贝过来

    屏幕快照 2016-01-30 下午3.02.18.png

    编译,如果有报错,缺库就导库,头文件就 header search paths,
    我还需要一个报错,导了一个 demo 里没有的库:libstdc++.6.0.9. tbd
    3>处理支付的商品信息,签名等等
    导入头文件

    #import "Order.h"
    #import <AlipaySDK/AlipaySDK.h>
    #import "DataSigner.h"
    

    处理支付业务

     /**
                 *  1.生成订单信息
                 */
                Order *order = [[Order alloc]init];
                order.partner = PARTNER;
                order.seller = SELLER;
                order.tradeNO = self.orderCode;
                order.productName = @"这是一个支付宝测试";
                order.productDescription = @"我说了这是一个测试数据";
                order.amount = [NSString stringWithFormat:@"%.2f",0.01];
                //回调 URL
                order.notifyURL = @"url url url ";
                order.service = @"mobile.securitypay.pay";
                order.paymentType = @"1";
                order.inputCharset = @"utf-8";
                order.itBPay = @"30m";
                order.showUrl = @"m.alipay.com";
                
                // 应用注册scheme,在当前项目的Info.plist定义URL types
                NSString *appScheme = @"";//同 url types
                //将订单信息拼接成在字符串
                NSString *orderSpec = [order description];
    

    第一步基本上和官方 demo 一样,比微信好多了(不得不吐槽一下)

     /**
                 *  2.签名加密
                 *  获取私钥并将商户信息签名, 外部商户可以根据情况存放私钥和签名, 只需要遵循 RSA 签名规范, 并将签名字符串 base64 编码和 UrlEncode
                 */
                NSString *str = PRIVATE;
                id<DataSigner> signer = CreateRSADataSigner(str);
                NSString *signedString = [signer signString:orderSpec];
    

    请直接copy demo 这一部分

               /**
                 *  3. 将签名成功字符串格式化为订单字符串,请严格按照该格式
                 */
                NSString *orderString = nil;
                if (signedString != nil) {
                    orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
                                   orderSpec, signedString, @"RSA"];
                    
                    [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
                        //处理你的支付结果
                        NSLog(@"resuly===%@",resultDic);
                        }
                    }];
                }
    

    appDelegate里面需要设置

    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    /**
         *  Alipay
         */
        //如果极简开发包不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给开 发包
        if ([url.host isEqualToString:@"safepay"]) {
            [[AlipaySDK defaultService]processOrderWithPaymentResult:url
             standbyCallback:^(NSDictionary *resultDic) {
    #warning ======支付结果处理
                 NSLog(@"ewsult====%@",resultDic);
             }];
        }
        
        //支付宝钱包快登授权返回
        if ([url.host isEqualToString:@"platformapi"]) {
            [[AlipaySDK defaultService]processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
    #warning ======支付结果处理
                 NSLog(@"ewsult====%@",resultDic);
            }];
        }
    }
    

    支付宝就这么多了,很简单的代码,一般的配置,复杂的申请....

    2.微信支付
    做微信支付是有挺多小坑的,这个坑主要取决于你的后台怎么样,微信不同于支付宝的是,它把支付过程分成了两步,就到导致了后台需要先做第一步,再传数据给前端,然后前端去完成第二步.

    第一步是:向微信注册你的应用程序 ID
    这一步没什么技术,按照流程就好了(这都是产品经理做的吧.....)
    https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317780&token=f6e95c1f1c5fd970d5fb3b2425e2d612b6cbce47&lang=zh_CN
    照这个流程来就好
    第二步:下载官方 demo
    https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1
    其实不推荐官方的 demo...而且微信的官方 demo 不像支付宝一样还可以用来去检查 appId,等等值是否配好
    第三步:配置微信 SDK

    屏幕快照 2016-01-31 下午5.28.57.png

    需要配置的库好像跟支付宝差不多...
    第四步:调用微信支付 SDK
    这个第四步就要分情况讨论了
    微信的支付流程是先获取prePayid,再加appid,appkey,noncestr,package,partnerId,timestamp去签名完成支付.
    第一种情况:如果你的后台去完成获取预支付订单
    这种是微信支付官方推荐的,而且这样更加安全,相关的配置信息和 key 都存在服务器更加安全.
    这种情况前端需要在用户发起微信支付后吧订单信息传给服务器(传递的信息需要沟通),返回值为

         // 调起微信支付
                PayReq *request = [[PayReq alloc]init];
                request.partnerId = _WXPayModel.partnerid;
                request.prepayId = _WXPayModel.prepayid;
                request.package = @"Sign=WXPay";
                request.nonceStr = _WXPayModel.noncestr;
                request.timeStamp = [_WXPayModel.timestamp intValue];
    

    package 一定要写成那样!
    package 一定要写成那样!
    package 一定要写成那样!

     // 这里要注意key里的值一定要填对, 微信官方给的参数名是错误的,不是第二个字母大写
                NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
                [signParams setObject: _WXPayModel.appid               forKey:@"appid"];
                [signParams setObject: _WXPayModel.partnerid           forKey:@"partnerid"];
                [signParams setObject: request.nonceStr      forKey:@"noncestr"];
                [signParams setObject: request.package       forKey:@"package"];
                [signParams setObject: _WXPayModel.timestamp forKey:@"timestamp"];
                [signParams setObject: request.prepayId      forKey:@"prepayid"];
                
                //生成签名
                NSString *sign  = [MyUtil genSign:signParams];
                NSLog(@"sign===%@",sign);
                
                //添加签名
                request.sign = sign;
                
                [WXApi sendReq:request];
    

    基本上调起支付的代码就这样...这当然是在服务端完成第一步的情况下.
    第二种情况:(如果你家后台又懒又不会而且你又比较闲的话)

    //微信支付
    - (void)wxpay
    {
        //商户号
        NSString *PARTNER_ID    = @"1900000109";
        //商户密钥
        NSString *PARTNER_KEY   = @"8934e7d15453e97507ef794cf7b0519d";
        //APPID
        NSString *APPI_ID       = @"wxd930ea5d5a258f4f";
        //appsecret
        NSString *APP_SECRET = @"db426a9829e4b49a0dcac7b4162da6b6";
        //支付密钥
        NSString *APP_KEY       = @"L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K";
        NSLog(@"%ld,%ld,%ld",PARTNER_KEY.length,APP_SECRET.length,APP_KEY.length);
        //支付结果回调页面
        NSString *NOTIFY_URL    = @"http://localhost/pay/wx/notify_url.asp";
        //订单标题
        NSString *ORDER_NAME    = @"Ios客户端签名支付 测试";
        //订单金额,单位(分)
        NSString *ORDER_PRICE   = @"1";
        
        //创建支付签名对象
        payRequsestHandler *req = [payRequsestHandler alloc];
        //初始化支付签名对象
        [req init:APPI_ID app_secret:APP_SECRET partner_key:PARTNER_KEY app_key:APP_KEY];
        
        //判断Token过期时间,10分钟内不重复获取,测试帐号多个使用,可能造成其他地方获取后不能用,需要即时获取
        time_t  now;
        time(&now);
        //if ( (now - token_time) > 0 )//非测试帐号调试请启用该条件判断
        {
            //获取Token
            Token                   = [req GetToken];
            //设置Token有效期为10分钟
            token_time              = now + 600;
            //日志输出
            NSLog(@"获取Token: %@\n",[req getDebugifo]);
        }
        if ( Token != nil){
            //================================
            //预付单参数订单设置
            //================================
            NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
            [packageParams setObject: @"WX"                                             forKey:@"bank_type"];
            [packageParams setObject: ORDER_NAME                                        forKey:@"body"];
            [packageParams setObject: @"1"                                              forKey:@"fee_type"];
            [packageParams setObject: @"UTF-8"                                          forKey:@"input_charset"];
            [packageParams setObject: NOTIFY_URL                                        forKey:@"notify_url"];
            [packageParams setObject: [NSString stringWithFormat:@"%ld",time(0)]        forKey:@"out_trade_no"];
            [packageParams setObject: PARTNER_ID                                        forKey:@"partner"];
            [packageParams setObject: @"196.168.1.1"                                    forKey:@"spbill_create_ip"];
            [packageParams setObject: ORDER_PRICE                                       forKey:@"total_fee"];
            
            NSString    *package, *time_stamp, *nonce_str, *traceid;
            //获取package包
            package  = [req genPackage:packageParams];
            
            //输出debug info
            NSString *debug     = [req getDebugifo];
            NSLog(@"gen package: %@\n",package);
            NSLog(@"生成package: %@\n",debug);
            
            //设置支付参数
            time_stamp  = [NSString stringWithFormat:@"%ld", now];
            nonce_str = [TenpayUtil md5:time_stamp];
            traceid  = @"mytestid_001";
            NSMutableDictionary *prePayParams = [NSMutableDictionary dictionary];
            [prePayParams setObject: APPI_ID                                            forKey:@"appid"];
            [prePayParams setObject: APP_KEY                                            forKey:@"appkey"];
            [prePayParams setObject: nonce_str                                          forKey:@"noncestr"];
            [prePayParams setObject: package                                            forKey:@"package"];
            [prePayParams setObject: time_stamp                                         forKey:@"timestamp"];
            [prePayParams setObject: traceid                                            forKey:@"traceid"];
            
            //生成支付签名
            NSString    *sign;
            sign  = [req createSHA1Sign:prePayParams];
            //增加非参与签名的额外参数
            [prePayParams setObject: @"sha1"                                            forKey:@"sign_method"];
            [prePayParams setObject: sign                                               forKey:@"app_signature"];
            
            //获取prepayId
            NSString *prePayid;
            prePayid            = [req sendPrepay:prePayParams];
            //输出debug info
            debug               = [req getDebugifo];
            NSLog(@"提交预付单: %@\n",debug);
            
            if ( prePayid != nil) {
                //重新按提交格式组包,微信客户端5.0.3以前版本只支持package=Sign=***格式,须考虑升级后支持携带package具体参数的情况
                //package       = [NSString stringWithFormat:@"Sign=%@",package];
                package         = @"Sign=WXPay";
                //签名参数列表
                NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
                [signParams setObject: APPI_ID                                          forKey:@"appid"];
                [signParams setObject: APP_KEY                                          forKey:@"appkey"];
                [signParams setObject: nonce_str                                        forKey:@"noncestr"];
                [signParams setObject: package                                          forKey:@"package"];
                [signParams setObject: PARTNER_ID                                       forKey:@"partnerid"];
                [signParams setObject: time_stamp                                       forKey:@"timestamp"];
                [signParams setObject: prePayid                                         forKey:@"prepayid"];
                
                //生成签名
                sign  = [req createSHA1Sign:signParams];
                
                //输出debug info
                debug     = [req getDebugifo];
                NSLog(@"调起支付签名: %@\n",debug);
                
                //调起微信支付
                PayReq* req = [[PayReq alloc] init];
                req.openID      = APPI_ID;
                req.partnerId   = PARTNER_ID;
                req.prepayId    = prePayid;
                req.nonceStr    = nonce_str;
                req.timeStamp   = now;
                req.package     = package;
                req.sign        = sign;
                [WXApi safeSendReq:req];
            }else{
                /*long errcode = [req getLasterrCode];
                 if ( errcode == 40001 )
                 {//Token实效,重新获取
                 Token                   = [req GetToken];
                 token_time              = now + 600;
                 NSLog(@"获取Token: %@\n",[req getDebugifo]);
                 };*/
                NSLog(@"获取prepayid失败\n");
                [self alert:@"提示信息" msg:debug];
            }
        }else{
            NSLog(@"获取Token失败\n");
            [self alert:@"提示信息" msg:@"获取Token失败"];
        }
        
    }
    

    第四步:设置 url回调以及等等琐碎的东西
    1.info URL Types 设置app回调
    2.appdelegate中注册 app

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
        [WXApi registerApp:@"xxxxxxxxxxxx" withDescription:@"xxxxxx"];
    

    微信支付完成后会通过 appdelegate 中的代理方法发送通知,处理支付结果

    if ([resp isKindOfClass:[PayResp class]]) {
            PayResp *response = (PayResp *)resp;
            NSLog(@"response.errCoderesponse.errCoderesponse.errCode%d",response.errCode);
            
            switch (response.errCode) {
                case WXSuccess:{
                    NSLog(@"successWXPay");
                    NSNotification *notification = [NSNotification notificationWithName:@"orderPay" object:@"success"];
                    [[NSNotificationCenter defaultCenter]postNotification:notification];
                    break;
                }
                case WXErrCodeCommon:
                    [SVProgressHUD showErrorWithStatus:@"发送错误"];
                    break;
                
                case WXErrCodeUserCancel:
                    [SVProgressHUD showErrorWithStatus:@"支付已取消"];
                    break;
                    
                case WXErrCodeSentFail:
                    [SVProgressHUD showErrorWithStatus:@"发送失败"];
                    break;
                    
                case WXErrCodeUnsupport:
                    [SVProgressHUD showErrorWithStatus:@"微信不支持"];
                    break;
    //                WXErrCodeCommon     = -1,   /**< 普通错误类型    */
    //                WXErrCodeUserCancel = -2,   /**< 用户点击取消并返回    */
    //                WXErrCodeSentFail   = -3,   /**< 发送失败    */
    //                WXErrCodeAuthDeny   = -4,   /**< 授权失败    */
    //                WXErrCodeUnsupport  = -5,   /**< 微信不支持    */
                default:{
                    NSLog(@"wxpay");
                    break;
                }
            }
        }
    

    到这里微信支付就差不多完成了,如果出现微信的各种报错,简书上有很多,就不啰嗦了.
    再说说做第三方支付的感受吧,其实我以后打算直接用 ping++了.......

    相关文章

      网友评论

      • 丶丶夏天:这个seller可以换成任意的收款支付宝帐号吗?
        一铭_:@2f0e9d948df7 对的

      本文标题:支付宝支付以及微信支付集成

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