概述
詳細
一、項目結構與前言
首先看下整體框架
如果我們項目中已經導入了友盟的SDK,那么我們就不必在導入微信 支付寶官方的SDK。
在使用友盟SDK時我們會遇到各種各樣的問題,報錯,例如:#import <UMSocialCore/UMSocialCore.h> not found #import <AlipaySDK/AlipaySDK.h> not found這一類報錯的話,一般都是我們的地址不對,只需要在TARGETS-Build Settings - Header Search Paths里面修改找不到的類的地址就好。
在我們對接微信支付的時候解析XMl文件時報錯ARC 文件提前 釋放時 我們需要在Buils Phases - Compile Sources 里面的集體的某個控制器或者類的后面添加-fno-objc-arc字段。
支付寶支付存在APP支付和網頁支付,微信支付只有App支付,
進行支付功能的集成 我們需要在項目中配置它的一些參數。
我們分享的View可以添加到任何位置,並不局限與下方。
分享的話有微信好友 朋友圈 QQ 空間 微博的分享,為了防止蘋果審核被拒,友盟已經為我們做好了顯示我們手機安裝的可分享的第三方。
#pragma mark - 判斷平台是否安裝 - (BOOL)gz_UMSocialIsInstall:(UMSocialPlatformType)platformType { return [GZUMSocialData isInstall:platformType]; }
友盟分享也為我們提供了多種分享模式,純文本 ,帶圖片文 ,純圖片 ,一般的分享是這種,title、content、縮略圖、URL , 文本 + 圖片【暫時只對新浪分享有效】 ,音樂 ,視頻 ,gif 動圖等等,完全可以滿足我們的需求。
支付方面的問題絕大多數出現在回調函數這塊,我們只要按照每個平台的官方文檔進行書寫,一般不會出什么大的問題。
二、准備工作
1、集成微信支付首先需要注冊(https://open.weixin.qq.com )注冊完成后我們選擇移動應用,創建移動應用,信息自己填寫, 最后我們需要申請支付功能,這個是需要交money的(300/年)成功后我們需要有一個商戶帳號與之對接,最后就是協議簽署,這樣微信支付大功告成。
2、支付寶支付需要用戶進螞蟻金服官網注冊帳號,來獲取支付功能,同樣它和微信一樣每年300元的費用。
三、程序設計與實現
首先我們介紹我微信支付,微信公眾平台有多種支付方式,我們選擇的是App支付,集成微信支付按照微信文檔進行下載SDK,
適用於商戶在移動端APP中集成微信支付功能。
商戶APP調用微信提供的SDK調用微信支付模塊,商戶APP會跳轉到微信中完成支付,支付完后跳回到商戶APP內,最后展示支付結果。
步驟1:用戶進入商戶APP,選擇商品下單、確認購買,進入支付環節。商戶服務后台生成支付訂單,簽名后將數據傳輸到APP端。以微信提供的DEMO為例。
步驟2:用戶點擊后發起支付操作,進入到微信界面,調起微信支付,出現確認支付界面。
步驟3:用戶確認收款方和金額,點擊立即支付后出現輸入密碼界面,可選擇零錢或銀行卡支付。
現在的微信支付SDK應該是在Xcode6的基礎上,
1、項目設置APPID
商戶在微信開放平台申請開發APP應用后,微信開放平台會生成APP的唯一標識APPID。在Xcode中打開項目,設置項目屬性中的URL Schemes為您的APPID。
我們需要在info-URL Types 中填寫商戶自己的AppID
要想能i進行支付,我們還需要微信注冊我們的APPID
//微信支付 [WXApi registerApp:GZWX_APP_KEY]; 3、調起支付 商戶服務器生成支付訂單,先調用【統一下單API】生成預付單,獲取到prepay_id后將參數再次簽名傳輸給APP發起支付。以下是調起微信支付的關鍵代碼: 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];
我們需要注意的是,微信支付它的單位是以分來計算的,所以我們集成時,注意下這塊!
- ( NSMutableDictionary *)sendPay_OrderName:(NSString *)ProductName PayPrice:(NSString *)PriductPrice;{ //訂單標題,展示給用戶 NSString *order_name = ProductName; //訂單金額,單位(分) // NSString *order_price = PriductPrice ; NSString *order_price = [NSString stringWithFormat:@"%d",[PriductPrice intValue]];//1分錢測試
對於這塊,因為ARC的緣故我們需要在Build Phases - Compile Sources中添加 -fno-objc-arc
調起微信支付 -(void)ByWeiXinBuy{ [self weXinAplyPayOrderName:@"剛子支付Demo" PayPrice:@"1"]; } #pragma mark--微信支付 -(void)weXinAplyPayOrderName:(NSString *)OrderName PayPrice:(NSString *)PayPrice{ if (![WXApi isWXAppInstalled]) { [self.view gz_showAlertView:@"溫馨提示" message:@"未檢測到客戶端,請安裝"]; }else{ //創建支付簽名對象 payRequsestHandler *req = [payRequsestHandler alloc]; //初始化支付簽名對象 [req init:APP_ID mch_id:MCH_ID]; //設置密鑰 [req setKey:PARTNER_ID]; //獲取到實際調起微信支付的參數后,在app端調起支付 NSMutableDictionary *dict = [req sendPay_OrderName:OrderName PayPrice:PayPrice]; if(dict == nil){ //錯誤提示 NSString *debug = [req getDebugifo]; [self.view gz_showAlertView:@"提示信息" message:debug]; }else{ [self sendRepweixin:dict];//提交支付 } } } -(void)sendRepweixin:(NSDictionary *)dict{ NSMutableString *stamp = [dict objectForKey:@"timestamp"]; //調起微信支付 PayReq* req = [[PayReq alloc] init]; 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]; }
2、支付寶支付
首先在螞蟻金服創建帳號申請分享 支付功能 (300RMB)
集成支付寶支付,將在官網下載的SDK導入到項目中
在Build Phases選項卡的Link Binary With Libraries中,增加以下依賴:
其中,需要注意的是:
-
如果是Xcode 7.0之后的版本,需要添加libc++.tbd、libz.tbd;
-
如果是Xcode 7.0之前的版本,需要添加libc++.dylib、libz.dylib
-(void)buyproduct{ //四美坊app商戶ID 用戶ID 私鑰 NSString *pid = @"2088421263479877"; NSString *appID = @"2016092201949956"; NSString *privateKey = @"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALhNuoy6DrIF27wxQXT1JarZIhCleLbGZIKi/xLGb0KMP6m9xP17GJ0asqhDqIPQOos2vmwmeA8ast2gQQWzbtaKMyqsrxQgrlTvYomwo3579JwOS29wgpjAWn2YQ9t3YGlECpFtoX3KtyJ7JPhtTcfJqPpHiNFjujmPCU83s9qJAgMBAAECgYAw4y1gttm/Dx7CRK6AP6bGMuJ+V+Y1VVrD7EiMymYo2NrqQ5RFSKm2wqYxTAEfNdTRqKvKNEoUd5iKgT++K2JywugECubbv/2hSzUqsr1VhQ/buzIwSTTPFJHrG2WSL+c8hqgsxk3Fn79vKarRnPdYj7r+7xZ43uwfxx/mzaXnoQJBANtyF6P8vjJLazCwrX+bg7CS447c/38Nsai6CTOr4GyvEzd+sIUkFahTGzk83qBdU4ksMGfGrv7Bwvk5X2c4AcMCQQDXAQ9067qOtGsWXiDgNqDe2+CgNotXwhBOKGlbv3t9xYi89K2u9hqIz3yUWBbbxOaolCJvpFREJV4mmtXQiEHDAkEAr1tijMZg7ivaQhRM8FXDTAx1DyqGeG7m8t+GjuXf9rmIb6YrRJlrPRD8Bicf96HcKRdIrwTTvfvz49f25rKYpQJBAK+OvRlCdlWZ+isMdxm9YYQ30+XeQ89Htdqr4sO4ydQ73Fg2Di/j4my9x0K13wxabeFO/ANfEjOGs6cgHOCmsdMCQQCNyYE6MloO1xaHkFIRuzMjUJB94Wkaip/DzZE5a/vIsm6mk6JcaPDCGAm2yf2xd6f/1y0WViaSLv6jLcdwZCZ8"; //pid和appID獲取失敗,提示 if ([pid length] == 0 || [appID length] == 0 || [privateKey length] == 0) { [self.view gz_showAlertView:@"提示" message:@"缺少pid或者appID或者私鑰。"]; return ; } /* *生成訂單信息及簽名 */ Order* order = [Order new]; //將商品信息賦予AlixPayOrder的成員變liang // NOTE: app_id設置 order.app_id = appID; order.notify_url = @"http://www.88meichou.com/api/alipay/alipay.php"; order.biz_content.seller_id = pid ; // NOTE: 支付接口名稱 order.method = @"alipay.trade.app.pay"; // NOTE: 參數編碼格式 order.charset = @"utf-8"; // NOTE: 當前時間點 NSDateFormatter* formatter = [NSDateFormatter new]; [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; order.timestamp = [formatter stringFromDate:[NSDate date]]; // NOTE: 支付版本 order.version = @"1.0"; // NOTE: sign_type設置 order.sign_type = @"RSA"; // NOTE: 商品數據 order.biz_content = [BizContent new]; order.biz_content.body = @"剛子支付Demo"; order.biz_content.subject = [NSString stringWithFormat:@"購買%@美豆",@"1"]; order.biz_content.out_trade_no = order_sn ; // order.biz_content.out_trade_no = [self generateTradeNO]; //訂單ID(由商家自行制定) order.biz_content.timeout_express = @"30m"; //超時時間設置 // order.biz_content.total_amount = [NSString stringWithFormat:@"%.2f",0.01]; order.biz_content.total_amount = [NSString stringWithFormat:@"%@", @"0.1"]; //商品價格 //將商品信息拼接成字符串 NSString *orderInfo = [order orderInfoEncoded:NO]; NSString *orderInfoEncoded = [order orderInfoEncoded:YES]; // NSLog(@"orderSpec = %@",orderInfo); // NOTE: 獲取私鑰並將商戶信息簽名,外部商戶的加簽過程請務必放在服務端,防止公私鑰數據泄露; // 需要遵循RSA簽名規范,並將簽名字符串base64編碼和UrlEncode id<DataSigner> signer = CreateRSADataSigner(privateKey); NSString *signedString = [signer signString:orderInfo]; // NOTE: 如果加簽成功,則繼續執行支付 if (signedString != nil) { //應用注冊scheme,在AliSDKDemo-Info.plist定義URL types NSString *appScheme = @"ap2016092201949956"; // NOTE: 將簽名成功字符串格式化為訂單字符串,請嚴格按照該格式 NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@", orderInfoEncoded, signedString]; // NSLog(@"~~~~~~~~~~~!!~~~~~~~~~~%@",orderString);簽名 // NOTE: 調用支付結果開始支付 [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) { // NSLog(@"reslut = %@",resultDic); NSString * str = resultDic[@"memo"]; // NSLog(@"~~~~~!!~~%@",str); NSString *result = resultDic[@"resultStatus"]; if ([result isEqualToString:@"9000"]) { #pragma 回掉函數 } }]; } }
回調的話我們在最后給出 ,因為他們可以寫在一個方法中
3、友盟分享 統計
注冊友盟帳號,
UMConfigInstance.appKey = GZUmengAppkey ; UMConfigInstance.channelId = @"App Store" ; [MobClick startWithConfigure:UMConfigInstance];開啟統計
NSString *appVersion = [NSString stringWithFormat:@"2、獲取APP的版本號:%@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]; [MobClick setAppVersion:appVersion]; //對統計數據進行加密 [MobClick setEncryptEnabled:YES]; 分享的話 我做了一個分類,這樣顯得AppDelegate里面不是那么的亂。
#pragma mark - ***** 友盟分享 - (void)addShareOpt { GZShareManage *manager = [GZShareManage shareManage]; [manager gz_setupShareConfig]; #import <Foundation/Foundation.h> #import <UMSocialCore/UMSocialCore.h> #import <MessageUI/MessageUI.h> @protocol GZShareManageDelegate <NSObject> /*! 返回用戶信息 */ - (void)getUserData:(NSDictionary *)backUserData; @end typedef NS_ENUM(NSUInteger, GZUM_SHARE_TYPE) { /*! 純文本 */ GZUM_SHARE_TYPE_TEXT = 1, /*! 純圖片:本地圖片 */ GZUM_SHARE_TYPE_IMAGE, /*! 純圖片:網絡圖片 URL */ GZUM_SHARE_TYPE_IMAGE_URL, /*! 網頁:一般的分享是這種,title、content、縮略圖、URL */ GZUM_SHARE_TYPE_WEB_LINK, /*! 文本 + 圖片 【暫時只對新浪分享有效】 */ GZUM_SHARE_TYPE_TEXT_IMAGE, /*! 音樂 */ GZUM_SHARE_TYPE_MUSIC_LINK, /*! 視頻 */ GZUM_SHARE_TYPE_VIDEO_LINK, /*! gif 動圖【注:目前只有微信支持動圖分享,其他平台均不支持】*/ GZUM_SHARE_TYPE_GIF, /*! 文件【注:目前只有微信支持動圖分享,其他平台均不支持】 */ GZUM_SHARE_TYPE_FILE }; /*! 登錄后返回的數據回調 */ typedef void (^GZUMLoginCallback)(UMSocialUserInfoResponse *response); @interface GZShareManage : NSObject /*! 登錄后返回的數據回調 */ @property (nonatomic, copy) GZUMLoginCallback loginCallback; /*! 分享標題 */ @property (nonatomic, strong) NSString *shareTitle; /*! 分享摘要 */ @property (nonatomic, strong) NSString *shareText; /*! 分享大圖【本地 imageName】】 */ @property (nonatomic, strong) NSString *shareBigImage; /*! 分享 URL 圖片 */ @property (nonatomic, strong) NSString *shareImageUrl; /*! 分享網頁 */ @property (nonatomic, strong) NSString *shareWebpageUrl; /*! 分享音樂 URL【必傳】 */ @property (nonatomic, strong) NSString *shareMusicUrl; /*! 分享音樂 DataUrl */ @property (nonatomic, strong) NSString *shareMusicDataUrl; /*! 分享視頻 URL */ @property (nonatomic, strong) NSString *shareVideoUrl; /*! 分享 gif 動圖路徑 */ @property (nonatomic, strong) NSString *shareGifFilePath; /*! 分享文件路徑 */ @property (nonatomic, strong) NSString *shareFileFilePath; /*! 分享文件后綴類型 */ @property (nonatomic, strong) NSString *shareFileFileExtension; /*! 授權回調 */ @property (nonatomic, strong) void (^authOpFinish)(); @property (nonatomic, strong) id<GZShareManageDelegate> delegate; /*! 圖片數組 */ @property (nonatomic, strong) NSArray *shareImageArray; /*! 分享的名字數組(要和圖片名字一一對應哦!) */ @property (nonatomic, strong) NSArray *shareNameArray; //// 友盟分享SDK的各種key設置【pod下來后只需調用下即可】 //@property (nonatomic, strong) NSString *GZShareUmengAppkey; //@property (nonatomic, strong) NSString *GZShareSinaAppKey; //@property (nonatomic, strong) NSString *GZShareWX_APP_KEY; //@property (nonatomic, strong) NSString *GZShareWX_APP_SECRET; //@property (nonatomic, strong) NSString *GZSharekQQKey; //@property (nonatomic, strong) NSString *GZSharekQQAppID; + (GZShareManage *)shareManage; /*! * 友盟分享設置 */ - (void)gz_setupShareConfig; /*! * 判斷平台是否安裝 * * @param platformType 平台類型 @see UMSocialPlatformType * * @return YES 代表安裝,NO 代表未安裝 * @note 在判斷QQ空間的App的時候,QQApi判斷會出問題 */ - (BOOL)gz_UMSocialIsInstall:(UMSocialPlatformType)platformType; #pragma mark - 友盟分享 version 2.1 /*! 微信分享 */ #pragma mark 微信分享 version 2.1 - (void)gz_wechatShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark 微信朋友圈分享 version 2.1 - (void)gz_wechatTimeLineShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark 新浪微博分享 version 2.1 - (void)gz_sinaShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark qq分享 version 2.1 - (void)gz_qqShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark Qzone分享 version 2.1 - (void)gz_qZoneShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark - 友盟分享 /*! * 剛子友盟分享列表 version 2.1 * * @param shareType 分享類型,具體看枚舉 * @param viewController viewController */ - (void)gz_shareListWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark - 友盟登錄 #pragma mark 微信登錄 version 2.1 - (void)gz_wechatLoginWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:(BOOL)isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark QQ登錄 version 2.1 - (void)gz_qqLoginWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:(BOOL)isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark QQZone登錄 version 2.1 - (void)gz_qZoneLoginWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:(BOOL)isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark 微博登錄 version 2.1 - (void)gz_sinaLoginWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:(BOOL)isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark - 友盟登錄列表 version 2.1 /*! * 友盟登錄列表 version 2.1 * * @param viewController viewController description * @param isGetAuthWithUserInfo YES:授權並獲取用戶信息(獲取uid、access token及用戶名等) NO:只需獲取第三方平台token和uid,不獲取用戶名等用戶信息,可以調用以下接口 * @param loginCallback 登錄后返回的數據回調 */ - (void)gz_loginListWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:(BOOL)isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark - 清除授權 - (void)gz_cancelAuthWithPlatformType:(UMSocialPlatformType)platformType; @end }
以下為微信支付寶支付成功回調 友盟分享回調!
// NOTE: 9.0以后使用新API接口 - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options { if ([url.host isEqualToString:@"safepay"]) { // 支付跳轉支付寶錢包進行支付,處理支付結果 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { // NSLog(@"result = %@",resultDic); [[NSNotificationCenter defaultCenter]postNotificationName:@"alipayResult" object:[resultDic objectForKey:@"resultStatus"]]; }]; return YES ; }else if ([url.host isEqualToString:@"pay"]) { return [WXApi handleOpenURL:url delegate:self]; }else{ return [[UMSocialManager defaultManager] handleOpenURL:url]; } } /** 這里處理新浪微博SSO授權之后跳轉回來,和微信分享完成之后跳轉回來 */ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { if ([url.host isEqualToString:@"safepay"]) { // 支付跳轉支付寶錢包進行支付,處理支付結果 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { // NSLog(@"result = %@",resultDic); [[NSNotificationCenter defaultCenter]postNotificationName:@"alipayResult" object:[resultDic objectForKey:@"resultStatus"]]; }]; return YES ; }else if ([url.host isEqualToString:@"pay"]) { return [WXApi handleOpenURL:url delegate:self]; }else{ return [[UMSocialManager defaultManager] handleOpenURL:url]; } } - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { if ([url.host isEqualToString:@"safepay"]) { // 支付跳轉支付寶錢包進行支付,處理支付結果 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { [[NSNotificationCenter defaultCenter]postNotificationName:@"alipayResult" object:[resultDic objectForKey:@"resultStatus"]]; }]; return YES ; }else if ([url.host isEqualToString:@"pay"]) { return [WXApi handleOpenURL:url delegate:self]; }else{ return [[UMSocialManager defaultManager] handleOpenURL:url]; } } //微信支付結果 - (void) onResp:(BaseResp*)resp { [[NSNotificationCenter defaultCenter] postNotificationName:@"weixinPay" object:resp];
四、運行效果
效果圖如下:
由於項目過大不能整體上傳的平台 ,所以一些包文件請移步百度網盤進行下載,地址上面有!
注:本文著作權歸作者,由demo大師發表,拒絕轉載,轉載需要作者授權