添加微信分分享按钮
authorguangchao.xu <guangchao.xu@supwisdom.com>
Wed, 8 Jul 2020 09:55:24 +0000 (17:55 +0800)
committerguangchao.xu <guangchao.xu@supwisdom.com>
Wed, 8 Jul 2020 09:55:24 +0000 (17:55 +0800)
60 files changed:
package-lock.json
package.json
platforms/android/android.json
platforms/android/app/build.gradle
platforms/android/app/src/main/AndroidManifest.xml
platforms/android/app/src/main/assets/www/cordova_plugins.js
platforms/android/app/src/main/assets/www/main.html
platforms/android/app/src/main/java/com/dalipolice/app/wxapi/EntryActivity.java [new file with mode: 0644]
platforms/android/app/src/main/java/com/dalipolice/app/wxapi/WXEntryActivity.java [new file with mode: 0644]
platforms/android/app/src/main/java/com/dalipolice/app/wxapi/WXPayEntryActivity.java [new file with mode: 0644]
platforms/android/app/src/main/java/xu/li/cordova/wechat/Util.java [new file with mode: 0644]
platforms/android/app/src/main/java/xu/li/cordova/wechat/Wechat.java [new file with mode: 0644]
platforms/android/app/src/main/res/xml/config.xml
platforms/android/cordova-plugin-wechat/app-android-build.gradle [new file with mode: 0644]
platforms/android/platform_www/cordova_plugins.js
platforms/android/platform_www/plugins/cordova-plugin-wechat/www/wechat.js [new file with mode: 0644]
platforms/android/project.properties
platforms/browser/browser.json
platforms/browser/platform_www/cordova_plugins.js
platforms/browser/platform_www/plugins/cordova-plugin-wechat/www/wechat.js [new file with mode: 0644]
platforms/ios/dlapp.xcodeproj/project.pbxproj
platforms/ios/dlapp/Plugins/cordova-plugin-wechat/AppDelegate+Wechat.h [new file with mode: 0644]
platforms/ios/dlapp/Plugins/cordova-plugin-wechat/AppDelegate+Wechat.m [new file with mode: 0644]
platforms/ios/dlapp/Plugins/cordova-plugin-wechat/CDVWechat.h [new file with mode: 0644]
platforms/ios/dlapp/Plugins/cordova-plugin-wechat/CDVWechat.m [new file with mode: 0644]
platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WXApi.h [new file with mode: 0644]
platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WXApiObject.h [new file with mode: 0644]
platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WechatAuthSDK.h [new file with mode: 0644]
platforms/ios/dlapp/Plugins/cordova-plugin-wechat/libWeChatSDK.a [new file with mode: 0644]
platforms/ios/dlapp/config.xml
platforms/ios/dlapp/dlapp-Info.plist
platforms/ios/frameworks.json
platforms/ios/ios.json
platforms/ios/platform_www/cordova_plugins.js
platforms/ios/platform_www/plugins/cordova-plugin-wechat/www/wechat.js [new file with mode: 0644]
plugins/android.json
plugins/browser.json
plugins/cordova-plugin-wechat/android-build.gradle [new file with mode: 0644]
plugins/cordova-plugin-wechat/donate.png [new file with mode: 0644]
plugins/cordova-plugin-wechat/package.json [new file with mode: 0644]
plugins/cordova-plugin-wechat/plugin.xml [new file with mode: 0644]
plugins/cordova-plugin-wechat/scripts/android-install.js [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/android/EntryActivity.java [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/android/Util.java [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/android/WXEntryActivity.java [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/android/WXPayEntryActivity.java [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/android/Wechat.java [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/AppDelegate+Wechat.h [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/AppDelegate+Wechat.m [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/CDVWechat.h [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/CDVWechat.m [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/README.txt [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WXApi.h [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WXApiObject.h [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WechatAuthSDK.h [new file with mode: 0644]
plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/libWeChatSDK.a [new file with mode: 0644]
plugins/cordova-plugin-wechat/www/wechat.js [new file with mode: 0644]
plugins/fetch.json
plugins/ios.json
www/main.html

index ad363bc..d50bafb 100644 (file)
             "resolved": "https://registry.npmjs.org/cordova-plugin-touch-id/-/cordova-plugin-touch-id-3.4.0.tgz",
             "integrity": "sha512-2rHwAngECGcIiYCSGDtduwisGCcmGbV++fMfOuoiXLdc0hd6uj9kmR3EWBtKF2/q4erZnl+5+u+0tFIFSprGzA=="
         },
+        "cordova-plugin-wechat": {
+            "version": "git+https://github.com/xu-li/cordova-plugin-wechat.git#82f4fbc259ea7371eed2eff57645b29fd76af718",
+            "from": "git+https://github.com/xu-li/cordova-plugin-wechat.git",
+            "requires": {
+                "shelljs": "^0.5.3"
+            },
+            "dependencies": {
+                "shelljs": {
+                    "version": "0.5.3",
+                    "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz",
+                    "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM="
+                }
+            }
+        },
         "cordova-plugin-whitelist": {
             "version": "1.3.3",
             "resolved": "https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.3.3.tgz",
index f844329..8de6f24 100644 (file)
@@ -32,6 +32,7 @@
     "cordova-plugin-statusbar": "^2.4.2",
     "cordova-plugin-themeablebrowser": "^0.2.18",
     "cordova-plugin-touch-id": "^3.4.0",
+    "cordova-plugin-wechat": "git+https://github.com/xu-li/cordova-plugin-wechat.git",
     "cordova-plugin-wkwebview-engine": "^1.2.1",
     "jpush-phonegap-plugin": "^3.7.2",
     "shelljs": "^0.8.3"
       "cordova-plugin-prevent-screenshot-coffice": {},
       "cordova-plugin-qqsdk": {
         "QQ_APP_ID": "101885581"
+      },
+      "cordova-plugin-wechat": {
+        "WECHATAPPID": "wxa483e2c392b08993",
+        "UNIVERSALLINK": "YOUR_UNIVERSAL_LINK"
       }
     },
     "platforms": [
index 105b5f2..02e24ed 100644 (file)
             {
               "xml": "<preference name=\"QQ_APP_ID\" value=\"101885581\" />",
               "count": 1
+            },
+            {
+              "xml": "<feature name=\"Wechat\"><param name=\"android-package\" value=\"xu.li.cordova.wechat.Wechat\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<preference name=\"WECHATAPPID\" value=\"wxa483e2c392b08993\" />",
+              "count": 1
             }
           ]
         }
           "/*": [
             {
               "xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />",
-              "count": 2
+              "count": 3
             },
             {
               "xml": "<uses-permission android:name=\"android.permission.CAMERA\" android:required=\"false\" />",
             {
               "xml": "<uses-permission android:name=\"android.permission.USE_FINGERPRINT\" />",
               "count": 1
+            },
+            {
+              "xml": "<uses-permission android:name=\"android.permission.INTERNET\" />",
+              "count": 1
+            },
+            {
+              "xml": "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />",
+              "count": 1
+            },
+            {
+              "xml": "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />",
+              "count": 1
+            },
+            {
+              "xml": "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />",
+              "count": 1
             }
           ],
           "/manifest": [
             {
               "xml": "<activity android:exported=\"true\" android:name=\"de.niklasmerz.cordova.biometric.BiometricActivity\" android:theme=\"@style/TransparentTheme\" />",
               "count": 1
+            },
+            {
+              "xml": "<activity android:exported=\"true\" android:label=\"@string/launcher_name\" android:launchMode=\"singleTask\" android:name=\".wxapi.WXEntryActivity\" android:taskAffinity=\"com.dalipolice.app\"><intent-filter><action android:name=\"android.intent.action.VIEW\" /><category android:name=\"android.intent.category.DEFAULT\" /><data android:scheme=\"wxa483e2c392b08993\" /></intent-filter></activity>",
+              "count": 1
+            },
+            {
+              "xml": "<activity android:exported=\"true\" android:label=\"@string/launcher_name\" android:launchMode=\"singleTop\" android:name=\".wxapi.WXPayEntryActivity\"><intent-filter><action android:name=\"android.intent.action.VIEW\" /><category android:name=\"android.intent.category.DEFAULT\" /><data android:scheme=\"wxa483e2c392b08993\" /></intent-filter></activity>",
+              "count": 1
             }
           ]
         }
     "cordova-plugin-qqsdk": {
       "QQ_APP_ID": "101885581",
       "PACKAGE_NAME": "com.dalipolice.app"
+    },
+    "cordova-plugin-wechat": {
+      "WECHATAPPID": "wxa483e2c392b08993",
+      "UNIVERSALLINK": "YOUR_UNIVERSAL_LINK",
+      "PACKAGE_NAME": "com.dalipolice.app"
     }
   },
   "dependent_plugins": {},
       "clobbers": [
         "QQSDK"
       ]
+    },
+    {
+      "id": "cordova-plugin-wechat.Wechat",
+      "file": "plugins/cordova-plugin-wechat/www/wechat.js",
+      "pluginId": "cordova-plugin-wechat",
+      "clobbers": [
+        "Wechat"
+      ]
     }
   ],
   "plugin_metadata": {
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
     "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
-    "cordova-plugin-qqsdk": "0.9.7"
+    "cordova-plugin-qqsdk": "0.9.7",
+    "cordova-plugin-wechat": "3.0.0"
   }
 }
index e758e33..6a72223 100644 (file)
@@ -92,6 +92,7 @@ ext {
 // PLUGIN GRADLE EXTENSIONS START
 apply from: "../cordova-plugin-qrscanner/dlapp-qrscanner.gradle"
 apply from: "../cordova-plugin-fingerprint-aio/app-build.gradle"
+apply from: "../cordova-plugin-wechat/app-android-build.gradle"
 // PLUGIN GRADLE EXTENSIONS END
 
 def hasBuildExtras1 = file('build-extras.gradle').exists()
index 4b6fab6..7ccac86 100644 (file)
             </intent-filter>
         </activity>
         <activity android:configChanges="orientation|keyboardHidden" android:name="com.tencent.connect.common.AssistActivity" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+        <activity android:exported="true" android:label="@string/launcher_name" android:launchMode="singleTask" android:name=".wxapi.WXEntryActivity" android:taskAffinity="com.dalipolice.app">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="wxa483e2c392b08993" />
+            </intent-filter>
+        </activity>
+        <activity android:exported="true" android:label="@string/launcher_name" android:launchMode="singleTop" android:name=".wxapi.WXPayEntryActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="wxa483e2c392b08993" />
+            </intent-filter>
+        </activity>
     </application>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.CAMERA" android:required="false" />
index 08297e5..02af8e9 100644 (file)
@@ -359,6 +359,14 @@ cordova.define('cordova/plugin_list', function(require, exports, module) {
       "clobbers": [
         "QQSDK"
       ]
+    },
+    {
+      "id": "cordova-plugin-wechat.Wechat",
+      "file": "plugins/cordova-plugin-wechat/www/wechat.js",
+      "pluginId": "cordova-plugin-wechat",
+      "clobbers": [
+        "Wechat"
+      ]
     }
   ];
   module.exports.metadata = {
@@ -381,6 +389,7 @@ cordova.define('cordova/plugin_list', function(require, exports, module) {
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
     "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
-    "cordova-plugin-qqsdk": "0.9.7"
+    "cordova-plugin-qqsdk": "0.9.7",
+    "cordova-plugin-wechat": "3.0.0"
   };
 });
\ No newline at end of file
index 8cced49..d9dcb90 100644 (file)
 <!doctype html>
 <html>
 
-<head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
-    <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
-    <link rel="stylesheet" type="text/css" href="css/aui.css" />
-    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
-    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
-    <link rel="stylesheet" type="text/css" href="css/index.css" />
-    <link rel="stylesheet" type="text/css" href="css/aui-slide.css">
-    <style type="text/css">
-        .aui-slide-node{
-            /*background: transparent!important;*/
-        }
-    </style>
-</head>
-<body>
-    <div id="main1">
-        <div id="maintop">
-            <div id="startslider" class="main" style="height: 240px;display: block;">
-                <div class="aui-slide-wrap" >
-                    <div class="aui-slide-node" style="padding:36px 30px 30px 30px;background-color: #ACEAF5" >
-                        <img src="img/p1.png"  style="background-color: #ACEAF5"/>
-                    </div>
-                    <div class="aui-slide-node" style="padding:36px 30px 30px 30px;background-color: #a4e4d4">
-                        <img src="img/p2.png"  style="background-color: #a4e4d4"/>
-                    </div>
-                    <div class="aui-slide-node " style="padding:36px 30px 30px 30px;background-color: #65abe7">
-                        <img src="img/p3.png"  style="background-color: #65abe7"/>
-                    </div>
-                    <div class="aui-slide-node " style="padding:36px 30px 30px 30px;background-color: #357a8a">
-                        <img src="img/p4.png"  style="background-color: #357a8a"/>
-                    </div>
-                </div>
-                <div class="aui-slide-page-wrap"><!--分页容器--></div>
-            </div>
-        </div>
-        <div style="position: absolute;bottom:50px;width: 100%;top:240px" id="maincontent">
-            <section class="aui-content " style="height: 100%">
-                <div class="aui-grid" style="height: 100%">
-                    <div class="aui-row" style="height: 50%">
-                        <div class="aui-col-xs-6  mainmeun-div" id="qrcodeBtn" style="background: #BBE6EC;">
-                            <div>
-                                <div class="center-in"><img src="img/m4.png" class="meun-img"class="meun-img"></div>
-                                <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">读码</div>
-                            </div>
-                        </div>
-                        <div class="aui-col-xs-6 mainmeun-div" id="scanBtn" style="background: #91DDEA;">
-                            <div>
-                                <div class="center-in"><img src="img/m2.png" class="meun-img"></div>
-                                <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">扫码</div>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="aui-row" style="height: 50%">
-                        <div class="aui-col-xs-6 mainmeun-div" id="qrcodeBtn1" style="background: #fff;">
-                            <div>
-                                <div class="center-in"><img src="img/m3.png" class="meun-img"></div>
-                                <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">访码</div>
-                            </div>
-                        </div>
-                        <div class="aui-col-xs-6 mainmeun-div" id="moreFuncBtn"  style="background: #FDD479;">
-                            <div>
-                                <div class="center-in"><img src="img/m1.png" class="meun-img"></div>
-                                <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">更多</div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </section>
-        </div>
-    </div>
-    <div id="main2" style="display: none">
-        <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
-            消息
-        </header>
-        <section class="aui-content">
-             <div class="weui-loadmore weui-loadmore_line"   >
-                <span class="weui-loadmore__tips" style="background: transparent;" id="nodatahint">暂无消息</span>
-            </div>
-        </section>
-    </div>
-    <div id="main3" style="display: none;">
-        <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
-            我的
-        </header>
-        <!-- bg-white -->
-        <section class="aui-content aui-margin-b-15" style=" margin-top: -2px;">
-            <div class="aui-list aui-media-list aui-list-noborder aui-bg-info user-info">
-                <div class="aui-list-item aui-list-item-middle top-btn">
-                    <div class="aui-media-list-item-inner ">
-                        <div class="aui-list-item-media" style="width:3rem;">
-                            <img src="img/icon_header.png" class="aui-img-round" id="userlogo">
-                        </div>
-                        <div class="aui-list-item-inner">
-                            <div class="aui-list-item-text text-white aui-font-size-18" id="username">匿名</div>
-                            <div class="aui-list-item-text text-white">
-                                <div><i class="aui-iconfont aui-icon-mobile aui-font-size-14"></i><span id="userphone"></span></div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </section>
-        <section class="aui-content">
-            <ul class="aui-list aui-list-in aui-margin-b-15">
-                <li class="aui-list-item" onclick="app.toCard()">
-                    <div class="aui-list-item-label-icon">
-                        <i class="aui-iconfont aui-icon-cert aui-text-info"></i>
-                    </div>
-                    <div class="aui-list-item-inner aui-list-item-arrow">
-                        <div class="aui-list-item-title">市民卡签约</div>
-                        <div class="aui-list-item-right" id="usersign"></div>
-                    </div>
-                </li>
-                <!--<li class="aui-list-item" id="accsignbtn">-->
-                    <!--<div class="aui-list-item-label-icon">-->
-                        <!--<i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>-->
-                    <!--</div>-->
-                    <!--<div class="aui-list-item-inner aui-list-item-arrow">-->
-                        <!--<div class="aui-list-item-title">签约代扣免密付</div>-->
-                        <!--<div class="aui-list-item-right" id="usersign"></div>-->
-                    <!--</div>-->
-                <!--</li>-->
-            </ul>
-            <ul class="aui-list aui-list-in aui-margin-b-15">
-                <li class="aui-list-item" id="usersec">
-                    <div class="aui-list-item-label-icon">
-                        <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
-                    </div>
-                    <div class="aui-list-item-inner aui-list-item-arrow">
-                        <div class="aui-list-item-title">账户安全</div>
-                    </div>
-                </li>
-            </ul>
-            <ul class="aui-list aui-list-in">
-                <li class="aui-list-item" id="usersec"  onclick="app.verisonCheck()">
-                    <div class="aui-list-item-label-icon">
-                        <i class="aui-iconfont aui-icon-info aui-text-info"></i>
-                    </div>
-                    <div class="aui-list-item-inner aui-list-item-arrow">
-                        <div class="aui-list-item-title">版本检测</div>
-                        <div class="aui-list-item-right" id="versioncheck">
-                        </div>
-                    </div>
-                </li>
-            </ul>
-                       <ul class="aui-list aui-list-in">
-                           <li class="aui-list-item" id="share" >
-                               <div class="aui-list-item-label-icon">
-                                   <i class="aui-iconfont aui-icon-info aui-text-info"></i>
-                               </div>
-                               <div class="aui-list-item-inner aui-list-item-arrow">
-                                   <div class="aui-list-item-title">分享测试</div>
-                                   <div class="aui-list-item-right" id="versioncheck">
-                                   </div>
-                               </div>
-                           </li>
-                       </ul>
-            <div style="padding: 20px;margin-top: 40px;">
-                <a href="javascript:app.logout();" class="weui-btn weui-btn_warn">退出登录</a>
-            </div>
-        </section>
-    </div>
-    <footer class="aui-bar aui-bar-tab aui-border-t" id="footer">
-        <div class="aui-bar-tab-item aui-active" tapmode onclick="switchTo(1)" id="tab1">
-            <i class="aui-iconfont aui-icon-home"></i>
-            <div class="aui-bar-tab-label">首页</div>
-        </div>
-        <div class="aui-bar-tab-item" tapmode onclick="switchTo(2)" id="tab2">
-            <i class="aui-iconfont aui-icon-comment"></i>
-            <div class="aui-bar-tab-label">消息</div>
-        </div>
-        <div class="aui-bar-tab-item" tapmode onclick="switchTo(3)" id="tab3">
-            <i class="aui-iconfont aui-icon-my"></i>
-            <div class="aui-bar-tab-label">我的</div>
-        </div>
-    </footer>
-</body>
-<script type="text/javascript" src="cordova.js"></script>
-<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
-<script type="text/javascript" src="js/lib/aui-tab.js"></script>
-<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
-<script type="text/javascript" src="js/lib/aui-slide.js"></script>
-<script type="text/javascript" src="js/server.js"></script>
-<script type="text/javascript" src="js/mainmenu.js"></script>
-<script type="text/javascript">
-var share = document.getElementById("share")
-       share.onclick=function(){
-               var args = {};
-               args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM;
-               args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite
-               args.url = 'https://cordova.apache.org/';
-               args.title = '这个是 Cordova QQ 新闻分享的标题';
-               args.description = '这个是 Cordova QQ 新闻分享的描述';
-               args.image = 'https://cordova.apache.org/static/img/cordova_bot.png';
-               QQSDK.shareNews(function () {
-                 alert('shareNews success');
-               }, function (failReason) {
-                 alert(failReason);
-               }, args);
-       }
-</script>
-</html>
\ No newline at end of file
+       <head>
+               <meta charset="utf-8">
+               <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
+               <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
+               <link rel="stylesheet" type="text/css" href="css/aui.css" />
+               <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+               <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+               <link rel="stylesheet" type="text/css" href="css/index.css" />
+               <link rel="stylesheet" type="text/css" href="css/aui-slide.css">
+               <style type="text/css">
+                       .aui-slide-node {
+                               /*background: transparent!important;*/
+                       }
+               </style>
+       </head>
+       <body>
+               <div id="main1">
+                       <div id="maintop">
+                               <div id="startslider" class="main" style="height: 240px;display: block;">
+                                       <div class="aui-slide-wrap">
+                                               <div class="aui-slide-node" style="padding:36px 30px 30px 30px;background-color: #ACEAF5">
+                                                       <img src="img/p1.png" style="background-color: #ACEAF5" />
+                                               </div>
+                                               <div class="aui-slide-node" style="padding:36px 30px 30px 30px;background-color: #a4e4d4">
+                                                       <img src="img/p2.png" style="background-color: #a4e4d4" />
+                                               </div>
+                                               <div class="aui-slide-node " style="padding:36px 30px 30px 30px;background-color: #65abe7">
+                                                       <img src="img/p3.png" style="background-color: #65abe7" />
+                                               </div>
+                                               <div class="aui-slide-node " style="padding:36px 30px 30px 30px;background-color: #357a8a">
+                                                       <img src="img/p4.png" style="background-color: #357a8a" />
+                                               </div>
+                                       </div>
+                                       <div class="aui-slide-page-wrap">
+                                               <!--分页容器-->
+                                       </div>
+                               </div>
+                       </div>
+                       <div style="position: absolute;bottom:50px;width: 100%;top:240px" id="maincontent">
+                               <section class="aui-content " style="height: 100%">
+                                       <div class="aui-grid" style="height: 100%">
+                                               <div class="aui-row" style="height: 50%">
+                                                       <div class="aui-col-xs-6  mainmeun-div" id="qrcodeBtn" style="background: #BBE6EC;">
+                                                               <div>
+                                                                       <div class="center-in"><img src="img/m4.png" class="meun-img" class="meun-img"></div>
+                                                                       <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">读码</div>
+                                                               </div>
+                                                       </div>
+                                                       <div class="aui-col-xs-6 mainmeun-div" id="scanBtn" style="background: #91DDEA;">
+                                                               <div>
+                                                                       <div class="center-in"><img src="img/m2.png" class="meun-img"></div>
+                                                                       <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">扫码</div>
+                                                               </div>
+                                                       </div>
+                                               </div>
+                                               <div class="aui-row" style="height: 50%">
+                                                       <div class="aui-col-xs-6 mainmeun-div" id="qrcodeBtn1" style="background: #fff;">
+                                                               <div>
+                                                                       <div class="center-in"><img src="img/m3.png" class="meun-img"></div>
+                                                                       <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">访码</div>
+                                                               </div>
+                                                       </div>
+                                                       <div class="aui-col-xs-6 mainmeun-div" id="moreFuncBtn" style="background: #FDD479;">
+                                                               <div>
+                                                                       <div class="center-in"><img src="img/m1.png" class="meun-img"></div>
+                                                                       <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">更多</div>
+                                                               </div>
+                                                       </div>
+                                               </div>
+                                       </div>
+                               </section>
+                       </div>
+               </div>
+               <div id="main2" style="display: none">
+                       <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
+                               消息
+                       </header>
+                       <section class="aui-content">
+                               <div class="weui-loadmore weui-loadmore_line">
+                                       <span class="weui-loadmore__tips" style="background: transparent;" id="nodatahint">暂无消息</span>
+                               </div>
+                       </section>
+               </div>
+               <div id="main3" style="display: none;">
+                       <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
+                               我的
+                       </header>
+                       <!-- bg-white -->
+                       <section class="aui-content aui-margin-b-15" style=" margin-top: -2px;">
+                               <div class="aui-list aui-media-list aui-list-noborder aui-bg-info user-info">
+                                       <div class="aui-list-item aui-list-item-middle top-btn">
+                                               <div class="aui-media-list-item-inner ">
+                                                       <div class="aui-list-item-media" style="width:3rem;">
+                                                               <img src="img/icon_header.png" class="aui-img-round" id="userlogo">
+                                                       </div>
+                                                       <div class="aui-list-item-inner">
+                                                               <div class="aui-list-item-text text-white aui-font-size-18" id="username">匿名</div>
+                                                               <div class="aui-list-item-text text-white">
+                                                                       <div><i class="aui-iconfont aui-icon-mobile aui-font-size-14"></i><span id="userphone"></span></div>
+                                                               </div>
+                                                       </div>
+                                               </div>
+                                       </div>
+                               </div>
+                       </section>
+                       <section class="aui-content">
+                               <ul class="aui-list aui-list-in aui-margin-b-15">
+                                       <li class="aui-list-item" onclick="app.toCard()">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-cert aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">市民卡签约</div>
+                                                       <div class="aui-list-item-right" id="usersign"></div>
+                                               </div>
+                                       </li>
+                                       <!--<li class="aui-list-item" id="accsignbtn">-->
+                                       <!--<div class="aui-list-item-label-icon">-->
+                                       <!--<i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>-->
+                                       <!--</div>-->
+                                       <!--<div class="aui-list-item-inner aui-list-item-arrow">-->
+                                       <!--<div class="aui-list-item-title">签约代扣免密付</div>-->
+                                       <!--<div class="aui-list-item-right" id="usersign"></div>-->
+                                       <!--</div>-->
+                                       <!--</li>-->
+                               </ul>
+                               <ul class="aui-list aui-list-in aui-margin-b-15">
+                                       <li class="aui-list-item" id="usersec">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">账户安全</div>
+                                               </div>
+                                       </li>
+                               </ul>
+                               <ul class="aui-list aui-list-in">
+                                       <li class="aui-list-item" id="usersec" onclick="app.verisonCheck()">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-info aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">版本检测</div>
+                                                       <div class="aui-list-item-right" id="versioncheck">
+                                                       </div>
+                                               </div>
+                                       </li>
+                               </ul>
+                               <ul class="aui-list aui-list-in">
+                                       <li class="aui-list-item" id="shareqq">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-info aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">qq分享测试</div>
+                                                       <div class="aui-list-item-right" id="versioncheck">
+                                                       </div>
+                                               </div>
+                                       </li>
+                               </ul>
+                               <ul class="aui-list aui-list-in">
+                                       <li class="aui-list-item" id="sharewx">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-info aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">wx分享测试</div>
+                                                       <div class="aui-list-item-right" id="versioncheck">
+                                                       </div>
+                                               </div>
+                                       </li>
+                               </ul>
+                               <div style="padding: 20px;margin-top: 40px;">
+                                       <a href="javascript:app.logout();" class="weui-btn weui-btn_warn">退出登录</a>
+                               </div>
+                       </section>
+               </div>
+               <footer class="aui-bar aui-bar-tab aui-border-t" id="footer">
+                       <div class="aui-bar-tab-item aui-active" tapmode onclick="switchTo(1)" id="tab1">
+                               <i class="aui-iconfont aui-icon-home"></i>
+                               <div class="aui-bar-tab-label">首页</div>
+                       </div>
+                       <div class="aui-bar-tab-item" tapmode onclick="switchTo(2)" id="tab2">
+                               <i class="aui-iconfont aui-icon-comment"></i>
+                               <div class="aui-bar-tab-label">消息</div>
+                       </div>
+                       <div class="aui-bar-tab-item" tapmode onclick="switchTo(3)" id="tab3">
+                               <i class="aui-iconfont aui-icon-my"></i>
+                               <div class="aui-bar-tab-label">我的</div>
+                       </div>
+               </footer>
+       </body>
+       <script type="text/javascript" src="cordova.js"></script>
+       <script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+       <script type="text/javascript" src="js/lib/aui-tab.js"></script>
+       <script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+       <script type="text/javascript" src="js/lib/aui-slide.js"></script>
+       <script type="text/javascript" src="js/server.js"></script>
+       <script type="text/javascript" src="js/mainmenu.js"></script>
+       <script type="text/javascript">
+               var shareqq = document.getElementById("shareqq");
+               var sharewx = document.getElementById("sharewx");
+               shareqq.onclick = function() {
+                       var args = {};
+                       args.client = QQSDK.ClientType.QQ; //QQSDK.ClientType.QQ,QQSDK.ClientType.TIM;
+                       args.scene = QQSDK.Scene.QQ; //QQSDK.Scene.QQZone,QQSDK.Scene.Favorite
+                       args.url = 'https://cordova.apache.org/';
+                       args.title = '这个是 Cordova QQ 新闻分享的标题';
+                       args.description = '这个是 Cordova QQ 新闻分享的描述';
+                       args.image = 'https://cordova.apache.org/static/img/cordova_bot.png';
+                       QQSDK.shareNews(function() {
+                               alert('shareNews success');
+                       }, function(failReason) {
+                               alert(failReason);
+                       }, args);
+               }
+               sharewx.onclick = function() {
+                       Wechat.share({
+                           message: {
+                               title: "Hi, there",
+                               description: "This is description.",
+                               thumb: "www/img/thumbnail.png",
+                               mediaTagName: "TEST-TAG-001",
+                               messageExt: "这是第三方带的测试字段",
+                               messageAction: "<action>dotalist</action>",
+                               media: {
+                                           type: Wechat.Type.WEBPAGE,
+                                           webpageUrl: "http://www.jason-z.com"
+                                       }
+                           },
+                           scene: Wechat.Scene.TIMELINE   // share to Timeline
+                       }, function () {
+                           alert("Success");
+                       }, function (reason) {
+                           alert("Failed: " + reason);
+                       });
+               }
+       </script>
+</html>
diff --git a/platforms/android/app/src/main/java/com/dalipolice/app/wxapi/EntryActivity.java b/platforms/android/app/src/main/java/com/dalipolice/app/wxapi/EntryActivity.java
new file mode 100644 (file)
index 0000000..9d25f66
--- /dev/null
@@ -0,0 +1,176 @@
+package com.dalipolice.app.wxapi;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.tencent.mm.opensdk.constants.ConstantsAPI;
+import com.tencent.mm.opensdk.modelbase.BaseReq;
+import com.tencent.mm.opensdk.modelbase.BaseResp;
+import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;
+import com.tencent.mm.opensdk.modelmsg.SendAuth;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
+import com.tencent.mm.opensdk.modelbiz.ChooseCardFromWXCardPackage;
+
+import org.apache.cordova.CallbackContext;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+import xu.li.cordova.wechat.Wechat;
+
+/**
+ * Created by xu.li<AthenaLightenedMyPath@gmail.com> on 9/1/15.
+ */
+public class EntryActivity extends Activity implements IWXAPIEventHandler {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        IWXAPI api = Wechat.getWxAPI(this);
+
+        if (api == null) {
+            startMainActivity();
+        } else {
+            api.handleIntent(getIntent(), this);
+        }
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+
+        setIntent(intent);
+
+        IWXAPI api = Wechat.getWxAPI(this);
+        if (api == null) {
+            startMainActivity();
+        } else {
+            api.handleIntent(intent, this);
+        }
+
+    }
+
+    @Override
+    public void onResp(BaseResp resp) {
+        Log.d(Wechat.TAG, resp.toString());
+
+        CallbackContext ctx = Wechat.getCurrentCallbackContext();
+
+        if (ctx == null) {
+            startMainActivity();
+            return ;
+        }
+
+        switch (resp.errCode) {
+            case BaseResp.ErrCode.ERR_OK:
+                switch (resp.getType()) {
+                    case ConstantsAPI.COMMAND_SENDAUTH:
+                        auth(resp);
+                        break;
+                    case ConstantsAPI.COMMAND_CHOOSE_CARD_FROM_EX_CARD_PACKAGE:
+                        plunckInvoiceData(resp);
+                        break;
+                    case ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM:
+                        Log.d(Wechat.TAG, "miniprogram back;");
+                        WXLaunchMiniProgram.Resp miniProResp = (WXLaunchMiniProgram.Resp) resp;
+                        launchMiniProResp(miniProResp);
+                        break;
+                    case ConstantsAPI.COMMAND_PAY_BY_WX:
+                    default:
+                        ctx.success();
+                        break;
+                }
+                break;
+            case BaseResp.ErrCode.ERR_USER_CANCEL:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_USER_CANCEL);
+                break;
+            case BaseResp.ErrCode.ERR_AUTH_DENIED:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_AUTH_DENIED);
+                break;
+            case BaseResp.ErrCode.ERR_SENT_FAILED:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_SENT_FAILED);
+                break;
+            case BaseResp.ErrCode.ERR_UNSUPPORT:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_UNSUPPORT);
+                break;
+            case BaseResp.ErrCode.ERR_COMM:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_COMMON);
+                break;
+            default:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_UNKNOWN);
+                break;
+        }
+
+        finish();
+    }
+
+    @Override
+    public void onReq(BaseReq req) {
+        finish();
+    }
+
+    protected void startMainActivity() {
+        Intent intent = new Intent();
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setPackage(getApplicationContext().getPackageName());
+        getApplicationContext().startActivity(intent);
+    }
+
+    protected void launchMiniProResp(WXLaunchMiniProgram.Resp launchMiniProResp){
+        CallbackContext ctx = Wechat.getCurrentCallbackContext();
+        String extraData =launchMiniProResp.extMsg; //对应小程序组件 <button open-type="launchApp"> 中的 app-parameter 属性
+        JSONObject response = new JSONObject();
+        try {
+            response.put("extMsg", extraData);
+        }catch (Exception e){
+            Log.e(Wechat.TAG, e.getMessage());
+        }
+        ctx.success(response);
+    }
+
+    protected void auth(BaseResp resp) {
+        SendAuth.Resp res = ((SendAuth.Resp) resp);
+
+        Log.d(Wechat.TAG, res.toString());
+
+        // get current callback context
+        CallbackContext ctx = Wechat.getCurrentCallbackContext();
+
+        if (ctx == null) {
+            return ;
+        }
+
+        JSONObject response = new JSONObject();
+        try {
+            response.put("code", res.code);
+            response.put("state", res.state);
+            response.put("country", res.country);
+            response.put("lang", res.lang);
+        } catch (JSONException e) {
+            Log.e(Wechat.TAG, e.getMessage());
+        }
+
+        ctx.success(response);
+    }
+
+    protected void plunckInvoiceData(BaseResp resp) {
+
+            CallbackContext ctx = Wechat.getCurrentCallbackContext();
+            ChooseCardFromWXCardPackage.Resp resp1 = (ChooseCardFromWXCardPackage.Resp) resp;
+            JSONObject response = new JSONObject();
+
+            try {
+                JSONArray resp2 = new JSONArray(resp1.cardItemList);
+                response.put("data", resp2);
+            } catch (JSONException e) {
+                Log.e(Wechat.TAG, e.getMessage());
+            }
+
+            ctx.success(response);
+        }
+}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/java/com/dalipolice/app/wxapi/WXEntryActivity.java b/platforms/android/app/src/main/java/com/dalipolice/app/wxapi/WXEntryActivity.java
new file mode 100644 (file)
index 0000000..8dc5c1e
--- /dev/null
@@ -0,0 +1,4 @@
+package com.dalipolice.app.wxapi;
+
+public class WXEntryActivity extends EntryActivity {
+}
diff --git a/platforms/android/app/src/main/java/com/dalipolice/app/wxapi/WXPayEntryActivity.java b/platforms/android/app/src/main/java/com/dalipolice/app/wxapi/WXPayEntryActivity.java
new file mode 100644 (file)
index 0000000..d461aac
--- /dev/null
@@ -0,0 +1,5 @@
+package com.dalipolice.app.wxapi;
+
+public class WXPayEntryActivity extends EntryActivity {
+
+}
diff --git a/platforms/android/app/src/main/java/xu/li/cordova/wechat/Util.java b/platforms/android/app/src/main/java/xu/li/cordova/wechat/Util.java
new file mode 100644 (file)
index 0000000..28bada2
--- /dev/null
@@ -0,0 +1,102 @@
+package xu.li.cordova.wechat;
+
+import android.content.Context;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class Util {
+
+    /**
+     * Read bytes from InputStream
+     *
+     * @link http://stackoverflow.com/questions/2436385/android-getting-from-a-uri-to-an-inputstream-to-a-byte-array
+     * @param inputStream
+     * @return
+     * @throws IOException
+     */
+    public static byte[] readBytes(InputStream inputStream) throws IOException {
+        // this dynamically extends to take the bytes you read
+        ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
+
+        // this is storage overwritten on each iteration with bytes
+        int bufferSize = 1024;
+        byte[] buffer = new byte[bufferSize];
+
+        // we need to know how may bytes were read to write them to the byteBuffer
+        int len = 0;
+        while ((len = inputStream.read(buffer)) != -1) {
+            byteBuffer.write(buffer, 0, len);
+        }
+
+        // and then we can return your byte array.
+        return byteBuffer.toByteArray();
+    }
+
+    public static File getCacheFolder(Context context) {
+        File cacheDir = null;
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            cacheDir = new File(Environment.getExternalStorageDirectory(), "cache");
+            if (!cacheDir.isDirectory()) {
+                cacheDir.mkdirs();
+            }
+        }
+
+        if(!cacheDir.isDirectory()) {
+            cacheDir = context.getCacheDir(); //get system cache folder
+        }
+
+        return cacheDir;
+    }
+
+    public static File downloadAndCacheFile(Context context, String url) {
+        URL fileURL = null;
+        try {
+            fileURL = new URL(url);
+
+            Log.d(Wechat.TAG, String.format("Start downloading file at %s.", url));
+
+            HttpURLConnection connection = (HttpURLConnection) fileURL.openConnection();
+            connection.connect();
+
+            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+                Log.e(Wechat.TAG, String.format("Failed to download file from %s, response code: %d.", url, connection.getResponseCode()));
+                return null;
+            }
+
+            InputStream inputStream = connection.getInputStream();
+
+            File cacheDir = getCacheFolder(context);
+            File cacheFile = new File(cacheDir, url.substring(url.lastIndexOf("/") + 1));
+            FileOutputStream outputStream = new FileOutputStream(cacheFile);
+
+            byte buffer[] = new byte[4096];
+            int dataSize;
+            while ((dataSize = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, dataSize);
+            }
+            outputStream.close();
+
+            Log.d(Wechat.TAG, String.format("File was downloaded and saved at %s.", cacheFile.getAbsolutePath()));
+
+            return cacheFile;
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+}
diff --git a/platforms/android/app/src/main/java/xu/li/cordova/wechat/Wechat.java b/platforms/android/app/src/main/java/xu/li/cordova/wechat/Wechat.java
new file mode 100644 (file)
index 0000000..291110c
--- /dev/null
@@ -0,0 +1,761 @@
+package xu.li.cordova.wechat;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Environment;
+import android.os.Build;
+import android.util.Base64;
+import android.util.Log;
+import android.webkit.URLUtil;
+
+import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;
+import com.tencent.mm.opensdk.modelmsg.SendAuth;
+import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
+import com.tencent.mm.opensdk.modelmsg.WXAppExtendObject;
+import com.tencent.mm.opensdk.modelmsg.WXEmojiObject;
+import com.tencent.mm.opensdk.modelmsg.WXFileObject;
+import com.tencent.mm.opensdk.modelmsg.WXImageObject;
+import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
+import com.tencent.mm.opensdk.modelmsg.WXMusicObject;
+import com.tencent.mm.opensdk.modelmsg.WXTextObject;
+import com.tencent.mm.opensdk.modelmsg.WXVideoObject;
+import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
+import com.tencent.mm.opensdk.modelmsg.WXMiniProgramObject;
+import com.tencent.mm.opensdk.modelpay.PayReq;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+import com.tencent.mm.opensdk.modelbiz.ChooseCardFromWXCardPackage;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.PluginResult;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import org.apache.cordova.CordovaPreferences;
+
+public class Wechat extends CordovaPlugin {
+
+    public static final String TAG = "Cordova.Plugin.Wechat";
+
+    public static final String PREFS_NAME = "Cordova.Plugin.Wechat";
+    public static final String WXAPPID_PROPERTY_KEY = "wechatappid";
+
+    public static final String ERROR_WECHAT_NOT_INSTALLED = "未安装微信";
+    public static final String ERROR_INVALID_PARAMETERS = "参数格式错误";
+    public static final String ERROR_SEND_REQUEST_FAILED = "发送请求失败";
+    public static final String ERROR_WECHAT_RESPONSE_COMMON = "普通错误";
+    public static final String ERROR_WECHAT_RESPONSE_USER_CANCEL = "用户点击取消并返回";
+    public static final String ERROR_WECHAT_RESPONSE_SENT_FAILED = "发送失败";
+    public static final String ERROR_WECHAT_RESPONSE_AUTH_DENIED = "授权失败";
+    public static final String ERROR_WECHAT_RESPONSE_UNSUPPORT = "微信不支持";
+    public static final String ERROR_WECHAT_RESPONSE_UNKNOWN = "未知错误";
+
+    public static final String EXTERNAL_STORAGE_IMAGE_PREFIX = "external://";
+    public static final int REQUEST_CODE_ENABLE_PERMISSION = 55433;
+    public static final String ANDROID_WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
+
+    public static final String KEY_ARG_MESSAGE = "message";
+    public static final String KEY_ARG_SCENE = "scene";
+    public static final String KEY_ARG_TEXT = "text";
+    public static final String KEY_ARG_MESSAGE_TITLE = "title";
+    public static final String KEY_ARG_MESSAGE_DESCRIPTION = "description";
+    public static final String KEY_ARG_MESSAGE_THUMB = "thumb";
+    public static final String KEY_ARG_MESSAGE_MEDIA = "media";
+    public static final String KEY_ARG_MESSAGE_MEDIA_TYPE = "type";
+    public static final String KEY_ARG_MESSAGE_MEDIA_WEBPAGEURL = "webpageUrl";
+    public static final String KEY_ARG_MESSAGE_MEDIA_IMAGE = "image";
+    public static final String KEY_ARG_MESSAGE_MEDIA_TEXT = "text";
+    public static final String KEY_ARG_MESSAGE_MEDIA_MUSICURL = "musicUrl";
+    public static final String KEY_ARG_MESSAGE_MEDIA_MUSICDATAURL = "musicDataUrl";
+    public static final String KEY_ARG_MESSAGE_MEDIA_VIDEOURL = "videoUrl";
+    public static final String KEY_ARG_MESSAGE_MEDIA_FILE = "file";
+    public static final String KEY_ARG_MESSAGE_MEDIA_EMOTION = "emotion";
+    public static final String KEY_ARG_MESSAGE_MEDIA_EXTINFO = "extInfo";
+    public static final String KEY_ARG_MESSAGE_MEDIA_URL = "url";
+    public static final String KEY_ARG_MESSAGE_MEDIA_USERNAME = "userName";
+    public static final String KEY_ARG_MESSAGE_MEDIA_MINIPROGRAMTYPE = "miniprogramType";
+    public static final String KEY_ARG_MESSAGE_MEDIA_MINIPROGRAM = "miniProgram";
+    public static final String KEY_ARG_MESSAGE_MEDIA_PATH = "path";
+    public static final String KEY_ARG_MESSAGE_MEDIA_WITHSHARETICKET = "withShareTicket";
+    public static final String KEY_ARG_MESSAGE_MEDIA_HDIMAGEDATA = "hdImageData";
+
+    public static final int TYPE_WECHAT_SHARING_APP = 1;
+    public static final int TYPE_WECHAT_SHARING_EMOTION = 2;
+    public static final int TYPE_WECHAT_SHARING_FILE = 3;
+    public static final int TYPE_WECHAT_SHARING_IMAGE = 4;
+    public static final int TYPE_WECHAT_SHARING_MUSIC = 5;
+    public static final int TYPE_WECHAT_SHARING_VIDEO = 6;
+    public static final int TYPE_WECHAT_SHARING_WEBPAGE = 7;
+    public static final int TYPE_WECHAT_SHARING_MINI = 8;
+
+    public static final int SCENE_SESSION = 0;
+    public static final int SCENE_TIMELINE = 1;
+    public static final int SCENE_FAVORITE = 2;
+
+    public static final int MAX_THUMBNAIL_SIZE = 320;
+
+    protected static CallbackContext currentCallbackContext;
+    protected static IWXAPI wxAPI;
+    protected static String appId;
+    protected static CordovaPreferences wx_preferences;
+
+    @Override
+    protected void pluginInitialize() {
+
+        super.pluginInitialize();
+
+        String id = getAppId(preferences);
+
+        // save app id
+        saveAppId(cordova.getActivity(), id);
+
+        // init api
+        initWXAPI();
+
+        Log.d(TAG, "plugin initialized.");
+    }
+
+    protected void initWXAPI() {
+        IWXAPI api = getWxAPI(cordova.getActivity());
+        if(wx_preferences == null) {
+            wx_preferences = preferences;
+        }
+        if (api != null) {
+            api.registerApp(getAppId(preferences));
+        }
+    }
+
+    /**
+     * Get weixin api
+     * @param ctx
+     * @return
+     */
+    public static IWXAPI getWxAPI(Context ctx) {
+        if (wxAPI == null) {
+            String appId = getSavedAppId(ctx);
+
+            if (!appId.isEmpty()) {
+                wxAPI = WXAPIFactory.createWXAPI(ctx, appId, true);
+            }
+        }
+
+        return wxAPI;
+    }
+
+    @Override
+    public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
+        Log.d(TAG, String.format("%s is called. Callback ID: %s.", action, callbackContext.getCallbackId()));
+
+        if (action.equals("share")) {
+            return share(args, callbackContext);
+        } else if (action.equals("sendAuthRequest")) {
+            return sendAuthRequest(args, callbackContext);
+        } else if (action.equals("sendPaymentRequest")) {
+            return sendPaymentRequest(args, callbackContext);
+        } else if (action.equals("isWXAppInstalled")) {
+            return isInstalled(callbackContext);
+        }else if (action.equals("chooseInvoiceFromWX")){
+            return chooseInvoiceFromWX(args, callbackContext);
+        }else if(action.equals("openMiniProgram")){
+            return openMiniProgram(args,callbackContext);
+        }
+
+        return false;
+    }
+
+    protected boolean share(CordovaArgs args, final CallbackContext callbackContext)
+            throws JSONException {
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        // check if installed
+        if (!api.isWXAppInstalled()) {
+            callbackContext.error(ERROR_WECHAT_NOT_INSTALLED);
+            return true;
+        }
+
+        // check if # of arguments is correct
+        final JSONObject params;
+        try {
+            params = args.getJSONObject(0);
+        } catch (JSONException e) {
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        final SendMessageToWX.Req req = new SendMessageToWX.Req();
+        req.transaction = buildTransaction();
+
+        if (params.has(KEY_ARG_MESSAGE)) {
+            //小程序卡片单独构建
+            JSONObject message = params.getJSONObject(KEY_ARG_MESSAGE);
+            if (message.has(KEY_ARG_MESSAGE_MEDIA)) {
+                JSONObject media = message.getJSONObject(KEY_ARG_MESSAGE_MEDIA);
+                int type = media.has(KEY_ARG_MESSAGE_MEDIA_TYPE) ? media
+                        .getInt(KEY_ARG_MESSAGE_MEDIA_TYPE) : TYPE_WECHAT_SHARING_MINI;
+                if (type == TYPE_WECHAT_SHARING_MINI) {
+                    req.transaction = buildTransaction(KEY_ARG_MESSAGE_MEDIA_MINIPROGRAM);
+                }
+            }
+        }
+
+        if (params.has(KEY_ARG_SCENE)) {
+            switch (params.getInt(KEY_ARG_SCENE)) {
+                case SCENE_FAVORITE:
+                    req.scene = SendMessageToWX.Req.WXSceneFavorite;
+                    break;
+                case SCENE_TIMELINE:
+                    req.scene = SendMessageToWX.Req.WXSceneTimeline;
+                    break;
+                case SCENE_SESSION:
+                    req.scene = SendMessageToWX.Req.WXSceneSession;
+                    break;
+                default:
+                    req.scene = SendMessageToWX.Req.WXSceneTimeline;
+            }
+        } else {
+            req.scene = SendMessageToWX.Req.WXSceneTimeline;
+        }
+
+        // run in background
+        cordova.getThreadPool().execute(new Runnable() {
+
+            @Override
+            public void run() {
+                try {
+                    req.message = buildSharingMessage(params);
+                } catch (JSONException e) {
+                    Log.e(TAG, "Failed to build sharing message.", e);
+
+                    // clear callback context
+                    currentCallbackContext = null;
+
+                    // send json exception error
+                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                }
+
+                if (api.sendReq(req)) {
+                    Log.i(TAG, "Message has been sent successfully.");
+                } else {
+                    Log.i(TAG, "Message has been sent unsuccessfully.");
+
+                    // clear callback context
+                    currentCallbackContext = null;
+
+                    // send error
+                    callbackContext.error(ERROR_SEND_REQUEST_FAILED);
+                }
+            }
+        });
+
+        // send no result
+        sendNoResultPluginResult(callbackContext);
+
+        return true;
+    }
+
+    protected boolean sendAuthRequest(CordovaArgs args, CallbackContext callbackContext) {
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        final SendAuth.Req req = new SendAuth.Req();
+        try {
+            req.scope = args.getString(0);
+            req.state = args.getString(1);
+        } catch (JSONException e) {
+            Log.e(TAG, e.getMessage());
+
+            req.scope = "snsapi_userinfo";
+            req.state = "wechat";
+        }
+
+        if (api.sendReq(req)) {
+            Log.i(TAG, "Auth request has been sent successfully.");
+
+            // send no result
+            sendNoResultPluginResult(callbackContext);
+        } else {
+            Log.i(TAG, "Auth request has been sent unsuccessfully.");
+
+            // send error
+            callbackContext.error(ERROR_SEND_REQUEST_FAILED);
+        }
+
+        return true;
+    }
+
+    protected boolean sendPaymentRequest(CordovaArgs args, CallbackContext callbackContext) {
+
+        // check if # of arguments is correct
+        final JSONObject params;
+        try {
+            params = args.getJSONObject(0);
+        } catch (JSONException e) {
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        PayReq req = new PayReq();
+
+        try {
+            // final String appid = params.getString("appid");
+            // final String savedAppid = getSavedAppId(cordova.getActivity());
+            // if (!savedAppid.equals(appid)) {
+            //     this.saveAppId(cordova.getActivity(), appid);
+            // }
+            req.appId = getAppId(preferences);
+            req.partnerId = params.has("mch_id") ? params.getString("mch_id") : params.getString("partnerid");
+            req.prepayId = params.has("prepay_id") ? params.getString("prepay_id") : params.getString("prepayid");
+            req.nonceStr = params.has("nonce") ? params.getString("nonce") : params.getString("noncestr");
+            req.timeStamp = params.getString("timestamp");
+            req.sign = params.getString("sign");
+            req.packageValue = "Sign=WXPay";
+        } catch (Exception e) {
+            Log.e(TAG, e.getMessage());
+
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        if (api.sendReq(req)) {
+            Log.i(TAG, "Payment request has been sent successfully.");
+
+            // send no result
+            sendNoResultPluginResult(callbackContext);
+        } else {
+            Log.i(TAG, "Payment request has been sent unsuccessfully.");
+
+            // send error
+            callbackContext.error(ERROR_SEND_REQUEST_FAILED);
+        }
+
+        return true;
+    }
+
+    protected boolean chooseInvoiceFromWX(CordovaArgs args, CallbackContext callbackContext) {
+
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        // check if # of arguments is correct
+        final JSONObject params;
+        try {
+            params = args.getJSONObject(0);
+        } catch (JSONException e) {
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        ChooseCardFromWXCardPackage.Req req = new ChooseCardFromWXCardPackage.Req();
+
+        try {
+            req.appId = getAppId(preferences);
+            req.cardType = "INVOICE";
+            req.signType = params.getString("signType");
+            req.cardSign = params.getString("cardSign");
+            req.nonceStr = params.getString("nonceStr");
+            req.timeStamp = params.getString("timeStamp");
+            req.canMultiSelect = "1";
+        } catch (Exception e) {
+            Log.e(TAG, e.getMessage());
+
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        if (api.sendReq(req)) {
+            Log.i(TAG, "Invoice request has been sent successfully.");
+
+            // send no result
+            sendNoResultPluginResult(callbackContext);
+        } else {
+            Log.i(TAG, "Invoice request has been sent unsuccessfully.");
+
+            // send error
+            callbackContext.error(ERROR_SEND_REQUEST_FAILED);
+        }
+
+        return true;
+    }
+
+    protected boolean isInstalled(CallbackContext callbackContext) {
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        if (!api.isWXAppInstalled()) {
+            callbackContext.success(0);
+        } else {
+            callbackContext.success(1);
+        }
+
+        return true;
+    }
+
+
+    protected WXMediaMessage buildSharingMessage(JSONObject params)
+            throws JSONException {
+        Log.d(TAG, "Start building message.");
+
+        // media parameters
+        WXMediaMessage.IMediaObject mediaObject = null;
+        WXMediaMessage wxMediaMessage = new WXMediaMessage();
+
+        if (params.has(KEY_ARG_TEXT)) {
+            WXTextObject textObject = new WXTextObject();
+            textObject.text = params.getString(KEY_ARG_TEXT);
+            mediaObject = textObject;
+            wxMediaMessage.description = textObject.text;
+        } else {
+            JSONObject message = params.getJSONObject(KEY_ARG_MESSAGE);
+            JSONObject media = message.getJSONObject(KEY_ARG_MESSAGE_MEDIA);
+
+            wxMediaMessage.title = message.getString(KEY_ARG_MESSAGE_TITLE);
+            wxMediaMessage.description = message.getString(KEY_ARG_MESSAGE_DESCRIPTION);
+
+            // thumbnail
+            Bitmap thumbnail = getThumbnail(message, KEY_ARG_MESSAGE_THUMB);
+            if (thumbnail != null) {
+                wxMediaMessage.setThumbImage(thumbnail);
+                thumbnail.recycle();
+            }
+
+            // check types
+            int type = media.has(KEY_ARG_MESSAGE_MEDIA_TYPE) ? media
+                    .getInt(KEY_ARG_MESSAGE_MEDIA_TYPE) : TYPE_WECHAT_SHARING_WEBPAGE;
+
+            switch (type) {
+                case TYPE_WECHAT_SHARING_APP:
+                    WXAppExtendObject appObject = new WXAppExtendObject();
+                    appObject.extInfo = media.getString(KEY_ARG_MESSAGE_MEDIA_EXTINFO);
+                    appObject.filePath = media.getString(KEY_ARG_MESSAGE_MEDIA_URL);
+                    mediaObject = appObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_EMOTION:
+                    WXEmojiObject emoObject = new WXEmojiObject();
+                    InputStream emoji = getFileInputStream(media.getString(KEY_ARG_MESSAGE_MEDIA_EMOTION));
+                    if (emoji != null) {
+                        try {
+                            emoObject.emojiData = Util.readBytes(emoji);
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                    mediaObject = emoObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_FILE:
+                    WXFileObject fileObject = new WXFileObject();
+                    InputStream file = getFileInputStream(media.getString(KEY_ARG_MESSAGE_MEDIA_FILE));
+                    if (file != null) {
+                        try {
+                            fileObject.fileData = Util.readBytes(file);
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                    mediaObject = fileObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_IMAGE:
+                    Bitmap image = getBitmap(message.getJSONObject(KEY_ARG_MESSAGE_MEDIA), KEY_ARG_MESSAGE_MEDIA_IMAGE, 0);
+                    // give some tips to user           
+                    if(image != null) {
+                        mediaObject = new WXImageObject(image);
+                        image.recycle();
+                    }
+                    break;
+
+                case TYPE_WECHAT_SHARING_MUSIC:
+                    WXMusicObject musicObject = new WXMusicObject();
+                    musicObject.musicUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_MUSICURL);
+                    musicObject.musicDataUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_MUSICDATAURL);
+                    mediaObject = musicObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_VIDEO:
+                    WXVideoObject videoObject = new WXVideoObject();
+                    videoObject.videoUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_VIDEOURL);
+                    mediaObject = videoObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_MINI:
+                    WXMiniProgramObject miniProgramObj = new WXMiniProgramObject();
+                    try {
+                        miniProgramObj.webpageUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_WEBPAGEURL); // 兼容低版本的网页链接
+                        miniProgramObj.miniprogramType = media.getInt(KEY_ARG_MESSAGE_MEDIA_MINIPROGRAMTYPE);// 正式版:0,测试版:1,体验版:2
+                        miniProgramObj.userName = media.getString(KEY_ARG_MESSAGE_MEDIA_USERNAME);     // 小程序原始id
+                        miniProgramObj.path = media.getString(KEY_ARG_MESSAGE_MEDIA_PATH);            //小程序页面路径
+                        miniProgramObj.withShareTicket = media.getBoolean(KEY_ARG_MESSAGE_MEDIA_WITHSHARETICKET); // 是否使用带shareTicket的分享
+                        wxMediaMessage = new WXMediaMessage(miniProgramObj);
+                        wxMediaMessage.title = message.getString(KEY_ARG_MESSAGE_TITLE);                    // 小程序消息title
+                        wxMediaMessage.description = message.getString(KEY_ARG_MESSAGE_DESCRIPTION);               // 小程序消息desc
+                        wxMediaMessage.thumbData = Util.readBytes(getFileInputStream(media.getString(KEY_ARG_MESSAGE_MEDIA_HDIMAGEDATA))); // 小程序消息封面图片,小于128k
+                        return wxMediaMessage;
+                    }catch (Exception e){
+                        Log.e(TAG, e.getMessage());
+                    }
+                    break;
+
+                case TYPE_WECHAT_SHARING_WEBPAGE:
+                default:
+                    mediaObject = new WXWebpageObject(media.getString(KEY_ARG_MESSAGE_MEDIA_WEBPAGEURL));
+            }
+        }
+
+        wxMediaMessage.mediaObject = mediaObject;
+
+        return wxMediaMessage;
+    }
+
+    private String buildTransaction() {
+        return String.valueOf(System.currentTimeMillis());
+    }
+
+    private String buildTransaction(final String type) {
+        return type + System.currentTimeMillis();
+    }
+
+    protected Bitmap getThumbnail(JSONObject message, String key) {
+        return getBitmap(message, key, MAX_THUMBNAIL_SIZE);
+    }
+
+    protected Bitmap getBitmap(JSONObject message, String key, int maxSize) {
+        Bitmap bmp = null;
+        String url = null;
+
+        try {
+            if (!message.has(key)) {
+                return null;
+            }
+
+            url = message.getString(key);
+
+            // get input stream
+            InputStream inputStream = getFileInputStream(url);
+            if (inputStream == null) {
+                return null;
+            }
+
+            // decode it
+            // @TODO make sure the image is not too big, or it will cause out of memory
+            BitmapFactory.Options options = new BitmapFactory.Options();
+            bmp = BitmapFactory.decodeStream(inputStream, null, options);
+
+            // scale
+            if (maxSize > 0 && (options.outWidth > maxSize || options.outHeight > maxSize)) {
+
+                Log.d(TAG, String.format("Bitmap was decoded, dimension: %d x %d, max allowed size: %d.",
+                        options.outWidth, options.outHeight, maxSize));
+
+                int width = 0;
+                int height = 0;
+
+                if (options.outWidth > options.outHeight) {
+                    width = maxSize;
+                    height = width * options.outHeight / options.outWidth;
+                } else {
+                    height = maxSize;
+                    width = height * options.outWidth / options.outHeight;
+                }
+
+                Bitmap scaled = Bitmap.createScaledBitmap(bmp, width, height, true);
+                bmp.recycle();
+
+                int length = scaled.getRowBytes() * scaled.getHeight();
+
+                if(length > (maxSize/10)*1024) {
+                    scaled = compressImage(scaled,(maxSize/10));
+                }
+
+                bmp = scaled;
+            }
+
+            inputStream.close();
+
+        } catch (JSONException e) {
+            bmp = null;
+            e.printStackTrace();
+        } catch (IOException e) {
+            bmp = null;
+            e.printStackTrace();
+        }
+
+        return bmp;
+    }
+
+
+    /**
+     * compress bitmap by quility
+     */
+    protected  Bitmap compressImage(Bitmap image,Integer maxSize) {
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
+        int options = 90;
+
+        while (baos.toByteArray().length / 1024 > maxSize) {
+            baos.reset();
+            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
+            options -= 10;
+        }
+        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
+        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
+        return bitmap;
+    }
+
+    /**
+     * Get input stream from a url
+     */
+    protected InputStream getFileInputStream(String url) {
+        InputStream inputStream = null;
+        try {
+
+            if (URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)) {
+
+                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
+                    if (!cordova.hasPermission(ANDROID_WRITE_EXTERNAL_STORAGE)) {
+                        cordova.requestPermission(this, REQUEST_CODE_ENABLE_PERMISSION, ANDROID_WRITE_EXTERNAL_STORAGE);
+                    }
+                }
+
+                File file = Util.downloadAndCacheFile(webView.getContext(), url);
+
+                if (file == null) {
+                    Log.d(TAG, String.format("File could not be downloaded from %s.", url));
+                    return null;
+                }
+
+                // url = file.getAbsolutePath();
+                inputStream = new FileInputStream(file);
+
+                Log.d(TAG, String.format("File was downloaded and cached to %s.", file.getAbsolutePath()));
+
+            } else if (url.startsWith("data:image")) {  // base64 image
+
+                String imageDataBytes = url.substring(url.indexOf(",") + 1);
+                byte imageBytes[] = Base64.decode(imageDataBytes.getBytes(), Base64.DEFAULT);
+                inputStream = new ByteArrayInputStream(imageBytes);
+
+                Log.d(TAG, "Image is in base64 format.");
+
+            } else if (url.startsWith(EXTERNAL_STORAGE_IMAGE_PREFIX)) { // external path
+
+                url = Environment.getExternalStorageDirectory().getAbsolutePath() + url.substring(EXTERNAL_STORAGE_IMAGE_PREFIX.length());
+                inputStream = new FileInputStream(url);
+
+                Log.d(TAG, String.format("File is located on external storage at %s.", url));
+
+            } else if (!url.startsWith("/")) { // relative path
+
+                inputStream = cordova.getActivity().getApplicationContext().getAssets().open(url);
+
+                Log.d(TAG, String.format("File is located in assets folder at %s.", url));
+
+            } else {
+
+                inputStream = new FileInputStream(url);
+
+                Log.d(TAG, String.format("File is located at %s.", url));
+
+            }
+
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return inputStream;
+    }
+
+    public static String getAppId(CordovaPreferences f_preferences) {
+        if (appId == null) {
+            if(f_preferences != null) {
+                appId = f_preferences.getString(WXAPPID_PROPERTY_KEY, "");
+            }else if(wx_preferences != null){
+                appId = wx_preferences.getString(WXAPPID_PROPERTY_KEY, "");
+            }
+        }
+
+        return appId;
+    }
+
+    /**
+     * Get saved app id
+     * @param ctx
+     * @return
+     */
+    public static String getSavedAppId(Context ctx) {
+        SharedPreferences settings = ctx.getSharedPreferences(PREFS_NAME, 0);
+        return settings.getString(WXAPPID_PROPERTY_KEY, "");
+    }
+
+    /**
+     * Save app id into SharedPreferences
+     * @param ctx
+     * @param id
+     */
+    public static void saveAppId(Context ctx, String id) {
+        if (id!=null && id.isEmpty()) {
+            return ;
+        }
+
+        SharedPreferences settings = ctx.getSharedPreferences(PREFS_NAME, 0);
+        SharedPreferences.Editor editor = settings.edit();
+        editor.putString(WXAPPID_PROPERTY_KEY, id);
+        editor.commit();
+    }
+
+    public static CallbackContext getCurrentCallbackContext() {
+        return currentCallbackContext;
+    }
+
+    private void sendNoResultPluginResult(CallbackContext callbackContext) {
+        // save current callback context
+        currentCallbackContext = callbackContext;
+
+        // send no result and keep callback
+        PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+        result.setKeepCallback(true);
+        callbackContext.sendPluginResult(result);
+    }
+
+    protected boolean openMiniProgram(CordovaArgs args, CallbackContext callbackContext){
+        currentCallbackContext = callbackContext;
+        String appId = getAppId(preferences);; // 填应用AppId
+        IWXAPI api = WXAPIFactory.createWXAPI(cordova.getActivity(), appId);
+
+        final JSONObject params;
+        try {
+            params = args.getJSONObject(0);
+        } catch (JSONException e) {
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req();
+        try {
+            req.userName = params.getString(KEY_ARG_MESSAGE_MEDIA_USERNAME); // 填小程序原始id
+            req.path = params.getString(KEY_ARG_MESSAGE_MEDIA_PATH);                  //拉起小程序页面的可带参路径,不填默认拉起小程序首页
+            req.miniprogramType = params.getInt(KEY_ARG_MESSAGE_MEDIA_MINIPROGRAMTYPE);// 可选打开 开发版,体验版和正式版
+            api.sendReq(req);
+        }catch (Exception e){
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            Log.e(TAG,e.getMessage());
+        }
+        return true;
+    }
+
+}
index e85c38a..6675ca2 100644 (file)
@@ -58,6 +58,9 @@
     <access origin="http://*.ptlogin2.qq.com/*" />
     <access origin="http://*.qq.com/*" />
     <access origin="http://q2.qlogo.cn/*" />
+    <feature name="Wechat">
+        <param name="android-package" value="xu.li.cordova.wechat.Wechat" />
+    </feature>
     <name short="大理智警">dlapp</name>
     <description>
         A sample Apache Cordova application that responds to the deviceready event.
@@ -86,6 +89,7 @@
     <allow-intent href="market:*" />
     <preference name="loglevel" value="DEBUG" />
     <preference name="QQ_APP_ID" value="101885581" />
+    <preference name="WECHATAPPID" value="wxa483e2c392b08993" />
     <preference name="AutoHideSplashScreen" value="true" />
     <preference name="SplashScreenDelay" value="0" />
     <preference name="SplashShowOnlyFirstTime" value="true" />
diff --git a/platforms/android/cordova-plugin-wechat/app-android-build.gradle b/platforms/android/cordova-plugin-wechat/app-android-build.gradle
new file mode 100644 (file)
index 0000000..317ddcb
--- /dev/null
@@ -0,0 +1,7 @@
+repositories {
+    jcenter()
+}
+
+dependencies {
+    compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
+}
index 08297e5..02af8e9 100644 (file)
@@ -359,6 +359,14 @@ cordova.define('cordova/plugin_list', function(require, exports, module) {
       "clobbers": [
         "QQSDK"
       ]
+    },
+    {
+      "id": "cordova-plugin-wechat.Wechat",
+      "file": "plugins/cordova-plugin-wechat/www/wechat.js",
+      "pluginId": "cordova-plugin-wechat",
+      "clobbers": [
+        "Wechat"
+      ]
     }
   ];
   module.exports.metadata = {
@@ -381,6 +389,7 @@ cordova.define('cordova/plugin_list', function(require, exports, module) {
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
     "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
-    "cordova-plugin-qqsdk": "0.9.7"
+    "cordova-plugin-qqsdk": "0.9.7",
+    "cordova-plugin-wechat": "3.0.0"
   };
 });
\ No newline at end of file
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-wechat/www/wechat.js b/platforms/android/platform_www/plugins/cordova-plugin-wechat/www/wechat.js
new file mode 100644 (file)
index 0000000..7f86ab9
--- /dev/null
@@ -0,0 +1,190 @@
+cordova.define("cordova-plugin-wechat.Wechat", function(require, exports, module) {
+var exec = require('cordova/exec');
+
+module.exports = {
+    Scene: {
+        SESSION:  0, // 聊天界面
+        TIMELINE: 1, // 朋友圈
+        FAVORITE: 2  // 收藏
+    },
+
+    Type: {
+        APP:     1,
+        EMOTION: 2,
+        FILE:    3,
+        IMAGE:   4,
+        MUSIC:   5,
+        VIDEO:   6,
+        WEBPAGE: 7,
+        MINI:    8
+    },
+
+    Mini: {
+        RELEASE: 0, // 正式版
+        TEST:    1, // 测试版
+        PREVIEW: 2  // 体验版
+    },
+
+    isInstalled: function (onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "isWXAppInstalled", []);
+    },
+
+    /**
+     * Share a message to wechat app
+     *
+     * @example
+     * <code>
+     * Wechat.share({
+     *     message: {
+     *        title: "Message Title",
+     *        description: "Message Description(optional)",
+     *        mediaTagName: "Media Tag Name(optional)",
+     *        thumb: "http://YOUR_THUMBNAIL_IMAGE",
+     *        media: {
+     *            type: Wechat.Type.WEBPAGE,   // webpage
+     *            webpageUrl: "https://github.com/xu-li/cordova-plugin-wechat"    // webpage
+     *        }
+     *    },
+     *    scene: Wechat.Scene.TIMELINE   // share to Timeline
+     * }, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    share: function (message, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "share", [message]);
+    },
+
+    /**
+     * Sending an auth request to Wechat
+     *
+     * @example
+     * <code>
+     * Wechat.auth(function (response) { alert(response.code); });
+     * </code>
+     */
+    auth: function (scope, state, onSuccess, onError) {
+        if (typeof scope == "function") {
+            // Wechat.auth(function () { alert("Success"); });
+            // Wechat.auth(function () { alert("Success"); }, function (error) { alert(error); });
+            return exec(scope, state, "Wechat", "sendAuthRequest");
+        }
+
+        if (typeof state == "function") {
+            // Wechat.auth("snsapi_userinfo", function () { alert("Success"); });
+            // Wechat.auth("snsapi_userinfo", function () { alert("Success"); }, function (error) { alert(error); });
+            return exec(state, onSuccess, "Wechat", "sendAuthRequest", [scope]);
+        }
+
+        return exec(onSuccess, onError, "Wechat", "sendAuthRequest", [scope, state]);
+    },
+
+    /**
+     * Send a payment request
+     *
+     * @link https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1
+     * @example
+     * <code>
+     * var params = {
+     *     mch_id: '10000100', // merchant id
+     *     prepay_id: 'wx201411101639507cbf6ffd8b0779950874', // prepay id returned from server
+     *     nonce: '1add1a30ac87aa2db72f57a2375d8fec', // nonce string returned from server
+     *     timestamp: '1439531364', // timestamp
+     *     sign: '0CB01533B8C1EF103065174F50BCA001', // signed string
+     * };
+     * Wechat.sendPaymentRequest(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    sendPaymentRequest: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "sendPaymentRequest", [params]);
+    },
+
+    /**
+     * jumpToBizProfile (跳转到某个微信公众号)2016-11-11 测试是失效的,囧
+     *
+     * @link https://segmentfault.com/a/1190000007204624
+     * @link https://segmentfault.com/q/1010000003907796
+     * @example
+     * <code>
+     * var params = {
+     *     info: 'gh_xxxxxxx', // 公众帐号原始ID
+     *     type:  'Normal' // 普通号
+     * }
+     * or
+     * var params = {
+     *     info: 'extMsg', // 相关的硬件二维码串
+     *     type:  'Device' // 硬件号
+     * };
+     * Wechat.jumpToBizProfile(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+
+    jumpToBizProfile: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "jumpToBizProfile", [params]);
+    },
+
+    /**
+     * jumpToWechat (因为jumpToBizProfile失效了,暂时新增了一个临时的api)
+     *
+     * @link https://segmentfault.com/a/1190000007204624
+     * @example
+     * <code>
+     * var url = "wechat://" 现阶段貌似只支持这一个协议了
+     * Wechat.jumpToWechat(url, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    jumpToWechat: function (url, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "jumpToWechat", [url]);
+    },
+
+    /**
+     * chooseInvoiceFromWX exq:choose invoices from Wechat card list
+     *
+     * @example
+     * <code>
+     * params: signType, cardSign, nonceStr, timeStamp  all required
+     * Wechat.chooseInvoiceFromWX(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    chooseInvoiceFromWX: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "chooseInvoiceFromWX", [params]);
+    },
+
+    /**
+     * openMiniProgram exq:app opens wechat mini program
+     *
+     * @example
+     * <code>
+     * params: userName, path, miniprogramType  all required
+     * Wechat.openMiniProgram(params, function (data) {
+     *     alert(data.extMsg);
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    openMiniProgram: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "openMiniProgram", [params]);
+    }
+
+};
+
+});
index 0a6f4b6..e0172f1 100644 (file)
@@ -15,4 +15,5 @@ cordova.system.library.1=com.squareup.okhttp3:okhttp-urlconnection:3.10.0
 cordova.gradle.include.1=cordova-plugin-qrscanner/dlapp-qrscanner.gradle
 cordova.system.library.2=com.android.support:support-v4:24.1.1+
 cordova.gradle.include.2=cordova-plugin-fingerprint-aio/app-build.gradle
-cordova.system.library.3=com.android.support:support-v4:24.1.1+
\ No newline at end of file
+cordova.system.library.3=com.android.support:support-v4:24.1.1+
+cordova.gradle.include.3=cordova-plugin-wechat/app-android-build.gradle
\ No newline at end of file
index 72d20b5..41c0468 100644 (file)
     "cordova-plugin-qqsdk": {
       "QQ_APP_ID": "101885581",
       "PACKAGE_NAME": "com.dalipolice.app"
+    },
+    "cordova-plugin-wechat": {
+      "WECHATAPPID": "wxa483e2c392b08993",
+      "UNIVERSALLINK": "YOUR_UNIVERSAL_LINK",
+      "PACKAGE_NAME": "com.dalipolice.app"
     }
   },
   "dependent_plugins": {},
       "clobbers": [
         "QQSDK"
       ]
+    },
+    {
+      "file": "plugins/cordova-plugin-wechat/www/wechat.js",
+      "id": "cordova-plugin-wechat.Wechat",
+      "pluginId": "cordova-plugin-wechat",
+      "clobbers": [
+        "Wechat"
+      ]
     }
   ],
   "plugin_metadata": {
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
     "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
-    "cordova-plugin-qqsdk": "0.9.7"
+    "cordova-plugin-qqsdk": "0.9.7",
+    "cordova-plugin-wechat": "3.0.0"
   }
 }
index 2743983..f7a88cc 100644 (file)
@@ -385,6 +385,14 @@ module.exports = [
         "clobbers": [
             "QQSDK"
         ]
+    },
+    {
+        "file": "plugins/cordova-plugin-wechat/www/wechat.js",
+        "id": "cordova-plugin-wechat.Wechat",
+        "pluginId": "cordova-plugin-wechat",
+        "clobbers": [
+            "Wechat"
+        ]
     }
 ];
 module.exports.metadata = 
@@ -409,7 +417,8 @@ module.exports.metadata =
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
     "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
-    "cordova-plugin-qqsdk": "0.9.7"
+    "cordova-plugin-qqsdk": "0.9.7",
+    "cordova-plugin-wechat": "3.0.0"
 }
 // BOTTOM OF METADATA
 });
\ No newline at end of file
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-wechat/www/wechat.js b/platforms/browser/platform_www/plugins/cordova-plugin-wechat/www/wechat.js
new file mode 100644 (file)
index 0000000..01a0a4d
--- /dev/null
@@ -0,0 +1,189 @@
+cordova.define("cordova-plugin-wechat.Wechat", function(require, exports, module) { var exec = require('cordova/exec');
+
+module.exports = {
+    Scene: {
+        SESSION:  0, // 聊天界面
+        TIMELINE: 1, // 朋友圈
+        FAVORITE: 2  // 收藏
+    },
+
+    Type: {
+        APP:     1,
+        EMOTION: 2,
+        FILE:    3,
+        IMAGE:   4,
+        MUSIC:   5,
+        VIDEO:   6,
+        WEBPAGE: 7,
+        MINI:    8
+    },
+
+    Mini: {
+        RELEASE: 0, // 正式版
+        TEST:    1, // 测试版
+        PREVIEW: 2  // 体验版
+    },
+
+    isInstalled: function (onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "isWXAppInstalled", []);
+    },
+
+    /**
+     * Share a message to wechat app
+     *
+     * @example
+     * <code>
+     * Wechat.share({
+     *     message: {
+     *        title: "Message Title",
+     *        description: "Message Description(optional)",
+     *        mediaTagName: "Media Tag Name(optional)",
+     *        thumb: "http://YOUR_THUMBNAIL_IMAGE",
+     *        media: {
+     *            type: Wechat.Type.WEBPAGE,   // webpage
+     *            webpageUrl: "https://github.com/xu-li/cordova-plugin-wechat"    // webpage
+     *        }
+     *    },
+     *    scene: Wechat.Scene.TIMELINE   // share to Timeline
+     * }, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    share: function (message, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "share", [message]);
+    },
+
+    /**
+     * Sending an auth request to Wechat
+     *
+     * @example
+     * <code>
+     * Wechat.auth(function (response) { alert(response.code); });
+     * </code>
+     */
+    auth: function (scope, state, onSuccess, onError) {
+        if (typeof scope == "function") {
+            // Wechat.auth(function () { alert("Success"); });
+            // Wechat.auth(function () { alert("Success"); }, function (error) { alert(error); });
+            return exec(scope, state, "Wechat", "sendAuthRequest");
+        }
+
+        if (typeof state == "function") {
+            // Wechat.auth("snsapi_userinfo", function () { alert("Success"); });
+            // Wechat.auth("snsapi_userinfo", function () { alert("Success"); }, function (error) { alert(error); });
+            return exec(state, onSuccess, "Wechat", "sendAuthRequest", [scope]);
+        }
+
+        return exec(onSuccess, onError, "Wechat", "sendAuthRequest", [scope, state]);
+    },
+
+    /**
+     * Send a payment request
+     *
+     * @link https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1
+     * @example
+     * <code>
+     * var params = {
+     *     mch_id: '10000100', // merchant id
+     *     prepay_id: 'wx201411101639507cbf6ffd8b0779950874', // prepay id returned from server
+     *     nonce: '1add1a30ac87aa2db72f57a2375d8fec', // nonce string returned from server
+     *     timestamp: '1439531364', // timestamp
+     *     sign: '0CB01533B8C1EF103065174F50BCA001', // signed string
+     * };
+     * Wechat.sendPaymentRequest(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    sendPaymentRequest: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "sendPaymentRequest", [params]);
+    },
+
+    /**
+     * jumpToBizProfile (跳转到某个微信公众号)2016-11-11 测试是失效的,囧
+     *
+     * @link https://segmentfault.com/a/1190000007204624
+     * @link https://segmentfault.com/q/1010000003907796
+     * @example
+     * <code>
+     * var params = {
+     *     info: 'gh_xxxxxxx', // 公众帐号原始ID
+     *     type:  'Normal' // 普通号
+     * }
+     * or
+     * var params = {
+     *     info: 'extMsg', // 相关的硬件二维码串
+     *     type:  'Device' // 硬件号
+     * };
+     * Wechat.jumpToBizProfile(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+
+    jumpToBizProfile: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "jumpToBizProfile", [params]);
+    },
+
+    /**
+     * jumpToWechat (因为jumpToBizProfile失效了,暂时新增了一个临时的api)
+     *
+     * @link https://segmentfault.com/a/1190000007204624
+     * @example
+     * <code>
+     * var url = "wechat://" 现阶段貌似只支持这一个协议了
+     * Wechat.jumpToWechat(url, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    jumpToWechat: function (url, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "jumpToWechat", [url]);
+    },
+
+    /**
+     * chooseInvoiceFromWX exq:choose invoices from Wechat card list
+     *
+     * @example
+     * <code>
+     * params: signType, cardSign, nonceStr, timeStamp  all required
+     * Wechat.chooseInvoiceFromWX(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    chooseInvoiceFromWX: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "chooseInvoiceFromWX", [params]);
+    },
+
+    /**
+     * openMiniProgram exq:app opens wechat mini program
+     *
+     * @example
+     * <code>
+     * params: userName, path, miniprogramType  all required
+     * Wechat.openMiniProgram(params, function (data) {
+     *     alert(data.extMsg);
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    openMiniProgram: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "openMiniProgram", [params]);
+    }
+
+};
+
+});
index 0693b93..e44ab6e 100644 (file)
                EDCB3A04AD4D4B289E64F99E /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D29239646664D05B61A0517 /* libsqlite3.tbd */; };
                988F095294ED444C9ACB1281 /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F5208F54124408BAA42D80E /* libstdc++.tbd */; };
                1CA6AE2CB7C4454E96B08442 /* TencentOpenAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8DABF1D129444628738EB6A /* TencentOpenAPI.framework */; };
+               2651E8E7F39F4BAEB5018A67 /* CDVWechat.m in Sources */ = {isa = PBXBuildFile; fileRef = CFB3542D16294A29B1D3AFDE /* CDVWechat.m */; };
+               CAF09C8DB131463391477371 /* AppDelegate+Wechat.m in Sources */ = {isa = PBXBuildFile; fileRef = 61422FD6698645BF8AC270CD /* AppDelegate+Wechat.m */; };
+               57123A61EE2A4480A03BC15C /* libWeChatSDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8FD71481ADD343BD913C96D8 /* libWeChatSDK.a */; };
+               0A2D48DC88304649B610E8F0 /* Webkit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C74ADF6EBDB4ACEBBE4B331 /* Webkit.framework */; };
+               BA5A99C01B124815B127341C /* libc++.1.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F51A743DD2B847EBBD2D265B /* libc++.1.tbd */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
                9D29239646664D05B61A0517 /* libsqlite3.tbd */ = {isa = PBXFileReference; name = "libsqlite3.tbd"; path = "usr/lib/libsqlite3.tbd"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = sourcecode.text-based-dylib-definition; explicitFileType = undefined; includeInIndex = 0; };
                1F5208F54124408BAA42D80E /* libstdc++.tbd */ = {isa = PBXFileReference; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = sourcecode.text-based-dylib-definition; explicitFileType = undefined; includeInIndex = 0; };
                B8DABF1D129444628738EB6A /* TencentOpenAPI.framework */ = {isa = PBXFileReference; name = "TencentOpenAPI.framework"; path = "dlapp/Plugins/cordova-plugin-qqsdk/TencentOpenAPI.framework"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.framework; explicitFileType = undefined; includeInIndex = 0; };
+               CFB3542D16294A29B1D3AFDE /* CDVWechat.m */ = {isa = PBXFileReference; name = "CDVWechat.m"; path = "cordova-plugin-wechat/CDVWechat.m"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; explicitFileType = undefined; includeInIndex = 0; };
+               61422FD6698645BF8AC270CD /* AppDelegate+Wechat.m */ = {isa = PBXFileReference; name = "AppDelegate+Wechat.m"; path = "cordova-plugin-wechat/AppDelegate+Wechat.m"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; explicitFileType = undefined; includeInIndex = 0; };
+               8FD71481ADD343BD913C96D8 /* libWeChatSDK.a */ = {isa = PBXFileReference; name = "libWeChatSDK.a"; path = "dlapp/Plugins/cordova-plugin-wechat/libWeChatSDK.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; };
+               5C3308DBC1A34B35AF496FD3 /* CDVWechat.h */ = {isa = PBXFileReference; name = "CDVWechat.h"; path = "cordova-plugin-wechat/CDVWechat.h"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
+               F2935B7ACABA4BAC8EA2270D /* AppDelegate+Wechat.h */ = {isa = PBXFileReference; name = "AppDelegate+Wechat.h"; path = "cordova-plugin-wechat/AppDelegate+Wechat.h"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
+               070FA15264B741429C96151A /* WXApi.h */ = {isa = PBXFileReference; name = "WXApi.h"; path = "cordova-plugin-wechat/WXApi.h"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
+               F88A8EA7C7B4483DAEB50719 /* WXApiObject.h */ = {isa = PBXFileReference; name = "WXApiObject.h"; path = "cordova-plugin-wechat/WXApiObject.h"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
+               575C7C23599048A5B0A81656 /* WechatAuthSDK.h */ = {isa = PBXFileReference; name = "WechatAuthSDK.h"; path = "cordova-plugin-wechat/WechatAuthSDK.h"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
+               0C74ADF6EBDB4ACEBBE4B331 /* Webkit.framework */ = {isa = PBXFileReference; name = "Webkit.framework"; path = "System/Library/Frameworks/Webkit.framework"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = wrapper.framework; explicitFileType = undefined; includeInIndex = 0; };
+               F51A743DD2B847EBBD2D265B /* libc++.1.tbd */ = {isa = PBXFileReference; name = "libc++.1.tbd"; path = "usr/lib/libc++.1.tbd"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = sourcecode.text-based-dylib-definition; explicitFileType = undefined; includeInIndex = 0; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                EDCB3A04AD4D4B289E64F99E /* libsqlite3.tbd in Frameworks */,
                                988F095294ED444C9ACB1281 /* libstdc++.tbd in Frameworks */,
                                1CA6AE2CB7C4454E96B08442 /* TencentOpenAPI.framework in Frameworks */,
+                               57123A61EE2A4480A03BC15C /* libWeChatSDK.a in Frameworks */,
+                               0A2D48DC88304649B610E8F0 /* Webkit.framework in Frameworks */,
+                               BA5A99C01B124815B127341C /* libc++.1.tbd in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                9D29239646664D05B61A0517 /* libsqlite3.tbd */,
                                1F5208F54124408BAA42D80E /* libstdc++.tbd */,
                                B8DABF1D129444628738EB6A /* TencentOpenAPI.framework */,
+                               8FD71481ADD343BD913C96D8 /* libWeChatSDK.a */,
+                               0C74ADF6EBDB4ACEBBE4B331 /* Webkit.framework */,
+                               F51A743DD2B847EBBD2D265B /* libc++.1.tbd */,
                        );
                        name = Frameworks;
                        sourceTree = "<group>";
                                6C8C62629761432796084184 /* ScreenRecordingDetector.h */,
                                29DE4F0A316B400B959056A3 /* CDVQQSDK.m */,
                                E381D08A673C42D780B0EAA7 /* CDVQQSDK.h */,
+                               CFB3542D16294A29B1D3AFDE /* CDVWechat.m */,
+                               61422FD6698645BF8AC270CD /* AppDelegate+Wechat.m */,
+                               5C3308DBC1A34B35AF496FD3 /* CDVWechat.h */,
+                               F2935B7ACABA4BAC8EA2270D /* AppDelegate+Wechat.h */,
+                               070FA15264B741429C96151A /* WXApi.h */,
+                               F88A8EA7C7B4483DAEB50719 /* WXApiObject.h */,
+                               575C7C23599048A5B0A81656 /* WechatAuthSDK.h */,
                        );
                        name = Plugins;
                        path = dlapp/Plugins;
                                F70AC332CD71455D9E103429 /* ScreenshotBlocker.m in Sources */,
                                1ED02270B4D74F8BB970350D /* ScreenRecordingDetector.m in Sources */,
                                EF44EC2E45A745DAA3A1FB50 /* CDVQQSDK.m in Sources */,
+                               2651E8E7F39F4BAEB5018A67 /* CDVWechat.m in Sources */,
+                               CAF09C8DB131463391477371 /* AppDelegate+Wechat.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                        "$(inherited)",
                                        "\"$(SRCROOT)/$(TARGET_NAME)/Plugins/cordova-plugin-jcore\"",
                                        "\"$(SRCROOT)/$(TARGET_NAME)/Plugins/jpush-phonegap-plugin\"",
+                                       "\"$(SRCROOT)/$(TARGET_NAME)/Plugins/cordova-plugin-wechat\"",
                                );
                                PRODUCT_BUNDLE_IDENTIFIER = com.dalipolice.app;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                        "$(inherited)",
                                        "\"$(SRCROOT)/$(TARGET_NAME)/Plugins/cordova-plugin-jcore\"",
                                        "\"$(SRCROOT)/$(TARGET_NAME)/Plugins/jpush-phonegap-plugin\"",
+                                       "\"$(SRCROOT)/$(TARGET_NAME)/Plugins/cordova-plugin-wechat\"",
                                );
                                PRODUCT_BUNDLE_IDENTIFIER = com.dalipolice.app;
                                PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/AppDelegate+Wechat.h b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/AppDelegate+Wechat.h
new file mode 100644 (file)
index 0000000..5a5b092
--- /dev/null
@@ -0,0 +1,16 @@
+//
+//  AppDelegate+Wechat.h
+//  cordova-plugin-wechat
+//
+//  Created by Jason.z on 26/2/20.
+//
+//
+
+#import "AppDelegate.h"
+
+@interface AppDelegate (Wechat)
+
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
+- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/AppDelegate+Wechat.m b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/AppDelegate+Wechat.m
new file mode 100644 (file)
index 0000000..c6ecda4
--- /dev/null
@@ -0,0 +1,57 @@
+//
+//  AppDelegate+Wechat.h
+//  cordova-plugin-wechat
+//
+//  Created by Jason.z on 26/2/20.
+//
+//
+
+#import "AppDelegate+Wechat.h"
+#import "CDVWechat.h"
+
+#import <objc/runtime.h>
+
+@implementation AppDelegate (Wechat)
+
+static BOOL swizzled = NO;
+
++ (void)load {
+    // only need to worry about this in iOS 8 and later
+    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
+    if ([processInfo respondsToSelector:@selector(operatingSystemVersion)]) {
+        //operatingSystemVersion was introduced in iOS 8
+        Method swizzlee = class_getInstanceMethod(self, @selector(application:continueUserActivity:restorationHandler:));
+        Method swizzler = class_getInstanceMethod(self, @selector(swizzleApplication:continueUserActivity:restorationHandler:));
+        
+        if (swizzlee) {
+            method_exchangeImplementations(swizzlee, swizzler);
+            swizzled = YES;
+        } else {
+            // app delegate has not implemented optional protocol method. add it in with our implementation
+            const char *typeEncoding = method_getTypeEncoding(swizzler);
+            class_addMethod(self, @selector(application:continueUserActivity:restorationHandler:), method_getImplementation(swizzler), typeEncoding);
+        }
+    }
+}
+
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
+    CDVWechat *cdvWechat = [self.viewController getCommandInstance:@"wechat"];
+    return [cdvWechat handleWechatOpenURL:url];
+}
+
+- (BOOL)swizzleApplication:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
+    if (![userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
+        if (swizzled) {
+            return [self swizzleApplication:application continueUserActivity:userActivity restorationHandler:restorationHandler];
+        }
+        
+        return NO;
+    }
+    
+    CDVWechat *cdvWechat = [self.viewController getCommandInstance:@"wechat"];
+    
+    return [cdvWechat handleUserActivity:userActivity];
+
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/CDVWechat.h b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/CDVWechat.h
new file mode 100644 (file)
index 0000000..8d4ae16
--- /dev/null
@@ -0,0 +1,39 @@
+//
+//  CDVWechat.h
+//  cordova-plugin-wechat
+//
+//  Created by xu.li on 12/23/13.
+//
+//
+
+#import <Cordova/CDV.h>
+#import "WXApi.h"
+#import "WXApiObject.h"
+
+enum  CDVWechatSharingType {
+    CDVWXSharingTypeApp = 1,
+    CDVWXSharingTypeEmotion,
+    CDVWXSharingTypeFile,
+    CDVWXSharingTypeImage,
+    CDVWXSharingTypeMusic,
+    CDVWXSharingTypeVideo,
+    CDVWXSharingTypeWebPage,
+    CDVWXSharingTypeMini
+};
+
+@interface CDVWechat:CDVPlugin <WXApiDelegate>
+
+@property (nonatomic, strong) NSString *currentCallbackId;
+@property (nonatomic, strong) NSString *wechatAppId;
+
+- (void)isWXAppInstalled:(CDVInvokedUrlCommand *)command;
+- (void)share:(CDVInvokedUrlCommand *)command;
+- (void)sendAuthRequest:(CDVInvokedUrlCommand *)command;
+- (void)sendPaymentRequest:(CDVInvokedUrlCommand *)command;
+- (void)jumpToBizProfile:(CDVInvokedUrlCommand *)command;
+- (void)jumpToWechat:(CDVInvokedUrlCommand *)command;
+- (void)chooseInvoiceFromWX: (CDVInvokedUrlCommand *)command;
+- (void)openMiniProgram: (CDVInvokedUrlCommand *)command;
+- (BOOL)handleUserActivity:(NSUserActivity *)userActivity;
+- (BOOL)handleWechatOpenURL:(NSURL *)url;
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/CDVWechat.m b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/CDVWechat.m
new file mode 100644 (file)
index 0000000..4f7b424
--- /dev/null
@@ -0,0 +1,575 @@
+//
+//  CDVWechat.m
+//  cordova-plugin-wechat
+//
+//  Created by xu.li on 12/23/13.
+//
+//
+
+#import "CDVWechat.h"
+
+static int const MAX_THUMBNAIL_SIZE = 320;
+
+@implementation CDVWechat
+
+#pragma mark "API"
+- (void)pluginInitialize {
+    NSString* appId = [[self.commandDelegate settings] objectForKey:@"wechatappid"];
+    
+    NSString* universalLink = [[self.commandDelegate settings] objectForKey:@"universallink"];
+    
+    if (appId && ![appId isEqualToString:self.wechatAppId]) {
+        self.wechatAppId = appId;
+        [WXApi registerApp: appId universalLink: universalLink];
+        
+        NSLog(@"cordova-plugin-wechat has been initialized. Wechat SDK Version: %@. APP_ID: %@.", [WXApi getApiVersion], appId);
+    }
+}
+
+- (void)isWXAppInstalled:(CDVInvokedUrlCommand *)command
+{
+    CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:[WXApi isWXAppInstalled]];
+
+    [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId];
+}
+
+- (void)share:(CDVInvokedUrlCommand *)command
+{
+    // if not installed
+    if (![WXApi isWXAppInstalled])
+    {
+        [self failWithCallbackID:command.callbackId withMessage:@"未安装微信"];
+        return ;
+    }
+
+    // check arguments
+    NSDictionary *params = [command.arguments objectAtIndex:0];
+    if (!params)
+    {
+        [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+        return ;
+    }
+
+    // save the callback id
+    self.currentCallbackId = command.callbackId;
+
+    SendMessageToWXReq* req = [[SendMessageToWXReq alloc] init];
+
+    // check the scene
+    if ([params objectForKey:@"scene"])
+    {
+        req.scene = (int)[[params objectForKey:@"scene"] integerValue];
+    }
+    else
+    {
+        req.scene = WXSceneTimeline;
+    }
+
+    // message or text?
+    NSDictionary *message = [params objectForKey:@"message"];
+
+    if (message)
+    {
+        req.bText = NO;
+
+        // async
+        [self.commandDelegate runInBackground:^{
+            req.message = [self buildSharingMessage:message];
+            
+            [WXApi sendReq:(BaseReq *)req completion:^(BOOL success) {
+                if (!success) {
+                    [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+                                   self.currentCallbackId = nil;
+                }
+            }];
+        }];
+    }
+    else
+    {
+        req.bText = YES;
+        req.text = [params objectForKey:@"text"];
+
+        [WXApi sendReq:(BaseReq *)req completion:^(BOOL success) {
+            if (!success) {
+                [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+                               self.currentCallbackId = nil;
+            }
+        }];
+    }
+}
+
+- (void)sendAuthRequest:(CDVInvokedUrlCommand *)command
+{
+
+    SendAuthReq* req =[[SendAuthReq alloc] init];
+
+    // scope
+    if ([command.arguments count] > 0)
+    {
+        req.scope = [command.arguments objectAtIndex:0];
+    }
+    else
+    {
+        req.scope = @"snsapi_userinfo";
+    }
+
+    // state
+    if ([command.arguments count] > 1)
+    {
+        req.state = [command.arguments objectAtIndex:1];
+    }
+
+    [WXApi sendAuthReq:req viewController:self.viewController delegate:self completion:^(BOOL success) {
+        if(success) {
+            self.currentCallbackId = command.callbackId;
+        } else {
+            [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+        }
+    }];
+}
+
+- (void)sendPaymentRequest:(CDVInvokedUrlCommand *)command
+{
+    // check arguments
+    NSDictionary *params = [command.arguments objectAtIndex:0];
+    if (!params)
+    {
+        [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+        return ;
+    }
+
+    // check required parameters
+    NSArray *requiredParams;
+    if ([params objectForKey:@"mch_id"])
+    {
+        requiredParams = @[@"mch_id", @"prepay_id", @"timestamp", @"nonce", @"sign"];
+    }
+    else
+    {
+        requiredParams = @[@"partnerid", @"prepayid", @"timestamp", @"noncestr", @"sign"];
+    }
+
+    for (NSString *key in requiredParams)
+    {
+        if (![params objectForKey:key])
+        {
+            [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+            return ;
+        }
+    }
+
+    PayReq *req = [[PayReq alloc] init];
+
+    // NSString *appId = [params objectForKey:requiredParams[5]];
+    // if (appId && ![appId isEqualToString:self.wechatAppId]) {
+    //     self.wechatAppId = appId;
+    //     [WXApi registerApp: appId];
+    // }
+
+    req.partnerId = [params objectForKey:requiredParams[0]];
+    req.prepayId = [params objectForKey:requiredParams[1]];
+    req.timeStamp = [[params objectForKey:requiredParams[2]] intValue];
+    req.nonceStr = [params objectForKey:requiredParams[3]];
+    req.package = @"Sign=WXPay";
+    req.sign = [params objectForKey:requiredParams[4]];
+    
+    [WXApi sendReq:(BaseReq *)req completion:^(BOOL success) {
+       if (success) {
+           self.currentCallbackId = command.callbackId;
+       } else {
+           [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+       }
+    }];
+}
+
+- (void)chooseInvoiceFromWX:(CDVInvokedUrlCommand *)command
+{
+    NSDictionary *params = [command.arguments objectAtIndex:0];
+    WXChooseInvoiceReq *req = [[WXChooseInvoiceReq alloc] init];
+    req.cardSign = [params objectForKey:@"cardSign"];
+    req.timeStamp = [[params objectForKey:@"timeStamp"] intValue];
+    req.appID = [params objectForKey:@"appId"];
+    req.nonceStr = [params objectForKey:@"nonceStr"];
+    req.signType = [params objectForKey:@"signType"];
+    
+    [WXApi sendReq:(BaseReq *)req completion:^(BOOL success) {
+        if (success) {
+            self.currentCallbackId = command.callbackId;
+        } else {
+            [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+        }
+    }];
+}
+
+- (void)jumpToBizProfile:(CDVInvokedUrlCommand *)command
+{
+    // check arguments
+//    NSDictionary *params = [command.arguments objectAtIndex:0];
+//    if (!params)
+//    {
+//        [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+//        return ;
+//    }
+//
+//    // check required parameters
+//    NSArray *requiredParams;
+//    requiredParams = @[@"type", @"info"];
+//
+//    for (NSString *key in requiredParams)
+//    {
+//        if (![params objectForKey:key])
+//        {
+//            [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+//            return ;
+//        }
+//    }
+//    JumpToBizProfileReq *req = [JumpToBizProfileReq new];
+//    NSString *bizType =  [params objectForKey:requiredParams[0]];
+//
+//    if ([bizType isEqualToString:@"Normal"]) {
+//        req.profileType = WXBizProfileType_Normal;
+//        req.username = [params objectForKey:requiredParams[1]];
+//    } else {
+//        req.profileType = WXBizProfileType_Device;
+//        req.extMsg = [params objectForKey:requiredParams[1]];
+//    }
+//
+//    if ([WXApi sendReq:req])
+//    {
+//        // save the callback id
+//        self.currentCallbackId = command.callbackId;
+//    }
+//    else
+//    {
+//        [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+//    }
+}
+
+- (void)jumpToWechat:(CDVInvokedUrlCommand *)command
+{
+    // check arguments
+    NSString *url = [command.arguments objectAtIndex:0];
+    if (!url || ![url hasPrefix:@"weixin://"])
+    {
+        [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+        return ;
+    }
+
+    NSURL *formatUrl = [NSURL URLWithString:[url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
+    if ([[UIApplication sharedApplication] canOpenURL:formatUrl]) {
+        NSDictionary *options = @{UIApplicationOpenURLOptionUniversalLinksOnly : @YES};
+        [[UIApplication sharedApplication] openURL:formatUrl options:options completionHandler:nil];
+    } else{
+        [self failWithCallbackID:command.callbackId withMessage:@"未安装微信或其他错误"];
+    }
+    return ;
+}
+
+
+
+#pragma mark "WXApiDelegate"
+
+/**
+ * Not implemented
+ */
+- (void)onReq:(BaseReq *)req
+{
+    NSLog(@"%@", req);
+}
+
+- (void)onResp:(WXLaunchMiniProgramResp *)resp
+{
+    BOOL success = NO;
+    NSString *message = @"Unknown";
+    NSDictionary *response = nil;
+
+    switch (resp.errCode)
+    {
+        case WXSuccess:
+            success = YES;
+            break;
+
+        case WXErrCodeCommon:
+            message = @"普通错误";
+            break;
+
+        case WXErrCodeUserCancel:
+            message = @"用户点击取消并返回";
+            break;
+
+        case WXErrCodeSentFail:
+            message = @"发送失败";
+            break;
+
+        case WXErrCodeAuthDeny:
+            message = @"授权失败";
+            break;
+
+        case WXErrCodeUnsupport:
+            message = @"微信不支持";
+            break;
+
+        default:
+            message = @"未知错误";
+    }
+
+    if (success)
+    {
+        if ([resp isKindOfClass:[SendAuthResp class]])
+        {
+            // fix issue that lang and country could be nil for iPhone 6 which caused crash.
+            SendAuthResp* authResp = (SendAuthResp*)resp;
+            response = @{
+                         @"code": authResp.code != nil ? authResp.code : @"",
+                         @"state": authResp.state != nil ? authResp.state : @"",
+                         @"lang": authResp.lang != nil ? authResp.lang : @"",
+                         @"country": authResp.country != nil ? authResp.country : @"",
+                         };
+
+            CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:response];
+
+            [self.commandDelegate sendPluginResult:commandResult callbackId:self.currentCallbackId];
+        }
+        else if([resp isKindOfClass:[WXChooseInvoiceResp class]]){
+                    WXChooseInvoiceResp* invoiceResp = (WXChooseInvoiceResp *)resp;
+
+        //            response = @{
+        //                         @"data":invoiceResp.cardAry
+        //                         }
+                    NSMutableArray *arrM = [[NSMutableArray alloc] init];
+                    NSDictionary *mutableDic = nil;
+                    for(WXInvoiceItem *invoiceItem in invoiceResp.cardAry){
+                        mutableDic = @{
+                                       @"cardId": invoiceItem.cardId,
+                                       @"encryptCode": invoiceItem.encryptCode,
+                                       };
+                        [arrM addObject:mutableDic];
+                    }
+                    response = @{
+                                 @"data": arrM
+                                 };
+                    NSLog(@"response======= %@", response);
+                    CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:response];
+                    [self.commandDelegate sendPluginResult:commandResult callbackId:self.currentCallbackId];
+                }
+        else if ([resp isKindOfClass:[WXLaunchMiniProgramResp class]])
+        {
+            NSString *extMsg = resp.extMsg;
+            response = @{
+                         @"extMsg": extMsg
+                         };
+            CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:response];
+            [self.commandDelegate sendPluginResult:commandResult callbackId:self.currentCallbackId];
+        }
+        else
+        {
+            [self successWithCallbackID:self.currentCallbackId];
+        }
+    }
+    else
+    {
+        [self failWithCallbackID:self.currentCallbackId withMessage:message];
+    }
+
+    [self pluginInitialize];
+    self.currentCallbackId = nil;
+}
+
+#pragma mark "CDVPlugin Overrides"
+
+- (void)handleOpenURL:(NSNotification *)notification
+{
+    NSURL* url = [notification object];
+
+    if ([url isKindOfClass:[NSURL class]] && [url.scheme isEqualToString:self.wechatAppId])
+    {
+        [WXApi handleOpenURL:url delegate:self];
+    }
+}
+
+#pragma mark "Private methods"
+
+- (WXMediaMessage *)buildSharingMessage:(NSDictionary *)message
+{
+    WXMediaMessage *wxMediaMessage = [WXMediaMessage message];
+    wxMediaMessage.title = [message objectForKey:@"title"];
+    wxMediaMessage.description = [message objectForKey:@"description"];
+    wxMediaMessage.mediaTagName = [message objectForKey:@"mediaTagName"];
+    wxMediaMessage.messageExt = [message objectForKey:@"messageExt"];
+    wxMediaMessage.messageAction = [message objectForKey:@"messageAction"];
+    if ([message objectForKey:@"thumb"])
+    {
+        [wxMediaMessage setThumbImage:[self getUIImageFromURL:[message objectForKey:@"thumb"]]];
+    }
+
+    // media parameters
+    id mediaObject = nil;
+    WXMiniProgramObject *object;
+    NSDictionary *media = [message objectForKey:@"media"];
+    // check types
+    NSInteger type = [[media objectForKey:@"type"] integerValue];
+    switch (type)
+    {
+        case CDVWXSharingTypeApp:
+            mediaObject = [WXAppExtendObject object];
+            ((WXAppExtendObject*)mediaObject).extInfo = [media objectForKey:@"extInfo"];
+            ((WXAppExtendObject*)mediaObject).url = [media objectForKey:@"url"];
+            break;
+
+        case CDVWXSharingTypeEmotion:
+            mediaObject = [WXEmoticonObject object];
+            ((WXEmoticonObject*)mediaObject).emoticonData = [self getNSDataFromURL:[media objectForKey:@"emotion"]];
+            break;
+
+        case CDVWXSharingTypeFile:
+            mediaObject = [WXFileObject object];
+            ((WXFileObject*)mediaObject).fileData = [self getNSDataFromURL:[media objectForKey:@"file"]];
+            ((WXFileObject*)mediaObject).fileExtension = [media objectForKey:@"fileExtension"];
+            break;
+
+        case CDVWXSharingTypeImage:
+            mediaObject = [WXImageObject object];
+            ((WXImageObject*)mediaObject).imageData = [self getNSDataFromURL:[media objectForKey:@"image"]];
+            break;
+
+        case CDVWXSharingTypeMusic:
+            mediaObject = [WXMusicObject object];
+            ((WXMusicObject*)mediaObject).musicUrl = [media objectForKey:@"musicUrl"];
+            ((WXMusicObject*)mediaObject).musicDataUrl = [media objectForKey:@"musicDataUrl"];
+            break;
+
+        case CDVWXSharingTypeVideo:
+            mediaObject = [WXVideoObject object];
+            ((WXVideoObject*)mediaObject).videoUrl = [media objectForKey:@"videoUrl"];
+            break;
+        case CDVWXSharingTypeMini:
+            object = [WXMiniProgramObject object];
+            object.webpageUrl = [media objectForKey:@"webpageUrl"];
+            object.userName = [media objectForKey:@"userName"];
+            object.path = [media objectForKey:@"path"]; // pages/inbox/inbox?name1=key1&name=key2
+            object.hdImageData = [self getNSDataFromURL:[media objectForKey:@"hdImageData"]];
+            object.withShareTicket = [[media objectForKey:@"withShareTicket"] boolValue];
+            object.miniProgramType = (int)[[media objectForKey:@"miniProgramType"] integerValue];
+            wxMediaMessage.mediaObject = object;
+            return wxMediaMessage;
+            
+        case CDVWXSharingTypeWebPage:
+        default:
+            mediaObject = [WXWebpageObject object];
+            ((WXWebpageObject *)mediaObject).webpageUrl = [media objectForKey:@"webpageUrl"];
+    }
+
+    wxMediaMessage.mediaObject = mediaObject;
+    return wxMediaMessage;
+}
+
+- (NSData *)getNSDataFromURL:(NSString *)url
+{
+    NSData *data = nil;
+
+    if ([url hasPrefix:@"http://"] || [url hasPrefix:@"https://"])
+    {
+        data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
+    }
+    else if ([url hasPrefix:@"data:image"])
+    {
+        // a base 64 string
+        NSURL *base64URL = [NSURL URLWithString:url];
+        data = [NSData dataWithContentsOfURL:base64URL];
+    }
+    else if ([url rangeOfString:@"temp:"].length != 0)
+    {
+        url =  [NSTemporaryDirectory() stringByAppendingPathComponent:[url componentsSeparatedByString:@"temp:"][1]];
+        data = [NSData dataWithContentsOfFile:url];
+    }
+    else
+    {
+        // local file
+        url = [[NSBundle mainBundle] pathForResource:[url stringByDeletingPathExtension] ofType:[url pathExtension]];
+        data = [NSData dataWithContentsOfFile:url];
+    }
+
+    return data;
+}
+
+- (UIImage *)getUIImageFromURL:(NSString *)url
+{
+    NSData *data = [self getNSDataFromURL:url];
+    UIImage *image = [UIImage imageWithData:data];
+
+    if (image.size.width > MAX_THUMBNAIL_SIZE || image.size.height > MAX_THUMBNAIL_SIZE)
+    {
+        CGFloat width = 0;
+        CGFloat height = 0;
+
+        // calculate size
+        if (image.size.width > image.size.height)
+        {
+            width = MAX_THUMBNAIL_SIZE;
+            height = width * image.size.height / image.size.width;
+        }
+        else
+        {
+            height = MAX_THUMBNAIL_SIZE;
+            width = height * image.size.width / image.size.height;
+        }
+
+        // scale it
+        UIGraphicsBeginImageContext(CGSizeMake(width, height));
+        [image drawInRect:CGRectMake(0, 0, width, height)];
+        UIImage *scaled = UIGraphicsGetImageFromCurrentImageContext();
+        UIGraphicsEndImageContext();
+
+        return scaled;
+    }
+
+    return image;
+}
+
+- (void)successWithCallbackID:(NSString *)callbackID
+{
+    [self successWithCallbackID:callbackID withMessage:@"OK"];
+}
+
+- (void)successWithCallbackID:(NSString *)callbackID withMessage:(NSString *)message
+{
+    CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message];
+    [self.commandDelegate sendPluginResult:commandResult callbackId:callbackID];
+}
+
+- (void)failWithCallbackID:(NSString *)callbackID withError:(NSError *)error
+{
+    [self failWithCallbackID:callbackID withMessage:[error localizedDescription]];
+}
+
+- (void)failWithCallbackID:(NSString *)callbackID withMessage:(NSString *)message
+{
+    CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message];
+    [self.commandDelegate sendPluginResult:commandResult callbackId:callbackID];
+}
+
+-  (void)openMiniProgram:(CDVInvokedUrlCommand *)command
+{
+    NSDictionary *params = [command.arguments objectAtIndex:0];
+    WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
+    launchMiniProgramReq.userName = [params objectForKey:@"userName"];  //拉起的小程序的username
+    launchMiniProgramReq.path = [params objectForKey:@"path"];    //拉起小程序页面的可带参路径,不填默认拉起小程序首页
+    launchMiniProgramReq.miniProgramType = (int)[[params objectForKey:@"miniprogramType"] integerValue]; //拉起小程序的类型
+    [WXApi sendReq:launchMiniProgramReq completion:^(BOOL success) {
+        if(success) {
+             self.currentCallbackId = command.callbackId;
+        } else {
+            [self failWithCallbackID:command.callbackId withMessage:@"打开请求失败"];
+        }
+    }];
+}
+
+- (BOOL)handleUserActivity:(NSUserActivity *)userActivity {
+   return [WXApi handleOpenUniversalLink:userActivity delegate:self];
+}
+
+- (BOOL)handleWechatOpenURL:(NSURL *)url  {
+    return [WXApi handleOpenURL:url delegate:self];
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WXApi.h b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WXApi.h
new file mode 100644 (file)
index 0000000..38e6476
--- /dev/null
@@ -0,0 +1,183 @@
+//
+//  WXApi.h
+//  所有Api接口
+//
+//  Created by Wechat on 12-2-28.
+//  Copyright (c) 2012年 Tencent. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "WXApiObject.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - WXApiDelegate
+/*! @brief 接收并处理来自微信终端程序的事件消息
+ *
+ * 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。
+ * WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。
+ */
+@protocol WXApiDelegate <NSObject>
+@optional
+
+/*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果
+ *
+ * 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。
+ * 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。
+ * @param req 具体请求内容,是自动释放的
+ */
+- (void)onReq:(BaseReq*)req;
+
+
+
+/*! @brief 发送一个sendReq后,收到微信的回应
+ *
+ * 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
+ * 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
+ * @param resp具体的回应内容,是自动释放的
+ */
+- (void)onResp:(BaseResp*)resp;
+
+@end
+
+#pragma mark - WXApiLogDelegate
+
+@protocol WXApiLogDelegate <NSObject>
+
+- (void)onLog:(NSString*)log logLevel:(WXLogLevel)level;
+
+@end
+
+#pragma mark - WXApi
+
+/*! @brief 微信Api接口函数类
+ *
+ * 该类封装了微信终端SDK的所有接口
+ */
+@interface WXApi : NSObject
+
+/*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。
+ *
+ * 需要在每次启动第三方应用程序时调用。
+ * @attention 请保证在主线程中调用此函数
+ * @param appid 微信开发者ID
+ * @param universalLink 微信开发者Universal Link
+ * @return 成功返回YES,失败返回NO。
+ */
++ (BOOL)registerApp:(NSString *)appid universalLink:(NSString *)universalLink;
+
+
+/*! @brief 处理旧版微信通过URL启动App时传递的数据
+ *
+ * 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。
+ * @param url 微信启动第三方应用时传递过来的URL
+ * @param delegate  WXApiDelegate对象,用来接收微信触发的消息。
+ * @return 成功返回YES,失败返回NO。
+ */
++ (BOOL)handleOpenURL:(NSURL *)url delegate:(nullable id<WXApiDelegate>)delegate;
+
+
+/*! @brief 处理微信通过Universal Link启动App时传递的数据
+ *
+ * 需要在 application:continueUserActivity:restorationHandler:中调用。
+ * @param userActivity 微信启动第三方应用时系统API传递过来的userActivity
+ * @param delegate  WXApiDelegate对象,用来接收微信触发的消息。
+ * @return 成功返回YES,失败返回NO。
+ */
++ (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity delegate:(nullable id<WXApiDelegate>)delegate;
+
+
+/*! @brief 检查微信是否已被用户安装
+ *
+ * @return 微信已安装返回YES,未安装返回NO。
+ */
++ (BOOL)isWXAppInstalled;
+
+
+
+/*! @brief 判断当前微信的版本是否支持OpenApi
+ *
+ * @return 支持返回YES,不支持返回NO。
+ */
++ (BOOL)isWXAppSupportApi;
+
+
+
+/*! @brief 获取微信的itunes安装地址
+ *
+ * @return 微信的安装地址字符串。
+ */
++ (NSString *)getWXAppInstallUrl;
+
+
+
+/*! @brief 获取当前微信SDK的版本号
+ *
+ * @return 返回当前微信SDK的版本号
+ */
++ (NSString *)getApiVersion;
+
+
+
+/*! @brief 打开微信
+ *
+ * @return 成功返回YES,失败返回NO。
+ */
++ (BOOL)openWXApp;
+
+
+
+/*! @brief 发送请求到微信,等待微信返回onResp
+ *
+ * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型
+ * SendAuthReq、SendMessageToWXReq、PayReq等。
+ * @param req 具体的发送请求。
+ * @param completion 调用结果回调block
+ */
++ (void)sendReq:(BaseReq *)req completion:(void (^ __nullable)(BOOL success))completion;
+
+/*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面
+ *
+ * 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有
+ * GetMessageFromWXResp、ShowMessageFromWXResp等。
+ * @param resp 具体的应答内容
+ * @param completion 调用结果回调block
+ */
++ (void)sendResp:(BaseResp*)resp completion:(void (^ __nullable)(BOOL success))completion;
+
+
+/*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp
+ *
+ * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。
+ * @param req 具体的发送请求。
+ * @param viewController 当前界面对象。
+ * @param delegate  WXApiDelegate对象,用来接收微信触发的消息。
+ * @param completion 调用结果回调block
+ */
++ (void)sendAuthReq:(SendAuthReq *)req viewController:(UIViewController*)viewController delegate:(nullable id<WXApiDelegate>)delegate completion:(void (^ __nullable)(BOOL success))completion;
+
+
+/*! @brief WXApi的成员函数,接受微信的log信息。byBlock
+    注意1:SDK会强引用这个block,注意不要导致内存泄漏,注意不要导致内存泄漏
+    注意2:调用过一次startLog by block之后,如果再调用一次任意方式的startLoad,会释放上一次logBlock,不再回调上一个logBlock
+ *
+ *  @param level 打印log的级别
+ *  @param logBlock 打印log的回调block
+ */
++ (void)startLogByLevel:(WXLogLevel)level logBlock:(WXLogBolock)logBlock;
+
+/*! @brief WXApi的成员函数,接受微信的log信息。byDelegate 
+    注意1:sdk会弱引用这个delegate,这里可加任意对象为代理,不需要与WXApiDelegate同一个对象
+    注意2:调用过一次startLog by delegate之后,再调用一次任意方式的startLoad,不会再回调上一个logDelegate对象
+ *  @param level 打印log的级别
+ *  @param logDelegate 打印log的回调代理,
+ */
++ (void)startLogByLevel:(WXLogLevel)level logDelegate:(id<WXApiLogDelegate>)logDelegate;
+
+/*! @brief 停止打印log,会清理block或者delegate为空,释放block
+ *  @param 
+ */
++ (void)stopLog;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WXApiObject.h b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WXApiObject.h
new file mode 100644 (file)
index 0000000..28828e2
--- /dev/null
@@ -0,0 +1,1026 @@
+//
+//  MMApiObject.h
+//  Api对象,包含所有接口和对象数据定义
+//
+//  Created by Wechat on 12-2-28.
+//  Copyright (c) 2012年 Tencent. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief 错误码
+ *
+ */
+enum  WXErrCode {
+    WXSuccess           = 0,    /**< 成功    */
+    WXErrCodeCommon     = -1,   /**< 普通错误类型    */
+    WXErrCodeUserCancel = -2,   /**< 用户点击取消并返回    */
+    WXErrCodeSentFail   = -3,   /**< 发送失败    */
+    WXErrCodeAuthDeny   = -4,   /**< 授权失败    */
+    WXErrCodeUnsupport  = -5,   /**< 微信不支持    */
+};
+
+
+
+/*! @brief 请求发送场景
+ *
+ */
+enum WXScene {
+    WXSceneSession          = 0,   /**< 聊天界面    */
+    WXSceneTimeline         = 1,   /**< 朋友圈     */
+    WXSceneFavorite         = 2,   /**< 收藏       */
+    WXSceneSpecifiedSession = 3,   /**< 指定联系人  */
+};
+
+
+enum WXAPISupport {
+    WXAPISupportSession = 0,
+};
+
+
+
+/*! @brief 跳转profile类型
+ *
+ */
+enum WXBizProfileType {
+    WXBizProfileType_Normal = 0,    //**< 普通公众号  */
+    WXBizProfileType_Device = 1,    //**< 硬件公众号  */
+};
+
+/*! @brief 分享小程序类型
+ *
+ */
+typedef NS_ENUM(NSUInteger, WXMiniProgramType) {
+    WXMiniProgramTypeRelease = 0,       //**< 正式版  */
+    WXMiniProgramTypeTest = 1,        //**< 开发版  */
+    WXMiniProgramTypePreview = 2,         //**< 体验版  */
+};
+
+/*! @brief 跳转mp网页类型
+ *
+ */
+enum WXMPWebviewType {
+    WXMPWebviewType_Ad = 0,        /**< 广告网页 **/
+};
+
+/*! @brief log的级别
+ *
+ */
+typedef NS_ENUM(NSInteger,WXLogLevel) {
+    WXLogLevelNormal = 0,      // 打印日常的日志
+    WXLogLevelDetail = 1,      // 打印详细的日志
+};
+
+
+/*! @brief 打印回调的block
+ *
+ */
+typedef void(^WXLogBolock)(NSString *log);
+
+#pragma mark - BaseReq
+/*! @brief 该类为微信终端SDK所有请求类的基类
+ *
+ */
+@interface BaseReq : NSObject
+
+/** 请求类型 */
+@property (nonatomic, assign) int type;
+/** 由用户微信号和AppID组成的唯一标识,需要校验微信用户是否换号登录时填写*/
+@property (nonatomic, copy) NSString *openID;
+
+@end
+
+
+
+#pragma mark - BaseResp
+/*! @brief 该类为微信终端SDK所有响应类的基类
+ *
+ */
+@interface BaseResp : NSObject
+/** 错误码 */
+@property (nonatomic, assign) int errCode;
+/** 错误提示字符串 */
+@property (nonatomic, copy) NSString *errStr;
+/** 响应类型 */
+@property (nonatomic, assign) int type;
+
+@end
+
+
+
+#pragma mark - WXMediaMessage
+@class WXMediaMessage;
+
+#ifndef BUILD_WITHOUT_PAY
+
+#pragma mark - PayReq
+/*! @brief 第三方向微信终端发起支付的消息结构体
+ *
+ *  第三方向微信终端发起支付的消息结构体,微信终端处理后会向第三方返回处理结果
+ * @see PayResp
+ */
+@interface PayReq : BaseReq
+
+/** 商家向财付通申请的商家id */
+@property (nonatomic, copy) NSString *partnerId;
+/** 预支付订单 */
+@property (nonatomic, copy) NSString *prepayId;
+/** 随机串,防重发 */
+@property (nonatomic, copy) NSString *nonceStr;
+/** 时间戳,防重发 */
+@property (nonatomic, assign) UInt32 timeStamp;
+/** 商家根据财付通文档填写的数据和签名 */
+@property (nonatomic, copy) NSString *package;
+/** 商家根据微信开放平台文档对数据做的签名 */
+@property (nonatomic, copy) NSString *sign;
+
+@end
+
+
+#pragma mark - PayResp
+/*! @brief 微信终端返回给第三方的关于支付结果的结构体
+ *
+ *  微信终端返回给第三方的关于支付结果的结构体
+ */
+@interface PayResp : BaseResp
+
+/** 财付通返回给商家的信息 */
+@property (nonatomic, copy) NSString *returnKey;
+
+@end
+
+#pragma mark - WXOfflinePay
+/*! @brief 第三方向微信终端发起离线支付
+ *
+ *  第三方向微信终端发起离线支付的消息结构体
+ */
+@interface WXOfflinePayReq : BaseReq
+
+@end
+
+/*! @brief 第三方向微信终端发起离线支付返回
+ *
+ *  第三方向微信终端发起离线支付返回的消息结构体
+ */
+@interface WXOfflinePayResp : BaseResp
+
+@end
+
+
+#pragma mark - WXNontaxPayReq
+@interface WXNontaxPayReq:BaseReq
+
+@property (nonatomic, copy) NSString *urlString;
+
+@end
+
+#pragma mark - WXNontaxPayResp
+@interface WXNontaxPayResp : BaseResp
+
+@property (nonatomic, copy) NSString *wxOrderId;
+
+@end
+
+#pragma mark - WXPayInsuranceReq
+@interface WXPayInsuranceReq : BaseReq
+
+@property (nonatomic, copy) NSString *urlString;
+
+@end
+
+#pragma mark - WXPayInsuranceResp
+@interface WXPayInsuranceResp : BaseResp
+
+@property (nonatomic, copy) NSString *wxOrderId;
+
+@end
+
+#endif
+
+
+#pragma mark - SendAuthReq
+/*! @brief 第三方程序向微信终端请求认证的消息结构
+ *
+ * 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,
+ * 向微信终端发送一个SendAuthReq消息结构。微信终端处理完后会向第三方程序发送一个处理结果。
+ * @see SendAuthResp
+ */
+@interface SendAuthReq : BaseReq
+/** 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,向微信终端发送一个SendAuthReq消息结构。微信终端处理完后会向第三方程序发送一个处理结果。
+ * @see SendAuthResp
+ * @note scope字符串长度不能超过1K
+ */
+@property (nonatomic, copy) NSString *scope;
+/** 第三方程序本身用来标识其请求的唯一性,最后跳转回第三方程序时,由微信终端回传。
+ * @note state字符串长度不能超过1K
+ */
+@property (nonatomic, copy) NSString *state;
+
+@end
+
+#pragma mark - SendAuthResp
+/*! @brief 微信处理完第三方程序的认证和权限申请后向第三方程序回送的处理结果。
+ *
+ * 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,向微信终端发送一个SendAuthReq消息结构。
+ * 微信终端处理完后会向第三方程序发送一个SendAuthResp。
+ * @see onResp
+ */
+@interface SendAuthResp : BaseResp
+@property (nonatomic, copy, nullable) NSString *code;
+/** 第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传
+ * @note state字符串长度不能超过1K
+ */
+@property (nonatomic, copy, nullable) NSString *state;
+@property (nonatomic, copy, nullable) NSString *lang;
+@property (nonatomic, copy, nullable) NSString *country;
+@end
+
+
+
+#pragma mark - SendMessageToWXReq
+/*! @brief 第三方程序发送消息至微信终端程序的消息结构体
+ *
+ * 第三方程序向微信发送信息需要传入SendMessageToWXReq结构体,信息类型包括文本消息和多媒体消息,
+ * 分别对应于text和message成员。调用该方法后,微信处理完信息会向第三方程序发送一个处理结果。
+ * @see SendMessageToWXResp
+ */
+@interface SendMessageToWXReq : BaseReq
+/** 发送消息的文本内容
+ * @note 文本长度必须大于0且小于10K
+ */
+@property (nonatomic, copy) NSString *text;
+/** 发送消息的多媒体内容
+ * @see WXMediaMessage
+ */
+@property (nonatomic, strong) WXMediaMessage *message;
+/** 发送消息的类型,包括文本消息和多媒体消息两种,两者只能选择其一,不能同时发送文本和多媒体消息 */
+@property (nonatomic, assign) BOOL bText;
+/** 发送的目标场景,可以选择发送到会话(WXSceneSession)或者朋友圈(WXSceneTimeline)。 默认发送到会话。
+ * @see WXScene
+ */
+@property (nonatomic, assign) int scene;
+/** 指定发送消息的人
+ * @note WXSceneSpecifiedSession时有效
+ */
+@property (nonatomic, copy, nullable) NSString *toUserOpenId;
+@end
+
+#pragma mark - SendMessageToWXResp
+/*! @brief 微信终端向第三方程序返回的SendMessageToWXReq处理结果。
+ *
+ * 第三方程序向微信终端发送SendMessageToWXReq后,微信发送回来的处理结果,该结果用SendMessageToWXResp表示。
+ */
+@interface SendMessageToWXResp : BaseResp
+@property(nonatomic, copy) NSString *lang;
+@property(nonatomic, copy) NSString *country;
+@end
+
+#pragma mark - GetMessageFromWXReq
+/*! @brief 微信终端向第三方程序请求提供内容的消息结构体。
+ *
+ * 微信终端向第三方程序请求提供内容,微信终端会向第三方程序发送GetMessageFromWXReq消息结构体,
+ * 需要第三方程序调用sendResp返回一个GetMessageFromWXResp消息结构体。
+ */
+@interface GetMessageFromWXReq : BaseReq
+@property (nonatomic, strong) NSString *lang;
+@property (nonatomic, strong) NSString *country;
+@end
+
+
+
+#pragma mark - GetMessageFromWXResp
+/*! @brief 微信终端向第三方程序请求提供内容,第三方程序向微信终端返回的消息结构体。
+ *
+ * 微信终端向第三方程序请求提供内容,第三方程序调用sendResp向微信终端返回一个GetMessageFromWXResp消息结构体。
+ */
+@interface GetMessageFromWXResp : BaseResp
+/** 向微信终端提供的文本内容
+ @note 文本长度必须大于0且小于10K
+ */
+@property (nonatomic, strong) NSString *text;
+/** 向微信终端提供的多媒体内容。
+ * @see WXMediaMessage
+ */
+@property (nonatomic, strong) WXMediaMessage *message;
+/** 向微信终端提供内容的消息类型,包括文本消息和多媒体消息两种,两者只能选择其一,不能同时发送文本和多媒体消息 */
+@property (nonatomic, assign) BOOL bText;
+@end
+
+
+
+#pragma mark - ShowMessageFromWXReq
+/*! @brief 微信通知第三方程序,要求第三方程序显示的消息结构体。
+ *
+ * 微信需要通知第三方程序显示或处理某些内容时,会向第三方程序发送ShowMessageFromWXReq消息结构体。
+ * 第三方程序处理完内容后调用sendResp向微信终端发送ShowMessageFromWXResp。
+ */
+@interface ShowMessageFromWXReq : BaseReq
+/** 微信终端向第三方程序发送的要求第三方程序处理的多媒体内容
+ * @see WXMediaMessage
+ */
+@property (nonatomic, strong) WXMediaMessage *message;
+@property (nonatomic, copy) NSString *lang;
+@property (nonatomic, copy) NSString *country;
+@end
+
+
+
+#pragma mark - ShowMessageFromWXResp
+/*! @brief 微信通知第三方程序,要求第三方程序显示或处理某些消息,第三方程序处理完后向微信终端发送的处理结果。
+ *
+ * 微信需要通知第三方程序显示或处理某些内容时,会向第三方程序发送ShowMessageFromWXReq消息结构体。
+ * 第三方程序处理完内容后调用sendResp向微信终端发送ShowMessageFromWXResp。
+ */
+@interface ShowMessageFromWXResp : BaseResp
+@end
+
+
+#pragma mark - LaunchFromWXReq
+/*! @brief 微信终端打开第三方程序携带的消息结构体
+ *
+ *  微信向第三方发送的结构体,第三方不需要返回
+ */
+@interface LaunchFromWXReq : BaseReq
+@property (nonatomic, strong) WXMediaMessage *message;
+@property (nonatomic, copy) NSString *lang;
+@property (nonatomic, copy) NSString *country;
+@end
+
+
+#pragma mark - OpenWebviewReq
+/* ! @brief 第三方通知微信启动内部浏览器,打开指定网页
+ *
+ *  第三方通知微信启动内部浏览器,打开指定Url对应的网页
+ */
+@interface OpenWebviewReq : BaseReq
+/** 需要打开的网页对应的Url
+ * @attention 长度不能超过1024
+ */
+@property(nonatomic, copy) NSString *url;
+
+@end
+
+#pragma mark - OpenWebviewResp
+/*! @brief 微信终端向第三方程序返回的OpenWebviewReq处理结果
+ *
+ * 第三方程序向微信终端发送OpenWebviewReq后,微信发送回来的处理结果,该结果用OpenWebviewResp表示
+ */
+@interface OpenWebviewResp : BaseResp
+
+@end
+
+
+
+#pragma mark - WXOpenBusinessWebViewReq
+/*! @brief 第三方通知微信启动内部浏览器,打开指定业务的网页
+ *
+ *
+ */
+@interface WXOpenBusinessWebViewReq : BaseReq
+
+/** 网页业务类型
+ * @attention
+ */
+@property (nonatomic, assign) UInt32 businessType;
+
+/** 网页业务参数
+ * @attention
+ */
+@property (nonatomic, strong, nullable) NSDictionary *queryInfoDic;
+
+@end
+
+#pragma mark - WXOpenBusinessWebViewResp
+/*! @brief 微信终端向第三方程序返回的WXOpenBusinessWebViewResp处理结果。
+ *
+ * 第三方程序向微信终端发送WXOpenBusinessWebViewReq后,微信发送回来的处理结果,该结果用WXOpenBusinessWebViewResp表示。
+ */
+@interface WXOpenBusinessWebViewResp : BaseResp
+/** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理
+ * @attention 长度不能超过2k
+ */
+@property (nonatomic, copy) NSString *result;
+
+/** 网页业务类型
+ * @attention
+ */
+@property (nonatomic, assign) UInt32 businessType;
+
+@end
+
+
+#pragma mark - OpenRankListReq
+/* ! @brief 第三方通知微信,打开硬件排行榜
+ *
+ * 第三方通知微信,打开硬件排行榜
+ */
+@interface OpenRankListReq : BaseReq
+
+@end
+
+#pragma mark - OpenRanklistResp
+/*! @brief 微信终端向第三方程序返回的OpenRankListReq处理结果。
+ *
+ * 第三方程序向微信终端发送OpenRankListReq后,微信发送回来的处理结果,该结果用OpenRankListResp表示。
+ */
+@interface OpenRankListResp : BaseResp
+
+@end
+
+
+#pragma mark - WXCardItem
+
+@interface WXCardItem : NSObject
+/** 卡id
+ * @attention 长度不能超过1024字节
+ */
+@property (nonatomic, copy) NSString *cardId;
+/** ext信息
+ * @attention 长度不能超过2024字节
+ */
+@property (nonatomic, copy, nullable) NSString *extMsg;
+/**
+ * @attention 卡的状态,req不需要填。resp:0为未添加,1为已添加。
+ */
+@property (nonatomic, assign) UInt32 cardState;
+/**
+ * @attention req不需要填,chooseCard返回的。
+ */
+@property (nonatomic, copy) NSString *encryptCode;
+/**
+ * @attention req不需要填,chooseCard返回的。
+ */
+@property (nonatomic, copy) NSString *appID;
+@end;
+
+#pragma mark - WXInvoiceItem
+
+@interface WXInvoiceItem : NSObject
+/** 卡id
+ * @attention 长度不能超过1024字节
+ */
+@property (nonatomic, copy) NSString *cardId;
+/** ext信息
+ * @attention 长度不能超过2024字节
+ */
+@property (nonatomic, copy, nullable) NSString *extMsg;
+/**
+ * @attention 卡的状态,req不需要填。resp:0为未添加,1为已添加。
+ */
+@property (nonatomic, assign) UInt32 cardState;
+/**
+ * @attention req不需要填,chooseCard返回的。
+ */
+@property (nonatomic, copy) NSString *encryptCode;
+/**
+ * @attention req不需要填,chooseCard返回的。
+ */
+@property (nonatomic, copy) NSString *appID;
+
+@end
+
+#pragma mark - AddCardToWXCardPackageReq
+/* ! @brief 请求添加卡券至微信卡包
+ *
+ */
+
+@interface AddCardToWXCardPackageReq : BaseReq
+/** 卡列表
+ * @attention 个数不能超过40个 类型WXCardItem
+ */
+@property (nonatomic, strong) NSArray *cardAry;
+
+@end
+
+
+#pragma mark - AddCardToWXCardPackageResp
+/** ! @brief 微信返回第三方添加卡券结果
+ *
+ */
+
+@interface AddCardToWXCardPackageResp : BaseResp
+/** 卡列表
+ * @attention 个数不能超过40个 类型WXCardItem
+ */
+@property (nonatomic, strong) NSArray *cardAry;
+@end
+
+#pragma mark - WXChooseCardReq
+/* ! @brief 请求从微信选取卡券
+ *
+ */
+
+@interface WXChooseCardReq : BaseReq
+@property (nonatomic, copy) NSString *appID;
+@property (nonatomic, assign) UInt32 shopID;
+@property (nonatomic, assign) UInt32 canMultiSelect;
+@property (nonatomic, copy) NSString *cardType;
+@property (nonatomic, copy) NSString *cardTpID;
+@property (nonatomic, copy) NSString *signType;
+@property (nonatomic, copy) NSString *cardSign;
+@property (nonatomic, assign) UInt32 timeStamp;
+@property (nonatomic, copy) NSString *nonceStr;
+@end
+
+
+#pragma mark - WXChooseCardResp
+/** ! @brief 微信返回第三方请求选择卡券结果
+ *
+ */
+
+@interface WXChooseCardResp : BaseResp
+@property (nonatomic, strong ) NSArray* cardAry;
+@end
+
+
+#pragma mark - WXChooseInvoiceReq
+/* ! @brief 请求从微信选取发票
+ *
+ */
+@interface WXChooseInvoiceReq : BaseReq
+@property (nonatomic, copy) NSString *appID;
+@property (nonatomic, assign) UInt32 shopID;
+@property (nonatomic, copy) NSString *signType;
+@property (nonatomic, copy) NSString *cardSign;
+@property (nonatomic, assign) UInt32 timeStamp;
+@property (nonatomic, copy) NSString *nonceStr;
+@end
+
+#pragma mark - WXChooseInvoiceResp
+/** ! @brief 微信返回第三方请求选择发票结果
+ *
+ */
+@interface WXChooseInvoiceResp : BaseResp
+@property (nonatomic, strong) NSArray* cardAry;
+@end
+
+#pragma mark - WXSubscriptionReq
+@interface WXSubscribeMsgReq : BaseReq
+@property (nonatomic, assign) UInt32 scene;
+@property (nonatomic, copy) NSString *templateId;
+@property (nonatomic, copy, nullable) NSString *reserved;
+@end
+
+#pragma mark - WXSubscriptionReq
+@interface WXSubscribeMsgResp : BaseResp
+
+@property (nonatomic, copy) NSString *templateId;
+@property (nonatomic, assign) UInt32 scene;
+@property (nonatomic, copy) NSString *action;
+@property (nonatomic, copy) NSString *reserved;
+@property (nonatomic, copy, nullable) NSString *openId;
+
+@end
+
+#pragma mark - WXSubscribeMiniProgramMsg
+/** ! @brief 第三方请求订阅小程序消息
+ *
+ */
+@interface WXSubscribeMiniProgramMsgReq : BaseReq
+@property (nonatomic, copy) NSString *miniProgramAppid;
+@end
+
+#pragma mark - WXSubscriptionReq
+@interface WXSubscribeMiniProgramMsgResp : BaseResp
+
+@property(nonatomic, copy) NSString *openId;   // 小程序openid
+@property(nonatomic, copy) NSString *unionId;  // unionId
+@property(nonatomic, copy) NSString *nickName; // 用户昵称
+
+@end
+
+#pragma mark - WXinvoiceAuthInsertReq
+@interface WXInvoiceAuthInsertReq : BaseReq
+
+@property (nonatomic, copy) NSString *urlString;
+
+@end
+
+#pragma mark - WXinvoiceAuthInsertResp
+
+@interface WXInvoiceAuthInsertResp : BaseResp
+
+@property (nonatomic, copy) NSString *wxOrderId;
+
+@end
+
+#pragma mark - WXMediaMessage
+
+/*! @brief 多媒体消息结构体
+ *
+ * 用于微信终端和第三方程序之间传递消息的多媒体消息内容
+ */
+@interface WXMediaMessage : NSObject
+
++ (WXMediaMessage *)message;
+
+/** 标题
+ * @note 长度不能超过512字节
+ */
+@property (nonatomic, copy) NSString *title;
+/** 描述内容
+ * @note 长度不能超过1K
+ */
+@property (nonatomic, copy) NSString *description;
+/** 缩略图数据
+ * @note 大小不能超过64K
+ */
+@property (nonatomic, strong, nullable) NSData *thumbData;
+/**
+ * @note 长度不能超过64字节
+ */
+@property (nonatomic, copy, nullable) NSString *mediaTagName;
+/**
+ *
+ */
+@property (nonatomic, copy, nullable) NSString *messageExt;
+@property (nonatomic, copy, nullable) NSString *messageAction;
+/**
+ * 多媒体数据对象,可以为WXImageObject,WXMusicObject,WXVideoObject,WXWebpageObject等。
+ */
+@property (nonatomic, strong) id mediaObject;
+
+/*! @brief 设置消息缩略图的方法
+ *
+ * @param image 缩略图
+ * @note 大小不能超过64K
+ */
+- (void)setThumbImage:(UIImage *)image;
+
+@end
+
+
+
+#pragma mark - WXImageObject
+/*! @brief 多媒体消息中包含的图片数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的图片数据对象。
+ * @note imageData成员不能为空
+ * @see WXMediaMessage
+ */
+@interface WXImageObject : NSObject
+/*! @brief 返回一个WXImageObject对象
+ *
+ * @note 返回的WXImageObject对象是自动释放的
+ */
++ (WXImageObject *)object;
+
+/** 图片真实数据内容
+ * @note 大小不能超过25M
+ */
+@property (nonatomic, strong) NSData *imageData;
+
+@end
+
+
+#pragma mark - WXMusicObject
+/*! @brief 多媒体消息中包含的音乐数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的音乐数据对象。
+ * @note musicUrl和musicLowBandUrl成员不能同时为空。
+ * @see WXMediaMessage
+ */
+@interface WXMusicObject : NSObject
+/*! @brief 返回一个WXMusicObject对象
+ *
+ * @note 返回的WXMusicObject对象是自动释放的
+ */
++ (WXMusicObject *)object;
+
+/** 音乐网页的url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *musicUrl;
+/** 音乐lowband网页的url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *musicLowBandUrl;
+/** 音乐数据url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *musicDataUrl;
+
+/**音乐lowband数据url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *musicLowBandDataUrl;
+
+/**音乐封面图Url
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *songAlbumUrl;
+
+/**歌词信息 LRC格式
+ * @note 长度不能超过32K
+ */
+@property (nonatomic, copy, nullable) NSString *songLyric;
+@end
+
+
+
+#pragma mark - WXVideoObject
+/*! @brief 多媒体消息中包含的视频数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的视频数据对象。
+ * @note videoUrl和videoLowBandUrl不能同时为空。
+ * @see WXMediaMessage
+ */
+@interface WXVideoObject : NSObject
+/*! @brief 返回一个WXVideoObject对象
+ *
+ * @note 返回的WXVideoObject对象是自动释放的
+ */
++ (WXVideoObject *)object;
+
+/** 视频网页的url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *videoUrl;
+/** 视频lowband网页的url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *videoLowBandUrl;
+
+@end
+
+
+
+#pragma mark - WXWebpageObject
+/*! @brief 多媒体消息中包含的网页数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的网页数据对象。
+ * @see WXMediaMessage
+ */
+@interface WXWebpageObject : NSObject
+/*! @brief 返回一个WXWebpageObject对象
+ *
+ * @note 返回的WXWebpageObject对象是自动释放的
+ */
++ (WXWebpageObject *)object;
+
+/** 网页的url地址
+ * @note 不能为空且长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *webpageUrl;
+
+@end
+
+
+
+#pragma mark - WXAppExtendObject
+/*! @brief 多媒体消息中包含的App扩展数据对象
+ *
+ * 第三方程序向微信终端发送包含WXAppExtendObject的多媒体消息,
+ * 微信需要处理该消息时,会调用该第三方程序来处理多媒体消息内容。
+ * @note url,extInfo和fileData不能同时为空
+ * @see WXMediaMessage
+ */
+@interface WXAppExtendObject : NSObject
+/*! @brief 返回一个WXAppExtendObject对象
+ *
+ * @note 返回的WXAppExtendObject对象是自动释放的
+ */
++ (WXAppExtendObject *)object;
+
+/** 若第三方程序不存在,微信终端会打开该url所指的App下载地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *url;
+/** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理
+ * @note 长度不能超过2K
+ */
+@property (nonatomic, copy, nullable) NSString *extInfo;
+/** App文件数据,该数据发送给微信好友,微信好友需要点击后下载数据,微信终端会回传给第三方程序处理
+ * @note 大小不能超过10M
+ */
+@property (nonatomic, strong, nullable) NSData *fileData;
+
+@end
+
+
+
+#pragma mark - WXEmoticonObject
+/*! @brief 多媒体消息中包含的表情数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的表情数据对象。
+ * @see WXMediaMessage
+ */
+@interface WXEmoticonObject : NSObject
+
+/*! @brief 返回一个WXEmoticonObject对象
+ *
+ * @note 返回的WXEmoticonObject对象是自动释放的
+ */
++ (WXEmoticonObject *)object;
+
+/** 表情真实数据内容
+ * @note 大小不能超过10M
+ */
+@property (nonatomic, strong) NSData *emoticonData;
+
+@end
+
+
+
+#pragma mark - WXFileObject
+/*! @brief 多媒体消息中包含的文件数据对象
+ *
+ * @see WXMediaMessage
+ */
+@interface WXFileObject : NSObject
+
+/*! @brief 返回一个WXFileObject对象
+ *
+ * @note 返回的WXFileObject对象是自动释放的
+ */
++ (WXFileObject *)object;
+
+/** 文件后缀名
+ * @note 长度不超过64字节
+ */
+@property (nonatomic, copy) NSString *fileExtension;
+
+/** 文件真实数据内容
+ * @note 大小不能超过10M
+ */
+@property (nonatomic, strong) NSData *fileData;
+
+@end
+
+
+#pragma mark - WXLocationObject
+/*! @brief 多媒体消息中包含的地理位置数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的地理位置数据对象。
+ * @see WXMediaMessage
+ */
+@interface WXLocationObject : NSObject
+
+/*! @brief 返回一个WXLocationObject对象
+ *
+ * @note 返回的WXLocationObject对象是自动释放的
+ */
++ (WXLocationObject *)object;
+
+/** 地理位置信息
+ * @note 经纬度
+ */
+@property (nonatomic, assign) double lng; //经度
+@property (nonatomic, assign) double lat; //纬度
+
+@end
+
+#pragma mark - WXTextObject
+/*! @brief 多媒体消息中包含的文本数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的文本数据对象。
+ * @see WXMediaMessage
+ */
+@interface WXTextObject : NSObject
+
+/*! @brief 返回一个WXTextObject对象
+ *
+ * @note 返回的WXTextObject对象是自动释放的
+ */
++ (WXTextObject *)object;
+
+/** 地理位置信息
+ * @note 文本内容
+ */
+@property (nonatomic, copy) NSString *contentText;
+
+@end
+
+#pragma mark - WXMiniProgramObject
+
+@interface WXMiniProgramObject : NSObject
+
+/*! @brief WXMiniProgramObject对象
+ *
+ * @note 返回的WXMiniProgramObject对象是自动释放的
+ */
++ (WXMiniProgramObject *)object;
+
+/** 低版本网页链接
+ * @attention 长度不能超过1024字节
+ */
+@property (nonatomic, copy) NSString *webpageUrl;
+
+/** 小程序username */
+@property (nonatomic, copy) NSString *userName;
+
+/** 小程序页面的路径
+ * @attention 不填默认拉起小程序首页
+ */
+@property (nonatomic, copy, nullable) NSString *path;
+
+/** 小程序新版本的预览图
+ * @attention 大小不能超过128k
+ */
+@property (nonatomic, strong, nullable) NSData *hdImageData;
+
+/** 是否使用带 shareTicket 的转发 */
+@property (nonatomic, assign) BOOL withShareTicket;
+
+/** 分享小程序的版本
+ * @attention (正式,开发,体验)
+ */
+@property (nonatomic, assign) WXMiniProgramType miniProgramType;
+
+/** 是否禁用转发 */
+@property (nonatomic, assign) BOOL disableForward;
+
+@end
+
+#pragma mark - WXLaunchMiniProgramReq
+
+/*! @brief WXLaunchMiniProgramReq对象, 可实现通过sdk拉起微信小程序
+ *
+ * @note 返回的WXLaunchMiniProgramReq对象是自动释放的
+ */
+@interface WXLaunchMiniProgramReq : BaseReq
+
++ (WXLaunchMiniProgramReq *)object;
+
+/** 小程序username */
+@property (nonatomic, copy) NSString *userName;
+
+/** 小程序页面的路径
+ * @attention 不填默认拉起小程序首页
+ */
+@property (nonatomic, copy, nullable) NSString *path;
+
+/** 分享小程序的版本
+ * @attention (正式,开发,体验)
+ */
+@property (nonatomic, assign) WXMiniProgramType miniProgramType;
+
+/** ext信息
+ * @attention json格式
+ */
+@property (nonatomic, copy, nullable) NSString *extMsg;
+
+/** extDic
+ * @attention 字典,可存放图片等比较大的数据
+ */
+@property (nonatomic, copy, nullable) NSDictionary *extDic;
+
+@end
+
+#pragma mark - WXLaunchMiniProgramResp
+/*! @brief 微信终端向第三方程序返回的WXLaunchMiniProgramReq处理结果。
+ *
+ * 第三方程序向微信终端发送WXLaunchMiniProgramReq后,微信发送回来的处理结果,该结果用WXLaunchMiniProgramResp表示。
+ */
+@interface WXLaunchMiniProgramResp : BaseResp
+
+@property (nonatomic, copy, nullable) NSString *extMsg;
+
+@end
+
+
+#pragma mark - WXOpenBusinessViewReq
+/*! @brief WXOpenBusinessViewReq对象, 可实现第三方通知微信启动,打开业务页面
+ *
+ * @note 返回的WXOpenBusinessViewReq对象是自动释放的
+ */
+
+@interface WXOpenBusinessViewReq : BaseReq
+
++ (WXOpenBusinessViewReq *)object;
+
+/** 业务类型
+ */
+@property (nonatomic, copy) NSString *businessType;
+
+/** 业务参数
+ */
+@property (nonatomic, copy, nullable) NSString *query;
+
+/** ext信息
+ * @note 选填,json格式
+ */
+@property (nonatomic, copy, nullable) NSString *extInfo;
+
+/** extData数据
+ * @note
+ */
+@property (nonatomic, strong, nullable) NSData *extData;
+@end
+
+
+@interface WXOpenBusinessViewResp : BaseResp
+
+/** 业务类型
+ */
+@property (nonatomic, copy) NSString *businessType;
+
+/** 业务返回数据
+ */
+@property (nonatomic, copy, nullable) NSString *extMsg;
+
+@end
+NS_ASSUME_NONNULL_END
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WechatAuthSDK.h b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/WechatAuthSDK.h
new file mode 100644 (file)
index 0000000..308aaea
--- /dev/null
@@ -0,0 +1,68 @@
+//
+//  WechatAuthSDK.h
+//  WechatAuthSDK
+//
+//  Created by 李凯 on 13-11-29.
+//  Copyright (c) 2013年 Tencent. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+enum  AuthErrCode {
+    WechatAuth_Err_Ok = 0,  //Auth成功
+    WechatAuth_Err_NormalErr = -1,  //普通错误
+    WechatAuth_Err_NetworkErr = -2, //网络错误
+    WechatAuth_Err_GetQrcodeFailed = -3,    //获取二维码失败
+    WechatAuth_Err_Cancel = -4,     //用户取消授权
+    WechatAuth_Err_Timeout = -5,    //超时
+};
+
+@protocol WechatAuthAPIDelegate<NSObject>
+@optional
+
+- (void)onAuthGotQrcode:(UIImage *)image;  //得到二维码
+- (void)onQrcodeScanned;    //二维码被扫描
+- (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode;    //成功登录
+
+@end
+
+@interface WechatAuthSDK : NSObject{
+    NSString *_sdkVersion;
+    __weak id<WechatAuthAPIDelegate> _delegate;
+}
+
+@property(nonatomic, weak, nullable) id<WechatAuthAPIDelegate> delegate;
+@property(nonatomic, readonly) NSString *sdkVersion;   //authSDK版本号
+
+/*! @brief 发送登录请求,等待WechatAuthAPIDelegate回调
+ *
+ * @param appId 微信开发者ID
+ * @param nonceStr 一个随机的尽量不重复的字符串,用来使得每次的signature不同
+ * @param timeStamp 时间戳
+ * @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔
+ * @param signature 签名
+ * @param schemeData 会在扫码后拼在scheme后
+ * @return 成功返回YES,失败返回NO
+    注:该实现只保证同时只有一个Auth在运行,Auth未完成或未Stop再次调用Auth接口时会返回NO。
+ */
+
+- (BOOL)Auth:(NSString *)appId
+    nonceStr:(NSString *)nonceStr
+   timeStamp:(NSString *)timeStamp
+       scope:(NSString *)scope
+   signature:(NSString *)signature
+  schemeData:(nullable NSString *)schemeData;
+
+
+/*! @brief 暂停登录请求
+ *
+ * @return 成功返回YES,失败返回NO。
+ */
+- (BOOL)StopAuth;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/libWeChatSDK.a b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/libWeChatSDK.a
new file mode 100644 (file)
index 0000000..ddf18bb
Binary files /dev/null and b/platforms/ios/dlapp/Plugins/cordova-plugin-wechat/libWeChatSDK.a differ
index 66cd47a..6e5270f 100755 (executable)
     <feature name="QQSDK">
         <param name="ios-package" value="CDVQQSDK" />
     </feature>
+    <feature name="Wechat">
+        <param name="ios-package" value="CDVWechat" />
+        <param name="onload" value="true" />
+    </feature>
     <name short="大理智警">dlapp</name>
     <description>
         A sample Apache Cordova application that responds to the deviceready event.
     <preference name="StatusBarStyle" value="lightcontent" />
     <preference name="CameraUsesGeolocation" value="false" />
     <preference name="QQ_APP_ID" value="101885581" />
+    <preference name="WECHATAPPID" value="wxa483e2c392b08993" />
+    <preference name="UNIVERSALLINK" value="YOUR_UNIVERSAL_LINK" />
     <preference name="AutoHideSplashScreen" value="true" />
     <preference name="SplashScreenDelay" value="0" />
     <preference name="SplashShowOnlyFirstTime" value="true" />
index 07026c3..649db61 100644 (file)
                                <string>tencent101885581</string>
                        </array>
                </dict>
+               <dict>
+                       <key>CFBundleURLName</key>
+                       <string>weixin</string>
+                       <key>CFBundleURLSchemes</key>
+                       <array>
+                               <string>wxa483e2c392b08993</string>
+                       </array>
+               </dict>
        </array>
        <key>LSApplicationQueriesSchemes</key>
        <array>
                <string>timopensdkdataline</string>
                <string>wtlogintimV1</string>
                <string>timapiV1</string>
+               <string>weixin</string>
+               <string>wechat</string>
+               <string>weixinULAPI</string>
        </array>
        <key>NSCameraUsageDescription</key>
        <string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>
index d516bf0..8022925 100644 (file)
@@ -1,21 +1,24 @@
 {
-    "Security.framework": 4,
-    "SystemConfiguration.framework": 3,
+    "Security.framework": 5,
+    "SystemConfiguration.framework": 4,
     "LocalAuthentication.framework": 1,
     "ImageIO.framework": 1,
     "CoreLocation.framework": 1,
     "AVFoundation.framework": 1,
-    "CFNetwork.framework": 1,
+    "CFNetwork.framework": 2,
     "CoreFoundation.framework": 1,
-    "CoreTelephony.framework": 2,
+    "CoreTelephony.framework": 3,
     "Foundation.framework": 1,
     "UIKit.framework": 2,
-    "libz.tbd": 2,
+    "libz.tbd": 3,
     "AdSupport.framework": 1,
     "UserNotifications.framework": 1,
     "libresolv.tbd": 1,
     "WebKit.framework": 1,
     "libiconv.tbd": 1,
     "libsqlite3.tbd": 1,
-    "libstdc++.tbd": 1
+    "libstdc++.tbd": 1,
+    "libsqlite3.0.tbd": 1,
+    "Webkit.framework": 1,
+    "libc++.1.tbd": 1
 }
\ No newline at end of file
index 543eb31..c718eee 100644 (file)
             {
               "xml": "<preference name=\"QQ_APP_ID\" value=\"101885581\" />",
               "count": 1
+            },
+            {
+              "xml": "<feature name=\"Wechat\"><param name=\"ios-package\" value=\"CDVWechat\" /><param name=\"onload\" value=\"true\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<preference name=\"WECHATAPPID\" value=\"wxa483e2c392b08993\" />",
+              "count": 1
+            },
+            {
+              "xml": "<preference name=\"UNIVERSALLINK\" value=\"YOUR_UNIVERSAL_LINK\" />",
+              "count": 1
             }
           ]
         }
             {
               "xml": "<array><dict><key>CFBundleTypeRole</key><string>Editor</string><key>CFBundleURLName</key><string>tencentopenapi</string><key>CFBundleURLSchemes</key><array><string>tencent101885581</string></array></dict></array>",
               "count": 1
+            },
+            {
+              "xml": "<array><dict><key>CFBundleURLName</key><string>weixin</string><key>CFBundleURLSchemes</key><array><string>wxa483e2c392b08993</string></array></dict></array>",
+              "count": 1
             }
           ],
           "LSApplicationQueriesSchemes": [
             {
               "xml": "<array><string>mqqapi</string><string>mqq</string><string>mqqOpensdkSSoLogin</string><string>mqqconnect</string><string>mqqopensdkdataline</string><string>mqqopensdkgrouptribeshare</string><string>mqqopensdkfriend</string><string>mqqopensdkapi</string><string>mqqopensdkapiV2</string><string>mqqopensdkapiV3</string><string>mqqopensdkapiV4</string><string>mqzoneopensdk</string><string>wtloginmqq</string><string>wtloginmqq2</string><string>mqqwpa</string><string>mqzone</string><string>mqzonev2</string><string>mqzoneshare</string><string>wtloginqzone</string><string>mqzonewx</string><string>mqzoneopensdkapiV2</string><string>mqzoneopensdkapi19</string><string>mqzoneopensdkapi</string><string>mqzoneopensdk</string><string>mqqgamebindinggroup</string><string>tencentapi.qq.reqContent</string><string>tencentapi.qzone.reqContent</string><string>tim</string><string>timapi</string><string>timopensdkfriend</string><string>timwpa</string><string>timgamebindinggroup</string><string>timapiwallet</string><string>timOpensdkSSoLogin</string><string>wtlogintim</string><string>timopensdkgrouptribeshare</string><string>timopensdkapiV4</string><string>timgamebindinggroup</string><string>timopensdkdataline</string><string>wtlogintimV1</string><string>timapiV1</string></array>",
               "count": 1
+            },
+            {
+              "xml": "<array><string>weixin</string><string>wechat</string><string>weixinULAPI</string></array>",
+              "count": 1
+            }
+          ],
+          "NSAppTransportSecurity": [
+            {
+              "xml": "<dict><key>NSAllowsArbitraryLoads</key><true /></dict>",
+              "count": 1
             }
           ]
         }
     "cordova-plugin-qqsdk": {
       "QQ_APP_ID": "101885581",
       "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-wechat": {
+      "WECHATAPPID": "wxa483e2c392b08993",
+      "UNIVERSALLINK": "YOUR_UNIVERSAL_LINK",
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
     }
   },
   "dependent_plugins": {},
       "clobbers": [
         "QQSDK"
       ]
