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

IOS客戶端接入微信支付

 更新時間:2015年09月20日 09:52:43   投稿:mrr  
對于一個ios的app,如果有一些虛擬的商品或者服務需要通過在線支付來收費的話,一般有幾種主流的選擇。如果是通過APP調(diào)用支付平臺APP的思路的話,一個是調(diào)起支付寶客戶端,一個則是調(diào)起微信支付。本文給大家分享ios客戶端接入微信支付,需要的朋友可以參考下

實際上,從代碼的角度,調(diào)起支付APP就是把一些關鍵的參數(shù)通過一定方式打包成為一個訂單,然后發(fā)送到支付平臺的服務器。所以,只要搞清楚了參數(shù)設置,搞清楚了每個支付平臺的SDK里面一些關鍵API的使用,基本上就可以很簡單的支持支付。

今天記錄一下客戶端里面,如何支持微信支付。首先。我們要仔細閱讀一下微信SDK的開發(fā)文檔,了解一下整個支付的大概流程。

然后根據(jù)提示,把相應的SDK下載下來,所謂的SDK,也就是一個鏈接庫和兩個頭文件,很簡單。

下載完畢,需要把SDK導入到工程里面,并且配置一下工程。因為開發(fā)者文檔已經(jīng)有詳細描述,這里就不再復述。

從文檔看到,調(diào)起微信支付其實最核心的是一下這么一段

<code class="hljs" vbscript="">PayReq *request = [[[PayReq alloc] init] autorelease];
request.partnerId = @10000100;
request.prepayId= @1101000000140415649af9fc314aa427;
request.package = @Sign=WXPay;
request.nonceStr= @a462b76e7436e98e0ed6e13c64b4fd1c;
request.timeStamp= @1397527777;
request.sign= @582282D72DD2B03AD892830965F428CB16E7A256;
[WXApi sendReq:request];</code>

這里的范例是一段hardcode,真正使用的時候,參數(shù)都需要自行傳入。

為了搞清楚如何使用API,我們可以下載Sample代碼。不過,這個sample代碼應該是微信的實習生寫的,而且應該是一個對于C++比較熟悉,對于ObjectC比較陌生的實習生。。。代碼風格可以看出很多東西哈。。所以這個sample讀起來總覺得有點奇怪。當然,寫出這個demo也是需要不錯的水平,因為這個sample不僅僅是一些API的調(diào)用,還包括了一些算法的實現(xiàn),MD5之類的。
看懂了sample之后,一般可以自己重構一下,成為自己APP里面的一個Manager類。

我是在2015 5 23下載的微信Sampel代碼,里面包括有:

ApiXml.h

ApiXml.m

WXUtil.h

WXUtil.m

payRequestHandler.h

payRequestHandler.m

如果比較看重命名規(guī)范的OC程序猿,就會覺得這個payRequestHandler類非常別扭,不符合camel命名規(guī)則,而且handler這個詞更偏向于c++風格。我就以這個類為原型,重構了一下,并改裝成一個傳參的方法,供自己的APP調(diào)用。APP里面賣商品,一般就是商品名字,價格兩個關鍵參數(shù)。所以這個重構的方法也只是提供這兩個參數(shù)的接口。
ApiXml.h && ApiXml.m && WXUtil.h && WXUtil.m不變

<code class="hljs" objectivec="">//
// WechatPayManager.h
//
// Created by HuangCharlie on 5/24/15.
//
//
#import <foundation foundation.h="">
#import WXUtil.h
#import ApiXml.h
#import WXApi.h
// 賬號帳戶資料
// 更改商戶把相關參數(shù)后可測試
#define APP_ID     @wx@@@@@@@@@@@@@@@@    //APPID
#define APP_SECRET   @             //appsecret,看起來好像沒用
//商戶號,填寫商戶對應參數(shù)
#define MCH_ID     @@@@@@@@@@@
//商戶API密鑰,填寫相應參數(shù)
#define PARTNER_ID   @12345678901234567890123456789012
//支付結果回調(diào)頁面
#define NOTIFY_URL   @http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php
//獲取服務器端支付數(shù)據(jù)地址(商戶自定義)(在小吉這里,簽名算法直接放在APP端,故不需要自定義)
#define SP_URL     @http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php
@interface WechatPayManager : NSObject
{
}
//預支付網(wǎng)關url地址
@property (nonatomic,strong) NSString* payUrl;
//debug信息
@property (nonatomic,strong) NSMutableString *debugInfo;
@property (nonatomic,assign) NSInteger lastErrCode;//返回的錯誤碼
//商戶關鍵信息
@property (nonatomic,strong) NSString *appId,*mchId,*spKey;
//初始化函數(shù)
-(id)initWithAppID:(NSString*)appID
       mchID:(NSString*)mchID
       spKey:(NSString*)key;
//獲取當前的debug信息
-(NSString *) getDebugInfo;
//獲取預支付訂單信息(核心是一個prepayID)
- (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name
                     price:(NSString*)price
                    device:(NSString*)device;
@end
</foundation></code>
<code class="hljs" objectivec="">//
// WechatPayManager.m
//
// Created by HuangCharlie on 5/24/15.
//
//
#import WechatPayManager.h
@implementation WechatPayManager
//初始化函數(shù)
-(id)initWithAppID:(NSString*)appID mchID:(NSString*)mchID spKey:(NSString*)key
{
  self = [super init];
  if(self)
  {
    //初始化私有參數(shù),主要是一些和商戶有關的參數(shù)
    self.payUrl  = @https://api.mch.weixin.qq.com/pay/unifiedorder;
    if (self.debugInfo == nil){
      self.debugInfo = [NSMutableString string];
    }
    [self.debugInfo setString:@];
    self.appId = appID;//微信分配給商戶的appID
    self.mchId = mchID;//
    self.spKey = key;//商戶的密鑰
  }
  return self;
}
//獲取debug信息
-(NSString*) getDebugInfo
{
  NSString *res = [NSString stringWithString:self.debugInfo];
  [self.debugInfo setString:@];
  return res;
}
//創(chuàng)建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=%@, self.spKey];
  //得到MD5 sign簽名
  NSString *md5Sign =[WXUtil md5:contentString];
  //輸出Debug Info
  [self.debugInfo appendFormat:@MD5簽名字符串:
%@
,contentString];
  return md5Sign;
}
//獲取package帶參數(shù)的簽名包
-(NSString *)genPackage:(NSMutableDictionary*)packageParams
{
  NSString *sign;
  NSMutableString *reqPars=[NSMutableString string];
  //生成簽名
  sign    = [self createMd5Sign:packageParams];
  //生成xml的package
  NSArray *keys = [packageParams allKeys];
  [reqPars appendString:@<xml>
];
  for (NSString *categoryId in keys) {
    [reqPars appendFormat:@<%@>%@<!--%@-->
, categoryId, [packageParams objectForKey:categoryId],categoryId];
  }
  [reqPars appendFormat:@<sign>%@</sign>
</xml>, sign];
  return [NSString stringWithString:reqPars];
}
//提交預支付
-(NSString *)sendPrepay:(NSMutableDictionary *)prePayParams
{
  NSString *prepayid = nil;
  //獲取提交支付
  NSString *send   = [self genPackage:prePayParams];
  //輸出Debug Info
  [self.debugInfo appendFormat:@API鏈接:%@
, self.payUrl];
  [self.debugInfo appendFormat:@發(fā)送的xml:%@
, send];
  //發(fā)送請求post xml數(shù)據(jù)
  NSData *res = [WXUtil httpSend:self.payUrl method:@POST data:send];
  //輸出Debug Info
  [self.debugInfo appendFormat:@服務器返回:
%@
,[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];
  XMLHelper *xml = [[XMLHelper alloc] autorelease];
  //開始解析
  [xml startParse:res];
  NSMutableDictionary *resParams = [xml getDict];
  //判斷返回
  NSString *return_code  = [resParams objectForKey:@return_code];
  NSString *result_code  = [resParams objectForKey:@result_code];
  if ( [return_code isEqualToString:@SUCCESS] )
  {
    //生成返回數(shù)據(jù)的簽名
    NSString *sign   = [self createMd5Sign:resParams ];
    NSString *send_sign =[resParams objectForKey:@sign] ;
    //驗證簽名正確性
    if( [sign isEqualToString:send_sign]){
      if( [result_code isEqualToString:@SUCCESS]) {
        //驗證業(yè)務處理狀態(tài)
        prepayid  = [resParams objectForKey:@prepay_id];
        return_code = 0;
        [self.debugInfo appendFormat:@獲取預支付交易標示成功!
];
      }
    }else{
      self.lastErrCode = 1;
      [self.debugInfo appendFormat:@gen_sign=%@
  _sign=%@
,sign,send_sign];
      [self.debugInfo appendFormat:@服務器返回簽名驗證錯誤?。?!
];
    }
  }else{
    self.lastErrCode = 2;
    [self.debugInfo appendFormat:@接口返回錯誤?。。?
];
  }
  return prepayid;
}
- (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name
                     price:(NSString*)price
                    device:(NSString*)device
{
  //訂單標題,展示給用戶
  NSString* orderName = name;
  //訂單金額,單位(分)
  NSString* orderPrice = price;//以分為單位的整數(shù)
  //支付設備號或門店號
  NSString* orderDevice = device;
  //支付類型,固定為APP
  NSString* orderType = @APP;
  //發(fā)器支付的機器ip,暫時沒有發(fā)現(xiàn)其作用
  NSString* orderIP = @196.168.1.1;
  //隨機數(shù)串
  srand( (unsigned)time(0) );
  NSString *noncestr = [NSString stringWithFormat:@%d, rand()];
  NSString *orderNO  = [NSString stringWithFormat:@%ld,time(0)];
  //================================
  //預付單參數(shù)訂單設置
  //================================
  NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
  [packageParams setObject: self.appId forKey:@appid];    //開放平臺appid
  [packageParams setObject: self.mchId forKey:@mch_id];   //商戶號
  [packageParams setObject: orderDevice forKey:@device_info]; //支付設備號或門店號
  [packageParams setObject: noncestr   forKey:@nonce_str];  //隨機串
  [packageParams setObject: orderType  forKey:@trade_type]; //支付類型,固定為APP
  [packageParams setObject: orderName  forKey:@body];    //訂單描述,展示給用戶
  [packageParams setObject: NOTIFY_URL forKey:@notify_url]; //支付結果異步通知
  [packageParams setObject: orderNO   forKey:@out_trade_no];//商戶訂單號
  [packageParams setObject: orderIP   forKey:@spbill_create_ip];//發(fā)器支付的機器ip
  [packageParams setObject: orderPrice  forKey:@total_fee];    //訂單金額,單位為分
  //獲取prepayId(預支付交易會話標識)
  NSString *prePayid;
  prePayid = [self sendPrepay:packageParams];
  if(prePayid == nil)
  {
    [self.debugInfo appendFormat:@獲取prepayid失敗!
];
    return nil;
  }
  //獲取到prepayid后進行第二次簽名
  NSString  *package, *time_stamp, *nonce_str;
  //設置支付參數(shù)
  time_t now;
  time(&now);
  time_stamp = [NSString stringWithFormat:@%ld, now];
  nonce_str = [WXUtil md5:time_stamp];
  //重新按提交格式組包,微信客戶端暫只支持package=Sign=WXPay格式,須考慮升級后支持攜帶package具體參數(shù)的情況
  //package    = [NSString stringWithFormat:@Sign=%@,package];
  package     = @Sign=WXPay;
  //第二次簽名參數(shù)列表
  NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
  [signParams setObject: self.appId forKey:@appid];
  [signParams setObject: self.mchId forKey:@partnerid];
  [signParams setObject: nonce_str  forKey:@noncestr];
  [signParams setObject: package   forKey:@package];
  [signParams setObject: time_stamp  forKey:@timestamp];
  [signParams setObject: prePayid   forKey:@prepayid];
  //生成簽名
  NSString *sign = [self createMd5Sign:signParams];
  //添加簽名
  [signParams setObject: sign     forKey:@sign];
  [self.debugInfo appendFormat:@第二步簽名成功,sign=%@
,sign];
  //返回參數(shù)列表
  return signParams;
}
@end</code>

然后,在需要調(diào)用微信支付的Controller里面,新建一個方法。在合適的地方調(diào)用。這個方法里面利用WechatPayManager這個類進行了初始化和參數(shù)封裝,然后把上述的核心代碼(PayReq那一段)

<code class="hljs" objectivec="">- (void)wxPayWithOrderName:(NSString*)name price:(NSString*)price
{
  //創(chuàng)建支付簽名對象 && 初始化支付簽名對象
  WechatPayManager* wxpayManager = [[[WechatPayManager alloc]initWithAppID:APP_ID mchID:MCH_ID spKey:PARTNER_ID] autorelease];
 
  //獲取到實際調(diào)起微信支付的參數(shù)后,在app端調(diào)起支付
  //生成預支付訂單,實際上就是把關鍵參數(shù)進行第一次加密。
  NSString* device = [[UserManager defaultManager]userId];
  NSMutableDictionary *dict = [wxpayManager getPrepayWithOrderName:name
                                price:price
                             device:device];
  if(dict == nil){
    //錯誤提示
    NSString *debug = [wxpayManager getDebugInfo];
    return;
  }

  NSMutableString *stamp = [dict objectForKey:@timestamp];
 
  //調(diào)起微信支付
  PayReq* req       = [[[PayReq alloc] init]autorelease];
  req.openID       = [dict objectForKey:@appid];
  req.partnerId     = [dict objectForKey:@partnerid];
  req.prepayId      = [dict objectForKey:@prepayid];
  req.nonceStr      = [dict objectForKey:@noncestr];
  req.timeStamp     = stamp.intValue;
  req.package      = [dict objectForKey:@package];
  req.sign        = [dict objectForKey:@sign];
 
//    BOOL flag = [WXApi sendReq:req];
  BOOL flag = [WXApi safeSendReq:req];
}</code>

再者,支付完成了需要調(diào)用一個delegate,這個delegate方便個性化顯示支付結果。一般直接把這兩個delegate放在AppDelegate就好了。因為有一些其他內(nèi)容也是需要在AppDelegate里面實現(xiàn),省的分開找不到。

<code class="hljs" objectivec="">-(void) onResp:(BaseResp*)resp
{ 
  //啟動微信支付的response
  NSString *strMsg = [NSString stringWithFormat:@errcode:%d, resp.errCode];
  if([resp isKindOfClass:[PayResp class]]){
    //支付返回結果,實際支付結果需要去微信服務器端查詢
    switch (resp.errCode) {
      case 0:
        strMsg = @支付結果:成功!;
        break;
      case -1:
        strMsg = @支付結果:失?。?
        break;
      case -2:
        strMsg = @用戶已經(jīng)退出支付!;
        break;
      default:
        strMsg = [NSString stringWithFormat:@支付結果:失敗!retcode = %d, retstr = %@, resp.errCode,resp.errStr];
        break;
    }
  }
}</code>

注意事項:

1)如果APP里面已經(jīng)使用了ShareSDK,就有一些地方要注意。不要再重復導入微信的SDK,因為shareSDK里面的extend已經(jīng)包括了微信的SDK。

2)微信本身是鼓勵客戶APP把簽名算法放到服務器上面,這樣信息就不容易被破解。但是如果客戶APP本身沒有服務器端,或者認為不需要放到服務器端,也可以直接把簽名(加密)的部分直接放在APP端。Sample代碼的注釋有點亂,多次提到服務器云云,但是其實可以不這么做。

