我的天吶??官脓,怎么會(huì)有這么詳細(xì)的微信支付說明

公司要求項(xiàng)目添加上微信支付和支付寶支付在這里我將自己的心得以及自己總結(jié)的步驟總結(jié)在這里,希望讓讀者少一點(diǎn)入坑涝焙。卑笨,那么我們現(xiàn)在從最難的骨頭啃起來,一步步教大家完成微信支付仑撞,關(guān)于申請(qǐng)微信支付的東西我就不再這里累贅赤兴,很多帖子都有(其實(shí)是因?yàn)楣具@部分我沒有參與,嘿嘿)隧哮。開始我們的微信支付的旅行吧桶良。
前提條件,讓你的 APP有支付的本領(lǐng) 沮翔,申請(qǐng)到微信支付相關(guān)以后陨帆,下面這些東西對(duì)我們很重要。

前提條件:
//APPID 一般以wx開頭
static NSString *const ZQAppID = @"APPID";
//appsecret
static NSString *const ZQAppSecret = @"appsecret";
//商戶號(hào)采蚀,填寫商戶對(duì)應(yīng)參數(shù)
static NSString *const ZQMchID = @"商戶號(hào)";
//商戶API密鑰疲牵,填寫相應(yīng)參數(shù)
static NSString *const ZQPartnerID = @"商戶API密鑰";
// 預(yù)支付請(qǐng)求路徑固定可以不改變
static NSString *const ZQPrePayURL =       @"https://api.mch.weixin.qq.com/pay/unifiedorder";
// // 支付回調(diào)頁面(異步)   (https://api.mch.weixin.qq.com/pay/unifiedorder)(異步處理支付調(diào)用返回?cái)?shù)據(jù))
static NSString *const ZQPayNotifyURL = @"支付回調(diào)頁面";
注意

微信支付的單位為分!2妗瑰步!整數(shù)類型才可以(int)

流程簡(jiǎn)述

支付要保證安全性,就要使用加密璧眠。微信當(dāng)然也是這樣,微信為了防止中間有人加入竊取信息或者改變價(jià)格读虏。有自己的加密方式——生成預(yù)支付Id责静,我們通過封裝數(shù)據(jù)形成XML格式(中間加密)以字符串類型傳給微信,獲取預(yù)支付Id盖桥。緊接著灾螃,獲取以后通過預(yù)支付等信息再次加密。APP將參數(shù)傳給微信揩徊,付款成功腰鬼!回調(diào)信息說明支付情況嵌赠。(關(guān)于加密具體怎么實(shí)現(xiàn)我會(huì)在下面詳細(xì)說明)。

步驟以及代碼

接下來說說主要的步驟吧(比比叨這么久終于說正事了熄赡,請(qǐng)不要打我么么噠~)


H92X9S)M$J0XZQ@K13C0GVS.jpg

1.在做微信支付以前導(dǎo)入

libc++.tbd
libsqlite3.0.tbd
libz.tbd
SystemConfiguration.framework
CoreTelephony.framework
Security.framework

2.在AppDelegate 的導(dǎo)入頭文件 #import "WXApi.h" 掛上代理 WXApiDelegate

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//這里是你自己寫的一些其他代碼 實(shí)例化window 設(shè)置根視圖云云
  [WXApi registerApp:@"APPID" withDescription:@"應(yīng)用描述"];

  } 
 //支付回調(diào)
  - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
   return  [WXApi handleOpenURL:url delegate:self];
   }
  - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
   return [WXApi handleOpenURL:url delegate:self];
   }


   #pragma mark 微信回調(diào)的代理方法
   - (void)onResp:(BaseResp *)resp {
   if ([resp isKindOfClass:[PayResp class]]) {
   PayResp *response = (PayResp *)resp;
   switch (response.errCode) {
   case WXSuccess:
   NSLog(@"suceess");
   break;
   default:
   NSLog(@"failed");
   break;
   }
   }
   }

如果集成里支付寶以及微信支付等 姜挺,走的回調(diào)方法是相同的 ,我們是通過 回調(diào)中字符串sourceApplication 進(jìn)行判斷的 例如支付寶支付 為com.alipay.iphoneclient 微信支付為 com.tencent.xin

3.在targets的info中添加 urltypes添加一個(gè)在 identifier自己起一個(gè)名稱(最好軟件英文名字) 在 URL schemes 中寫下APPID

E618D85B-4F5C-480B-96DA-6F4E9FE548A9.png

