国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

iOS實現微信支付流程詳解

2020-07-26 02:42:44
字體:
來源:轉載
供稿:網友

背景

自微信支付、支付寶支付入世以來,移動端的支付日漸火熱。虛擬貨幣有取代實體貨幣的趨向(這句純屬扯淡,不用管),支付在app開發中是一項基本的功能,有必要去掌握。從難易程度上講,不管是微信支付還是支付寶支付都是非常簡單的,因為第三方的支付文檔非常詳細,而且他們內部的安全性也非常高。作為使用這些支付策略的我們,只需要掌握流程,能夠實現正常支付的功能即可。為什么要寫下這篇博文,原因有二。其一,微信支付流程中有坑,其二,以后忘記了可以拿出來看看。

配置

1.微信支付需要兩個賬號,財付通和微信開發者,注冊完成后需要開通支付功能,這些流程就不用多說了。在所有申請成功后,我們要取出我們支付功能需要的key:

appID、app密鑰(微信發給你的郵件中有如何生成密鑰的鏈接)、商戶號。

2.在Xcode中配置app ID,需要設置下白名單,在url中配置app ID,不清楚的童鞋可以百度一下。

支付

從此處開始,進入本次的主題,開始支付。支付的過程且分為四個步驟:

第一步  獲取訂單號

獲取訂單號的途徑可以是客戶端自己生成,也可以去服務器生成,不過一般都是服務器生成。假設拿到了訂單號設為order_no。

第二步  統一下單

這個過程是非常關鍵的一步,也是坑常駐的一步。統一下單有的人做法是在服務器操作,有的在客戶端,不管在哪下單都是有必要搞懂的。接下來看看統一下單必須要的參數列表:

/*應用ID 微信開放平臺審核通過的應用app ID*/@property (nonatomic, copy) NSString *appid;/*商戶號 微信支付分配的商戶號*/@property (nonatomic, copy) NSString *mch_id;/*隨機字符串 隨機字符串,不長于32位*/@property (nonatomic, copy) NSString *nonce_str;/*簽名*/@property (nonatomic, copy) NSString *sign;/*商品描述 天天愛消除-游戲充值。*/@property (nonatomic, copy) NSString *body;/*商戶訂單號*/@property (nonatomic, copy) NSString *out_trade_no;/*總金額 訂單總金額,單位為分*/@property (nonatomic, copy) NSString *total_fee;/*終端IP*/@property (nonatomic, copy) NSString *spbill_create_ip;/*通知地址*/@property (nonatomic, copy) NSString *notify_url;/*交易類型*/@property (nonatomic, copy) NSString *trade_type;

其中,sign是其他所有參數按照key1=value1&key2=value2...的方式拼接,然后進行加密得到。參數拼接按照字母排序,舉個例子,參數為appid=@"id",mch_id=@"mch"得到的字符串應該是:@"appid=id&mch_id=mch",然后對該字符串進行加密,如下述代碼

- (instancetype)initWithDicInfo:(NSDictionary *)infoDic{  if (self = [super init]) {    self.appid = WECHAT_SHARE_APPID;    self.mch_id = WECHAT_MCH_ID;    self.nonce_str = [AppMethod getRandomString];    self.body = @"test";    self.out_trade_no = [infoDic formateObjectForKey:@"order_no"];    self.total_fee = [NSString stringWithFormat:@"%@", [infoDic formateObjectForKey:@"amount"]];    self.spbill_create_ip = [AppMethod deviceIPAdress];    self.notify_url = [NSString stringWithFormat:@"%@%@", BASE_URL, WECHAT_NOTI_URL];    self.trade_type = @"APP";    self.payDic = [NSMutableDictionary dictionary];    [self.payDic setValue:self.appid forKey:@"appid"];    [self.payDic setValue:self.mch_id forKey:@"mch_id"];    [self.payDic setValue:self.nonce_str forKey:@"nonce_str"];    [self.payDic setValue:self.body forKey:@"body"];    [self.payDic setValue:self.out_trade_no forKey:@"out_trade_no"];    [self.payDic setValue:self.total_fee forKey:@"total_fee"];    [self.payDic setValue:self.spbill_create_ip forKey:@"spbill_create_ip"];    [self.payDic setValue:self.notify_url forKey:@"notify_url"];    [self.payDic setValue:self.trade_type forKey:@"trade_type"];    self.sign = [self partnerSignOrder:self.payDic];    [self.payDic setValue:self.sign forKey:@"sign"];  }  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];//app密鑰  return [[AppMethod signString:paramString] uppercaseString];}AppMethod.m+ (NSString *)signString:(NSString*)origString{  const char *original_str = [origString UTF8String];  unsigned char result[32];  CC_MD5(original_str, (CC_LONG)strlen(original_str), result);//調用md5  NSMutableString *hash = [NSMutableString string];  for (int i = 0; i < 16; i++){    [hash appendFormat:@"%02X", result[i]];  }  return hash;}

這樣,統一下單的參數已經準備好了,下面開始請求微信的下單接口:https://api.mch.weixin.qq.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;}

如果到了這一步,而且跑到了微信并完成了支付,那么微信會有一個回調,告訴你支付成功了。然而真的成功了嘛,請繼續看第四步。

第四步  去服務器查詢是否支付成功

即使微信告訴你支付成功了,你也不能相信,只有錢真正打到你們的賬號里面了,才算支付成功。任何時候都不能以微信的回調的值判斷支付是否成功(這是微信文檔說的)。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 克拉玛依市| 壶关县| 泉州市| 威宁| 禄丰县| 丰顺县| 成都市| 福州市| 彭阳县| 班戈县| 米脂县| 大悟县| 开原市| 五指山市| 光山县| 聂拉木县| 长寿区| 武义县| 双桥区| 广南县| 南川市| 咸阳市| 石狮市| 绥宁县| 美姑县| 龙游县| 凌海市| 南丹县| 商洛市| 吴江市| 旬邑县| 社会| 马龙县| 洛扎县| 揭东县| 武夷山市| 旬邑县| 镇原县| 南康市| 泗洪县| 南城县|