1. 程式人生 > >iOS 微信支付開發

iOS 微信支付開發

微信支付有很多坑的,官方提供的文件一點都不全面,而且demo也比較”羞澀”難懂。很多注意的細節都沒有體現出來,走了很多彎路。於是,系統的開發流程如下。(完整的demo附在部落格最後面)這裡麵包括微信支付開發和支付寶開發呼叫客戶端的相容處理。(兩次簽名放在移動端,部落格中沒提到沒安裝微信客戶端的情況,也很簡單[WXApi sendReq:request]呼叫這個方法的返回值為0即可判斷。)
一、環境配置
1、首先是https協議訪問,在plist設定白名單
這裡寫圖片描述

2、當你工程中有微信分享、收藏、支付、登入等,需要在“Info.plist”裡增加如下程式碼(LSApplicationQueriesSchemes)
這裡寫圖片描述

3、解決bitcode編譯不過問題
這裡寫圖片描述

4、設定URL types
這裡寫圖片描述

5、匯入SDK(可從微信官方的demo移植過來)
這裡寫圖片描述

6、匯入系統依賴庫
這裡寫圖片描述

7、特別要注意的是
微信支付是以分為單位的,也就是說,如果你支付金額是保留兩位小數,支付的金額必須*100後再傳給微信支付平臺,其他的依次類推。

二、程式碼開發
1、在程式入口(即applegate.m)需要進行的操作
這裡寫圖片描述

2、增加如下代理方法,否則不回撥微信客服端(也是在delegate.m檔案中)
這裡寫圖片描述

3、微信支付成功的回撥函式
這個有必要說明下,官方文件是這樣說明的:不能以客服端支付成功的結果就直接當做是訂單支付成功的結果,要以伺服器返回的訂單狀態為準,也就是說,客服端支付成功後,微信支付平臺會給伺服器傳送支付成功的訊息,後臺修改訂單狀態,重新返回給客戶端。簡單就是,支付成功要傳送給特定的檢視控制器(帶有微信支付功能的檢視控制器)傳送通知,讓這個特定的檢視控制去請求伺服器訂單的住狀態。這個回撥函式必須寫在delegate.m中!!!


這裡寫圖片描述

4、特定檢視控制器的程式碼(帶有微信支付功能的檢視控制器)
4.1 提交預支付訂單獲得預訂單id(這個過程必須經過兩次簽名,分別是不帶引數簽名和攜帶引數簽名,當然,這些方法都已經在payRequsestHandler類封裝好了,你只需要傳引數呼叫方法就可以了)這個也是點選支付按鈕的動作方法
這裡寫圖片描述

4.2得到預支付訂單,那麼就可以調微信支付的客服端(4.2和4.1程式碼是連續的)
這裡寫圖片描述
附帶sign引數簽名的獨立封裝的兩個方法,沒用payRequsestHandler封裝的方法,自己寫的,因為用了出現問題(問題截圖如下),先程式碼截圖,後面再提供可直接複製黏貼的程式碼塊
問題截圖:(相信很多人遇到過,100%是sign簽名的問題)
這裡寫圖片描述


方法一:
這裡寫圖片描述
方法二:
這裡寫圖片描述

4.3 上面的程式碼就可以完全解決微信支付問題,剩下最後一個步驟,支付成功返回app呼叫delegate的-(void)onResp:(BaseResp*)resp方法,那麼這裡要傳送通知給特定的檢視控制器,讓他去請求後臺的訂單狀態。這裡要說明的是,你從那個介面調的微信支付後,返回還是在原處。只是回撥方法必須在delegate中,所以必須在回撥方法傳送成功的通知。那麼要在特定的檢視控制器的檢視即將出現的方法中,監聽到這個通知,然後請求後臺的訂單狀態。這裡需要注意的是,需要重寫dealloc方法,移除通知。
這裡寫圖片描述

三、支付寶和微信支付的回撥客戶端的代理方法的相容處理
這裡寫圖片描述

可供複製黏貼的程式碼(sign簽名)
-(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欄位
[contentString appendFormat:@”key=%@”, @”這裡填寫商戶金鑰”];
NSString *result = [self md5:contentString];
return result;

}//建立發起支付時的sige簽名

-(NSString ) md5:(NSString )str
{
const char *cStr = [str UTF8String];
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]
];
}//MD5 加密