4.觸發(fā)支付
觸發(fā)支付彼硫,就要對(duì)自己的訂單號(hào)價(jià)格等進(jìn)行加密 在這里就可以分成兩種加密 炊豪,一種是在APP端進(jìn)行加密,第二種是在服務(wù)端進(jìn)行加密拧篮。一般使用的在服務(wù)端加密比較安全词渤。一個(gè)個(gè)進(jìn)行說明。
4.1 服務(wù)端進(jìn)行加密
服務(wù)端加密我們不需要知道具體加密怎么進(jìn)行的串绩。(在底下我會(huì)給你說清楚的啦~)我們只是需要將所需參數(shù)傳過去 我是用的AFN

//初始化一個(gè)請(qǐng)求管理器
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
//接口地址
NSString *urlString = [NSString stringWithFormat:@"%@%@",@"地址頭",@"其他"];
//參數(shù)字典
NSDictionary *parameters =@{@"fcode": @"賬號(hào)",
                            @"password": @"密碼",@"out_trade_no":@"訂單號(hào)",@"total_fee":@"金額(分為單位)",@"attach":@"商品詳情"};
//post請(qǐng)求
[manager POST:urlString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
    //返回狀態(tài)值1表示成功 0表示失敗
    NSString *state=responseObject[@"state"];
   //預(yù)支付ID
    NSString *prepayid=responseObject[@"prepayid"];
   //返回文字信息成功或者失敗
    NSString *message=responseObject[@"message"];
   //請(qǐng)求數(shù)據(jù)成功
        if ([state intValue]==1) {
   //支付信息
            PayReq* req             = [[PayReq alloc] init];
   //APPID
            req.openID              = [responseObject objectForKey:@"appid"];
   //商戶號(hào)
            req.partnerId           = [responseObject objectForKey:@"partnerid"];
   //預(yù)支付ID
            req.prepayId            = [responseObject objectForKey:@"prepayid"];
   //時(shí)間戳
            req.nonceStr            = [responseObject objectForKey:@"noncestr"];
   //支付類型(為固定字符串:Sign=WXPay)
            req.timeStamp           = [[responseObject objectForKey:@"timestamp"] intValue];
   //加密串
            req.package             = [responseObject objectForKey:@"package"];
   //預(yù)支付ID
            req.sign                = [responseObject objectForKey:@"sign"];
            
            // 發(fā)起微信支付
            [WXApi sendReq:req];;
            
        }
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

}];

后臺(tái)沒有加密錯(cuò)誤缺虐,那么會(huì)跳轉(zhuǎn)到微信上進(jìn)行支付。(好累啊 怎么還不結(jié)束呀)
4.2 APP端進(jìn)行加密
這種方法可以自己先進(jìn)行測(cè)試 礁凡,或者為了縮短工期自己進(jìn)行所有工作志笼。(看起來好像好厲害的樣子啊 )
首先,下載文章最底部封裝的微信支付文件把篓,導(dǎo)入到工程中纫溃。
支付界面引入頭文件
#import "ZQPay.h"
在觸發(fā)支付的方法中調(diào)用

[ZQPay payWXWithOrderName:@"訂單名字(不是訂單詳情)" price:@"訂單價(jià)格(單位為分)" tradeNo:@"訂單號(hào)" attach:@"訂單詳情"]

調(diào)用支付成功!結(jié)束 (我說了“結(jié)束”一定會(huì)打我的吧韧掩,原理步驟都不說 這太敷衍了 哈哈哈 紊浩,你們來打我啊)

