1.下载微信支付SDK https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319164&token=&lang=zh_CN
并在发起支付之前初始化SDK[WXApi registerApp:@"项目申请得到的APPID"];
2.添加App 拉起白名单 和 https 网络访问配置
<key>LSApplicationQueriesSchemes</key>
<array>
<string>wechat</string>
<string>weixin</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
3.添加 URL Types / URL Schemes
4.添加微信SDK 依赖库
SystemConfiguration.framework
libz.tbd
libsqlite3.0.tbd
CoreTelephony.framework
QuartzCore.framework
5.如何获取预支付订单号
NSString* orderName = @"订单标题"; //订单标题,展示给用户
NSString* orderPrice = @"100";//以分为单位的整数
NSString* orderDevice = [[UIDevice currentDevice] identifierForVendor].UUIDString;//支付设备号
NSString* orderType = @"APP"; //支付类型,固定为APP
NSString* orderIP = [self fetchIPAddress]; //发器支付的机器ip
NSString *noncestr = [self generateRandomString]; //随机数串
//订单号 --- (随机生成可以直接用时间戳)
NSString *orderNO = [NSString stringWithFormat:@"%ld",(long)[[NSDate date] timeIntervalSince1970]];
/*预付单参数订单设置*/
NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
[packageParams setObject: @"项目申请得到的APPID" forKey:@"appid"]; //开放平台appid
[packageParams setObject: @"项目申请得到的商户号" 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: @"支付成功通知网址" forKey:@"notify_url"]; //支付结果异步通知
[packageParams setObject: orderNO forKey:@"out_trade_no"];//商户订单号
[packageParams setObject: orderIP forKey:@"spbill_create_ip"];//发器支付的机器ip
[packageParams setObject: orderPrice forKey:@"total_fee"]; //订单金额,单位为分
/** 下单获取到预支付ID(prepay_id) **/
NSString * prePayID = [self getPrePayId:packageParams];
//获取ip地址头文件
#include <ifaddrs.h>
#include <arpa/inet.h>
#pragma mark - 获取设备ip地址
- (NSString *)fetchIPAddress {
NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
success = getifaddrs(&interfaces);
if (success == 0) {
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
return address;
}
#pragma mark - 产生随机字符串
- (NSString *)generateRandomString {
static int kNumber = 15;
NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
NSMutableString *resultStr = [[NSMutableString alloc] init];
srand((unsigned)time(0));
for (int i = 0; i < kNumber; i++) {
unsigned index = rand() % [sourceStr length];
NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, 1)];
[resultStr appendString:oneStr];
}
return resultStr;
}
#pragma mark --- 获取prePayid
-(NSString *)getPrePayId:(NSMutableDictionary *)pakeParams{
NSString *prepayid = nil;
//获取提交支付
NSString *send = [self genPackage:pakeParams];
//发送请求post xml数据
NSData *res = [self httpSend:@"https://api.mch.weixin.qq.com/pay/unifiedorder" method:@"POST" data:send];
XMLHelper *xml = [[XMLHelper alloc] init];
//开始解析
[xml startParse:res];
NSMutableDictionary *resParams = [xml getDict];
NSLog(@"%@",resParams);
//判断返回
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 prepayid;
}
#pragma mark --- 创建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=%@", @"密钥api_key"];
NSLog(@"%@",contentString);
//得到MD5 sign签名
NSString *md5Sign =[self md5:contentString];
return md5Sign;
}
生成过程中需要用到xml 解析文件
#import <Foundation/Foundation.h>
/*
XML 解析库api说明:
//============================================================================
//输入参数为xml格式串,初始化解析器
-(void)startParse:(NSData *)data;
//获取解析后的字典
-(NSMutableDictionary*) getDict;
//============================================================================
*/
@interface XMLHelper : NSObject<NSXMLParserDelegate> {
//解析器
NSXMLParser *xmlParser;
//解析元素
NSMutableArray *xmlElements;
//解析结果
NSMutableDictionary *dictionary;
//临时串变量
NSMutableString *contentString;
}
//输入参数为xml格式串,初始化解析器
-(void)startParse:(NSData *)data;
//获取解析后的字典
-(NSMutableDictionary*) getDict;
@end
#import <Foundation/Foundation.h>
#import "ApiXml.h"
/*
XML 解析库
*/
@implementation XMLHelper
-(void) startParse:(NSData *)data{
dictionary =[NSMutableDictionary dictionary];
contentString=[NSMutableString string];
//Demo XML解析实例
xmlElements = [[NSMutableArray alloc] init];
xmlParser = [[NSXMLParser alloc] initWithData:data];
[xmlParser setDelegate:self];
[xmlParser parse];
}
-(NSMutableDictionary*) getDict{
return dictionary;
}
//解析文档开始
- (void)parserDidStartDocument:(NSXMLParser *)parser{
//NSLog(@"解析文档开始");
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
//NSLog(@"遇到启始标签:%@",elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
//NSLog(@"遇到内容:%@",string);
[contentString setString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
//NSLog(@"遇到结束标签:%@",elementName);
if( ![contentString isEqualToString:@"\n"] && ![elementName isEqualToString:@"root"]){
[dictionary setObject: [contentString copy] forKey:elementName];
//NSLog(@"%@=%@",elementName, contentString);
}
}
//解析文档结束
- (void)parserDidEndDocument:(NSXMLParser *)parser{
//NSLog(@"文档解析结束");
xmlElements = nil;
xmlParser = nil;
}
@end
6 . 获取到预支付订单之后,获取签名 发起支付
/** 获取到prepayid后进行第二次签名 **/
NSString *package = @"Sign=WXPay";
NSString *time_stamp = [NSString stringWithFormat:@"%ld",(long)[[NSDate date] timeIntervalSince1970]];//时间戳
NSString *nonce_str = [self md5:time_stamp];//随机字符串(直接用时间戳来生成就可以了)
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];//用于二次签名的参数
[signParams setObject:@"项目申请得到的APPID" forKey:@"appid"];
[signParams setObject:@"项目申请得到的商户号" forKey:@"partnerid"];
[signParams setObject: nonce_str forKey:@"noncestr"];
[signParams setObject: package forKey:@"package"];
[signParams setObject: time_stamp forKey:@"timestamp"];
[signParams setObject: prePayID forKey:@"prepayid"];
//调起微信支付
PayReq* req = [[PayReq alloc] init];
req.partnerId = @"项目申请得到的商户号";
req.prepayId = prePayID;
req.nonceStr = nonce_str;
req.timeStamp = time_stamp.intValue;
req.package = package;
req.sign = [self createMd5Sign:signParams];//二次签名
[WXApi sendReq:req];
7 . 监听支付结果回调 实现 微信代理<WXApiDelegate>
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
if ([url.host isEqualToString:@"pay"]) {
return [WXApi handleOpenURL:url delegate:self];;
}
return YES;
}
-(BOOL)application:(UIApplication *)app handleOpenURL:(nonnull NSURL *)url{
if ([url.host isEqualToString:@"pay"]) {
return [WXApi handleOpenURL:url delegate:self];;
}
return YES;
}
-(void)onResp:(BaseResp *)resp{
NSString *strTitle;
if ([resp isKindOfClass:[SendMessageToWXResp class]]) {
strTitle = [NSString stringWithFormat:@"发送媒体消息结果"];
}
if ([resp isKindOfClass:[PayResp class]]) {
strTitle = [NSString stringWithFormat:@"支付结果"];
switch (resp.errCode) {
case WXSuccess:
{
NSLog(@"支付结果: 成功!");
}
break;
case WXErrCodeCommon:
{ //签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等
NSLog(@"支付结果: 失败!");
}
break;
case WXErrCodeUserCancel:
{ //用户点击取消并返回
NSLog(@"用户点击取消并返回");
}
break;
case WXErrCodeSentFail:
{ //发送失败
NSLog(@"发送失败");
}
break;
case WXErrCodeUnsupport:
{ //微信不支持
NSLog(@"微信不支持");
}
break;
case WXErrCodeAuthDeny:
{ //授权失败
NSLog(@"授权失败");
}
break;
default:
break;
}
}
}