├── .gitignore ├── Documents └── imgs │ ├── link │ ├── target_dependence │ └── urlschema ├── Frameworks └── QQWalletSDK.framework │ ├── Headers │ ├── QQWalletSDK │ ├── Resources │ └── Versions │ ├── A │ ├── Headers │ │ ├── QQWalletDefines.h │ │ ├── QQWalletSDK.h │ │ └── QWMessage.h │ ├── QQWalletSDK │ └── Resources │ │ ├── Info.plist │ │ ├── en.lproj │ │ └── InfoPlist.strings │ │ └── readme.markdown │ └── Current ├── LICENSE ├── QQWalletSDK.podspec ├── QQWalletSDK.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── QQWalletSDK.xccheckout │ └── xcuserdata │ │ └── stonedong.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── stonedong.xcuserdatad │ └── xcschemes │ ├── Document.xcscheme │ ├── QQWalletSDK.xcscheme │ └── xcschememanagement.plist ├── QQWalletSDK ├── Classes │ ├── Base64.h │ ├── Base64.m │ ├── connects │ │ ├── QWApplication.h │ │ ├── QWApplication.m │ │ ├── QWURLEncodeEngine.h │ │ └── QWURLEncodeEngine.m │ ├── objc │ │ ├── SBJson4.h │ │ ├── SBJson4Parser.h │ │ ├── SBJson4Parser.m │ │ ├── SBJson4StreamParser.h │ │ ├── SBJson4StreamParser.m │ │ ├── SBJson4StreamParserState.h │ │ ├── SBJson4StreamParserState.m │ │ ├── SBJson4StreamTokeniser.h │ │ ├── SBJson4StreamTokeniser.m │ │ ├── SBJson4StreamWriter.h │ │ ├── SBJson4StreamWriter.m │ │ ├── SBJson4StreamWriterState.h │ │ ├── SBJson4StreamWriterState.m │ │ ├── SBJson4Writer.h │ │ └── SBJson4Writer.m │ ├── sdk │ │ ├── QQWallet.h │ │ ├── QQWallet.m │ │ ├── QWPayTask.h │ │ ├── QWPayTask.m │ │ ├── QWPayment.h │ │ ├── QWPayment.m │ │ ├── QWProduct.h │ │ ├── QWProduct.m │ │ ├── QWServerPayTask.h │ │ ├── QWServerPayTask.m │ │ ├── QWTask.h │ │ ├── QWTask.m │ │ └── needsDoc │ │ │ ├── QQWalletDefines.h │ │ │ ├── QQWalletDefines.m │ │ │ ├── QQWalletSDK.h │ │ │ ├── QQWalletSDK.m │ │ │ ├── QWMessage.h │ │ │ └── QWMessage.m │ └── tools │ │ ├── LoadAbleCategory.h │ │ ├── NSDate+StringFormatter.h │ │ └── NSDate+StringFormatter.m ├── QQWalletSDK-Info.plist ├── QQWalletSDK-Prefix.pch └── en.lproj │ └── InfoPlist.strings ├── QQWalletSDKTests ├── QQWalletSDKTests-Info.plist ├── QQWalletSDKTests.m └── en.lproj │ └── InfoPlist.strings ├── readme.markdown └── updatePods.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # CocoaPods 2 | # 3 | # We recommend against adding the Pods directory to your .gitignore. However 4 | # you should judge for yourself, the pros and cons are mentioned at: 5 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control? 6 | # 7 | # Pods/ 8 | 9 | -------------------------------------------------------------------------------- /Documents/imgs/link: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentWallet/QQWalletSDK/778ec14fa459ce9cf05cced2973e43027e229ca4/Documents/imgs/link -------------------------------------------------------------------------------- /Documents/imgs/target_dependence: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentWallet/QQWalletSDK/778ec14fa459ce9cf05cced2973e43027e229ca4/Documents/imgs/target_dependence -------------------------------------------------------------------------------- /Documents/imgs/urlschema: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentWallet/QQWalletSDK/778ec14fa459ce9cf05cced2973e43027e229ca4/Documents/imgs/urlschema -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/QQWalletSDK: -------------------------------------------------------------------------------- 1 | Versions/Current/QQWalletSDK -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Versions/A/Headers/QQWalletDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // QQWalletDefines.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define DEFINE_EXTERN_STRING(key) extern NSString* const k##key 12 | 13 | 14 | /** 15 | * 代表QQWallet出错的域名 16 | */ 17 | extern NSString* const kQWErrorDomain; 18 | 19 | /** 20 | * QQWallet出错信息 21 | */ 22 | typedef enum { 23 | /** 24 | * 未知错误,不支持 25 | */ 26 | QWErrorNotSupport = 7000, 27 | /** 28 | * 参数传递错误 29 | */ 30 | QWErrorParamsError = 8000 31 | }QWErrorCode; 32 | 33 | /** 34 | * 手机QQ唤起钱包功能使用的URL Schema 35 | */ 36 | extern NSString* const kQWURLScheme; 37 | 38 | 39 | /** 40 | * 支付时传参,用来表示单号 41 | */ 42 | extern NSString* const kQWPayParamTokenID; 43 | /** 44 | * 支付时传参,用来表示关注公共账号的提示语 45 | */ 46 | extern NSString* const kQWPayParamPubHint; 47 | /** 48 | * 支付时穿残,用来表示关注公共账号的需要关注的公共账号信息 49 | */ 50 | extern NSString* const kQWPayParamPubAccountID; 51 | 52 | 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | BOOL IsSupportQQWallet(); 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | /** 63 | * 检查当前系统环境是否支持QQWallet调用 64 | * 65 | * @return BOOL 当前系统环境是否支持QQWallet调用 66 | */ 67 | #define SystemSupportQQWallet IsSupportQQWallet() 68 | 69 | 70 | 71 | @class QWMessage; 72 | /** 73 | * 进行QQWallet操作之后的回调函数,开发者可以在这里进行,QQWallet动作完成后接受完成结果,并进行处理 74 | * 75 | * @param message 包含返回结果信息的对象 76 | * @param error 出错信息,如果出错则改信息不为空,否则为空。 77 | */ 78 | typedef void(^QQTaskCompletion)(QWMessage* message, NSError* error); 79 | 80 | 81 | -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Versions/A/Headers/QQWalletSDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // QQWalletSDK.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "QQWalletDefines.h" 11 | @class UIApplication; 12 | /** 13 | * 钱包SDK 14 | */ 15 | @interface QQWalletSDK : NSObject 16 | 17 | /** 18 | * 调起手Q进行支付,参数为从第三方APP从服务器获取的参数,透传到手机QQ内,唤起支付功能 19 | * 20 | * @param params 第三方APP下单后从无武器获取的参数 21 | * @param completion 回调的Block 22 | */ 23 | + (void) startPayWithServerParams:(NSDictionary*)params 24 | completion:(QQTaskCompletion)completion; 25 | 26 | /** 27 | * 注册第三方APP信息 28 | * 29 | * @param appId APP的唯一标识 30 | * @param urlScheme APP的URL SCHEME,用户在手机QQ内部完成功能后进行回调 31 | * @param name APP的名字 32 | */ 33 | + (void) registerQQWalletApplication:(NSString*)appId 34 | urlScheme:(NSString*)urlScheme 35 | name:(NSString*)name; 36 | 37 | /** 38 | * 在手机QQ完成功能后,进行对本APP进行回调,传递功能执行结果 39 | * 40 | * @param application 当前APP 41 | * @param url 出发回调的URL 42 | * @param sourceApplication 发起回调的APP 43 | * @param annotation nil 44 | * 45 | * @return 是否能够响应改回调 46 | */ 47 | + (BOOL) QQWalletSDKHanldeApplication:(UIApplication*)application 48 | openURL:(NSURL *)url 49 | sourceApplication:(NSString *)sourceApplication 50 | annotation:(id)annotation; 51 | @end 52 | -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Versions/A/Headers/QWMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWMessage.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "QQWalletDefines.h" 11 | 12 | DEFINE_EXTERN_STRING(QWMessageCode); 13 | DEFINE_EXTERN_STRING(QWMessageText); 14 | DEFINE_EXTERN_STRING(QWMessageInfos); 15 | 16 | /** 17 | * 代表QQWallet调用,回调信息的类 18 | */ 19 | @interface QWMessage : NSObject 20 | /** 21 | * 回调结果代号,0代表成功,其他值代表出错(并对应响应的出错信息) 22 | */ 23 | @property (nonatomic, assign) int code; 24 | /** 25 | * 回调提示信息,如果出错,则代表出错的具体错误信息 26 | */ 27 | @property (nonatomic, strong) NSString* message; 28 | /** 29 | * 按照key-value的方式存储回调结果信息 30 | */ 31 | @property (nonatomic, strong) NSDictionary* infos; 32 | 33 | - (NSDictionary*) dictionaryWithAllValues; 34 | @end 35 | -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Versions/A/QQWalletSDK: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentWallet/QQWalletSDK/778ec14fa459ce9cf05cced2973e43027e229ca4/Frameworks/QQWalletSDK.framework/Versions/A/QQWalletSDK -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentWallet/QQWalletSDK/778ec14fa459ce9cf05cced2973e43027e229ca4/Frameworks/QQWalletSDK.framework/Versions/A/Resources/Info.plist -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Versions/A/Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentWallet/QQWalletSDK/778ec14fa459ce9cf05cced2973e43027e229ca4/Frameworks/QQWalletSDK.framework/Versions/A/Resources/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Versions/A/Resources/readme.markdown: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentWallet/QQWalletSDK/778ec14fa459ce9cf05cced2973e43027e229ca4/Frameworks/QQWalletSDK.framework/Versions/A/Resources/readme.markdown -------------------------------------------------------------------------------- /Frameworks/QQWalletSDK.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /QQWalletSDK.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = "QQWalletSDK" 4 | s.version = "0.0.2" 5 | s.summary = "QQ钱包支付能力开放SDK" 6 | 7 | s.description = <<-DESC 8 | 手机Iphone,QQ钱包支付能力开放SDK。 9 | DESC 10 | 11 | s.homepage = "https://github.com/TencentWallet/QQWalletSDK" 12 | s.license = 'MIT' 13 | s.author = { "Stone Dong" => "stonedong@tencent.com" } 14 | s.platform = :ios, '5.0' 15 | s.source = { :git => "https://github.com/TencentWallet/QQWalletSDK.git", :tag => "0.0.2"} 16 | s.source_files = 'QQWalletSDK/Classes', 'QQWalletSDK/Classes/**/*.{h,m}' 17 | s.exclude_files = 'QQWalletSDK/Classes/Exclude' 18 | s.requires_arc = true 19 | 20 | end 21 | -------------------------------------------------------------------------------- /QQWalletSDK.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /QQWalletSDK.xcodeproj/project.xcworkspace/xcshareddata/QQWalletSDK.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 4FC8E1C0-9F5A-4C0C-B31B-5332D18E38F1 9 | IDESourceControlProjectName 10 | QQWalletSDK 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | D6D5F5F3-07CD-4FCD-A0CD-646EEEDF16A1 14 | https://github.com/yishuiliunian/QQWalletSDK.git 15 | 16 | IDESourceControlProjectPath 17 | QQWalletSDK.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | D6D5F5F3-07CD-4FCD-A0CD-646EEEDF16A1 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/yishuiliunian/QQWalletSDK.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | D6D5F5F3-07CD-4FCD-A0CD-646EEEDF16A1 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | D6D5F5F3-07CD-4FCD-A0CD-646EEEDF16A1 36 | IDESourceControlWCCName 37 | QQWalletSDK 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /QQWalletSDK.xcodeproj/project.xcworkspace/xcuserdata/stonedong.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentWallet/QQWalletSDK/778ec14fa459ce9cf05cced2973e43027e229ca4/QQWalletSDK.xcodeproj/project.xcworkspace/xcuserdata/stonedong.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /QQWalletSDK.xcodeproj/xcuserdata/stonedong.xcuserdatad/xcschemes/Document.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 44 | 45 | 51 | 52 | 54 | 55 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /QQWalletSDK.xcodeproj/xcuserdata/stonedong.xcuserdatad/xcschemes/QQWalletSDK.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 54 | 55 | 61 | 62 | 64 | 65 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /QQWalletSDK.xcodeproj/xcuserdata/stonedong.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Document.xcscheme 8 | 9 | orderHint 10 | 2 11 | 12 | QQWalletSDK.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 6545158F18E98F7A0008055B 21 | 22 | primary 23 | 24 | 25 | 6545159F18E98F7A0008055B 26 | 27 | primary 28 | 29 | 30 | 65C940AD1904C6DC00DFD9F3 31 | 32 | primary 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/Base64.h: -------------------------------------------------------------------------------- 1 | // 2 | // Base64.h 3 | // 4 | // Version 1.2 5 | // 6 | // Created by Nick Lockwood on 12/01/2012. 7 | // Copyright (C) 2012 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/Base64 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | #import 34 | 35 | 36 | @interface NSData (Base64) 37 | 38 | + (NSData *)dataWithBase64EncodedString:(NSString *)string; 39 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth; 40 | - (NSString *)base64EncodedString; 41 | 42 | @end 43 | 44 | 45 | @interface NSString (Base64) 46 | 47 | + (NSString *)stringWithBase64EncodedString:(NSString *)string; 48 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth; 49 | - (NSString *)base64EncodedString; 50 | - (NSString *)base64DecodedString; 51 | - (NSData *)base64DecodedData; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/Base64.m: -------------------------------------------------------------------------------- 1 | // 2 | // Base64.m 3 | // 4 | // Version 1.2 5 | // 6 | // Created by Nick Lockwood on 12/01/2012. 7 | // Copyright (C) 2012 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/Base64 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an aacknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | #import "Base64.h" 34 | 35 | 36 | #pragma GCC diagnostic ignored "-Wselector" 37 | 38 | 39 | #import 40 | #if !__has_feature(objc_arc) 41 | #error This library requires automatic reference counting 42 | #endif 43 | 44 | 45 | @implementation NSData (Base64) 46 | 47 | + (NSData *)dataWithBase64EncodedString:(NSString *)string 48 | { 49 | if (![string length]) return nil; 50 | 51 | NSData *decoded = nil; 52 | 53 | #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 54 | 55 | if (![NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) 56 | { 57 | decoded = [[self alloc] initWithBase64Encoding:[string stringByReplacingOccurrencesOfString:@"[^A-Za-z0-9+/=]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [string length])]]; 58 | } 59 | else 60 | 61 | #endif 62 | 63 | { 64 | decoded = [[self alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters]; 65 | } 66 | 67 | return [decoded length]? decoded: nil; 68 | } 69 | 70 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth 71 | { 72 | if (![self length]) return nil; 73 | 74 | NSString *encoded = nil; 75 | 76 | #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 77 | 78 | if (![NSData instancesRespondToSelector:@selector(base64EncodedStringWithOptions:)]) 79 | { 80 | encoded = [self base64Encoding]; 81 | } 82 | else 83 | 84 | #endif 85 | 86 | { 87 | switch (wrapWidth) 88 | { 89 | case 64: 90 | { 91 | return [self base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; 92 | } 93 | case 76: 94 | { 95 | return [self base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; 96 | } 97 | default: 98 | { 99 | encoded = [self base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]; 100 | } 101 | } 102 | } 103 | 104 | if (!wrapWidth || wrapWidth >= [encoded length]) 105 | { 106 | return encoded; 107 | } 108 | 109 | wrapWidth = (wrapWidth / 4) * 4; 110 | NSMutableString *result = [NSMutableString string]; 111 | for (NSUInteger i = 0; i < [encoded length]; i+= wrapWidth) 112 | { 113 | if (i + wrapWidth >= [encoded length]) 114 | { 115 | [result appendString:[encoded substringFromIndex:i]]; 116 | break; 117 | } 118 | [result appendString:[encoded substringWithRange:NSMakeRange(i, wrapWidth)]]; 119 | [result appendString:@"\r\n"]; 120 | } 121 | 122 | return result; 123 | } 124 | 125 | - (NSString *)base64EncodedString 126 | { 127 | return [self base64EncodedStringWithWrapWidth:0]; 128 | } 129 | 130 | @end 131 | 132 | 133 | @implementation NSString (Base64) 134 | 135 | + (NSString *)stringWithBase64EncodedString:(NSString *)string 136 | { 137 | NSData *data = [NSData dataWithBase64EncodedString:string]; 138 | if (data) 139 | { 140 | return [[self alloc] initWithData:data encoding:NSUTF8StringEncoding]; 141 | } 142 | return nil; 143 | } 144 | 145 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth 146 | { 147 | NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; 148 | return [data base64EncodedStringWithWrapWidth:wrapWidth]; 149 | } 150 | 151 | - (NSString *)base64EncodedString 152 | { 153 | NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; 154 | return [data base64EncodedString]; 155 | } 156 | 157 | - (NSString *)base64DecodedString 158 | { 159 | return [NSString stringWithBase64EncodedString:self]; 160 | } 161 | 162 | - (NSData *)base64DecodedData 163 | { 164 | return [NSData dataWithBase64EncodedString:self]; 165 | } 166 | 167 | @end 168 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/connects/QWApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWApplication.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-4-2. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString* const kQWAppKeyName; 12 | extern NSString* const kQWAppKeyUrlScheme; 13 | extern NSString* const kQWAppKeySDKVersion; 14 | extern NSString* const kQWAppKeyAPPID; 15 | extern NSString* const kQWAppKeyType; 16 | 17 | 18 | // 19 | extern NSString* const kQWAppTypeNative; 20 | extern NSString* const kQWAppTypeBrowser; 21 | 22 | @interface QWApplication : NSObject 23 | @property (nonatomic, strong) NSString* name; 24 | @property (nonatomic, strong) NSString* urlScheme; 25 | @property (nonatomic, strong) NSString* sdkVersion; 26 | @property (nonatomic, strong) NSString* appId; 27 | @property (nonatomic, strong) NSString* type; 28 | @property (nonatomic, strong ,readonly) NSString* urlSchemePrefix; 29 | + (QWApplication*) shareApplication; 30 | 31 | - (NSDictionary*) dictionaryWithAllValues; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/connects/QWApplication.m: -------------------------------------------------------------------------------- 1 | // 2 | // QWApplication.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-4-2. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWApplication.h" 10 | NSString* const kQWAppKeyName = @"name"; 11 | NSString* const kQWAppKeyUrlScheme = @"urlScheme"; 12 | NSString* const kQWAppKeySDKVersion = @"sdkVersion"; 13 | NSString* const kQWAppKeyAPPID= @"appId"; 14 | NSString* const kQWAppKeyType = @"type"; 15 | 16 | NSString* const kQWAppTypeNative = @"native"; 17 | NSString* const kQWAppTypeBrowser = @"browser"; 18 | 19 | @implementation QWApplication 20 | 21 | 22 | + (QWApplication*) shareApplication 23 | { 24 | static QWApplication* share = nil; 25 | static dispatch_once_t onceToken; 26 | dispatch_once(&onceToken, ^{ 27 | share = [[QWApplication alloc] init]; 28 | share.name = @"unknown application"; 29 | share.urlScheme = @""; 30 | share.sdkVersion = @"0.0.1"; 31 | share.appId = @"invalid"; 32 | share.type = kQWAppTypeNative; 33 | }); 34 | return share; 35 | } 36 | - (NSString*) urlSchemePrefix 37 | { 38 | return [NSString stringWithFormat:@"%@://",_urlScheme]; 39 | } 40 | - (void) setValue:(id)value forKey:(NSString *)key 41 | { 42 | if ([key isEqual:kQWAppKeyName]) { 43 | _name = value; 44 | } else if ([key isEqual:kQWAppKeySDKVersion]) 45 | { 46 | if ([value isKindOfClass:[NSNumber class]]) { 47 | value = [value stringValue]; 48 | } else 49 | { 50 | _sdkVersion = value; 51 | } 52 | } else if ([key isEqual:kQWAppKeyUrlScheme]) 53 | { 54 | _urlScheme = value; 55 | } else if ([key isEqual:kQWAppKeyAPPID]) 56 | { 57 | _appId = value; 58 | } else if ([key isEqual:kQWAppKeyType]) 59 | { 60 | _type = value; 61 | } 62 | } 63 | 64 | - (id) valueForKey:(NSString *)key 65 | { 66 | if ([key isEqual:kQWAppKeyName]) { 67 | return _name; 68 | } else if ([key isEqual:kQWAppKeySDKVersion]) 69 | { 70 | return _sdkVersion; 71 | } else if ([key isEqual:kQWAppKeyUrlScheme]) 72 | { 73 | return _urlScheme; 74 | } else if ([key isEqual:kQWAppKeyAPPID]) 75 | { 76 | return _appId; 77 | } else if ([key isEqual:kQWAppKeyType]) 78 | { 79 | return _type; 80 | } 81 | return [NSNull null]; 82 | } 83 | 84 | - (NSDictionary*) dictionaryWithAllValues 85 | { 86 | return [self dictionaryWithValuesForKeys:@[kQWAppKeyUrlScheme, kQWAppKeySDKVersion, kQWAppKeyName, kQWAppKeyAPPID]]; 87 | } 88 | @end 89 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/connects/QWURLEncodeEngine.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWURLEncodeEngine.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-4-2. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString* const kQWURLKeyAction; 12 | extern NSString* const kQWURLKeyParams; 13 | extern NSString* const kQWURLKeyApplication; 14 | 15 | @interface QWURLEncodeEngine : NSObject 16 | 17 | + (NSURL*) encodeWithAction:(NSDictionary*)action params:(NSDictionary*)params error:(NSError* __autoreleasing *)error; 18 | + (NSDictionary*) decodeWithInfo:(NSURL *)url error:(NSError *__autoreleasing *)error; 19 | @end 20 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/connects/QWURLEncodeEngine.m: -------------------------------------------------------------------------------- 1 | // 2 | // QWURLEncodeEngine.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-4-2. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWURLEncodeEngine.h" 10 | #import "QQWalletDefines.h" 11 | #import "SBJson4.h" 12 | #import "Base64.h" 13 | #import "QWApplication.h" 14 | 15 | NSString* const kQWURLKeyAction = @"action"; 16 | NSString* const kQWURLKeyParams = @"params"; 17 | NSString* const kQWURLKeyApplication = @"application"; 18 | 19 | @implementation QWURLEncodeEngine 20 | 21 | + (NSURL*) encodeWithAction:(NSDictionary *)action 22 | params:(NSDictionary *)params 23 | error:(NSError *__autoreleasing *)error 24 | { 25 | NSMutableDictionary* infos = [NSMutableDictionary new]; 26 | if (action) { 27 | infos[kQWURLKeyAction] = action; 28 | } 29 | if (params) { 30 | infos[kQWURLKeyParams] = params; 31 | } 32 | infos[kQWURLKeyApplication] = [[QWApplication shareApplication] dictionaryWithAllValues]; 33 | NSMutableString* urlString = [NSMutableString stringWithFormat:@"%@://",kQWURLScheme]; 34 | SBJson4Writer* jsonWriter = [SBJson4Writer new]; 35 | NSString* datas = [jsonWriter stringWithObject:infos]; 36 | [urlString appendString:[NSString stringWithFormat:@"%@",[datas base64EncodedString]]]; 37 | NSURL* url = [NSURL URLWithString:urlString]; 38 | if (!url) { 39 | if (error != NULL) { 40 | *error = [NSError errorWithDomain:kQWErrorDomain code:QWErrorParamsError userInfo:@{NSLocalizedDescriptionKey:@"参数错误!"}]; 41 | } 42 | return nil; 43 | } 44 | return url; 45 | } 46 | 47 | + (NSDictionary*) decodeWithInfo:(NSURL *)url error:(NSError *__autoreleasing *)error 48 | { 49 | NSString* string = [url absoluteString]; 50 | NSString* prefix = [NSString stringWithFormat:@"%@://",[QWApplication shareApplication].urlScheme]; 51 | 52 | NSRange range = [string rangeOfString:prefix]; 53 | if (range.length == NSNotFound || range.location == NSNotFound) { 54 | if (error != NULL) { 55 | *error = [NSError errorWithDomain:kQWErrorDomain code:QWErrorParamsError userInfo:@{NSLocalizedDescriptionKey:@"url scheme error"}]; 56 | } 57 | return nil; 58 | } 59 | NSString* datas = [string substringFromIndex:range.location + range.length]; 60 | NSData* jsonData = [datas base64DecodedData]; 61 | 62 | __block NSDictionary* infos = nil; 63 | __block NSError* parserError = nil; 64 | SBJson4Parser* parser = [SBJson4Parser multiRootParserWithBlock:^(id item, BOOL *stop) { 65 | infos = item; 66 | } errorHandler:^(NSError *error) { 67 | parserError = error; 68 | }]; 69 | // 70 | [parser parse:jsonData]; 71 | // 72 | if (parserError) { 73 | if (error != NULL) { 74 | *error = parserError; 75 | } 76 | return nil; 77 | } 78 | return infos; 79 | } 80 | @end 81 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009-2011 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import "SBJson4Writer.h" 31 | #import "SBJson4StreamParser.h" 32 | #import "SBJson4Parser.h" 33 | #import "SBJson4StreamWriter.h" 34 | #import "SBJson4StreamTokeniser.h" 35 | 36 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4Parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010-2013, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | #import "SBJson4StreamParser.h" 35 | 36 | /** 37 | Block called when the parser has parsed an item. This could be once 38 | for each root document parsed, or once for each unwrapped root array element. 39 | 40 | @param item contains the parsed item. 41 | @param stop set to YES if you want the parser to stop 42 | */ 43 | typedef void (^SBJson4ValueBlock)(id item, BOOL* stop); 44 | 45 | /** 46 | Block called if an error occurs. 47 | @param error the error. 48 | */ 49 | typedef void (^SBJson4ErrorBlock)(NSError* error); 50 | 51 | /** 52 | Block used to process parsed tokens as they are encountered. You can use this 53 | to transform strings containing dates into NSDate, for example. 54 | @param item the parsed token 55 | @param path the JSON Path of the token 56 | */ 57 | typedef id (^SBJson4ProcessBlock)(id item, NSString* path); 58 | 59 | 60 | /** 61 | Parse one or more chunks of JSON data. 62 | 63 | Using this class directly you can reduce the apparent latency for each 64 | download/parse cycle of documents over a slow connection. You can start 65 | parsing *and return chunks of the parsed document* before the entire 66 | document is downloaded. 67 | 68 | Using this class is also useful to parse huge documents on disk 69 | bit by bit so you don't have to keep them all in memory. 70 | 71 | JSON is mapped to Objective-C types in the following way: 72 | 73 | - null -> NSNull 74 | - string -> NSString 75 | - array -> NSMutableArray 76 | - object -> NSMutableDictionary 77 | - true -> NSNumber's -numberWithBool:YES 78 | - false -> NSNumber's -numberWithBool:NO 79 | - number -> NSNumber 80 | 81 | Since Objective-C doesn't have a dedicated class for boolean values, 82 | these turns into NSNumber instances. However, since these are 83 | initialised with the -initWithBool: method they round-trip back to JSON 84 | properly. In other words, they won't silently suddenly become 0 or 1; 85 | they'll be represented as 'true' and 'false' again. 86 | 87 | Integers are parsed into either a `long long` or `unsigned long long` 88 | type if they fit, else a `double` is used. All real & exponential numbers 89 | are represented using a `double`. Previous versions of this library used 90 | an NSDecimalNumber in some cases, but this is no longer the case. 91 | 92 | The default behaviour is that your passed-in block is only called once the 93 | entire input is parsed. If you set supportManyDocuments to YES and your input 94 | contains multiple (whitespace limited) JSON documents your block will be called 95 | for each document: 96 | 97 | SBJson4ValueBlock block = ^(id v, BOOL *stop) { 98 | BOOL isArray = [v isKindOfClass:[NSArray class]]; 99 | NSLog(@"Found: %@", isArray ? @"Array" : @"Object"); 100 | } 101 | 102 | SBJson4ErrorBlock eh = ^(NSError* err) { 103 | NSLog(@"OOPS: %@", err); 104 | } 105 | 106 | id parser = [SBJson4Parser multiRootParserWithBlock:block 107 | errorHandler:eh]; 108 | 109 | // Note that this input contains multiple top-level JSON documents 110 | id data = [@"[]{}" dataWithEncoding:NSUTF8StringEncoding]; 111 | [parser parse:data]; 112 | [parser parse:data]; 113 | 114 | The above example will print: 115 | 116 | - Found: Array 117 | - Found: Object 118 | - Found: Array 119 | - Found: Object 120 | 121 | Often you won't have control over the input you're parsing, so can't make use 122 | of this feature. But, all is not lost: if you are parsing a long array you can 123 | get the same effect by setting rootArrayItems to YES: 124 | 125 | id parser = [SBJson4Parser unwrapRootArrayParserWithBlock:block 126 | errorHandler:eh]; 127 | 128 | // Note that this input contains A SINGLE top-level document 129 | id data = [@"[[],{},[],{}]" dataWithEncoding:NSUTF8StringEncoding]; 130 | [parser parse:data]; 131 | 132 | @note Stream based parsing does mean that you lose some of the correctness 133 | verification you would have with a parser that considered the entire input 134 | before returning an answer. It is technically possible to have some parts 135 | of a document returned *as if they were correct* but then encounter an error 136 | in a later part of the document. You should keep this in mind when 137 | considering whether it would suit your application. 138 | 139 | 140 | */ 141 | @interface SBJson4Parser : NSObject 142 | 143 | /** 144 | Create a JSON Parser. 145 | 146 | This can be used to create a parser that accepts only one document, or one that parses 147 | many documents any 148 | 149 | @param block Called for each element. Set *stop to `YES` if you have seen 150 | enough and would like to skip the rest of the elements. 151 | 152 | @param allowMultiRoot Indicate that you are expecting multiple whitespace-separated 153 | JSON documents, similar to what Twitter uses. 154 | 155 | @param unwrapRootArray If set the parser will pretend an root array does not exist 156 | and the enumerator block will be called once for each item in it. This option 157 | does nothing if the the JSON has an object at its root. 158 | 159 | @param eh Called if the parser encounters an error. 160 | 161 | @see -unwrapRootArrayParserWithBlock:errorHandler: 162 | @see -multiRootParserWithBlock:errorHandler: 163 | @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler: 164 | 165 | */ 166 | + (id)parserWithBlock:(SBJson4ValueBlock)block 167 | allowMultiRoot:(BOOL)allowMultiRoot 168 | unwrapRootArray:(BOOL)unwrapRootArray 169 | errorHandler:(SBJson4ErrorBlock)eh; 170 | 171 | 172 | /** 173 | Create a JSON Parser that parses multiple whitespace separated documents. 174 | This is useful for something like twitter's feed, which gives you one JSON 175 | document per line. 176 | 177 | @param block Called for each element. Set *stop to `YES` if you have seen 178 | enough and would like to skip the rest of the elements. 179 | 180 | @param eh Called if the parser encounters an error. 181 | 182 | @see +unwrapRootArrayParserWithBlock:errorHandler: 183 | @see +parserWithBlock:allowMultiRoot:unwrapRootArray:errorHandler: 184 | @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler: 185 | */ 186 | + (id)multiRootParserWithBlock:(SBJson4ValueBlock)block 187 | errorHandler:(SBJson4ErrorBlock)eh; 188 | 189 | /** 190 | Create a JSON Parser that parses a huge array and calls for the value block for 191 | each element in the outermost array. 192 | 193 | @param block Called for each element. Set *stop to `YES` if you have seen 194 | enough and would like to skip the rest of the elements. 195 | 196 | @param eh Called if the parser encounters an error. 197 | 198 | @see +multiRootParserWithBlock:errorHandler: 199 | @see +parserWithBlock:allowMultiRoot:unwrapRootArray:errorHandler: 200 | @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler: 201 | */ 202 | + (id)unwrapRootArrayParserWithBlock:(SBJson4ValueBlock)block 203 | errorHandler:(SBJson4ErrorBlock)eh; 204 | 205 | /** 206 | Create a JSON Parser. 207 | 208 | @param block Called for each element. Set *stop to `YES` if you have seen 209 | enough and would like to skip the rest of the elements. 210 | 211 | @param processBlock A block that allows you to process individual values before being 212 | returned. 213 | 214 | @param multiRoot Indicate that you are expecting multiple whitespace-separated 215 | JSON documents, similar to what Twitter uses. 216 | 217 | @param unwrapRootArray If set the parser will pretend an root array does not exist 218 | and the enumerator block will be called once for each item in it. This option 219 | does nothing if the the JSON has an object at its root. 220 | 221 | @param maxDepth The max recursion depth of the parser. Defaults to 32. 222 | 223 | @param eh Called if the parser encounters an error. 224 | 225 | */ 226 | - (id)initWithBlock:(SBJson4ValueBlock)block 227 | processBlock:(SBJson4ProcessBlock)processBlock 228 | multiRoot:(BOOL)multiRoot 229 | unwrapRootArray:(BOOL)unwrapRootArray 230 | maxDepth:(NSUInteger)maxDepth 231 | errorHandler:(SBJson4ErrorBlock)eh; 232 | 233 | /** 234 | Parse some JSON 235 | 236 | The JSON is assumed to be UTF8 encoded. This can be a full JSON document, or a part of one. 237 | 238 | @param data An NSData object containing the next chunk of JSON 239 | 240 | @return 241 | - SBJson4ParserComplete if a full document was found 242 | - SBJson4ParserWaitingForData if a partial document was found and more data is required to complete it 243 | - SBJson4ParserError if an error occured. 244 | 245 | */ 246 | - (SBJson4ParserStatus)parse:(NSData*)data; 247 | 248 | @end 249 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4Parser.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010-2013, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #if !__has_feature(objc_arc) 34 | #error "This source file must be compiled with ARC enabled!" 35 | #endif 36 | 37 | #import "SBJson4Parser.h" 38 | 39 | @interface SBJson4Parser () 40 | 41 | - (void)pop; 42 | - (void)parser:(SBJson4StreamParser *)parser found:(id)obj; 43 | 44 | @end 45 | 46 | typedef enum { 47 | SBJson4ChunkNone, 48 | SBJson4ChunkArray, 49 | SBJson4ChunkObject, 50 | } SBJson4ChunkType; 51 | 52 | @implementation SBJson4Parser { 53 | SBJson4StreamParser *_parser; 54 | NSUInteger depth; 55 | NSMutableArray *array; 56 | NSMutableDictionary *dict; 57 | NSMutableArray *keyStack; 58 | NSMutableArray *stack; 59 | NSMutableArray *path; 60 | SBJson4ProcessBlock processBlock; 61 | SBJson4ErrorBlock errorHandler; 62 | SBJson4ValueBlock valueBlock; 63 | SBJson4ChunkType currentType; 64 | BOOL supportManyDocuments; 65 | BOOL supportPartialDocuments; 66 | NSUInteger _maxDepth; 67 | } 68 | 69 | #pragma mark Housekeeping 70 | 71 | - (id)init { 72 | @throw @"Not Implemented"; 73 | } 74 | 75 | + (id)multiRootParserWithBlock:(SBJson4ValueBlock)block errorHandler:(SBJson4ErrorBlock)eh { 76 | return [self parserWithBlock:block 77 | allowMultiRoot:YES 78 | unwrapRootArray:NO 79 | errorHandler:eh]; 80 | } 81 | 82 | + (id)unwrapRootArrayParserWithBlock:(SBJson4ValueBlock)block errorHandler:(SBJson4ErrorBlock)eh { 83 | return [self parserWithBlock:block 84 | allowMultiRoot:NO 85 | unwrapRootArray:YES 86 | errorHandler:eh]; 87 | } 88 | 89 | + (id)parserWithBlock:(SBJson4ValueBlock)block 90 | allowMultiRoot:(BOOL)allowMultiRoot 91 | unwrapRootArray:(BOOL)unwrapRootArray 92 | errorHandler:(SBJson4ErrorBlock)eh { 93 | 94 | return [[self alloc] initWithBlock:block 95 | processBlock:nil 96 | multiRoot:allowMultiRoot 97 | unwrapRootArray:unwrapRootArray 98 | maxDepth:32 99 | errorHandler:eh]; 100 | } 101 | 102 | - (id)initWithBlock:(SBJson4ValueBlock)block 103 | processBlock:(SBJson4ProcessBlock)initialProcessBlock 104 | multiRoot:(BOOL)multiRoot 105 | unwrapRootArray:(BOOL)unwrapRootArray 106 | maxDepth:(NSUInteger)maxDepth 107 | errorHandler:(SBJson4ErrorBlock)eh { 108 | 109 | self = [super init]; 110 | if (self) { 111 | _parser = [[SBJson4StreamParser alloc] init]; 112 | _parser.delegate = self; 113 | 114 | supportManyDocuments = multiRoot; 115 | supportPartialDocuments = unwrapRootArray; 116 | 117 | valueBlock = block; 118 | keyStack = [[NSMutableArray alloc] initWithCapacity:32]; 119 | stack = [[NSMutableArray alloc] initWithCapacity:32]; 120 | if (initialProcessBlock) 121 | path = [[NSMutableArray alloc] initWithCapacity:32]; 122 | processBlock = initialProcessBlock; 123 | errorHandler = eh ? eh : ^(NSError*err) { NSLog(@"%@", err); }; 124 | currentType = SBJson4ChunkNone; 125 | _maxDepth = maxDepth; 126 | } 127 | return self; 128 | } 129 | 130 | 131 | #pragma mark Private methods 132 | 133 | - (void)pop { 134 | [stack removeLastObject]; 135 | array = nil; 136 | dict = nil; 137 | currentType = SBJson4ChunkNone; 138 | 139 | id value = [stack lastObject]; 140 | 141 | if ([value isKindOfClass:[NSArray class]]) { 142 | array = value; 143 | currentType = SBJson4ChunkArray; 144 | } else if ([value isKindOfClass:[NSDictionary class]]) { 145 | dict = value; 146 | currentType = SBJson4ChunkObject; 147 | } 148 | } 149 | 150 | - (void)parser:(SBJson4StreamParser *)parser found:(id)obj { 151 | [self parserFound:obj isValue:NO ]; 152 | } 153 | 154 | - (void)parserFound:(id)obj isValue:(BOOL)isValue { 155 | NSParameterAssert(obj); 156 | 157 | if(processBlock&&path) { 158 | if(isValue) { 159 | obj = processBlock(obj,[NSString stringWithFormat:@"%@.%@",[self pathString],[keyStack lastObject]]); 160 | } 161 | else { 162 | [path removeLastObject]; 163 | } 164 | } 165 | 166 | switch (currentType) { 167 | case SBJson4ChunkArray: 168 | [array addObject:obj]; 169 | break; 170 | 171 | case SBJson4ChunkObject: 172 | NSParameterAssert(keyStack.count); 173 | [dict setObject:obj forKey:[keyStack lastObject]]; 174 | [keyStack removeLastObject]; 175 | break; 176 | 177 | case SBJson4ChunkNone: { 178 | __block BOOL stop = NO; 179 | valueBlock(obj, &stop); 180 | if (stop) [_parser stop]; 181 | } 182 | break; 183 | 184 | default: 185 | break; 186 | } 187 | } 188 | 189 | 190 | #pragma mark Delegate methods 191 | 192 | - (void)parserFoundObjectStart { 193 | ++depth; 194 | if (depth > _maxDepth) 195 | [self maxDepthError]; 196 | 197 | if (path) 198 | [self addToPath]; 199 | dict = [NSMutableDictionary new]; 200 | [stack addObject:dict]; 201 | currentType = SBJson4ChunkObject; 202 | } 203 | 204 | - (void)parserFoundObjectKey:(NSString *)key_ { 205 | [keyStack addObject:key_]; 206 | } 207 | 208 | - (void)parserFoundObjectEnd { 209 | depth--; 210 | id value = dict; 211 | [self pop]; 212 | [self parser:_parser found:value]; 213 | } 214 | 215 | - (void)parserFoundArrayStart { 216 | depth++; 217 | if (depth > _maxDepth) 218 | [self maxDepthError]; 219 | 220 | if (depth > 1 || !supportPartialDocuments) { 221 | if(path) 222 | [self addToPath]; 223 | array = [NSMutableArray new]; 224 | [stack addObject:array]; 225 | currentType = SBJson4ChunkArray; 226 | } 227 | } 228 | 229 | - (void)parserFoundArrayEnd { 230 | depth--; 231 | if (depth > 1 || !supportPartialDocuments) { 232 | id value = array; 233 | [self pop]; 234 | [self parser:_parser found:value]; 235 | } 236 | } 237 | 238 | - (void)maxDepthError { 239 | id ui = @{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Input depth exceeds max depth of %lu", (unsigned long)_maxDepth]}; 240 | errorHandler([NSError errorWithDomain:@"org.sbjson.parser" code:3 userInfo:ui]); 241 | [_parser stop]; 242 | } 243 | 244 | - (void)parserFoundBoolean:(BOOL)x { 245 | [self parserFound:[NSNumber numberWithBool:x] isValue:YES ]; 246 | } 247 | 248 | - (void)parserFoundNull { 249 | [self parserFound:[NSNull null] isValue:YES ]; 250 | } 251 | 252 | - (void)parserFoundNumber:(NSNumber *)num { 253 | [self parserFound:num isValue:YES ]; 254 | } 255 | 256 | - (void)parserFoundString:(NSString *)string { 257 | [self parserFound:string isValue:YES ]; 258 | } 259 | 260 | - (void)parserFoundError:(NSError *)err { 261 | errorHandler(err); 262 | } 263 | 264 | - (void)addToPath { 265 | if([path count]==0) 266 | [path addObject:@"$"]; 267 | else if([[stack lastObject] isKindOfClass:[NSArray class]]) 268 | [path addObject:@([[stack lastObject] count])]; 269 | else 270 | [path addObject:[keyStack lastObject]]; 271 | } 272 | 273 | - (NSString *)pathString { 274 | NSMutableString *pathString = [NSMutableString stringWithString:@"$"]; 275 | for(NSUInteger i=1;i<[path count];i++) { 276 | if([[path objectAtIndex:i] isKindOfClass:[NSNumber class]]) 277 | [pathString appendString:[NSString stringWithFormat:@"[%@]",[path objectAtIndex:i]]]; 278 | else 279 | [pathString appendString:[NSString stringWithFormat:@".%@",[path objectAtIndex:i]]]; 280 | } 281 | return pathString; 282 | } 283 | 284 | - (BOOL)parserShouldSupportManyDocuments { 285 | return supportManyDocuments; 286 | } 287 | 288 | - (SBJson4ParserStatus)parse:(NSData *)data { 289 | return [_parser parse:data]; 290 | } 291 | 292 | @end 293 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010-2013, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | @class SBJson4StreamParser; 36 | @class SBJson4StreamParserState; 37 | 38 | typedef enum { 39 | SBJson4ParserComplete, 40 | SBJson4ParserStopped, 41 | SBJson4ParserWaitingForData, 42 | SBJson4ParserError, 43 | } SBJson4ParserStatus; 44 | 45 | 46 | /** 47 | Delegate for interacting directly with the low-level parser 48 | 49 | You will most likely find it much more convenient to use the SBJson4Parser instead. 50 | */ 51 | @protocol SBJson4StreamParserDelegate < NSObject > 52 | 53 | /// Called when object start is found 54 | - (void)parserFoundObjectStart; 55 | 56 | /// Called when object key is found 57 | - (void)parserFoundObjectKey:(NSString *)key; 58 | 59 | /// Called when object end is found 60 | - (void)parserFoundObjectEnd; 61 | 62 | /// Called when array start is found 63 | - (void)parserFoundArrayStart; 64 | 65 | /// Called when array end is found 66 | - (void)parserFoundArrayEnd; 67 | 68 | /// Called when a boolean value is found 69 | - (void)parserFoundBoolean:(BOOL)x; 70 | 71 | /// Called when a null value is found 72 | - (void)parserFoundNull; 73 | 74 | /// Called when a number is found 75 | - (void)parserFoundNumber:(NSNumber *)num; 76 | 77 | /// Called when a string is found 78 | - (void)parserFoundString:(NSString *)string; 79 | 80 | /// Called when an error occurs 81 | - (void)parserFoundError:(NSError *)err; 82 | 83 | @optional 84 | 85 | /// Called to determine whether to allow multiple whitespace-separated documents 86 | - (BOOL)parserShouldSupportManyDocuments; 87 | 88 | @end 89 | 90 | /** 91 | Low-level Stream parser 92 | 93 | You most likely want to use the SBJson4Parser instead, but if you 94 | really need low-level access to tokens one-by-one you can use this class. 95 | */ 96 | @interface SBJson4StreamParser : NSObject 97 | 98 | @property (nonatomic, weak) SBJson4StreamParserState *state; // Private 99 | @property (nonatomic, readonly, strong) NSMutableArray *stateStack; // Private 100 | 101 | /** 102 | Delegate to receive messages 103 | 104 | The object set here receives a series of messages as the parser breaks down the JSON stream 105 | into valid tokens. 106 | 107 | Usually this should be an instance of SBJson4Parser, but you can 108 | substitute your own implementation of the SBJson4StreamParserDelegate protocol if you need to. 109 | */ 110 | @property (nonatomic, weak) id delegate; 111 | 112 | /** 113 | Parse some JSON 114 | 115 | The JSON is assumed to be UTF8 encoded. This can be a full JSON document, or a part of one. 116 | 117 | @param data An NSData object containing the next chunk of JSON 118 | 119 | @return 120 | - SBJson4ParserComplete if a full document was found 121 | - SBJson4ParserWaitingForData if a partial document was found and more data is required to complete it 122 | - SBJson4ParserError if an error occured. 123 | 124 | */ 125 | - (SBJson4ParserStatus)parse:(NSData*)data; 126 | 127 | /** 128 | Call this to cause parsing to stop. 129 | */ 130 | - (void)stop; 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamParser.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #if !__has_feature(objc_arc) 34 | #error "This source file must be compiled with ARC enabled!" 35 | #endif 36 | 37 | #import "SBJson4StreamParser.h" 38 | #import "SBJson4StreamTokeniser.h" 39 | #import "SBJson4StreamParserState.h" 40 | 41 | #define SBStringIsSurrogateHighCharacter(character) ((character >= 0xD800UL) && (character <= 0xDBFFUL)) 42 | 43 | @implementation SBJson4StreamParser { 44 | SBJson4StreamTokeniser *tokeniser; 45 | BOOL stopped; 46 | } 47 | 48 | #pragma mark Housekeeping 49 | 50 | - (id)init { 51 | self = [super init]; 52 | if (self) { 53 | _stateStack = [[NSMutableArray alloc] initWithCapacity:32]; 54 | _state = [SBJson4StreamParserStateStart sharedInstance]; 55 | tokeniser = [[SBJson4StreamTokeniser alloc] init]; 56 | } 57 | return self; 58 | } 59 | 60 | 61 | #pragma mark Methods 62 | 63 | - (NSString*)tokenName:(sbjson4_token_t)token { 64 | switch (token) { 65 | case sbjson4_token_array_open: 66 | return @"start of array"; 67 | break; 68 | 69 | case sbjson4_token_array_close: 70 | return @"end of array"; 71 | break; 72 | 73 | case sbjson4_token_integer: 74 | case sbjson4_token_real: 75 | return @"number"; 76 | break; 77 | 78 | case sbjson4_token_string: 79 | case sbjson4_token_encoded: 80 | return @"string"; 81 | break; 82 | 83 | case sbjson4_token_bool: 84 | return @"boolean"; 85 | break; 86 | 87 | case sbjson4_token_null: 88 | return @"null"; 89 | break; 90 | 91 | case sbjson4_token_entry_sep: 92 | return @"key-value separator"; 93 | break; 94 | 95 | case sbjson4_token_value_sep: 96 | return @"value separator"; 97 | break; 98 | 99 | case sbjson4_token_object_open: 100 | return @"start of object"; 101 | break; 102 | 103 | case sbjson4_token_object_close: 104 | return @"end of object"; 105 | break; 106 | 107 | case sbjson4_token_eof: 108 | case sbjson4_token_error: 109 | break; 110 | } 111 | NSAssert(NO, @"Should not get here"); 112 | return @""; 113 | } 114 | 115 | - (void)handleObjectStart { 116 | [_delegate parserFoundObjectStart]; 117 | [_stateStack addObject:_state]; 118 | _state = [SBJson4StreamParserStateObjectStart sharedInstance]; 119 | } 120 | 121 | - (void)handleObjectEnd: (sbjson4_token_t) tok { 122 | _state = [_stateStack lastObject]; 123 | [_stateStack removeLastObject]; 124 | [_state parser:self shouldTransitionTo:tok]; 125 | [_delegate parserFoundObjectEnd]; 126 | } 127 | 128 | - (void)handleArrayStart { 129 | [_delegate parserFoundArrayStart]; 130 | [_stateStack addObject:_state]; 131 | _state = [SBJson4StreamParserStateArrayStart sharedInstance]; 132 | } 133 | 134 | - (void)handleArrayEnd: (sbjson4_token_t) tok { 135 | _state = [_stateStack lastObject]; 136 | [_stateStack removeLastObject]; 137 | [_state parser:self shouldTransitionTo:tok]; 138 | [_delegate parserFoundArrayEnd]; 139 | } 140 | 141 | - (void) handleTokenNotExpectedHere: (sbjson4_token_t) tok { 142 | NSString *tokenName = [self tokenName:tok]; 143 | NSString *stateName = [_state name]; 144 | 145 | _state = [SBJson4StreamParserStateError sharedInstance]; 146 | id ui = @{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Token '%@' not expected %@", tokenName, stateName]}; 147 | [_delegate parserFoundError:[NSError errorWithDomain:@"org.sbjson.parser" code:2 userInfo:ui]]; 148 | } 149 | 150 | - (SBJson4ParserStatus)parse:(NSData *)data_ { 151 | @autoreleasepool { 152 | [tokeniser appendData:data_]; 153 | 154 | for (;;) { 155 | 156 | if (stopped) 157 | return SBJson4ParserStopped; 158 | 159 | if ([_state isError]) 160 | return SBJson4ParserError; 161 | 162 | char *token; 163 | NSUInteger token_len; 164 | sbjson4_token_t tok = [tokeniser getToken:&token length:&token_len]; 165 | 166 | switch (tok) { 167 | case sbjson4_token_eof: 168 | return [_state parserShouldReturn:self]; 169 | break; 170 | 171 | case sbjson4_token_error: 172 | _state = [SBJson4StreamParserStateError sharedInstance]; 173 | [_delegate parserFoundError:[NSError errorWithDomain:@"org.sbjson.parser" code:3 174 | userInfo:@{NSLocalizedDescriptionKey : tokeniser.error}]]; 175 | return SBJson4ParserError; 176 | break; 177 | 178 | default: 179 | 180 | if (![_state parser:self shouldAcceptToken:tok]) { 181 | [self handleTokenNotExpectedHere: tok]; 182 | return SBJson4ParserError; 183 | } 184 | 185 | switch (tok) { 186 | case sbjson4_token_object_open: 187 | [self handleObjectStart]; 188 | break; 189 | 190 | case sbjson4_token_object_close: 191 | [self handleObjectEnd: tok]; 192 | break; 193 | 194 | case sbjson4_token_array_open: 195 | [self handleArrayStart]; 196 | break; 197 | 198 | case sbjson4_token_array_close: 199 | [self handleArrayEnd: tok]; 200 | break; 201 | 202 | case sbjson4_token_value_sep: 203 | case sbjson4_token_entry_sep: 204 | [_state parser:self shouldTransitionTo:tok]; 205 | break; 206 | 207 | case sbjson4_token_bool: 208 | [_delegate parserFoundBoolean:token[0] == 't']; 209 | [_state parser:self shouldTransitionTo:tok]; 210 | break; 211 | 212 | 213 | case sbjson4_token_null: 214 | [_delegate parserFoundNull]; 215 | [_state parser:self shouldTransitionTo:tok]; 216 | break; 217 | 218 | case sbjson4_token_integer: { 219 | const int UNSIGNED_LONG_LONG_MAX_DIGITS = 20; 220 | if (token_len <= UNSIGNED_LONG_LONG_MAX_DIGITS) { 221 | if (*token == '-') 222 | [_delegate parserFoundNumber:@(strtoll(token, NULL, 10))]; 223 | else 224 | [_delegate parserFoundNumber:@(strtoull(token, NULL, 10))]; 225 | 226 | [_state parser:self shouldTransitionTo:tok]; 227 | break; 228 | } 229 | } 230 | // FALLTHROUGH 231 | 232 | case sbjson4_token_real: { 233 | [_delegate parserFoundNumber:@(strtod(token, NULL))]; 234 | [_state parser:self shouldTransitionTo:tok]; 235 | break; 236 | } 237 | 238 | case sbjson4_token_string: { 239 | NSString *string = [[NSString alloc] initWithBytes:token length:token_len encoding:NSUTF8StringEncoding]; 240 | if ([_state needKey]) 241 | [_delegate parserFoundObjectKey:string]; 242 | else 243 | [_delegate parserFoundString:string]; 244 | [_state parser:self shouldTransitionTo:tok]; 245 | break; 246 | } 247 | 248 | case sbjson4_token_encoded: { 249 | NSString *string = [self decodeStringToken:token length:token_len]; 250 | if ([_state needKey]) 251 | [_delegate parserFoundObjectKey:string]; 252 | else 253 | [_delegate parserFoundString:string]; 254 | [_state parser:self shouldTransitionTo:tok]; 255 | break; 256 | } 257 | 258 | default: 259 | break; 260 | } 261 | break; 262 | } 263 | } 264 | return SBJson4ParserComplete; 265 | } 266 | } 267 | 268 | - (unichar)decodeHexQuad:(char *)quad { 269 | unichar ch = 0; 270 | for (NSUInteger i = 0; i < 4; i++) { 271 | int c = quad[i]; 272 | ch *= 16; 273 | switch (c) { 274 | case '0' ... '9': ch += c - '0'; break; 275 | case 'a' ... 'f': ch += 10 + c - 'a'; break; 276 | case 'A' ... 'F': ch += 10 + c - 'A'; break; 277 | default: @throw @"FUT FUT FUT"; 278 | } 279 | } 280 | return ch; 281 | } 282 | 283 | - (NSString*)decodeStringToken:(char*)bytes length:(NSUInteger)len { 284 | NSMutableData *buf = [NSMutableData dataWithCapacity:len]; 285 | for (NSUInteger i = 0; i < len;) { 286 | switch ((unsigned char)bytes[i]) { 287 | case '\\': { 288 | switch ((unsigned char)bytes[++i]) { 289 | case '"': [buf appendBytes:"\"" length:1]; i++; break; 290 | case '/': [buf appendBytes:"/" length:1]; i++; break; 291 | case '\\': [buf appendBytes:"\\" length:1]; i++; break; 292 | case 'b': [buf appendBytes:"\b" length:1]; i++; break; 293 | case 'f': [buf appendBytes:"\f" length:1]; i++; break; 294 | case 'n': [buf appendBytes:"\n" length:1]; i++; break; 295 | case 'r': [buf appendBytes:"\r" length:1]; i++; break; 296 | case 't': [buf appendBytes:"\t" length:1]; i++; break; 297 | case 'u': { 298 | unichar hi = [self decodeHexQuad:bytes + i + 1]; 299 | i += 5; 300 | if (SBStringIsSurrogateHighCharacter(hi)) { 301 | // Skip past \u that we know is there.. 302 | unichar lo = [self decodeHexQuad:bytes + i + 2]; 303 | i += 6; 304 | [buf appendData:[[NSString stringWithFormat:@"%C%C", hi, lo] dataUsingEncoding:NSUTF8StringEncoding]]; 305 | } else { 306 | [buf appendData:[[NSString stringWithFormat:@"%C", hi] dataUsingEncoding:NSUTF8StringEncoding]]; 307 | } 308 | break; 309 | } 310 | default: @throw @"FUT FUT FUT"; 311 | } 312 | break; 313 | } 314 | default: 315 | [buf appendBytes:bytes + i length:1]; 316 | i++; 317 | break; 318 | } 319 | } 320 | return [[NSString alloc] initWithData:buf encoding:NSUTF8StringEncoding]; 321 | } 322 | 323 | - (void)stop { 324 | stopped = YES; 325 | } 326 | 327 | @end 328 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamParserState.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | #import "SBJson4StreamTokeniser.h" 36 | #import "SBJson4StreamParser.h" 37 | 38 | @interface SBJson4StreamParserState : NSObject 39 | + (id)sharedInstance; 40 | 41 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token; 42 | - (SBJson4ParserStatus)parserShouldReturn:(SBJson4StreamParser *)parser; 43 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok; 44 | - (BOOL)needKey; 45 | - (BOOL)isError; 46 | 47 | - (NSString*)name; 48 | 49 | @end 50 | 51 | @interface SBJson4StreamParserStateStart : SBJson4StreamParserState 52 | @end 53 | 54 | @interface SBJson4StreamParserStateComplete : SBJson4StreamParserState 55 | @end 56 | 57 | @interface SBJson4StreamParserStateError : SBJson4StreamParserState 58 | @end 59 | 60 | @interface SBJson4StreamParserStateObjectStart : SBJson4StreamParserState 61 | @end 62 | 63 | @interface SBJson4StreamParserStateObjectGotKey : SBJson4StreamParserState 64 | @end 65 | 66 | @interface SBJson4StreamParserStateObjectSeparator : SBJson4StreamParserState 67 | @end 68 | 69 | @interface SBJson4StreamParserStateObjectGotValue : SBJson4StreamParserState 70 | @end 71 | 72 | @interface SBJson4StreamParserStateObjectNeedKey : SBJson4StreamParserState 73 | @end 74 | 75 | @interface SBJson4StreamParserStateArrayStart : SBJson4StreamParserState 76 | @end 77 | 78 | @interface SBJson4StreamParserStateArrayGotValue : SBJson4StreamParserState 79 | @end 80 | 81 | @interface SBJson4StreamParserStateArrayNeedValue : SBJson4StreamParserState 82 | @end 83 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamParserState.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010-2013, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #if !__has_feature(objc_arc) 34 | #error "This source file must be compiled with ARC enabled!" 35 | #endif 36 | 37 | #import "SBJson4StreamParserState.h" 38 | 39 | #define SINGLETON \ 40 | + (id)sharedInstance { \ 41 | static id state = nil; \ 42 | if (!state) { \ 43 | @synchronized(self) { \ 44 | if (!state) state = [[self alloc] init]; \ 45 | } \ 46 | } \ 47 | return state; \ 48 | } 49 | 50 | @implementation SBJson4StreamParserState 51 | 52 | + (id)sharedInstance { return nil; } 53 | 54 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 55 | return NO; 56 | } 57 | 58 | - (SBJson4ParserStatus)parserShouldReturn:(SBJson4StreamParser *)parser { 59 | return SBJson4ParserWaitingForData; 60 | } 61 | 62 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok {} 63 | 64 | - (BOOL)needKey { 65 | return NO; 66 | } 67 | 68 | - (NSString*)name { 69 | return @""; 70 | } 71 | 72 | - (BOOL)isError { 73 | return NO; 74 | } 75 | 76 | @end 77 | 78 | #pragma mark - 79 | 80 | @implementation SBJson4StreamParserStateStart 81 | 82 | SINGLETON 83 | 84 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 85 | return token == sbjson4_token_array_open || token == sbjson4_token_object_open; 86 | } 87 | 88 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 89 | 90 | SBJson4StreamParserState *state = nil; 91 | switch (tok) { 92 | case sbjson4_token_array_open: 93 | state = [SBJson4StreamParserStateArrayStart sharedInstance]; 94 | break; 95 | 96 | case sbjson4_token_object_open: 97 | state = [SBJson4StreamParserStateObjectStart sharedInstance]; 98 | break; 99 | 100 | case sbjson4_token_array_close: 101 | case sbjson4_token_object_close: 102 | if ([parser.delegate respondsToSelector:@selector(parserShouldSupportManyDocuments)] && [parser.delegate parserShouldSupportManyDocuments]) 103 | state = parser.state; 104 | else 105 | state = [SBJson4StreamParserStateComplete sharedInstance]; 106 | break; 107 | 108 | case sbjson4_token_eof: 109 | return; 110 | 111 | default: 112 | state = [SBJson4StreamParserStateError sharedInstance]; 113 | break; 114 | } 115 | 116 | 117 | parser.state = state; 118 | } 119 | 120 | - (NSString*)name { return @"before outer-most array or object"; } 121 | 122 | @end 123 | 124 | #pragma mark - 125 | 126 | @implementation SBJson4StreamParserStateComplete 127 | 128 | SINGLETON 129 | 130 | - (NSString*)name { return @"after outer-most array or object"; } 131 | 132 | - (SBJson4ParserStatus)parserShouldReturn:(SBJson4StreamParser *)parser { 133 | return SBJson4ParserComplete; 134 | } 135 | 136 | @end 137 | 138 | #pragma mark - 139 | 140 | @implementation SBJson4StreamParserStateError 141 | 142 | SINGLETON 143 | 144 | - (NSString*)name { return @"in error"; } 145 | 146 | - (SBJson4ParserStatus)parserShouldReturn:(SBJson4StreamParser *)parser { 147 | return SBJson4ParserError; 148 | } 149 | 150 | - (BOOL)isError { 151 | return YES; 152 | } 153 | 154 | @end 155 | 156 | #pragma mark - 157 | 158 | @implementation SBJson4StreamParserStateObjectStart 159 | 160 | SINGLETON 161 | 162 | - (NSString*)name { return @"at beginning of object"; } 163 | 164 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 165 | switch (token) { 166 | case sbjson4_token_object_close: 167 | case sbjson4_token_string: 168 | case sbjson4_token_encoded: 169 | return YES; 170 | break; 171 | default: 172 | return NO; 173 | break; 174 | } 175 | } 176 | 177 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 178 | parser.state = [SBJson4StreamParserStateObjectGotKey sharedInstance]; 179 | } 180 | 181 | - (BOOL)needKey { 182 | return YES; 183 | } 184 | 185 | @end 186 | 187 | #pragma mark - 188 | 189 | @implementation SBJson4StreamParserStateObjectGotKey 190 | 191 | SINGLETON 192 | 193 | - (NSString*)name { return @"after object key"; } 194 | 195 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 196 | return token == sbjson4_token_entry_sep; 197 | } 198 | 199 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 200 | parser.state = [SBJson4StreamParserStateObjectSeparator sharedInstance]; 201 | } 202 | 203 | @end 204 | 205 | #pragma mark - 206 | 207 | @implementation SBJson4StreamParserStateObjectSeparator 208 | 209 | SINGLETON 210 | 211 | - (NSString*)name { return @"as object value"; } 212 | 213 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 214 | switch (token) { 215 | case sbjson4_token_object_open: 216 | case sbjson4_token_array_open: 217 | case sbjson4_token_bool: 218 | case sbjson4_token_null: 219 | case sbjson4_token_integer: 220 | case sbjson4_token_real: 221 | case sbjson4_token_string: 222 | case sbjson4_token_encoded: 223 | return YES; 224 | break; 225 | 226 | default: 227 | return NO; 228 | break; 229 | } 230 | } 231 | 232 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 233 | parser.state = [SBJson4StreamParserStateObjectGotValue sharedInstance]; 234 | } 235 | 236 | @end 237 | 238 | #pragma mark - 239 | 240 | @implementation SBJson4StreamParserStateObjectGotValue 241 | 242 | SINGLETON 243 | 244 | - (NSString*)name { return @"after object value"; } 245 | 246 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 247 | switch (token) { 248 | case sbjson4_token_object_close: 249 | case sbjson4_token_value_sep: 250 | return YES; 251 | break; 252 | default: 253 | return NO; 254 | break; 255 | } 256 | } 257 | 258 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 259 | parser.state = [SBJson4StreamParserStateObjectNeedKey sharedInstance]; 260 | } 261 | 262 | 263 | @end 264 | 265 | #pragma mark - 266 | 267 | @implementation SBJson4StreamParserStateObjectNeedKey 268 | 269 | SINGLETON 270 | 271 | - (NSString*)name { return @"in place of object key"; } 272 | 273 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 274 | return sbjson4_token_string == token || sbjson4_token_encoded == token; 275 | } 276 | 277 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 278 | parser.state = [SBJson4StreamParserStateObjectGotKey sharedInstance]; 279 | } 280 | 281 | - (BOOL)needKey { 282 | return YES; 283 | } 284 | 285 | @end 286 | 287 | #pragma mark - 288 | 289 | @implementation SBJson4StreamParserStateArrayStart 290 | 291 | SINGLETON 292 | 293 | - (NSString*)name { return @"at array start"; } 294 | 295 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 296 | switch (token) { 297 | case sbjson4_token_object_close: 298 | case sbjson4_token_entry_sep: 299 | case sbjson4_token_value_sep: 300 | return NO; 301 | break; 302 | 303 | default: 304 | return YES; 305 | break; 306 | } 307 | } 308 | 309 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 310 | parser.state = [SBJson4StreamParserStateArrayGotValue sharedInstance]; 311 | } 312 | 313 | @end 314 | 315 | #pragma mark - 316 | 317 | @implementation SBJson4StreamParserStateArrayGotValue 318 | 319 | SINGLETON 320 | 321 | - (NSString*)name { return @"after array value"; } 322 | 323 | 324 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 325 | return token == sbjson4_token_array_close || token == sbjson4_token_value_sep; 326 | } 327 | 328 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 329 | if (tok == sbjson4_token_value_sep) 330 | parser.state = [SBJson4StreamParserStateArrayNeedValue sharedInstance]; 331 | } 332 | 333 | @end 334 | 335 | #pragma mark - 336 | 337 | @implementation SBJson4StreamParserStateArrayNeedValue 338 | 339 | SINGLETON 340 | 341 | - (NSString*)name { return @"as array value"; } 342 | 343 | 344 | - (BOOL)parser:(SBJson4StreamParser *)parser shouldAcceptToken:(sbjson4_token_t)token { 345 | switch (token) { 346 | case sbjson4_token_array_close: 347 | case sbjson4_token_entry_sep: 348 | case sbjson4_token_object_close: 349 | case sbjson4_token_value_sep: 350 | return NO; 351 | break; 352 | 353 | default: 354 | return YES; 355 | break; 356 | } 357 | } 358 | 359 | - (void)parser:(SBJson4StreamParser *)parser shouldTransitionTo:(sbjson4_token_t)tok { 360 | parser.state = [SBJson4StreamParserStateArrayGotValue sharedInstance]; 361 | } 362 | 363 | @end 364 | 365 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamTokeniser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SuperPappi on 09/01/2013. 3 | // 4 | // To change the template use AppCode | Preferences | File Templates. 5 | // 6 | 7 | #import 8 | 9 | typedef enum { 10 | sbjson4_token_error = -1, 11 | sbjson4_token_eof, 12 | 13 | sbjson4_token_array_open, 14 | sbjson4_token_array_close, 15 | sbjson4_token_value_sep, 16 | 17 | sbjson4_token_object_open, 18 | sbjson4_token_object_close, 19 | sbjson4_token_entry_sep, 20 | 21 | sbjson4_token_bool, 22 | sbjson4_token_null, 23 | 24 | sbjson4_token_integer, 25 | sbjson4_token_real, 26 | 27 | sbjson4_token_string, 28 | sbjson4_token_encoded, 29 | } sbjson4_token_t; 30 | 31 | 32 | @interface SBJson4StreamTokeniser : NSObject 33 | 34 | @property (nonatomic, readonly, copy) NSString *error; 35 | 36 | - (void)appendData:(NSData*)data_; 37 | - (sbjson4_token_t)getToken:(char**)tok length:(NSUInteger*)len; 38 | 39 | @end 40 | 41 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamTokeniser.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SuperPappi on 09/01/2013. 3 | // 4 | // To change the template use AppCode | Preferences | File Templates. 5 | // 6 | 7 | 8 | #import "SBJson4StreamTokeniser.h" 9 | 10 | #define SBStringIsIllegalSurrogateHighCharacter(character) (((character) >= 0xD800UL) && ((character) <= 0xDFFFUL)) 11 | #define SBStringIsSurrogateLowCharacter(character) ((character >= 0xDC00UL) && (character <= 0xDFFFUL)) 12 | #define SBStringIsSurrogateHighCharacter(character) ((character >= 0xD800UL) && (character <= 0xDBFFUL)) 13 | 14 | @implementation SBJson4StreamTokeniser { 15 | NSMutableData *data; 16 | const char *bytes; 17 | NSUInteger index; 18 | NSUInteger offset; 19 | } 20 | 21 | - (void)setError:(NSString *)error { 22 | _error = [NSString stringWithFormat:@"%@ at index %lu", error, (unsigned long)(offset + index)]; 23 | } 24 | 25 | - (void)appendData:(NSData *)data_ { 26 | if (!data) { 27 | data = [data_ mutableCopy]; 28 | 29 | } else if (index) { 30 | // Discard data we've already parsed 31 | [data replaceBytesInRange:NSMakeRange(0, index) withBytes:"" length:0]; 32 | [data appendData:data_]; 33 | 34 | // Add to the offset for reporting 35 | offset += index; 36 | 37 | // Reset index to point to current position 38 | index = 0u; 39 | 40 | } 41 | else { 42 | [data appendData:data_]; 43 | } 44 | 45 | bytes = [data bytes]; 46 | } 47 | 48 | - (void)skipWhitespace { 49 | while (index < data.length) { 50 | switch (bytes[index]) { 51 | case ' ': 52 | case '\t': 53 | case '\r': 54 | case '\n': 55 | index++; 56 | break; 57 | default: 58 | return; 59 | } 60 | } 61 | } 62 | 63 | - (BOOL)getUnichar:(unichar *)ch { 64 | if ([self haveRemainingCharacters:1]) { 65 | *ch = (unichar) bytes[index]; 66 | return YES; 67 | } 68 | return NO; 69 | } 70 | 71 | - (BOOL)haveOneMoreCharacter { 72 | return [self haveRemainingCharacters:1]; 73 | } 74 | 75 | - (BOOL)haveRemainingCharacters:(NSUInteger)length { 76 | return data.length - index >= length; 77 | } 78 | 79 | - (sbjson4_token_t)match:(char *)str retval:(sbjson4_token_t)tok token:(char **)token length:(NSUInteger *)length { 80 | NSUInteger len = strlen(str); 81 | if ([self haveRemainingCharacters:len]) { 82 | if (!memcmp(bytes + index, str, len)) { 83 | *token = str; 84 | *length = len; 85 | index += len; 86 | return tok; 87 | } 88 | [self setError: [NSString stringWithFormat:@"Expected '%s' after initial '%.1s'", str, str]]; 89 | return sbjson4_token_error; 90 | } 91 | 92 | return sbjson4_token_eof; 93 | } 94 | 95 | - (BOOL)decodeHexQuad:(unichar*)quad { 96 | unichar tmp = 0; 97 | 98 | for (int i = 0; i < 4; i++, index++) { 99 | unichar c = bytes[index]; 100 | tmp *= 16; 101 | switch (c) { 102 | case '0' ... '9': 103 | tmp += c - '0'; 104 | break; 105 | 106 | case 'a' ... 'f': 107 | tmp += 10 + c - 'a'; 108 | break; 109 | 110 | case 'A' ... 'F': 111 | tmp += 10 + c - 'A'; 112 | break; 113 | 114 | default: 115 | return NO; 116 | } 117 | } 118 | *quad = tmp; 119 | return YES; 120 | } 121 | 122 | - (sbjson4_token_t)getStringToken:(char **)token length:(NSUInteger *)length { 123 | 124 | // Skip initial " 125 | index++; 126 | 127 | NSUInteger string_start = index; 128 | sbjson4_token_t tok = sbjson4_token_string; 129 | 130 | for (;;) { 131 | if (![self haveOneMoreCharacter]) 132 | return sbjson4_token_eof; 133 | 134 | switch (bytes[index]) { 135 | case 0 ... 0x1F: 136 | [self setError:[NSString stringWithFormat:@"Unescaped control character [0x%0.2X] in string", bytes[index]]]; 137 | return sbjson4_token_error; 138 | 139 | case '"': 140 | *token = (char *)(bytes + string_start); 141 | *length = index - string_start; 142 | index++; 143 | return tok; 144 | 145 | case '\\': 146 | tok = sbjson4_token_encoded; 147 | index++; 148 | if (![self haveOneMoreCharacter]) 149 | return sbjson4_token_eof; 150 | 151 | if (bytes[index] == 'u') { 152 | index++; 153 | if (![self haveRemainingCharacters:4]) 154 | return sbjson4_token_eof; 155 | 156 | unichar hi; 157 | if (![self decodeHexQuad:&hi]) { 158 | [self setError:@"Invalid hex quad"]; 159 | return sbjson4_token_error; 160 | } 161 | 162 | if (SBStringIsSurrogateHighCharacter(hi)) { 163 | if (![self haveRemainingCharacters:6]) 164 | return sbjson4_token_eof; 165 | 166 | unichar lo; 167 | if (bytes[index++] != '\\' || bytes[index++] != 'u' || ![self decodeHexQuad:&lo]) { 168 | [self setError:@"Missing low character in surrogate pair"]; 169 | return sbjson4_token_error; 170 | } 171 | 172 | if (!SBStringIsSurrogateLowCharacter(lo)) { 173 | [self setError:@"Invalid low character in surrogate pair"]; 174 | return sbjson4_token_error; 175 | } 176 | 177 | } else if (SBStringIsIllegalSurrogateHighCharacter(hi)) { 178 | [self setError:@"Invalid high character in surrogate pair"]; 179 | return sbjson4_token_error; 180 | 181 | } 182 | 183 | 184 | } else { 185 | switch (bytes[index]) { 186 | case '\\': 187 | case '/': 188 | case '"': 189 | case 'b': 190 | case 'n': 191 | case 'r': 192 | case 't': 193 | case 'f': 194 | index++; 195 | break; 196 | 197 | default: 198 | [self setError:[NSString stringWithFormat:@"Illegal escape character [%x]", bytes[index]]]; 199 | return sbjson4_token_error; 200 | } 201 | } 202 | 203 | break; 204 | 205 | default: 206 | index++; 207 | break; 208 | } 209 | } 210 | 211 | @throw @"FUT FUT FUT"; 212 | } 213 | 214 | - (sbjson4_token_t)getNumberToken:(char **)token length:(NSUInteger *)length { 215 | NSUInteger num_start = index; 216 | if (bytes[index] == '-') { 217 | index++; 218 | 219 | if (![self haveOneMoreCharacter]) 220 | return sbjson4_token_eof; 221 | } 222 | 223 | sbjson4_token_t tok = sbjson4_token_integer; 224 | if (bytes[index] == '0') { 225 | index++; 226 | 227 | if (![self haveOneMoreCharacter]) 228 | return sbjson4_token_eof; 229 | 230 | if (isdigit(bytes[index])) { 231 | [self setError:@"Leading zero is illegal in number"]; 232 | return sbjson4_token_error; 233 | } 234 | } 235 | 236 | while (isdigit(bytes[index])) { 237 | index++; 238 | if (![self haveOneMoreCharacter]) 239 | return sbjson4_token_eof; 240 | } 241 | 242 | if (![self haveOneMoreCharacter]) 243 | return sbjson4_token_eof; 244 | 245 | 246 | if (bytes[index] == '.') { 247 | index++; 248 | tok = sbjson4_token_real; 249 | 250 | if (![self haveOneMoreCharacter]) 251 | return sbjson4_token_eof; 252 | 253 | NSUInteger frac_start = index; 254 | while (isdigit(bytes[index])) { 255 | index++; 256 | if (![self haveOneMoreCharacter]) 257 | return sbjson4_token_eof; 258 | } 259 | 260 | if (frac_start == index) { 261 | [self setError:@"No digits after decimal point"]; 262 | return sbjson4_token_error; 263 | } 264 | } 265 | 266 | if (bytes[index] == 'e' || bytes[index] == 'E') { 267 | index++; 268 | tok = sbjson4_token_real; 269 | 270 | if (![self haveOneMoreCharacter]) 271 | return sbjson4_token_eof; 272 | 273 | if (bytes[index] == '-' || bytes[index] == '+') { 274 | index++; 275 | if (![self haveOneMoreCharacter]) 276 | return sbjson4_token_eof; 277 | } 278 | 279 | NSUInteger exp_start = index; 280 | while (isdigit(bytes[index])) { 281 | index++; 282 | if (![self haveOneMoreCharacter]) 283 | return sbjson4_token_eof; 284 | } 285 | 286 | if (exp_start == index) { 287 | [self setError:@"No digits in exponent"]; 288 | return sbjson4_token_error; 289 | } 290 | 291 | } 292 | 293 | if (num_start + 1 == index && bytes[num_start] == '-') { 294 | [self setError:@"No digits after initial minus"]; 295 | return sbjson4_token_error; 296 | } 297 | 298 | *token = (char *)(bytes + num_start); 299 | *length = index - num_start; 300 | return tok; 301 | } 302 | 303 | 304 | - (sbjson4_token_t)getToken:(char **)token length:(NSUInteger *)length { 305 | [self skipWhitespace]; 306 | NSUInteger copyOfIndex = index; 307 | 308 | unichar ch; 309 | if (![self getUnichar:&ch]) 310 | return sbjson4_token_eof; 311 | 312 | sbjson4_token_t tok; 313 | switch (ch) { 314 | case '{': { 315 | index++; 316 | tok = sbjson4_token_object_open; 317 | break; 318 | } 319 | case '}': { 320 | index++; 321 | tok = sbjson4_token_object_close; 322 | break; 323 | 324 | } 325 | case '[': { 326 | index++; 327 | tok = sbjson4_token_array_open; 328 | break; 329 | 330 | } 331 | case ']': { 332 | index++; 333 | tok = sbjson4_token_array_close; 334 | break; 335 | 336 | } 337 | case 't': { 338 | tok = [self match:"true" retval:sbjson4_token_bool token:token length:length]; 339 | break; 340 | 341 | } 342 | case 'f': { 343 | tok = [self match:"false" retval:sbjson4_token_bool token:token length:length]; 344 | break; 345 | 346 | } 347 | case 'n': { 348 | tok = [self match:"null" retval:sbjson4_token_null token:token length:length]; 349 | break; 350 | 351 | } 352 | case ',': { 353 | index++; 354 | tok = sbjson4_token_value_sep; 355 | break; 356 | 357 | } 358 | case ':': { 359 | index++; 360 | tok = sbjson4_token_entry_sep; 361 | break; 362 | 363 | } 364 | case '"': { 365 | tok = [self getStringToken:token length:length]; 366 | break; 367 | 368 | } 369 | case '-': 370 | case '0' ... '9': { 371 | tok = [self getNumberToken:token length:length]; 372 | break; 373 | 374 | } 375 | case '+': { 376 | self.error = @"Leading + is illegal in number"; 377 | tok = sbjson4_token_error; 378 | break; 379 | 380 | } 381 | default: { 382 | self.error = [NSString stringWithFormat:@"Illegal start of token [%c]", ch]; 383 | tok = sbjson4_token_error; 384 | break; 385 | } 386 | } 387 | 388 | if (tok == sbjson4_token_eof) { 389 | // We ran out of bytes before we could finish parsing the current token. 390 | // Back up to the start & wait for more data. 391 | index = copyOfIndex; 392 | } 393 | 394 | return tok; 395 | } 396 | 397 | @end 398 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamWriter.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | /// Enable JSON writing for non-native objects 36 | @interface NSObject (SBProxyForJson) 37 | 38 | /** 39 | Allows generation of JSON for otherwise unsupported classes. 40 | 41 | If you have a custom class that you want to create a JSON representation 42 | for you can implement this method in your class. It should return a 43 | representation of your object defined in terms of objects that can be 44 | translated into JSON. For example, a Person object might implement it like this: 45 | 46 | - (id)proxyForJson { 47 | return [NSDictionary dictionaryWithObjectsAndKeys: 48 | name, @"name", 49 | phone, @"phone", 50 | email, @"email", 51 | nil]; 52 | } 53 | 54 | */ 55 | - (id)proxyForJson; 56 | 57 | @end 58 | 59 | @class SBJson4StreamWriter; 60 | 61 | @protocol SBJson4StreamWriterDelegate 62 | 63 | - (void)writer:(SBJson4StreamWriter *)writer appendBytes:(const void *)bytes length:(NSUInteger)length; 64 | 65 | @end 66 | 67 | @class SBJson4StreamWriterState; 68 | 69 | /** 70 | The Stream Writer class. 71 | 72 | Accepts a stream of messages and writes JSON of these to its delegate object. 73 | 74 | This class provides a range of high-, mid- and low-level methods. You can mix 75 | and match calls to these. For example, you may want to call -writeArrayOpen 76 | to start an array and then repeatedly call -writeObject: with various objects 77 | before finishing off with a -writeArrayClose call. 78 | 79 | Objective-C types are mapped to JSON types in the following way: 80 | 81 | - NSNull -> null 82 | - NSString -> string 83 | - NSArray -> array 84 | - NSDictionary -> object 85 | - NSNumber's -initWithBool:YES -> true 86 | - NSNumber's -initWithBool:NO -> false 87 | - NSNumber -> number 88 | 89 | NSNumber instances created with the -numberWithBool: method are 90 | converted into the JSON boolean "true" and "false" values, and vice 91 | versa. Any other NSNumber instances are converted to a JSON number the 92 | way you would expect. 93 | 94 | @warning: In JSON the keys of an object must be strings. NSDictionary 95 | keys need not be, but attempting to convert an NSDictionary with 96 | non-string keys into JSON will throw an exception.* 97 | 98 | */ 99 | 100 | @interface SBJson4StreamWriter : NSObject { 101 | NSMutableDictionary *cache; 102 | } 103 | 104 | @property (nonatomic, weak) SBJson4StreamWriterState *state; // Internal 105 | @property (nonatomic, readonly, strong) NSMutableArray *stateStack; // Internal 106 | 107 | /** 108 | delegate to receive JSON output 109 | Delegate that will receive messages with output. 110 | */ 111 | @property (nonatomic, weak) id delegate; 112 | 113 | /** 114 | The maximum recursing depth. 115 | 116 | Defaults to 512. If the input is nested deeper than this the input will be deemed to be 117 | malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can 118 | turn off this security feature by setting the maxDepth value to 0. 119 | */ 120 | @property(nonatomic) NSUInteger maxDepth; 121 | 122 | /** 123 | Whether we are generating human-readable (multiline) JSON. 124 | 125 | Set whether or not to generate human-readable JSON. The default is NO, which produces 126 | JSON without any whitespace between tokens. If set to YES, generates human-readable 127 | JSON with linebreaks after each array value and dictionary key/value pair, indented two 128 | spaces per nesting level. 129 | */ 130 | @property(nonatomic) BOOL humanReadable; 131 | 132 | /** 133 | Whether or not to sort the dictionary keys in the output. 134 | 135 | If this is set to YES, the dictionary keys in the JSON output will be in sorted order. 136 | (This is useful if you need to compare two structures, for example.) The default is NO. 137 | */ 138 | @property(nonatomic) BOOL sortKeys; 139 | 140 | /** 141 | An optional comparator to be used if sortKeys is YES. 142 | 143 | If this is nil, sorting will be done via @selector(compare:). 144 | */ 145 | @property (nonatomic, copy) NSComparator sortKeysComparator; 146 | 147 | /// Contains the error description after an error has occured. 148 | @property (nonatomic, copy) NSString *error; 149 | 150 | /** 151 | Write an NSDictionary to the JSON stream. 152 | @return YES if successful, or NO on failure 153 | */ 154 | - (BOOL)writeObject:(NSDictionary*)dict; 155 | 156 | /** 157 | Write an NSArray to the JSON stream. 158 | @return YES if successful, or NO on failure 159 | */ 160 | - (BOOL)writeArray:(NSArray *)array; 161 | 162 | /** 163 | Start writing an Object to the stream 164 | @return YES if successful, or NO on failure 165 | */ 166 | - (BOOL)writeObjectOpen; 167 | 168 | /** 169 | Close the current object being written 170 | @return YES if successful, or NO on failure 171 | */ 172 | - (BOOL)writeObjectClose; 173 | 174 | /** Start writing an Array to the stream 175 | @return YES if successful, or NO on failure 176 | */ 177 | - (BOOL)writeArrayOpen; 178 | 179 | /** Close the current Array being written 180 | @return YES if successful, or NO on failure 181 | */ 182 | - (BOOL)writeArrayClose; 183 | 184 | /** Write a null to the stream 185 | @return YES if successful, or NO on failure 186 | */ 187 | - (BOOL)writeNull; 188 | 189 | /** Write a boolean to the stream 190 | @return YES if successful, or NO on failure 191 | */ 192 | - (BOOL)writeBool:(BOOL)x; 193 | 194 | /** Write a Number to the stream 195 | @return YES if successful, or NO on failure 196 | */ 197 | - (BOOL)writeNumber:(NSNumber*)n; 198 | 199 | /** Write a String to the stream 200 | @return YES if successful, or NO on failure 201 | */ 202 | - (BOOL)writeString:(NSString*)s; 203 | 204 | @end 205 | 206 | @interface SBJson4StreamWriter (Private) 207 | - (BOOL)writeValue:(id)v; 208 | - (void)appendBytes:(const void *)bytes length:(NSUInteger)length; 209 | @end 210 | 211 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamWriter.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #if !__has_feature(objc_arc) 34 | #error "This source file must be compiled with ARC enabled!" 35 | #endif 36 | 37 | #import "SBJson4StreamWriter.h" 38 | #import "SBJson4StreamWriterState.h" 39 | 40 | static NSNumber *kTrue; 41 | static NSNumber *kFalse; 42 | static NSNumber *kPositiveInfinity; 43 | static NSNumber *kNegativeInfinity; 44 | 45 | 46 | @implementation SBJson4StreamWriter 47 | 48 | + (void)initialize { 49 | kPositiveInfinity = [NSNumber numberWithDouble:+HUGE_VAL]; 50 | kNegativeInfinity = [NSNumber numberWithDouble:-HUGE_VAL]; 51 | kTrue = [NSNumber numberWithBool:YES]; 52 | kFalse = [NSNumber numberWithBool:NO]; 53 | } 54 | 55 | #pragma mark Housekeeping 56 | 57 | - (id)init { 58 | self = [super init]; 59 | if (self) { 60 | _maxDepth = 32u; 61 | _stateStack = [[NSMutableArray alloc] initWithCapacity:_maxDepth]; 62 | _state = [SBJson4StreamWriterStateStart sharedInstance]; 63 | cache = [[NSMutableDictionary alloc] initWithCapacity:32]; 64 | } 65 | return self; 66 | } 67 | 68 | #pragma mark Methods 69 | 70 | - (void)appendBytes:(const void *)bytes length:(NSUInteger)length { 71 | [_delegate writer:self appendBytes:bytes length:length]; 72 | } 73 | 74 | - (BOOL)writeObject:(NSDictionary *)dict { 75 | if (![self writeObjectOpen]) 76 | return NO; 77 | 78 | NSArray *keys = [dict allKeys]; 79 | 80 | if (_sortKeys) { 81 | if (_sortKeysComparator) { 82 | keys = [keys sortedArrayWithOptions:NSSortStable usingComparator:_sortKeysComparator]; 83 | } 84 | else{ 85 | keys = [keys sortedArrayUsingSelector:@selector(compare:)]; 86 | } 87 | } 88 | 89 | for (id k in keys) { 90 | if (![k isKindOfClass:[NSString class]]) { 91 | self.error = [NSString stringWithFormat:@"JSON object key must be string: %@", k]; 92 | return NO; 93 | } 94 | 95 | if (![self writeString:k]) 96 | return NO; 97 | if (![self writeValue:[dict objectForKey:k]]) 98 | return NO; 99 | } 100 | 101 | return [self writeObjectClose]; 102 | } 103 | 104 | - (BOOL)writeArray:(NSArray*)array { 105 | if (![self writeArrayOpen]) 106 | return NO; 107 | for (id v in array) 108 | if (![self writeValue:v]) 109 | return NO; 110 | return [self writeArrayClose]; 111 | } 112 | 113 | 114 | - (BOOL)writeObjectOpen { 115 | if ([_state isInvalidState:self]) return NO; 116 | if ([_state expectingKey:self]) return NO; 117 | [_state appendSeparator:self]; 118 | if (_humanReadable && _stateStack.count) [_state appendWhitespace:self]; 119 | 120 | [_stateStack addObject:_state]; 121 | self.state = [SBJson4StreamWriterStateObjectStart sharedInstance]; 122 | 123 | if (_maxDepth && _stateStack.count > _maxDepth) { 124 | self.error = @"Nested too deep"; 125 | return NO; 126 | } 127 | 128 | [_delegate writer:self appendBytes:"{" length:1]; 129 | return YES; 130 | } 131 | 132 | - (BOOL)writeObjectClose { 133 | if ([_state isInvalidState:self]) return NO; 134 | 135 | SBJson4StreamWriterState *prev = _state; 136 | 137 | self.state = [_stateStack lastObject]; 138 | [_stateStack removeLastObject]; 139 | 140 | if (_humanReadable) [prev appendWhitespace:self]; 141 | [_delegate writer:self appendBytes:"}" length:1]; 142 | 143 | [_state transitionState:self]; 144 | return YES; 145 | } 146 | 147 | - (BOOL)writeArrayOpen { 148 | if ([_state isInvalidState:self]) return NO; 149 | if ([_state expectingKey:self]) return NO; 150 | [_state appendSeparator:self]; 151 | if (_humanReadable && _stateStack.count) [_state appendWhitespace:self]; 152 | 153 | [_stateStack addObject:_state]; 154 | self.state = [SBJson4StreamWriterStateArrayStart sharedInstance]; 155 | 156 | if (_maxDepth && _stateStack.count > _maxDepth) { 157 | self.error = @"Nested too deep"; 158 | return NO; 159 | } 160 | 161 | [_delegate writer:self appendBytes:"[" length:1]; 162 | return YES; 163 | } 164 | 165 | - (BOOL)writeArrayClose { 166 | if ([_state isInvalidState:self]) return NO; 167 | if ([_state expectingKey:self]) return NO; 168 | 169 | SBJson4StreamWriterState *prev = _state; 170 | 171 | self.state = [_stateStack lastObject]; 172 | [_stateStack removeLastObject]; 173 | 174 | if (_humanReadable) [prev appendWhitespace:self]; 175 | [_delegate writer:self appendBytes:"]" length:1]; 176 | 177 | [_state transitionState:self]; 178 | return YES; 179 | } 180 | 181 | - (BOOL)writeNull { 182 | if ([_state isInvalidState:self]) return NO; 183 | if ([_state expectingKey:self]) return NO; 184 | [_state appendSeparator:self]; 185 | if (_humanReadable) [_state appendWhitespace:self]; 186 | 187 | [_delegate writer:self appendBytes:"null" length:4]; 188 | [_state transitionState:self]; 189 | return YES; 190 | } 191 | 192 | - (BOOL)writeBool:(BOOL)x { 193 | if ([_state isInvalidState:self]) return NO; 194 | if ([_state expectingKey:self]) return NO; 195 | [_state appendSeparator:self]; 196 | if (_humanReadable) [_state appendWhitespace:self]; 197 | 198 | if (x) 199 | [_delegate writer:self appendBytes:"true" length:4]; 200 | else 201 | [_delegate writer:self appendBytes:"false" length:5]; 202 | [_state transitionState:self]; 203 | return YES; 204 | } 205 | 206 | 207 | - (BOOL)writeValue:(id)o { 208 | if ([o isKindOfClass:[NSDictionary class]]) { 209 | return [self writeObject:o]; 210 | 211 | } else if ([o isKindOfClass:[NSArray class]]) { 212 | return [self writeArray:o]; 213 | 214 | } else if ([o isKindOfClass:[NSString class]]) { 215 | [self writeString:o]; 216 | return YES; 217 | 218 | } else if ([o isKindOfClass:[NSNumber class]]) { 219 | return [self writeNumber:o]; 220 | 221 | } else if ([o isKindOfClass:[NSNull class]]) { 222 | return [self writeNull]; 223 | 224 | } else if ([o respondsToSelector:@selector(proxyForJson)]) { 225 | return [self writeValue:[o proxyForJson]]; 226 | 227 | } 228 | 229 | self.error = [NSString stringWithFormat:@"JSON serialisation not supported for %@", [o class]]; 230 | return NO; 231 | } 232 | 233 | static const char *strForChar(int c) { 234 | switch (c) { 235 | case 0: return "\\u0000"; break; 236 | case 1: return "\\u0001"; break; 237 | case 2: return "\\u0002"; break; 238 | case 3: return "\\u0003"; break; 239 | case 4: return "\\u0004"; break; 240 | case 5: return "\\u0005"; break; 241 | case 6: return "\\u0006"; break; 242 | case 7: return "\\u0007"; break; 243 | case 8: return "\\b"; break; 244 | case 9: return "\\t"; break; 245 | case 10: return "\\n"; break; 246 | case 11: return "\\u000b"; break; 247 | case 12: return "\\f"; break; 248 | case 13: return "\\r"; break; 249 | case 14: return "\\u000e"; break; 250 | case 15: return "\\u000f"; break; 251 | case 16: return "\\u0010"; break; 252 | case 17: return "\\u0011"; break; 253 | case 18: return "\\u0012"; break; 254 | case 19: return "\\u0013"; break; 255 | case 20: return "\\u0014"; break; 256 | case 21: return "\\u0015"; break; 257 | case 22: return "\\u0016"; break; 258 | case 23: return "\\u0017"; break; 259 | case 24: return "\\u0018"; break; 260 | case 25: return "\\u0019"; break; 261 | case 26: return "\\u001a"; break; 262 | case 27: return "\\u001b"; break; 263 | case 28: return "\\u001c"; break; 264 | case 29: return "\\u001d"; break; 265 | case 30: return "\\u001e"; break; 266 | case 31: return "\\u001f"; break; 267 | case 34: return "\\\""; break; 268 | case 92: return "\\\\"; break; 269 | } 270 | NSLog(@"FUTFUTFUT: -->'%c'<---", c); 271 | return "FUTFUTFUT"; 272 | } 273 | 274 | - (BOOL)writeString:(NSString*)string { 275 | if ([_state isInvalidState:self]) return NO; 276 | [_state appendSeparator:self]; 277 | if (_humanReadable) [_state appendWhitespace:self]; 278 | 279 | NSMutableData *buf = [cache objectForKey:string]; 280 | if (!buf) { 281 | 282 | NSUInteger len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 283 | const char *utf8 = [string UTF8String]; 284 | NSUInteger written = 0, i = 0; 285 | 286 | buf = [NSMutableData dataWithCapacity:(NSUInteger)(len * 1.1f)]; 287 | [buf appendBytes:"\"" length:1]; 288 | 289 | for (i = 0; i < len; i++) { 290 | int c = utf8[i]; 291 | BOOL isControlChar = c >= 0 && c < 32; 292 | if (isControlChar || c == '"' || c == '\\') { 293 | if (i - written) 294 | [buf appendBytes:utf8 + written length:i - written]; 295 | written = i + 1; 296 | 297 | const char *t = strForChar(c); 298 | [buf appendBytes:t length:strlen(t)]; 299 | } 300 | } 301 | 302 | if (i - written) 303 | [buf appendBytes:utf8 + written length:i - written]; 304 | 305 | [buf appendBytes:"\"" length:1]; 306 | [cache setObject:buf forKey:string]; 307 | } 308 | 309 | [_delegate writer:self appendBytes:[buf bytes] length:[buf length]]; 310 | [_state transitionState:self]; 311 | return YES; 312 | } 313 | 314 | - (BOOL)writeNumber:(NSNumber*)number { 315 | if (number == kTrue || number == kFalse) 316 | return [self writeBool:[number boolValue]]; 317 | 318 | if ([_state isInvalidState:self]) return NO; 319 | if ([_state expectingKey:self]) return NO; 320 | [_state appendSeparator:self]; 321 | if (_humanReadable) [_state appendWhitespace:self]; 322 | 323 | if ([kPositiveInfinity isEqualToNumber:number]) { 324 | self.error = @"+Infinity is not a valid number in JSON"; 325 | return NO; 326 | 327 | } else if ([kNegativeInfinity isEqualToNumber:number]) { 328 | self.error = @"-Infinity is not a valid number in JSON"; 329 | return NO; 330 | 331 | } else if (isnan([number doubleValue])) { 332 | self.error = @"NaN is not a valid number in JSON"; 333 | return NO; 334 | } 335 | 336 | const char *objcType = [number objCType]; 337 | char num[128]; 338 | size_t len; 339 | 340 | switch (objcType[0]) { 341 | case 'c': case 'i': case 's': case 'l': case 'q': 342 | len = snprintf(num, sizeof num, "%lld", [number longLongValue]); 343 | break; 344 | case 'C': case 'I': case 'S': case 'L': case 'Q': 345 | len = snprintf(num, sizeof num, "%llu", [number unsignedLongLongValue]); 346 | break; 347 | case 'f': case 'd': default: { 348 | len = snprintf(num, sizeof num, "%.17g", [number doubleValue]); 349 | break; 350 | } 351 | } 352 | [_delegate writer:self appendBytes:num length: len]; 353 | [_state transitionState:self]; 354 | return YES; 355 | } 356 | 357 | @end 358 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamWriterState.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | @class SBJson4StreamWriter; 36 | 37 | @interface SBJson4StreamWriterState : NSObject 38 | + (id)sharedInstance; 39 | - (BOOL)isInvalidState:(SBJson4StreamWriter *)writer; 40 | - (void)appendSeparator:(SBJson4StreamWriter *)writer; 41 | - (BOOL)expectingKey:(SBJson4StreamWriter *)writer; 42 | - (void)transitionState:(SBJson4StreamWriter *)writer; 43 | - (void)appendWhitespace:(SBJson4StreamWriter *)writer; 44 | @end 45 | 46 | @interface SBJson4StreamWriterStateObjectStart : SBJson4StreamWriterState 47 | @end 48 | 49 | @interface SBJson4StreamWriterStateObjectKey : SBJson4StreamWriterStateObjectStart 50 | @end 51 | 52 | @interface SBJson4StreamWriterStateObjectValue : SBJson4StreamWriterState 53 | @end 54 | 55 | @interface SBJson4StreamWriterStateArrayStart : SBJson4StreamWriterState 56 | @end 57 | 58 | @interface SBJson4StreamWriterStateArrayValue : SBJson4StreamWriterState 59 | @end 60 | 61 | @interface SBJson4StreamWriterStateStart : SBJson4StreamWriterState 62 | @end 63 | 64 | @interface SBJson4StreamWriterStateComplete : SBJson4StreamWriterState 65 | @end 66 | 67 | @interface SBJson4StreamWriterStateError : SBJson4StreamWriterState 68 | @end 69 | 70 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4StreamWriterState.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #if !__has_feature(objc_arc) 34 | #error "This source file must be compiled with ARC enabled!" 35 | #endif 36 | 37 | #import "SBJson4StreamWriterState.h" 38 | #import "SBJson4StreamWriter.h" 39 | 40 | #define SINGLETON \ 41 | + (id)sharedInstance { \ 42 | static id state = nil; \ 43 | if (!state) { \ 44 | @synchronized(self) { \ 45 | if (!state) state = [[self alloc] init]; \ 46 | } \ 47 | } \ 48 | return state; \ 49 | } 50 | 51 | 52 | @implementation SBJson4StreamWriterState 53 | + (id)sharedInstance { return nil; } 54 | - (BOOL)isInvalidState:(SBJson4StreamWriter *)writer { return NO; } 55 | - (void)appendSeparator:(SBJson4StreamWriter *)writer {} 56 | - (BOOL)expectingKey:(SBJson4StreamWriter *)writer { return NO; } 57 | - (void)transitionState:(SBJson4StreamWriter *)writer {} 58 | - (void)appendWhitespace:(SBJson4StreamWriter *)writer { 59 | [writer appendBytes:"\n" length:1]; 60 | for (NSUInteger i = 0; i < writer.stateStack.count; i++) 61 | [writer appendBytes:" " length:2]; 62 | } 63 | @end 64 | 65 | @implementation SBJson4StreamWriterStateObjectStart 66 | 67 | SINGLETON 68 | 69 | - (void)transitionState:(SBJson4StreamWriter *)writer { 70 | writer.state = [SBJson4StreamWriterStateObjectValue sharedInstance]; 71 | } 72 | - (BOOL)expectingKey:(SBJson4StreamWriter *)writer { 73 | writer.error = @"JSON object key must be string"; 74 | return YES; 75 | } 76 | @end 77 | 78 | @implementation SBJson4StreamWriterStateObjectKey 79 | 80 | SINGLETON 81 | 82 | - (void)appendSeparator:(SBJson4StreamWriter *)writer { 83 | [writer appendBytes:"," length:1]; 84 | } 85 | @end 86 | 87 | @implementation SBJson4StreamWriterStateObjectValue 88 | 89 | SINGLETON 90 | 91 | - (void)appendSeparator:(SBJson4StreamWriter *)writer { 92 | [writer appendBytes:":" length:1]; 93 | } 94 | - (void)transitionState:(SBJson4StreamWriter *)writer { 95 | writer.state = [SBJson4StreamWriterStateObjectKey sharedInstance]; 96 | } 97 | - (void)appendWhitespace:(SBJson4StreamWriter *)writer { 98 | [writer appendBytes:" " length:1]; 99 | } 100 | @end 101 | 102 | @implementation SBJson4StreamWriterStateArrayStart 103 | 104 | SINGLETON 105 | 106 | - (void)transitionState:(SBJson4StreamWriter *)writer { 107 | writer.state = [SBJson4StreamWriterStateArrayValue sharedInstance]; 108 | } 109 | @end 110 | 111 | @implementation SBJson4StreamWriterStateArrayValue 112 | 113 | SINGLETON 114 | 115 | - (void)appendSeparator:(SBJson4StreamWriter *)writer { 116 | [writer appendBytes:"," length:1]; 117 | } 118 | @end 119 | 120 | @implementation SBJson4StreamWriterStateStart 121 | 122 | SINGLETON 123 | 124 | 125 | - (void)transitionState:(SBJson4StreamWriter *)writer { 126 | writer.state = [SBJson4StreamWriterStateComplete sharedInstance]; 127 | } 128 | - (void)appendSeparator:(SBJson4StreamWriter *)writer { 129 | } 130 | @end 131 | 132 | @implementation SBJson4StreamWriterStateComplete 133 | 134 | SINGLETON 135 | 136 | - (BOOL)isInvalidState:(SBJson4StreamWriter *)writer { 137 | writer.error = @"Stream is closed"; 138 | return YES; 139 | } 140 | @end 141 | 142 | @implementation SBJson4StreamWriterStateError 143 | 144 | SINGLETON 145 | 146 | @end 147 | 148 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4Writer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import 31 | 32 | /** 33 | The JSON writer class. 34 | 35 | This uses SBJson4StreamWriter internally. 36 | 37 | */ 38 | 39 | @interface SBJson4Writer : NSObject 40 | 41 | /** 42 | The maximum recursing depth. 43 | 44 | Defaults to 32. If the input is nested deeper than this the input will be deemed to be 45 | malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can 46 | turn off this security feature by setting the maxDepth value to 0. 47 | */ 48 | @property(nonatomic) NSUInteger maxDepth; 49 | 50 | /** 51 | Return an error trace, or nil if there was no errors. 52 | 53 | Note that this method returns the trace of the last method that failed. 54 | You need to check the return value of the call you're making to figure out 55 | if the call actually failed, before you know call this method. 56 | */ 57 | @property (nonatomic, readonly, copy) NSString *error; 58 | 59 | /** 60 | Whether we are generating human-readable (multiline) JSON. 61 | 62 | Set whether or not to generate human-readable JSON. The default is NO, which produces 63 | JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable 64 | JSON with linebreaks after each array value and dictionary key/value pair, indented two 65 | spaces per nesting level. 66 | */ 67 | @property(nonatomic) BOOL humanReadable; 68 | 69 | /** 70 | Whether or not to sort the dictionary keys in the output. 71 | 72 | If this is set to YES, the dictionary keys in the JSON output will be in sorted order. 73 | (This is useful if you need to compare two structures, for example.) The default is NO. 74 | */ 75 | @property(nonatomic) BOOL sortKeys; 76 | 77 | /** 78 | An optional comparator to be used if sortKeys is YES. 79 | 80 | If this is nil, sorting will be done via @selector(compare:). 81 | */ 82 | @property (nonatomic, copy) NSComparator sortKeysComparator; 83 | 84 | /** 85 | Generates string with JSON representation for the given object. 86 | 87 | Returns a string containing JSON representation of the passed in value, or nil on error. 88 | If nil is returned and error is not NULL, *error can be interrogated to find the cause of the error. 89 | 90 | @param value any instance that can be represented as JSON text. 91 | */ 92 | - (NSString*)stringWithObject:(id)value; 93 | 94 | /** 95 | Generates JSON representation for the given object. 96 | 97 | Returns an NSData object containing JSON represented as UTF8 text, or nil on error. 98 | 99 | @param value any instance that can be represented as JSON text. 100 | */ 101 | - (NSData*)dataWithObject:(id)value; 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/objc/SBJson4Writer.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #if !__has_feature(objc_arc) 31 | #error "This source file must be compiled with ARC enabled!" 32 | #endif 33 | 34 | #import "SBJson4Writer.h" 35 | #import "SBJson4StreamWriter.h" 36 | 37 | 38 | @interface SBJson4Writer () < SBJson4StreamWriterDelegate > 39 | @property (nonatomic, copy) NSString *error; 40 | @property (nonatomic, strong) NSMutableData *acc; 41 | @end 42 | 43 | @implementation SBJson4Writer 44 | 45 | - (id)init { 46 | self = [super init]; 47 | if (self) { 48 | self.maxDepth = 32u; 49 | } 50 | return self; 51 | } 52 | 53 | 54 | - (NSString*)stringWithObject:(id)value { 55 | NSData *data = [self dataWithObject:value]; 56 | if (data) 57 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 58 | return nil; 59 | } 60 | 61 | - (NSData*)dataWithObject:(id)object { 62 | self.error = nil; 63 | 64 | self.acc = [[NSMutableData alloc] initWithCapacity:8096u]; 65 | 66 | SBJson4StreamWriter *streamWriter = [[SBJson4StreamWriter alloc] init]; 67 | streamWriter.sortKeys = self.sortKeys; 68 | streamWriter.maxDepth = self.maxDepth; 69 | streamWriter.sortKeysComparator = self.sortKeysComparator; 70 | streamWriter.humanReadable = self.humanReadable; 71 | streamWriter.delegate = self; 72 | 73 | BOOL ok = NO; 74 | if ([object isKindOfClass:[NSDictionary class]]) 75 | ok = [streamWriter writeObject:object]; 76 | 77 | else if ([object isKindOfClass:[NSArray class]]) 78 | ok = [streamWriter writeArray:object]; 79 | 80 | else if ([object respondsToSelector:@selector(proxyForJson)]) 81 | return [self dataWithObject:[object proxyForJson]]; 82 | else { 83 | self.error = @"Not valid type for JSON"; 84 | return nil; 85 | } 86 | if (ok) 87 | return self.acc; 88 | self.error = streamWriter.error; 89 | return nil; 90 | } 91 | 92 | #pragma mark SBJson4StreamWriterDelegate 93 | 94 | - (void)writer:(SBJson4StreamWriter *)writer appendBytes:(const void *)bytes length:(NSUInteger)length { 95 | [self.acc appendBytes:bytes length:length]; 96 | } 97 | 98 | 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QQWallet.h: -------------------------------------------------------------------------------- 1 | // 2 | // QQWallet.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "QQWalletDefines.h" 11 | 12 | #define QQDefaultWallet [QQWallet shareInstance] 13 | 14 | @class QWTask; 15 | @interface QQWallet : NSObject 16 | @property (nonatomic, strong, readonly) QWTask* currentTask; 17 | + (QQWallet*) shareInstance; 18 | - (void) startTask:(QWTask*)task; 19 | - (void) handleResposeWithInfo:(NSDictionary*)infos; 20 | @end 21 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QQWallet.m: -------------------------------------------------------------------------------- 1 | // 2 | // QQWallet.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QQWallet.h" 10 | #import "QWTask.h" 11 | #import "QWPayment.h" 12 | #import "QWProduct.h" 13 | #import "QWURLEncodeEngine.h" 14 | #import "QWMessage.h" 15 | @implementation QQWallet 16 | @synthesize currentTask = _currentTask; 17 | 18 | + (QQWallet*) shareInstance 19 | { 20 | static QQWallet* share = nil; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | share = [QQWallet new]; 24 | }); 25 | return share; 26 | } 27 | 28 | - (void) startTask:(QWTask *)task 29 | { 30 | if (!SystemSupportQQWallet) { 31 | NSError *error = [NSError errorWithDomain:kQWErrorDomain 32 | code:QWErrorNotSupport 33 | userInfo:@{NSLocalizedDescriptionKey:@"not support"} 34 | ]; 35 | if (task.completionBlock) { 36 | task.completionBlock(nil , error); 37 | } 38 | return; 39 | } 40 | _currentTask = task; 41 | NSError* error = nil; 42 | if (![_currentTask start:&error]) { 43 | if (task.completionBlock) { 44 | task.completionBlock(nil, error); 45 | } 46 | } 47 | } 48 | 49 | - (void) handleResposeWithInfo:(NSDictionary *)infos 50 | { 51 | NSDictionary* actions = infos[kQWURLKeyAction]; 52 | NSDictionary* params = infos[kQWURLKeyParams]; 53 | 54 | QWMessage* message = [QWMessage new]; 55 | [message setValuesForKeysWithDictionary:params]; 56 | 57 | NSString* identifier = actions[kQWTaskKeyIdentifier]; 58 | if (![identifier isEqual:_currentTask.identifier]) { 59 | return; 60 | } 61 | NSError* error = nil; 62 | if (message.code != 0) { 63 | error = [NSError errorWithDomain:kQWErrorDomain code:message.code userInfo:@{NSLocalizedDescriptionKey: message.message ? message.message: @"unknow!"}]; 64 | } 65 | if (_currentTask.completionBlock) { 66 | _currentTask.completionBlock(message, error); 67 | } 68 | } 69 | @end 70 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWPayTask.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWPayTask.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWTask.h" 10 | #import "QWPayment.h" 11 | @interface QWPayTask : QWTask 12 | @property (nonatomic, strong) QWPayment* payment; 13 | - (instancetype) initWithPayment:(QWPayment*)payment; 14 | @end 15 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWPayTask.m: -------------------------------------------------------------------------------- 1 | // 2 | // QWPayTask.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWPayTask.h" 10 | 11 | @implementation QWPayTask 12 | 13 | + (NSString*) actionName 14 | { 15 | return @"pay1"; 16 | } 17 | - (BOOL) start:(NSError *__autoreleasing *)error 18 | { 19 | NSDictionary* infos = [_payment dictionaryWithAllValues]; 20 | return [self startWithParams:infos error:error]; 21 | } 22 | 23 | - (instancetype) initWithPayment:(QWPayment *)payment 24 | { 25 | self = [super init]; 26 | if (!self) { 27 | return self; 28 | } 29 | _payment = payment; 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWPayment.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWPayment.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString* const kQWPaymentOrderID; 12 | extern NSString* const kQWPaymentPartnerOrderId; 13 | extern NSString* const kQWPaymentTransTotal; 14 | extern NSString* const kQWPaymentCurrentCyID; 15 | extern NSString* const kQWPaymentTranstDate; 16 | extern NSString* const kQWPaymentProduct; 17 | 18 | 19 | @class QWProduct; 20 | @interface QWPayment : NSObject 21 | @property (nonatomic, strong) NSString* orderId; 22 | @property (nonatomic, strong) NSString* partnerOrderId; 23 | @property (nonatomic, assign) float transtotal; 24 | @property (nonatomic, assign) int currentCyId; 25 | @property (nonatomic, strong) NSDate* transtDate; 26 | @property (nonatomic, strong) QWProduct* product; 27 | - (NSDictionary*) dictionaryWithAllValues; 28 | @end 29 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWPayment.m: -------------------------------------------------------------------------------- 1 | // 2 | // QWPayment.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWPayment.h" 10 | #import "QWProduct.h" 11 | #import "NSDate+StringFormatter.h" 12 | NSString* const kQWPaymentOrderID = @"order_id"; 13 | NSString* const kQWPaymentPartnerOrderId = @"partner_order_id"; 14 | NSString* const kQWPaymentTransTotal = @"trans_total"; 15 | NSString* const kQWPaymentCurrentCyID = @"current_cy_id"; 16 | NSString* const kQWPaymentTranstDate = @"trans_date"; 17 | NSString* const kQWPaymentProduct = @"product"; 18 | 19 | @implementation QWPayment 20 | - (void) setValue:(id)value forKey:(NSString *)key 21 | { 22 | if ([key isEqual:kQWPaymentOrderID]) { 23 | [self setOrderId:value]; 24 | } else if ([key isEqual:kQWPaymentCurrentCyID]) 25 | { 26 | [self setCurrentCyId:[value intValue]]; 27 | } else if ([key isEqualToString:kQWPaymentPartnerOrderId]) 28 | { 29 | [self setPartnerOrderId:value]; 30 | } else if ([key isEqualToString:kQWPaymentTranstDate]) 31 | { 32 | NSDate* date = nil; 33 | if ([value isKindOfClass:[NSDate class]]) { 34 | date = value; 35 | } else if ([value isKindOfClass:[NSString class]]) 36 | { 37 | date = [NSDate dateFromString:value]; 38 | } 39 | [self setTranstDate:date]; 40 | } else if ([key isEqualToString:kQWPaymentProduct]) 41 | { 42 | QWProduct* product = nil; 43 | if ([value isKindOfClass:[QWProduct class]]) { 44 | product = value; 45 | } else if ([value isKindOfClass:[NSDictionary class]]) 46 | { 47 | product = [[QWProduct alloc] init]; 48 | [product setValuesForKeysWithDictionary:value]; 49 | } 50 | [self setProduct:product]; 51 | } else if ([key isEqualToString:kQWPaymentTransTotal]) 52 | { 53 | [self setTranstotal:[value floatValue]]; 54 | } 55 | } 56 | 57 | - (id) valueForKey:(NSString *)key 58 | { 59 | if ([key isEqual:kQWPaymentOrderID]) { 60 | return _orderId; 61 | } else if ([key isEqual:kQWPaymentCurrentCyID]) 62 | { 63 | return @(_currentCyId); 64 | } else if ([key isEqualToString:kQWPaymentPartnerOrderId]) 65 | { 66 | return _partnerOrderId; 67 | } else if ([key isEqualToString:kQWPaymentTranstDate]) 68 | { 69 | return [_transtDate string]; 70 | } else if ([key isEqualToString:kQWPaymentProduct]) 71 | { 72 | return [_product dictionaryWithAllValues]; 73 | } else if ([key isEqualToString:kQWPaymentTransTotal]) 74 | { 75 | return @(_transtotal); 76 | } 77 | return [NSNull null]; 78 | } 79 | 80 | - (NSDictionary*) dictionaryWithAllValues 81 | { 82 | return [self dictionaryWithValuesForKeys:@[kQWPaymentTransTotal, 83 | kQWPaymentTranstDate, 84 | kQWPaymentProduct, 85 | kQWPaymentPartnerOrderId, 86 | kQWPaymentOrderID, 87 | kQWPaymentCurrentCyID]]; 88 | } 89 | @end 90 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWProduct.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWProduct.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString* const kQWProductKeyIdentifer; 12 | extern NSString* const kQWProductKeyName; 13 | extern NSString* const kQWProductKeyNum; 14 | extern NSString* const kQWProductKeyDetail; 15 | 16 | 17 | @interface QWProduct : NSObject 18 | @property (nonatomic, strong) NSString* identifier; 19 | @property (nonatomic, strong) NSString* name; 20 | @property (nonatomic, assign) int num; 21 | @property (nonatomic, strong) NSString* detailDescription; 22 | 23 | - (NSDictionary*) dictionaryWithAllValues; 24 | @end 25 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWProduct.m: -------------------------------------------------------------------------------- 1 | // 2 | // QWProduct.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWProduct.h" 10 | 11 | NSString* const kQWProductKeyIdentifer = @"identifier"; 12 | NSString* const kQWProductKeyName = @"name"; 13 | NSString* const kQWProductKeyNum = @"num"; 14 | NSString* const kQWProductKeyDetail = @"detail"; 15 | 16 | @implementation QWProduct 17 | 18 | - (void) setValue:(id)value forKey:(NSString *)key 19 | { 20 | if ([key isEqual:kQWProductKeyIdentifer]) { 21 | [self setIdentifier:value]; 22 | } else if ([key isEqual:kQWProductKeyName]) 23 | { 24 | [self setName:value]; 25 | } else if ([key isEqual:kQWProductKeyNum]) 26 | { 27 | [self setNum:[value intValue]]; 28 | } else if ( [key isEqual:kQWProductKeyDetail]) 29 | { 30 | [self setDetailDescription:value]; 31 | } 32 | } 33 | 34 | - (id) valueForKey:(NSString *)key 35 | { 36 | if ([key isEqual:kQWProductKeyIdentifer]) { 37 | return _identifier; 38 | } else if ([key isEqual:kQWProductKeyName]) 39 | { 40 | return _name; 41 | } else if ([key isEqual:kQWProductKeyNum]) 42 | { 43 | return @(_num); 44 | } else if ( [key isEqual:kQWProductKeyDetail]) 45 | { 46 | return _detailDescription; 47 | } 48 | return [NSNull null]; 49 | } 50 | 51 | - (NSDictionary*) dictionaryWithAllValues 52 | { 53 | return [self dictionaryWithValuesForKeys:@[kQWProductKeyNum,kQWProductKeyName,kQWProductKeyIdentifer,kQWProductKeyDetail]]; 54 | } 55 | @end 56 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWServerPayTask.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWServerPayTask.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-4-3. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWTask.h" 10 | 11 | @interface QWServerPayTask : QWTask 12 | @property (nonatomic, strong) NSDictionary* params; 13 | 14 | - (instancetype) initWithParams:(NSDictionary*)params; 15 | @end 16 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWServerPayTask.m: -------------------------------------------------------------------------------- 1 | // 2 | // QWServerPayTask.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-4-3. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWServerPayTask.h" 10 | 11 | @implementation QWServerPayTask 12 | + (NSString*) actionName 13 | { 14 | return @"pay"; 15 | } 16 | - (BOOL) start:(NSError *__autoreleasing *)error 17 | { 18 | NSDictionary* infos = _params; 19 | return [self startWithParams:infos error:error]; 20 | } 21 | 22 | - (instancetype) initWithParams:(NSDictionary *)params 23 | { 24 | self = [super init]; 25 | if (!self) { 26 | return self; 27 | } 28 | _params = params; 29 | return self; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWTask.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWTask.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "QQWalletDefines.h" 11 | extern NSString* const kQWTaskKeyIdentifier; 12 | 13 | @interface QWTask : NSObject 14 | @property (nonatomic, strong) QQTaskCompletion completionBlock; 15 | @property (nonatomic, strong) NSString* identifier; 16 | + (NSString*) actionName; 17 | - (NSDictionary*) dictionaryWithAllValues; 18 | - (BOOL) start:(NSError *__autoreleasing *)error; 19 | - (BOOL) startWithParams:(NSDictionary *)params error:(NSError *__autoreleasing *)error; 20 | @end 21 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/QWTask.m: -------------------------------------------------------------------------------- 1 | // 2 | // QWTask.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWTask.h" 10 | #import "QQWalletDefines.h" 11 | #import "QWURLEncodeEngine.h" 12 | #import 13 | #import "QWApplication.h" 14 | 15 | NSString* const kQWTaskKeyIdentifier = @"identifier"; 16 | NSString* const kQWTaskKeyActionName = @"name"; 17 | 18 | @implementation QWTask 19 | @synthesize identifier = _identifier; 20 | - (instancetype) init 21 | { 22 | self = [super init]; 23 | if (!self) { 24 | return self; 25 | } 26 | _identifier = [NSString stringWithFormat:@"%d%d",rand(),rand()]; 27 | return self; 28 | } 29 | 30 | - (void) setValue:(id)value forKey:(NSString *)key 31 | { 32 | if ([key isEqual:kQWTaskKeyIdentifier]) 33 | { 34 | _identifier = value; 35 | } 36 | } 37 | 38 | - (id) valueForKey:(NSString *)key 39 | { 40 | if ([key isEqual:kQWTaskKeyActionName]) { 41 | return [[self class] actionName]; 42 | } else if ([key isEqual:kQWTaskKeyIdentifier]) 43 | { 44 | return _identifier; 45 | } 46 | return [NSNull null]; 47 | } 48 | 49 | - (NSDictionary*) dictionaryWithAllValues 50 | { 51 | return [self dictionaryWithValuesForKeys:@[kQWTaskKeyIdentifier, kQWTaskKeyActionName]]; 52 | } 53 | 54 | + (NSString*) actionName 55 | { 56 | return @"not_support"; 57 | } 58 | - (BOOL) start:(NSError *__autoreleasing *)error 59 | { 60 | return [self startWithParams:nil error:error]; 61 | } 62 | 63 | - (BOOL) startWithParams:(NSDictionary *)params error:(NSError *__autoreleasing *)error 64 | { 65 | NSURL* url = [QWURLEncodeEngine encodeWithAction:[self dictionaryWithAllValues] params:params error:error]; 66 | if (!url) { 67 | return NO; 68 | } 69 | [[UIApplication sharedApplication] openURL:url]; 70 | return YES; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/needsDoc/QQWalletDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // QQWalletDefines.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define DEFINE_EXTERN_STRING(key) extern NSString* const k##key 12 | 13 | 14 | /** 15 | * 代表QQWallet出错的域名 16 | */ 17 | extern NSString* const kQWErrorDomain; 18 | 19 | /** 20 | * QQWallet出错信息 21 | */ 22 | typedef enum { 23 | /** 24 | * 未知错误,不支持 25 | */ 26 | QWErrorNotSupport = 7000, 27 | /** 28 | * 参数传递错误 29 | */ 30 | QWErrorParamsError = 8000 31 | }QWErrorCode; 32 | 33 | /** 34 | * 手机QQ唤起钱包功能使用的URL Schema 35 | */ 36 | extern NSString* const kQWURLScheme; 37 | 38 | 39 | /** 40 | * 支付时传参,用来表示单号 41 | */ 42 | extern NSString* const kQWPayParamTokenID; 43 | /** 44 | * 支付时传参,用来表示关注公共账号的提示语 45 | */ 46 | extern NSString* const kQWPayParamPubHint; 47 | /** 48 | * 支付时穿残,用来表示关注公共账号的需要关注的公共账号信息 49 | */ 50 | extern NSString* const kQWPayParamPubAccountID; 51 | 52 | 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | BOOL IsSupportQQWallet(); 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | /** 63 | * 检查当前系统环境是否支持QQWallet调用 64 | * 65 | * @return BOOL 当前系统环境是否支持QQWallet调用 66 | */ 67 | #define SystemSupportQQWallet IsSupportQQWallet() 68 | 69 | 70 | 71 | @class QWMessage; 72 | /** 73 | * 进行QQWallet操作之后的回调函数,开发者可以在这里进行,QQWallet动作完成后接受完成结果,并进行处理 74 | * 75 | * @param message 包含返回结果信息的对象 76 | * @param error 出错信息,如果出错则改信息不为空,否则为空。 77 | */ 78 | typedef void(^QQTaskCompletion)(QWMessage* message, NSError* error); 79 | 80 | 81 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/needsDoc/QQWalletDefines.m: -------------------------------------------------------------------------------- 1 | // 2 | // QQWalletDefines.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QQWalletDefines.h" 10 | #import 11 | 12 | NSString* const kQWURLScheme = @"mqqwallet"; 13 | NSString* const kQWErrorDomain = @"com.tencent.qw.error"; 14 | 15 | // 16 | NSString* const kQWPayParamTokenID = @"tokenId"; 17 | NSString* const kQWPayParamPubHint = @"pubHint"; 18 | NSString* const kQWPayParamPubAccountID = @"pubAcc"; 19 | 20 | BOOL IsSupportQQWallet() 21 | { 22 | NSString* fullUrl = [NSString stringWithFormat:@"%@://wallet/pay?src_type=app&callback_name=myQQPayDemo&order_no=000000000111111&callback_type=scheme&version=1", kQWURLScheme]; 23 | 24 | NSURL* url = [NSURL URLWithString:fullUrl]; 25 | if([[UIApplication sharedApplication] canOpenURL:url]) 26 | { 27 | return YES; 28 | } 29 | return NO; 30 | } -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/needsDoc/QQWalletSDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // QQWalletSDK.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "QQWalletDefines.h" 11 | @class UIApplication; 12 | /** 13 | * 钱包SDK 14 | */ 15 | @interface QQWalletSDK : NSObject 16 | 17 | /** 18 | * 调起手Q进行支付,参数为从第三方APP从服务器获取的参数,透传到手机QQ内,唤起支付功能 19 | * 20 | * @param params 第三方APP下单后从无武器获取的参数 21 | * @param completion 回调的Block 22 | */ 23 | + (void) startPayWithServerParams:(NSDictionary*)params 24 | completion:(QQTaskCompletion)completion; 25 | 26 | /** 27 | * 注册第三方APP信息 28 | * 29 | * @param appId APP的唯一标识 30 | * @param urlScheme APP的URL SCHEME,用户在手机QQ内部完成功能后进行回调 31 | * @param name APP的名字 32 | */ 33 | + (void) registerQQWalletApplication:(NSString*)appId 34 | urlScheme:(NSString*)urlScheme 35 | name:(NSString*)name; 36 | 37 | /** 38 | * 在手机QQ完成功能后,进行对本APP进行回调,传递功能执行结果 39 | * 40 | * @param application 当前APP 41 | * @param url 出发回调的URL 42 | * @param sourceApplication 发起回调的APP 43 | * @param annotation nil 44 | * 45 | * @return 是否能够响应改回调 46 | */ 47 | + (BOOL) QQWalletSDKHanldeApplication:(UIApplication*)application 48 | openURL:(NSURL *)url 49 | sourceApplication:(NSString *)sourceApplication 50 | annotation:(id)annotation; 51 | @end 52 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/needsDoc/QQWalletSDK.m: -------------------------------------------------------------------------------- 1 | // 2 | // QQWalletSDK.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QQWalletSDK.h" 10 | #import 11 | #import "QWPayTask.h" 12 | #import "QQWallet.h" 13 | #import "QWApplication.h" 14 | #import "QWURLEncodeEngine.h" 15 | #import "QWServerPayTask.h" 16 | @implementation QQWalletSDK 17 | 18 | + (void) startPayWithServerParams:(NSDictionary*)params completion:(QQTaskCompletion)completion 19 | { 20 | QWServerPayTask* task = [[QWServerPayTask alloc] initWithParams:params]; 21 | task.completionBlock = completion; 22 | [QQDefaultWallet startTask:task]; 23 | } 24 | 25 | + (BOOL) QQWalletSDKHanldeApplication:(UIApplication*)application 26 | openURL:(NSURL *)url 27 | sourceApplication:(NSString *)sourceApplication 28 | annotation:(id)annotation 29 | { 30 | 31 | if (![[url absoluteString] hasPrefix:[QWApplication shareApplication].urlSchemePrefix]) { 32 | return NO; 33 | } 34 | NSError* error = nil; 35 | NSDictionary* infos = [QWURLEncodeEngine decodeWithInfo:url error:&error]; 36 | [[QQWallet shareInstance] handleResposeWithInfo:infos]; 37 | return YES; 38 | } 39 | 40 | + (void) registerQQWalletApplication:(NSString *)appId urlScheme:(NSString *)urlScheme name:(NSString *)name 41 | { 42 | QWApplication* application = [QWApplication shareApplication]; 43 | application.name = name; 44 | application.appId = appId; 45 | application.urlScheme = urlScheme; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/needsDoc/QWMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // QWMessage.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "QQWalletDefines.h" 11 | 12 | DEFINE_EXTERN_STRING(QWMessageCode); 13 | DEFINE_EXTERN_STRING(QWMessageText); 14 | DEFINE_EXTERN_STRING(QWMessageInfos); 15 | 16 | /** 17 | * 代表QQWallet调用,回调信息的类 18 | */ 19 | @interface QWMessage : NSObject 20 | /** 21 | * 回调结果代号,0代表成功,其他值代表出错(并对应响应的出错信息) 22 | */ 23 | @property (nonatomic, assign) int code; 24 | /** 25 | * 回调提示信息,如果出错,则代表出错的具体错误信息 26 | */ 27 | @property (nonatomic, strong) NSString* message; 28 | /** 29 | * 按照key-value的方式存储回调结果信息 30 | */ 31 | @property (nonatomic, strong) NSDictionary* infos; 32 | 33 | - (NSDictionary*) dictionaryWithAllValues; 34 | @end 35 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/sdk/needsDoc/QWMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // QWMessage.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "QWMessage.h" 10 | 11 | #define INIT_EXTERN_STRING(key, value) NSString* const k##key=@""#value 12 | INIT_EXTERN_STRING(QWMessageCode, code); 13 | INIT_EXTERN_STRING(QWMessageText, message); 14 | INIT_EXTERN_STRING(QWMessageInfos, infos); 15 | 16 | @implementation QWMessage 17 | - (void) setValue:(id)value forKey:(NSString *)key 18 | { 19 | if ([key isEqual:kQWMessageCode]) { 20 | _code = [value intValue]; 21 | } else if ([key isEqual:kQWMessageInfos]) 22 | { 23 | _infos = value; 24 | } else if ([key isEqual:kQWMessageText]) 25 | { 26 | _message = value; 27 | } 28 | } 29 | 30 | - (id) valueForKey:(NSString *)key 31 | { 32 | if ([key isEqual:kQWMessageCode]) { 33 | return @(_code) ; 34 | } else if ([key isEqual:kQWMessageInfos]) 35 | { 36 | return _infos ; 37 | } else if ([key isEqual:kQWMessageText]) 38 | { 39 | return _message; 40 | } 41 | return [NSNull null]; 42 | } 43 | 44 | - (NSDictionary*) dictionaryWithAllValues 45 | { 46 | return [self dictionaryWithValuesForKeys:@[kQWMessageText, kQWMessageInfos, kQWMessageCode]]; 47 | } 48 | @end 49 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/tools/LoadAbleCategory.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // LoadableCategory.h 4 | // Objective-Gems 5 | // 6 | // Copyright 2010 Karl Stenerud 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall remain in place 16 | // in this source code. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | 28 | /** Make all categories in the current file loadable without using -load-all. 29 | * 30 | * Normally, compilers will skip linking files that contain only categories. 31 | * Adding a call to this macro adds a dummy class, which causes the linker 32 | * to add the file. 33 | * 34 | * @param UNIQUE_NAME A globally unique name. 35 | */ 36 | #define MAKE_CATEGORIES_LOADABLE(UNIQUE_NAME) @interface FORCELOAD_##UNIQUE_NAME @end @implementation FORCELOAD_##UNIQUE_NAME @end -------------------------------------------------------------------------------- /QQWalletSDK/Classes/tools/NSDate+StringFormatter.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+StringFormatter.h 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-4-1. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | extern NSString* const kQWStringFormatString; 11 | 12 | 13 | @interface NSDate (StringFormatter) 14 | + (NSDate*) dateFromString:(NSString*)str; 15 | - (NSString *)string; 16 | @end 17 | -------------------------------------------------------------------------------- /QQWalletSDK/Classes/tools/NSDate+StringFormatter.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+StringFormatter.m 3 | // QQWalletSDK 4 | // 5 | // Created by stonedong on 14-4-1. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import "NSDate+StringFormatter.h" 10 | #import "LoadAbleCategory.h" 11 | 12 | NSString* const kQWStringFormatString = @"yyyy-MM-dd HH:mm:ss"; 13 | 14 | //MAKE_CATEGORIES_LOADABLE(NSDate_StringFormatter); 15 | 16 | @implementation NSDate (StringFormatter) 17 | - (NSString *)stringWithFormat:(NSString *)format { 18 | NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init]; 19 | [outputFormatter setDateFormat:format]; 20 | NSString *timestamp_str = [outputFormatter stringFromDate:self]; 21 | return timestamp_str; 22 | } 23 | 24 | - (NSString *)string { 25 | return [self stringWithFormat:kQWStringFormatString]; 26 | } 27 | 28 | + (NSDate *)dateFromString:(NSString *)string withFormat:(NSString *)format { 29 | NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init]; 30 | [inputFormatter setDateFormat:format]; 31 | NSDate *date = [inputFormatter dateFromString:string]; 32 | return date; 33 | } 34 | 35 | + (NSDate*) dateFromString:(NSString*)str 36 | { 37 | return [self dateFromString:str withFormat:kQWStringFormatString]; 38 | } 39 | @end 40 | -------------------------------------------------------------------------------- /QQWalletSDK/QQWalletSDK-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.tencent.qqwallet.example.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /QQWalletSDK/QQWalletSDK-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /QQWalletSDK/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /QQWalletSDKTests/QQWalletSDKTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.tencent.qqwallet.example.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /QQWalletSDKTests/QQWalletSDKTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // QQWalletSDKTests.m 3 | // QQWalletSDKTests 4 | // 5 | // Created by stonedong on 14-3-31. 6 | // Copyright (c) 2014年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QQWalletSDKTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation QQWalletSDKTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /QQWalletSDKTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | QQWalletSDK 2 | =========== 3 | 4 | Iphone QQ支付能力开放SDK封装。 5 | 6 | 7 | ##一、安装 8 | ###1.使用源码 9 | ####依赖(在使用需要安装以下工具): 10 | 11 | 1. [iOS-Universal-Framework](https://github.com/kstenerud/iOS-Universal-Framework) 12 | 13 | 14 | ####(1)cocoapods 15 | 16 | 1. 如果不存在Podfile文件通过以下命令创建Podfile文件,如果存在则忽略此步骤 17 | ```pod setup``` 18 | 2. 在Podfile中添加 19 | ``` 20 | pod "QQWalletSDK" 21 | ``` 22 | 3. 执行 23 | ``` 24 | pod install 25 | ``` 26 | 之后,变可以在您的工程中使用QQWalletSDK。 27 | 28 | ####(2)引入工程的方式 29 | 30 | 1. git clone https://github.com/TencentWallet/QQWalletSDK 31 | 32 | 2. 将QQWalletSDK工程拖入到您的工程当中,并且设置工程依赖关系: 33 | 34 | ![image](./Documents/imgs/target_dependence) 35 | 36 | 3. 链接framework: 37 | ![image](./Documents/imgs/link) 38 | 39 | 备注:在安装appledoc工具后,执行工程中的document目标将自动生成类文档。 40 | 41 | ####(3) [使用Example](https://github.com/TencentWallet/QQWalletSDKExample) 42 | 43 | 44 | ###2. 使用framework文件 45 | 46 | 您可以直接将位于./Framework/QQWalletSDK.framework的库文件链接到您的工程中使用。 47 | 48 | ##二、使用说明 49 | 50 | 1. 在您的工程中的plist文件中创建用于回调的URL SCHEMA。此URL SCHEMA用于手机QQ完成功能后,传递结果信息用。请尽量保证此URL SCHEMA不会与其他冲突。 51 | ![image](./Documents/imgs/urlschema) 52 | 53 | 2. 在**appDelegate.m中注册您的应用, 54 | 55 | ``` 56 | 57 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 58 | { 59 | // Override point for customization after application launch. 60 | /** 61 | * 注册第三方APP信息 62 | * 63 | * @param appId APP的唯一标识 64 | * @param urlScheme APP的URL SCHEME,用户在手机QQ内部完成功能后进行回调 65 | * @param name APP的名字 66 | */ 67 | [QQWalletSDK registerQQWalletApplication:@"aa.aa" urlScheme:@"com.qqwallet.demo" name:@"Demo"]; 68 | return YES; 69 | } 70 | ``` 71 | 72 | 3. 在函数```- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation``` 中注册回调监听 73 | 74 | ``` 75 | - (BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 76 | { 77 | if ([QQWalletSDK QQWalletSDKHanldeApplication:application openURL:url sourceApplication:sourceApplication annotation:annotation] ) { 78 | return YES; 79 | } 80 | return YES; 81 | } 82 | ``` 83 | 84 | ##三、功能调用 85 | (1)支付接口 86 | 87 | ``` 88 | /** 89 | * 调起手Q进行支付,参数为从第三方APP从服务器获取的参数,透传到手机QQ内,唤起支付功能 90 | * 91 | * @param params 第三方APP下单后从无武器获取的参数 92 | * @param completion 回调的Block 93 | */ 94 | + (void) startPayWithServerParams:(NSDictionary*)params 95 | completion:(QQTaskCompletion)completion; 96 | 97 | ``` 98 | 必须传入的参数: 99 | 100 | 101 | | 关键字 | 类型 | 含义 | 程序中使用变量 | 102 | | ------------- |:-------------:| -----:| --------: | 103 | | tokenId | NSString* | 订单号 | kQWPayParamTokenID | 104 | 105 | 可选参数,需要关注公共账号时填入下面两个参数: 106 | 107 | | 关键字 | 类型 | 含义 | 程序中使用变量 | 108 | | ------------- |:-------------:| -----:| --------: | 109 | | pubAcc | NSString* | 需要关注的公共账号唯一标识 | kQWPayParamPubAccountID | 110 | | pubHint | NSString* | 关注公共账号的提示语 | kQWPayParamPubHint | 111 | 112 | 您需要实现QQTaskComletion的内容来处理回调: 113 | 114 | ``` 115 | /** 116 | * 进行QQWallet操作之后的回调函数,开发者可以在这里进行,QQWallet动作完成后接受完成结果,并进行处理 117 | * 118 | * @param message 包含返回结果信息的对象 119 | * @param error 出错信息,如果出错则改信息不为空,否则为空。 120 | */ 121 | typedef void(^QQTaskCompletion)(QWMessage* message, NSError* error); 122 | ``` 123 | 124 | 其中message类的定义为: 125 | 126 | ``` 127 | /** 128 | * 代表QQWallet调用,回调信息的类 129 | */ 130 | @interface QWMessage : NSObject 131 | /** 132 | * 回调结果代号,0代表成功,其他值代表出错(并对应响应的出错信息) 133 | */ 134 | @property (nonatomic, assign) int code; 135 | /** 136 | * 回调提示信息,如果出错,则代表出错的具体错误信息 137 | */ 138 | @property (nonatomic, strong) NSString* message; 139 | /** 140 | * 按照key-value的方式存储回调结果信息 141 | */ 142 | @property (nonatomic, strong) NSDictionary* infos; 143 | 144 | - (NSDictionary*) dictionaryWithAllValues; 145 | @end 146 | 147 | ``` -------------------------------------------------------------------------------- /updatePods.sh: -------------------------------------------------------------------------------- 1 | !/usr/bin 2 | cp QQWalletSDK.podspec ~/.cocoapods/repos/master/QQWalletSDK/0.0.2/ 3 | git commit -m "cocoapods更改" 4 | git push 5 | 6 | 7 | 8 | --------------------------------------------------------------------------------