目錄: (沒閑工夫看扯淡的第一部分, 可直接看第二和第三部分. 沒有任何影響)
一, 寫文檔的初衷, 和遇到的一些問題 (包含扯淡)
二, 集成步驟 (主要是官方文檔部分), 偷懶了很多頁面, 你們自己根據(jù)流程點擊
三, 實現(xiàn)代碼 (不包含第二部分的配置)
四, 注意點 / 可能會遇到的問題
五, 參考文章
一 , 扯淡
先說一下為啥要寫這個demo教程, 不是有官方文檔嗎?
因為官方文檔真心不咋地!!!!! 更新不及時, 好多地方也不說清楚
官方demo也運行不了. 有問題了想找個客服問, 只能給技術(shù)人員發(fā)郵件, 發(fā)郵件!!!
微信支付技術(shù)支持的郵箱: wepayTS@tencent.com
我?guī)е鴨栴}一堆問題問, 人家只會一兩句: 你的key設(shè)置的有問題吧.
我真想呵呵. 問了兩次, 還是沒告訴我咋弄, 就說我key有問題.
最后我解決問題了, 也不是key的問題. 等著客服郵件給你解決, 真是浪費生命, 浪費時間.
二, 集成步驟
前提, 申請成開發(fā)者, 和商戶.( 商戶, 商戶. ). 這個沒啥坑. 按照文檔一步步弄就行.
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317780&token=&lang=zh_CN
正式開始集成如果項目之前沒有集成過微信SDK, 那么跟著下面的文檔集成一下.
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417694084&token=&lang=zh_CN如果及集成過, 檢查一下這幾個框架是否已經(jīng)加入
SystemConfiguration.framework, libz.dylib, libsqlite3.0.dylib, libc++.dylib, Security.framework, CoreTelephony.framework, CFNetwork.framework接著官方文檔集成 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
(需要看注意點 2)
三, 代碼, 這只是.m文件, 商戶信息啦, appid啦, key啦, 自己替換,
#import "WXApi.h"
#import "WXApiRequestHandler.h"
#import "WXApiManager.h"
#import "AFNetworking.h"
#import <CommonCrypto/CommonDigest.h>
@interface WXApiRequestHandler()
@property (nonatomic, strong) AFHTTPSessionManager *mgr;
@end
@implementation WXApiRequestHandler
- (AFHTTPSessionManager *)mgr {
if (_mgr == nil) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_mgr = [[AFHTTPSessionManager alloc]initWithBaseURL:[NSURL URLWithString:@"http://xxxxxxxxx"] sessionConfiguration:config];
_mgr.requestSerializer.timeoutInterval = 10;
_mgr.responseSerializer = [AFJSONResponseSerializer serializer];
_mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/x-json", @"text/plain",@"text/html", nil];
// _mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
}
return _mgr;
}
#pragma mark - 支付
- (NSString *)jumpToBizPay {
NSMutableDictionary *dictc = [NSMutableDictionary dictionary];
[self.mgr POST:@"xxxxxxr" parameters:dictc success:^(NSURLSessionDataTask *task, NSDictionary *dict) {
NSLog(@"dict:%@", dict);
// 這倆字典, 你們別搞混了 dict, 是服務(wù)器返回的, dict2是處理過, 加了sign的字典
// 就干了一件事, 生成sign
NSMutableDictionary *dict2 = [self getSign:dict];
// 我服務(wù)器傳過來的時間戳, 誰生成都無所謂, 注意一定是只精確到秒, 是個10位的數(shù)字串
NSMutableString *stamp = [dict2 objectForKey:@"timestamp"];
//調(diào)起微信支付
PayReq* req = [[PayReq alloc] init];
req.nonceStr = [dict2 objectForKey:@"noncestr"];// 隨機字符串
req.package = @"Sign=WXPay"; // 微信說暫時寫死
req.partnerId = [dict2 objectForKey:@"partnerid"];// 就是mch_id, 商戶id
req.prepayId = [dict2 objectForKey:@"prepayid"];// 微信返回的
req.timeStamp = stamp.intValue;
req.sign = [dict2 objectForKey:@"sign"];
[WXApi sendReq:req];
//日志輸出
NSLog(@"appid=%@\npartid=%@\nprepayid=%@\nnoncestr=%@\ntimestamp=%ld\npackage=%@\nsign=%@",[dict objectForKey:@"appid"],req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.package,req.sign );
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"失敗了");
}];
return @"";
}
// 這段是為了組成sign簽名所需的key, 微信的文檔表述的, 讓新手看不懂, 會傻一會兒,
// 具體可以看 文章的"注意點5"
- (NSMutableDictionary *)getSign:(NSDictionary *)dict{
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: @"wxd1111111111111" forKey:@"appid"];
[signParams setObject: @"1111111111" forKey:@"partnerid"];
[signParams setObject: dict[@"nonce_str"] forKey:@"noncestr"];
[signParams setObject: @"Sign=WXPay" forKey:@"package"];
[signParams setObject: dict[@"timestamp"] forKey:@"timestamp"];
[signParams setObject: dict[@"prepay_id"] forKey:@"prepayid"];
//生成簽名
NSString *sign = [self createMd5Sign:signParams];
//添加簽名
[signParams setObject: sign forKey:@"sign"];
return signParams;
}
#pragma mark - 獲取簽名
-(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 (![categoryId isEqualToString:@"sign"] && ![categoryId isEqualToString:@"key"])
{
[contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
}
}
//添加key字段, 設(shè)置路徑 微信商戶平臺(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->密鑰設(shè)置
[contentString appendFormat:@"key=%@", @"xxxxxxxxxxxxxxxxxxxxxx"];
//得到MD5 sign簽名, 一定要轉(zhuǎn)大寫!!!!!! 一定要轉(zhuǎn)大寫!!!!!!
NSString *md5Sign =[[self md5:contentString] uppercaseString];
NSLog(@"md5:%@", md5Sign);
return md5Sign;
}
// 這段微信沒寫
- (NSString *) md5:(NSString *) input {
const char *cStr = [input UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
@end
四, 注意點:
如果沒有加入CFNetwork.framework, 項目隨便編譯不報錯, 但是會運行會崩潰在
[WXApi registerApp:@"wxd1111111111111" ]; 這句.微信文檔 注冊APPID 那段代碼已經(jīng)不對了, 要寫成上面"注意點1" 那樣.
[WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"demo 2.0"]; // 錯的
包括微信支付的官方demo, 這句也是錯的.微信支付的官方demo, 里面的地址也不能用了, demo里面的微信SDK都不是最新的, 呵呵了
- key的設(shè)置路徑: 微信商戶平臺(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->密鑰設(shè)置
不超過32位的字符串, , 需要自己生成, 并且設(shè)置到該路徑 - sign簽名key
貼圖所在頁 : https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12
五:
-
http://www.2cto.com/kf/201505/403114.html
文章中包含ios生成服務(wù)器統(tǒng)一下單代碼(臨時) -
https://pay.weixin.qq.com/wiki/tools/signverify/
生成sign時, 校驗頁面