微信APP支付
1.到微信开放平台注册并开通开发者资质 <a href="https://open.weixin.qq.com">微信开放平台</a>
2.提交APP应用进行审核,只有审核通过的应用才能正式发布使用。
3.审核通过后APP应用获取支付能力 <a href ="http://kf.qq.com/faq/140225MveaUz150107UVFNjy.html">微信支付商户申请接入</a>
4.<a href ="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317780&token=&lang=zh_CN">申请流程指引</a>
调用微信支付Xcode配置
<a href="https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1">官方文档及demol</a>
注册APPID
商户APP工程中引入微信lib库和头文件,调用API前,需要先向微信注册您的APPID,代码如下:
[WXApi registerApp:@"自己的APPID" withDescription:@"WechatPay"];
1、iOS 9系统策略更新,限制了http协议的访问,此外应用需要在Info.plist中将要使用的URL Schemes列为白名单,才可正常检查其他应用是否安装。
Info.plist **右击->Open As ->Source Code **里添加如下代码
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
需要导入的静态库文件
SystemConfiguration.framework
libz.tbd
libsqlite3.0.tbd
libc++.tbd
CoreTelephony.framework
首先先调用统一下单接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再在APP里面调起支付。(为了安全,一般调用该接口的需要的参数由后台生成)
统一下单接口 https://api.mch.weixin.qq.com/pay/unifiedorder
后台生成的xml JSON字符串如下格式(也可在前端自己拼接,拼接方式与调起微信支付时生成的参数签名方法一致)
<xml>
<appid>自己的APPID</appid>
<body>商品的标题</body>
<mch_id>商户号</mch_id>
<nonce_str>随机字符串</nonce_str>
<notify_url>后台回调地址异步通知给后台支付结果</notify_url>
<out_trade_no>商户订单号</out_trade_no>
<spbill_create_ip>168.0.0.1</spbill_create_ip>//用户端实际ip
<total_fee>订单总金额,单位为分</total_fee>
<trade_type>APP</trade_type>//固定值
//微信商户平台里面自定义的密钥key和以上参数拼接之后进行MD5获得的签名
<sign>签名</sign>
</xml>
NSString *paramesXmlString 上面的字符串
//创建URL
NSURL *unifiedOrderURL = [NSURL URLWithString:@"https://api.mch.weixin.qq.com/pay/unifiedorder"];
//请求
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:unifiedOrderURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:5.0];
[request addValue:@"text/xml" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
//paramesXmlString 上面由后台生成的xml JSON字符串;
NSData *httData = [paramesXmlString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:httData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//返回的是xml 进行xml解析
xmlParser = [[XMLParseManager alloc]initWthXmlData:data andResultBlock:^(NSMutableDictionary *resultDictionary) {
_prepayid = [resultDictionary objectForKey:@"prepay_id"];
_noncestr =[resultDictionary objectForKey:@"nonce_str"];
_mchid =[resultDictionary objectForKey:@"mch_id"];
_appid =[resultDictionary objectForKey:@"appid"];
[self payWX];
}];
[xmlParser startParse];
}];
[task resume];
//微信支付服务后台生成预支付交易单信息
//resultDictionary
{
appid = APPID;
"mch_id" = 商户号;
"nonce_str" = Ob5KviQMBrJJ9GMK;//随机字符串
"prepay_id" = wx2016080220898a8b0ag4387943;//支付订单号
"result_code" = SUCCESS;
"return_code" = SUCCESS;
"return_msg" = OK;
sign = BUHKU849FJLD;
"trade_type" = APP;
}
得到了微信支付服务后台生成预支付交易单信息,拼接参数并生成签名,最后调起微信支付
获取当前时间
time_t now;
time(&now);
NSString *timestamp = [NSString stringWithFormat:@"%ld",now];
//得到的微信支付后台生成预订单信息
NSDictionary *dict = @{@"appid":_appid,//APPID
@"noncestr":_noncestr,//随机字符串
@"package":@"Sign=WXPay",//固定值
@"partnerid":_mchid,//商户ID
@"prepaid":_prepayid,//支付订单号
@"timestamp":timestamp};
NSMutableString *contentString = [NSMutableString string];
NSArray *keys = [dict allKeys];
//按首字母排序
NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull 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[categoryId]];
}
}
[contentString appendFormat:@"key=%@",@"微信商户平台里面自定义的密钥key"];
//加密生成字符串 MD5
NSString *md5Sign = [WXUtil md5:contentString];
//调起微信支付
PayReq* req = [[PayReq alloc] init];
req.partnerId = [dict objectForKey:@"partnerid"];
req.prepayId = [dict objectForKey:@"prepayid"];
req.nonceStr = [dict objectForKey:@"noncestr"];
req.timeStamp = timestamp.intValue;
req.package = [dict objectForKey:@"package"];
req.sign = md5Sign;
//最关键的就是这里发送请求到微信,
[WXApi sendReq:req];
+(NSString *)md5:(NSString *)str{
const char *cStr = [str UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr,(unsigned int)strlen(cStr),digest);
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;
}
// XMLParseManager
//开始xml解析
- (void)startParse{
_xmlParser = [[NSXMLParser alloc]initWithData:_xmlData];
[_xmlParser setDelegate:self];
[_xmlParser parse];
}
//开始解析的时候,初始化要解析的内容
-(void)parserDidStartDocument:(NSXMLParser *)parser{
_resultDictionary = [NSMutableDictionary dictionary];
_contentSting = [NSMutableString string];
}
//记录节点内容
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
[_contentSting setString:string];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if (![_contentSting isEqualToString:@"\\n"]&& ![elementName isEqualToString:@"root"] ) {
[_resultDictionary setObject:[_contentSting copy] forKey:elementName];
}
}
//解析结果之后,传入一个字典
-(void)parserDidEndDocument:(NSXMLParser *)parser{
_resultBlock(_resultDictionary);
}