iOS 不用微信 SDK 唤起微信支付
Lou4523
8年前
<h2><strong>要想知道微信SDK是如何调起微信客户端,那么咱们先看看微信SDK到底做了什么</strong></h2> <h2><strong>SDK集成流程</strong></h2> <ol> <li>将解压的微信OpenSDK文件夹拷贝到项目文件夹下,并导入开发环境中。 libWeChatSDK.a<br> WechatAuthSDK.h<br> WXApi.h<br> WXApiObject.h</li> </ol> <h2><strong>导入系统依赖库</strong></h2> <p>在link Binary With Libraries 里面添加</p> <p>libc++.tbd<br> CoreTelephony.framework<br> libsqlite3.0.tbd<br> libz.tbd<br> SystemConfiguration.framework</p> <p>还有之前导入的 libWeChatSDK.a</p> <p>到这一步,SDK集成已经完毕</p> <h2><strong>配置代码</strong></h2> <ul> <li> <p>添加URL Schemes</p> <p>点击项目名称,点击“Info”选项卡,在“URL Types”选项中,点击“+”, 在“URL Schemes”中输入微信的注册码</p> </li> </ul> <p><img src="https://simg.open-open.com/show/441e1917c8dfc2c8905991d9818e2b44.png"></p> <p>c1000</p> <ul> <li>在支付的类里引用头文件:</li> </ul> <pre> <code class="language-objectivec">#import "WXApi.h" </code></pre> <ul> <li>配置wxpay支付</li> </ul> <pre> <code class="language-objectivec">#pragma mark ==============配置wxpay支付============== - (void)payAction{ //发起网络请求,去你们服务器请求1.订单id,2. 钱(单位:分),3. 内容描述 //订单最好服务器生成,本文为了各位看的明白,所以在本地生成! [NetWorkTooldingiD:[self generateTradeNO]andDetail:@"描述"success:^(NSDictionary *responseObject) { //服务器返回数据 //调起微信支付 PayReq* wxreq = [[PayReq alloc]init]; /** appid */ wxreq.openID = responseObject[@"result"][@"appid"]; /** 商家向财付通申请的商家id */ wxreq.partnerId = responseObject[@"result"][@"partnerid"]; /** 预支付订单 */ wxreq.prepayId = responseObject[@"result"][@"prepayid"]; /** 随机串,防重发 */ wxreq.nonceStr = responseObject[@"result"][@"noncestr"]; /** 时间戳,防重发 */ wxreq.timeStamp = [responseObject[@"result"][@"timestamp"]intValue]; /** 商家根据财付通文档填写的数据和签名 */ wxreq.package = responseObject[@"result"][@"package"]; /** 商家根据微信开放平台文档对数据做的签名 */ wxreq.sign = responseObject[@"result"][@"sign"]; [WXApisendReq:wxreq]; }failure:^(NSError *error) { NSLog(@"%@",error); }]; } #pragma mark ==============产生随机订单号============== - (NSString *)generateTradeNO { static int kNumber = 15; NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; NSMutableString *resultStr = [[NSMutableString alloc]init]; srand((unsigned)time(0)); for (int i = 0; i < kNumber; i++) { unsigned index = rand() % [sourceStrlength]; NSString *oneStr = [sourceStrsubstringWithRange:NSMakeRange(index, 1)]; [resultStrappendString:oneStr]; } return resultStr; } </code></pre> <ul> <li>配置返回处理代码</li> </ul> <p>在 AppDelegate.h 文件中,增加微信协议:</p> <pre> <code class="language-objectivec">#import "WXApi.h" @interface AppDelegate : UIResponder <UIApplicationDelegate,WXApiDelegate> </code></pre> <p>在 AppDelegate.m 文件中,增加引用代码:</p> <pre> <code class="language-objectivec">- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 初始化微信sdk [WXApiregisterApp:@"wx*********"]; return YES; } - (BOOL)application:(UIApplication *)applicationopenURL:(NSURL *)urlsourceApplication:(NSString *)sourceApplicationannotation:(id)annotation { /*! @brief 处理微信通过URL启动App时传递的数据 * * 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。 * @param url 微信启动第三方应用时传递过来的URL * @param delegate WXApiDelegate对象,用来接收微信触发的消息。 * @return 成功返回YES,失败返回NO。 */ return [WXApihandleOpenURL:urldelegate:self]; } - (void)onResp:(BaseResp *)resp { //支付返回结果,实际支付结果需要去微信服务器端查询 NSString *strMsg = [NSStringstringWithFormat:@"支付结果"]; switch (resp.errCode) { caseWXSuccess: strMsg = @"支付结果:成功!"; NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode); break; default: strMsg = [NSStringstringWithFormat:@"支付结果:失败!retcode = %d, retstr = %@", resp.errCode,resp.errStr]; NSLog(@"错误,retcode = %d, retstr = %@", resp.errCode,resp.errStr); break; } } </code></pre> <h2><strong>不用微信SDK 唤起微信支付</strong></h2> <ol> <li>众所周知,iOS是一个封闭的系统,应用之间是不可以互相读取文件的,苹果就使用了URL Scheme来实现了这个功能。通过各个APP设计的符合苹果的统一规范的URL Scheme,Url Scheme 是可以用来传递信息的 <p>URL Scheme是为方便app之间互相调用而设计的。你可以通过一个类似URL的链接,通过系统的OpenURl来打开该app,并可以传递一些参数。每个URL必须能唯一标识一个APP,如果你设置的URL与别的APP的URL冲突,此时,你的APP不一定会被调用起来,原因是当APP在安装的时候就已经在系统里面注册了此APP的URL Scheme,如果你的一致但是是后安装的,那么系统不会调用你的APP,因为你的APP设置的URL scheme被覆盖了。</p> </li> <li>分析得出,微信,支付宝等sdk 的分享,支付功能,都是通过URL scheme 进行传递内容的</li> <li>那么我们可以查看微信SDK唤起微信客服端支付的时候,传递的URL Scheme 是什么内容,如果可以找到其编码规律,那么即可以不用sdk进行支付</li> </ol> <p>那么,发起支付的过程中,系统会唤起微信客户端,我们思路是查看微信sdk发送给微信客户端的URL Scheme内容,就要伪造一个微信,也就是向系统声明一个和微信URL Scheme相同的地址</p> <h2><strong>查看微信URL Scheme地址</strong></h2> <p>经测试: <strong>微信的URL Scheme是:weixin://</strong></p> <p>那么,我们新建个工程,起名为:GetPayURLScheme</p> <p>接着注册自定义 URL Scheme</p> <p>点击 项目里info.plist (非test里面的info.plist)并选择 右键 Open As – Source Code:加入:</p> <pre> <code class="language-objectivec"><key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>weixin</string> </array> <key>CFBundleURLName</key> <string>1111</string> </dict> </array> </code></pre> <p>这时候,点击 项目里info.plist (非test里面的info.plist)并选择 右键 Open As – list:</p> <p>这样就生成了如下图的URLscheme:</p> <p><img src="https://simg.open-open.com/show/ab62f2afeec02b03beff6fb33e4fde6b.png"></p> <p>c1000</p> <p>在 AppDelegate.m 里面添加</p> <pre> <code class="language-objectivec">//应用app接收urlScheme传值时会响应此方法 - (BOOL)application:(UIApplication *)applicationopenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplicationannotation:(id)annotation{ //显示截取的urlscheme UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"接收到的urlScheme"message:url.absoluteStringdelegate:nilcancelButtonTitle:nilotherButtonTitles:@"确定", nil]; [alertshow]; 复制到剪贴板 UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; pasteboard.string = url.absoluteString; return YES; } </code></pre> <p>运行到手机里面,这时候,你无论那个app要微信付款的时候,唤起的是刚才新建的名叫GetPayURLScheme工程 ,如下图:</p> <p><img src="https://simg.open-open.com/show/5fd4a06cf222fef36a9920b1ad94698b.png"></p> <p><img src="https://simg.open-open.com/show/7c3199178edf4c921f94ce1e2210127b.png"></p> <p>可以看到:那个urlScheme:</p> <pre> <code class="language-objectivec">weixin://app/wxdf261c3b90ffbc25/pay/?nonceStr=Ho7nAFOALQpVqSM7&package=Sign%3DWXPay&partnerId=1236537302&prepayId=wx201606052201506009de63980169148758&timeStamp=1465135310&sign=5A3EF234382FD61D36CEC104723387ED&signType=SHA1 </code></pre> <p>可以看出:它的拼接方法是:</p> <pre> <code class="language-objectivec">NSString *str = [NSStringstringWithFormat:@"weixin://app/%@/pay/?nonceStr=%@&package=Sign%%3DWXPay&partnerId=%@&prepayId=%@&timeStamp=%@&sign=%@&signType=SHA1",appid,noncestr,partnerid,prepayid,[NSStringstringWithFormat:@"%d",[timestampintValue]],sign]; </code></pre> <h2><strong>不用SDK,只需要配置这么一段代码,微信支付即可完成!!!!!!!!</strong></h2> <pre> <code class="language-objectivec">- (void)payAction{ //发起网络请求,去你们服务器请求1.订单id,2. 钱(单位:分),3. 内容描述 //订单最好服务器生成,本文为了各位看的明白,所以在本地生成! [NetWorkTooldingiD:[self generateTradeNO]andDetail:@"描述"success:^(NSDictionary *responseObject) { /** appid */ NSString *appid = responseObject[@"result"][@"appid"]; /** 商家向财付通申请的商家id */ NSString *partnerId = responseObject[@"result"][@"partnerid"]; /** 预支付订单 */ NSString *prepayId = responseObject[@"result"][@"prepayid"]; /** 随机串,防重发 */ NSString *nonceStr = responseObject[@"result"][@"noncestr"]; /** 时间戳,防重发 */ NSString *timeStamp = responseObject[@"result"][@"timestamp"]; /** 商家根据财付通文档填写的数据和签名 */ NSString *package = responseObject[@"result"][@"package"]; /** 商家根据微信开放平台文档对数据做的签名 */ NSString *sign = responseObject[@"result"][@"sign"]; //生成URLscheme NSString *str = [NSStringstringWithFormat:@"weixin://app/%@/pay/?nonceStr=%@&package=Sign%%3DWXPay&partnerId=%@&prepayId=%@&timeStamp=%@&sign=%@&signType=SHA1",appid,nonceStr,partnerId,prepayId,[NSStringstringWithFormat:@"%d",[timeStampintValue] ],sign]; //通过openURL的方法唤起支付界面 [[UIApplication sharedApplication]openURL:[NSURLURLWithString:str]]; }failure:^(NSError *error) { NSLog(@"%@",error); }]; } </code></pre> <p><img src="https://simg.open-open.com/show/4a48fc71e99f5451f68751bc01aa3d4a.png"></p> <p> </p> <p> </p> <p>来自:http://ios.jobbole.com/85793/</p> <p> </p>