現實上,從代碼的角度,調起付出APP就是把一些症結的參數經由過程必定方法打包成為一個定單,然後發送到付出平台的辦事器。所以,只需弄清晰了參數設置,弄清晰了每一個付出平台的SDK外面一些症結API的應用,根本上便可以很簡略的支撐付出。
明天記載一下客戶端外面,若何支撐微信付出。起首。我們要細心浏覽一下微信SDK的開辟文檔,懂得一下全部付出的年夜概流程。
然後依據提醒,把響應的SDK下載上去,所謂的SDK,也就是一個鏈接庫和兩個頭文件,很簡略。
下載終了,須要把SDK導入到工程外面,而且設置裝備擺設一下工程。由於開辟者文檔曾經有具體描寫,這裡就不再復述。
從文檔看到,調起微信付出其實最焦點的是一下這麼一段
<code class="hljs" vbscript="">PayReq *request = [[[PayReq alloc] init] autorelease]; request.partnerId = @10000100; request.prepayId= @1101000000140415649af9fc314aa427; request.package = @Sign=WXPay; request.nonceStr= @a462b76e7436e98e0ed6e13c64b4fd1c; request.timeStamp= @1397527777; request.sign= @582282D72DD2B03AD892830965F428CB16E7A256; [WXApi sendReq:request];</code>
這裡的典范是一段hardcode,真正應用的時刻,參數都須要自行傳入。
為了弄清晰若何應用API,我們可以下載Sample代碼。不外,這個sample代碼應當是微信的練習生寫的,並且應當是一個關於C++比擬熟習,關於ObjectC比擬生疏的練習生。。。代碼作風可以看出許多器械哈。。所以這個sample讀起來總認為有點奇異。固然,寫出這個demo也是須要不錯的程度,由於這個sample不只僅是一些API的挪用,還包含了一些算法的完成,MD5之類的。
看懂了sample以後,普通可以本身重構一下,成為本身APP外面的一個Manager類。
我是在2015 5 23下載的微信Sampel代碼,外面包含有:
ApiXmlRss/ target=_blank class=infotextkey>Xml.h
ApiXmlRss/ target=_blank class=infotextkey>Xml.m
WXUtil.h
WXUtil.m
payRequestHandler.h
payRequestHandler.m
假如比擬重視定名標准的OC法式猿,就會認為這個payRequestHandler類異常別扭,不相符camel定名規矩,並且handler這個詞更傾向於c++作風。我就以這個類為原型,重構了一下,並改裝成一個傳參的辦法,供本身的APP挪用。APP外面賣商品,普通就是商品名字,價錢兩個症結參數。所以這個重構的辦法也只是供給這兩個參數的接口。
ApiXml.h && ApiXml.m && WXUtil.h && WXUtil.m不變
<code class="hljs" objectivec="">// // WechatPayManager.h // // Created by HuangCharlie on 5/24/15. // // #import <foundation foundation.h=""> #import WXUtil.h #import ApiXml.h #import WXApi.h // 賬號帳戶材料 // 更改商戶把相干參數後可測試 #define APP_ID @wx@@@@@@@@@@@@@@@@ //APPID #define APP_SECRET @ //appsecret,看起來似乎沒用 //商戶號,填寫商戶對應參數 #define MCH_ID @@@@@@@@@@@ //商戶API密鑰,填寫響應參數 #define PARTNER_ID @12345678901234567890123456789012 //付出成果回調頁面 #define NOTIFY_URL @http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php //獲得辦事器端付出數據地址(商戶自界說)(在小吉這裡,簽名算法直接放在APP端,故不須要自界說) #define SP_URL @http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php @interface WechatPayManager : NSObject { } //預付付網關url地址 @property (nonatomic,strong) NSString* payUrl; //debug信息 @property (nonatomic,strong) NSMutableString *debugInfo; @property (nonatomic,assign) NSInteger lastErrCode;//前往的毛病碼 //商戶症結信息 @property (nonatomic,strong) NSString *appId,*mchId,*spKey; //初始化函數 -(id)initWithAppID:(NSString*)appID mchID:(NSString*)mchID spKey:(NSString*)key; //獲得以後的debug信息 -(NSString *) getDebugInfo; //獲得預付付定單信息(焦點是一個prepayID) - (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name price:(NSString*)price device:(NSString*)device; @end </foundation></code> <code class="hljs" objectivec="">// // WechatPayManager.m // // Created by HuangCharlie on 5/24/15. // // #import WechatPayManager.h @implementation WechatPayManager //初始化函數 -(id)initWithAppID:(NSString*)appID mchID:(NSString*)mchID spKey:(NSString*)key { self = [super init]; if(self) { //初始化公有參數,重要是一些和商戶有關的參數 self.payUrl = @https://api.mch.weixin.qq.com/pay/unifiedorder; if (self.debugInfo == nil){ self.debugInfo = [NSMutableString string]; } [self.debugInfo setString:@]; self.appId = appID;//微信分派給商戶的appID self.mchId = mchID;// self.spKey = key;//商戶的密鑰 } return self; } //獲得debug信息 -(NSString*) getDebugInfo { NSString *res = [NSString stringWithString:self.debugInfo]; [self.debugInfo setString:@]; return res; } //創立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=%@, self.spKey]; //獲得MD5 sign簽名 NSString *md5Sign =[WXUtil md5:contentString]; //輸入Debug Info [self.debugInfo appendFormat:@MD5簽名字符串: %@ ,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> ]; for (NSString *categoryId in keys) { [reqPars appendFormat:@<%@>%@<!--%@--> , categoryId, [packageParams objectForKey:categoryId],categoryId]; } [reqPars appendFormat:@<sign>%@</sign> </xml>, sign]; return [NSString stringWithString:reqPars]; } //提交預付付 -(NSString *)sendPrepay:(NSMutableDictionary *)prePayParams { NSString *prepayid = nil; //獲得提交付出 NSString *send = [self genPackage:prePayParams]; //輸入Debug Info [self.debugInfo appendFormat:@API鏈接:%@ , self.payUrl]; [self.debugInfo appendFormat:@發送的xml:%@ , send]; //發送要求post xml數據 NSData *res = [WXUtil httpSend:self.payUrl method:@POST data:send]; //輸入Debug Info [self.debugInfo appendFormat:@辦事器前往: %@ ,[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]]; XMLHelper *xml = [[XMLHelper alloc] autorelease]; //開端解析 [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; [self.debugInfo appendFormat:@獲得預付付生意業務標示勝利! ]; } }else{ self.lastErrCode = 1; [self.debugInfo appendFormat:@gen_sign=%@ _sign=%@ ,sign,send_sign]; [self.debugInfo appendFormat:@辦事器前往簽名驗證毛病!!! ]; } }else{ self.lastErrCode = 2; [self.debugInfo appendFormat:@接口前往毛病!!! ]; } return prepayid; } - (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name price:(NSString*)price device:(NSString*)device { //定單題目,展現給用戶 NSString* orderName = name; //定單金額,單元(分) NSString* orderPrice = price;//以分為單元的整數 //付出裝備號或門店號 NSString* orderDevice = device; //付出類型,固定為APP NSString* orderType = @APP; //發器付出的機械ip,臨時沒有發明其感化 NSString* orderIP = @196.168.1.1; //隨機數串 srand( (unsigned)time(0) ); NSString *noncestr = [NSString stringWithFormat:@%d, rand()]; NSString *orderNO = [NSString stringWithFormat:@%ld,time(0)]; //================================ //預支單參數定單設置 //================================ NSMutableDictionary *packageParams = [NSMutableDictionary dictionary]; [packageParams setObject: self.appId forKey:@appid]; //開放平台appid [packageParams setObject: self.mchId forKey:@mch_id]; //商戶號 [packageParams setObject: orderDevice forKey:@device_info]; //付出裝備號或門店號 [packageParams setObject: noncestr forKey:@nonce_str]; //隨機串 [packageParams setObject: orderType forKey:@trade_type]; //付出類型,固定為APP [packageParams setObject: orderName forKey:@body]; //定單描寫,展現給用戶 [packageParams setObject: NOTIFY_URL forKey:@notify_url]; //付出成果異步告訴 [packageParams setObject: orderNO forKey:@out_trade_no];//商戶定單號 [packageParams setObject: orderIP forKey:@spbill_create_ip];//發器付出的機械ip [packageParams setObject: orderPrice forKey:@total_fee]; //定單金額,單元為分 //獲得prepayId(預付付生意業務會話標識) NSString *prePayid; prePayid = [self sendPrepay:packageParams]; if(prePayid == nil) { [self.debugInfo appendFormat:@獲得prepayid掉敗! ]; return 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 = [NSString stringWithFormat:@Sign=%@,package]; package = @Sign=WXPay; //第二次簽名參數列表 NSMutableDictionary *signParams = [NSMutableDictionary dictionary]; [signParams setObject: self.appId forKey:@appid]; [signParams setObject: self.mchId forKey:@partnerid]; [signParams setObject: nonce_str forKey:@noncestr]; [signParams setObject: package forKey:@package]; [signParams setObject: time_stamp forKey:@timestamp]; [signParams setObject: prePayid forKey:@prepayid]; //生成簽名 NSString *sign = [self createMd5Sign:signParams]; //添加簽名 [signParams setObject: sign forKey:@sign]; [self.debugInfo appendFormat:@第二步簽名勝利,sign=%@ ,sign]; //前往參數列表 return signParams; } @end</code>
然後,在須要挪用微信付出的Controller外面,新建一個辦法。在適合的處所挪用。這個辦法外面應用WechatPayManager這個類停止了初始化和參數封裝,然後把上述的焦點代碼(PayReq那一段)
<code class="hljs" objectivec="">- (void)wxPayWithOrderName:(NSString*)name price:(NSString*)price { //創立付出簽名對象 && 初始化付出簽名對象 WechatPayManager* wxpayManager = [[[WechatPayManager alloc]initWithAppID:APP_ID mchID:MCH_ID spKey:PARTNER_ID] autorelease]; //獲得到現實調起微信付出的參數後,在app端調起付出 //生成預付付定單,現實上就是把症結參數停止第一次加密。 NSString* device = [[UserManager defaultManager]userId]; NSMutableDictionary *dict = [wxpayManager getPrepayWithOrderName:name price:price device:device]; if(dict == nil){ //毛病提醒 NSString *debug = [wxpayManager getDebugInfo]; return; } NSMutableString *stamp = [dict objectForKey:@timestamp]; //調起微信付出 PayReq* req = [[[PayReq alloc] init]autorelease]; 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]; // BOOL flag = [WXApi sendReq:req]; BOOL flag = [WXApi safeSendReq:req]; }</code>
再者,付出完成了須要挪用一個delegate,這個delegate便利特性化顯示付出成果。普通直接把這兩個delegate放在AppDelegate就行了。由於有一些其他內容也是須要在AppDelegate外面完成,省的離開找不到。
<code class="hljs" objectivec="">-(void) onResp:(BaseResp*)resp { //啟動微信付出的response NSString *strMsg = [NSString stringWithFormat:@errcode:%d, resp.errCode]; if([resp isKindOfClass:[PayResp class]]){ //付出前往成果,現實付出成果須要去微佩服務器端查詢 switch (resp.errCode) { case 0: strMsg = @付出成果:勝利!; break; case -1: strMsg = @付出成果:掉敗!; break; case -2: strMsg = @用戶曾經加入付出!; break; default: strMsg = [NSString stringWithFormat:@付出成果:掉敗!retcode = %d, retstr = %@, resp.errCode,resp.errStr]; break; } } }</code>
留意事項:
1)假如APP外面曾經應用了ShareSDK,就有一些處所要留意。不要再反復導入微信的SDK,由於shareSDK外面的extend曾經包含了微信的SDK。
2)微信自己是勉勵客戶APP把簽名算法放到辦事器下面,如許信息就不輕易被破解。然則假如客戶APP自己沒有辦事器端,或許以為不須要放到辦事器端,也能夠直接把簽名(加密)的部門直接放在APP端。Sample代碼的正文有點亂,屢次提到辦事器如此,然則其實可以不這麼做。
3)微信的price單元是分。留意下便可。
4)臨時想不到,今後想到了再記載。。
以上是本文給年夜家論述的IOS客戶端接入微信付出的全體內容,願望年夜家愛好。
【IOS客戶端接入微信付出】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!