+    },
+    {
+      "id": "cordova-plugin-wechat.Wechat",
+      "file": "plugins/cordova-plugin-wechat/www/wechat.js",
+      "pluginId": "cordova-plugin-wechat",
+      "clobbers": [
+        "Wechat"
+      ]
     }
   ],
   "plugin_metadata": {
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
     "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
-    "cordova-plugin-qqsdk": "0.9.7"
+    "cordova-plugin-qqsdk": "0.9.7",
+    "cordova-plugin-wechat": "3.0.0"
   }
 }
index 3e450c8..45f3e0b 100644 (file)
@@ -375,6 +375,14 @@ cordova.define('cordova/plugin_list', function(require, exports, module) {
       "clobbers": [
         "QQSDK"
       ]
+    },
+    {
+      "id": "cordova-plugin-wechat.Wechat",
+      "file": "plugins/cordova-plugin-wechat/www/wechat.js",
+      "pluginId": "cordova-plugin-wechat",
+      "clobbers": [
+        "Wechat"
+      ]
     }
   ];
   module.exports.metadata = {
@@ -397,6 +405,7 @@ cordova.define('cordova/plugin_list', function(require, exports, module) {
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
     "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
-    "cordova-plugin-qqsdk": "0.9.7"
+    "cordova-plugin-qqsdk": "0.9.7",
+    "cordova-plugin-wechat": "3.0.0"
   };
 });
