最近項(xiàng)目要求添加一個(gè)微信支付的功能,要求是不需要服務(wù)端的配合,獨(dú)立在客戶端完成。
開始看官方demo的時(shí)候發(fā)現(xiàn)客戶端只有短短的幾行代碼便成功了,更關(guān)鍵的是文檔中那些參數(shù)都解釋的含含糊糊僵朗。結(jié)果花了我好幾天的時(shí)間才最終弄好。現(xiàn)在細(xì)數(shù)其辛酸歷程屑彻。
//調(diào)起微信支付
PayReq* req = [[[PayReq alloc] init]autorelease];
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];
這就官方文檔中最核心的調(diào)出支付的代碼验庙,我們所需要做的一切都是獲取這六個(gè)參數(shù)。
首先來一個(gè)個(gè)的解釋這些參數(shù)
partnerId :這個(gè)就是在你申請(qǐng)通過微信商戶資料后發(fā)到你郵件的中的一個(gè)商戶號(hào)
prepayid : 這個(gè)是需要向微信服務(wù)器提交申請(qǐng)后返回的一個(gè)支付交易會(huì)話ID社牲,詳細(xì)的下面會(huì)提到粪薛。
nonceStr : 這個(gè)是你自己生成的一個(gè)隨機(jī)數(shù)。
timeStamp : 這個(gè)是你生成的一個(gè)時(shí)間戳搏恤。10位Nナ佟E冉弧!不是13位的那個(gè)藤巢!
package : 這個(gè)目前是一個(gè)定死的值 Sign=WXPay搞莺。
sign : 這個(gè)是自己根據(jù)參數(shù)生成的一個(gè)簽名!最坑的就是它了掂咒!
現(xiàn)在來一個(gè)的說如何得到這些參數(shù)值
1才沧、prepayid
這個(gè)一般來說是在服務(wù)端申請(qǐng)好的,客戶端直接獲取就行绍刮。但是萬惡的公司居然要求在客戶端弄温圆。
先看官方文檔:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1
乍一看無非是向微信的一個(gè)接口提交數(shù)據(jù),然后就會(huì)返回了录淡。
但是這茫茫多的參數(shù)中其實(shí)隱藏著無數(shù)的細(xì)節(jié)捌木,稍有不慎就返回一個(gè)大大失敗油坝,然后你就愁的一頭包了嫉戚。
這些參數(shù)里面有一個(gè)是需要生成一個(gè)簽名,這個(gè)簽名也是有官方文檔專門介紹的:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=4_3
這個(gè)文檔中有舉一個(gè)例子澈圈,大概就是說把一些參數(shù)按照ASCII的順序先進(jìn)行排序然后再拼接上一個(gè)key(這個(gè)key是你在申請(qǐng)成功商戶資料后按照郵件中提示進(jìn)行設(shè)置的彬檀,32位)。拼接好后進(jìn)行MD5轉(zhuǎn)碼瞬女∏系郏看起來很輕松明了吧,但是這里面最大的一個(gè)坑就是他這個(gè)舉例了诽偷!這個(gè)例子中只有寥寥幾個(gè)參數(shù)坤学,如果你就按照他這個(gè)也只是用這幾個(gè)參數(shù)生成簽名,那就怎么也獲取不到這個(gè)prepayid了报慕!實(shí)際上深浮,這個(gè)簽名里面所包含的參數(shù)是需要包含你所要提交獲取prepayid的所有參數(shù)的!
也就是前面給的官方文檔中所有表示必須要的參數(shù)眠冈,當(dāng)然除了你現(xiàn)在要生成的這個(gè)sign飞苇。
順便提一句,這里的提交數(shù)據(jù)是以XML的形式蜗顽,解析數(shù)據(jù)也是XML的格式布卡。
這樣就可以順利的獲得prepayid了。
2雇盖、nonceStr
這個(gè)很簡(jiǎn)單
NSString * nonce_str = [self md5:[NSString stringWithFormat:@"%d", arc4random() % 10000]];
nonce_str = [nonce_str uppercaseString];
- (NSString *) md5: (NSString *) inPutText
{
const char *cStr = [inPutText UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, strlen(cStr), result);
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]
] lowercaseString];
}
其實(shí)就是一個(gè)隨機(jī)數(shù)忿等,怎么生成隨你。有個(gè)不得不提的地方崔挖,這里的noncestr就是你在第一次生成簽名時(shí)的那個(gè)隨機(jī)數(shù)这弧,不用再次生成了娃闲!
3、timeStamp
NSString * timeString = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
這個(gè)地方需要提示一下
@property (nonatomic, assign) UInt32 timeStamp;
他的類型是這個(gè)樣的匾浪,而你生成的是一個(gè)字符串類型的皇帮,最后提交的時(shí)候需要進(jìn)行轉(zhuǎn)化的!
4蛋辈、sign
這里的簽名不同于你第一次申請(qǐng)prepayid的簽名属拾,這里的生成簽名的參數(shù)是appid,prepayid,partnerid,timestamp,noncestr,package,這幾個(gè)排序后再拼接key,最后生成一個(gè)sign冷溶。
這樣一看渐白,其實(shí)還是很簡(jiǎn)答的嘛!果然還是我太蠢了.......好了逞频,如果還是不行纯衍,請(qǐng)?jiān)倏匆槐椋屑?xì)的看一遍苗胀。實(shí)在不行襟诸,請(qǐng)聯(lián)系我!