iOS实现微信支付流程详解

2020-01-21 00:50:28王振洲

这样,统一下单的参数已经准备好了,下面开始请求微信的下单接口:https://www.easck.com/pay/unifiedorder,现在坑又来了。按照微信的下单说明,传给微信服务器的参数必须是XML格式的数据。如果你传过这种类型的自然好办,不过我猜大多数童鞋没有传过这种类型的数据,好在AF有提供方法,不然就等着哭吧。继续看代码


+ (void)postWechatPayWithUrl:(NSString *)url
           params:(id)params
         andSuccess:(requestSuccessResult)successBlock
         andFailure:(requestFailureResult)failureBlock{
  NSString *string = [params XMLString];//这里需要导入XMLDictionary文件,里面有该方法
  AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
  // 这里传入的XML字符串只是形似XML,但不是正确是XML格式,需要使用AF方法进行转义
  session.responseSerializer = [[AFHTTPResponseSerializer alloc] init];
  [session.requestSerializer setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
  [session.requestSerializer setValue:url forHTTPHeaderField:@"SOAPAction"];
  [session.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error) {
    return string;
  }];
  
  [session POST:url parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
    
  } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
    successBlock(responseObject);
  } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    HPError *hpError = [HPError errorWithCode:error.code desc:error.description];
    failureBlock(hpError);
  }];
}

按照上述的步骤,到这里就可以正常下单了,如果微信服务器返回给你的数据中有"result_code" = SUCCESS; "return_code" = SUCCESS,说明下单成功,这个步骤也到此结束。

第三步  调起微信客户端,并完成支付

如果第二步正常下单,那么微信会返回给你预支付ID,这个ID在最后的支付中至关重要,下面的代码是比较统一的,大家都这么写。


HPWechatProduct *product = [[HPWechatProduct alloc] initWithDic:result];
PayReq *req       = [[PayReq alloc] init];
req.partnerId      = product.partnerid;
req.prepayId       = product.prepayid;
req.nonceStr       = product.noncestr;
req.timeStamp      = [product.timestamp intValue];
req.package       = product.package;
req.sign         = product.sign;
BOOL flag = [WXApi sendReq:req];

HPWechatProduct.m
- (instancetype)initWithDic:(NSDictionary *)dic{
  if (self = [super init]) {
    self.appid = WECHAT_SHARE_APPID;
    self.partnerid = mah_id;
    self.prepayid = [dic formateObjectForKey:@"prepay_id"];
    self.package = @"Sign=WXPay";
    self.noncestr = [AppMethod getRandomString];
    self.timestamp = [self getTime];
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    [dic setValue:self.appid forKey:@"appid"];
    [dic setValue:self.partnerid forKey:@"partnerid"];
    [dic setValue:self.prepayid forKey:@"prepayid"];
    [dic setValue:self.package forKey:@"package"];
    [dic setValue:self.noncestr forKey:@"noncestr"];
    [dic setValue:self.timestamp forKey:@"timestamp"];
    self.sign = [self partnerSignOrder:dic];
  }
  return self;
}
- (NSString *)partnerSignOrder:(NSDictionary*)paramDic{
  NSArray *keyArray = [paramDic allKeys];
  NSMutableArray *sortedKeyArray = [NSMutableArray arrayWithArray:keyArray];
  [sortedKeyArray sortUsingComparator:^NSComparisonResult(NSString* key1, NSString* key2) {
    return [key1 compare:key2];
  }];
  NSMutableString *paramString = [NSMutableString stringWithString:@""];
  // 拼接成 A=B&X=Y
  for (NSString *key in sortedKeyArray){
    if ([paramDic[key] length] != 0){
      [paramString appendFormat:@"&%@=%@", key, paramDic[key]];
    }
  }
  if ([paramString length] > 1){
    [paramString deleteCharactersInRange:NSMakeRange(0, 1)];  // remove first '&'
  }
  [paramString appendFormat:@"&key=%@", WeChatPARTNER_ID];
  return [[AppMethod signString:paramString] uppercaseString];
}

- (NSString *)getTime{
  NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
  return [NSString stringWithFormat:@"%ld", (long)interval];
}


AppMethod.m
+ (NSString *)getRandomString
{
  NSString *str = [NSString stringWithFormat:@"%s",genRandomString(32)];
  return str;
}