-
与微信官方签署在线协议
-
导入微信支付需要的SDK相关文件
-
配置App跳转的白名单
-
添加URL Schemes
-
配置代码
- 在AppDelegate.m中向微信注册第三方应用
//向微信终端程序注册第三方应用
[WXApi registerApp:wexinAppId]; - 确保支付结果回调方法能够接受到,在AppDelegate.m中添加一下代码
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
if([url.host isEqualToString:@"pay"]){
return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
}else{
return YES;
}
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(nonnull NSURL *)url
{
if([url.host isEqualToString:@"pay"]){
return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
}else{
return YES;
}
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
if([url.host isEqualToString:@"pay"]){
return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
}else{
return YES;
}
}
设置支付信息,调用微信支付
NSMutableDictionary dict = [result[@"data"] objectAtIndex:0];
//调起微信支付
PayReq req = [[PayReq alloc] init];
//由用户微信号和AppID组成的唯一标识
req.openID = [dict objectForKey:@"appid"];
//商家向财付通申请的商家id
req.partnerId = [dict objectForKey:@"mch_id"];
//预支付订单
req.prepayId = [dict objectForKey:@"prepay_id"];
//随机串,防重发
req.nonceStr = [dict objectForKey:@"nonce_str"];
//时间戳,防重发
req.timeStamp = [[dict objectForKey:@"timeStamp"] intValue];
//商家根据财付通文档填写的数据和签名
req.package = @"Sign=WXPay";
//商家根据微信开放平台文档对数据做的签名
req.sign = [self getWeiXinPaySign:req];
[WXApi sendReq:req];-
处理支付结果
为了对支付结果可以进行不同的操作处理,可以创建一个单例对象来管理。
#import <Foundation/Foundation.h>
#import "WXApi.h"
@protocol WXApiManagerDelegate <NSObject>
@optional
- (void)managerDidRecvPayForSuccessResponse:(PayResp *)response;- (void)managerDidRecvPayForFailResponse:(PayResp *)response; @end @interface WXApiManager : NSObject<WXApiDelegate> @property (nonatomic, assign) id<WXApiManagerDelegate> delegate; + (instancetype)sharedManager; @end #import "WXApiManager.h" @implementation WXApiManager #pragma mark - LifeCycle +(instancetype)sharedManager { static dispatch_once_t onceToken; static WXApiManager *instance; dispatch_once(&onceToken, ^{ instance = [[WXApiManager alloc] init]; }); return instance; } - (void)dealloc { self.delegate = nil; [super dealloc]; } #pragma mark - WXApiDelegate - (void)onResp:(BaseResp *)resp { if([resp isKindOfClass:[PayResp class]]){ switch (resp.errCode) { case WXSuccess: { if (_delegate && [_delegate respondsToSelector:@selector(managerDidRecvPayForSuccessResponse:)]) { PayResp *payResp = (PayResp *)resp; [_delegate managerDidRecvPayForSuccessResponse:payResp]; } } break; default: if (_delegate && [_delegate respondsToSelector:@selector(managerDidRecvPayForFailResponse:)]) { PayResp *payResp = (PayResp *)resp; [_delegate managerDidRecvPayForFailResponse:payResp]; } break; } } } @end
-
签名sign生成方法
//获取微信签名
-(NSString)getWeiXinPaySign:(PayReq)req
{
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: req.openID forKey:@"appid"];
[signParams setObject: req.nonceStr forKey:@"noncestr"];
[signParams setObject: req.package forKey:@"package"];
[signParams setObject: req.partnerId forKey:@"partnerid"];
[signParams setObject: [NSString stringWithFormat:@"%u",(unsigned int)req.timeStamp] forKey:@"timestamp"];
[signParams setObject: req.prepayId forKey:@"prepayid"];
//生成签名
NSString *sign = [self createMd5Sign:signParams];
return sign;
}//创建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=%@", @"xxxxxxxxxxx"]; //得到MD5 sign签名 NSString *md5Sign =[WXUtil md5:contentString]; return md5Sign; } //md5 encode +(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]; //这里的x是小写则产生的md5也是小写,是大写则产生的md5是大写 for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) [output appendFormat:@"%02X", digest[i]]; return output; }
- 在AppDelegate.m中向微信注册第三方应用
-
注意事项:
- 签名Sign一定得进行MD5加密,格式严格按照微信官方方式加密。
prepayId(预支付订单)失效、过期。
如果出现上述问题(一般是参数错误),就会造成调起微信支付,只出现一个确定按钮
- 支付结果无法获取回调?
确保第四步的b步骤是否实现 - 如果APP里面使用了友盟或者ShareSDK做分享,那就不用再导入SDK了,否则会出现一些诡异的问题,
例如无法调起手机微信客户端、无法调起微信客户端web页面,调起了但是一闪而过。这都基本上都是因为分享的SDK里面已经包括了微信的SDK。所以如果出现诡异的错误了看看是不是两个冲突了。 - 如果你用了友盟社会化分享来做微信登录的话,那么你要先用友盟注册微信,后调用微信SDK注册
[UMSocialWechatHandlersetWXAppId:SHappSecret:SH url:SHAREURL];
[WXApiregisterApp:SHARE_WX withDescription:@"demo"]; - 微信无法调起
未安装微信、未将微信加入白名单
- 签名Sign一定得进行MD5加密,格式严格按照微信官方方式加密。