iOS第三方支付集成——微信支付

        

       近期筆者開發的項目中,需要用到支付寶支付和微信支付。大概一個月前,支付寶就已經集成完畢並可以正常使用。但在集成坑爹的微信支付SDK時,遇到了諸多問題,搞了將近三個星期。期間不斷的跟後臺同事覈對代碼(簽名、下單),支付流程,其中的血淚艱辛,不言而喻。現筆者把集成過程中遇到的一些問題記錄下來,供自己和大家參考。如果有什麼不對的地方,也請大家多多指正:


       吐槽完了,下面出正文。

       補充說明:第一準備階段不需要開發者負責操作,如果你是iOS開發人員,只想找到調用微信支付的代碼,可直接跳過 第一準備階段。


       一、準備階段


       (1)筆者公司用戶是微信開放平臺下開通的微信支付功能,網址:https://open.weixin.qq.com/?qq-pf-to=pcqq.c2c網上大部分資料講的都是微信公衆平臺下的微信支付集成,其實原理和代碼實現上大同小異。       

       (2)到微信開放平臺的管理中心創建移動應用,待移動應用審覈通過以後,申請獲得微信支付能,這個流程走下來,大概需要 2 - 3 周。筆者建議提前到開放平臺審覈爲好。網址:https://open.weixin.qq.com/cgi-bin/applist?t=manage/list&lang=zh_CN&token=478d1d01575659fb7b53ee40d1f37c5cfc8689e5

       移動應用審覈通過後,獲取APP_IDAppSecret,附上截圖:

wKiom1YXXILBWh1cAAFrvvDHNBU791.jpg



       (3)等到移動應用審覈通過,獲得微信支付能力之後,進入微信商戶商戶平臺。商戶平臺的賬號和密碼,在公司賬號開通微信支付功能以後,財付通就會下發。微信商戶平臺網址:https://pay.weixin.qq.com/index.php/home/login?return_url=/

       進入微信商戶平臺後,獲取商戶號和商戶API密鑰。附上截圖:

wKioL1YXW9iRiDr9AAIhc8Ak5JA319.jpg




       二、獲取微信支付IOS頭文件和庫下載及APP支付示例和解讀


       (1)進入網址https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1,下載微信支付APP支付示例。在APP支付示例中,已經包含了頭文件和庫,所以不需要在下載頭文件和庫。


       (2)解壓文件,會得到文件名爲:wechat_sdk_sample_ios_v3_pay的文件夾。從名字可以知道,這是一份v3版本的代碼,目前v2版本的微信支付幾乎已經不用,新添加的微信支付SDK幾乎都是v3版本的。集成的時候,要明白這點,很重要。


       (3)文件目錄及作用

       readme.txt:首次集成微信支付SDK時,讀讀沒壞處。

       設置appid.jpg:直接運行demo是無法調用微信客戶端的,需要按鈕圖片的內容,設置 URL Schemes 和 APP_ID 才能運行。

       wechat_sdk_sample_ios_payV3:

       ~ lib:配置文件,配置了微信支付所要設置的相關內容

       ~ SDKExport:微信支付頭文件和庫文件

       ~ SDKSample:項目功能實現代碼


       (4)代碼準備工作

       Xcode打開工程代碼,點擊AppDelegate.m文件,可以查看到微信支付的實現代碼。

       ~[WXApi registerApp:APP_ID withDescription:@"demo 2.0"];向微信註冊,必寫代碼。

       ~ -(void) onReq:(BaseReq*)req:發送信息給微信客戶端,請查看微信支付demo具體代碼實現

       ~ -(void) onResp:(BaseResp*)resp:收到微信客戶端信息的代理方法,請查看微信支付demo具體代碼實現


       (5)調起微信支付

       重點來了!!!通過調試,我們可以知道,"微信支付測試簽名"、“微信支付demo”兩個按鈕,分別對應的是 

- (void)sendPay - (void)sendPay_demo 兩個方法,那麼這兩個方法都做了什麼呢?什麼是簽名呢?

在解釋上面的問題前,有必要先解釋一下微信支付的簽名流程。


      微信支付demo和微信支付開發文檔多處提到以下幾點:

       ~ 後臺服務器做簽名、下單請求,從微信服務器獲取到 預支付ID 和 sign 簽名等多個參數;

       ~ APP通過獲取後臺返回的參數(openID、partnerID商戶號、prepayID預支付ID、nonceStr隨機字符串、timeStamp時間戳、package包、sign簽名),調用微信支付接口,就可以調用手機微信客戶端進行支付

       ~ 調用微信支付的代碼如下(核心代碼哦,我們所有的操作都是爲了這段核心的參數做準備):

