iOS接入微信支付
微信支付SDK比支付宝的SDK好了不知道多少倍,坑也少了好多,简直是支付类SDK中的良心之作!!
iOS接入支付宝SDK传送门
准备
首先要去微信申请一个账号,分别有商户API密钥
和商户号
https://open.weixin.qq.com/
下载SDK
目前微信SDK已经升级到了(1.6.2)。但是我现在用的是上一个版本SDK,这里有下载
为什么不用最新的呢?因为最新的SDK里面要求签名加密等操作在服务器上完成然后返回给手机端,然而……额,我这个项目的后台比较菜,不知道签名是怎么回事。而我比他更菜,我懒得自己写md5加密,所以就用了老版本的SDK。老版本SDK自带了各种各样加密方法,网上教程也比较多,所以很容易集成。
当然,微信这么做也是有原因的,你把私钥放到了每一台手机上用来做签名……这样跟泄露了私钥有什么区别~
运行DEMO
SDKSample
下的demo跑一遍,没有什么问题,没有支付宝那么坑~~
lib文件夹下payRequsestHandler.h
文件中填上APP_ID
、APP_SECRET
、MCH_ID
、PARTNER_ID
的值,然后运行demo,试一下能否完成支付,如果可以就可以进行下一步接入工作了。
接入
将SDKExport下的libWeChatSDK.a
、WXApi.h
、WXApiObject.h
三个文件拖入工程中,再把lib文件夹拖入工程中。。可能会有报错,ApiXml.m中报错那两行注释掉就好
支付代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #import <Foundation/Foundation.h> #import "WXApiObject.h" #import "WXApi.h"
#define APP_ID @"XXX" #define APP_SECRET @"XXX"
#define MCH_ID @"XXX"
#define PARTNER_ID @"XXX"
#define NOTIFY_URL @"http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php" #define SP_URL @"http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php"
@interface WechatPayManager : NSObject { }
@property (nonatomic,strong) NSString* payUrl;
@property (nonatomic,strong) NSMutableString *debugInfo; @property (nonatomic,assign) NSInteger lastErrCode;
@property (nonatomic,strong) NSString *appId,*mchId,*spKey;
-(id)initWithAppID:(NSString*)appID mchID:(NSString*)mchID spKey:(NSString*)key;
-(NSString *) getDebugInfo;
- (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name price:(NSString*)price device:(NSString*)device;
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
#import "WechatPayManager.h" #import "WXUtil.h" #import "ApiXml.h"
@implementation WechatPayManager
-(id)initWithAppID:(NSString*)appID mchID:(NSString*)mchID spKey:(NSString*)key { self = [super init]; if(self) { self.payUrl = @"https://api.mch.weixin.qq.com/pay/unifiedorder"; if (self.debugInfo == nil){ self.debugInfo = [NSMutableString string]; } [self.debugInfo setString:@""]; self.appId = appID; self.mchId = mchID; self.spKey = key; } return self; }
-(NSString*) getDebugInfo { NSString *res = [NSString stringWithString:self.debugInfo]; [self.debugInfo setString:@""]; return res; }
-(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]]; } } [contentString appendFormat:@"key=%@", self.spKey]; NSString *md5Sign =[WXUtil md5:contentString]; [self.debugInfo appendFormat:@"MD5签名字符串:\n%@\n\n",contentString]; return md5Sign; }
-(NSString *)genPackage:(NSMutableDictionary*)packageParams { NSString *sign; NSMutableString *reqPars=[NSMutableString string]; sign = [self createMd5Sign:packageParams]; NSArray *keys = [packageParams allKeys]; [reqPars appendString:@"<xml>\n"]; for (NSString *categoryId in keys) { [reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId]; } [reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign]; return [NSString stringWithString:reqPars]; }
-(NSString *)sendPrepay:(NSMutableDictionary *)prePayParams { NSString *prepayid = nil; NSString *send = [self genPackage:prePayParams]; [self.debugInfo appendFormat:@"API链接:%@\n", self.payUrl]; [self.debugInfo appendFormat:@"发送的xml:%@\n", send]; NSData *res = [WXUtil httpSend:self.payUrl method:@"POST" data:send]; [self.debugInfo appendFormat:@"服务器返回:\n%@\n\n",[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]]; XMLHelper *xml = [[XMLHelper alloc] init]; [xml startParse:res]; NSMutableDictionary *resParams = [xml getDict]; 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_code = 0; [self.debugInfo appendFormat:@"获取预支付交易标示成功!\n"]; } }else{ self.lastErrCode = 1; [self.debugInfo appendFormat:@"gen_sign=%@\n _sign=%@\n",sign,send_sign]; [self.debugInfo appendFormat:@"服务器返回签名验证错误!!!\n"]; } }else{ self.lastErrCode = 2; [self.debugInfo appendFormat:@"接口返回错误!!!\n"]; } return prepayid; }
- (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name price:(NSString*)price device:(NSString*)device { NSString* orderName = name; NSString* orderPrice = price; NSString* orderDevice = device; NSString* orderType = @"APP"; NSString* orderIP = @"196.168.1.1"; srand( (unsigned)time(0) ); NSString *noncestr = [NSString stringWithFormat:@"%d", rand()]; NSString *orderNO = [NSString stringWithFormat:@"%ld",time(0)]; NSMutableDictionary *packageParams = [NSMutableDictionary dictionary]; [packageParams setObject: self.appId forKey:@"appid"]; [packageParams setObject: self.mchId forKey:@"mch_id"]; [packageParams setObject: orderDevice forKey:@"device_info"]; [packageParams setObject: noncestr forKey:@"nonce_str"]; [packageParams setObject: orderType forKey:@"trade_type"]; [packageParams setObject: orderName forKey:@"body"]; [packageParams setObject: NOTIFY_URL forKey:@"notify_url"]; [packageParams setObject: orderNO forKey:@"out_trade_no"]; [packageParams setObject: orderIP forKey:@"spbill_create_ip"]; [packageParams setObject: orderPrice forKey:@"total_fee"]; NSString *prePayid; prePayid = [self sendPrepay:packageParams]; if(prePayid == nil) { [self.debugInfo appendFormat:@"获取prepayid失败!\n"]; return nil; } NSString *package, *time_stamp, *nonce_str; time_t now; time(&now); time_stamp = [NSString stringWithFormat:@"%ld", now]; nonce_str = [WXUtil md5:time_stamp]; package = @"Sign=WXPay"; NSMutableDictionary *signParams = [NSMutableDictionary dictionary]; [signParams setObject: self.appId forKey:@"appid"]; [signParams setObject: self.mchId forKey:@"partnerid"]; [signParams setObject: nonce_str forKey:@"noncestr"]; [signParams setObject: package forKey:@"package"]; [signParams setObject: time_stamp forKey:@"timestamp"]; [signParams setObject: prePayid forKey:@"prepayid"]; NSString *sign = [self createMd5Sign:signParams]; [signParams setObject: sign forKey:@"sign"]; [self.debugInfo appendFormat:@"第二步签名成功,sign=%@\n",sign]; return signParams; } @end
|
支付函数
调用这个函数即可完成支付~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| - (void)wxPayWithOrderName:(NSString*)name price:(NSString*)price { WechatPayManager* wxpayManager = [[WechatPayManager alloc]initWithAppID:APP_ID mchID:MCH_ID spKey:PARTNER_ID]; NSString* device = @"aaaaaa"; NSMutableDictionary *dict = [wxpayManager getPrepayWithOrderName:name price:price device:device]; if(dict == nil){ NSString *debug = [wxpayManager getDebugInfo]; NSLog(@"%@",debug); return; } NSMutableString *stamp = [dict objectForKey:@"timestamp"]; PayReq* req = [[PayReq alloc] init]; req.openID = [dict objectForKey:@"appid"]; 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"]; BOOL flag = [WXApi sendReq:req]; if (!flag) { NSLog(@"ERROR!"); } }
|
可能遇到的问题
“OBJC_CLASS$_CTTelephonyNetworkInfo” 报错
“Undefined symbols for architecture armv7:”报错
在General
->Linked Frameworks and Libraries
中加入以下Libraries:
写的比较仓促,如果发现什么问题请留言,我一定会回复的~