美文网首页iOS学无止境iOS Developer
iOS-支付宝&微信支付,接入笔记

iOS-支付宝&微信支付,接入笔记

作者: 多面兽 | 来源:发表于2016-07-10 00:24 被阅读2551次

    MY BLOG--->

    Demo

    Demo下载地址
    demo使用时,请在WTPayKeys.h里面将各个参数配置好!!!!

    一. 微信支付

    1.所需要的材料

    • 微信SDK
      微信SDK
    • 在微信开放平台上面申请得到的参数

    // 应用的APPID
    kWXAppID @"wxc82cXXXXXXXX"
    // AppSecret
    kWXAppSecret @"7f47bfe47b84XXXXXXXXXXXx"
    //商户号
    kWXMchID @"1242XXXXXX"
    //商户API密钥
    kWXPartnerID @"n1LeHtXUV9ZuPp156mcmXXXXXXXXX"
    //支付结果回调页面
    kWXNotifyURL @"http://XXXXXXXXX"

    1.2 微信支付工程配置

    // 需要的系统依赖

    SystemConfiguration.framework
    libz.dylib
    libsqlite3.0.dylib
    libc++.dylib

    2.调起微信客户端代码

        [WXApi registerApp:weichat_appid];
        //调起微信支付
        PayReq* req             = [[PayReq alloc] init];
        req.partnerId           = item.partnerid;
        req.prepayId            = item.prepayid;
        req.nonceStr            = item.noncestr;
        req.timeStamp           = [item.timestamp intValue];
        req.package             = item.package;
        req.sign                = item.sign;
        
        [WXApi sendReq:req];
    

    问: 微信支付怎么支付?
    答: 其实就是上面的代码.

    • 创建一个PayReq对象req, 然后[WXApi sendReq:req]; 就这么简单.
      难就难在,怎么得到PayReq对象所需要的那些值,一共六个值.
      而这六个值其他的值好说,就两个:prepayId和sign比较麻烦.
    • 获取prepayId(预支付订单)是需要发请求给微信(统一下单),然后微信返回结果给我们的.
    • 而sign前面的话,各种参数柔和在一起,MD5一下,也比较烦.

    3.拿到prepayId

    怎么拿?
    官方文档---->统一下单
    就是发一个请求给微信,然后微信返回prepayId给你.官方要求统一下单要放在我们的服务器做.--------这是个好事情!!!!!!!!!!!
    服务器端完成的!!!!哈哈哈哈,其实放在服务器端做的话,接入微信支付就没什么好说的了.

    其实不用服务端,我们也可以完成. 就是我们自己发请求然后拿到prepayId,我只是说我们自己可以做,但是现实中我们应当放在服务端,官方文档就是这么要求,这样我们省了好多事的好不,接入微信就很简单了.</br>
    但是为了演示效果,而又没有现成的服务器接口给我们.所以Demo中,我是将说有过程写在我们本地.

    放在我们本地的做法
    1.我们想这个接口:@"https://api.mch.weixin.qq.com/pay/unifiedorder" 发一个post请求

    2.参数
    aped //开放平台appid
    mch_id //商户号
    nonce_str//随机串
    trade_type //支付类型,固定为APP
    body //订单描述,展示给用户, 就是商品名
    notify_url //支付结果异步通知, 就是kWXNotifyURL
    out_trade_no //商户订单号 我们自己设定的订单号
    spbill_create_ip // //发器支付的机器ip
    total_fee //订单金额,单位为分

    sign // 签名, 就是上面那些参数按照字母顺序拼接成一个字符串,然后再拼接一个kWXPartnerID . 有关sign(签名)的生成可以参考官方文档,或者看下面关于sign的"通俗说法",或者直接看Demo

    4.partnerId 商家向财付通申请的商家id

    // 商家向财付通申请的商家id 这个不用说, 自己去微信开放平台上拿

    5.nonceStr 随机串

    /**
     *  生成随机字符串
     *
     *  @param kNumber 订单号的长度
     */
    - (NSString *)generateRomNumWithNumber: (NSInteger)kNumber
    {
        
        NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        NSMutableString *resultStr = [[NSMutableString alloc] init];
        srand((unsigned int)time(0));
        for (NSInteger i = 0; i < kNumber; i++)
        {
            unsigned index = rand() % [sourceStr length];
            NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, 1)];
            [resultStr appendString:oneStr];
        }
        return resultStr;
    }
    
    

    6.timeStamp 时间戳

    time_t now;
    time(&now);
    time_stamp  = [NSString stringWithFormat:@"%ld", now];
    

    7.package 商家根据财付通文档填写的数据和签名

    这个是个死值 Sign=WXPay
    官方文档说:暂填写固定值Sign=WXPay

    8.sign

    官方文档这么说的</br>
    签名算法
    签名生成的通用步骤如下:
    第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
    特别注意以下重要规则:
    ◆ 参数名ASCII码从小到大排序(字典序);
    ◆ 如果参数的值为空不参与签名;
    ◆ 参数名区分大小写;
    ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
    ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
    第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。


    通俗的说:
    1.就是拿到PayReq对象的其他5个值,参数名ASCII码从小到大排序(字典序),然后
    a字母顺序第一个appid,就是第一,然后后面的同样按照字母先后顺序一个&一个那么拼接成一个字符串.

    str1 = @"appid=wxd930ea5d5a258f4f&package=Sign=WXPay......";
    

    2.得到上面的字符串以后了再在后的字符串后面拼接上key
    // kWXPartnerID @"n1LeHtXUV9ZuPp156mcmXXXXXXXXX"
    str2 = [str1 appendFormat:@"key=%@", kWXPartnerID];

    然后对str2 MD5加密一下,就得到了sign了.

    如果是按照官方文档"统一下单API、支付结果通知API和查询订单API等都涉及签名过程,调用都必须在商户服务器端完成。"这样,上面的这些所有参数你都不用管,你要做的只是,拿到你们APP里面商品的价格,商品名什么的发给后台,然后后台就会把你需要的这些所有参数给你,然后你拿着这些参数调起微信就ok!

    </br></br>

    二.支付宝支付

    1.需要的材料

    支付宝SDK
    下载下来解压文件如图

    Snip20160709_15.png

    // 解压iOS那个zip


    Snip20160709_17.png

    // 得到如图

    Snip20160709_18.png

    // 我们需要的文件有如图

    Snip20160709_19.png

    // 在我们工程里面新建一个文件夹Alipay将上面我们需要的文件放在文件Alipay下

    Snip20160709_20.png

    // 支付宝需要的系统库

    "1"CFNetwork.framework
    "2"CoreMotion.framework
    "3"“SystemConfiguration.framework”,
    "4"“CoreGraphics.Framework”、
    "5"“CoreTelephony.framework”
    "6"“libz.dylib”
    "7"libc++.dylib
    "8"QuartzCore.framework
    "9"CoreText.framework

    // 在支付宝上申请得到的参数

    
    #ifndef __OPTIMIZE__
    #define kPayNotifyURL @"http://WWW.XXXX.XXXXXXXXX"
    #else
    #define kPayNotifyURL @"https://WWW.FFFF.XXXXXXX"
    #endif
    #define kPrivateKey @"SDGSFHGDFHGSVF$%#$RFFDSFASFASFASFSDFASDFASDCVCVZXVZXCVZXCVZXCVXCVZXCVGQWY%##$T@!RXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"// 
    #define kSeller @"20XXXXXXXXXXXXXX"
    #define kPartner @"20XXXXXXXXXXXXX"
    

    kPayNotifyURL
    kPrivateKey
    kSeller
    kPartner

    2.支付实现

    我是用WTPayManager统一管理微信和支付宝支付的
    在WTPayManager里包含

    import <AlipaySDK/AlipaySDK.h>

    调用支付宝代码

    + (void)aliPayWithOrderItem:(WTPayOrderItem *)orderItem
    {
        /*
         *商户的唯一的parnter和seller。
         *签约后,支付宝会为每个商户分配一个唯一的 parnter 和 seller。
         */
        
        /*
         *生成订单信息及签名
         */
        //将商品信息赋予AlixPayOrder的成员变量
        Order *order = [[Order alloc] init];
        order.partner = kPartner;
        order.sellerID = kSeller;
        order.outTradeNO = orderItem.orderOutTradeNO;//订单ID(由商家自行制定)
        
        order.subject = orderItem.orderName;//商品标题
        order.body = orderItem.orderBody; //商品描述
        order.totalFee = orderItem.orderPrice; //商品价格
        order.notifyURL = kPayNotifyURL;
        order.service = @"mobile.securitypay.pay";//接口名称,固定为mobile.securitypay.pay。
        order.paymentType = @"1";
        order.inputCharset = @"utf-8";
        order.itBPay = @"30m";
        order.showURL = @"m.alipay.com";
        
        //应用注册scheme,在AlixPayDemo-Info.plist定义URL types
        NSString *appScheme = @"XXXXXXXXXX";
        
        //将商品信息拼接成字符串
        NSString *orderSpec = [order description];
        NSLog(@"orderSpec = %@",orderSpec);
        
        //获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
        id<DataSigner> signer = CreateRSADataSigner(kPrivateKey);
        NSString *signedString = [signer signString:orderSpec];
        
        //将签名成功字符串格式化为订单字符串,请严格按照该格式
        
    //    __weak typeof(self) weakSelf = self;
        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(@"resultDic=%@",resultDic);
                
                //[weakSelf handleAlipayResponse:resultDic];
            }];
            
        }else{
            //[self handleAlipayResponse:nil];
        }
    
    }
    

    // 支付宝支付相对微信来说简单些

    拿到
    kPayNotifyURL
    kPrivateKey
    kSeller
    kPartner
    这几个参数
    加上我们的商品价格,名称,商品订单,本地加个密,往支付宝一推,就ok了.

    集成支付宝openssl可能会出现
    导入SDK或者调用支付宝失败的情况
    1.0 openssl/asn1.h file not found
    点击这里答案,感谢-----荏苒少年

    三.统一配置

    info.plist // 文件下加入这个

    <key>LSApplicationQueriesSchemes</key>
        <array>
            <string>sinaweibohd</string>
            <string>sinaweibo</string>
            <string>sinaweibosso</string>
            <string>weibosdk</string>
            <string>weibosdk2.5</string>
            <string>mqqapi</string>
            <string>mqq</string>
            <string>mqqOpensdkSSoLogin</string>
            <string>mqqconnect</string>
            <string>mqqopensdkdataline</string>
            <string>mqqopensdkgrouptribeshare</string>
            <string>mqqopensdkfriend</string>
            <string>mqqopensdkapi</string>
            <string>mqqopensdkapiV2</string>
            <string>mqqopensdkapiV3</string>
            <string>mqzoneopensdk</string>
            <string>wtloginmqq</string>
            <string>wtloginmqq2</string>
            <string>mqqwpa</string>
            <string>mqzone</string>
            <string>mqzonev2</string>
            <string>mqzoneshare</string>
            <string>wtloginqzone</string>
            <string>mqzonewx</string>
            <string>mqzoneopensdkapiV2</string>
            <string>mqzoneopensdkapi19</string>
            <string>mqzoneopensdkapi</string>
            <string>mqzoneopensdk</string>
            <string>alipay</string>
            <string>alipayshare</string>
        </array>
        <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSAllowsArbitraryLoads</key>
            <true/>
        </dict>
    
    Snip20160709_21.png

    // PCH

    Snip20160709_22.png

    // -ObjC

    Snip20160709_23.png

    // URL Schemes

    Snip20160709_24.png

    四. WTPayManager 代码实现

    WTPayManager.h

    //
    //  WTPayManager.h
    //  WT_Pay
    //
    //  Created by Mac on 16/7/5.
    //  Copyright © 2016年 wutong. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import <AlipaySDK/AlipaySDK.h>
    #import "WXApi.h"
    
    
    @interface WTPayOrderItem : NSObject
    
    /**
     商品名称
     */
    @property (nonatomic, strong)NSString * orderName;
    
    /**
    商品价格
     
     支付宝的单位是元
     微信的单位是分
    */
    @property (nonatomic, strong)NSString * orderPrice;
    
    /**
    订单号
    */
    @property (nonatomic, strong)NSString * orderOutTradeNO;
    
    /**
     商品描述
     */
    @property (nonatomic, strong)NSString * orderBody;
    
    
    @end
    
    
    
    
    typedef NS_ENUM(NSInteger, WTPayType) {
        WTPayTypeAli = 0,   // 支付宝支付
       WTPayTypeWeixin  // 微信支付
    };
    
    typedef NS_ENUM(NSInteger, WTPayAilPayResultType) {
        WTPayAilPayResultTypeSucess = 9000,   // 支付成功
        WTPayAilPayResultTypeCancel = 6001// 用户取消
    };
    
    typedef void(^WTPayResultBlock)(NSDictionary * payResult, NSString * error);
    @interface WTPayManager : NSObject<WXApiDelegate>
    
    
    + (instancetype)shareWTPayManager;
    - (void)handleAlipayResponse:(NSDictionary *)resultDic;
    
    
    + (void)wtPayOrderItem:(WTPayOrderItem *)orderItem payType:(WTPayType)type result:(WTPayResultBlock)result;
    @end
    
    
    
    
    
    

    WTPayManager.m

    //
    //  WTPayManager.m
    //  WT_Pay
    //
    //  Created by Mac on 16/7/5.
    //  Copyright © 2016年 wutong. All rights reserved.
    //
    
    #import "WTPayManager.h"
    #import "payRequsestHandler.h"
    #import "Order.h"
    #import "DataSigner.h"
    
    @interface WTPayManager ()<NSCopying>
    @property (nonatomic, copy)WTPayResultBlock result;
    @end
    
    @implementation WTPayManager
    
    + (void)initialize
    {
        [WTPayManager shareWTPayManager];
    }
    
    
    static WTPayManager * _instance;
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:zone];
            [_instance setRegisterApps];
        });
        return _instance;
    }
    
    + (instancetype)shareWTPayManager
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[self alloc]init];
            [_instance setRegisterApps];
        });
        return _instance;
    }
    
    
    - (id)copyWithZone:(nullable NSZone *)zone
    {
        return _instance;
    }
    
    
    
    // 注册appid
    - (void)setRegisterApps
    {    // 微信注册
        [WXApi registerApp:kWXAppID];
    }
    
    + (void)wtPayOrderItem:(WTPayOrderItem *)orderItem payType:(WTPayType)type result:(WTPayResultBlock)result
    {
        [WTPayManager shareWTPayManager].result = result;
        if (type == WTPayTypeWeixin) {
            [WTPayManager weixinPayWithOrderItem:orderItem];
        }else if (type == WTPayTypeAli){
            [WTPayManager aliPayWithOrderItem:orderItem];
        }
    }
    + (void)aliPayWithOrderItem:(WTPayOrderItem *)orderItem
    {
        /*
         *商户的唯一的parnter和seller。
         *签约后,支付宝会为每个商户分配一个唯一的 parnter 和 seller。
         */
        
        /*
         *生成订单信息及签名
         */
        //将商品信息赋予AlixPayOrder的成员变量
        Order *order = [[Order alloc] init];
        order.partner = kPartner;
        order.sellerID = kSeller;
        order.outTradeNO = orderItem.orderOutTradeNO;//订单ID(由商家自行制定)
        
        order.subject = orderItem.orderName;//商品标题
        order.body = orderItem.orderBody; //商品描述
        order.totalFee = orderItem.orderPrice; //商品价格
        order.notifyURL = kPayNotifyURL;
        order.service = @"mobile.securitypay.pay";
        order.paymentType = @"1";
        order.inputCharset = @"utf-8";
        order.itBPay = @"30m";
        order.showURL = @"m.alipay.com";
        
        //应用注册scheme,在AlixPayDemo-Info.plist定义URL types
        NSString *appScheme = @"mralipaysdk";
        
        //将商品信息拼接成字符串
        NSString *orderSpec = [order description];
        NSLog(@"orderSpec = %@",orderSpec);
        
        //获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
        id<DataSigner> signer = CreateRSADataSigner(kPrivateKey);
        NSString *signedString = [signer signString:orderSpec];
        
        //将签名成功字符串格式化为订单字符串,请严格按照该格式
        
    //    __weak typeof(self) weakSelf = self;
        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(@"resultDic=%@",resultDic);
                
                //[weakSelf handleAlipayResponse:resultDic];
            }];
            
        }else{
            //[self handleAlipayResponse:nil];
        }
    
    }
    
    - (void)handleAlipayResponse:(NSDictionary *)resultDic
    {
        
    //    resultDic;
        NSLog(@"%@", resultDic);
        
        if ([resultDic[@"resultStatus"] integerValue] != WTPayAilPayResultTypeSucess) {
            
            NSString * errorStr;
            errorStr = resultDic[@"memo"] ? resultDic[@"memo"] : @"支付失败";
            self.result(nil, errorStr);
        }else{
            NSDictionary * response = @{@"result":@"支付宝支付成功!"};
            self.result(response,nil);
        }
        
        
    }
    
    
    
    
    + (void)weixinPayWithOrderItem:(WTPayOrderItem *)orderItem
    {
    
        payRequsestHandler *payObj = [payRequsestHandler sharedInstance];
        //1. 拿到prepayId 和 sign, 其他参数写在外面都行
        NSDictionary * dict = [payObj sendPay:orderItem.orderName orderPrice:orderItem.orderPrice outTradeNo:orderItem.orderOutTradeNO];
    
    
        // 2.调起微信支付
        if(dict != nil){
            NSMutableString *retcode = [dict objectForKey:@"retcode"];
            if (retcode.intValue == 0){
                NSMutableString *stamp  = [dict objectForKey:@"timestamp"];
                
                //调起微信支付
                PayReq* req             = [[PayReq alloc] init];
                req.partnerId           = [dict objectForKey:@"partnerid"];
                req.prepayId            = [dict objectForKey:@"prepayid"];
                req.nonceStr            = [dict objectForKey:@"noncestr"];
                req.timeStamp           = stamp.intValue;
                req.package             = [dict objectForKey:@"package"];
                req.sign                = [dict objectForKey:@"sign"];
                
                BOOL success = [WXApi sendReq:req];
                if(!success){
                    NSLog(@"调微信失败");
                }
                return;
            }else{
                NSLog(@"%@",[dict objectForKey:@"retmsg"]);
            }
        }else{
            NSLog(@"服务器返回错误");
        }
    
    
        
    }
    
    
    
    
    -(void)onResp:(BaseResp*)resp{
        if ([resp isKindOfClass:[PayResp class]]){
            PayResp*response=(PayResp*)resp;
            
            
            if (response.errCode == WXSuccess) {
                NSDictionary * response = @{@"result":@"微信支付成功!"};
                self.result(response,nil);
    
            }else{
                NSLog(@"支付失败,retcode=%d",resp.errCode);
                
                self.result(nil,@"支付失败");
                
            }
        }
    }
    
    @end
    
    
    
    @implementation WTPayOrderItem
    @end
    

    Demo

    Demo下载地址
    demo使用时,请在WTPayKeys.h里面将各个参数配置好!!!!

    相关文章

      网友评论

      • 谢谢生活:打赏了2元,金额虽然,但是非常感谢。
      • 谢谢生活:大神 请教你两个问题:NSDictionary * dict = [payObj sendPay:orderItem.orderName orderPrice:orderItem.orderPrice outTradeNo:orderItem.orderOutTradeNO];这个签名是你自己做的还是微信做的,新版sdk没有看到。第二个问题:我们要实现你一个功能就是:用户用我们的币可以提现金,需求是:点击体现跳转微信或者支付宝把钱转给用户。
        多面兽:@谢谢生活 不好意,好久这块代码. 没时间看,还是自己Google一下吧.:grin:
      • c2d2794a53c7:大神,微信支付 总是提示 商户下单支付ID非法 是为什么呢
      • 讨厌下雨的鱼:请问:kWXPartnerID是什么
        讨厌下雨的鱼:@多面兽 谢谢大神,我找到了。
        多面兽:@这位壮士不太冷 //商户API密钥
        kWXPartnerID @"n1LeHtXUV9ZuPp156mcmXXXXXXXXX"
      • Misaki_yuyi:不知道楼主有没有遇到 唤醒微信 显示 “支付验证签名失败”的按钮 URL Schemes我设置就是AppID 那个sign 我用微信的验证工具没有错误 不知道问题出在哪

      本文标题:iOS-支付宝&微信支付,接入笔记

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