1. 程式人生 > >iOS 微信支付詳細步驟及幾個可能遇到的小問題

iOS 微信支付詳細步驟及幾個可能遇到的小問題

一. 支付準備工作

1. 微信相關準備工作

(1) 向微信官方開通支付功能. 這個不是前端的工作.

(2) 匯入官方下載的微信支付SDK包. 我用的是微信開放平臺下載的SDK 1.6.2

(3) 匯入必要的庫檔案

     SystemConfiguration.framework,

     libz.dylib,

     libsqlite3.0.dylib,

     libc++.dylib,

     CoreTelephoy.framework (坑一: 這個庫是必要的,但是微信官方文件中沒有說到要匯入)

(4) 該專案中的Bundle Identifier 應該填向微信註冊的Bundle Identifier

(5) 註冊微信 (回撥的時候用到,告訴微信,從微信返回到哪個APP)

     Target --> info --> URL Types --> +按鈕 --> 填寫identifier 和 URL Schemes. 前一個是識別符號,一般填@"weixin".後一個是註冊的微信appId. 比如"wx19a984b788a8a0b1".(註釋: 假的appid)

(6) 新增微信白名單

     info.plist --> 右擊 --> open as  --> source Code --> 新增白名單

     我是在<key>CFBundleVersion</key>

這一行上面新增的. 注意保持正確的鍵值對.別插錯了.

<key>LSApplicationQueriesSchemes</key>
    <array>
        <string>wechat</string>
        <string>weixin</string>
    </array>

(7) 如果支付成功,回撥方法不執行,或者回調不成功.請再次確認(4)(5)(6),是否填寫正確. 

(8) 執行一下,不報錯.報錯,再次確認(1)--(7)步驟.

二.程式碼相關

1. 在AppDelegate.h中

(1) 匯入微信類 #import @"WXApi.h".

(2) 遵守微信代理方法 <WXApiDelegate>

2. 在APPDelegate.m中

(1) 註冊微信

複製程式碼
#pragma mark 註冊微信
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ 
    //註冊 微信
    /**
     引數1 : 微信Appid
     引數2 : 對專案的描述資訊(用專案名稱)
     */
    [WXApi registerApp:@"微信Appid" withDescription:@"雲宴"];
    
    return YES;
}
複製程式碼

 (2) 跳轉方法,並設定代理

複製程式碼
#pragma mark 跳轉處理
//被廢棄的方法. 但是在低版本中會用到.建議寫上
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    return [WXApi handleOpenURL:url delegate:self];
}
//被廢棄的方法. 但是在低版本中會用到.建議寫上

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    return [WXApi handleOpenURL:url delegate:self];
}

//新的方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
    return [WXApi handleOpenURL:url delegate:self];
}
複製程式碼

(3) 微信回撥方法 (注意: 不要寫成Req方法了)

複製程式碼
#pragma mark 微信回撥方法

- (void)onResp:(BaseResp *)resp
{
    NSString * strMsg = [NSString stringWithFormat:@"errorCode: %d",resp.errCode];
    NSLog(@"strMsg: %@",strMsg);

    NSString * errStr       = [NSString stringWithFormat:@"errStr: %@",resp.errStr];
    NSLog(@"errStr: %@",errStr);

    
    NSString * strTitle;
    //判斷是微信訊息的回撥 --> 是支付回調回來的還是訊息回調回來的.
    if ([resp isKindOfClass:[SendMessageToWXResp class]])
    {
        strTitle = [NSString stringWithFormat:@"傳送媒體訊息的結果"];
    }

    NSString * wxPayResult;
    //判斷是否是微信支付回撥 (注意是PayResp 而不是PayReq)

    if ([resp isKindOfClass:[PayResp class]])
    {
        //支付返回的結果, 實際支付結果需要去微信伺服器端查詢
        strTitle = [NSString stringWithFormat:@"支付結果"];
        switch (resp.errCode)
        {
            case WXSuccess:
            {
                strMsg = @"支付結果:";
                NSLog(@"支付成功: %d",resp.errCode);
                wxPayResult = @"success";
                break;
            }
            case WXErrCodeUserCancel:
            {
                strMsg = @"使用者取消了支付";
                NSLog(@"使用者取消支付: %d",resp.errCode);
                wxPayResult = @"cancel";
                break;
            }
            default:
            {
                strMsg = [NSString stringWithFormat:@"支付失敗! code: %d  errorStr: %@",resp.errCode,resp.errStr];
                NSLog(@":支付失敗: code: %d str: %@",resp.errCode,resp.errStr);
                wxPayResult = @"faile";
                break;
            }
        }
        //發出通知 從微信回調回來之後,發一個通知,讓請求支付的頁面接收訊息,並且展示出來,或者進行一些自定義的展示或者跳轉
        NSNotification * notification = [NSNotification notificationWithName:@"WXPay" object:wxPayResult];
        [[NSNotificationCenter defaultCenter] postNotification:notification];
    }
}
複製程式碼

 3. 在ViewController.h (進行支付請求的類)

 暫時沒有任何操作

