-
與微信官方簽署在線協議
-
導入微信支付需要的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加密,格式嚴格按照微信官方方式加密。