![ZH]0RDFI%M7FXPS`(0FBEUE.jpg](http://upload-images.jianshu.io/upload_images/1141241-53e22ffdd4735dac.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
(傲迫瘛7凰!滑臊!不要打我 我說還不行嗎)
繼續(xù)正題口芍!
傳入?yún)?shù)我具體做了一些什么呢現(xiàn)在我就說說 步驟了啊(我不會(huì)就這樣輕易的狗帶)雇卷。
4.2.1 獲取預(yù)支付Id 鬓椭,將所需要參數(shù)封裝成字典

NSMutableDictionary *orderParas = [NSMutableDictionary dictionary];

[orderParas setObject: ZQAppID           forKey:@"appid"];       //開放平臺(tái)appid
[orderParas setObject: ZQMchID           forKey:@"mch_id"];//商戶號(hào)
[orderParas setObject: @"APP-001"        forKey:@"device_info"]; //支付設(shè)備號(hào)或門店號(hào)
[orderParas setObject: noncestr          forKey:@"nonce_str"];   //隨機(jī)串
[orderParas setObject: @"APP"            forKey:@"trade_type"];  //支付類型,固定為APP
[orderParas setObject: order_name        forKey:@"body"];        //訂單描述关划,展示給用戶
[orderParas setObject: ZQPayNotifyURL    forKey:@"notify_url"];  //支付結(jié)果異步通知
[orderParas setObject: tradeNo           forKey:@"out_trade_no"];//商戶訂單號(hào)
[orderParas setObject: [ZQDeVice deviceIPAdress]    forKey:@"spbill_create_ip"];//發(fā)起支付的機(jī)器ip
[orderParas setObject: order_price       forKey:@"total_fee"];       //訂單金額小染,單位為分
[orderParas setObject:attach forKey:@"attach"];//訂單詳細(xì)描述

4.2.2添加sign加密串 形成XMl格式字符串 paras 為封裝的字典(第一次加密)

NSString *sign;
NSMutableString *reqPars = [NSMutableString string];

//生成xml的package
NSArray *keys = [paras allKeys];
[reqPars appendString:@"<xml>\\n"];

for (NSString *categoryId in keys) {
    [reqPars appendFormat:@"<%@>%@</%@>\\n", categoryId, [paras objectForKey:categoryId],categoryId];
}

//生成簽名,并將簽名添加到簽名包中
sign = [self createMd5Sign:paras];
[reqPars appendFormat:@"<sign>%@</sign>\\n</xml>", sign];

return [NSString stringWithString:reqPars];

4.2.3將獲取的xml串傳給微信獲取預(yù)支付ID 接口地址 @"https://api.mch.weixin.qq.com/pay/unifiedorder" send為XML串

//發(fā)送請(qǐng)求post xml數(shù)據(jù)
NSData *res = [ZQUtil httpSend:ZQPrePayURL method:@"POST" data:send];

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

//判斷返回
NSString *return_code = [resParams objectForKey:@"return_code"];
NSString *result_code = [resParams objectForKey:@"result_code"];
 NSString *codeDes = [resParams objectForKey:@"err_code_des"];
if ( [return_code isEqualToString:@"SUCCESS"] )
{
    //生成返回?cái)?shù)據(jù)的簽名
    NSString *sign      = [self createMd5Sign:resParams];
    
    NSString *send_sign =[resParams objectForKey:@"sign"] ;
    
    //驗(yàn)證簽名正確性
    if( [sign isEqualToString:send_sign]){
        if( [result_code isEqualToString:@"SUCCESS"]) {
            //驗(yàn)證業(yè)務(wù)處理狀態(tài)
            prepayid    = [resParams objectForKey:@"prepay_id"];
            return_code = 0;
        }
    }
}
[dic setValue:prepayid forKey:@"prepay_id"];
[dic setValue:codeDes forKey:@"err_code_des"];
return dic;

4.2.4 將獲取的預(yù)支付id重新加密獲取新的sign 封裝成字典

//獲取到prepayid后進(jìn)行第二次簽名
NSString    *package, *time_stamp, *nonce_str;

//設(shè)置支付參數(shù)
time_t now;

time(&now);

time_stamp  = [NSString stringWithFormat:@"%ld", now];
nonce_str   = [ZQUtil stringMd5WithString:time_stamp];


package         = @"Sign=WXPay";

// 第二次簽名參數(shù)列表
NSMutableDictionary *signParas = [NSMutableDictionary dictionary];
[signParas setObject: ZQAppID        forKey:@"appid"];
[signParas setObject: nonce_str    forKey:@"noncestr"];
[signParas setObject: package      forKey:@"package"];
[signParas setObject: ZQMchID        forKey:@"partnerid"];
[signParas setObject: time_stamp   forKey:@"timestamp"];
[signParas setObject: prepayID     forKey:@"prepayid"];
// 生成簽名
NSString *sign  = [self createMd5Sign:signParas];

// 添加簽名
[signParas setObject: sign         forKey:@"sign"]; 

時(shí)間戳為新的時(shí)間戳 隨機(jī)數(shù)是通過時(shí)間戳MD5加密獲取的

4.2.5 至此加密結(jié)束 發(fā)起微信支付跳轉(zhuǎn)到微信進(jìn)行付款

PayReq* req             = [[PayReq alloc] init];
req.openID              = [paras objectForKey:@"appid"];
req.partnerId           = [paras objectForKey:@"partnerid"];
req.prepayId            = [paras objectForKey:@"prepayid"];
req.nonceStr            = [paras objectForKey:@"noncestr"];
req.timeStamp           = [[paras objectForKey:@"timestamp"] intValue];
req.package             = [paras objectForKey:@"package"];
req.sign                = [paras objectForKey:@"sign"];

// 發(fā)起微信支付
[WXApi sendReq:req];

5.微信支付成功以后 要通知服務(wù)端以及APP端 服務(wù)器是通過回調(diào)地址進(jìn)行操作,而對(duì)于App端通過Appdelegate中回調(diào)函數(shù)調(diào)用微信代理 步驟2中有說明。我就不再說了么么噠 (算了贮折,我再這里在重新嗶嗶一次吧)
//支付回調(diào)
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [WXApi handleOpenURL:url delegate:self];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [WXApi handleOpenURL:url delegate:self];
}

   #pragma mark 微信回調(diào)的代理方法
 - (void)onResp:(BaseResp *)resp {
if ([resp isKindOfClass:[PayResp class]]) {
    PayResp *response = (PayResp *)resp;
    NSString *message;
    switch (response.errCode) {
      case WXSuccess:
        {  message=@"支付成功";
            [[NSNotificationCenter defaultCenter] postNotificationName:APP_PAY_SUCCESS object:nil];
        }
            break;
        case WXErrCodeCommon:
         //普通錯(cuò)誤類型
            message=@"支付錯(cuò)誤";
            break;
        case WXErrCodeUserCancel:
           //用戶點(diǎn)擊取消并且返回
           message=@"您取消了交易";
            break;
        case WXErrCodeSentFail:
            //發(fā)送失敗
           message=@"信息發(fā)送失敗";
            break;
        case WXErrCodeAuthDeny:
           //授權(quán)失敗
            message=@"授權(quán)失敗";
            break;
        case WXErrCodeUnsupport:
          //微信不不支持
           message=@"您的微信版本過低";
            break;
        default:
            NSLog(@"failed");
            break;
    }

  }
}

支付成功以后通過通知告知用戶支付情況
5.1 支付界面接收成功通知告知用戶(我這里是跳轉(zhuǎn)到新的界面)

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appPaySuccess) name:APP_PAY_SUCCESS object:nil];

5.2通知方法

-(void)appPaySuccess{
ZQPaySuccessVC *paySuccessVC=[[ZQPaySuccessVC alloc]init];
[self.navigationController pushViewController:paySuccessVC animated:YES];
}

5.3移除通知(不移除會(huì)崩潰呦)

-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:APP_PAY_SUCCESS object:nil];
}

6.支付完成裤翩!
歡迎小伙伴們給我補(bǔ)充,提意見 么么噠~~~

點(diǎn)我 獲取支付法寶
附:寶寶好累啊 關(guān)注本寶寶吧~~

89c40b46f21fbe09f9774dff6d600c338644adc4.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末调榄,一起剝皮案震驚了整個(gè)濱河市踊赠,隨后出現(xiàn)的幾起案子呵扛,更是在濱河造成了極大的恐慌,老刑警劉巖筐带,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件今穿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡烫堤,警方通過查閱死者的電腦和手機(jī)荣赶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸽斟,“玉大人拔创,你說我怎么就攤上這事「恍睿” “怎么了剩燥?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)立倍。 經(jīng)常有香客問我灭红,道長(zhǎng),這世上最難降的妖魔是什么口注? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任变擒,我火速辦了婚禮,結(jié)果婚禮上寝志,老公的妹妹穿的比我還像新娘娇斑。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扒披,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苦丁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天物臂,我揣著相機(jī)與錄音旺拉,去河邊找鬼。 笑死鹦聪,一個(gè)胖子當(dāng)著我的面吹牛账阻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播泽本,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼姻僧!你這毒婦竟也來了规丽?” 一聲冷哼從身側(cè)響起蒲牧,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赌莺,沒想到半個(gè)月后冰抢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡艘狭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年挎扰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巢音。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡遵倦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出官撼,到底是詐尸還是另有隱情梧躺,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布傲绣,位于F島的核電站掠哥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秃诵。R本人自食惡果不足惜续搀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望菠净。 院中可真熱鬧禁舷,春花似錦、人聲如沸嗤练。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽煞抬。三九已至霜大,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間革答,已是汗流浹背战坤。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留残拐,地道東北人途茫。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像溪食,于是被迫代替她去往敵國和親囊卜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,525評(píng)論 25 707
  • 一、背景介紹 作為一名Android開發(fā)栅组,從最初的跌跌撞撞到現(xiàn)在小有所悟雀瓢,這其中經(jīng)歷過的辛酸苦辣也是一種痛并快樂著...
    freecats08閱讀 4,816評(píng)論 7 54
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件玉掸、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,033評(píng)論 4 62
  • Anaven閱讀 232評(píng)論 0 0
  • 一開始刃麸,我是想認(rèn)真的畫一只萌萌兔的, 然后司浪, 然后我發(fā)現(xiàn)泊业,我想多了 寶寶心里苦,寶寶不說……
    阿拉斯加海灣0閱讀 400評(píng)論 2 6