4. 在ViewController.m中(進行支付的請求的類)

(1) 匯入微信庫 #import @"WXApi.h"

(2) 監聽APPDelegate.m中傳送的通知

複製程式碼
#pragma mark 監聽通知
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];
    
    //檢測是否裝了微信軟體
    if ([WXApi isWXAppInstalled])
    {
        
        //監聽通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"WXPay" object:nil];
    }
}
複製程式碼 複製程式碼
#pragma mark - 事件
- (void)getOrderPayResult:(NSNotification *)notification
{
    NSLog(@"userInfo: %@",notification.userInfo);
    
    if ([notification.object isEqualToString:@"success"])
    {
        UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"提示資訊" message:@"支付成功" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
        [alertView show];
    }
    else
    {
        [self alert:@"提示" msg:@"支付失敗"];
    }
}

//客戶端提示資訊
- (void)alert:(NSString *)title msg:(NSString *)msg
{
    UIAlertView *alter = [[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alter show];
}
複製程式碼

(3) 移除通知

#pragma mark 移除通知
- (void)dealloc 
{    
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

(4) 調起微信去支付

複製程式碼
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self pay_button];
}

#pragma mark - 實現方法

#pragma mark 建立支付按鈕
- (void)pay_button
{
    self.payButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.payButton.frame = CGRectMake(10, 100, 300, 40);
    self.payButton.backgroundColor = [UIColor orangeColor];
    [self.payButton setTitle:@"去支付" forState:UIControlStateNormal];
    [self.payButton addTarget:self action:@selector(payButtonClicked) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:self.payButton];
}

#pragma mark - 點選事件
- (void)payButtonClicked
{
    [self sendNetWorking_WXPay];
}

- (void)sendNetWorking_WXPay
{
    NSString * urlStr = [NSString stringWithFormat:@"%@%@",YYIP,@"wx/pay"];
    
    NSDictionary * parameter = @{
                                 @"pay_type"       : @"1",
                                 @"total_price"    : @"10",
                                 @"appointment_id" : @"208"
                                 };
    
    [self sendNetWorkingWith:urlStr andParameter:parameter];
}

#pragma mark 網路請求 -->> post
- (void)sendNetWorkingWith:(NSString *)url andParameter:(NSDictionary *)parameter
{
    AFHTTPSessionManager * manager = [AFHTTPSessionManager manager];
    
    [manager POST:url parameters:parameter progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        NSLog(@"%@",responseObject);
        
        //網路請求回來的8個引數.詳見微信開發平臺
        
        NSDictionary * result = responseObject[@"result"];
        
        NSString * appid         = result[@"appid"];
        NSString * noncestr      = result[@"noncestr"];
        NSString * package1      = result[@"package1"];
        NSString * partnerid     = result[@"partnerid"];
        NSString * paySign       = result[@"paySign"];
        NSString * prepayid      = result[@"prepayid"];
        NSString * timestamp     = result[@"timestamp"];
        
        
//        NSString * err_code      = result[@"err_code"];
//        NSString * timeStamp     = result[@"timeStamp"];
//        NSString * tradeid       = result[@"tradeid"];

        
    [self WXPayRequest:appid nonceStr:noncestr package:package1 partnerId:partnerid prepayId:prepayid timeStamp:timestamp sign:paySign];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@",error);
    }];
}

#pragma mark - 調起微信支付
- (void)WXPayRequest:(NSString *)appId nonceStr:(NSString *)nonceStr package:(NSString *)package partnerId:(NSString *)partnerId prepayId:(NSString *)prepayId timeStamp:(NSString *)timeStamp sign:(NSString *)sign{
    //調起微信支付
    PayReq* wxreq             = [[PayReq alloc] init];
    
    wxreq.openID              = appId; // 微信的appid
    wxreq.partnerId           = partnerId;
    wxreq.prepayId            = prepayId;
    wxreq.nonceStr            = nonceStr;
    wxreq.timeStamp           = [timeStamp intValue];
    wxreq.package             = package;
    wxreq.sign                = sign;
    
    [WXApi sendReq:wxreq];
}
複製程式碼

三.上程式碼

1. AppDelegate.h

複製程式碼
#import <UIKit/UIKit.h>

#import "WXApi.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate,WXApiDelegate>

@property (strong, nonatomic) UIWindow *window;