3)微信的price單位是分。注意下即可。

4)暫時想不到,以后想到了再記錄。。

以上是本文給大家敘述的IOS客戶端接入微信支付的全部內(nèi)容,希望大家喜歡。

相關文章

  • iOS中的3種定時器匯總介紹

    iOS中的3種定時器匯總介紹

    這篇文章主要介紹了iOS中的3種定時器匯總介紹的相關資料,需要的朋友可以參考下
    2023-05-05
  • iOS實現(xiàn)二維碼的掃描功能

    iOS實現(xiàn)二維碼的掃描功能

    本文給大家介紹的是iOS 原生態(tài)API實現(xiàn)二維碼的掃描功能,非常簡單實用,有需要的小伙伴可以參考下。
    2015-07-07
  • iOS微信第三方登錄實例

    iOS微信第三方登錄實例

    這篇文章主要為大家詳細介紹了iOS微信第三方登錄實現(xiàn)過程,一步一步告訴大家iOS微信實現(xiàn)第三方登錄的方法,感興趣的小伙伴們可以參考一下
    2016-12-12
  • iOS富文本的使用方法示例詳解

    iOS富文本的使用方法示例詳解

    這篇文章主要給大家介紹了關于iOS富文本的使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-12-12
  • Objective-C 實現(xiàn)2048算法類

    Objective-C 實現(xiàn)2048算法類

    本文給大家介紹的是使用Objective-C 實現(xiàn)的IOS版小游戲2048算法類,十分的實用,有需要的小伙伴可以參考下。
    2015-06-06
  • iOS在Block中修改外部變量值的實現(xiàn)代碼

    iOS在Block中修改外部變量值的實現(xiàn)代碼

    這篇文章主要介紹了iOS在Block中修改外部變量值的實現(xiàn)代碼,需要的朋友可以參考下
    2017-08-08
  • iOS實用教程之Https雙向認證詳解

    iOS實用教程之Https雙向認證詳解

    這篇文章主要給大家介紹了關于iOS中Https雙向認證的相關資料,文中介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-05-05
  • IOS 中動畫的暫停與繼續(xù)播放的詳解

    IOS 中動畫的暫停與繼續(xù)播放的詳解

    這篇文章主要介紹了IOS 中動畫的暫停與繼續(xù)播放的詳解的相關資料,希望通過本文大家能理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • iOS功能實現(xiàn)之列表的橫向刷新加載

    iOS功能實現(xiàn)之列表的橫向刷新加載

    現(xiàn)今已有越來越多的APP需要橫向刷新的需求,而橫向刷新加載的控件卻寥寥無幾,即使有也是集成起來非常的麻煩,恰巧最近項目中又用到了這個功能,所以干脆自己來造個輪子,方便大家使用。
    2016-08-08
  • iOS開發(fā)中指紋識別簡單介紹

    iOS開發(fā)中指紋識別簡單介紹

    指紋識別是在iOS8.0以后才推出的,所以我們?nèi)绻氚阎讣y集成到我們的APP當中,我們首先就要在代碼中判斷iOS版本。接下來通過本文給大家分享iOS開發(fā)中指紋識別簡單介紹,需要的朋友參考下吧
    2017-11-11

最新評論