欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

iOS實(shí)現(xiàn)微信支付流程詳解

 更新時(shí)間:2017年09月07日 08:18:23   作者:Meng鋒  
本篇文章主要介紹了iOS實(shí)現(xiàn)微信支付流程詳解 ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

背景

自微信支付、支付寶支付入世以來,移動(dòng)端的支付日漸火熱。虛擬貨幣有取代實(shí)體貨幣的趨向(這句純屬扯淡,不用管),支付在app開發(fā)中是一項(xiàng)基本的功能,有必要去掌握。從難易程度上講,不管是微信支付還是支付寶支付都是非常簡單的,因?yàn)榈谌降闹Ц段臋n非常詳細(xì),而且他們內(nèi)部的安全性也非常高。作為使用這些支付策略的我們,只需要掌握流程,能夠?qū)崿F(xiàn)正常支付的功能即可。為什么要寫下這篇博文,原因有二。其一,微信支付流程中有坑,其二,以后忘記了可以拿出來看看。

配置

1.微信支付需要兩個(gè)賬號(hào),財(cái)付通和微信開發(fā)者,注冊(cè)完成后需要開通支付功能,這些流程就不用多說了。在所有申請(qǐng)成功后,我們要取出我們支付功能需要的key:

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

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

支付

從此處開始,進(jìn)入本次的主題,開始支付。支付的過程且分為四個(gè)步驟:

第一步  獲取訂單號(hào)

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

第二步  統(tǒng)一下單

這個(gè)過程是非常關(guān)鍵的一步,也是坑常駐的一步。統(tǒng)一下單有的人做法是在服務(wù)器操作,有的在客戶端,不管在哪下單都是有必要搞懂的。接下來看看統(tǒng)一下單必須要的參數(shù)列表:

/*應(yīng)用ID 微信開放平臺(tái)審核通過的應(yīng)用app ID*/
@property (nonatomic, copy) NSString *appid;
/*商戶號(hào) 微信支付分配的商戶號(hào)*/
@property (nonatomic, copy) NSString *mch_id;
/*隨機(jī)字符串 隨機(jī)字符串,不長于32位*/
@property (nonatomic, copy) NSString *nonce_str;
/*簽名*/
@property (nonatomic, copy) NSString *sign;
/*商品描述 天天愛消除-游戲充值。*/
@property (nonatomic, copy) NSString *body;
/*商戶訂單號(hào)*/
@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是其他所有參數(shù)按照key1=value1&key2=value2...的方式拼接,然后進(jìn)行加密得到。參數(shù)拼接按照字母排序,舉個(gè)例子,參數(shù)為appid=@"id",mch_id=@"mch"得到的字符串應(yīng)該是:@"appid=id&mch_id=mch",然后對(duì)該字符串進(jìn)行加密,如下述代碼

- (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);//調(diào)用md5
  NSMutableString *hash = [NSMutableString string];
  for (int i = 0; i < 16; i++){
    [hash appendFormat:@"%02X", result[i]];
  }
  return hash;
}

這樣,統(tǒng)一下單的參數(shù)已經(jīng)準(zhǔn)備好了,下面開始請(qǐng)求微信的下單接口:https://api.mch.weixin.qq.com/pay/unifiedorder,現(xiàn)在坑又來了。按照微信的下單說明,傳給微信服務(wù)器的參數(shù)必須是XML格式的數(shù)據(jù)。如果你傳過這種類型的自然好辦,不過我猜大多數(shù)童鞋沒有傳過這種類型的數(shù)據(jù),好在AF有提供方法,不然就等著哭吧。繼續(xù)看代碼

+ (void)postWechatPayWithUrl:(NSString *)url
           params:(id)params
         andSuccess:(requestSuccessResult)successBlock
         andFailure:(requestFailureResult)failureBlock{
  NSString *string = [params XMLString];//這里需要導(dǎo)入XMLDictionary文件,里面有該方法
  AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
  // 這里傳入的XML字符串只是形似XML,但不是正確是XML格式,需要使用AF方法進(jìn)行轉(zhuǎn)義
  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);
  }];
}

