iOS之“微信支付”開發流程

實現微信支付的開發,iOS端裏面只需要四個步驟:

  • 向服務端請求預支付,獲得prepayid以及noncestr;

  • 把參數拼起來簽名;

  • 發起支付請求;

  • 處理支付結果。

iOS的微信SDK的接入:即爲“向微信註冊你的應用程序id”、“下載微信終端SDK文件”、“搭建開發環境”、“在代碼中使用開發工具包”。
詳情請參看iOS的接入指南:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417694084&token=96a6fb085dbc61bcafd732d1469e5fd0e20c9819&lang=zh_CN

導入微信支付庫:
開發者需要在工程中鏈接上:SystemConfiguration.framework,libz.dylib,libsqlite3.0.dylib,最重要的庫是libc++.dylib;

iOS微信支付的具體流程:

  • 向服務端請求預支付,獲得prepayid以及noncestr
//提交預支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams {
    NSString *prepayid = nil;
    //獲取提交支付
    NSString *send = [self genPackage:prePayParams];
    //輸出Debug Info
    [debugInfo appendFormat:@"API鏈接:%@\n", payUrl];
    [debugInfo appendFormat:@"發送的xml:%@\n", send];
    //發送請求post xml數據
    NSData *res = [WXUtil httpSend:payUrl method:@"POST" data:send];
    //輸出Debug Info
    [debugInfo appendFormat:@"服務器返回:\n%@\n\n",[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];

    XMLHelper *xml  = [XMLHelper alloc];

    //開始解析
    [xml startParse:res];
    NSMutableDictionary *resParams = [xml getDict];

    //判斷返回
    NSString *return_code   = [resParams objectForKey:@"return_code"];
    NSString *result_code   = [resParams objectForKey:@"result_code"];
    if ([return_code isEqualToString:@"SUCCESS"]) {
        //生成返回數據的簽名
        NSString *sign      = [self createMd5Sign:resParams ];
        NSString *send_sign =[resParams objectForKey:@"sign"] ;

        //驗證簽名正確性
        if( [sign isEqualToString:send_sign]) {
            if( [result_code isEqualToString:@"SUCCESS"]) {
                //驗證業務處理狀態
                prepayid    = [resParams objectForKey:@"prepay_id"];
                return_code = 0;
                [debugInfo appendFormat:@"獲取預支付交易標示成功!\n"];
            }
        }else{
            last_errcode = 1;
            [debugInfo appendFormat:@"gen_sign=%@\n   _sign=%@\n",sign,send_sign];
            [debugInfo appendFormat:@"服務器返回簽名驗證錯誤!!!\n"];
        }
    }else{
        last_errcode = 2;
        [debugInfo appendFormat:@"接口返回錯誤!!!\n"];
    }
    return prepayid;
}

- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo {

    //訂單標題,展示給用戶
    NSString *order_name = @"展示給用戶的訂單標題";
    //預付單參數訂單設置
    srand( (unsigned)time(0) );
    NSString *noncestr  = [NSString stringWithFormat:@"%d", rand()];
    NSString *orderno   = orderNo;
    NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];

    [packageParams setObject: appid          forKey:@"appid"];           //開放平臺appid
    [packageParams setObject: mchid          forKey:@"mch_id"];          //商戶號
    [packageParams setObject: @"APP-001"     forKey:@"device_info"];     //支付設備號或門店號
    [packageParams setObject: noncestr       forKey:@"nonce_str"];       //隨機串
    [packageParams setObject: @"APP"         forKey:@"trade_type"];      //支付類型,固定爲APP
    [packageParams setObject: order_name     forKey:@"body"];            //訂單描述,展示給用戶
    [packageParams setObject: NOTIFY_URL     forKey:@"notify_url"];      //支付結果異步通知
    [packageParams setObject: orderno        forKey:@"out_trade_no"];    //商戶訂單號
    [packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];//發器支付的機器ip
    [packageParams setObject: order_price    forKey:@"total_fee"];       //訂單金額,單位爲分

    //獲取prepayId(預支付交易會話標識)
    NSString *prePayid;
    prePayid = [self sendPrepay:packageParams];

    if ( prePayid != nil) {
        //獲取到prepayid後進行第二次簽名
        NSString *package, *time_stamp, *nonce_str;

        //設置支付參數
        time_t now;
        time(&now);
        time_stamp  = [NSString stringWithFormat:@"%ld", now];
        nonce_str   = [WXUtil md5:time_stamp];
        //重新按提交格式組包,微信客戶端暫只支持package=Sign=WXPay格式,須考慮升級後支持攜帶package具體參數的情況
        package = @"Sign=WXPay";

        //第二次簽名參數列表
        NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
        [signParams setObject: appid        forKey:@"appid"];
        [signParams setObject: nonce_str    forKey:@"noncestr"];
        [signParams setObject: package      forKey:@"package"];
        [signParams setObject: mchid        forKey:@"partnerid"];
        [signParams setObject: time_stamp   forKey:@"timestamp"];
        [signParams setObject: prePayid     forKey:@"prepayid"];

        //生成簽名
        NSString *sign = [self createMd5Sign:signParams];

        //添加簽名
        [signParams setObject: sign forKey:@"sign"];
        [debugInfo appendFormat:@"第二步簽名成功,sign=%@\n",sign];

        //返回參數列表
        return signParams;

    }else{
        [debugInfo appendFormat:@"獲取prepayid失敗!\n"];
    }
    return nil;
}
  • 把參數拼起來簽名