//調起微信支付
        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"];
        
        [WXApi sendReq:req];


       根據上面的說明,童鞋們不知道明白了沒。其實所有的代碼,都是爲了上面的核心作準備的,目的地就是爲了獲取上面核心代碼的參數,已調用微信支付的接口。我們回到最初點:

       ~ - (void)sendPay:模擬簽名的過程。爲了更好的安全性,關於微信支付的下單和簽名的過程,一般都是在後臺完成,後臺再把這些參數傳回到APP,APP再調用。這個方法卻是在APP端完成下單和簽名的操作,這其實只是一個演示的過程“//本實例只是演示簽名過程, 請將該過程在商戶服務器上實現

       ~ - (void)sendPay_demo:使用微信後臺提供的參數,做支付演示。調用這個方法,控制檯會打印出這樣一串東西:url:http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=ios&order_no=1444376336&product_name=Ios%B7%FE%CE%F1%C6%F7%B6%CB%C7%A9%C3%FB%D6%A7%B8%B6%20%B2%E2%CA%D4&order_price=0.01這串字符串中,包含了調用微信支付接口所需的所有的參數。核心代碼通過使用這些參數,就可以成功調用微信客戶端完成支付。

wKiom1YXcHuwM8O0AAGTFkkSEdM479.jpg


     微信支付提供的官方文檔:

     統一下單,獲取預支付ID:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1

     調起支付接口,調起手機微信客戶端:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_12&index=2


     通過上面的描述,童鞋們明白了簽名、下單、調用微信支付調用的原理和代碼實現了沒?



     三、代碼實現微信支付


     通過上面的描述,我們可以得知一下幾點:


   (0)在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 函數中添加以下代碼://向微信註冊  [WXApi registerApp:APP_ID withDescription:@"demo 2.0"];


   (1)調用微信支付前,需要下單、簽名等操作,以便獲取微信支付所必要的參數。爲了提高安全性,下單、簽名操作一般是在後臺完成

   參數包括:appid、partid(商戶號)、prepayid(預支付訂單ID)、noncestr(參與簽名的隨機字符串)、timestamp(參與簽名的時間戳)、sign(簽名字符串)

   


   (2)APP端獲取後臺的參數數據,調用一下的核心代碼,調起微信支付

//調起微信支付
        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"];
        
        [WXApi sendReq:req];



   (3)筆者提供一段親測成功的核心代碼,演示如何後臺獲取參數,調起微信支付:

    //請求網絡數據
    [[TDNetworkingHelper sharedInstane] postRequestWithPath:[NSString stringWithFormat:@"%@%@", BASE_URL, orders_pay_wxpay_sign] parameter:paramDic whenSuccessed:^(id json) {
        
        if ([[json objectForKey:@"code"] integerValue]==1)   //數據獲取成功
        {
            //調用微信支付
            [self sendWeChatReqWithOrderData:[json objectForKey:@"data"]];
        }
        else        //獲取失敗
        {
            ALERT([json objectForKey:@"msg"]);
        }
        
        [self hideHub];
        self.view.userInteractionEnabled = true;
        
    } whenFailed:^(NSError *error) {
        [self hideHub];
        self.view.userInteractionEnabled = true;
        //判斷網絡狀態
        [self judgeNetworkStaus];
    }];
    
    
 -(void)sendWeChatReqWithOrderData:(NSDictionary*)orderData
  {
      NSLog(@"提交的參數:%@", orderData);
        
      //調起微信支付
      PayReq* req             = [[PayReq alloc] init];
      req.openID              = [orderData objectForKey:@"appid"];
      req.partnerId           = [orderData objectForKey:@"partnerid"];
      req.prepayId            = [orderData objectForKey:@"prepayid"];
      req.nonceStr            = [orderData objectForKey:@"noncestr"];
      req.timeStamp           = (UInt32)[[orderData objectForKey:@"timestamp"] integerValue];
      req.package             = [orderData objectForKey:@"package"];
      req.sign                = [orderData objectForKey:@"sign"];
      [WXApi sendReq:req];
  }



     五、無法完成微信支付的各種異常狀態分與處理

     筆者在開發過程中,也遇到過不少的異常狀態,現記錄如下:


     (1)無法調起手機微信客戶端、無法調起微信客戶端頁面,一閃而過

     原因分析:第一種如果您的APP集成了友盟或者shareSDK的第三方分享SDK,會導致WechaSDK包的重複衝突;

     處理方法:刪除友盟或者shareSDK裏面的WechaSDK包;在調用微信支付接口的文件裏,後綴改爲 .mm


     (2)中間只有一個確定按鈕,點擊按鈕,返回APP,提示 “支付結果:失敗!retcode=-2,retstr=nil ”

     原因分析:到這裏,說明代碼沒有問題,是傳遞的參數有問題,任何一個參數出錯都可能導致這樣的問題。

     處理方法:與後臺完成簽名、下單的同事溝通,檢查後臺的代碼。

    備註:我就是卡在這裏兩個多星期,後來檢查發現是後臺同事在簽名的時候出現了問題。微信支付要求有兩次簽名,第二次需要timestamp(時間戳)參與簽名。我們只有一次簽名,一直沒法調起支付界面



     希望這篇可以幫到你,讓你少走彎路。

     對以上內容有任何疑問的童鞋,請留言指教!




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章