按照上述的步驟,到這里就可以正常下單了,如果微信服務(wù)器返回給你的數(shù)據(jù)中有"result_code" = SUCCESS; "return_code" = SUCCESS,說明下單成功,這個(gè)步驟也到此結(jié)束。

第三步  調(diào)起微信客戶端,并完成支付

如果第二步正常下單,那么微信會(huì)返回給你預(yù)支付ID,這個(gè)ID在最后的支付中至關(guān)重要,下面的代碼是比較統(tǒng)一的,大家都這么寫。

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;
}

如果到了這一步,而且跑到了微信并完成了支付,那么微信會(huì)有一個(gè)回調(diào),告訴你支付成功了。然而真的成功了嘛,請(qǐng)繼續(xù)看第四步。

第四步  去服務(wù)器查詢是否支付成功

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

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談Xcode 開發(fā)工具 XCActionBar

    淺談Xcode 開發(fā)工具 XCActionBar

    本文主要給大家簡單講解了Xcode的開發(fā)工具 XCActionBar的介紹與使用方法,非常的全面實(shí)用,有需要的小伙伴可以參考下。
    2015-11-11
  • iOS實(shí)現(xiàn)視頻播放全屏和取消全屏功能

    iOS實(shí)現(xiàn)視頻播放全屏和取消全屏功能

    這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)視頻播放全屏和取消全屏功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • MacOS系統(tǒng)下Unity啟動(dòng)黑屏的解決方法

    MacOS系統(tǒng)下Unity啟動(dòng)黑屏的解決方法

    最近發(fā)現(xiàn)了一個(gè)問題,unity一打開就黑屏,通過查找相關(guān)的資料終于解決了,所以下面這篇文章主要給大家介紹了關(guān)于在MacOS系統(tǒng)下Unity啟動(dòng)黑屏的解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。
    2018-01-01
  • iOS 增加右側(cè)按鈕功能實(shí)例代碼

    iOS 增加右側(cè)按鈕功能實(shí)例代碼

    這篇文章主要介紹了iOS 增加右側(cè)按鈕功能實(shí)例代碼,需要的朋友可以參考下
    2017-07-07
  • IOS NSTimeInterval使用案例詳解

    IOS NSTimeInterval使用案例詳解

    這篇文章主要介紹了IOS NSTimeInterval使用案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 詳解iOS開發(fā)中Keychain的相關(guān)使用

    詳解iOS開發(fā)中Keychain的相關(guān)使用

    這篇文章主要介紹了iOS開發(fā)中Keychain的相關(guān)使用,文中列舉了一個(gè)使用Keychain來保存密碼的例子,需要的朋友可以參考下
    2015-10-10
  • iOS中MD5加密算法的介紹和使用

    iOS中MD5加密算法的介紹和使用

    MD5加密是最常用的加密方法之一,是從一段字符串中通過相應(yīng)特征生成一段32位的數(shù)字字母混合碼。對(duì)輸入信息生成唯一的128位散列值(32個(gè)字符)。這篇文章就給大家介紹了iOS中MD5加密算法,已經(jīng)iOS中MD5加密算法的使用,有需要的朋友們可以參考借鑒。
    2016-10-10
  • iOS改變UITextField占位文字顏色的三種方法

    iOS改變UITextField占位文字顏色的三種方法

    這篇文章主要為大家詳細(xì)介紹了iOS改變UITextField的占位文字顏色的三種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • 99%?iOS開發(fā)都不知道的KVO崩潰分析詳解

    99%?iOS開發(fā)都不知道的KVO崩潰分析詳解

    這篇文章主要為大家介紹了99%?iOS開發(fā)都不知道的KVO崩潰分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • iOS 把圖片保存到相冊(cè),并獲取圖片文件名的實(shí)例

    iOS 把圖片保存到相冊(cè),并獲取圖片文件名的實(shí)例

    下面小編就為大家分享一篇iOS 把圖片保存到相冊(cè),并獲取圖片文件名的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12

最新評(píng)論