@end
複製程式碼

2. AppDelegate.m

複製程式碼
#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


#pragma mark 註冊微信
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    
    //註冊 微信
    /**
     引數1 : 微信Appid
     引數2 : 對專案的描述資訊(用專案名稱)
     */
    [WXApi registerApp:@"wx09a984b788a8a0b0" withDescription:@"雲宴"];
    
    return YES;
}

#pragma mark 跳轉處理
//被廢棄的方法. 但是在低版本中會用到.建議寫上
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    return [WXApi handleOpenURL:url delegate:self];
}
//被廢棄的方法. 但是在低版本中會用到.建議寫上

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    return [WXApi handleOpenURL:url delegate:self];
}

//新的方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
    return [WXApi handleOpenURL:url delegate:self];
}

#warning 這一步中  不要錯誤的把req 當成了 resp
#pragma mark 微信回撥方法
- (void)onResp:(BaseResp *)resp
{
    NSString * strMsg = [NSString stringWithFormat:@"errorCode: %d",resp.errCode];
    NSLog(@"strMsg: %@",strMsg);
    
    NSString * errStr       = [NSString stringWithFormat:@"errStr: %@",resp.errStr];
    NSLog(@"errStr: %@",errStr);
    
    
    NSString * strTitle;
    //判斷是微信訊息的回撥
    if ([resp isKindOfClass:[SendMessageToWXResp class]])
    {
        strTitle = [NSString stringWithFormat:@"傳送媒體訊息的結果"];
    }
    
    
    NSString * wxPayResult;
    //判斷是否是微信支付回撥 (注意是PayResp 而不是PayReq)
    if ([resp isKindOfClass:[PayResp class]])
    {
        //支付返回的結果, 實際支付結果需要去微信伺服器端查詢
        
        strTitle = [NSString stringWithFormat:@"支付結果"];
        
        switch (resp.errCode)
        {
            case WXSuccess:
            {
                strMsg = @"支付結果:";
                NSLog(@"支付成功: %d",resp.errCode);
                wxPayResult = @"success";
                break;
            }
                case WXErrCodeUserCancel:
            {
                strMsg = @"使用者取消了支付";
                NSLog(@"使用者取消支付: %d",resp.errCode);
                wxPayResult = @"cancel";
                break;
            }
            default:
            {
                strMsg = [NSString stringWithFormat:@"支付失敗! code: %d  errorStr: %@",resp.errCode,resp.errStr];
                NSLog(@":支付失敗: code: %d str: %@",resp.errCode,resp.errStr);
                wxPayResult = @"faile";
                break;
            }
        }
        
        //發出通知
        NSNotification * notification = [NSNotification notificationWithName:@"WXPay" object:wxPayResult];
        [[NSNotificationCenter defaultCenter] postNotification:notification];
    }
}

@end
複製程式碼

3. ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController


@end

4. ViewController.m

複製程式碼
#import "ViewController.h"

#import "AFHTTPSessionManager.h"
#import "WXApi.h"

#define YYIP       @"http:公司IP地址"


@interface ViewController ()

@property (nonatomic, strong) UIButton * payButton;


@end

@implementation ViewController

#pragma mark 監聽通知
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];
    
    //檢測是否裝了微信軟體
    if ([WXApi isWXAppInstalled])
    {
        
        //監聽通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"WXPay" object:nil];
    }
}

#pragma mark 移除通知
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:YES];
    
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self pay_button];

}

#pragma mark - 實現方法

#pragma mark 建立支付按鈕
- (void)pay_button
{
    self.payButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.payButton.frame = CGRectMake(10, 100, 300, 40);
    self.payButton.backgroundColor = [UIColor orangeColor];
    [self.payButton setTitle:@"去支付" forState:UIControlStateNormal];
    [self.payButton addTarget:self action:@selector(payButtonClicked) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:self.payButton];
}

#pragma mark - 點選事件
- (void)payButtonClicked
{

    if ([WXApi isWXAppInstalled])

    {

      [self sendNetWorking_WXPay];

    }

     else

    {

      [self alert:@"提示" msg:@"未安裝微信"];

    }

}

- (void)sendNetWorking_WXPay
{
    NSString * urlStr = [NSString stringWithFormat:@"%@%@",YYIP,@"wx/pay"];
       
    NSDictionary * parameter = @{
                                 @"pay_type"       : @"1",
                                 @"total_price"    : @"10",
                                 @"appointment_id" : @"208"
                                 };
    
    [self sendNetWorkingWith:urlStr andParameter:parameter];
}

#pragma mark 網路請求 -->> post
- (void)sendNetWorkingWith:(NSString *)url andParameter:(NSDictionary *)p