ios端接入本地企业微信支付证书问题

4 篇文章 0 订阅

前言

1.接入微信支付前,需要申请应用的appid,这将用于获取用户在该appid下的openid
2.需要一个微信商户号,用于企业微信支付,应用的appid需要绑定到这个微信商户上。
3.完成这些操作后,再去微信商户后台下载API证书,API证书将用于接口访问时的验证,一般微信不建议我们将API证书放在客户端,这样安全性得不到保证,这里只是在客户端完成微信支付过程,商业用户需要将证书安装到自主服务器上。

证书问题

1.需要将下载下来的cer证书拖入xcode工程中
2.post请求微信接口时,微信接口需要我们进行证书的单向认证
3.认证完毕,即可收到对应响应
4.详细过程请按照微信官方文档步骤来

请求代码

NSMutableURLRequest *request=[[NSMutableURLRequest alloc]init];
    [request setURL:[NSURL URLWithString:url]];
    [request setHTTPMethod:@"POST"];
    
    NSString *contentType=[NSString stringWithFormat:@"text/xml"];
    [request addValue:contentType forHTTPHeaderField:@"Content-Type"];
    
    NSMutableData *postBody=[NSMutableData data];
    [postBody appendData:[[NSString stringWithFormat:
                           @"<xml><mch_appid>%@</mch_appid><mchid>%@</mchid><nonce_str>%@</nonce_str><partner_trade_no>%@</partner_trade_no><openid>%@</openid><check_name>%@</check_name><amount>%d</amount><desc>%@</desc><sign>%@</sign></xml>",self.mch_appid,self.mchid,self.nonce_str,self.partner_trade_no,self.openid,self.check_name,self.amount,self.desc,self.sign] dataUsingEncoding:NSUTF8StringEncoding]];
    
    [request setHTTPBody:postBody];
    
    NSString *bodyStr=[[NSString alloc]initWithData:postBody encoding:NSUTF8StringEncoding];
    NSLog(@"********提交表单信息 post body: %@",bodyStr);
    NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
    //config.TLSMaximumSupportedProtocol = kTLSProtocol1;
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    //NSURLSession *session=[NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        NSLog(@"返回的数据 data:%@",data);
       // NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
        
        if(error)
        {  NSLog(@"error:%@",error.description);
            return;
        }
        GDataXMLDocument *document=[[GDataXMLDocument alloc]initWithData:data options:kNilOptions error:nil];
        GDataXMLElement *root=document.rootElement;
        NSArray *arr1=root.children;
        Boolean returnCode=false;
        Boolean resultCode=false;
        NSString *err=nil;
        for (int i=0; i<[arr1 count]; i++) {
           GDataXMLElement *ele=[arr1 objectAtIndex:i];
           // ele
            NSLog(@"**************xml name:%@  value:%@ ",[ele name],[ele stringValue]);
            if([[ele name]isEqualToString:@"return_code"]&&[[ele stringValue] isEqualToString: @"SUCCESS"])
            {
                returnCode=true;
            }
            if([[ele name]isEqualToString:@"result_code"]&&[[ele stringValue]isEqualToString: @"SUCCESS"])
            {
                resultCode=true;
            }
            if([[ele name]isEqualToString:@"err_code"])
            {
                err=[ele stringValue];
            }
        }
        if(returnCode&&resultCode)
        {
            [[GDTAppDelegate shareInstance]paySuccess];
            NSDictionary * para = [NSDictionary dictionaryWithObjectsAndKeys:@"openid",[GDTAppDelegate shareInstance].openid,@"amount",[GDTAppDelegate shareInstance].amount, nil];
            [GDTAppDelegate payAction:@"withdrawal" attributes:para];
        }
        else
        {
            [[GDTAppDelegate shareInstance]payFail:err];
        }
    }];
    [task resume];

证书验证代码:

NSURLCredential *secureCredential;
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"证书认证");
    NSLog(@"didReceiveChallenge: %@", challenge.protectionSpace.authenticationMethod);
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {

        NSLog(@"challenged for client certificate");

          NSString *sslCertName = @"apiclient_cert";
          NSString *path2 = [[NSBundle mainBundle] pathForResource:sslCertName ofType:@"p12"];
          NSData *p12data = [NSData dataWithContentsOfFile:path2];

          CFDataRef inP12data = (__bridge CFDataRef) p12data;

          SecIdentityRef myIdentity;
          SecTrustRef myTrust;

          extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);

          SecCertificateRef myCertificate;
          SecIdentityCopyCertificate(myIdentity, &myCertificate);
          const void *certs[] = {myCertificate};
          CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);

          CFRelease(myCertificate);

          secureCredential = [NSURLCredential credentialWithIdentity:myIdentity
                                                        certificates:(__bridge NSArray *) certsArray
                                                         persistence:NSURLCredentialPersistencePermanent];

        CFRelease(certsArray);

        [[challenge sender] useCredential:secureCredential forAuthenticationChallenge:challenge];

        completionHandler(NSURLSessionAuthChallengeUseCredential, secureCredential);
      }

      else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

        NSLog(@"challenged for server trust");

        [challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]
             forAuthenticationChallenge: challenge];

        completionHandler(NSURLSessionAuthChallengeUseCredential,
                          [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
      } else {

        NSLog(@"other challenge");

        if ([challenge previousFailureCount] == 0) {

          [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];

        } else {

          [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
          completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,nil);
        }

      }
}
OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
{
  OSStatus securityError = errSecSuccess;

  CFStringRef password = CFSTR("1577168641");
  const void *keys[] = { kSecImportExportPassphrase };
  const void *values[] = { password };

  CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

  CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

  securityError = SecPKCS12Import(inP12data, options, &items);

  if (securityError == 0) {
    CFDictionaryRef myIdentityAndTrust = (CFDictionaryRef)CFArrayGetValueAtIndex(items, 0);
    const void *tempIdentity = NULL;
    tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
    *identity = (SecIdentityRef)tempIdentity;
    const void *tempTrust = NULL;
    tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
    *trust = (SecTrustRef)tempTrust;
  }

  if (options) {
    CFRelease(options);
  }

  return securityError;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值