//創建package簽名
- (NSString*)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:@""] && ![categoryId isEqualToString:@"sign"] && ![categoryId isEqualToString:@"key"])
        {
            [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
        }
    }
    //添加key字段
    [contentString appendFormat:@"key=%@", spkey];
    //得到MD5 sign簽名
    NSString *md5Sign =[WXUtil md5:contentString];
    //輸出Debug Info
    [debugInfo appendFormat:@"MD5簽名字符串:\n%@\n\n",contentString];

    return md5Sign;
}

//獲取package帶參數的簽名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams {
    NSString *sign;
    NSMutableString *reqPars=[NSMutableString string];
    //生成簽名
    sign = [self createMd5Sign:packageParams];
    //生成xml的package
    NSArray *keys = [packageParams allKeys];
    [reqPars appendString:@"<xml>\n"];
    for (NSString *categoryId in keys) {
        [reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId];
    }
    [reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];
    return [NSString stringWithString:reqPars];
}
  • 發起支付請求
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //支付結果通知註冊
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"ORDER_PAY_NOTIFICATION" object:nil];
}

//調用微信支付
- (void)viewDidLoad {
    [super viewDidLoad];
    [self WXPay];
}

#pragma mark -- 發起”微信支付“請求
- (void)WXPay {
    if (![WXApi isWXAppInstalled]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"您還沒有安裝微信" message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            //跳轉到微信的下載安裝地址
        }];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
        return ;
    }
    YDWWeChatPayResquest *req = [YDWWeChatPayResquest new];
    //初始化支付簽名對象
    [req init:APP_ID mch_id:MCH_ID];
    //設置密鑰
    [req setKey:PARTNER_ID];

    //獲取到實際調起微信支付的參數後,在app端調起支付
    NSInteger payTheAmount;//支付金額
    NSString *orderMeony = [NSString stringWithFormat:@"%ld",payTheAmount];

    NSDictionary *orderDic;//支付訂單
    NSString *orderNo = [orderDic objectForKey:@"orderNumber"];
    NSMutableDictionary *dict = [req sendPay_WithPrice:orderMeony orderNo: orderNo];

    if(dict == nil){
        //錯誤提示
        NSString *debug = [req getDebugifo];
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:debug message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }else{

        NSMutableString *stamp  = [dict objectForKey:@"timestamp"];

        //調起微信支付
        PayReq* req             = [[PayReq alloc] init];
        req.openID              = [dict objectForKey:@"appid"];
        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"];

        [WXApi sendReq:req];
    }
}


- (void)weixinPay {
    YDWWeixinPayParams *signParams = [[YDWWeixinPayParams alloc] initWithPrepayid:self.prepay_id noncestr:self.nonce_str];
    //調起微信支付
    PayReq *req = [[PayReq alloc] init];
    req.openID = signParams.appid;
    req.partnerId = signParams.partnerid;
    req.prepayId = signParams.prepayid;
    req.nonceStr = signParams.noncestr;
    req.timeStamp = signParams.timestamp.intValue;
    req.package = signParams.package;
    req.sign = [signParams sign];

    [WXApi sendReq:req];
}

#pragma mark - 支付結果通知信息
- (void)getOrderPayResult:(NSNotification *)notification{
    if ([notification.object isEqualToString:@"success"]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"恭喜" message:@"您已成功支付啦!" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }
    else
    {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"支付失敗,可在待付款訂單中查看" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }
}

//移除通知
- (void)viewWillDisappear:(BOOL)animated{
    [[NSNotificationCenter defaultCenter]removeObserver:self];
}
  • 處理支付結果,在AppDelegate中做的工作:

1、導入#import “WXApi.h”和#import “WXApiObject.h”,並遵守WXApiDelegate協議,要使你的程序啓動後微信終端能響應你的程序,必須在代碼中向微信終端註冊你的id:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    [WXApi registerApp:@"WXAppId" withDescription:@"YDWWXPayDes"];

    return YES;
}

2、重寫AppDelegate的handleOpenURL和openURL方法:

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
     if ([url.absoluteString hasPrefix:Weixin_Appid]) {
        return [WXApi handleOpenURL:url delegate:self];
    } 
    return YES;
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

    return [WXApi handleOpenURL:url delegate:self];
}

3、處理結果:

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

    if([resp isKindOfClass:[SendMessageToWXResp class]]) {
        strTitle = [NSString stringWithFormat:@"發送媒體消息結果"];
    }

    if([resp isKindOfClass:[PayResp class]])
    {
        //支付返回結果,實際支付結果需要去微信服務器端查詢
        strTitle = [NSString stringWithFormat:@"支付結果"];

        switch (resp.errCode) {
            case WXSuccess:{
                strMsg = @"支付結果:成功!";
                NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
                NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"success"];
                [[NSNotificationCenter defaultCenter] postNotification:notification];
                break;
            }
            default:{
                strMsg = [NSString stringWithFormat:@"支付結果:失敗!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
                NSLog(@"錯誤,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
                NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"fail"];
                [[NSNotificationCenter defaultCenter] postNotification:notification];
                break;
            }
        }
    }

//        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
//        [alert show];

}

常見的問題:
如果跳轉到微信裏之只彈出了一個確定按鈕,那麼這時候需要檢查幾個方面:
1、appid,mch_id,partner_id是否設置正確。mch_id對應的key其實是partnerid,partner_id對應的key其實是key;
2、timestamp 應爲10位;
3、簽名需要排序,並用md5加密。

最後附上重要的類的全部代碼:
AppDelegate:

//  AppDelegate.h
//  微信支付
//
//  Created by YDW on 16/3/28.
//  Copyright © 2016年 IZHUO.NET. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "WXApi.h"
#import "WXApiObject.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate,WXApiDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

//  AppDelegate.m
//  微信支付
//
//  Created by YDW on 16/3/28.
//  Copyright © 2016年 IZHUO.NET. All rights reserved.
//

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    [WXApi registerApp:@"WXAppId" withDescription:@"YDWWXPayDes"];

    return YES;
}

- (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];
}


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

    if([resp isKindOfClass:[SendMessageToWXResp class]]) {
        strTitle = [NSString stringWithFormat:@"發送媒體消息結果"];
    }

    if([resp isKindOfClass:[PayResp class]])
    {
        //支付返回結果,實際支付結果需要去微信服務器端查詢
        strTitle = [NSString stringWithFormat:@"支付結果"];

        switch (resp.errCode) {
            case WXSuccess:{
                strMsg = @"支付結果:成功!";
                NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
                NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"success"];
                [[NSNotificationCenter defaultCenter] postNotification:notification];
                break;
            }
            default:{
                strMsg = [NSString stringWithFormat:@"支付結果:失敗!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
                NSLog(@"錯誤,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
                NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"fail"];
                [[NSNotificationCenter defaultCenter] postNotification:notification];
                break;
            }
        }
    }

//        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
//        [alert show];

}

YDWWeChatPayResquest:

//  YDWWeChatPayResquest.h
//  微信支付
//
//  Created by YDW on 16/3/28.
//  Copyright © 2016年 IZHUO.NET. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "WXUtil.h"
#import "ApiXml.h"

/*
 * 賬號的賬戶資料:更改商戶後的相關參數後可以使用
 */

#define APP_ID        @"你的APP的ID"       //APPID
#define APP_SECRET    @"你的APP的secret"   //appsecret
#define MCH_ID        @"商戶號"            //商戶號,填寫商戶對應參數
#define PARTNER_ID    @"商戶API密鑰"       //商戶API密鑰,填寫相應參數
#define NOTIFY_URL    @"回調頁面地址"       //支付結果回調頁面
#define SP_URL        @"服務器端支付數據地址"//獲取服務器端支付數據地址(商戶自定義)

@interface YDWWeChatPayResquest : NSObject {
    //預支付的url地址
    NSString *payUrl;

    //lash_errcode;
    long     last_errcode;

    //debug信息
    NSMutableString *debugInfo;
    NSString        *appid,*mchid,*spkey;

}

