你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> IOS客戶端接入微信付出

IOS客戶端接入微信付出

編輯:IOS開發綜合

現實上,從代碼的角度,調起付出APP就是把一些症結的參數經由過程必定方法打包成為一個定單,然後發送到付出平台的辦事器。所以,只需弄清晰了參數設置,弄清晰了每一個付出平台的SDK外面一些症結API的應用,根本上便可以很簡略的支撐付出。

明天記載一下客戶端外面,若何支撐微信付出。起首。我們要細心浏覽一下微信SDK的開辟文檔,懂得一下全部付出的年夜概流程。

然後依據提醒,把響應的SDK下載上去,所謂的SDK,也就是一個鏈接庫和兩個頭文件,很簡略。

下載終了,須要把SDK導入到工程外面,而且設置裝備擺設一下工程。由於開辟者文檔曾經有具體描寫,這裡就不再復述。

從文檔看到,調起微信付出其實最焦點的是一下這麼一段

<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,真正應用的時刻,參數都須要自行傳入。

為了弄清晰若何應用API,我們可以下載Sample代碼。不外,這個sample代碼應當是微信的練習生寫的,並且應當是一個關於C++比擬熟習,關於ObjectC比擬生疏的練習生。。。代碼作風可以看出許多器械哈。。所以這個sample讀起來總認為有點奇異。固然,寫出這個demo也是須要不錯的程度,由於這個sample不只僅是一些API的挪用,還包含了一些算法的完成,MD5之類的。
看懂了sample以後,普通可以本身重構一下,成為本身APP外面的一個Manager類。

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

ApiXmlRss/ target=_blank class=infotextkey>Xml.h

ApiXmlRss/ target=_blank class=infotextkey>Xml.m

WXUtil.h

WXUtil.m

payRequestHandler.h

payRequestHandler.m

假如比擬重視定名標准的OC法式猿,就會認為這個payRequestHandler類異常別扭,不相符camel定名規矩,並且handler這個詞更傾向於c++作風。我就以這個類為原型,重構了一下,並改裝成一個傳參的辦法,供本身的APP挪用。APP外面賣商品,普通就是商品名字,價錢兩個症結參數。所以這個重構的辦法也只是供給這兩個參數的接口。
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
// 賬號帳戶材料
// 更改商戶把相干參數後可測試
#define APP_ID     @wx@@@@@@@@@@@@@@@@    //APPID
#define APP_SECRET   @             //appsecret,看起來似乎沒用
//商戶號,填寫商戶對應參數
#define MCH_ID     @@@@@@@@@@@
//商戶API密鑰,填寫響應參數
#define PARTNER_ID   @12345678901234567890123456789012
//付出成果回調頁面
#define NOTIFY_URL   @http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php
//獲得辦事器端付出數據地址(商戶自界說)(在小吉這裡,簽名算法直接放在APP端,故不須要自界說)
#define SP_URL     @http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php
@interface WechatPayManager : NSObject
{
}
//預付付網關url地址
@property (nonatomic,strong) NSString* payUrl;
//debug信息
@property (nonatomic,strong) NSMutableString *debugInfo;
@property (nonatomic,assign) NSInteger lastErrCode;//前往的毛病碼
//商戶症結信息
@property (nonatomic,strong) NSString *appId,*mchId,*spKey;
//初始化函數
-(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
//初始化函數
-(id)initWithAppID:(NSString*)appID mchID:(NSString*)mchID spKey:(NSString*)key
{
  self = [super init];
  if(self)
  {
    //初始化公有參數,重要是一些和商戶有關的參數
    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;
}
//創立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帶參數的簽名包
-(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:@發送的xml:%@
, send];
  //發送要求post xml數據
  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] )
  {
    //生成前往數據的簽名
    NSString *sign   = [self createMd5Sign:resParams ];
    NSString *send_sign =[resParams objectForKey:@sign] ;
    //驗證簽名准確性
    if( [sign isEqualToString:send_sign]){
      if( [result_code isEqualToString:@SUCCESS]) {
        //驗證營業處置狀況
        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;//以分為單元的整數
  //付出裝備號或門店號
  NSString* orderDevice = device;
  //付出類型,固定為APP
  NSString* orderType = @APP;
  //發器付出的機械ip,臨時沒有發明其感化
  NSString* orderIP = @196.168.1.1;
  //隨機數串
  srand( (unsigned)time(0) );
  NSString *noncestr = [NSString stringWithFormat:@%d, rand()];
  NSString *orderNO  = [NSString stringWithFormat:@%ld,time(0)];
  //================================
  //預支單參數定單設置
  //================================
  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];//發器付出的機械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;
  //設置付出參數
  time_t now;
  time(&now);
  time_stamp = [NSString stringWithFormat:@%ld, now];
  nonce_str = [WXUtil md5:time_stamp];
  //從新按提交格局組包,微信客戶端暫只支撐package=Sign=WXPay格局,須斟酌進級後支撐攜帶package詳細參數的情形
  //package    = [NSString stringWithFormat:@Sign=%@,package];
  package     = @Sign=WXPay;
  //第二次簽名參數列表
  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];
  //前往參數列表
  return signParams;
}
@end</code>

然後,在須要挪用微信付出的Controller外面,新建一個辦法。在適合的處所挪用。這個辦法外面應用WechatPayManager這個類停止了初始化和參數封裝,然後把上述的焦點代碼(PayReq那一段)

<code class="hljs" objectivec="">- (void)wxPayWithOrderName:(NSString*)name price:(NSString*)price
{
  //創立付出簽名對象 && 初始化付出簽名對象
  WechatPayManager* wxpayManager = [[[WechatPayManager alloc]initWithAppID:APP_ID mchID:MCH_ID spKey:PARTNER_ID] autorelease];
 
  //獲得到現實調起微信付出的參數後,在app端調起付出
  //生成預付付定單,現實上就是把症結參數停止第一次加密。
  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];
 
  //調起微信付出
  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>

再者,付出完成了須要挪用一個delegate,這個delegate便利特性化顯示付出成果。普通直接把這兩個delegate放在AppDelegate就行了。由於有一些其他內容也是須要在AppDelegate外面完成,省的離開找不到。

<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 = @用戶曾經加入付出!;
        break;
      default:
        strMsg = [NSString stringWithFormat:@付出成果:掉敗!retcode = %d, retstr = %@, resp.errCode,resp.errStr];
        break;
    }
  }
}</code>

留意事項:

1)假如APP外面曾經應用了ShareSDK,就有一些處所要留意。不要再反復導入微信的SDK,由於shareSDK外面的extend曾經包含了微信的SDK。

2)微信自己是勉勵客戶APP把簽名算法放到辦事器下面,如許信息就不輕易被破解。然則假如客戶APP自己沒有辦事器端,或許以為不須要放到辦事器端,也能夠直接把簽名(加密)的部門直接放在APP端。Sample代碼的正文有點亂,屢次提到辦事器如此,然則其實可以不這麼做。

3)微信的price單元是分。留意下便可。

4)臨時想不到,今後想到了再記載。。

以上是本文給年夜家論述的IOS客戶端接入微信付出的全體內容,願望年夜家愛好。

【IOS客戶端接入微信付出】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved