美文网首页iOS开发好文三方管理自鉴
iOS接入微信支付(小白都能看懂的微信支付)

iOS接入微信支付(小白都能看懂的微信支付)

作者: lyonLiu | 来源:发表于2016-06-17 11:06 被阅读27228次

    因为近期项目中需要接入微信支付功能,自己也爬了很多的坑,所以做了一下这边文章供大家学习参考,远离爬坑,文章主要讲到以下五部分:

    一、 填写商户平台所需资料

    二、 具体Demo代码@Github下载地址


    本文为本人学习记录笔记,如需转载,请注明出处@iOS_lyon


    填写商户平台所需资料

    一、填写经营信息


    @查看截图指引

    下图选择不同的类目,所需要上传的资料也是有所不同的,下图拿其它为例子

    填写经营信息

    二、填写商户信息(确认信息操作,此处省略)

    三、填写对公帐号信息(此处省略)


    以下是微信官方给出的交互步骤

    商户系统和微信支付系统主要交互说明:
    步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。
    步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。参见【统一下单API】。
    步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay
    步骤4:商户APP调起微信支付。api参见本章节【app端开发步骤说明
    步骤5:商户后台接收支付通知。api参见【支付结果通知API
    步骤6:商户后台查询支付结果。,api参见【查询订单API

    具体项目

    一、创建一个项目
    二、下载微信终端SDK文件

    SDK文件包括 libWeChatSDK.a,WXApi.h,WXApiObject.h 三个。
    请前往“资源下载页”下载最新SDK包

    1.将下载好的SDK导入项目,如下图

    Paste_Image.png

    2.添加依赖库


    Paste_Image.png

    3.准备所需配置的数据

    // 开放平台登录https://open.weixin.qq.com的开发者中心获取APPID
    #define WX_APPID @"wxd21d890***2db4ca"
    // 开放平台登录https://open.weixin.qq.com的开发者中心获取AppSecret。
    #define WX_APPSecret @"fc32dfae9****eb5f77dddd4ea5"
    // 微信支付商户号
    #define MCH_ID  @"13536**702"
    
    // 安全校验码(MD5)密钥,商户平台登录账户和密码登录http://pay.weixin.qq.com 平台设置的“API密钥”,为了安全,请设置为以数字和字母组成的32字符串。
    #define WX_PartnerKey @"b5f9c901480*****0f4c6e659be0"
    

    4.在Xcode中,选择你的工程设置项,选中“TARGETS”一栏,在“info”标签栏的“URL type“添加“URL scheme”为你所注册AppId(如下图所示)

    Paste_Image.png

    配置好上述参数后就可以写代码了,具体可查看@Github下载地址

    • PCH头文件: 在该文件配置好以下备注中要配置参数即可运行demo
    #ifndef PrefixHeader_pch
    #define PrefixHeader_pch
    
    #pragma mark -  
    #pragma mark - 微信支付配置参数
    
    // 开放平台登录https://open.weixin.qq.com的开发者中心获取APPID
    #define WX_APPID @"wxd21d89033***b4ca"
    // 开放平台登录https://open.weixin.qq.com的开发者中心获取AppSecret。
    #define WX_APPSecret @"fc32dfae99bc67e****5f77dddd4ea5"
    // 微信支付商户号
    #define MCH_ID  @"1353***702"
    // 安全校验码(MD5)密钥,商户平台登录账户和密码登录http://pay.weixin.qq.com
    // 平台设置的“API密钥”,为了安全,请设置为以数字和字母组成的32字符串。
    #define WX_PartnerKey @"B6246A6D8***C730EEA0F78D3B461"
    
    
    #pragma mark -  
    #pragma mark - 统一下单请求参数键值
    
    //  应用id
    #define WXAPPID @"appid"
    //  商户号
    #define WXMCHID @"mch_id"
    //  随机字符串
    #define WXNONCESTR @"nonce_str"
    //  签名
    #define WXSIGN @"sign"
    //  商品描述
    #define WXBODY @"body"
    //  商户订单号
    #define WXOUTTRADENO @"out_trade_no"
    //  总金额
    #define WXTOTALFEE @"total_fee"
    //  终端IP
    #define WXEQUIPMENTIP @"spbill_create_ip"
    //  通知地址
    #define WXNOTIFYURL @"notify_url"
    //  交易类型
    #define WXTRADETYPE @"trade_type"
    //  预支付交易会话
    #define WXPREPAYID @"prepay_id"
    
    
    
    #pragma mark - 
    #pragma mark - 微信下单接口
    
    //  微信统一下单接口连接
    #define WXUNIFIEDORDERURL @"https://api.mch.weixin.qq.com/pay/unifiedorder"
    
    #endif /* PrefixHeader_pch */
    
     
    #import "AppDelegate.h"
    #import "WXApiManager.h"
    
    @interface AppDelegate ()
    
    @end
    
    @implementation AppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // 注册微信
        [WXApi registerApp:WX_APPID withDescription:@"demo 2.0"];
        
        return YES;
    }
    
    - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
    {
        return  [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
    }
    
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
    {
        return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
    }
    
    @end
    

    ** 微信支付回调管理类**

    
    #import "WXApiManager.h"
    
    @implementation WXApiManager
    
    #pragma mark - 单粒
    
    +(instancetype)sharedManager {
        static dispatch_once_t onceToken;
        static WXApiManager *instance;
        dispatch_once(&onceToken, ^{
            instance = [[WXApiManager alloc] init];
        });
        return instance;
    }
    
    #pragma mark - WXApiDelegate
    
    - (void)onResp:(BaseResp *)resp
    {
        if([resp isKindOfClass:[PayResp class]]){
            
            //支付返回结果,实际支付结果需要去微信服务器端查询
            NSString *strMsg;
        
            switch (resp.errCode) {
                case WXSuccess:
                    strMsg = @"支付结果:成功!";
                    NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
                    break;
                    
                default:
                    strMsg = [NSString stringWithFormat:@"支付结果:失败!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
                    NSLog(@"错误,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
                    break;
            }
        }
    }
    
    @end
    

    步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。

    #import "ViewController.h"
    #import "WXApiRequestHandler.h"
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        //  发起支付
        [WXApiRequestHandler jumpToBizPay];
    }
    
    @end
    

    步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。参见【统一下单API】。

    #import <Foundation/Foundation.h>
    #import "WXApiObject.h"
    
    @interface WXApiRequestHandler : NSObject
    
    + (NSString *)jumpToBizPay;
    
    @end
    
    
    #import "WXApi.h"
    #import "WXApiRequestHandler.h"
    #import "WXApiManager.h"
    #import "DataMD5.h"
    #import "XMLDictionary.h"
    #import <AFNetworking.h>
    
    #pragma mark - 用于获取设备ip地址
    
    #include <ifaddrs.h>
    #include <arpa/inet.h>
    
    @implementation WXApiRequestHandler
    
    #pragma mark - 产生随机字符串
    
    //生成随机数算法 ,随机字符串,不长于32位
    //微信支付API接口协议中包含字段nonce_str,主要保证签名不可预测。
    //我们推荐生成随机数算法如下:调用随机数函数生成,将得到的值转换为字符串。
    
    + (NSString *)generateTradeNO {
        
        static int kNumber = 15;
        
        NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        
        NSMutableString *resultStr = [[NSMutableString alloc] init];
        
        //  srand函数是初始化随机数的种子,为接下来的rand函数调用做准备。
        //  time(0)函数返回某一特定时间的小数值。
        //  这条语句的意思就是初始化随机数种子,time函数是为了提高随机的质量(也就是减少重复)而使用的。
        
        // srand(time(0)) 就是给这个算法一个启动种子,也就是算法的随机种子数,有这个数以后才可以产生随机数,用1970.1.1至今的秒数,初始化随机数种子。
        // Srand是种下随机种子数,你每回种下的种子不一样,用Rand得到的随机数就不一样。为了每回种下一个不一样的种子,所以就选用Time(0),Time(0)是得到当前时时间值(因为每时每刻时间是不一样的了)。
        
        srand(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;
    }
    
    #pragma mark - 获取设备ip地址
    
    + (NSString *)fetchIPAddress {
        NSString *address = @"error";
        struct ifaddrs *interfaces = NULL;
        struct ifaddrs *temp_addr = NULL;
        int success = 0;
        // retrieve the current interfaces - returns 0 on success
        success = getifaddrs(&interfaces);
        if (success == 0) {
            // Loop through linked list of interfaces
            temp_addr = interfaces;
            while(temp_addr != NULL) {
                if(temp_addr->ifa_addr->sa_family == AF_INET) {
                    // Check if interface is en0 which is the wifi connection on the iPhone
                    if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                        // Get NSString from C String
                        address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                    }
                }
                temp_addr = temp_addr->ifa_next;
            }
        }
        // Free memory
        freeifaddrs(interfaces);
        return address;
    }
    
    #pragma mark - Public Methods
    //  发起微信支付
    + (void)jumpToWxPay
     {
        
    #pragma mark 客户端操作时候的代码 \ 但是这些步骤应该放在服务端操作
    
    //============================================================
        // V3&V4支付流程实现
        // 注意:参数配置请查看服务器端Demo
        // 更新时间:2015年11月20日
        //============================================================
        
    // 交易类型
    #define TRADE_TYPE @"APP"
        
    // 交易结果通知网站此处用于测试,随意填写,正式使用时填写正确网站
    #define NOTIFY_URL @"http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php"
        
    // 交易价格1表示0.01元,10表示0.1元
    #define PRICE @"1"
        
        
        //  随机字符串变量 这里最好使用和安卓端一致的生成逻辑
        NSString *nonce_str = [self generateTradeNO];
        
        //  设备IP地址,请再wifi环境下测试,否则获取的ip地址为error,正确格式应该是8.8.8.8
        NSString *addressIP = [self fetchIPAddress];
        
        //  随机产生订单号用于测试,正式使用请换成你从自己服务器获取的订单号
        NSString *orderno = [NSString stringWithFormat:@"%ld",time(0)];
      
        //  获取SIGN签名
        DataMD5 *data = [[DataMD5 alloc] initWithAppid:WX_APPID
                                                mch_id:MCH_ID
                                             nonce_str:nonce_str
                                            partner_id:WX_PartnerKey
                                                  body:@"充值"
                                          out_trade_no:orderno
                                             total_fee:PRICE
                                      spbill_create_ip:addressIP
                                            notify_url:NOTIFY_URL
                                            trade_type:TRADE_TYPE];
        
        // 转换成xml字符串
        NSString *string = [[data dic] XMLString];
      
        
        AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
        //这里传入的xml字符串只是形似xml,但不是正确是xml格式,需要使用AF方法进行转义
        session.responseSerializer = [[AFHTTPResponseSerializer alloc] init];
        [session.requestSerializer setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [session.requestSerializer setValue:WXUNIFIEDORDERURL forHTTPHeaderField:@"SOAPAction"];
        [session.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error) {
            return string;
        }];
        [session POST:WXUNIFIEDORDERURL parameters:string progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            //  输出XML数据
            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:WXAPPID];
                request.partnerId = [dic objectForKey:WXMCHID];
                request.prepayId= [dic objectForKey:WXPREPAYID];
                request.package = @"Sign=WXPay";
                request.nonceStr= [dic objectForKey:WXNONCESTR];
                // 将当前时间转化成时间戳
                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 = [dic objectForKey:@"sign"];
                request.sign=[md5 createMD5SingForPay:request.openID
                                            partnerid:request.partnerId
                                             prepayid:request.prepayId
                                              package:request.package
                                             noncestr:request.nonceStr
                                            timestamp:request.timeStamp];
                // 调用微信
                [WXApi sendReq:request];
            }
     
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            NSLog(@"%@",error);
        }];
    
    #pragma mark  服务端操作微信支付 / 上述客户端操作可以忽略(仅供参考)没办法,靠后台还不如靠自己,先自己了解客户端实现支付的操作
        
        NSMutableDictionary *params = [NSMutableDictionary dictionary];
        params[WXTOTALFEE] = @"1";
        params[WXEQUIPMENTIP] = [self fetchIPAddress];
        
        AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
        [session POST:URLSTRING parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
     
            NSLog(@"responseObject = %@",responseObject);
            
            // 判断返回的许可
            if ([[responseObject objectForKey:@"result_code"] isEqualToString:@"SUCCESS"]
                &&[[responseObject objectForKey:@"return_code"] isEqualToString:@"SUCCESS"] ) {
                
                // 发起微信支付,设置参数
                PayReq *request     = [[PayReq alloc] init];
                request.openID      = [responseObject objectForKey:WXAPPID];
                request.partnerId   = [responseObject objectForKey:WXMCHID];
                request.prepayId    = [responseObject objectForKey:WXPREPAYID];
                request.package     = @"Sign=WXPay";
                request.nonceStr    = [responseObject objectForKey:WXNONCESTR];
                request.timeStamp   = [[responseObject objectForKey:@"timestamp"] intValue];
                request.sign        = [responseObject objectForKey:@"sign"];
                // 调用微信支付
                [WXApi sendReq:request];
            }else{
                // 显示错误信息
                [LyonKeyWindow.rootViewController showHint:responseObject[@"err_code_des"]];
            }
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            NSLog(@"%@",error);
        }];
    
    }
    
    @end
    

    以下皆是客户端的签名方法类

    #import "DataMD5.h"
    #import <CommonCrypto/CommonDigest.h>
    @interface DataMD5()
    
    @property (nonatomic,strong) NSString *appid;
    @property (nonatomic,strong) NSString *mch_id;
    @property (nonatomic,strong) NSString *nonce_str;
    @property (nonatomic,strong) NSString *partnerkey;
    @property (nonatomic,strong) NSString *body;
    @property (nonatomic,strong) NSString *out_trade_no;
    @property (nonatomic,strong) NSString *total_fee;
    @property (nonatomic,strong) NSString *spbill_create_ip;
    @property (nonatomic,strong) NSString *notify_url;
    @property (nonatomic,strong) NSString *trade_type;
    
    @end
    
    @implementation DataMD5
    
    #pragma makr - 懒加载
    
    - (NSMutableDictionary *)dic
    {
        if (!_dic) {
            _dic = [NSMutableDictionary dictionary];
        }
        return _dic;
    }
    
    #pragma mark - Config
    
    -(instancetype)initWithAppid:(NSString *)appid_key
                          mch_id:(NSString *)mch_id_key
                       nonce_str:(NSString *)noce_str_key
                      partner_id:(NSString *)partner_id
                            body:(NSString *)body_key
                   out_trade_no :(NSString *)out_trade_no_key
                       total_fee:(NSString *)total_fee_key
                spbill_create_ip:(NSString *)spbill_create_ip_key
                      notify_url:(NSString *)notify_url_key
                      trade_type:(NSString *)trade_type_key
    {
        if (self = [super init]) {
            
            _appid          = appid_key;
            _mch_id         = mch_id_key;
            _nonce_str      = noce_str_key;
            _partnerkey     = partner_id;
            _body           = body_key;
            _out_trade_no   = out_trade_no_key;
            _total_fee      = total_fee_key;
            _spbill_create_ip = spbill_create_ip_key;
            _notify_url     = notify_url_key;
            _trade_type     = trade_type_key;
            
            [self.dic setValue:_appid forKey:WXAPPID];
            [self.dic setValue:_mch_id forKey:WXMCHID];
            [self.dic setValue:_nonce_str forKey:WXNONCESTR];
            [self.dic setValue:_body forKey:WXBODY];
            [self.dic setValue:_out_trade_no forKey:WXOUTTRADENO];
            [self.dic setValue:_total_fee forKey:WXTOTALFEE];
            [self.dic setValue:_spbill_create_ip forKey:WXEQUIPMENTIP];
            [self.dic setValue:_notify_url forKey:WXNOTIFYURL];
            [self.dic setValue:_trade_type forKey:WXTRADETYPE];
            
            [self createMd5Sign:self.dic];
        }
        return self;
    }
    
    //创建签名
    //签名算法
    //签名生成的通用步骤如下:
    //第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
    //特别注意以下重要规则:
    //◆ 参数名ASCII码从小到大排序(字典序);
    //◆ 如果参数的值为空不参与签名;
    //◆ 参数名区分大小写;
    //◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
    //◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
    //第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
    //key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
    
    -(void)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:@""]
                && ![[dict objectForKey:categoryId] isEqualToString:@"sign"]
                && ![[dict objectForKey:categoryId] isEqualToString:@"key"]
                )
            {
                [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
            }
        }
        //添加商户密钥key字段
        [contentString appendFormat:@"key=%@",_partnerkey];
        
        NSLog(@"contentString = %@",contentString);
        
        //MD5 获取Sign签名
        NSString *md5Sign =[self md5:contentString];
        
        //  
        [self.dic setValue:md5Sign forKey:@"sign"];
        
    }
    
    //创建发起支付时的sige签名
    
    -(NSString *)createMD5SingForPay:(NSString *)appid_key partnerid:(NSString *)partnerid_key prepayid:(NSString *)prepayid_key package:(NSString *)package_key noncestr:(NSString *)noncestr_key timestamp:(UInt32)timestamp_key{
        NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
        [signParams setObject:appid_key forKey:@"appid"];
        [signParams setObject:noncestr_key forKey:@"noncestr"];
        [signParams setObject:package_key forKey:@"package"];
        [signParams setObject:partnerid_key forKey:@"partnerid"];
        [signParams setObject:prepayid_key forKey:@"prepayid"];
        [signParams setObject:[NSString stringWithFormat:@"%u",(unsigned int)timestamp_key] forKey:@"timestamp"];
        
        NSMutableString *contentString  =[NSMutableString string];
        NSArray *keys = [signParams allKeys];
        //按字母顺序排序
        NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            return [obj1 compare:obj2 options:NSNumericSearch];
        }];
        //拼接字符串
        for (NSString *categoryId in sortedArray) {
            if (   ![[signParams objectForKey:categoryId] isEqualToString:@""]
                && ![[signParams objectForKey:categoryId] isEqualToString:@"sign"]
                && ![[signParams objectForKey:categoryId] isEqualToString:@"key"]
                )
            {
                [contentString appendFormat:@"%@=%@&", categoryId, [signParams objectForKey:categoryId]];
            }
        }
        //添加商户密钥key字段
    #warning 注意此处一定要添加上商户密钥
        [contentString appendFormat:@"key=%@", WX_PartnerKey];
        NSString *result = [self md5:contentString];
        
        NSLog(@"result = %@",result);
        return result;
    }
    
    // MD5加密算法
    -(NSString *) md5:(NSString *)str
    {
        const char *cStr = [str UTF8String];
        //加密规则,因为逗比微信没有出微信支付demo,这里加密规则是参照安卓demo来得
        unsigned char result[16]= "0123456789abcdef";
        CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
        //这里的x是小写则产生的md5也是小写,x是大写则md5是大写,这里只能用大写,逗比微信的大小写验证很逗
        return [NSString stringWithFormat:
                @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
                result[0], result[1], result[2], result[3],
                result[4], result[5], result[6], result[7],
                result[8], result[9], result[10], result[11],
                result[12], result[13], result[14], result[15]
                ];
    }
    
    @end
    

    相关文章

      网友评论

      • 054225fe229a:不错,非常完美,谢谢
      • 0x00chen:为什么一直报这个错误Use of undeclared identifier 'PayResp',我已经把你的config导入到我的pch文件里面还不行,我单独吧WXAPiobject.h导入也不行,这是什么原因。。。。。
        a632073b5a6a: 我现在也遇到这个问题,你是怎么解决的....
      • 若即若离_3570:499978494@qq.com 求楼主发一份 最近傻叼后台要把所有东西放到前端来做 急需!! 好人一生平安~.~
        lyonLiu:@若即若离_3570 文章中有下载地址
      • 凌乱_ecea:你的获取ip地址会出现打印error的时候导致无法正常使用的...最好还是写个虚拟的ip吧
      • 白水灬煮一切:楼主你的git上怎么下载不了呢?
        lyonLiu:@白水灬煮一切 可以的,你提示的是什么
      • e862bc30a2eb:1253504781@qq.com 楼主发份demo,谢谢 :heart:
      • 谁先注册了阿K:你好,请问下,你的这个#define MXWechatPartnerKey @"6de04e7247f9aab635966cee18*ccced" 这个32位的字符串是自己随便取的吗?
      • 玫瑰的名字0: 楼主还在么,请问集成一个微信支付功能大致需要几天时间
      • 涅槃_ddb4:网上下运行的时候老有错误,linker command failed with exit code 1 (use -v to see invocation) 方便加您一个QQ吗 给发一份吗 21105078@qq.com 十分感谢
      • 小毛_8eec:给力!!!!!!!!
      • beyourking:看了几遍,感觉还可以,就是没有看明白到底哪些代码该客户端写,哪些该服务端写啊?可以指教一下嘛:joy:
      • Faded憔悴不堪:759906667@qq.com楼主求一份demo,刚好做到微信支付 谢谢
      • 北暖37:你好,我下载了你的demo,放入了我们自己的appid这些信息,但是运行起来,显示白屏。
        lyonLiu:@慕糖123 看下代码,是点击视图才会触发支付
      • 飞飞飞鱼哥:demo没反应运行 啊
      • 纵横小二:ld: library not found for -lAFNetworking 报这个错误
      • 青春码头客:能给我发一份吗 1150340211@qq.com 不胜感激
        lyonLiu:@青春码头客 文章中有demo
      • ethan_cun:楼主,我在客户端发起支付,弹出“APPID未关联PaySignKey",我已经商户平台上设置了API密钥,就是32为字母加数字的那个;是不是因为还在审核中的原因?
        lyonLiu:@EthanCun 如果未审核通过自然不能使用
      • 焦焦丶:494458378@qq.com 可以发一份demo 借鉴一下嘛 谢谢楼主
      • 丶去年的茶:这个demo是不是只要换一下APPID、AppSecret、微信支付商户号、API密钥。然后点击空白就能用了?
        丶去年的茶:@lyoniOS 嗯哈,谢谢。我等申请下来试试,谢谢你!
        lyonLiu:@伊人未归丶 是的
        丶去年的茶:因为我现在运行你的代码是一片空白的,点击,执行代码,但是没有任何返回。
      • 雪_晟:生成订单一般是放在后台做好点还是前端
        雪_晟:@lyoniOS 嗯 那前段可以省很多力气
        lyonLiu:@miss李manman 后台
      • 攻城狮丶:返回 您没有APP支付权限是怎么回事 后台都已经通过了
      • 0x00chen:楼主在吗,那个获取IP地址貌似只有在WiFi环境下才可以,我用4g试了下并不能调起微信支付,请问这个问题怎么解决呢
        lyonLiu:@究极魔法师 是的,只能在wifi情况下才可以获取ip地址,这个demo有说明。实际操作获取ip地址也是在服务端获取的,所以这个是可以忽略的
      • 0x00chen:楼主我的为什么一直提示这个错误 “#import <AFNetworkActivityIndicatorManager.h>”file not found
        lyonLiu:将这个报错的地方删除了吧,不影响
        0x00chen:@lyoniOS 导入了,3.0的
        lyonLiu:@究极魔法师 你导入Af了吗
      • 詹小白:大楼主,SharedPreferences这是安卓的???
        lyonLiu:@A_佳爷 那个是我自己项目中的文件,你忽略即可
        詹小白:@lyoniOS WXApiRequestHander的类文件中有用SharedPreferences
        lyonLiu:@A_佳爷 什么意思
      • 詹小白:现在git上的demo跟以前不一样了
        lyonLiu:@A_佳爷 建议你用新的这个。只要替换那几个参数就可以调起支付了
        詹小白:@iOSlyon 能不能把原来的发我下呢,我下载了你以前的但是现在有的文件不小心没有了。拜托了
        lyonLiu:@A_佳爷 是的,更换了新的sdk,优化了结构
      • 1ebb0d3f8d0d:请问,为什么下载你的demo,我参数配好过后不能跳转微信呢?谢谢了
        1ebb0d3f8d0d:@iOSlyon 判断返回的许可 的时候直接跳出去了
        1ebb0d3f8d0d:@iOSlyon 没错误信息,但是就是不跳转微信,我参数配置对了的
        lyonLiu:报什么错误?一般参数配置正常都是可以的,大部分原因都是参数错误
      • 猿小圣:问下openid是要用谁的微信号,是要支付用户的,还是在微信平台注册的?
      • ChanYuCung1:你好,请问可以发份demo借鉴一下吗 :smile:
        349073871@qq.com
      • 098bd10b7b60:楼主你好,我配置了参数,还是不能支付,问题是Printing description of dic:
        {
        "__name" = xml;
        "return_code" = FAIL;
        "return_msg" = "\U60a8\U6ca1\U6709APP\U652f\U4ed8\U6743\U9650";
        }
      • 08e77db408f7:// 设备IP地址,请再wifi环境下测试,否则获取的ip地址为error,正确格式应该是8.8.8.8
        NSString *addressIP = [self fetchIPAddress];
        设备IP地址是后台自己获取,还是需要app端传给后台?

        后台怎么能获得微信需要的IP地址
        lyonLiu:@懵然中寻找光芒 后台也有方法可以获取到设备的IP地址的,如果后台不懂就叫他百度
      • 卡农forever_love:The certificate used to sign "WxPayDemo" has either expired or has been revoked. An updated certificate is required to sign and install the application.跑真机IOS10上证书没用了
      • 孙公瑾i:楼主,我这边后台处理的订单,每次吊起都是提示 支付验证签名失败 是什么原因
        孙公瑾i:@iOSlyon 没出错啊。。安卓的用的好好地,ios签名就失败,一样的数据
        lyonLiu:@孙公瑾i

        配置参数出错
      • _旧时光:274030259@qq.com 求楼主发一份demo 谢谢楼主
      • 天狼鹰:为什么我修改的会报,签名错误
        lyonLiu:@天狼星_哲 如果你方便的话可以把你的解决方法跟大家分享一下
        天狼鹰: @iOSlyon 恩,没事,已经搞定了
        lyonLiu:不好意思,这段时间赶项目,没有时间帮忙查看,后续有时间会更新上传的
      • 董强牛逼:995286226@qq.com 求楼主发个demo
      • 雅尘:楼主求demo,本人小白,邮箱527861548@qq.com
        lyonLiu:@雅尘 文中有下载链接
      • 小的小碰撞:楼主 是不只需修改下
        #define WX_APPID
        #define WX_APPSecret
        #define MCH_ID @"13536**702"
        #define WX_PartnerKey
        这四个参数 就可以运行你的demo了 ,急求 。楼主看到望回答下
        lyonLiu:@小的小碰撞 是的,还有URLSCHEME
      • 小的小碰撞:统一下单请求参数键值 还需要改吗
      • 小的小碰撞:楼主,下载你的demo 修改 需要配置的参数 运行后没有反应 ,还有AppSecret是必须填写的吗
        怎么回事,求解 。很急
        小的小碰撞:有空吗 加扣扣聊吧 915954109
        小的小碰撞:运行后一点反应都没有,怎么回事。 需要后台签名吗
        lyonLiu:@小的小碰撞 是必须填写的
      • 我就叫土豆:运行Demo并没有成功调起微信支付,真机iOS版本:9.3.5
      • 慢慢来111:楼主 ,我们后台php 微信后台发给我们后台的信息如何处理啊 求知道
      • 洱马: // 将微信返回的xml数据解析转义成字典
        NSDictionary *dic = [NSDictionary dictionaryWithXMLString:responseString];

        // 判断返回的许可
        if ([[dic objectForKey:@"result_code"] isEqualToString:@"SUCCESS"]
        &&[[dic objectForKey:@"return_code"] isEqualToString:@"SUCCESS"] )

        提示: // 将微信返回的xml数据解析转义成字典
        NSDictionary *dic = [NSDictionary dictionaryWithXMLString:responseString];

        // 判断返回的许可
        if ([[dic objectForKey:@"result_code"] isEqualToString:@"SUCCESS"]
        &&[[dic objectForKey:@"return_code"] isEqualToString:@"SUCCESS"] )
        提示:XML格式错误,楼主这个怎么解决
        洱马:@子弹头 //设置参数并转化成xml格式(正确转换)
        sign = [data getSignForMD5];
        // 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:sign forKey:@"sign"];//签名
        // [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"];//交易类型
        // 转换成xml字符串
        // NSString *string = [dic XMLString];
        //把需要的参数转换成字典就信了,用这个字符串NSString *string = [dic XMLString];作为参数,


        //这个没用了
        // 转换成XML字符串,这里知识形似XML,实际并不是正确的XML格式,需要使用AF方法进行转义
        NSString *string = [[data dic] XMLString];

        洱马:@子弹头 解决了
        098bd10b7b60:@要啥昵称了 你好,你问题解决了吗
      • oooooooooozx:楼主给我发一份吧 1033259693@qq.com
        lyonLiu:@oooooooooozx 文中有下载地址
      • petter102:jp380490944@gmail.com 求一份demo。楼主
        lyonLiu:@petter102 文中有下载地址呢
      • fe92133993d1:AFHTTPSessionManager 报错 在demo哪里可以找到
      • fe92133993d1:给可以发个Demo,603503609@qq.com,谢谢
        fe92133993d1:@iOSlyon 谢谢
        lyonLiu:@ygd 文中有Demo的下载地址
      • JhonBook:遇到了和13楼同志同样的问题,微信支付完成,竟然不能自动跳转回自己的应用。
        if_you_like:@f1e0f94abc3d 好像不会自己跳回的,你看美团也不会的
      • 萌小菜:小黑能看懂吗?
        lyonLiu:@萌小菜 小黑不是看不懂,是看不到
      • 白行夜:楼主,app怎么调取微信客户端进行支付?
      • Seacity_:楼主 ,求一份儿demo ,速度啊,救急
        Seacity_:@iOSlyon 已经做好了,谢谢
        lyonLiu:@心海蓝 文中有下载链接,你可以在上面下载
      • 去搬砖:你好,添加你的代码,但是PrefixHeader.pch里定义的宏,在ViewController.m找不到,什么原因呢?谢谢
        去搬砖:@iOSlyon 哦。呵呵。iOS小白了。我去鼓捣鼓捣
        lyonLiu:@12343954 pch是在build setting那里设置的
        去搬砖:也没见这个文件在项目中引用
      • 伊乐兔:楼主,请问你有没有遇到这样一个问题 就是支付完成之后 页面右边会出现 按钮可以返回 app
        如果点击 回调正常 不点击 回调不起作用
        lyonLiu:@lilejianshu 介不介意把你遇到问题的Demo发给我,我看下是什么问题
        伊乐兔:@0263401535b9
        没有,我只是写了一个支付的Demo 写的都是死数据 不知道为什么会出现这个问题
        你有解决的办法吗 或者说 为什么会引起这个问题
        0263401535b9:@lilejianshu 这个问题解决了吗??
      • Lifg:给可以发个Demo,273559753@qq.com,谢谢
        lyonLiu:@__1994__ 文章中有demo的下载链接,你可以上去下载
      • 15356163496:735479094@qq.com 可以发一份demo 借鉴一下嘛 谢谢楼主
        lyonLiu:Demo可以在文章中的链接中下载
      • 鹰凌天下:app内置微信支付,不使用apple的内购,能通过审核?
        ShenYj:你们公司是什么产品啊
        lyonLiu:@鹰凌天下 可以的,内购只是在一些情况下才必须使用内购
      • 21593bb673fb:大神给我发一份呗,谢谢你啦,github上下载的总是提示错误 179434316@qq.com
        lyonLiu:@进击的小白 QQ也不怎么上,有什么问题你可以在这反馈给我,我去进行修改
        21593bb673fb:@iOSlyon linker command failed with exit code 1 (use -v to see invocation) 方便加您一个QQ吗
        lyonLiu:@进击的小白 github上下载的提示错误是指什么意思。我去看看
      • 0263401535b9:已赞 楼主可以发我一份demo吗?
        lyonLiu:@0263401535b9 这个是在商户平台中设置的,设置完之后就直接拿来用。只能在商户平台
        0263401535b9:平台设置的“API密钥”在商户平台查不到?请问在哪里可以查到??
        lyonLiu:@0263401535b9 文章里面有demo的下载地址,你可以直接在上面下载
      • 53dfe175a39f:前几天刚做完微信和支付宝支付的嵌入发现支付宝官方文档指导性的描述很少,前端还好有现成demo,但后台返回签名字段总出问题一直显示ALI系列的问题,最后发现是参数排序有问题,需按照前端demo里的参数排序一样。接下来就是最恶心的微信,文档描述居然是错的,官方文档说所有参数按照驼峰式规则书写,但实际上是需要把所有参数字段都小写才可以
      • lukyy:1531073749@qq.com 可以发一份demo 现在需要 谢谢楼主
        lukyy:@iOSlyon 收到了,非常感谢🙏🙏,写的很详细
        lyonLiu:@lukyy 已发,请查收
      • 1e9bc41934d4:楼主,照着你的代码 老是只出现一个确定按钮 不知道您出现过没有
        lyonLiu:@Viterbi 你可以使用微信平台上面的签名工具看看你最终的签名跟微信平台上得到的签名是否一致,一般都是签名问题。还有你的url scheme是否有填写
      • 177e2f7f8f57:953520170@qq.com 可以发一份demo 借鉴一下嘛 谢谢楼主
        Coke26:求楼主大大的demo 365754921@qq.com谢谢
        Apples8023:@iOSlyon 335983653@qq.com
        楼主,求发一份demo
        lyonLiu:已发
      • 巴赫海兹:楼主,现在要在支付时添加一些字段以便于微信返回数据到服务器上时便于获取,怎么做?
      • 瞳若点星:刚做到这块,正需要,谢谢分享
        lyonLiu:@瞳若点星 这个没有放到github,如果你有需要,可以邮箱发你一份自己测试的demo
        瞳若点星:@iOS_lyon 楼主有放到github上吗?想参考一下。
        lyonLiu:@瞳若点星 共勉!!

      本文标题:iOS接入微信支付(小白都能看懂的微信支付)

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