\ No newline at end of file
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-wechat/www/wechat.js b/platforms/ios/platform_www/plugins/cordova-plugin-wechat/www/wechat.js
new file mode 100644 (file)
index 0000000..7f86ab9
--- /dev/null
@@ -0,0 +1,190 @@
+cordova.define("cordova-plugin-wechat.Wechat", function(require, exports, module) {
+var exec = require('cordova/exec');
+
+module.exports = {
+    Scene: {
+        SESSION:  0, // 聊天界面
+        TIMELINE: 1, // 朋友圈
+        FAVORITE: 2  // 收藏
+    },
+
+    Type: {
+        APP:     1,
+        EMOTION: 2,
+        FILE:    3,
+        IMAGE:   4,
+        MUSIC:   5,
+        VIDEO:   6,
+        WEBPAGE: 7,
+        MINI:    8
+    },
+
+    Mini: {
+        RELEASE: 0, // 正式版
+        TEST:    1, // 测试版
+        PREVIEW: 2  // 体验版
+    },
+
+    isInstalled: function (onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "isWXAppInstalled", []);
+    },
+
+    /**
+     * Share a message to wechat app
+     *
+     * @example
+     * <code>
+     * Wechat.share({
+     *     message: {
+     *        title: "Message Title",
+     *        description: "Message Description(optional)",
+     *        mediaTagName: "Media Tag Name(optional)",
+     *        thumb: "http://YOUR_THUMBNAIL_IMAGE",
+     *        media: {
+     *            type: Wechat.Type.WEBPAGE,   // webpage
+     *            webpageUrl: "https://github.com/xu-li/cordova-plugin-wechat"    // webpage
+     *        }
+     *    },
+     *    scene: Wechat.Scene.TIMELINE   // share to Timeline
+     * }, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    share: function (message, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "share", [message]);
+    },
+
+    /**
+     * Sending an auth request to Wechat
+     *
+     * @example
+     * <code>
+     * Wechat.auth(function (response) { alert(response.code); });
+     * </code>
+     */
+    auth: function (scope, state, onSuccess, onError) {
+        if (typeof scope == "function") {
+            // Wechat.auth(function () { alert("Success"); });
+            // Wechat.auth(function () { alert("Success"); }, function (error) { alert(error); });
+            return exec(scope, state, "Wechat", "sendAuthRequest");
+        }
+
+        if (typeof state == "function") {
+            // Wechat.auth("snsapi_userinfo", function () { alert("Success"); });
+            // Wechat.auth("snsapi_userinfo", function () { alert("Success"); }, function (error) { alert(error); });
+            return exec(state, onSuccess, "Wechat", "sendAuthRequest", [scope]);
+        }
+
+        return exec(onSuccess, onError, "Wechat", "sendAuthRequest", [scope, state]);
+    },
+
+    /**
+     * Send a payment request
+     *
+     * @link https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1
+     * @example
+     * <code>
+     * var params = {
+     *     mch_id: '10000100', // merchant id
+     *     prepay_id: 'wx201411101639507cbf6ffd8b0779950874', // prepay id returned from server
+     *     nonce: '1add1a30ac87aa2db72f57a2375d8fec', // nonce string returned from server
+     *     timestamp: '1439531364', // timestamp
+     *     sign: '0CB01533B8C1EF103065174F50BCA001', // signed string
+     * };
+     * Wechat.sendPaymentRequest(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    sendPaymentRequest: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "sendPaymentRequest", [params]);
+    },
+
+    /**
+     * jumpToBizProfile (跳转到某个微信公众号)2016-11-11 测试是失效的,囧
+     *
+     * @link https://segmentfault.com/a/1190000007204624
+     * @link https://segmentfault.com/q/1010000003907796
+     * @example
+     * <code>
+     * var params = {
+     *     info: 'gh_xxxxxxx', // 公众帐号原始ID
+     *     type:  'Normal' // 普通号
+     * }
+     * or
+     * var params = {
+     *     info: 'extMsg', // 相关的硬件二维码串
+     *     type:  'Device' // 硬件号
+     * };
+     * Wechat.jumpToBizProfile(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+
+    jumpToBizProfile: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "jumpToBizProfile", [params]);
+    },
+
+    /**
+     * jumpToWechat (因为jumpToBizProfile失效了,暂时新增了一个临时的api)
+     *
+     * @link https://segmentfault.com/a/1190000007204624
+     * @example
+     * <code>
+     * var url = "wechat://" 现阶段貌似只支持这一个协议了
+     * Wechat.jumpToWechat(url, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    jumpToWechat: function (url, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "jumpToWechat", [url]);
+    },
+
+    /**
+     * chooseInvoiceFromWX exq:choose invoices from Wechat card list
+     *
+     * @example
+     * <code>
+     * params: signType, cardSign, nonceStr, timeStamp  all required
+     * Wechat.chooseInvoiceFromWX(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    chooseInvoiceFromWX: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "chooseInvoiceFromWX", [params]);
+    },
+
+    /**
+     * openMiniProgram exq:app opens wechat mini program
+     *
+     * @example
+     * <code>
+     * params: userName, path, miniprogramType  all required
+     * Wechat.openMiniProgram(params, function (data) {
+     *     alert(data.extMsg);
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    openMiniProgram: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "openMiniProgram", [params]);
+    }
+
+};
+
+});
index f40f980..0e823e7 100644 (file)
     "cordova-plugin-qqsdk": {
       "QQ_APP_ID": "101885581",
       "PACKAGE_NAME": "com.dalipolice.app"
+    },
+    "cordova-plugin-wechat": {
+      "WECHATAPPID": "wxa483e2c392b08993",
+      "UNIVERSALLINK": "YOUR_UNIVERSAL_LINK",
+      "PACKAGE_NAME": "com.dalipolice.app"
     }
   },
   "dependent_plugins": {
index 8c304f2..fcafb8c 100644 (file)
     "cordova-plugin-qqsdk": {
       "QQ_APP_ID": "101885581",
       "PACKAGE_NAME": "com.dalipolice.app"
+    },
+    "cordova-plugin-wechat": {
+      "WECHATAPPID": "wxa483e2c392b08993",
+      "UNIVERSALLINK": "YOUR_UNIVERSAL_LINK",
+      "PACKAGE_NAME": "com.dalipolice.app"
     }
   },
   "dependent_plugins": {
diff --git a/plugins/cordova-plugin-wechat/android-build.gradle b/plugins/cordova-plugin-wechat/android-build.gradle
new file mode 100644 (file)
index 0000000..317ddcb
--- /dev/null
@@ -0,0 +1,7 @@
+repositories {
+    jcenter()
+}
+
+dependencies {
+    compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
+}
diff --git a/plugins/cordova-plugin-wechat/donate.png b/plugins/cordova-plugin-wechat/donate.png
new file mode 100644 (file)
index 0000000..19928bc
Binary files /dev/null and b/plugins/cordova-plugin-wechat/donate.png differ
diff --git a/plugins/cordova-plugin-wechat/package.json b/plugins/cordova-plugin-wechat/package.json
new file mode 100644 (file)
index 0000000..b654483
--- /dev/null
@@ -0,0 +1,72 @@
+{
+  "_from": "git+https://github.com/xu-li/cordova-plugin-wechat.git",
+  "_id": "cordova-plugin-wechat@3.0.0",
+  "_inBundle": false,
+  "_integrity": "",
+  "_location": "/cordova-plugin-wechat",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "git",
+    "raw": "git+https://github.com/xu-li/cordova-plugin-wechat.git",
+    "rawSpec": "git+https://github.com/xu-li/cordova-plugin-wechat.git",
+    "saveSpec": "git+https://github.com/xu-li/cordova-plugin-wechat.git",
+    "fetchSpec": "https://github.com/xu-li/cordova-plugin-wechat.git",
+    "gitCommittish": null
+  },
+  "_requiredBy": [
+    "#USER",
+    "/"
+  ],
+  "_resolved": "git+https://github.com/xu-li/cordova-plugin-wechat.git#82f4fbc259ea7371eed2eff57645b29fd76af718",
+  "_spec": "git+https://github.com/xu-li/cordova-plugin-wechat.git",
+  "_where": "E:\\alipay\\mobile",
+  "author": {
+    "name": "xu.li",
+    "email": "AthenaLightenedMyPath@gmail.com"
+  },
+  "bugs": {
+    "url": "https://github.com/xu-li/cordova-plugin-wechat/issues"
+  },
+  "bundleDependencies": false,
+  "cordova": {
+    "id": "cordova-plugin-wechat",
+    "platforms": [
+      "ios",
+      "android"
+    ]
+  },
+  "dependencies": {
+    "shelljs": "^0.5.3"
+  },
+  "deprecated": false,
+  "description": "A cordova plugin, a JS version of Wechat SDK",
+  "engines": {
+    "cordovaDependencies": {
+      "2.0.0": {
+        "cordova": ">=6.1.0",
+        "cordova-android": ">=6.1.0",
+        "cordova-ios": ">=4.3.1"
+      },
+      "<2.0.0": {
+        "cordova": ">=3.5.0"
+      }
+    }
+  },
+  "homepage": "https://github.com/xu-li/cordova-plugin-wechat#readme",
+  "keywords": [
+    "cordova",
+    "wechat",
+    "weixin",
+    "share",
+    "ecosystem:cordova",
+    "cordova-ios",
+    "cordova-android"
+  ],
+  "license": "MIT",
+  "name": "cordova-plugin-wechat",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/xu-li/cordova-plugin-wechat.git"
+  },
+  "version": "3.0.0"
+}
diff --git a/plugins/cordova-plugin-wechat/plugin.xml b/plugins/cordova-plugin-wechat/plugin.xml
new file mode 100644 (file)
index 0000000..0e9dc33
--- /dev/null
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+    xmlns:rim="http://www.blackberry.com/ns/widgets"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="cordova-plugin-wechat"
+    version="3.0.0">
+
+    <name>Wechat</name>
+    <description>A cordova plugin, a JS version of Wechat SDK</description>
+    <license>MIT</license>
+    <keywords>cordova,wechat,weixin,share</keywords>
+    <repo>https://github.com/xu-li/cordova-plugin-wechat.git</repo>
+    <issue>https://github.com/xu-li/cordova-plugin-wechat/issues</issue>
+
+    <!-- add this to your config.xml -->
+    <!-- <preference name="WECHATAPPID" value="YOUR_WECHAT_APP_ID_HERE" /> -->
+    <preference name="WECHATAPPID" />
+    <preference name="UNIVERSALLINK" />
+
+    <!-- js module-->
+    <js-module src="www/wechat.js" name="Wechat">
+        <clobbers target="Wechat" />
+    </js-module>
+
+    <!-- ios -->
+    <platform name="ios">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Wechat">
+                <param name="ios-package" value="CDVWechat"/>
+                <param name="onload" value="true" />
+            </feature>
+            <preference name="WECHATAPPID" value="$WECHATAPPID"/>
+            <preference name="UNIVERSALLINK" value="$UNIVERSALLINK"/>
+        </config-file>
+
+        <config-file target="*-Info.plist" parent="LSApplicationQueriesSchemes">
+            <array>
+                <string>weixin</string>
+                <string>wechat</string>
+                <string>weixinULAPI</string>
+            </array>
+        </config-file>
+
+        <config-file target="*-Info.plist" parent="NSAppTransportSecurity">
+            <dict>
+                <key>NSAllowsArbitraryLoads</key>
+                <true/>
+            </dict>
+        </config-file>
+
+
+        <config-file target="*-Info.plist" parent="CFBundleURLTypes">
+            <array>
+                <dict>
+                    <key>CFBundleURLName</key>
+                    <string>weixin</string>
+                    <key>CFBundleURLSchemes</key>
+                    <array>
+                        <string>$WECHATAPPID</string>
+                    </array>
+                </dict>
+            </array>
+        </config-file>
+
+        <!-- Plugin source code -->
+        <header-file src="src/ios/CDVWechat.h" />
+        <source-file src="src/ios/CDVWechat.m" />
+        <header-file src="src/ios/AppDelegate+Wechat.h" />
+        <source-file src="src/ios/AppDelegate+Wechat.m" />
+
+        <!-- Wechat Official -->
+        <header-file src="src/ios/libs/OpenSDK1.8.6.2/WXApi.h" />
+        <header-file src="src/ios/libs/OpenSDK1.8.6.2/WXApiObject.h" />
+        <header-file src="src/ios/libs/OpenSDK1.8.6.2/WechatAuthSDK.h" />
+        <source-file src="src/ios/libs/OpenSDK1.8.6.2/libWeChatSDK.a" framework="true" />
+
+        <!-- Other required frameworks -->
+        <framework src="libz.tbd" />
+        <framework src="libsqlite3.0.tbd" />
+        <framework src="CoreTelephony.framework" />
+        <framework src="SystemConfiguration.framework" />
+        <framework src="Security.framework" />
+        <framework src="CFNetwork.framework" />
+        <framework src="CoreGraphics.framework" />
+        <framework src="Webkit.framework" />
+        <framework src="libc++.1.tbd" />
+    </platform>
+
+    <!-- android -->
+    <platform name="android">
+        <hook type="after_plugin_add" src="scripts/android-install.js" />
+        <hook type="after_plugin_install" src="scripts/android-install.js" />
+        <hook type="before_plugin_rm" src="scripts/android-install.js" />
+        <hook type="before_plugin_uninstall" src="scripts/android-install.js" />
+
+        <config-file target="res/xml/config.xml" parent="/*">
+            <feature name="Wechat">
+                <param name="android-package" value="xu.li.cordova.wechat.Wechat"/>
+            </feature>
+            <preference name="WECHATAPPID" value="$WECHATAPPID"/>
+        </config-file>
+
+        <config-file target="AndroidManifest.xml" parent="/*">
+            <uses-permission android:name="android.permission.INTERNET"/>
+            <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+            <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+            <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+        </config-file>
+
+        <config-file target="AndroidManifest.xml" parent="/manifest/application">
+            <activity
+                android:name=".wxapi.WXEntryActivity"
+                android:label="@string/launcher_name"
+                android:exported="true"
+                android:taskAffinity="$PACKAGE_NAME"
+                android:launchMode="singleTask">
+                <intent-filter>
+                    <action android:name="android.intent.action.VIEW"/>
+                    <category android:name="android.intent.category.DEFAULT"/>
+                    <data android:scheme="$WECHATAPPID"/>
+                </intent-filter>
+            </activity>
+            <activity
+                android:name=".wxapi.WXPayEntryActivity"
+                android:label="@string/launcher_name"
+                android:exported="true"
+                android:launchMode="singleTop">
+                <intent-filter>
+                    <action android:name="android.intent.action.VIEW"/>
+                    <category android:name="android.intent.category.DEFAULT"/>
+                    <data android:scheme="$WECHATAPPID"/>
+                </intent-filter>
+            </activity>
+        </config-file>
+
+        <source-file src="src/android/Wechat.java" target-dir="src/xu/li/cordova/wechat" />
+        <source-file src="src/android/Util.java" target-dir="src/xu/li/cordova/wechat" />
+        <framework src="android-build.gradle" custom="true" type="gradleReference" />
+    </platform>
+</plugin>
diff --git a/plugins/cordova-plugin-wechat/scripts/android-install.js b/plugins/cordova-plugin-wechat/scripts/android-install.js
new file mode 100644 (file)
index 0000000..4653e94
--- /dev/null
@@ -0,0 +1,93 @@
+#!/usr/bin/env node
+
+module.exports = function (context) {
+    var path        = require('path'),
+        fs          = require('fs'),
+        shell       = require('shelljs'),
+        semver      = require('semver'),
+    // var path        = context.requireCordovaModule('path'),
+    //     fs          = context.requireCordovaModule('fs'),
+    //     shell       = context.requireCordovaModule('shelljs'),
+    //     semver      = context.requireCordovaModule('semver'),
+        projectRoot = context.opts.projectRoot,
+        plugins     = context.opts.plugins || [];
+
+    // The plugins array will be empty during platform add
+    if (plugins.length > 0 && plugins.indexOf('cordova-plugin-wechat') === -1) {
+        return ;
+    }
+
+    var ConfigParser = null;
+    try {
+        ConfigParser = context.requireCordovaModule('cordova-common').ConfigParser;
+    } catch(e) {
+        // fallback
+        ConfigParser = context.requireCordovaModule('cordova-lib/src/configparser/ConfigParser');
+    }
+
+    var config      = new ConfigParser(path.join(context.opts.projectRoot, "config.xml")),
+        packageName = config.android_packageName() || config.packageName();
+
+    // replace dash (-) with underscore (_)
+    packageName = packageName.replace(/-/g , "_");
+    
+    console.info("Running android-install.Hook: " + context.hook + ", Package: " + packageName + ", Path: " + projectRoot + ".");
+
+    if (!packageName) {
+        console.error("Package name could not be found!");
+        return ;
+    }
+
+    // android platform available?
+    if (context.opts.cordova.platforms.indexOf("android") === -1) {
+        console.info("Android platform has not been added.");
+        return ;
+    }
+
+    var targetDir  = path.join(projectRoot, "platforms", "android", "src", packageName.replace(/\./g, path.sep), "wxapi");
+
+       if (!fs.existsSync(targetDir)) {
+               targetDir  = path.join(projectRoot, "platforms", "android", "app", "src", "main", "java", packageName.replace(/\./g, path.sep), "wxapi");
+       } 
+
+    // var engines =  config.getEngines();
+
+    // engines.forEach(function(item,index) {
+    //     if(item.name == 'android') {
+    //         var sepc = item.spec.replace('~','').replace('^','');
+    //         console.log(sepc);
+    //         if (semver.gte(sepc,'7.0.0')) {
+    //             console.info("Android platform Version above 7.0.0");
+    //             targetDir  = path.join(projectRoot, "platforms", "android", "app", "src", "main", "java", packageName.replace(/\./g, path.sep), "wxapi");
+    //         }
+    //     }
+    // }); 
+
+    console.log(targetDir);
+
+    var targetFiles = ["EntryActivity.java", "WXEntryActivity.java", "WXPayEntryActivity.java"];
+
+    if (['after_plugin_add', 'after_plugin_install'].indexOf(context.hook) === -1) {
+        // remove it?
+        targetFiles.forEach(function (f) {
+            try {
+                fs.unlinkSync(path.join(targetDir, f));
+            } catch (err) {}
+        });
+    } else {
+        // create directory
+        shell.mkdir('-p', targetDir);
+
+        // sync the content
+        targetFiles.forEach(function (f) {
+            fs.readFile(path.join(context.opts.plugin.dir, 'src', 'android', f), {encoding: 'utf-8'}, function (err, data) {
+                if (err) {
+                    throw err;
+                }
+
+                data = data.replace(/^package __PACKAGE_NAME__;/m, 'package ' + packageName + '.wxapi;');
+                fs.writeFileSync(path.join(targetDir, f), data);
+            });
+        });
+    }
+};
diff --git a/plugins/cordova-plugin-wechat/src/android/EntryActivity.java b/plugins/cordova-plugin-wechat/src/android/EntryActivity.java
new file mode 100644 (file)
index 0000000..0be0760
--- /dev/null
@@ -0,0 +1,176 @@
+package __PACKAGE_NAME__;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.tencent.mm.opensdk.constants.ConstantsAPI;
+import com.tencent.mm.opensdk.modelbase.BaseReq;
+import com.tencent.mm.opensdk.modelbase.BaseResp;
+import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;
+import com.tencent.mm.opensdk.modelmsg.SendAuth;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
+import com.tencent.mm.opensdk.modelbiz.ChooseCardFromWXCardPackage;
+
+import org.apache.cordova.CallbackContext;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+import xu.li.cordova.wechat.Wechat;
+
+/**
+ * Created by xu.li<AthenaLightenedMyPath@gmail.com> on 9/1/15.
+ */
+public class EntryActivity extends Activity implements IWXAPIEventHandler {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        IWXAPI api = Wechat.getWxAPI(this);
+
+        if (api == null) {
+            startMainActivity();
+        } else {
+            api.handleIntent(getIntent(), this);
+        }
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+
+        setIntent(intent);
+
+        IWXAPI api = Wechat.getWxAPI(this);
+        if (api == null) {
+            startMainActivity();
+        } else {
+            api.handleIntent(intent, this);
+        }
+
+    }
+
+    @Override
+    public void onResp(BaseResp resp) {
+        Log.d(Wechat.TAG, resp.toString());
+
+        CallbackContext ctx = Wechat.getCurrentCallbackContext();
+
+        if (ctx == null) {
+            startMainActivity();
+            return ;
+        }
+
+        switch (resp.errCode) {
+            case BaseResp.ErrCode.ERR_OK:
+                switch (resp.getType()) {
+                    case ConstantsAPI.COMMAND_SENDAUTH:
+                        auth(resp);
+                        break;
+                    case ConstantsAPI.COMMAND_CHOOSE_CARD_FROM_EX_CARD_PACKAGE:
+                        plunckInvoiceData(resp);
+                        break;
+                    case ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM:
+                        Log.d(Wechat.TAG, "miniprogram back;");
+                        WXLaunchMiniProgram.Resp miniProResp = (WXLaunchMiniProgram.Resp) resp;
+                        launchMiniProResp(miniProResp);
+                        break;
+                    case ConstantsAPI.COMMAND_PAY_BY_WX:
+                    default:
+                        ctx.success();
+                        break;
+                }
+                break;
+            case BaseResp.ErrCode.ERR_USER_CANCEL:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_USER_CANCEL);
+                break;
+            case BaseResp.ErrCode.ERR_AUTH_DENIED:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_AUTH_DENIED);
+                break;
+            case BaseResp.ErrCode.ERR_SENT_FAILED:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_SENT_FAILED);
+                break;
+            case BaseResp.ErrCode.ERR_UNSUPPORT:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_UNSUPPORT);
+                break;
+            case BaseResp.ErrCode.ERR_COMM:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_COMMON);
+                break;
+            default:
+                ctx.error(Wechat.ERROR_WECHAT_RESPONSE_UNKNOWN);
+                break;
+        }
+
+        finish();
+    }
+
+    @Override
+    public void onReq(BaseReq req) {
+        finish();
+    }
+
+    protected void startMainActivity() {
+        Intent intent = new Intent();
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setPackage(getApplicationContext().getPackageName());
+        getApplicationContext().startActivity(intent);
+    }
+
+    protected void launchMiniProResp(WXLaunchMiniProgram.Resp launchMiniProResp){
+        CallbackContext ctx = Wechat.getCurrentCallbackContext();
+        String extraData =launchMiniProResp.extMsg; //对应小程序组件 <button open-type="launchApp"> 中的 app-parameter 属性
+        JSONObject response = new JSONObject();
+        try {
+            response.put("extMsg", extraData);
+        }catch (Exception e){
+            Log.e(Wechat.TAG, e.getMessage());
+        }
+        ctx.success(response);
+    }
+
+    protected void auth(BaseResp resp) {
+        SendAuth.Resp res = ((SendAuth.Resp) resp);
+
+        Log.d(Wechat.TAG, res.toString());
+
+        // get current callback context
+        CallbackContext ctx = Wechat.getCurrentCallbackContext();
+
+        if (ctx == null) {
+            return ;
+        }
+
+        JSONObject response = new JSONObject();
+        try {
+            response.put("code", res.code);
+            response.put("state", res.state);
+            response.put("country", res.country);
+            response.put("lang", res.lang);
+        } catch (JSONException e) {
+            Log.e(Wechat.TAG, e.getMessage());
+        }
+
+        ctx.success(response);
+    }
+
+    protected void plunckInvoiceData(BaseResp resp) {
+
+            CallbackContext ctx = Wechat.getCurrentCallbackContext();
+            ChooseCardFromWXCardPackage.Resp resp1 = (ChooseCardFromWXCardPackage.Resp) resp;
+            JSONObject response = new JSONObject();
+
+            try {
+                JSONArray resp2 = new JSONArray(resp1.cardItemList);
+                response.put("data", resp2);
+            } catch (JSONException e) {
+                Log.e(Wechat.TAG, e.getMessage());
+            }
+
+            ctx.success(response);
+        }
+}
\ No newline at end of file
diff --git a/plugins/cordova-plugin-wechat/src/android/Util.java b/plugins/cordova-plugin-wechat/src/android/Util.java
new file mode 100644 (file)
index 0000000..28bada2
--- /dev/null
@@ -0,0 +1,102 @@
+package xu.li.cordova.wechat;
+
+import android.content.Context;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class Util {
+
+    /**
+     * Read bytes from InputStream
+     *
+     * @link http://stackoverflow.com/questions/2436385/android-getting-from-a-uri-to-an-inputstream-to-a-byte-array
+     * @param inputStream
+     * @return
+     * @throws IOException
+     */
+    public static byte[] readBytes(InputStream inputStream) throws IOException {
+        // this dynamically extends to take the bytes you read
+        ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
+
+        // this is storage overwritten on each iteration with bytes
+        int bufferSize = 1024;
+        byte[] buffer = new byte[bufferSize];
+
+        // we need to know how may bytes were read to write them to the byteBuffer
+        int len = 0;
+        while ((len = inputStream.read(buffer)) != -1) {
+            byteBuffer.write(buffer, 0, len);
+        }
+
+        // and then we can return your byte array.
+        return byteBuffer.toByteArray();
+    }
+
+    public static File getCacheFolder(Context context) {
+        File cacheDir = null;
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            cacheDir = new File(Environment.getExternalStorageDirectory(), "cache");
+            if (!cacheDir.isDirectory()) {
+                cacheDir.mkdirs();
+            }
+        }
+
+        if(!cacheDir.isDirectory()) {
+            cacheDir = context.getCacheDir(); //get system cache folder
+        }
+
+        return cacheDir;
+    }
+
+    public static File downloadAndCacheFile(Context context, String url) {
+        URL fileURL = null;
+        try {
+            fileURL = new URL(url);
+
+            Log.d(Wechat.TAG, String.format("Start downloading file at %s.", url));
+
+            HttpURLConnection connection = (HttpURLConnection) fileURL.openConnection();
+            connection.connect();
+
+            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+                Log.e(Wechat.TAG, String.format("Failed to download file from %s, response code: %d.", url, connection.getResponseCode()));
+                return null;
+            }
+
+            InputStream inputStream = connection.getInputStream();
+
+            File cacheDir = getCacheFolder(context);
+            File cacheFile = new File(cacheDir, url.substring(url.lastIndexOf("/") + 1));
+            FileOutputStream outputStream = new FileOutputStream(cacheFile);
+
+            byte buffer[] = new byte[4096];
+            int dataSize;
+            while ((dataSize = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, dataSize);
+            }
+            outputStream.close();
+
+            Log.d(Wechat.TAG, String.format("File was downloaded and saved at %s.", cacheFile.getAbsolutePath()));
+
+            return cacheFile;
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+}
diff --git a/plugins/cordova-plugin-wechat/src/android/WXEntryActivity.java b/plugins/cordova-plugin-wechat/src/android/WXEntryActivity.java
new file mode 100644 (file)
index 0000000..d8411a4
--- /dev/null
@@ -0,0 +1,4 @@
+package __PACKAGE_NAME__;
+
+public class WXEntryActivity extends EntryActivity {
+}
diff --git a/plugins/cordova-plugin-wechat/src/android/WXPayEntryActivity.java b/plugins/cordova-plugin-wechat/src/android/WXPayEntryActivity.java
new file mode 100644 (file)
index 0000000..957f069
--- /dev/null
@@ -0,0 +1,5 @@
+package __PACKAGE_NAME__;
+
+public class WXPayEntryActivity extends EntryActivity {
+
+}
diff --git a/plugins/cordova-plugin-wechat/src/android/Wechat.java b/plugins/cordova-plugin-wechat/src/android/Wechat.java
new file mode 100644 (file)
index 0000000..291110c
--- /dev/null
@@ -0,0 +1,761 @@
+package xu.li.cordova.wechat;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Environment;
+import android.os.Build;
+import android.util.Base64;
+import android.util.Log;
+import android.webkit.URLUtil;
+
+import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;
+import com.tencent.mm.opensdk.modelmsg.SendAuth;
+import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
+import com.tencent.mm.opensdk.modelmsg.WXAppExtendObject;
+import com.tencent.mm.opensdk.modelmsg.WXEmojiObject;
+import com.tencent.mm.opensdk.modelmsg.WXFileObject;
+import com.tencent.mm.opensdk.modelmsg.WXImageObject;
+import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
+import com.tencent.mm.opensdk.modelmsg.WXMusicObject;
+import com.tencent.mm.opensdk.modelmsg.WXTextObject;
+import com.tencent.mm.opensdk.modelmsg.WXVideoObject;
+import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
+import com.tencent.mm.opensdk.modelmsg.WXMiniProgramObject;
+import com.tencent.mm.opensdk.modelpay.PayReq;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+import com.tencent.mm.opensdk.modelbiz.ChooseCardFromWXCardPackage;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.PluginResult;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import org.apache.cordova.CordovaPreferences;
+
+public class Wechat extends CordovaPlugin {
+
+    public static final String TAG = "Cordova.Plugin.Wechat";
+
+    public static final String PREFS_NAME = "Cordova.Plugin.Wechat";
+    public static final String WXAPPID_PROPERTY_KEY = "wechatappid";
+
+    public static final String ERROR_WECHAT_NOT_INSTALLED = "未安装微信";
+    public static final String ERROR_INVALID_PARAMETERS = "参数格式错误";
+    public static final String ERROR_SEND_REQUEST_FAILED = "发送请求失败";
+    public static final String ERROR_WECHAT_RESPONSE_COMMON = "普通错误";
+    public static final String ERROR_WECHAT_RESPONSE_USER_CANCEL = "用户点击取消并返回";
+    public static final String ERROR_WECHAT_RESPONSE_SENT_FAILED = "发送失败";
+    public static final String ERROR_WECHAT_RESPONSE_AUTH_DENIED = "授权失败";
+    public static final String ERROR_WECHAT_RESPONSE_UNSUPPORT = "微信不支持";
+    public static final String ERROR_WECHAT_RESPONSE_UNKNOWN = "未知错误";
+
+    public static final String EXTERNAL_STORAGE_IMAGE_PREFIX = "external://";
+    public static final int REQUEST_CODE_ENABLE_PERMISSION = 55433;
+    public static final String ANDROID_WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
+
+    public static final String KEY_ARG_MESSAGE = "message";
+    public static final String KEY_ARG_SCENE = "scene";
+    public static final String KEY_ARG_TEXT = "text";
+    public static final String KEY_ARG_MESSAGE_TITLE = "title";
+    public static final String KEY_ARG_MESSAGE_DESCRIPTION = "description";
+    public static final String KEY_ARG_MESSAGE_THUMB = "thumb";
+    public static final String KEY_ARG_MESSAGE_MEDIA = "media";
+    public static final String KEY_ARG_MESSAGE_MEDIA_TYPE = "type";
+    public static final String KEY_ARG_MESSAGE_MEDIA_WEBPAGEURL = "webpageUrl";
+    public static final String KEY_ARG_MESSAGE_MEDIA_IMAGE = "image";
+    public static final String KEY_ARG_MESSAGE_MEDIA_TEXT = "text";
+    public static final String KEY_ARG_MESSAGE_MEDIA_MUSICURL = "musicUrl";
+    public static final String KEY_ARG_MESSAGE_MEDIA_MUSICDATAURL = "musicDataUrl";
+    public static final String KEY_ARG_MESSAGE_MEDIA_VIDEOURL = "videoUrl";
+    public static final String KEY_ARG_MESSAGE_MEDIA_FILE = "file";
+    public static final String KEY_ARG_MESSAGE_MEDIA_EMOTION = "emotion";
+    public static final String KEY_ARG_MESSAGE_MEDIA_EXTINFO = "extInfo";
+    public static final String KEY_ARG_MESSAGE_MEDIA_URL = "url";
+    public static final String KEY_ARG_MESSAGE_MEDIA_USERNAME = "userName";
+    public static final String KEY_ARG_MESSAGE_MEDIA_MINIPROGRAMTYPE = "miniprogramType";
+    public static final String KEY_ARG_MESSAGE_MEDIA_MINIPROGRAM = "miniProgram";
+    public static final String KEY_ARG_MESSAGE_MEDIA_PATH = "path";
+    public static final String KEY_ARG_MESSAGE_MEDIA_WITHSHARETICKET = "withShareTicket";
+    public static final String KEY_ARG_MESSAGE_MEDIA_HDIMAGEDATA = "hdImageData";
+
+    public static final int TYPE_WECHAT_SHARING_APP = 1;
+    public static final int TYPE_WECHAT_SHARING_EMOTION = 2;
+    public static final int TYPE_WECHAT_SHARING_FILE = 3;
+    public static final int TYPE_WECHAT_SHARING_IMAGE = 4;
+    public static final int TYPE_WECHAT_SHARING_MUSIC = 5;
+    public static final int TYPE_WECHAT_SHARING_VIDEO = 6;
+    public static final int TYPE_WECHAT_SHARING_WEBPAGE = 7;
+    public static final int TYPE_WECHAT_SHARING_MINI = 8;
+
+    public static final int SCENE_SESSION = 0;
+    public static final int SCENE_TIMELINE = 1;
+    public static final int SCENE_FAVORITE = 2;
+
+    public static final int MAX_THUMBNAIL_SIZE = 320;
+
+    protected static CallbackContext currentCallbackContext;
+    protected static IWXAPI wxAPI;
+    protected static String appId;
+    protected static CordovaPreferences wx_preferences;
+
+    @Override
+    protected void pluginInitialize() {
+
+        super.pluginInitialize();
+
+        String id = getAppId(preferences);
+
+        // save app id
+        saveAppId(cordova.getActivity(), id);
+
+        // init api
+        initWXAPI();
+
+        Log.d(TAG, "plugin initialized.");
+    }
+
+    protected void initWXAPI() {
+        IWXAPI api = getWxAPI(cordova.getActivity());
+        if(wx_preferences == null) {
+            wx_preferences = preferences;
+        }
+        if (api != null) {
+            api.registerApp(getAppId(preferences));
+        }
+    }
+
+    /**
+     * Get weixin api
+     * @param ctx
+     * @return
+     */
+    public static IWXAPI getWxAPI(Context ctx) {
+        if (wxAPI == null) {
+            String appId = getSavedAppId(ctx);
+
+            if (!appId.isEmpty()) {
+                wxAPI = WXAPIFactory.createWXAPI(ctx, appId, true);
+            }
+        }
+
+        return wxAPI;
+    }
+
+    @Override
+    public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
+        Log.d(TAG, String.format("%s is called. Callback ID: %s.", action, callbackContext.getCallbackId()));
+
+        if (action.equals("share")) {
+            return share(args, callbackContext);
+        } else if (action.equals("sendAuthRequest")) {
+            return sendAuthRequest(args, callbackContext);
+        } else if (action.equals("sendPaymentRequest")) {
+            return sendPaymentRequest(args, callbackContext);
+        } else if (action.equals("isWXAppInstalled")) {
+            return isInstalled(callbackContext);
+        }else if (action.equals("chooseInvoiceFromWX")){
+            return chooseInvoiceFromWX(args, callbackContext);
+        }else if(action.equals("openMiniProgram")){
+            return openMiniProgram(args,callbackContext);
+        }
+
+        return false;
+    }
+
+    protected boolean share(CordovaArgs args, final CallbackContext callbackContext)
+            throws JSONException {
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        // check if installed
+        if (!api.isWXAppInstalled()) {
+            callbackContext.error(ERROR_WECHAT_NOT_INSTALLED);
+            return true;
+        }
+
+        // check if # of arguments is correct
+        final JSONObject params;
+        try {
+            params = args.getJSONObject(0);
+        } catch (JSONException e) {
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        final SendMessageToWX.Req req = new SendMessageToWX.Req();
+        req.transaction = buildTransaction();
+
+        if (params.has(KEY_ARG_MESSAGE)) {
+            //小程序卡片单独构建
+            JSONObject message = params.getJSONObject(KEY_ARG_MESSAGE);
+            if (message.has(KEY_ARG_MESSAGE_MEDIA)) {
+                JSONObject media = message.getJSONObject(KEY_ARG_MESSAGE_MEDIA);
+                int type = media.has(KEY_ARG_MESSAGE_MEDIA_TYPE) ? media
+                        .getInt(KEY_ARG_MESSAGE_MEDIA_TYPE) : TYPE_WECHAT_SHARING_MINI;
+                if (type == TYPE_WECHAT_SHARING_MINI) {
+                    req.transaction = buildTransaction(KEY_ARG_MESSAGE_MEDIA_MINIPROGRAM);
+                }
+            }
+        }
+
+        if (params.has(KEY_ARG_SCENE)) {
+            switch (params.getInt(KEY_ARG_SCENE)) {
+                case SCENE_FAVORITE:
+                    req.scene = SendMessageToWX.Req.WXSceneFavorite;
+                    break;
+                case SCENE_TIMELINE:
+                    req.scene = SendMessageToWX.Req.WXSceneTimeline;
+                    break;
+                case SCENE_SESSION:
+                    req.scene = SendMessageToWX.Req.WXSceneSession;
+                    break;
+                default:
+                    req.scene = SendMessageToWX.Req.WXSceneTimeline;
+            }
+        } else {
+            req.scene = SendMessageToWX.Req.WXSceneTimeline;
+        }
+
+        // run in background
+        cordova.getThreadPool().execute(new Runnable() {
+
+            @Override
+            public void run() {
+                try {
+                    req.message = buildSharingMessage(params);
+                } catch (JSONException e) {
+                    Log.e(TAG, "Failed to build sharing message.", e);
+
+                    // clear callback context
+                    currentCallbackContext = null;
+
+                    // send json exception error
+                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                }
+
+                if (api.sendReq(req)) {
+                    Log.i(TAG, "Message has been sent successfully.");
+                } else {
+                    Log.i(TAG, "Message has been sent unsuccessfully.");
+
+                    // clear callback context
+                    currentCallbackContext = null;
+
+                    // send error
+                    callbackContext.error(ERROR_SEND_REQUEST_FAILED);
+                }
+            }
+        });
+
+        // send no result
+        sendNoResultPluginResult(callbackContext);
+
+        return true;
+    }
+
+    protected boolean sendAuthRequest(CordovaArgs args, CallbackContext callbackContext) {
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        final SendAuth.Req req = new SendAuth.Req();
+        try {
+            req.scope = args.getString(0);
+            req.state = args.getString(1);
+        } catch (JSONException e) {
+            Log.e(TAG, e.getMessage());
+
+            req.scope = "snsapi_userinfo";
+            req.state = "wechat";
+        }
+
+        if (api.sendReq(req)) {
+            Log.i(TAG, "Auth request has been sent successfully.");
+
+            // send no result
+            sendNoResultPluginResult(callbackContext);
+        } else {
+            Log.i(TAG, "Auth request has been sent unsuccessfully.");
+
+            // send error
+            callbackContext.error(ERROR_SEND_REQUEST_FAILED);
+        }
+
+        return true;
+    }
+
+    protected boolean sendPaymentRequest(CordovaArgs args, CallbackContext callbackContext) {
+
+        // check if # of arguments is correct
+        final JSONObject params;
+        try {
+            params = args.getJSONObject(0);
+        } catch (JSONException e) {
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        PayReq req = new PayReq();
+
+        try {
+            // final String appid = params.getString("appid");
+            // final String savedAppid = getSavedAppId(cordova.getActivity());
+            // if (!savedAppid.equals(appid)) {
+            //     this.saveAppId(cordova.getActivity(), appid);
+            // }
+            req.appId = getAppId(preferences);
+            req.partnerId = params.has("mch_id") ? params.getString("mch_id") : params.getString("partnerid");
+            req.prepayId = params.has("prepay_id") ? params.getString("prepay_id") : params.getString("prepayid");
+            req.nonceStr = params.has("nonce") ? params.getString("nonce") : params.getString("noncestr");
+            req.timeStamp = params.getString("timestamp");
+            req.sign = params.getString("sign");
+            req.packageValue = "Sign=WXPay";
+        } catch (Exception e) {
+            Log.e(TAG, e.getMessage());
+
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        if (api.sendReq(req)) {
+            Log.i(TAG, "Payment request has been sent successfully.");
+
+            // send no result
+            sendNoResultPluginResult(callbackContext);
+        } else {
+            Log.i(TAG, "Payment request has been sent unsuccessfully.");
+
+            // send error
+            callbackContext.error(ERROR_SEND_REQUEST_FAILED);
+        }
+
+        return true;
+    }
+
+    protected boolean chooseInvoiceFromWX(CordovaArgs args, CallbackContext callbackContext) {
+
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        // check if # of arguments is correct
+        final JSONObject params;
+        try {
+            params = args.getJSONObject(0);
+        } catch (JSONException e) {
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        ChooseCardFromWXCardPackage.Req req = new ChooseCardFromWXCardPackage.Req();
+
+        try {
+            req.appId = getAppId(preferences);
+            req.cardType = "INVOICE";
+            req.signType = params.getString("signType");
+            req.cardSign = params.getString("cardSign");
+            req.nonceStr = params.getString("nonceStr");
+            req.timeStamp = params.getString("timeStamp");
+            req.canMultiSelect = "1";
+        } catch (Exception e) {
+            Log.e(TAG, e.getMessage());
+
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        if (api.sendReq(req)) {
+            Log.i(TAG, "Invoice request has been sent successfully.");
+
+            // send no result
+            sendNoResultPluginResult(callbackContext);
+        } else {
+            Log.i(TAG, "Invoice request has been sent unsuccessfully.");
+
+            // send error
+            callbackContext.error(ERROR_SEND_REQUEST_FAILED);
+        }
+
+        return true;
+    }
+
+    protected boolean isInstalled(CallbackContext callbackContext) {
+        final IWXAPI api = getWxAPI(cordova.getActivity());
+
+        if (!api.isWXAppInstalled()) {
+            callbackContext.success(0);
+        } else {
+            callbackContext.success(1);
+        }
+
+        return true;
+    }
+
+
+    protected WXMediaMessage buildSharingMessage(JSONObject params)
+            throws JSONException {
+        Log.d(TAG, "Start building message.");
+
+        // media parameters
+        WXMediaMessage.IMediaObject mediaObject = null;
+        WXMediaMessage wxMediaMessage = new WXMediaMessage();
+
+        if (params.has(KEY_ARG_TEXT)) {
+            WXTextObject textObject = new WXTextObject();
+            textObject.text = params.getString(KEY_ARG_TEXT);
+            mediaObject = textObject;
+            wxMediaMessage.description = textObject.text;
+        } else {
+            JSONObject message = params.getJSONObject(KEY_ARG_MESSAGE);
+            JSONObject media = message.getJSONObject(KEY_ARG_MESSAGE_MEDIA);
+
+            wxMediaMessage.title = message.getString(KEY_ARG_MESSAGE_TITLE);
+            wxMediaMessage.description = message.getString(KEY_ARG_MESSAGE_DESCRIPTION);
+
+            // thumbnail
+            Bitmap thumbnail = getThumbnail(message, KEY_ARG_MESSAGE_THUMB);
+            if (thumbnail != null) {
+                wxMediaMessage.setThumbImage(thumbnail);
+                thumbnail.recycle();
+            }
+
+            // check types
+            int type = media.has(KEY_ARG_MESSAGE_MEDIA_TYPE) ? media
+                    .getInt(KEY_ARG_MESSAGE_MEDIA_TYPE) : TYPE_WECHAT_SHARING_WEBPAGE;
+
+            switch (type) {
+                case TYPE_WECHAT_SHARING_APP:
+                    WXAppExtendObject appObject = new WXAppExtendObject();
+                    appObject.extInfo = media.getString(KEY_ARG_MESSAGE_MEDIA_EXTINFO);
+                    appObject.filePath = media.getString(KEY_ARG_MESSAGE_MEDIA_URL);
+                    mediaObject = appObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_EMOTION:
+                    WXEmojiObject emoObject = new WXEmojiObject();
+                    InputStream emoji = getFileInputStream(media.getString(KEY_ARG_MESSAGE_MEDIA_EMOTION));
+                    if (emoji != null) {
+                        try {
+                            emoObject.emojiData = Util.readBytes(emoji);
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                    mediaObject = emoObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_FILE:
+                    WXFileObject fileObject = new WXFileObject();
+                    InputStream file = getFileInputStream(media.getString(KEY_ARG_MESSAGE_MEDIA_FILE));
+                    if (file != null) {
+                        try {
+                            fileObject.fileData = Util.readBytes(file);
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                    mediaObject = fileObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_IMAGE:
+                    Bitmap image = getBitmap(message.getJSONObject(KEY_ARG_MESSAGE_MEDIA), KEY_ARG_MESSAGE_MEDIA_IMAGE, 0);
+                    // give some tips to user           
+                    if(image != null) {
+                        mediaObject = new WXImageObject(image);
+                        image.recycle();
+                    }
+                    break;
+
+                case TYPE_WECHAT_SHARING_MUSIC:
+                    WXMusicObject musicObject = new WXMusicObject();
+                    musicObject.musicUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_MUSICURL);
+                    musicObject.musicDataUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_MUSICDATAURL);
+                    mediaObject = musicObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_VIDEO:
+                    WXVideoObject videoObject = new WXVideoObject();
+                    videoObject.videoUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_VIDEOURL);
+                    mediaObject = videoObject;
+                    break;
+
+                case TYPE_WECHAT_SHARING_MINI:
+                    WXMiniProgramObject miniProgramObj = new WXMiniProgramObject();
+                    try {
+                        miniProgramObj.webpageUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_WEBPAGEURL); // 兼容低版本的网页链接
+                        miniProgramObj.miniprogramType = media.getInt(KEY_ARG_MESSAGE_MEDIA_MINIPROGRAMTYPE);// 正式版:0,测试版:1,体验版:2
+                        miniProgramObj.userName = media.getString(KEY_ARG_MESSAGE_MEDIA_USERNAME);     // 小程序原始id
+                        miniProgramObj.path = media.getString(KEY_ARG_MESSAGE_MEDIA_PATH);            //小程序页面路径
+                        miniProgramObj.withShareTicket = media.getBoolean(KEY_ARG_MESSAGE_MEDIA_WITHSHARETICKET); // 是否使用带shareTicket的分享
+                        wxMediaMessage = new WXMediaMessage(miniProgramObj);
+                        wxMediaMessage.title = message.getString(KEY_ARG_MESSAGE_TITLE);                    // 小程序消息title
+                        wxMediaMessage.description = message.getString(KEY_ARG_MESSAGE_DESCRIPTION);               // 小程序消息desc
+                        wxMediaMessage.thumbData = Util.readBytes(getFileInputStream(media.getString(KEY_ARG_MESSAGE_MEDIA_HDIMAGEDATA))); // 小程序消息封面图片,小于128k
+                        return wxMediaMessage;
+                    }catch (Exception e){
+                        Log.e(TAG, e.getMessage());
+                    }
+                    break;
+
+                case TYPE_WECHAT_SHARING_WEBPAGE:
+                default:
+                    mediaObject = new WXWebpageObject(media.getString(KEY_ARG_MESSAGE_MEDIA_WEBPAGEURL));
+            }
+        }
+
+        wxMediaMessage.mediaObject = mediaObject;
+
+        return wxMediaMessage;
+    }
+
+    private String buildTransaction() {
+        return String.valueOf(System.currentTimeMillis());
+    }
+
+    private String buildTransaction(final String type) {
+        return type + System.currentTimeMillis();
+    }
+
+    protected Bitmap getThumbnail(JSONObject message, String key) {
+        return getBitmap(message, key, MAX_THUMBNAIL_SIZE);
+    }
+
+    protected Bitmap getBitmap(JSONObject message, String key, int maxSize) {
+        Bitmap bmp = null;
+        String url = null;
+
+        try {
+            if (!message.has(key)) {
+                return null;
+            }
+
+            url = message.getString(key);
+
+            // get input stream
+            InputStream inputStream = getFileInputStream(url);
+            if (inputStream == null) {
+                return null;
+            }
+
+            // decode it
+            // @TODO make sure the image is not too big, or it will cause out of memory
+            BitmapFactory.Options options = new BitmapFactory.Options();
+            bmp = BitmapFactory.decodeStream(inputStream, null, options);
+
+            // scale
+            if (maxSize > 0 && (options.outWidth > maxSize || options.outHeight > maxSize)) {
+
+                Log.d(TAG, String.format("Bitmap was decoded, dimension: %d x %d, max allowed size: %d.",
+                        options.outWidth, options.outHeight, maxSize));
+
+                int width = 0;
+                int height = 0;
+
+                if (options.outWidth > options.outHeight) {
+                    width = maxSize;
+                    height = width * options.outHeight / options.outWidth;
+                } else {
+                    height = maxSize;
+                    width = height * options.outWidth / options.outHeight;
+                }
+
+                Bitmap scaled = Bitmap.createScaledBitmap(bmp, width, height, true);
+                bmp.recycle();
+
+                int length = scaled.getRowBytes() * scaled.getHeight();
+
+                if(length > (maxSize/10)*1024) {
+                    scaled = compressImage(scaled,(maxSize/10));
+                }
+
+                bmp = scaled;
+            }
+
+            inputStream.close();
+
+        } catch (JSONException e) {
+            bmp = null;
+            e.printStackTrace();
+        } catch (IOException e) {
+            bmp = null;
+            e.printStackTrace();
+        }
+
+        return bmp;
+    }
+
+
+    /**
+     * compress bitmap by quility
+     */
+    protected  Bitmap compressImage(Bitmap image,Integer maxSize) {
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
+        int options = 90;
+
+        while (baos.toByteArray().length / 1024 > maxSize) {
+            baos.reset();
+            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
+            options -= 10;
+        }
+        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
+        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
+        return bitmap;
+    }
+
+    /**
+     * Get input stream from a url
+     */
+    protected InputStream getFileInputStream(String url) {
+        InputStream inputStream = null;
+        try {
+
+            if (URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)) {
+
+                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
+                    if (!cordova.hasPermission(ANDROID_WRITE_EXTERNAL_STORAGE)) {
+                        cordova.requestPermission(this, REQUEST_CODE_ENABLE_PERMISSION, ANDROID_WRITE_EXTERNAL_STORAGE);
+                    }
+                }
+
+                File file = Util.downloadAndCacheFile(webView.getContext(), url);
+
+                if (file == null) {
+                    Log.d(TAG, String.format("File could not be downloaded from %s.", url));
+                    return null;
+                }
+
+                // url = file.getAbsolutePath();
+                inputStream = new FileInputStream(file);
+
+                Log.d(TAG, String.format("File was downloaded and cached to %s.", file.getAbsolutePath()));
+
+            } else if (url.startsWith("data:image")) {  // base64 image
+
+                String imageDataBytes = url.substring(url.indexOf(",") + 1);
+                byte imageBytes[] = Base64.decode(imageDataBytes.getBytes(), Base64.DEFAULT);
+                inputStream = new ByteArrayInputStream(imageBytes);
+
+                Log.d(TAG, "Image is in base64 format.");
+
+            } else if (url.startsWith(EXTERNAL_STORAGE_IMAGE_PREFIX)) { // external path
+
+                url = Environment.getExternalStorageDirectory().getAbsolutePath() + url.substring(EXTERNAL_STORAGE_IMAGE_PREFIX.length());
+                inputStream = new FileInputStream(url);
+
+                Log.d(TAG, String.format("File is located on external storage at %s.", url));
+
+            } else if (!url.startsWith("/")) { // relative path
+
+                inputStream = cordova.getActivity().getApplicationContext().getAssets().open(url);
+
+                Log.d(TAG, String.format("File is located in assets folder at %s.", url));
+
+            } else {
+
+                inputStream = new FileInputStream(url);
+
+                Log.d(TAG, String.format("File is located at %s.", url));
+
+            }
+
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return inputStream;
+    }
+
+    public static String getAppId(CordovaPreferences f_preferences) {
+        if (appId == null) {
+            if(f_preferences != null) {
+                appId = f_preferences.getString(WXAPPID_PROPERTY_KEY, "");
+            }else if(wx_preferences != null){
+                appId = wx_preferences.getString(WXAPPID_PROPERTY_KEY, "");
+            }
+        }
+
+        return appId;
+    }
+
+    /**
+     * Get saved app id
+     * @param ctx
+     * @return
+     */
+    public static String getSavedAppId(Context ctx) {
+        SharedPreferences settings = ctx.getSharedPreferences(PREFS_NAME, 0);
+        return settings.getString(WXAPPID_PROPERTY_KEY, "");
+    }
+
+    /**
+     * Save app id into SharedPreferences
+     * @param ctx
+     * @param id
+     */
+    public static void saveAppId(Context ctx, String id) {
+        if (id!=null && id.isEmpty()) {
+            return ;
+        }
+
+        SharedPreferences settings = ctx.getSharedPreferences(PREFS_NAME, 0);
+        SharedPreferences.Editor editor = settings.edit();
+        editor.putString(WXAPPID_PROPERTY_KEY, id);
+        editor.commit();
+    }
+
+    public static CallbackContext getCurrentCallbackContext() {
+        return currentCallbackContext;
+    }
+
+    private void sendNoResultPluginResult(CallbackContext callbackContext) {
+        // save current callback context
+        currentCallbackContext = callbackContext;
+
+        // send no result and keep callback
+        PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+        result.setKeepCallback(true);
+        callbackContext.sendPluginResult(result);
+    }
+
+    protected boolean openMiniProgram(CordovaArgs args, CallbackContext callbackContext){
+        currentCallbackContext = callbackContext;
+        String appId = getAppId(preferences);; // 填应用AppId
+        IWXAPI api = WXAPIFactory.createWXAPI(cordova.getActivity(), appId);
+
+        final JSONObject params;
+        try {
+            params = args.getJSONObject(0);
+        } catch (JSONException e) {
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            return true;
+        }
+
+        WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req();
+        try {
+            req.userName = params.getString(KEY_ARG_MESSAGE_MEDIA_USERNAME); // 填小程序原始id
+            req.path = params.getString(KEY_ARG_MESSAGE_MEDIA_PATH);                  //拉起小程序页面的可带参路径,不填默认拉起小程序首页
+            req.miniprogramType = params.getInt(KEY_ARG_MESSAGE_MEDIA_MINIPROGRAMTYPE);// 可选打开 开发版,体验版和正式版
+            api.sendReq(req);
+        }catch (Exception e){
+            callbackContext.error(ERROR_INVALID_PARAMETERS);
+            Log.e(TAG,e.getMessage());
+        }
+        return true;
+    }
+
+}
diff --git a/plugins/cordova-plugin-wechat/src/ios/AppDelegate+Wechat.h b/plugins/cordova-plugin-wechat/src/ios/AppDelegate+Wechat.h
new file mode 100644 (file)
index 0000000..5a5b092
--- /dev/null
@@ -0,0 +1,16 @@
+//
+//  AppDelegate+Wechat.h
+//  cordova-plugin-wechat
+//
+//  Created by Jason.z on 26/2/20.
+//
+//
+
+#import "AppDelegate.h"
+
+@interface AppDelegate (Wechat)
+
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
+- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler;
+
+@end
diff --git a/plugins/cordova-plugin-wechat/src/ios/AppDelegate+Wechat.m b/plugins/cordova-plugin-wechat/src/ios/AppDelegate+Wechat.m
new file mode 100644 (file)
index 0000000..c6ecda4
--- /dev/null
@@ -0,0 +1,57 @@
+//
+//  AppDelegate+Wechat.h
+//  cordova-plugin-wechat
+//
+//  Created by Jason.z on 26/2/20.
+//
+//
+
+#import "AppDelegate+Wechat.h"
+#import "CDVWechat.h"
+
+#import <objc/runtime.h>
+
+@implementation AppDelegate (Wechat)
+
+static BOOL swizzled = NO;
+
++ (void)load {
+    // only need to worry about this in iOS 8 and later
+    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
+    if ([processInfo respondsToSelector:@selector(operatingSystemVersion)]) {
+        //operatingSystemVersion was introduced in iOS 8
+        Method swizzlee = class_getInstanceMethod(self, @selector(application:continueUserActivity:restorationHandler:));
+        Method swizzler = class_getInstanceMethod(self, @selector(swizzleApplication:continueUserActivity:restorationHandler:));
+        
+        if (swizzlee) {
+            method_exchangeImplementations(swizzlee, swizzler);
+            swizzled = YES;
+        } else {
+            // app delegate has not implemented optional protocol method. add it in with our implementation
+            const char *typeEncoding = method_getTypeEncoding(swizzler);
+            class_addMethod(self, @selector(application:continueUserActivity:restorationHandler:), method_getImplementation(swizzler), typeEncoding);
+        }
+    }
+}
+
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
+    CDVWechat *cdvWechat = [self.viewController getCommandInstance:@"wechat"];
+    return [cdvWechat handleWechatOpenURL:url];
+}
+
+- (BOOL)swizzleApplication:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
+    if (![userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
+        if (swizzled) {
+            return [self swizzleApplication:application continueUserActivity:userActivity restorationHandler:restorationHandler];
+        }
+        
+        return NO;
+    }
+    
+    CDVWechat *cdvWechat = [self.viewController getCommandInstance:@"wechat"];
+    
+    return [cdvWechat handleUserActivity:userActivity];
+
+}
+
+@end
diff --git a/plugins/cordova-plugin-wechat/src/ios/CDVWechat.h b/plugins/cordova-plugin-wechat/src/ios/CDVWechat.h
new file mode 100644 (file)
index 0000000..8d4ae16
--- /dev/null
@@ -0,0 +1,39 @@
+//
+//  CDVWechat.h
+//  cordova-plugin-wechat
+//
+//  Created by xu.li on 12/23/13.
+//
+//
+
+#import <Cordova/CDV.h>
+#import "WXApi.h"
+#import "WXApiObject.h"
+
+enum  CDVWechatSharingType {
+    CDVWXSharingTypeApp = 1,
+    CDVWXSharingTypeEmotion,
+    CDVWXSharingTypeFile,
+    CDVWXSharingTypeImage,
+    CDVWXSharingTypeMusic,
+    CDVWXSharingTypeVideo,
+    CDVWXSharingTypeWebPage,
+    CDVWXSharingTypeMini
+};
+
+@interface CDVWechat:CDVPlugin <WXApiDelegate>
+
+@property (nonatomic, strong) NSString *currentCallbackId;
+@property (nonatomic, strong) NSString *wechatAppId;
+
+- (void)isWXAppInstalled:(CDVInvokedUrlCommand *)command;
+- (void)share:(CDVInvokedUrlCommand *)command;
+- (void)sendAuthRequest:(CDVInvokedUrlCommand *)command;
+- (void)sendPaymentRequest:(CDVInvokedUrlCommand *)command;
+- (void)jumpToBizProfile:(CDVInvokedUrlCommand *)command;
+- (void)jumpToWechat:(CDVInvokedUrlCommand *)command;
+- (void)chooseInvoiceFromWX: (CDVInvokedUrlCommand *)command;
+- (void)openMiniProgram: (CDVInvokedUrlCommand *)command;
+- (BOOL)handleUserActivity:(NSUserActivity *)userActivity;
+- (BOOL)handleWechatOpenURL:(NSURL *)url;
+@end
diff --git a/plugins/cordova-plugin-wechat/src/ios/CDVWechat.m b/plugins/cordova-plugin-wechat/src/ios/CDVWechat.m
new file mode 100644 (file)
index 0000000..4f7b424
--- /dev/null
@@ -0,0 +1,575 @@
+//
+//  CDVWechat.m
+//  cordova-plugin-wechat
+//
+//  Created by xu.li on 12/23/13.
+//
+//
+
+#import "CDVWechat.h"
+
+static int const MAX_THUMBNAIL_SIZE = 320;
+
+@implementation CDVWechat
+
+#pragma mark "API"
+- (void)pluginInitialize {
+    NSString* appId = [[self.commandDelegate settings] objectForKey:@"wechatappid"];
+    
+    NSString* universalLink = [[self.commandDelegate settings] objectForKey:@"universallink"];
+    
+    if (appId && ![appId isEqualToString:self.wechatAppId]) {
+        self.wechatAppId = appId;
+        [WXApi registerApp: appId universalLink: universalLink];
+        
+        NSLog(@"cordova-plugin-wechat has been initialized. Wechat SDK Version: %@. APP_ID: %@.", [WXApi getApiVersion], appId);
+    }
+}
+
+- (void)isWXAppInstalled:(CDVInvokedUrlCommand *)command
+{
+    CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:[WXApi isWXAppInstalled]];
+
+    [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId];
+}
+
+- (void)share:(CDVInvokedUrlCommand *)command
+{
+    // if not installed
+    if (![WXApi isWXAppInstalled])
+    {
+        [self failWithCallbackID:command.callbackId withMessage:@"未安装微信"];
+        return ;
+    }
+
+    // check arguments
+    NSDictionary *params = [command.arguments objectAtIndex:0];
+    if (!params)
+    {
+        [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+        return ;
+    }
+
+    // save the callback id
+    self.currentCallbackId = command.callbackId;
+
+    SendMessageToWXReq* req = [[SendMessageToWXReq alloc] init];
+
+    // check the scene
+    if ([params objectForKey:@"scene"])
+    {
+        req.scene = (int)[[params objectForKey:@"scene"] integerValue];
+    }
+    else
+    {
+        req.scene = WXSceneTimeline;
+    }
+
+    // message or text?
+    NSDictionary *message = [params objectForKey:@"message"];
+
+    if (message)
+    {
+        req.bText = NO;
+
+        // async
+        [self.commandDelegate runInBackground:^{
+            req.message = [self buildSharingMessage:message];
+            
+            [WXApi sendReq:(BaseReq *)req completion:^(BOOL success) {
+                if (!success) {
+                    [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+                                   self.currentCallbackId = nil;
+                }
+            }];
+        }];
+    }
+    else
+    {
+        req.bText = YES;
+        req.text = [params objectForKey:@"text"];
+
+        [WXApi sendReq:(BaseReq *)req completion:^(BOOL success) {
+            if (!success) {
+                [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+                               self.currentCallbackId = nil;
+            }
+        }];
+    }
+}
+
+- (void)sendAuthRequest:(CDVInvokedUrlCommand *)command
+{
+
+    SendAuthReq* req =[[SendAuthReq alloc] init];
+
+    // scope
+    if ([command.arguments count] > 0)
+    {
+        req.scope = [command.arguments objectAtIndex:0];
+    }
+    else
+    {
+        req.scope = @"snsapi_userinfo";
+    }
+
+    // state
+    if ([command.arguments count] > 1)
+    {
+        req.state = [command.arguments objectAtIndex:1];
+    }
+
+    [WXApi sendAuthReq:req viewController:self.viewController delegate:self completion:^(BOOL success) {
+        if(success) {
+            self.currentCallbackId = command.callbackId;
+        } else {
+            [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+        }
+    }];
+}
+
+- (void)sendPaymentRequest:(CDVInvokedUrlCommand *)command
+{
+    // check arguments
+    NSDictionary *params = [command.arguments objectAtIndex:0];
+    if (!params)
+    {
+        [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+        return ;
+    }
+
+    // check required parameters
+    NSArray *requiredParams;
+    if ([params objectForKey:@"mch_id"])
+    {
+        requiredParams = @[@"mch_id", @"prepay_id", @"timestamp", @"nonce", @"sign"];
+    }
+    else
+    {
+        requiredParams = @[@"partnerid", @"prepayid", @"timestamp", @"noncestr", @"sign"];
+    }
+
+    for (NSString *key in requiredParams)
+    {
+        if (![params objectForKey:key])
+        {
+            [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+            return ;
+        }
+    }
+
+    PayReq *req = [[PayReq alloc] init];
+
+    // NSString *appId = [params objectForKey:requiredParams[5]];
+    // if (appId && ![appId isEqualToString:self.wechatAppId]) {
+    //     self.wechatAppId = appId;
+    //     [WXApi registerApp: appId];
+    // }
+
+    req.partnerId = [params objectForKey:requiredParams[0]];
+    req.prepayId = [params objectForKey:requiredParams[1]];
+    req.timeStamp = [[params objectForKey:requiredParams[2]] intValue];
+    req.nonceStr = [params objectForKey:requiredParams[3]];
+    req.package = @"Sign=WXPay";
+    req.sign = [params objectForKey:requiredParams[4]];
+    
+    [WXApi sendReq:(BaseReq *)req completion:^(BOOL success) {
+       if (success) {
+           self.currentCallbackId = command.callbackId;
+       } else {
+           [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+       }
+    }];
+}
+
+- (void)chooseInvoiceFromWX:(CDVInvokedUrlCommand *)command
+{
+    NSDictionary *params = [command.arguments objectAtIndex:0];
+    WXChooseInvoiceReq *req = [[WXChooseInvoiceReq alloc] init];
+    req.cardSign = [params objectForKey:@"cardSign"];
+    req.timeStamp = [[params objectForKey:@"timeStamp"] intValue];
+    req.appID = [params objectForKey:@"appId"];
+    req.nonceStr = [params objectForKey:@"nonceStr"];
+    req.signType = [params objectForKey:@"signType"];
+    
+    [WXApi sendReq:(BaseReq *)req completion:^(BOOL success) {
+        if (success) {
+            self.currentCallbackId = command.callbackId;
+        } else {
+            [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+        }
+    }];
+}
+
+- (void)jumpToBizProfile:(CDVInvokedUrlCommand *)command
+{
+    // check arguments
+//    NSDictionary *params = [command.arguments objectAtIndex:0];
+//    if (!params)
+//    {
+//        [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+//        return ;
+//    }
+//
+//    // check required parameters
+//    NSArray *requiredParams;
+//    requiredParams = @[@"type", @"info"];
+//
+//    for (NSString *key in requiredParams)
+//    {
+//        if (![params objectForKey:key])
+//        {
+//            [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+//            return ;
+//        }
+//    }
+//    JumpToBizProfileReq *req = [JumpToBizProfileReq new];
+//    NSString *bizType =  [params objectForKey:requiredParams[0]];
+//
+//    if ([bizType isEqualToString:@"Normal"]) {
+//        req.profileType = WXBizProfileType_Normal;
+//        req.username = [params objectForKey:requiredParams[1]];
+//    } else {
+//        req.profileType = WXBizProfileType_Device;
+//        req.extMsg = [params objectForKey:requiredParams[1]];
+//    }
+//
+//    if ([WXApi sendReq:req])
+//    {
+//        // save the callback id
+//        self.currentCallbackId = command.callbackId;
+//    }
+//    else
+//    {
+//        [self failWithCallbackID:command.callbackId withMessage:@"发送请求失败"];
+//    }
+}
+
+- (void)jumpToWechat:(CDVInvokedUrlCommand *)command
+{
+    // check arguments
+    NSString *url = [command.arguments objectAtIndex:0];
+    if (!url || ![url hasPrefix:@"weixin://"])
+    {
+        [self failWithCallbackID:command.callbackId withMessage:@"参数格式错误"];
+        return ;
+    }
+
+    NSURL *formatUrl = [NSURL URLWithString:[url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
+    if ([[UIApplication sharedApplication] canOpenURL:formatUrl]) {
+        NSDictionary *options = @{UIApplicationOpenURLOptionUniversalLinksOnly : @YES};
+        [[UIApplication sharedApplication] openURL:formatUrl options:options completionHandler:nil];
+    } else{
+        [self failWithCallbackID:command.callbackId withMessage:@"未安装微信或其他错误"];
+    }
+    return ;
+}
+
+
+
+#pragma mark "WXApiDelegate"
+
+/**
+ * Not implemented
+ */
+- (void)onReq:(BaseReq *)req
+{
+    NSLog(@"%@", req);
+}
+
+- (void)onResp:(WXLaunchMiniProgramResp *)resp
+{
+    BOOL success = NO;
+    NSString *message = @"Unknown";
+    NSDictionary *response = nil;
+
+    switch (resp.errCode)
+    {
+        case WXSuccess:
+            success = YES;
+            break;
+
+        case WXErrCodeCommon:
+            message = @"普通错误";
+            break;
+
+        case WXErrCodeUserCancel:
+            message = @"用户点击取消并返回";
+            break;
+
+        case WXErrCodeSentFail:
+            message = @"发送失败";
+            break;
+
+        case WXErrCodeAuthDeny:
+            message = @"授权失败";
+            break;
+
+        case WXErrCodeUnsupport:
+            message = @"微信不支持";
+            break;
+
+        default:
+            message = @"未知错误";
+    }
+
+    if (success)
+    {
+        if ([resp isKindOfClass:[SendAuthResp class]])
+        {
+            // fix issue that lang and country could be nil for iPhone 6 which caused crash.
+            SendAuthResp* authResp = (SendAuthResp*)resp;
+            response = @{
+                         @"code": authResp.code != nil ? authResp.code : @"",
+                         @"state": authResp.state != nil ? authResp.state : @"",
+                         @"lang": authResp.lang != nil ? authResp.lang : @"",
+                         @"country": authResp.country != nil ? authResp.country : @"",
+                         };
+
+            CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:response];
+
+            [self.commandDelegate sendPluginResult:commandResult callbackId:self.currentCallbackId];
+        }
+        else if([resp isKindOfClass:[WXChooseInvoiceResp class]]){
+                    WXChooseInvoiceResp* invoiceResp = (WXChooseInvoiceResp *)resp;
+
+        //            response = @{
+        //                         @"data":invoiceResp.cardAry
+        //                         }
+                    NSMutableArray *arrM = [[NSMutableArray alloc] init];
+                    NSDictionary *mutableDic = nil;
+                    for(WXInvoiceItem *invoiceItem in invoiceResp.cardAry){
+                        mutableDic = @{
+                                       @"cardId": invoiceItem.cardId,
+                                       @"encryptCode": invoiceItem.encryptCode,
+                                       };
+                        [arrM addObject:mutableDic];
+                    }
+                    response = @{
+                                 @"data": arrM
+                                 };
+                    NSLog(@"response======= %@", response);
+                    CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:response];
+                    [self.commandDelegate sendPluginResult:commandResult callbackId:self.currentCallbackId];
+                }
+        else if ([resp isKindOfClass:[WXLaunchMiniProgramResp class]])
+        {
+            NSString *extMsg = resp.extMsg;
+            response = @{
+                         @"extMsg": extMsg
+                         };
+            CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:response];
+            [self.commandDelegate sendPluginResult:commandResult callbackId:self.currentCallbackId];
+        }
+        else
+        {
+            [self successWithCallbackID:self.currentCallbackId];
+        }
+    }
+    else
+    {
+        [self failWithCallbackID:self.currentCallbackId withMessage:message];
+    }
+
+    [self pluginInitialize];
+    self.currentCallbackId = nil;
+}
+
+#pragma mark "CDVPlugin Overrides"
+
+- (void)handleOpenURL:(NSNotification *)notification
+{
+    NSURL* url = [notification object];
+
+    if ([url isKindOfClass:[NSURL class]] && [url.scheme isEqualToString:self.wechatAppId])
+    {
+        [WXApi handleOpenURL:url delegate:self];
+    }
+}
+
+#pragma mark "Private methods"
+
+- (WXMediaMessage *)buildSharingMessage:(NSDictionary *)message
+{
+    WXMediaMessage *wxMediaMessage = [WXMediaMessage message];
+    wxMediaMessage.title = [message objectForKey:@"title"];
+    wxMediaMessage.description = [message objectForKey:@"description"];
+    wxMediaMessage.mediaTagName = [message objectForKey:@"mediaTagName"];
+    wxMediaMessage.messageExt = [message objectForKey:@"messageExt"];
+    wxMediaMessage.messageAction = [message objectForKey:@"messageAction"];
+    if ([message objectForKey:@"thumb"])
+    {
+        [wxMediaMessage setThumbImage:[self getUIImageFromURL:[message objectForKey:@"thumb"]]];
+    }
+
+    // media parameters
+    id mediaObject = nil;
+    WXMiniProgramObject *object;
+    NSDictionary *media = [message objectForKey:@"media"];
+    // check types
+    NSInteger type = [[media objectForKey:@"type"] integerValue];
+    switch (type)
+    {
+        case CDVWXSharingTypeApp:
+            mediaObject = [WXAppExtendObject object];
+            ((WXAppExtendObject*)mediaObject).extInfo = [media objectForKey:@"extInfo"];
+            ((WXAppExtendObject*)mediaObject).url = [media objectForKey:@"url"];
+            break;
+
+        case CDVWXSharingTypeEmotion:
+            mediaObject = [WXEmoticonObject object];
+            ((WXEmoticonObject*)mediaObject).emoticonData = [self getNSDataFromURL:[media objectForKey:@"emotion"]];
+            break;
+
+        case CDVWXSharingTypeFile:
+            mediaObject = [WXFileObject object];
+            ((WXFileObject*)mediaObject).fileData = [self getNSDataFromURL:[media objectForKey:@"file"]];
+            ((WXFileObject*)mediaObject).fileExtension = [media objectForKey:@"fileExtension"];
+            break;
+
+        case CDVWXSharingTypeImage:
+            mediaObject = [WXImageObject object];
+            ((WXImageObject*)mediaObject).imageData = [self getNSDataFromURL:[media objectForKey:@"image"]];
+            break;
+
+        case CDVWXSharingTypeMusic:
+            mediaObject = [WXMusicObject object];
+            ((WXMusicObject*)mediaObject).musicUrl = [media objectForKey:@"musicUrl"];
+            ((WXMusicObject*)mediaObject).musicDataUrl = [media objectForKey:@"musicDataUrl"];
+            break;
+
+        case CDVWXSharingTypeVideo:
+            mediaObject = [WXVideoObject object];
+            ((WXVideoObject*)mediaObject).videoUrl = [media objectForKey:@"videoUrl"];
+            break;
+        case CDVWXSharingTypeMini:
+            object = [WXMiniProgramObject object];
+            object.webpageUrl = [media objectForKey:@"webpageUrl"];
+            object.userName = [media objectForKey:@"userName"];
+            object.path = [media objectForKey:@"path"]; // pages/inbox/inbox?name1=key1&name=key2
+            object.hdImageData = [self getNSDataFromURL:[media objectForKey:@"hdImageData"]];
+            object.withShareTicket = [[media objectForKey:@"withShareTicket"] boolValue];
+            object.miniProgramType = (int)[[media objectForKey:@"miniProgramType"] integerValue];
+            wxMediaMessage.mediaObject = object;
+            return wxMediaMessage;
+            
+        case CDVWXSharingTypeWebPage:
+        default:
+            mediaObject = [WXWebpageObject object];
+            ((WXWebpageObject *)mediaObject).webpageUrl = [media objectForKey:@"webpageUrl"];
+    }
+
+    wxMediaMessage.mediaObject = mediaObject;
+    return wxMediaMessage;
+}
+
+- (NSData *)getNSDataFromURL:(NSString *)url
+{
+    NSData *data = nil;
+
+    if ([url hasPrefix:@"http://"] || [url hasPrefix:@"https://"])
+    {
+        data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
+    }
+    else if ([url hasPrefix:@"data:image"])
+    {
+        // a base 64 string
+        NSURL *base64URL = [NSURL URLWithString:url];
+        data = [NSData dataWithContentsOfURL:base64URL];
+    }
+    else if ([url rangeOfString:@"temp:"].length != 0)
+    {
+        url =  [NSTemporaryDirectory() stringByAppendingPathComponent:[url componentsSeparatedByString:@"temp:"][1]];
+        data = [NSData dataWithContentsOfFile:url];
+    }
+    else
+    {
+        // local file
+        url = [[NSBundle mainBundle] pathForResource:[url stringByDeletingPathExtension] ofType:[url pathExtension]];
+        data = [NSData dataWithContentsOfFile:url];
+    }
+
+    return data;
+}
+
+- (UIImage *)getUIImageFromURL:(NSString *)url
+{
+    NSData *data = [self getNSDataFromURL:url];
+    UIImage *image = [UIImage imageWithData:data];
+
+    if (image.size.width > MAX_THUMBNAIL_SIZE || image.size.height > MAX_THUMBNAIL_SIZE)
+    {
+        CGFloat width = 0;
+        CGFloat height = 0;
+
+        // calculate size
+        if (image.size.width > image.size.height)
+        {
+            width = MAX_THUMBNAIL_SIZE;
+            height = width * image.size.height / image.size.width;
+        }
+        else
+        {
+            height = MAX_THUMBNAIL_SIZE;
+            width = height * image.size.width / image.size.height;
+        }
+
+        // scale it
+        UIGraphicsBeginImageContext(CGSizeMake(width, height));
+        [image drawInRect:CGRectMake(0, 0, width, height)];
+        UIImage *scaled = UIGraphicsGetImageFromCurrentImageContext();
+        UIGraphicsEndImageContext();
+
+        return scaled;
+    }
+
+    return image;
+}
+
+- (void)successWithCallbackID:(NSString *)callbackID
+{
+    [self successWithCallbackID:callbackID withMessage:@"OK"];
+}
+
+- (void)successWithCallbackID:(NSString *)callbackID withMessage:(NSString *)message
+{
+    CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message];
+    [self.commandDelegate sendPluginResult:commandResult callbackId:callbackID];
+}
+
+- (void)failWithCallbackID:(NSString *)callbackID withError:(NSError *)error
+{
+    [self failWithCallbackID:callbackID withMessage:[error localizedDescription]];
+}
+
+- (void)failWithCallbackID:(NSString *)callbackID withMessage:(NSString *)message
+{
+    CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message];
+    [self.commandDelegate sendPluginResult:commandResult callbackId:callbackID];
+}
+
+-  (void)openMiniProgram:(CDVInvokedUrlCommand *)command
+{
+    NSDictionary *params = [command.arguments objectAtIndex:0];
+    WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
+    launchMiniProgramReq.userName = [params objectForKey:@"userName"];  //拉起的小程序的username
+    launchMiniProgramReq.path = [params objectForKey:@"path"];    //拉起小程序页面的可带参路径,不填默认拉起小程序首页
+    launchMiniProgramReq.miniProgramType = (int)[[params objectForKey:@"miniprogramType"] integerValue]; //拉起小程序的类型
+    [WXApi sendReq:launchMiniProgramReq completion:^(BOOL success) {
+        if(success) {
+             self.currentCallbackId = command.callbackId;
+        } else {
+            [self failWithCallbackID:command.callbackId withMessage:@"打开请求失败"];
+        }
+    }];
+}
+
+- (BOOL)handleUserActivity:(NSUserActivity *)userActivity {
+   return [WXApi handleOpenUniversalLink:userActivity delegate:self];
+}
+
+- (BOOL)handleWechatOpenURL:(NSURL *)url  {
+    return [WXApi handleOpenURL:url delegate:self];
+}
+
+@end
diff --git a/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/README.txt b/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/README.txt
new file mode 100644 (file)
index 0000000..b467b46
--- /dev/null
@@ -0,0 +1,115 @@
+重要!
+
+SDK1.8.6.2
+1. 修改包含"UIWebView"字符的类名
+
+SDK1.8.6.1
+1.短信授权登录使用的UIWebview切换成WKWebview
+
+SDK1.8.6
+1. 支持Universal Link拉起微信以及返回App
+2. SDK移除MTA库
+
+SDK1.8.5
+1. 更换MTA库:取消对剪切板的访问, 防止和其他SDK竞争导致crash
+2. NSMutableArray的MTA分类方法改名,减少命名冲突
+3. 不含支付功能版本移除非税支付和医保支付接口
+4. 分享音乐支持填写歌词和高清封面图
+
+SDK1.8.4
+1. 调整分享图片大小限制
+2. 新增openBusinessView接口
+
+SDK1.8.3
+1. SDK增加调起微信刷卡支付接口
+2. SDK增加小程序订阅消息接口
+3. 修复小程序订阅消息接口没有resp的问题
+
+SDK1.8.2
+1. SDK增加开发票授权 WXInvoiceAuthInsert
+2. SDK增加非税接口   WXNontaxPay
+3. SDK增加医保接口   WXPayInsurance
+4. 更换MTA库
+
+SDK1.8.1
+1. SDK打开小程序支持指定版本(体验,开发,正式版)
+2. SDK分享小程序支持指定版本(体验,开发,正式版)
+3. SDK支持输出log日志
+
+SDK1.8.0
+1. SDK支持打开小程序
+2. SDK分享小程序支持shareTicket
+
+SDK1.7.9
+1. SDK订阅一次性消息
+
+SDK1.7.8
+1 SDK分享小程序支持大图
+
+SDK1.7.7
+1 增加SDK分享小程序
+2 增加选择发票接口
+
+SDK1.7.6
+1. 提高稳定性
+1 修复mta崩溃
+2  新增接口支持开发者关闭mta数据统计上报
+
+SDK1.7.5
+1. 提高稳定性
+2. 加快registerApp接口启动速度
+
+SDK1.7.4
+1. 更新支持iOS启用 ATS(App Transport Security)
+2. 需要在工程中链接CFNetwork.framework
+3. 在工程配置中的”Other Linker Flags”中加入”-Objc -all_load”
+
+SDK1.7.3
+1. 增强稳定性,适配iOS10
+2. 修复小于32K的jpg格式缩略图设置失败的问题
+
+SDK1.7.2
+1. 修复因CTTeleponyNetworkInfo引起的崩溃问题
+
+SDK1.7.1
+1. 支持兼容ipv6(提升稳定性)
+2. xCode Version 7.3.1 (7D1014) 编译
+
+SDK1.7
+1. 支持兼容ipv6
+2. 修复若干问题增强稳定性
+
+SDK1.6.3
+1. xCode7.2 构建的sdk包。
+2. 请使用xCode7.2进行编译。
+3. 需要在Build Phases中Link  Security.framework
+4. 修复若干小问题。
+
+SDK1.6.2
+1、xCode7.1 构建的sdk包
+2、请使用xCode7.1进行编译
+
+SDK1.6.1
+1、修复armv7s下,bitcode可能编译不过
+2、解决warning
+
+SDK1.6
+1、iOS 9系统策略更新,限制了http协议的访问,此外应用需要在“Info.plist”中将要使用的URL Schemes列为白名单,才可正常检查其他应用是否安装。
+受此影响,当你的应用在iOS 9中需要使用微信SDK的相关能力(分享、收藏、支付、登录等)时,需要在“Info.plist”里增加如下代码:
+<key>LSApplicationQueriesSchemes</key>
+<array>
+<string>weixin</string>
+</array>
+<key>NSAppTransportSecurity</key>
+<dict>
+<key>NSAllowsArbitraryLoads</key>
+<true/>
+</dict>
+2、开发者需要在工程中链接上 CoreTelephony.framework
+3、解决bitcode编译不过问题
+
+SDK1.5
+1、废弃safeSendReq:接口,使用sendReq:即可。
+2、新增+(BOOL) sendAuthReq:(SendAuthReq*) req viewController : (UIViewController*) viewController delegate:(id<WXApiDelegate>) delegate;
+支持未安装微信情况下Auth,具体见WXApi.h接口描述
+3、微信开放平台新增了微信模块用户统计功能,便于开发者统计微信功能模块的用户使用和活跃情况。开发者需要在工程中链接上:SystemConfiguration.framework,libz.dylib,libsqlite3.0.dylib。
diff --git a/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WXApi.h b/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WXApi.h
new file mode 100644 (file)
index 0000000..38e6476
--- /dev/null
@@ -0,0 +1,183 @@
+//
+//  WXApi.h
+//  所有Api接口
+//
+//  Created by Wechat on 12-2-28.
+//  Copyright (c) 2012年 Tencent. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "WXApiObject.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - WXApiDelegate
+/*! @brief 接收并处理来自微信终端程序的事件消息
+ *
+ * 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。
+ * WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。
+ */
+@protocol WXApiDelegate <NSObject>
+@optional
+
+/*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果
+ *
+ * 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。
+ * 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。
+ * @param req 具体请求内容,是自动释放的
+ */
+- (void)onReq:(BaseReq*)req;
+
+
+
+/*! @brief 发送一个sendReq后,收到微信的回应
+ *
+ * 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
+ * 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
+ * @param resp具体的回应内容,是自动释放的
+ */
+- (void)onResp:(BaseResp*)resp;
+
+@end
+
+#pragma mark - WXApiLogDelegate
+
+@protocol WXApiLogDelegate <NSObject>
+
+- (void)onLog:(NSString*)log logLevel:(WXLogLevel)level;
+
+@end
+
+#pragma mark - WXApi
+
+/*! @brief 微信Api接口函数类
+ *
+ * 该类封装了微信终端SDK的所有接口
+ */
+@interface WXApi : NSObject
+
+/*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。
+ *
+ * 需要在每次启动第三方应用程序时调用。
+ * @attention 请保证在主线程中调用此函数
+ * @param appid 微信开发者ID
+ * @param universalLink 微信开发者Universal Link
+ * @return 成功返回YES,失败返回NO。
+ */
++ (BOOL)registerApp:(NSString *)appid universalLink:(NSString *)universalLink;
+
+
+/*! @brief 处理旧版微信通过URL启动App时传递的数据
+ *
+ * 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。
+ * @param url 微信启动第三方应用时传递过来的URL
+ * @param delegate  WXApiDelegate对象,用来接收微信触发的消息。
+ * @return 成功返回YES,失败返回NO。
+ */
++ (BOOL)handleOpenURL:(NSURL *)url delegate:(nullable id<WXApiDelegate>)delegate;
+
+
+/*! @brief 处理微信通过Universal Link启动App时传递的数据
+ *
+ * 需要在 application:continueUserActivity:restorationHandler:中调用。
+ * @param userActivity 微信启动第三方应用时系统API传递过来的userActivity
+ * @param delegate  WXApiDelegate对象,用来接收微信触发的消息。
+ * @return 成功返回YES,失败返回NO。
+ */
++ (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity delegate:(nullable id<WXApiDelegate>)delegate;
+
+
+/*! @brief 检查微信是否已被用户安装
+ *
+ * @return 微信已安装返回YES,未安装返回NO。
+ */
++ (BOOL)isWXAppInstalled;
+
+
+
+/*! @brief 判断当前微信的版本是否支持OpenApi
+ *
+ * @return 支持返回YES,不支持返回NO。
+ */
++ (BOOL)isWXAppSupportApi;
+
+
+
+/*! @brief 获取微信的itunes安装地址
+ *
+ * @return 微信的安装地址字符串。
+ */
++ (NSString *)getWXAppInstallUrl;
+
+
+
+/*! @brief 获取当前微信SDK的版本号
+ *
+ * @return 返回当前微信SDK的版本号
+ */
++ (NSString *)getApiVersion;
+
+
+
+/*! @brief 打开微信
+ *
+ * @return 成功返回YES,失败返回NO。
+ */
++ (BOOL)openWXApp;
+
+
+
+/*! @brief 发送请求到微信,等待微信返回onResp
+ *
+ * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型
+ * SendAuthReq、SendMessageToWXReq、PayReq等。
+ * @param req 具体的发送请求。
+ * @param completion 调用结果回调block
+ */
++ (void)sendReq:(BaseReq *)req completion:(void (^ __nullable)(BOOL success))completion;
+
+/*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面
+ *
+ * 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有
+ * GetMessageFromWXResp、ShowMessageFromWXResp等。
+ * @param resp 具体的应答内容
+ * @param completion 调用结果回调block
+ */
++ (void)sendResp:(BaseResp*)resp completion:(void (^ __nullable)(BOOL success))completion;
+
+
+/*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp
+ *
+ * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。
+ * @param req 具体的发送请求。
+ * @param viewController 当前界面对象。
+ * @param delegate  WXApiDelegate对象,用来接收微信触发的消息。
+ * @param completion 调用结果回调block
+ */
++ (void)sendAuthReq:(SendAuthReq *)req viewController:(UIViewController*)viewController delegate:(nullable id<WXApiDelegate>)delegate completion:(void (^ __nullable)(BOOL success))completion;
+
+
+/*! @brief WXApi的成员函数,接受微信的log信息。byBlock
+    注意1:SDK会强引用这个block,注意不要导致内存泄漏,注意不要导致内存泄漏
+    注意2:调用过一次startLog by block之后,如果再调用一次任意方式的startLoad,会释放上一次logBlock,不再回调上一个logBlock
+ *
+ *  @param level 打印log的级别
+ *  @param logBlock 打印log的回调block
+ */
++ (void)startLogByLevel:(WXLogLevel)level logBlock:(WXLogBolock)logBlock;
+
+/*! @brief WXApi的成员函数,接受微信的log信息。byDelegate 
+    注意1:sdk会弱引用这个delegate,这里可加任意对象为代理,不需要与WXApiDelegate同一个对象
+    注意2:调用过一次startLog by delegate之后,再调用一次任意方式的startLoad,不会再回调上一个logDelegate对象
+ *  @param level 打印log的级别
+ *  @param logDelegate 打印log的回调代理,
+ */
++ (void)startLogByLevel:(WXLogLevel)level logDelegate:(id<WXApiLogDelegate>)logDelegate;
+
+/*! @brief 停止打印log,会清理block或者delegate为空,释放block
+ *  @param 
+ */
++ (void)stopLog;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WXApiObject.h b/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WXApiObject.h
new file mode 100644 (file)
index 0000000..28828e2
--- /dev/null
@@ -0,0 +1,1026 @@
+//
+//  MMApiObject.h
+//  Api对象,包含所有接口和对象数据定义
+//
+//  Created by Wechat on 12-2-28.
+//  Copyright (c) 2012年 Tencent. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief 错误码
+ *
+ */
+enum  WXErrCode {
+    WXSuccess           = 0,    /**< 成功    */
+    WXErrCodeCommon     = -1,   /**< 普通错误类型    */
+    WXErrCodeUserCancel = -2,   /**< 用户点击取消并返回    */
+    WXErrCodeSentFail   = -3,   /**< 发送失败    */
+    WXErrCodeAuthDeny   = -4,   /**< 授权失败    */
+    WXErrCodeUnsupport  = -5,   /**< 微信不支持    */
+};
+
+
+
+/*! @brief 请求发送场景
+ *
+ */
+enum WXScene {
+    WXSceneSession          = 0,   /**< 聊天界面    */
+    WXSceneTimeline         = 1,   /**< 朋友圈     */
+    WXSceneFavorite         = 2,   /**< 收藏       */
+    WXSceneSpecifiedSession = 3,   /**< 指定联系人  */
+};
+
+
+enum WXAPISupport {
+    WXAPISupportSession = 0,
+};
+
+
+
+/*! @brief 跳转profile类型
+ *
+ */
+enum WXBizProfileType {
+    WXBizProfileType_Normal = 0,    //**< 普通公众号  */
+    WXBizProfileType_Device = 1,    //**< 硬件公众号  */
+};
+
+/*! @brief 分享小程序类型
+ *
+ */
+typedef NS_ENUM(NSUInteger, WXMiniProgramType) {
+    WXMiniProgramTypeRelease = 0,       //**< 正式版  */
+    WXMiniProgramTypeTest = 1,        //**< 开发版  */
+    WXMiniProgramTypePreview = 2,         //**< 体验版  */
+};
+
+/*! @brief 跳转mp网页类型
+ *
+ */
+enum WXMPWebviewType {
+    WXMPWebviewType_Ad = 0,        /**< 广告网页 **/
+};
+
+/*! @brief log的级别
+ *
+ */
+typedef NS_ENUM(NSInteger,WXLogLevel) {
+    WXLogLevelNormal = 0,      // 打印日常的日志
+    WXLogLevelDetail = 1,      // 打印详细的日志
+};
+
+
+/*! @brief 打印回调的block
+ *
+ */
+typedef void(^WXLogBolock)(NSString *log);
+
+#pragma mark - BaseReq
+/*! @brief 该类为微信终端SDK所有请求类的基类
+ *
+ */
+@interface BaseReq : NSObject
+
+/** 请求类型 */
+@property (nonatomic, assign) int type;
+/** 由用户微信号和AppID组成的唯一标识,需要校验微信用户是否换号登录时填写*/
+@property (nonatomic, copy) NSString *openID;
+
+@end
+
+
+
+#pragma mark - BaseResp
+/*! @brief 该类为微信终端SDK所有响应类的基类
+ *
+ */
+@interface BaseResp : NSObject
+/** 错误码 */
+@property (nonatomic, assign) int errCode;
+/** 错误提示字符串 */
+@property (nonatomic, copy) NSString *errStr;
+/** 响应类型 */
+@property (nonatomic, assign) int type;
+
+@end
+
+
+
+#pragma mark - WXMediaMessage
+@class WXMediaMessage;
+
+#ifndef BUILD_WITHOUT_PAY
+
+#pragma mark - PayReq
+/*! @brief 第三方向微信终端发起支付的消息结构体
+ *
+ *  第三方向微信终端发起支付的消息结构体,微信终端处理后会向第三方返回处理结果
+ * @see PayResp
+ */
+@interface PayReq : BaseReq
+
+/** 商家向财付通申请的商家id */
+@property (nonatomic, copy) NSString *partnerId;
+/** 预支付订单 */
+@property (nonatomic, copy) NSString *prepayId;
+/** 随机串,防重发 */
+@property (nonatomic, copy) NSString *nonceStr;
+/** 时间戳,防重发 */
+@property (nonatomic, assign) UInt32 timeStamp;
+/** 商家根据财付通文档填写的数据和签名 */
+@property (nonatomic, copy) NSString *package;
+/** 商家根据微信开放平台文档对数据做的签名 */
+@property (nonatomic, copy) NSString *sign;
+
+@end
+
+
+#pragma mark - PayResp
+/*! @brief 微信终端返回给第三方的关于支付结果的结构体
+ *
+ *  微信终端返回给第三方的关于支付结果的结构体
+ */
+@interface PayResp : BaseResp
+
+/** 财付通返回给商家的信息 */
+@property (nonatomic, copy) NSString *returnKey;
+
+@end
+
+#pragma mark - WXOfflinePay
+/*! @brief 第三方向微信终端发起离线支付
+ *
+ *  第三方向微信终端发起离线支付的消息结构体
+ */
+@interface WXOfflinePayReq : BaseReq
+
+@end
+
+/*! @brief 第三方向微信终端发起离线支付返回
+ *
+ *  第三方向微信终端发起离线支付返回的消息结构体
+ */
+@interface WXOfflinePayResp : BaseResp
+
+@end
+
+
+#pragma mark - WXNontaxPayReq
+@interface WXNontaxPayReq:BaseReq
+
+@property (nonatomic, copy) NSString *urlString;
+
+@end
+
+#pragma mark - WXNontaxPayResp
+@interface WXNontaxPayResp : BaseResp
+
+@property (nonatomic, copy) NSString *wxOrderId;
+
+@end
+
+#pragma mark - WXPayInsuranceReq
+@interface WXPayInsuranceReq : BaseReq
+
+@property (nonatomic, copy) NSString *urlString;
+
+@end
+
+#pragma mark - WXPayInsuranceResp
+@interface WXPayInsuranceResp : BaseResp
+
+@property (nonatomic, copy) NSString *wxOrderId;
+
+@end
+
+#endif
+
+
+#pragma mark - SendAuthReq
+/*! @brief 第三方程序向微信终端请求认证的消息结构
+ *
+ * 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,
+ * 向微信终端发送一个SendAuthReq消息结构。微信终端处理完后会向第三方程序发送一个处理结果。
+ * @see SendAuthResp
+ */
+@interface SendAuthReq : BaseReq
+/** 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,向微信终端发送一个SendAuthReq消息结构。微信终端处理完后会向第三方程序发送一个处理结果。
+ * @see SendAuthResp
+ * @note scope字符串长度不能超过1K
+ */
+@property (nonatomic, copy) NSString *scope;
+/** 第三方程序本身用来标识其请求的唯一性,最后跳转回第三方程序时,由微信终端回传。
+ * @note state字符串长度不能超过1K
+ */
+@property (nonatomic, copy) NSString *state;
+
+@end
+
+#pragma mark - SendAuthResp
+/*! @brief 微信处理完第三方程序的认证和权限申请后向第三方程序回送的处理结果。
+ *
+ * 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,向微信终端发送一个SendAuthReq消息结构。
+ * 微信终端处理完后会向第三方程序发送一个SendAuthResp。
+ * @see onResp
+ */
+@interface SendAuthResp : BaseResp
+@property (nonatomic, copy, nullable) NSString *code;
+/** 第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传
+ * @note state字符串长度不能超过1K
+ */
+@property (nonatomic, copy, nullable) NSString *state;
+@property (nonatomic, copy, nullable) NSString *lang;
+@property (nonatomic, copy, nullable) NSString *country;
+@end
+
+
+
+#pragma mark - SendMessageToWXReq
+/*! @brief 第三方程序发送消息至微信终端程序的消息结构体
+ *
+ * 第三方程序向微信发送信息需要传入SendMessageToWXReq结构体,信息类型包括文本消息和多媒体消息,
+ * 分别对应于text和message成员。调用该方法后,微信处理完信息会向第三方程序发送一个处理结果。
+ * @see SendMessageToWXResp
+ */
+@interface SendMessageToWXReq : BaseReq
+/** 发送消息的文本内容
+ * @note 文本长度必须大于0且小于10K
+ */
+@property (nonatomic, copy) NSString *text;
+/** 发送消息的多媒体内容
+ * @see WXMediaMessage
+ */
+@property (nonatomic, strong) WXMediaMessage *message;
+/** 发送消息的类型,包括文本消息和多媒体消息两种,两者只能选择其一,不能同时发送文本和多媒体消息 */
+@property (nonatomic, assign) BOOL bText;
+/** 发送的目标场景,可以选择发送到会话(WXSceneSession)或者朋友圈(WXSceneTimeline)。 默认发送到会话。
+ * @see WXScene
+ */
+@property (nonatomic, assign) int scene;
+/** 指定发送消息的人
+ * @note WXSceneSpecifiedSession时有效
+ */
+@property (nonatomic, copy, nullable) NSString *toUserOpenId;
+@end
+
+#pragma mark - SendMessageToWXResp
+/*! @brief 微信终端向第三方程序返回的SendMessageToWXReq处理结果。
+ *
+ * 第三方程序向微信终端发送SendMessageToWXReq后,微信发送回来的处理结果,该结果用SendMessageToWXResp表示。
+ */
+@interface SendMessageToWXResp : BaseResp
+@property(nonatomic, copy) NSString *lang;
+@property(nonatomic, copy) NSString *country;
+@end
+
+#pragma mark - GetMessageFromWXReq
+/*! @brief 微信终端向第三方程序请求提供内容的消息结构体。
+ *
+ * 微信终端向第三方程序请求提供内容,微信终端会向第三方程序发送GetMessageFromWXReq消息结构体,
+ * 需要第三方程序调用sendResp返回一个GetMessageFromWXResp消息结构体。
+ */
+@interface GetMessageFromWXReq : BaseReq
+@property (nonatomic, strong) NSString *lang;
+@property (nonatomic, strong) NSString *country;
+@end
+
+
+
+#pragma mark - GetMessageFromWXResp
+/*! @brief 微信终端向第三方程序请求提供内容,第三方程序向微信终端返回的消息结构体。
+ *
+ * 微信终端向第三方程序请求提供内容,第三方程序调用sendResp向微信终端返回一个GetMessageFromWXResp消息结构体。
+ */
+@interface GetMessageFromWXResp : BaseResp
+/** 向微信终端提供的文本内容
+ @note 文本长度必须大于0且小于10K
+ */
+@property (nonatomic, strong) NSString *text;
+/** 向微信终端提供的多媒体内容。
+ * @see WXMediaMessage
+ */
+@property (nonatomic, strong) WXMediaMessage *message;
+/** 向微信终端提供内容的消息类型,包括文本消息和多媒体消息两种,两者只能选择其一,不能同时发送文本和多媒体消息 */
+@property (nonatomic, assign) BOOL bText;
+@end
+
+
+
+#pragma mark - ShowMessageFromWXReq
+/*! @brief 微信通知第三方程序,要求第三方程序显示的消息结构体。
+ *
+ * 微信需要通知第三方程序显示或处理某些内容时,会向第三方程序发送ShowMessageFromWXReq消息结构体。
+ * 第三方程序处理完内容后调用sendResp向微信终端发送ShowMessageFromWXResp。
+ */
+@interface ShowMessageFromWXReq : BaseReq
+/** 微信终端向第三方程序发送的要求第三方程序处理的多媒体内容
+ * @see WXMediaMessage
+ */
+@property (nonatomic, strong) WXMediaMessage *message;
+@property (nonatomic, copy) NSString *lang;
+@property (nonatomic, copy) NSString *country;
+@end
+
+
+
+#pragma mark - ShowMessageFromWXResp
+/*! @brief 微信通知第三方程序,要求第三方程序显示或处理某些消息,第三方程序处理完后向微信终端发送的处理结果。
+ *
+ * 微信需要通知第三方程序显示或处理某些内容时,会向第三方程序发送ShowMessageFromWXReq消息结构体。
+ * 第三方程序处理完内容后调用sendResp向微信终端发送ShowMessageFromWXResp。
+ */
+@interface ShowMessageFromWXResp : BaseResp
+@end
+
+
+#pragma mark - LaunchFromWXReq
+/*! @brief 微信终端打开第三方程序携带的消息结构体
+ *
+ *  微信向第三方发送的结构体,第三方不需要返回
+ */
+@interface LaunchFromWXReq : BaseReq
+@property (nonatomic, strong) WXMediaMessage *message;
+@property (nonatomic, copy) NSString *lang;
+@property (nonatomic, copy) NSString *country;
+@end
+
+
+#pragma mark - OpenWebviewReq
+/* ! @brief 第三方通知微信启动内部浏览器,打开指定网页
+ *
+ *  第三方通知微信启动内部浏览器,打开指定Url对应的网页
+ */
+@interface OpenWebviewReq : BaseReq
+/** 需要打开的网页对应的Url
+ * @attention 长度不能超过1024
+ */
+@property(nonatomic, copy) NSString *url;
+
+@end
+
+#pragma mark - OpenWebviewResp
+/*! @brief 微信终端向第三方程序返回的OpenWebviewReq处理结果
+ *
+ * 第三方程序向微信终端发送OpenWebviewReq后,微信发送回来的处理结果,该结果用OpenWebviewResp表示
+ */
+@interface OpenWebviewResp : BaseResp
+
+@end
+
+
+
+#pragma mark - WXOpenBusinessWebViewReq
+/*! @brief 第三方通知微信启动内部浏览器,打开指定业务的网页
+ *
+ *
+ */
+@interface WXOpenBusinessWebViewReq : BaseReq
+
+/** 网页业务类型
+ * @attention
+ */
+@property (nonatomic, assign) UInt32 businessType;
+
+/** 网页业务参数
+ * @attention
+ */
+@property (nonatomic, strong, nullable) NSDictionary *queryInfoDic;
+
+@end
+
+#pragma mark - WXOpenBusinessWebViewResp
+/*! @brief 微信终端向第三方程序返回的WXOpenBusinessWebViewResp处理结果。
+ *
+ * 第三方程序向微信终端发送WXOpenBusinessWebViewReq后,微信发送回来的处理结果,该结果用WXOpenBusinessWebViewResp表示。
+ */
+@interface WXOpenBusinessWebViewResp : BaseResp
+/** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理
+ * @attention 长度不能超过2k
+ */
+@property (nonatomic, copy) NSString *result;
+
+/** 网页业务类型
+ * @attention
+ */
+@property (nonatomic, assign) UInt32 businessType;
+
+@end
+
+
+#pragma mark - OpenRankListReq
+/* ! @brief 第三方通知微信,打开硬件排行榜
+ *
+ * 第三方通知微信,打开硬件排行榜
+ */
+@interface OpenRankListReq : BaseReq
+
+@end
+
+#pragma mark - OpenRanklistResp
+/*! @brief 微信终端向第三方程序返回的OpenRankListReq处理结果。
+ *
+ * 第三方程序向微信终端发送OpenRankListReq后,微信发送回来的处理结果,该结果用OpenRankListResp表示。
+ */
+@interface OpenRankListResp : BaseResp
+
+@end
+
+
+#pragma mark - WXCardItem
+
+@interface WXCardItem : NSObject
+/** 卡id
+ * @attention 长度不能超过1024字节
+ */
+@property (nonatomic, copy) NSString *cardId;
+/** ext信息
+ * @attention 长度不能超过2024字节
+ */
+@property (nonatomic, copy, nullable) NSString *extMsg;
+/**
+ * @attention 卡的状态,req不需要填。resp:0为未添加,1为已添加。
+ */
+@property (nonatomic, assign) UInt32 cardState;
+/**
+ * @attention req不需要填,chooseCard返回的。
+ */
+@property (nonatomic, copy) NSString *encryptCode;
+/**
+ * @attention req不需要填,chooseCard返回的。
+ */
+@property (nonatomic, copy) NSString *appID;
+@end;
+
+#pragma mark - WXInvoiceItem
+
+@interface WXInvoiceItem : NSObject
+/** 卡id
+ * @attention 长度不能超过1024字节
+ */
+@property (nonatomic, copy) NSString *cardId;
+/** ext信息
+ * @attention 长度不能超过2024字节
+ */
+@property (nonatomic, copy, nullable) NSString *extMsg;
+/**
+ * @attention 卡的状态,req不需要填。resp:0为未添加,1为已添加。
+ */
+@property (nonatomic, assign) UInt32 cardState;
+/**
+ * @attention req不需要填,chooseCard返回的。
+ */
+@property (nonatomic, copy) NSString *encryptCode;
+/**
+ * @attention req不需要填,chooseCard返回的。
+ */
+@property (nonatomic, copy) NSString *appID;
+
+@end
+
+#pragma mark - AddCardToWXCardPackageReq
+/* ! @brief 请求添加卡券至微信卡包
+ *
+ */
+
+@interface AddCardToWXCardPackageReq : BaseReq
+/** 卡列表
+ * @attention 个数不能超过40个 类型WXCardItem
+ */
+@property (nonatomic, strong) NSArray *cardAry;
+
+@end
+
+
+#pragma mark - AddCardToWXCardPackageResp
+/** ! @brief 微信返回第三方添加卡券结果
+ *
+ */
+
+@interface AddCardToWXCardPackageResp : BaseResp
+/** 卡列表
+ * @attention 个数不能超过40个 类型WXCardItem
+ */
+@property (nonatomic, strong) NSArray *cardAry;
+@end
+
+#pragma mark - WXChooseCardReq
+/* ! @brief 请求从微信选取卡券
+ *
+ */
+
+@interface WXChooseCardReq : BaseReq
+@property (nonatomic, copy) NSString *appID;
+@property (nonatomic, assign) UInt32 shopID;
+@property (nonatomic, assign) UInt32 canMultiSelect;
+@property (nonatomic, copy) NSString *cardType;
+@property (nonatomic, copy) NSString *cardTpID;
+@property (nonatomic, copy) NSString *signType;
+@property (nonatomic, copy) NSString *cardSign;
+@property (nonatomic, assign) UInt32 timeStamp;
+@property (nonatomic, copy) NSString *nonceStr;
+@end
+
+
+#pragma mark - WXChooseCardResp
+/** ! @brief 微信返回第三方请求选择卡券结果
+ *
+ */
+
+@interface WXChooseCardResp : BaseResp
+@property (nonatomic, strong ) NSArray* cardAry;
+@end
+
+
+#pragma mark - WXChooseInvoiceReq
+/* ! @brief 请求从微信选取发票
+ *
+ */
+@interface WXChooseInvoiceReq : BaseReq
+@property (nonatomic, copy) NSString *appID;
+@property (nonatomic, assign) UInt32 shopID;
+@property (nonatomic, copy) NSString *signType;
+@property (nonatomic, copy) NSString *cardSign;
+@property (nonatomic, assign) UInt32 timeStamp;
+@property (nonatomic, copy) NSString *nonceStr;
+@end
+
+#pragma mark - WXChooseInvoiceResp
+/** ! @brief 微信返回第三方请求选择发票结果
+ *
+ */
+@interface WXChooseInvoiceResp : BaseResp
+@property (nonatomic, strong) NSArray* cardAry;
+@end
+
+#pragma mark - WXSubscriptionReq
+@interface WXSubscribeMsgReq : BaseReq
+@property (nonatomic, assign) UInt32 scene;
+@property (nonatomic, copy) NSString *templateId;
+@property (nonatomic, copy, nullable) NSString *reserved;
+@end
+
+#pragma mark - WXSubscriptionReq
+@interface WXSubscribeMsgResp : BaseResp
+
+@property (nonatomic, copy) NSString *templateId;
+@property (nonatomic, assign) UInt32 scene;
+@property (nonatomic, copy) NSString *action;
+@property (nonatomic, copy) NSString *reserved;
+@property (nonatomic, copy, nullable) NSString *openId;
+
+@end
+
+#pragma mark - WXSubscribeMiniProgramMsg
+/** ! @brief 第三方请求订阅小程序消息
+ *
+ */
+@interface WXSubscribeMiniProgramMsgReq : BaseReq
+@property (nonatomic, copy) NSString *miniProgramAppid;
+@end
+
+#pragma mark - WXSubscriptionReq
+@interface WXSubscribeMiniProgramMsgResp : BaseResp
+
+@property(nonatomic, copy) NSString *openId;   // 小程序openid
+@property(nonatomic, copy) NSString *unionId;  // unionId
+@property(nonatomic, copy) NSString *nickName; // 用户昵称
+
+@end
+
+#pragma mark - WXinvoiceAuthInsertReq
+@interface WXInvoiceAuthInsertReq : BaseReq
+
+@property (nonatomic, copy) NSString *urlString;
+
+@end
+
+#pragma mark - WXinvoiceAuthInsertResp
+
+@interface WXInvoiceAuthInsertResp : BaseResp
+
+@property (nonatomic, copy) NSString *wxOrderId;
+
+@end
+
+#pragma mark - WXMediaMessage
+
+/*! @brief 多媒体消息结构体
+ *
+ * 用于微信终端和第三方程序之间传递消息的多媒体消息内容
+ */
+@interface WXMediaMessage : NSObject
+
++ (WXMediaMessage *)message;
+
+/** 标题
+ * @note 长度不能超过512字节
+ */
+@property (nonatomic, copy) NSString *title;
+/** 描述内容
+ * @note 长度不能超过1K
+ */
+@property (nonatomic, copy) NSString *description;
+/** 缩略图数据
+ * @note 大小不能超过64K
+ */
+@property (nonatomic, strong, nullable) NSData *thumbData;
+/**
+ * @note 长度不能超过64字节
+ */
+@property (nonatomic, copy, nullable) NSString *mediaTagName;
+/**
+ *
+ */
+@property (nonatomic, copy, nullable) NSString *messageExt;
+@property (nonatomic, copy, nullable) NSString *messageAction;
+/**
+ * 多媒体数据对象,可以为WXImageObject,WXMusicObject,WXVideoObject,WXWebpageObject等。
+ */
+@property (nonatomic, strong) id mediaObject;
+
+/*! @brief 设置消息缩略图的方法
+ *
+ * @param image 缩略图
+ * @note 大小不能超过64K
+ */
+- (void)setThumbImage:(UIImage *)image;
+
+@end
+
+
+
+#pragma mark - WXImageObject
+/*! @brief 多媒体消息中包含的图片数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的图片数据对象。
+ * @note imageData成员不能为空
+ * @see WXMediaMessage
+ */
+@interface WXImageObject : NSObject
+/*! @brief 返回一个WXImageObject对象
+ *
+ * @note 返回的WXImageObject对象是自动释放的
+ */
++ (WXImageObject *)object;
+
+/** 图片真实数据内容
+ * @note 大小不能超过25M
+ */
+@property (nonatomic, strong) NSData *imageData;
+
+@end
+
+
+#pragma mark - WXMusicObject
+/*! @brief 多媒体消息中包含的音乐数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的音乐数据对象。
+ * @note musicUrl和musicLowBandUrl成员不能同时为空。
+ * @see WXMediaMessage
+ */
+@interface WXMusicObject : NSObject
+/*! @brief 返回一个WXMusicObject对象
+ *
+ * @note 返回的WXMusicObject对象是自动释放的
+ */
++ (WXMusicObject *)object;
+
+/** 音乐网页的url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *musicUrl;
+/** 音乐lowband网页的url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *musicLowBandUrl;
+/** 音乐数据url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *musicDataUrl;
+
+/**音乐lowband数据url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *musicLowBandDataUrl;
+
+/**音乐封面图Url
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *songAlbumUrl;
+
+/**歌词信息 LRC格式
+ * @note 长度不能超过32K
+ */
+@property (nonatomic, copy, nullable) NSString *songLyric;
+@end
+
+
+
+#pragma mark - WXVideoObject
+/*! @brief 多媒体消息中包含的视频数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的视频数据对象。
+ * @note videoUrl和videoLowBandUrl不能同时为空。
+ * @see WXMediaMessage
+ */
+@interface WXVideoObject : NSObject
+/*! @brief 返回一个WXVideoObject对象
+ *
+ * @note 返回的WXVideoObject对象是自动释放的
+ */
++ (WXVideoObject *)object;
+
+/** 视频网页的url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *videoUrl;
+/** 视频lowband网页的url地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *videoLowBandUrl;
+
+@end
+
+
+
+#pragma mark - WXWebpageObject
+/*! @brief 多媒体消息中包含的网页数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的网页数据对象。
+ * @see WXMediaMessage
+ */
+@interface WXWebpageObject : NSObject
+/*! @brief 返回一个WXWebpageObject对象
+ *
+ * @note 返回的WXWebpageObject对象是自动释放的
+ */
++ (WXWebpageObject *)object;
+
+/** 网页的url地址
+ * @note 不能为空且长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *webpageUrl;
+
+@end
+
+
+
+#pragma mark - WXAppExtendObject
+/*! @brief 多媒体消息中包含的App扩展数据对象
+ *
+ * 第三方程序向微信终端发送包含WXAppExtendObject的多媒体消息,
+ * 微信需要处理该消息时,会调用该第三方程序来处理多媒体消息内容。
+ * @note url,extInfo和fileData不能同时为空
+ * @see WXMediaMessage
+ */
+@interface WXAppExtendObject : NSObject
+/*! @brief 返回一个WXAppExtendObject对象
+ *
+ * @note 返回的WXAppExtendObject对象是自动释放的
+ */
++ (WXAppExtendObject *)object;
+
+/** 若第三方程序不存在,微信终端会打开该url所指的App下载地址
+ * @note 长度不能超过10K
+ */
+@property (nonatomic, copy) NSString *url;
+/** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理
+ * @note 长度不能超过2K
+ */
+@property (nonatomic, copy, nullable) NSString *extInfo;
+/** App文件数据,该数据发送给微信好友,微信好友需要点击后下载数据,微信终端会回传给第三方程序处理
+ * @note 大小不能超过10M
+ */
+@property (nonatomic, strong, nullable) NSData *fileData;
+
+@end
+
+
+
+#pragma mark - WXEmoticonObject
+/*! @brief 多媒体消息中包含的表情数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的表情数据对象。
+ * @see WXMediaMessage
+ */
+@interface WXEmoticonObject : NSObject
+
+/*! @brief 返回一个WXEmoticonObject对象
+ *
+ * @note 返回的WXEmoticonObject对象是自动释放的
+ */
++ (WXEmoticonObject *)object;
+
+/** 表情真实数据内容
+ * @note 大小不能超过10M
+ */
+@property (nonatomic, strong) NSData *emoticonData;
+
+@end
+
+
+
+#pragma mark - WXFileObject
+/*! @brief 多媒体消息中包含的文件数据对象
+ *
+ * @see WXMediaMessage
+ */
+@interface WXFileObject : NSObject
+
+/*! @brief 返回一个WXFileObject对象
+ *
+ * @note 返回的WXFileObject对象是自动释放的
+ */
++ (WXFileObject *)object;
+
+/** 文件后缀名
+ * @note 长度不超过64字节
+ */
+@property (nonatomic, copy) NSString *fileExtension;
+
+/** 文件真实数据内容
+ * @note 大小不能超过10M
+ */
+@property (nonatomic, strong) NSData *fileData;
+
+@end
+
+
+#pragma mark - WXLocationObject
+/*! @brief 多媒体消息中包含的地理位置数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的地理位置数据对象。
+ * @see WXMediaMessage
+ */
+@interface WXLocationObject : NSObject
+
+/*! @brief 返回一个WXLocationObject对象
+ *
+ * @note 返回的WXLocationObject对象是自动释放的
+ */
++ (WXLocationObject *)object;
+
+/** 地理位置信息
+ * @note 经纬度
+ */
+@property (nonatomic, assign) double lng; //经度
+@property (nonatomic, assign) double lat; //纬度
+
+@end
+
+#pragma mark - WXTextObject
+/*! @brief 多媒体消息中包含的文本数据对象
+ *
+ * 微信终端和第三方程序之间传递消息中包含的文本数据对象。
+ * @see WXMediaMessage
+ */
+@interface WXTextObject : NSObject
+
+/*! @brief 返回一个WXTextObject对象
+ *
+ * @note 返回的WXTextObject对象是自动释放的
+ */
++ (WXTextObject *)object;
+
+/** 地理位置信息
+ * @note 文本内容
+ */
+@property (nonatomic, copy) NSString *contentText;
+
+@end
+
+#pragma mark - WXMiniProgramObject
+
+@interface WXMiniProgramObject : NSObject
+
+/*! @brief WXMiniProgramObject对象
+ *
+ * @note 返回的WXMiniProgramObject对象是自动释放的
+ */
++ (WXMiniProgramObject *)object;
+
+/** 低版本网页链接
+ * @attention 长度不能超过1024字节
+ */
+@property (nonatomic, copy) NSString *webpageUrl;
+
+/** 小程序username */
+@property (nonatomic, copy) NSString *userName;
+
+/** 小程序页面的路径
+ * @attention 不填默认拉起小程序首页
+ */
+@property (nonatomic, copy, nullable) NSString *path;
+
+/** 小程序新版本的预览图
+ * @attention 大小不能超过128k
+ */
+@property (nonatomic, strong, nullable) NSData *hdImageData;
+
+/** 是否使用带 shareTicket 的转发 */
+@property (nonatomic, assign) BOOL withShareTicket;
+
+/** 分享小程序的版本
+ * @attention (正式,开发,体验)
+ */
+@property (nonatomic, assign) WXMiniProgramType miniProgramType;
+
+/** 是否禁用转发 */
+@property (nonatomic, assign) BOOL disableForward;
+
+@end
+
+#pragma mark - WXLaunchMiniProgramReq
+
+/*! @brief WXLaunchMiniProgramReq对象, 可实现通过sdk拉起微信小程序
+ *
+ * @note 返回的WXLaunchMiniProgramReq对象是自动释放的
+ */
+@interface WXLaunchMiniProgramReq : BaseReq
+
++ (WXLaunchMiniProgramReq *)object;
+
+/** 小程序username */
+@property (nonatomic, copy) NSString *userName;
+
+/** 小程序页面的路径
+ * @attention 不填默认拉起小程序首页
+ */
+@property (nonatomic, copy, nullable) NSString *path;
+
+/** 分享小程序的版本
+ * @attention (正式,开发,体验)
+ */
+@property (nonatomic, assign) WXMiniProgramType miniProgramType;
+
+/** ext信息
+ * @attention json格式
+ */
+@property (nonatomic, copy, nullable) NSString *extMsg;
+
+/** extDic
+ * @attention 字典,可存放图片等比较大的数据
+ */
+@property (nonatomic, copy, nullable) NSDictionary *extDic;
+
+@end
+
+#pragma mark - WXLaunchMiniProgramResp
+/*! @brief 微信终端向第三方程序返回的WXLaunchMiniProgramReq处理结果。
+ *
+ * 第三方程序向微信终端发送WXLaunchMiniProgramReq后,微信发送回来的处理结果,该结果用WXLaunchMiniProgramResp表示。
+ */
+@interface WXLaunchMiniProgramResp : BaseResp
+
+@property (nonatomic, copy, nullable) NSString *extMsg;
+
+@end
+
+
+#pragma mark - WXOpenBusinessViewReq
+/*! @brief WXOpenBusinessViewReq对象, 可实现第三方通知微信启动,打开业务页面
+ *
+ * @note 返回的WXOpenBusinessViewReq对象是自动释放的
+ */
+
+@interface WXOpenBusinessViewReq : BaseReq
+
++ (WXOpenBusinessViewReq *)object;
+
+/** 业务类型
+ */
+@property (nonatomic, copy) NSString *businessType;
+
+/** 业务参数
+ */
+@property (nonatomic, copy, nullable) NSString *query;
+
+/** ext信息
+ * @note 选填,json格式
+ */
+@property (nonatomic, copy, nullable) NSString *extInfo;
+
+/** extData数据
+ * @note
+ */
+@property (nonatomic, strong, nullable) NSData *extData;
+@end
+
+
+@interface WXOpenBusinessViewResp : BaseResp
+
+/** 业务类型
+ */
+@property (nonatomic, copy) NSString *businessType;
+
+/** 业务返回数据
+ */
+@property (nonatomic, copy, nullable) NSString *extMsg;
+
+@end
+NS_ASSUME_NONNULL_END
diff --git a/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WechatAuthSDK.h b/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/WechatAuthSDK.h
new file mode 100644 (file)
index 0000000..308aaea
--- /dev/null
@@ -0,0 +1,68 @@
+//
+//  WechatAuthSDK.h
+//  WechatAuthSDK
+//
+//  Created by 李凯 on 13-11-29.
+//  Copyright (c) 2013年 Tencent. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+enum  AuthErrCode {
+    WechatAuth_Err_Ok = 0,  //Auth成功
+    WechatAuth_Err_NormalErr = -1,  //普通错误
+    WechatAuth_Err_NetworkErr = -2, //网络错误
+    WechatAuth_Err_GetQrcodeFailed = -3,    //获取二维码失败
+    WechatAuth_Err_Cancel = -4,     //用户取消授权
+    WechatAuth_Err_Timeout = -5,    //超时
+};
+
+@protocol WechatAuthAPIDelegate<NSObject>
+@optional
+
+- (void)onAuthGotQrcode:(UIImage *)image;  //得到二维码
+- (void)onQrcodeScanned;    //二维码被扫描
+- (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode;    //成功登录
+
+@end
+
+@interface WechatAuthSDK : NSObject{
+    NSString *_sdkVersion;
+    __weak id<WechatAuthAPIDelegate> _delegate;
+}
+
+@property(nonatomic, weak, nullable) id<WechatAuthAPIDelegate> delegate;
+@property(nonatomic, readonly) NSString *sdkVersion;   //authSDK版本号
+
+/*! @brief 发送登录请求,等待WechatAuthAPIDelegate回调
+ *
+ * @param appId 微信开发者ID
+ * @param nonceStr 一个随机的尽量不重复的字符串,用来使得每次的signature不同
+ * @param timeStamp 时间戳
+ * @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔
+ * @param signature 签名
+ * @param schemeData 会在扫码后拼在scheme后
+ * @return 成功返回YES,失败返回NO
+    注:该实现只保证同时只有一个Auth在运行,Auth未完成或未Stop再次调用Auth接口时会返回NO。
+ */
+
+- (BOOL)Auth:(NSString *)appId
+    nonceStr:(NSString *)nonceStr
+   timeStamp:(NSString *)timeStamp
+       scope:(NSString *)scope
+   signature:(NSString *)signature
+  schemeData:(nullable NSString *)schemeData;
+
+
+/*! @brief 暂停登录请求
+ *
+ * @return 成功返回YES,失败返回NO。
+ */
+- (BOOL)StopAuth;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/libWeChatSDK.a b/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/libWeChatSDK.a
new file mode 100644 (file)
index 0000000..ddf18bb
Binary files /dev/null and b/plugins/cordova-plugin-wechat/src/ios/libs/OpenSDK1.8.6.2/libWeChatSDK.a differ
diff --git a/plugins/cordova-plugin-wechat/www/wechat.js b/plugins/cordova-plugin-wechat/www/wechat.js
new file mode 100644 (file)
index 0000000..03458dc
--- /dev/null
@@ -0,0 +1,187 @@
+var exec = require('cordova/exec');
+
+module.exports = {
+    Scene: {
+        SESSION:  0, // 聊天界面
+        TIMELINE: 1, // 朋友圈
+        FAVORITE: 2  // 收藏
+    },
+
+    Type: {
+        APP:     1,
+        EMOTION: 2,
+        FILE:    3,
+        IMAGE:   4,
+        MUSIC:   5,
+        VIDEO:   6,
+        WEBPAGE: 7,
+        MINI:    8
+    },
+
+    Mini: {
+        RELEASE: 0, // 正式版
+        TEST:    1, // 测试版
+        PREVIEW: 2  // 体验版
+    },
+
+    isInstalled: function (onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "isWXAppInstalled", []);
+    },
+
+    /**
+     * Share a message to wechat app
+     *
+     * @example
+     * <code>
+     * Wechat.share({
+     *     message: {
+     *        title: "Message Title",
+     *        description: "Message Description(optional)",
+     *        mediaTagName: "Media Tag Name(optional)",
+     *        thumb: "http://YOUR_THUMBNAIL_IMAGE",
+     *        media: {
+     *            type: Wechat.Type.WEBPAGE,   // webpage
+     *            webpageUrl: "https://github.com/xu-li/cordova-plugin-wechat"    // webpage
+     *        }
+     *    },
+     *    scene: Wechat.Scene.TIMELINE   // share to Timeline
+     * }, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    share: function (message, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "share", [message]);
+    },
+
+    /**
+     * Sending an auth request to Wechat
+     *
+     * @example
+     * <code>
+     * Wechat.auth(function (response) { alert(response.code); });
+     * </code>
+     */
+    auth: function (scope, state, onSuccess, onError) {
+        if (typeof scope == "function") {
+            // Wechat.auth(function () { alert("Success"); });
+            // Wechat.auth(function () { alert("Success"); }, function (error) { alert(error); });
+            return exec(scope, state, "Wechat", "sendAuthRequest");
+        }
+
+        if (typeof state == "function") {
+            // Wechat.auth("snsapi_userinfo", function () { alert("Success"); });
+            // Wechat.auth("snsapi_userinfo", function () { alert("Success"); }, function (error) { alert(error); });
+            return exec(state, onSuccess, "Wechat", "sendAuthRequest", [scope]);
+        }
+
+        return exec(onSuccess, onError, "Wechat", "sendAuthRequest", [scope, state]);
+    },
+
+    /**
+     * Send a payment request
+     *
+     * @link https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1
+     * @example
+     * <code>
+     * var params = {
+     *     mch_id: '10000100', // merchant id
+     *     prepay_id: 'wx201411101639507cbf6ffd8b0779950874', // prepay id returned from server
+     *     nonce: '1add1a30ac87aa2db72f57a2375d8fec', // nonce string returned from server
+     *     timestamp: '1439531364', // timestamp
+     *     sign: '0CB01533B8C1EF103065174F50BCA001', // signed string
+     * };
+     * Wechat.sendPaymentRequest(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    sendPaymentRequest: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "sendPaymentRequest", [params]);
+    },
+
+    /**
+     * jumpToBizProfile (跳转到某个微信公众号)2016-11-11 测试是失效的,囧
+     *
+     * @link https://segmentfault.com/a/1190000007204624
+     * @link https://segmentfault.com/q/1010000003907796
+     * @example
+     * <code>
+     * var params = {
+     *     info: 'gh_xxxxxxx', // 公众帐号原始ID
+     *     type:  'Normal' // 普通号
+     * }
+     * or
+     * var params = {
+     *     info: 'extMsg', // 相关的硬件二维码串
+     *     type:  'Device' // 硬件号
+     * };
+     * Wechat.jumpToBizProfile(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+
+    jumpToBizProfile: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "jumpToBizProfile", [params]);
+    },
+
+    /**
+     * jumpToWechat (因为jumpToBizProfile失效了,暂时新增了一个临时的api)
+     *
+     * @link https://segmentfault.com/a/1190000007204624
+     * @example
+     * <code>
+     * var url = "wechat://" 现阶段貌似只支持这一个协议了
+     * Wechat.jumpToWechat(url, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    jumpToWechat: function (url, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "jumpToWechat", [url]);
+    },
+
+    /**
+     * chooseInvoiceFromWX exq:choose invoices from Wechat card list
+     *
+     * @example
+     * <code>
+     * params: signType, cardSign, nonceStr, timeStamp  all required
+     * Wechat.chooseInvoiceFromWX(params, function () {
+     *     alert("Success");
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    chooseInvoiceFromWX: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "chooseInvoiceFromWX", [params]);
+    },
+
+    /**
+     * openMiniProgram exq:app opens wechat mini program
+     *
+     * @example
+     * <code>
+     * params: userName, path, miniprogramType  all required
+     * Wechat.openMiniProgram(params, function (data) {
+     *     alert(data.extMsg);
+     * }, function (reason) {
+     *     alert("Failed: " + reason);
+     * });
+     * </code>
+     */
+    openMiniProgram: function (params, onSuccess, onError) {
+        exec(onSuccess, onError, "Wechat", "openMiniProgram", [params]);
+    }
+
+};
index da1b22c..9d45ae0 100644 (file)
     "variables": {
       "QQ_APP_ID": "101885581"
     }
+  },
+  "cordova-plugin-wechat": {
+    "source": {
+      "type": "registry",
+      "id": "git+https://github.com/xu-li/cordova-plugin-wechat.git"
+    },
+    "is_top_level": true,
+    "variables": {
+      "WECHATAPPID": "wxa483e2c392b08993",
+      "UNIVERSALLINK": "YOUR_UNIVERSAL_LINK"
+    }
   }
 }
\ No newline at end of file
index dfbd223..401f770 100644 (file)
     "cordova-plugin-qqsdk": {
       "QQ_APP_ID": "101885581",
       "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-wechat": {
+      "WECHATAPPID": "wxa483e2c392b08993",
+      "UNIVERSALLINK": "YOUR_UNIVERSAL_LINK",
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
     }
   },
   "dependent_plugins": {
index 8cced49..d9dcb90 100644 (file)
 <!doctype html>
 <html>
 
-<head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
-    <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
-    <link rel="stylesheet" type="text/css" href="css/aui.css" />
-    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
-    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
-    <link rel="stylesheet" type="text/css" href="css/index.css" />
-    <link rel="stylesheet" type="text/css" href="css/aui-slide.css">
-    <style type="text/css">
-        .aui-slide-node{
-            /*background: transparent!important;*/
-        }
-    </style>
-</head>
-<body>
-    <div id="main1">
-        <div id="maintop">
-            <div id="startslider" class="main" style="height: 240px;display: block;">
-                <div class="aui-slide-wrap" >
-                    <div class="aui-slide-node" style="padding:36px 30px 30px 30px;background-color: #ACEAF5" >
-                        <img src="img/p1.png"  style="background-color: #ACEAF5"/>
-                    </div>
-                    <div class="aui-slide-node" style="padding:36px 30px 30px 30px;background-color: #a4e4d4">
-                        <img src="img/p2.png"  style="background-color: #a4e4d4"/>
-                    </div>
-                    <div class="aui-slide-node " style="padding:36px 30px 30px 30px;background-color: #65abe7">
-                        <img src="img/p3.png"  style="background-color: #65abe7"/>
-                    </div>
-                    <div class="aui-slide-node " style="padding:36px 30px 30px 30px;background-color: #357a8a">
-                        <img src="img/p4.png"  style="background-color: #357a8a"/>
-                    </div>
-                </div>
-                <div class="aui-slide-page-wrap"><!--分页容器--></div>
-            </div>
-        </div>
-        <div style="position: absolute;bottom:50px;width: 100%;top:240px" id="maincontent">
-            <section class="aui-content " style="height: 100%">
-                <div class="aui-grid" style="height: 100%">
-                    <div class="aui-row" style="height: 50%">
-                        <div class="aui-col-xs-6  mainmeun-div" id="qrcodeBtn" style="background: #BBE6EC;">
-                            <div>
-                                <div class="center-in"><img src="img/m4.png" class="meun-img"class="meun-img"></div>
-                                <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">读码</div>
-                            </div>
-                        </div>
-                        <div class="aui-col-xs-6 mainmeun-div" id="scanBtn" style="background: #91DDEA;">
-                            <div>
-                                <div class="center-in"><img src="img/m2.png" class="meun-img"></div>
-                                <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">扫码</div>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="aui-row" style="height: 50%">
-                        <div class="aui-col-xs-6 mainmeun-div" id="qrcodeBtn1" style="background: #fff;">
-                            <div>
-                                <div class="center-in"><img src="img/m3.png" class="meun-img"></div>
-                                <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">访码</div>
-                            </div>
-                        </div>
-                        <div class="aui-col-xs-6 mainmeun-div" id="moreFuncBtn"  style="background: #FDD479;">
-                            <div>
-                                <div class="center-in"><img src="img/m1.png" class="meun-img"></div>
-                                <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">更多</div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </section>
-        </div>
-    </div>
-    <div id="main2" style="display: none">
-        <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
-            消息
-        </header>
-        <section class="aui-content">
-             <div class="weui-loadmore weui-loadmore_line"   >
-                <span class="weui-loadmore__tips" style="background: transparent;" id="nodatahint">暂无消息</span>
-            </div>
-        </section>
-    </div>
-    <div id="main3" style="display: none;">
-        <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
-            我的
-        </header>
-        <!-- bg-white -->
-        <section class="aui-content aui-margin-b-15" style=" margin-top: -2px;">
-            <div class="aui-list aui-media-list aui-list-noborder aui-bg-info user-info">
-                <div class="aui-list-item aui-list-item-middle top-btn">
-                    <div class="aui-media-list-item-inner ">
-                        <div class="aui-list-item-media" style="width:3rem;">
-                            <img src="img/icon_header.png" class="aui-img-round" id="userlogo">
-                        </div>
-                        <div class="aui-list-item-inner">
-                            <div class="aui-list-item-text text-white aui-font-size-18" id="username">匿名</div>
-                            <div class="aui-list-item-text text-white">
-                                <div><i class="aui-iconfont aui-icon-mobile aui-font-size-14"></i><span id="userphone"></span></div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </section>
-        <section class="aui-content">
-            <ul class="aui-list aui-list-in aui-margin-b-15">
-                <li class="aui-list-item" onclick="app.toCard()">
-                    <div class="aui-list-item-label-icon">
-                        <i class="aui-iconfont aui-icon-cert aui-text-info"></i>
-                    </div>
-                    <div class="aui-list-item-inner aui-list-item-arrow">
-                        <div class="aui-list-item-title">市民卡签约</div>
-                        <div class="aui-list-item-right" id="usersign"></div>
-                    </div>
-                </li>
-                <!--<li class="aui-list-item" id="accsignbtn">-->
-                    <!--<div class="aui-list-item-label-icon">-->
-                        <!--<i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>-->
-                    <!--</div>-->
-                    <!--<div class="aui-list-item-inner aui-list-item-arrow">-->
-                        <!--<div class="aui-list-item-title">签约代扣免密付</div>-->
-                        <!--<div class="aui-list-item-right" id="usersign"></div>-->
-                    <!--</div>-->
-                <!--</li>-->
-            </ul>
-            <ul class="aui-list aui-list-in aui-margin-b-15">
-                <li class="aui-list-item" id="usersec">
-                    <div class="aui-list-item-label-icon">
-                        <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
-                    </div>
-                    <div class="aui-list-item-inner aui-list-item-arrow">
-                        <div class="aui-list-item-title">账户安全</div>
-                    </div>
-                </li>
-            </ul>
-            <ul class="aui-list aui-list-in">
-                <li class="aui-list-item" id="usersec"  onclick="app.verisonCheck()">
-                    <div class="aui-list-item-label-icon">
-                        <i class="aui-iconfont aui-icon-info aui-text-info"></i>
-                    </div>
-                    <div class="aui-list-item-inner aui-list-item-arrow">
-                        <div class="aui-list-item-title">版本检测</div>
-                        <div class="aui-list-item-right" id="versioncheck">
-                        </div>
-                    </div>
-                </li>
-            </ul>
-                       <ul class="aui-list aui-list-in">
-                           <li class="aui-list-item" id="share" >
-                               <div class="aui-list-item-label-icon">
-                                   <i class="aui-iconfont aui-icon-info aui-text-info"></i>
-                               </div>
-                               <div class="aui-list-item-inner aui-list-item-arrow">
-                                   <div class="aui-list-item-title">分享测试</div>
-                                   <div class="aui-list-item-right" id="versioncheck">
-                                   </div>
-                               </div>
-                           </li>
-                       </ul>
-            <div style="padding: 20px;margin-top: 40px;">
-                <a href="javascript:app.logout();" class="weui-btn weui-btn_warn">退出登录</a>
-            </div>
-        </section>
-    </div>
-    <footer class="aui-bar aui-bar-tab aui-border-t" id="footer">
-        <div class="aui-bar-tab-item aui-active" tapmode onclick="switchTo(1)" id="tab1">
-            <i class="aui-iconfont aui-icon-home"></i>
-            <div class="aui-bar-tab-label">首页</div>
-        </div>
-        <div class="aui-bar-tab-item" tapmode onclick="switchTo(2)" id="tab2">
-            <i class="aui-iconfont aui-icon-comment"></i>
-            <div class="aui-bar-tab-label">消息</div>
-        </div>
-        <div class="aui-bar-tab-item" tapmode onclick="switchTo(3)" id="tab3">
-            <i class="aui-iconfont aui-icon-my"></i>
-            <div class="aui-bar-tab-label">我的</div>
-        </div>
-    </footer>
-</body>
-<script type="text/javascript" src="cordova.js"></script>
-<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
-<script type="text/javascript" src="js/lib/aui-tab.js"></script>
-<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
-<script type="text/javascript" src="js/lib/aui-slide.js"></script>
-<script type="text/javascript" src="js/server.js"></script>
-<script type="text/javascript" src="js/mainmenu.js"></script>
-<script type="text/javascript">
-var share = document.getElementById("share")
-       share.onclick=function(){
-               var args = {};
-               args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM;
-               args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite
-               args.url = 'https://cordova.apache.org/';
-               args.title = '这个是 Cordova QQ 新闻分享的标题';
-               args.description = '这个是 Cordova QQ 新闻分享的描述';
-               args.image = 'https://cordova.apache.org/static/img/cordova_bot.png';
-               QQSDK.shareNews(function () {
-                 alert('shareNews success');
-               }, function (failReason) {
-                 alert(failReason);
-               }, args);
-       }
-</script>
-</html>
\ No newline at end of file
+       <head>
+               <meta charset="utf-8">
+               <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
+               <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
+               <link rel="stylesheet" type="text/css" href="css/aui.css" />
+               <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+               <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+               <link rel="stylesheet" type="text/css" href="css/index.css" />
+               <link rel="stylesheet" type="text/css" href="css/aui-slide.css">
+               <style type="text/css">
+                       .aui-slide-node {
+                               /*background: transparent!important;*/
+                       }
+               </style>
+       </head>
+       <body>
+               <div id="main1">
+                       <div id="maintop">
+                               <div id="startslider" class="main" style="height: 240px;display: block;">
+                                       <div class="aui-slide-wrap">
+                                               <div class="aui-slide-node" style="padding:36px 30px 30px 30px;background-color: #ACEAF5">
+                                                       <img src="img/p1.png" style="background-color: #ACEAF5" />
+                                               </div>
+                                               <div class="aui-slide-node" style="padding:36px 30px 30px 30px;background-color: #a4e4d4">
+                                                       <img src="img/p2.png" style="background-color: #a4e4d4" />
+                                               </div>
+                                               <div class="aui-slide-node " style="padding:36px 30px 30px 30px;background-color: #65abe7">
+                                                       <img src="img/p3.png" style="background-color: #65abe7" />
+                                               </div>
+                                               <div class="aui-slide-node " style="padding:36px 30px 30px 30px;background-color: #357a8a">
+                                                       <img src="img/p4.png" style="background-color: #357a8a" />
+                                               </div>
+                                       </div>
+                                       <div class="aui-slide-page-wrap">
+                                               <!--分页容器-->
+                                       </div>
+                               </div>
+                       </div>
+                       <div style="position: absolute;bottom:50px;width: 100%;top:240px" id="maincontent">
+                               <section class="aui-content " style="height: 100%">
+                                       <div class="aui-grid" style="height: 100%">
+                                               <div class="aui-row" style="height: 50%">
+                                                       <div class="aui-col-xs-6  mainmeun-div" id="qrcodeBtn" style="background: #BBE6EC;">
+                                                               <div>
+                                                                       <div class="center-in"><img src="img/m4.png" class="meun-img" class="meun-img"></div>
+                                                                       <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">读码</div>
+                                                               </div>
+                                                       </div>
+                                                       <div class="aui-col-xs-6 mainmeun-div" id="scanBtn" style="background: #91DDEA;">
+                                                               <div>
+                                                                       <div class="center-in"><img src="img/m2.png" class="meun-img"></div>
+                                                                       <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">扫码</div>
+                                                               </div>
+                                                       </div>
+                                               </div>
+                                               <div class="aui-row" style="height: 50%">
+                                                       <div class="aui-col-xs-6 mainmeun-div" id="qrcodeBtn1" style="background: #fff;">
+                                                               <div>
+                                                                       <div class="center-in"><img src="img/m3.png" class="meun-img"></div>
+                                                                       <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">访码</div>
+                                                               </div>
+                                                       </div>
+                                                       <div class="aui-col-xs-6 mainmeun-div" id="moreFuncBtn" style="background: #FDD479;">
+                                                               <div>
+                                                                       <div class="center-in"><img src="img/m1.png" class="meun-img"></div>
+                                                                       <div class="aui-grid-label" style="margin-top:10px;font-size: 22px;">更多</div>
+                                                               </div>
+                                                       </div>
+                                               </div>
+                                       </div>
+                               </section>
+                       </div>
+               </div>
+               <div id="main2" style="display: none">
+                       <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
+                               消息
+                       </header>
+                       <section class="aui-content">
+                               <div class="weui-loadmore weui-loadmore_line">
+                                       <span class="weui-loadmore__tips" style="background: transparent;" id="nodatahint">暂无消息</span>
+                               </div>
+                       </section>
+               </div>
+               <div id="main3" style="display: none;">
+                       <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
+                               我的
+                       </header>
+                       <!-- bg-white -->
+                       <section class="aui-content aui-margin-b-15" style=" margin-top: -2px;">
+                               <div class="aui-list aui-media-list aui-list-noborder aui-bg-info user-info">
+                                       <div class="aui-list-item aui-list-item-middle top-btn">
+                                               <div class="aui-media-list-item-inner ">
+                                                       <div class="aui-list-item-media" style="width:3rem;">
+                                                               <img src="img/icon_header.png" class="aui-img-round" id="userlogo">
+                                                       </div>
+                                                       <div class="aui-list-item-inner">
+                                                               <div class="aui-list-item-text text-white aui-font-size-18" id="username">匿名</div>
+                                                               <div class="aui-list-item-text text-white">
+                                                                       <div><i class="aui-iconfont aui-icon-mobile aui-font-size-14"></i><span id="userphone"></span></div>
+                                                               </div>
+                                                       </div>
+                                               </div>
+                                       </div>
+                               </div>
+                       </section>
+                       <section class="aui-content">
+                               <ul class="aui-list aui-list-in aui-margin-b-15">
+                                       <li class="aui-list-item" onclick="app.toCard()">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-cert aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">市民卡签约</div>
+                                                       <div class="aui-list-item-right" id="usersign"></div>
+                                               </div>
+                                       </li>
+                                       <!--<li class="aui-list-item" id="accsignbtn">-->
+                                       <!--<div class="aui-list-item-label-icon">-->
+                                       <!--<i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>-->
+                                       <!--</div>-->
+                                       <!--<div class="aui-list-item-inner aui-list-item-arrow">-->
+                                       <!--<div class="aui-list-item-title">签约代扣免密付</div>-->
+                                       <!--<div class="aui-list-item-right" id="usersign"></div>-->
+                                       <!--</div>-->
+                                       <!--</li>-->
+                               </ul>
+                               <ul class="aui-list aui-list-in aui-margin-b-15">
+                                       <li class="aui-list-item" id="usersec">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">账户安全</div>
+                                               </div>
+                                       </li>
+                               </ul>
+                               <ul class="aui-list aui-list-in">
+                                       <li class="aui-list-item" id="usersec" onclick="app.verisonCheck()">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-info aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">版本检测</div>
+                                                       <div class="aui-list-item-right" id="versioncheck">
+                                                       </div>
+                                               </div>
+                                       </li>
+                               </ul>
+                               <ul class="aui-list aui-list-in">
+                                       <li class="aui-list-item" id="shareqq">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-info aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">qq分享测试</div>
+                                                       <div class="aui-list-item-right" id="versioncheck">
+                                                       </div>
+                                               </div>
+                                       </li>
+                               </ul>
+                               <ul class="aui-list aui-list-in">
+                                       <li class="aui-list-item" id="sharewx">
+                                               <div class="aui-list-item-label-icon">
+                                                       <i class="aui-iconfont aui-icon-info aui-text-info"></i>
+                                               </div>
+                                               <div class="aui-list-item-inner aui-list-item-arrow">
+                                                       <div class="aui-list-item-title">wx分享测试</div>
+                                                       <div class="aui-list-item-right" id="versioncheck">
+                                                       </div>
+                                               </div>
+                                       </li>
+                               </ul>
+                               <div style="padding: 20px;margin-top: 40px;">
+                                       <a href="javascript:app.logout();" class="weui-btn weui-btn_warn">退出登录</a>
+                               </div>
+                       </section>
+               </div>
+               <footer class="aui-bar aui-bar-tab aui-border-t" id="footer">
+                       <div class="aui-bar-tab-item aui-active" tapmode onclick="switchTo(1)" id="tab1">
+                               <i class="aui-iconfont aui-icon-home"></i>
+                               <div class="aui-bar-tab-label">首页</div>
+                       </div>
+                       <div class="aui-bar-tab-item" tapmode onclick="switchTo(2)" id="tab2">
+                               <i class="aui-iconfont aui-icon-comment"></i>
+                               <div class="aui-bar-tab-label">消息</div>
+                       </div>
+                       <div class="aui-bar-tab-item" tapmode onclick="switchTo(3)" id="tab3">
+                               <i class="aui-iconfont aui-icon-my"></i>
+                               <div class="aui-bar-tab-label">我的</div>
+                       </div>
+               </footer>
+       </body>
+       <script type="text/javascript" src="cordova.js"></script>
+       <script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+       <script type="text/javascript" src="js/lib/aui-tab.js"></script>
+       <script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+       <script type="text/javascript" src="js/lib/aui-slide.js"></script>
+       <script type="text/javascript" src="js/server.js"></script>
+       <script type="text/javascript" src="js/mainmenu.js"></script>
+       <script type="text/javascript">
+               var shareqq = document.getElementById("shareqq");
+               var sharewx = document.getElementById("sharewx");
+               shareqq.onclick = function() {
+                       var args = {};
+                       args.client = QQSDK.ClientType.QQ; //QQSDK.ClientType.QQ,QQSDK.ClientType.TIM;
+                       args.scene = QQSDK.Scene.QQ; //QQSDK.Scene.QQZone,QQSDK.Scene.Favorite
+                       args.url = 'https://cordova.apache.org/';
+                       args.title = '这个是 Cordova QQ 新闻分享的标题';
+                       args.description = '这个是 Cordova QQ 新闻分享的描述';
+                       args.image = 'https://cordova.apache.org/static/img/cordova_bot.png';
+                       QQSDK.shareNews(function() {
+                               alert('shareNews success');
+                       }, function(failReason) {
+                               alert(failReason);
+                       }, args);
+               }
+               sharewx.onclick = function() {
+                       Wechat.share({
+                           message: {
+                               title: "Hi, there",
+                               description: "This is description.",
+                               thumb: "www/img/thumbnail.png",
+                               mediaTagName: "TEST-TAG-001",
+                               messageExt: "这是第三方带的测试字段",
+                               messageAction: "<action>dotalist</action>",
+                               media: {
+                                           type: Wechat.Type.WEBPAGE,
+                                           webpageUrl: "http://www.jason-z.com"
+                                       }
+                           },
+                           scene: Wechat.Scene.TIMELINE   // share to Timeline
+                       }, function () {
+                           alert("Success");
+                       }, function (reason) {
+                           alert("Failed: " + reason);
+                       });
+               }
+       </script>
+</html>