- (BOOL)init:(NSString *)app_id mch_id:(NSString *)mch_id;
- (NSString *)getDebugifo;
- (long)getLasterrCode;
//設置商戶密鑰
- (void)setKey:(NSString *)key;
//創建package簽名
- (NSString*)createMd5Sign:(NSMutableDictionary*)dict;
//獲取package帶參數的簽名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams;
//提交預支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams;

- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo;
//簽名實例測試
//- (NSMutableDictionary *)sendPay_demo;
@end


//  YDWWeChatPayResquest.m
//  微信支付
//
//  Created by YDW on 16/3/28.
//  Copyright © 2016年 IZHUO.NET. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "YDWWeChatPayResquest.h"

@implementation YDWWeChatPayResquest

- (BOOL)init:(NSString *)app_id mch_id:(NSString *)mch_id {
    payUrl     = @"https://api.mch.weixin.qq.com/pay/unifiedorder";
    if (debugInfo == nil){
        debugInfo = [NSMutableString string];
    }
    [debugInfo setString:@""];
    appid = app_id;
    mchid = mch_id;
    return YES;
}

//設置商戶密鑰
- (void)setKey:(NSString *)key {
    spkey = [NSString stringWithString:key];
}

//獲取debug信息
- (NSString*)getDebugifo {
    NSString *res = [NSString stringWithString:debugInfo];
    [debugInfo setString:@""];
    return res;
}

//獲取最後服務返回錯誤代碼
- (long)getLasterrCode {
    return last_errcode;
}

//創建package簽名
- (NSString*)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:@""] && ![categoryId isEqualToString:@"sign"] && ![categoryId isEqualToString:@"key"])
        {
            [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
        }
    }
    //添加key字段
    [contentString appendFormat:@"key=%@", spkey];
    //得到MD5 sign簽名
    NSString *md5Sign =[WXUtil md5:contentString];
    //輸出Debug Info
    [debugInfo appendFormat:@"MD5簽名字符串:\n%@\n\n",contentString];

    return md5Sign;
}

//獲取package帶參數的簽名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams {
    NSString *sign;
    NSMutableString *reqPars=[NSMutableString string];
    //生成簽名
    sign = [self createMd5Sign:packageParams];
    //生成xml的package
    NSArray *keys = [packageParams allKeys];
    [reqPars appendString:@"<xml>\n"];
    for (NSString *categoryId in keys) {
        [reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId];
    }
    [reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];
    return [NSString stringWithString:reqPars];
}

//提交預支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams {
    NSString *prepayid = nil;
    //獲取提交支付
    NSString *send = [self genPackage:prePayParams];
    //輸出Debug Info
    [debugInfo appendFormat:@"API鏈接:%@\n", payUrl];
    [debugInfo appendFormat:@"發送的xml:%@\n", send];
    //發送請求post xml數據
    NSData *res = [WXUtil httpSend:payUrl method:@"POST" data:send];
    //輸出Debug Info
    [debugInfo appendFormat:@"服務器返回:\n%@\n\n",[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];

    XMLHelper *xml  = [XMLHelper alloc];

    //開始解析
    [xml startParse:res];
    NSMutableDictionary *resParams = [xml getDict];

    //判斷返回
    NSString *return_code   = [resParams objectForKey:@"return_code"];
    NSString *result_code   = [resParams objectForKey:@"result_code"];
    if ([return_code isEqualToString:@"SUCCESS"]) {
        //生成返回數據的簽名
        NSString *sign      = [self createMd5Sign:resParams ];
        NSString *send_sign =[resParams objectForKey:@"sign"] ;

        //驗證簽名正確性
        if( [sign isEqualToString:send_sign]) {
            if( [result_code isEqualToString:@"SUCCESS"]) {
                //驗證業務處理狀態
                prepayid    = [resParams objectForKey:@"prepay_id"];
                return_code = 0;
                [debugInfo appendFormat:@"獲取預支付交易標示成功!\n"];
            }
        }else{
            last_errcode = 1;
            [debugInfo appendFormat:@"gen_sign=%@\n   _sign=%@\n",sign,send_sign];
            [debugInfo appendFormat:@"服務器返回簽名驗證錯誤!!!\n"];
        }
    }else{
        last_errcode = 2;
        [debugInfo appendFormat:@"接口返回錯誤!!!\n"];
    }
    return prepayid;
}

- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo {

    //訂單標題,展示給用戶
    NSString *order_name = @"展示給用戶的訂單標題";
    //預付單參數訂單設置
    srand( (unsigned)time(0) );
    NSString *noncestr  = [NSString stringWithFormat:@"%d", rand()];
    NSString *orderno   = orderNo;
    NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];

    [packageParams setObject: appid          forKey:@"appid"];           //開放平臺appid
    [packageParams setObject: mchid          forKey:@"mch_id"];          //商戶號
    [packageParams setObject: @"APP-001"     forKey:@"device_info"];     //支付設備號或門店號
    [packageParams setObject: noncestr       forKey:@"nonce_str"];       //隨機串
    [packageParams setObject: @"APP"         forKey:@"trade_type"];      //支付類型,固定爲APP
    [packageParams setObject: order_name     forKey:@"body"];            //訂單描述,展示給用戶
    [packageParams setObject: NOTIFY_URL     forKey:@"notify_url"];      //支付結果異步通知
    [packageParams setObject: orderno        forKey:@"out_trade_no"];    //商戶訂單號
    [packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];//發器支付的機器ip
    [packageParams setObject: order_price    forKey:@"total_fee"];       //訂單金額,單位爲分

    //獲取prepayId(預支付交易會話標識)
    NSString *prePayid;
    prePayid            = [self sendPrepay:packageParams];

    if ( prePayid != nil) {
        //獲取到prepayid後進行第二次簽名
        NSString    *package, *time_stamp, *nonce_str;

        //設置支付參數
        time_t now;
        time(&now);
        time_stamp  = [NSString stringWithFormat:@"%ld", now];
        nonce_str   = [WXUtil md5:time_stamp];
        //重新按提交格式組包,微信客戶端暫只支持package=Sign=WXPay格式,須考慮升級後支持攜帶package具體參數的情況
        package         = @"Sign=WXPay";

        //第二次簽名參數列表
        NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
        [signParams setObject: appid        forKey:@"appid"];
        [signParams setObject: nonce_str    forKey:@"noncestr"];
        [signParams setObject: package      forKey:@"package"];
        [signParams setObject: mchid        forKey:@"partnerid"];
        [signParams setObject: time_stamp   forKey:@"timestamp"];
        [signParams setObject: prePayid     forKey:@"prepayid"];

        //生成簽名
        NSString *sign = [self createMd5Sign:signParams];

        //添加簽名
        [signParams setObject: sign forKey:@"sign"];
        [debugInfo appendFormat:@"第二步簽名成功,sign=%@\n",sign];

        //返回參數列表
        return signParams;

    }else{
        [debugInfo appendFormat:@"獲取prepayid失敗!\n"];
    }
    return nil;
}

@end

調用微信支付的頁面:

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self WXPay];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //支付結果通知註冊
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"ORDER_PAY_NOTIFICATION" object:nil];
}

#pragma mark -- 發起”微信支付“請求
- (void)WXPay {
    if (![WXApi isWXAppInstalled]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"您還沒有安裝微信" message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            //跳轉到微信的下載安裝地址
        }];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
        return ;
    }
    YDWWeChatPayResquest *req = [YDWWeChatPayResquest new];
    //初始化支付簽名對象
    [req init:APP_ID mch_id:MCH_ID];
    //設置密鑰
    [req setKey:PARTNER_ID];

    //獲取到實際調起微信支付的參數後,在app端調起支付
    NSInteger payTheAmount;//支付金額
    NSString *orderMeony = [NSString stringWithFormat:@"%ld",payTheAmount];

    NSDictionary *orderDic;//支付訂單
    NSString *orderNo = [orderDic objectForKey:@"orderNumber"];
    NSMutableDictionary *dict = [req sendPay_WithPrice:orderMeony orderNo: orderNo];

    if(dict == nil){
        //錯誤提示
        NSString *debug = [req getDebugifo];
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:debug message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }else{

        NSMutableString *stamp  = [dict objectForKey:@"timestamp"];

        //調起微信支付
        PayReq* req             = [[PayReq alloc] init];
        req.openID              = [dict objectForKey:@"appid"];
        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"];

        [WXApi sendReq:req];
    }
}

#pragma mark - 支付結果通知信息
- (void)getOrderPayResult:(NSNotification *)notification{
    if ([notification.object isEqualToString:@"success"]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"恭喜" message:@"您已成功支付啦!" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }
    else
    {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"支付失敗,可在待付款訂單中查看" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:sureAction];
        [self.navigationController presentViewController:alert animated:YES completion:nil];
    }
}

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

@end

參考資料:
http://www.cocoachina.com/bbs/read.php?tid=303132

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章