From 784d1f33eacc54c8fe14396f49196676f062fb6b Mon Sep 17 00:00:00 2001 From: jinyu Date: Mon, 27 Apr 2015 21:02:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E9=87=8D=E6=9E=84=EF=BC=9Aweixin4j?= =?UTF-8?q?=E7=B2=BE=E7=AE=80=E4=B8=BAweixin4j-base=E3=80=81weixin4j-mp?= =?UTF-8?q?=E3=80=81weixin4j-qy=E3=80=81weixin4j-server=E5=9B=9B=E4=B8=AA?= =?UTF-8?q?=E5=AD=90=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin4j-base/CHANGE.md | 51 + .../com/foxinmy/weixin4j/tuple/Tuple.java | 27 + .../com/foxinmy/weixin4j/util/Pageable.java | 90 ++ .../com/foxinmy/weixin4j/util/Pagedata.java | 67 + .../java/com/foxinmy/weixin4j/util/Sort.java | 65 + weixin4j-mp/CHANGE.md | 111 ++ weixin4j-mp/src/main/assembly.xml | 31 + .../foxinmy/weixin4j/mp/WeixinPayProxy.java | 624 ++++++++ .../com/foxinmy/weixin4j/mp/WeixinProxy.java | 1333 +++++++++++++++++ .../com/foxinmy/weixin4j/mp/api/CashApi.java | 146 ++ .../foxinmy/weixin4j/mp/api/CouponApi.java | 169 +++ .../foxinmy/weixin4j/mp/api/CustomApi.java | 357 +++++ .../com/foxinmy/weixin4j/mp/api/DataApi.java | 133 ++ .../com/foxinmy/weixin4j/mp/api/GroupApi.java | 189 +++ .../foxinmy/weixin4j/mp/api/HelperApi.java | 234 +++ .../com/foxinmy/weixin4j/mp/api/MassApi.java | 324 ++++ .../com/foxinmy/weixin4j/mp/api/MediaApi.java | 474 ++++++ .../com/foxinmy/weixin4j/mp/api/MenuApi.java | 114 ++ .../com/foxinmy/weixin4j/mp/api/MpApi.java | 28 + .../foxinmy/weixin4j/mp/api/NotifyApi.java | 86 ++ .../com/foxinmy/weixin4j/mp/api/OauthApi.java | 173 +++ .../com/foxinmy/weixin4j/mp/api/Pay2Api.java | 466 ++++++ .../com/foxinmy/weixin4j/mp/api/Pay3Api.java | 470 ++++++ .../com/foxinmy/weixin4j/mp/api/PayApi.java | 213 +++ .../com/foxinmy/weixin4j/mp/api/QrApi.java | 122 ++ .../com/foxinmy/weixin4j/mp/api/README.md | 31 + .../com/foxinmy/weixin4j/mp/api/TmplApi.java | 99 ++ .../com/foxinmy/weixin4j/mp/api/UserApi.java | 165 ++ .../foxinmy/weixin4j/mp/api/weixin.properties | 181 +++ .../mp/datacube/ArticleDatacube1.java | 133 ++ .../mp/datacube/ArticleDatacube2.java | 51 + .../mp/datacube/ArticleDatacubeShare.java | 101 ++ .../weixin4j/mp/datacube/ArticleSummary.java | 76 + .../weixin4j/mp/datacube/ArticleTotal.java | 77 + .../mp/datacube/InterfaceSummary.java | 107 ++ .../weixin4j/mp/datacube/UpstreamMsg.java | 108 ++ .../weixin4j/mp/datacube/UpstreamMsgDist.java | 66 + .../weixin4j/mp/datacube/UserSummary.java | 105 ++ .../weixin4j/mp/message/NotifyMessage.java | 60 + .../com/foxinmy/weixin4j/mp/message/README.md | 3 + .../weixin4j/mp/message/TemplateMessage.java | 144 ++ .../weixin4j/mp/model/AutoReplySetting.java | 260 ++++ .../weixin4j/mp/model/CustomRecord.java | 92 ++ .../foxinmy/weixin4j/mp/model/Following.java | 100 ++ .../com/foxinmy/weixin4j/mp/model/Group.java | 104 ++ .../foxinmy/weixin4j/mp/model/KfAccount.java | 126 ++ .../foxinmy/weixin4j/mp/model/KfSession.java | 66 + .../weixin4j/mp/model/MediaCounter.java | 79 + .../foxinmy/weixin4j/mp/model/MediaItem.java | 80 + .../weixin4j/mp/model/MediaRecord.java | 81 + .../weixin4j/mp/model/MenuSetting.java | 48 + .../foxinmy/weixin4j/mp/model/OauthToken.java | 64 + .../weixin4j/mp/model/QRParameter.java | 119 ++ .../foxinmy/weixin4j/mp/model/SemQuery.java | 128 ++ .../foxinmy/weixin4j/mp/model/SemResult.java | 100 ++ .../com/foxinmy/weixin4j/mp/model/User.java | 215 +++ .../weixin4j/mp/payment/JsPayNotify.java | 56 + .../weixin4j/mp/payment/MicroPayPackage.java | 117 ++ .../weixin4j/mp/payment/PayBaseInfo.java | 111 ++ .../weixin4j/mp/payment/PayPackage.java | 225 +++ .../weixin4j/mp/payment/PayRequest.java | 40 + .../foxinmy/weixin4j/mp/payment/PayUtil.java | 457 ++++++ .../com/foxinmy/weixin4j/mp/payment/README.md | 54 + .../foxinmy/weixin4j/mp/payment/cacert.pem | 21 + .../mp/payment/conver/CouponConverter.java | 135 ++ .../mp/payment/conver/RefundConverter.java | 190 +++ .../mp/payment/coupon/CouponDetail.java | 371 +++++ .../mp/payment/coupon/CouponInfo.java | 71 + .../mp/payment/coupon/CouponResult.java | 117 ++ .../mp/payment/coupon/CouponStock.java | 296 ++++ .../weixin4j/mp/payment/v2/ApiResult.java | 124 ++ .../mp/payment/v2/JsPayRequestV2.java | 64 + .../mp/payment/v2/NativePayNotifyV2.java | 38 + .../mp/payment/v2/NativePayResponseV2.java | 58 + .../foxinmy/weixin4j/mp/payment/v2/Order.java | 319 ++++ .../weixin4j/mp/payment/v2/PayFeedback.java | 100 ++ .../weixin4j/mp/payment/v2/PayPackageV2.java | 146 ++ .../weixin4j/mp/payment/v2/PayWarn.java | 54 + .../weixin4j/mp/payment/v2/RefundDetail.java | 144 ++ .../weixin4j/mp/payment/v2/RefundRecord.java | 72 + .../weixin4j/mp/payment/v2/RefundResult.java | 46 + .../weixin4j/mp/payment/v3/ApiResult.java | 137 ++ .../weixin4j/mp/payment/v3/MPPayment.java | 120 ++ .../mp/payment/v3/MPPaymentResult.java | 56 + .../mp/payment/v3/NativePayNotifyV3.java | 38 + .../mp/payment/v3/NativePayResponseV3.java | 79 + .../foxinmy/weixin4j/mp/payment/v3/Order.java | 256 ++++ .../weixin4j/mp/payment/v3/PayPackageV3.java | 149 ++ .../weixin4j/mp/payment/v3/PayRequestV3.java | 36 + .../weixin4j/mp/payment/v3/PrePay.java | 75 + .../weixin4j/mp/payment/v3/Redpacket.java | 272 ++++ .../mp/payment/v3/RedpacketSendResult.java | 87 ++ .../weixin4j/mp/payment/v3/RefundDetail.java | 278 ++++ .../weixin4j/mp/payment/v3/RefundRecord.java | 183 +++ .../weixin4j/mp/payment/v3/RefundResult.java | 46 + .../com/foxinmy/weixin4j/mp/spider/README.md | 3 + .../weixin4j/mp/spider/WeixinExecutor.java | 666 ++++++++ .../mp/token/WeixinJSTicketCreator.java | 58 + .../weixin4j/mp/token/WeixinTokenCreator.java | 58 + .../weixin4j/mp/type/AutomatchMode.java | 21 + .../weixin4j/mp/type/AutoreplyMode.java | 21 + .../foxinmy/weixin4j/mp/type/BillType.java | 34 + .../weixin4j/mp/type/CouponStatus.java | 34 + .../weixin4j/mp/type/CouponStockStatus.java | 42 + .../weixin4j/mp/type/CouponStockType.java | 30 + .../foxinmy/weixin4j/mp/type/CouponType.java | 34 + .../weixin4j/mp/type/CurrencyType.java | 23 + .../mp/type/CustomRecordOperCode.java | 45 + .../weixin4j/mp/type/DatacubeType.java | 110 ++ .../mp/type/DatacuteCountIntervalType.java | 29 + .../foxinmy/weixin4j/mp/type/EventType.java | 55 + .../foxinmy/weixin4j/mp/type/FaceSize.java | 38 + .../com/foxinmy/weixin4j/mp/type/IdQuery.java | 53 + .../com/foxinmy/weixin4j/mp/type/IdType.java | 38 + .../weixin4j/mp/type/IndustryType.java | 59 + .../weixin4j/mp/type/KfOnlineStatus.java | 29 + .../com/foxinmy/weixin4j/mp/type/Lang.java | 23 + .../mp/type/MPPaymentCheckNameType.java | 25 + .../com/foxinmy/weixin4j/mp/type/QRType.java | 25 + .../weixin4j/mp/type/RefundChannel.java | 29 + .../weixin4j/mp/type/RefundStatus.java | 34 + .../foxinmy/weixin4j/mp/type/RefundType.java | 35 + .../foxinmy/weixin4j/mp/type/SemCategory.java | 73 + .../weixin4j/mp/type/ShareSourceType.java | 29 + .../foxinmy/weixin4j/mp/type/SignType.java | 13 + .../foxinmy/weixin4j/mp/type/TradeState.java | 45 + .../foxinmy/weixin4j/mp/type/TradeType.java | 29 + .../weixin4j/mp/type/UserSourceType.java | 24 + .../foxinmy/weixin4j/mp/util/ExcelUtil.java | 438 ++++++ .../src/main/resources/weixin.properties | 23 + .../foxinmy/weixin4j/mp/test/CashTest.java | 50 + .../foxinmy/weixin4j/mp/test/CouponTest.java | 60 + .../foxinmy/weixin4j/mp/test/DataApiTest.java | 104 ++ .../foxinmy/weixin4j/mp/test/GroupTest.java | 76 + .../foxinmy/weixin4j/mp/test/HelpTest.java | 35 + .../foxinmy/weixin4j/mp/test/MediaTest.java | 138 ++ .../foxinmy/weixin4j/mp/test/MenuTest.java | 84 ++ .../com/foxinmy/weixin4j/mp/test/PayTest.java | 175 +++ .../com/foxinmy/weixin4j/mp/test/QRTest.java | 47 + .../weixin4j/mp/test/SemanticTest.java | 27 + .../foxinmy/weixin4j/mp/test/TokenTest.java | 54 + .../foxinmy/weixin4j/mp/test/UserTest.java | 53 + .../weixin4j/mp/test/msg/AesMsgTest.java | 64 + .../weixin4j/mp/test/msg/CustomTest.java | 121 ++ .../weixin4j/mp/test/msg/EventMsgTest.java | 179 +++ .../weixin4j/mp/test/msg/InMsgTest.java | 144 ++ .../weixin4j/mp/test/msg/MassMsgTest.java | 113 ++ .../weixin4j/mp/test/msg/MessagePush.java | 68 + .../weixin4j/mp/test/msg/NotifyMsgTest.java | 101 ++ .../weixin4j/mp/test/msg/TemplateMsgTest.java | 41 + weixin4j-qy/CHANGE.md | 51 + weixin4j-qy/src/main/assembly.xml | 31 + .../com/foxinmy/weixin4j/qy/WeixinProxy.java | 807 ++++++++++ .../com/foxinmy/weixin4j/qy/api/AgentApi.java | 118 ++ .../com/foxinmy/weixin4j/qy/api/BatchApi.java | 172 +++ .../foxinmy/weixin4j/qy/api/HelperApi.java | 43 + .../com/foxinmy/weixin4j/qy/api/MediaApi.java | 252 ++++ .../com/foxinmy/weixin4j/qy/api/MenuApi.java | 121 ++ .../foxinmy/weixin4j/qy/api/NotifyApi.java | 81 + .../com/foxinmy/weixin4j/qy/api/PartyApi.java | 111 ++ .../com/foxinmy/weixin4j/qy/api/QyApi.java | 28 + .../com/foxinmy/weixin4j/qy/api/TagApi.java | 178 +++ .../com/foxinmy/weixin4j/qy/api/UserApi.java | 281 ++++ .../foxinmy/weixin4j/qy/api/weixin.properties | 81 + .../weixin4j/qy/event/ScribeEventMessage.java | 28 + .../weixin4j/qy/message/NotifyMessage.java | 157 ++ .../foxinmy/weixin4j/qy/model/AgentInfo.java | 109 ++ .../weixin4j/qy/model/AgentOverview.java | 67 + .../weixin4j/qy/model/AgentSetter.java | 135 ++ .../weixin4j/qy/model/BatchResult.java | 99 ++ .../foxinmy/weixin4j/qy/model/Callback.java | 52 + .../weixin4j/qy/model/IdParameter.java | 64 + .../foxinmy/weixin4j/qy/model/NameValue.java | 48 + .../com/foxinmy/weixin4j/qy/model/Party.java | 87 ++ .../com/foxinmy/weixin4j/qy/model/Tag.java | 60 + .../com/foxinmy/weixin4j/qy/model/User.java | 262 ++++ .../qy/token/WeixinJSTicketCreator.java | 55 + .../weixin4j/qy/token/WeixinTokenCreator.java | 58 + .../foxinmy/weixin4j/qy/type/BatchStatus.java | 34 + .../foxinmy/weixin4j/qy/type/BatchType.java | 39 + .../foxinmy/weixin4j/qy/type/EventType.java | 25 + .../foxinmy/weixin4j/qy/type/InviteType.java | 21 + .../weixin4j/qy/type/ReportLocationType.java | 25 + .../foxinmy/weixin4j/qy/type/UserStatus.java | 38 + .../src/main/resources/weixin.properties | 10 + .../foxinmy/weixin4j/qy/test/AesMsgTest.java | 64 + .../foxinmy/weixin4j/qy/test/AgentTest.java | 56 + .../foxinmy/weixin4j/qy/test/BatchTest.java | 61 + .../foxinmy/weixin4j/qy/test/HelperTest.java | 35 + .../foxinmy/weixin4j/qy/test/MediaTest.java | 50 + .../foxinmy/weixin4j/qy/test/MenuTest.java | 63 + .../foxinmy/weixin4j/qy/test/MessagePush.java | 68 + .../weixin4j/qy/test/NotifyMsgTest.java | 93 ++ .../foxinmy/weixin4j/qy/test/PartyTest.java | 58 + .../com/foxinmy/weixin4j/qy/test/TagTest.java | 77 + .../foxinmy/weixin4j/qy/test/TokenTest.java | 34 + .../foxinmy/weixin4j/qy/test/UserTest.java | 92 ++ weixin4j-server/.gitignore | 32 + weixin4j-server/CHANGE.md | 19 + weixin4j-server/README.md | 67 + weixin4j-server/deploy.xml | 54 + weixin4j-server/pom.xml | 48 + weixin4j-server/src/main/assembly.xml | 36 + .../foxinmy/weixin4j/model/WeixinAccount.java | 76 + .../com/foxinmy/weixin4j/server/README.md | 5 + .../weixin4j/server/WeixinMessageDecoder.java | 76 + .../weixin4j/server/WeixinMessageHandler.java | 88 ++ .../server/WeixinServerInitializer.java | 20 + .../startup/WeixinServerBootstrap.java | 54 + .../com/foxinmy/weixin4j/util/ConfigUtil.java | 67 + .../com/foxinmy/weixin4j/util/Consts.java | 28 + .../com/foxinmy/weixin4j/util/DigestUtil.java | 80 + .../com/foxinmy/weixin4j/util/HttpUtil.java | 44 + .../foxinmy/weixin4j/util/MessageUtil.java | 155 ++ .../foxinmy/weixin4j/util/PKCS7Encoder.java | 70 + .../com/foxinmy/weixin4j/util/RandomUtil.java | 107 ++ .../main/resources/Copy of weixin.properties | 22 + .../src/main/resources/logback.xml | 63 + .../src/main/resources/netty.properties | 4 + .../src/main/resources/weixin.properties | 5 + weixin4j-server/src/main/startup.sh | 142 ++ 221 files changed, 24504 insertions(+) create mode 100644 weixin4j-base/CHANGE.md create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/tuple/Tuple.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Pageable.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Pagedata.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Sort.java create mode 100644 weixin4j-mp/CHANGE.md create mode 100644 weixin4j-mp/src/main/assembly.xml create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinPayProxy.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/CashApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/CouponApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/GroupApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/HelperApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MenuApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MpApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay3Api.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/PayApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/QrApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/README.md create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/TmplApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/UserApi.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/ArticleDatacube1.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/ArticleDatacube2.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/ArticleDatacubeShare.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/ArticleSummary.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/ArticleTotal.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/InterfaceSummary.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/UpstreamMsg.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/UpstreamMsgDist.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/datacube/UserSummary.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/message/NotifyMessage.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/message/README.md create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/message/TemplateMessage.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/AutoReplySetting.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/CustomRecord.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/Following.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/Group.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/KfAccount.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/KfSession.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/MediaCounter.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/MediaItem.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/MediaRecord.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/MenuSetting.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/OauthToken.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/QRParameter.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/SemQuery.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/SemResult.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/User.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/JsPayNotify.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/MicroPayPackage.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/PayBaseInfo.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/PayPackage.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/PayRequest.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/PayUtil.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/README.md create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/cacert.pem create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/conver/CouponConverter.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/conver/RefundConverter.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/coupon/CouponDetail.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/coupon/CouponInfo.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/coupon/CouponResult.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/coupon/CouponStock.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/ApiResult.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/JsPayRequestV2.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/NativePayNotifyV2.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/NativePayResponseV2.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/Order.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/PayFeedback.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/PayPackageV2.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/PayWarn.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/RefundDetail.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/RefundRecord.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/RefundResult.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/ApiResult.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/MPPayment.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/MPPaymentResult.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/NativePayNotifyV3.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/NativePayResponseV3.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/Order.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/PayPackageV3.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/PayRequestV3.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/PrePay.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/Redpacket.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/RedpacketSendResult.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/RefundDetail.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/RefundRecord.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v3/RefundResult.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/spider/README.md create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/spider/WeixinExecutor.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/token/WeixinJSTicketCreator.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/token/WeixinTokenCreator.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/AutomatchMode.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/AutoreplyMode.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/BillType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/CouponStatus.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/CouponStockStatus.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/CouponStockType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/CouponType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/CurrencyType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/CustomRecordOperCode.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/DatacubeType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/DatacuteCountIntervalType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/EventType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/FaceSize.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/IdQuery.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/IdType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/IndustryType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/KfOnlineStatus.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/Lang.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/MPPaymentCheckNameType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/QRType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/RefundChannel.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/RefundStatus.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/RefundType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/SemCategory.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/ShareSourceType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/SignType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/TradeState.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/TradeType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/UserSourceType.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/util/ExcelUtil.java create mode 100644 weixin4j-mp/src/main/resources/weixin.properties create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/CashTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/CouponTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/DataApiTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/GroupTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/HelpTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MenuTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/QRTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/SemanticTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/TokenTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/UserTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/msg/AesMsgTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/msg/EventMsgTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/msg/InMsgTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/msg/MassMsgTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/msg/MessagePush.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java create mode 100644 weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/msg/TemplateMsgTest.java create mode 100644 weixin4j-qy/CHANGE.md create mode 100644 weixin4j-qy/src/main/assembly.xml create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/AgentApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/HelperApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MenuApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/NotifyApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/PartyApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/QyApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/TagApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/weixin.properties create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/event/ScribeEventMessage.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/message/NotifyMessage.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/AgentInfo.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/AgentOverview.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/AgentSetter.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/BatchResult.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/Callback.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/IdParameter.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/NameValue.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/Party.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/Tag.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/User.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/token/WeixinJSTicketCreator.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/token/WeixinTokenCreator.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/type/BatchStatus.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/type/BatchType.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/type/EventType.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/type/InviteType.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/type/ReportLocationType.java create mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/type/UserStatus.java create mode 100644 weixin4j-qy/src/main/resources/weixin.properties create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/AesMsgTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/AgentTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/BatchTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/HelperTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/MediaTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/MenuTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/MessagePush.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/NotifyMsgTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/PartyTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/TagTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/TokenTest.java create mode 100644 weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/UserTest.java create mode 100644 weixin4j-server/.gitignore create mode 100644 weixin4j-server/CHANGE.md create mode 100644 weixin4j-server/README.md create mode 100644 weixin4j-server/deploy.xml create mode 100644 weixin4j-server/pom.xml create mode 100644 weixin4j-server/src/main/assembly.xml create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/model/WeixinAccount.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/server/README.md create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/server/WeixinMessageDecoder.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/server/WeixinMessageHandler.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/server/WeixinServerInitializer.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/startup/WeixinServerBootstrap.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/Consts.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/DigestUtil.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/HttpUtil.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/PKCS7Encoder.java create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/RandomUtil.java create mode 100644 weixin4j-server/src/main/resources/Copy of weixin.properties create mode 100644 weixin4j-server/src/main/resources/logback.xml create mode 100644 weixin4j-server/src/main/resources/netty.properties create mode 100644 weixin4j-server/src/main/resources/weixin.properties create mode 100644 weixin4j-server/src/main/startup.sh diff --git a/weixin4j-base/CHANGE.md b/weixin4j-base/CHANGE.md new file mode 100644 index 00000000..48f32b3e --- /dev/null +++ b/weixin4j-base/CHANGE.md @@ -0,0 +1,51 @@ +* 2014-10-31 + + + `TokenApi`重命名为`TokenHolder` + + + 新增`WeixinConfig`等类 + +* 2014-11-06 + + + 删除`WeixinConfig`类只保留`WeixinAccount`类 + +* 2014-11-15 + + + 新增`aes加密解密`函数 + +* 2014-11-19 + + + 新增`WeixinQyAccount`企业号账号信息类 + +* 2014-11-23 + + + 新增企业号消息体以及用`Responseable`,`Notifyable`,`Massable`三个接口标记不同的可接受的消息类型 + +* 2014-11-24 + + + 将Action跟Mapping基础类并入到项目 + +* 2015-01-04 + + + ConfigUtil类新增获取classpath目录下的资源路径的方法 + +* 2015-01-10 + + + 重构token实现机制 + + + 新增JSTICKET支持 + +* 2015-03-29 + + + 单行注释调整为多行文档注释 + +* 2015-04-01 + + + 新增异步消息事件[BatchjobresultMessage](./src/main/java/com/foxinmy/weixin4j/msg/event/BatchjobresultMessage.java) + +* 2015-04-13 + + + 删除WeixinTokenCreator与WeixinJSTicketCreator类 + +* 2015-04-19 + + + 删除ActionMapping相关类 \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/tuple/Tuple.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/tuple/Tuple.java new file mode 100644 index 00000000..e9f5fc56 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/tuple/Tuple.java @@ -0,0 +1,27 @@ +package com.foxinmy.weixin4j.tuple; + +import java.beans.Transient; +import java.io.Serializable; + +import com.alibaba.fastjson.annotation.JSONField; + +/** + * 消息元件 + * + * @className Tuple + * @author jy + * @date 2015年4月19日 + * @since JDK 1.7 + * @see + */ +public interface Tuple extends Serializable { + + /** + * 消息类型 + * + * @return + */ + @Transient + @JSONField(deserialize = false, serialize = false) + public String getMessageType(); +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Pageable.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Pageable.java new file mode 100644 index 00000000..94262597 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Pageable.java @@ -0,0 +1,90 @@ +package com.foxinmy.weixin4j.util; + +import java.io.Serializable; + +import com.foxinmy.weixin4j.util.Sort.Direction; + +/** + * @className Pageable + * @author jy + * @date 2014年12月27日 + * @since JDK 1.7 + * @see org.springframework.data.domain.Pageable + */ +public class Pageable implements Serializable { + + private static final long serialVersionUID = -8051554878205756307L; + + private final int page; + private final int size; + private Sort sort; + + /** + * + * @param page + * must not be less than one. + * @param size + * must not be less than one. + */ + public Pageable(int page, int size) { + if (page < 1) { + throw new IllegalArgumentException( + "Page index must not be less than one!"); + } + if (size < 1) { + throw new IllegalArgumentException( + "Page size must not be less than one!"); + } + this.page = page; + this.size = size; + } + public Pageable(int page, int size, Direction direction, + String... properties) { + this(page, size, new Sort(direction, properties)); + } + + public Pageable(int page, int size, Sort sort) { + this.page = page; + this.size = size; + this.sort = sort; + } + + public int getPageSize() { + return size; + } + + public int getPageNumber() { + return page; + } + public Sort getSort() { + return sort; + } + public void setSort(Sort sort) { + this.sort = sort; + } + public int getOffset() { + return (page - 1) * size; + } + + public boolean hasPrevious() { + return page > 1; + } + + public Pageable next() { + return new Pageable(getPageNumber() + 1, getPageSize(), getSort()); + } + + public Pageable previous() { + return getPageNumber() == 1 ? this : new Pageable(getPageNumber() - 1, + getPageSize(), getSort()); + } + + public Pageable first() { + return new Pageable(0, getPageSize(), getSort()); + } + @Override + public String toString() { + return "Pageable [page=" + page + ", size=" + size + ", sort=" + sort + + "]"; + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Pagedata.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Pagedata.java new file mode 100644 index 00000000..482eaaaa --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Pagedata.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.List; + +public class Pagedata implements Serializable, Iterable { + + private static final long serialVersionUID = 163159826528502864L; + + private final int total; + private final Pageable pageable; + private final List content; + + public Pagedata(Pageable pageable, int total, List content) { + this.pageable = pageable; + this.total = total; + this.content = content; + } + + public int getNumber() { + return pageable == null ? 0 : pageable.getPageNumber(); + } + + public int getSize() { + return pageable == null ? 0 : pageable.getPageSize(); + } + + public int getTotalPages() { + return getSize() == 0 ? 1 : (int) Math.ceil((double) total + / (double) getSize()); + } + + public int getTotalElements() { + return total; + } + + public int getNumberOfElements() { + return hasContent() ? 0 : content.size(); + } + + public boolean hasContent() { + return content != null && !content.isEmpty(); + } + + public boolean hasPrevious() { + return pageable == null ? false : pageable.hasPrevious(); + } + + public boolean hasNext() { + return getNumber() + 1 < getTotalPages(); + } + + public Sort getSort() { + return pageable == null ? null : pageable.getSort(); + } + + @Override + public Iterator iterator() { + return hasContent() ? content.iterator() : null; + } + + @Override + public String toString() { + return "Pagedata [total=" + total + ", pageable=" + pageable + "]"; + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Sort.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Sort.java new file mode 100644 index 00000000..dbb2cfab --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Sort.java @@ -0,0 +1,65 @@ +package com.foxinmy.weixin4j.util; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class Sort implements Serializable { + + private static final long serialVersionUID = -4298853295391613880L; + + public static final Direction DEFAULT_DIRECTION = Direction.ASC; + private Map> orders; + public Sort() { + } + public Sort(String... properties) { + this(DEFAULT_DIRECTION, properties); + } + + public Sort(Direction direction, String... properties) { + this(direction, properties == null ? new ArrayList() : Arrays + .asList(properties)); + } + + public Sort(Direction direction, List properties) { + if (properties == null || properties.isEmpty()) { + throw new IllegalArgumentException( + "You have to provide at least one property to sort by!"); + } + this.orders = new LinkedHashMap>( + properties.size()); + this.orders.put(direction, properties); + } + + public Map> getOrders() { + return orders; + } + public Map.Entry getFirst() { + if (hasSort()) { + Entry> firstEntry = orders.entrySet() + .iterator().next(); + Map firstMap = new HashMap(); + firstMap.put(firstEntry.getKey().name().toLowerCase(), firstEntry + .getValue().get(0)); + return firstMap.entrySet().iterator().next(); + } + return null; + } + public boolean hasSort() { + return orders != null && !orders.isEmpty(); + } + + public static enum Direction { + ASC, DESC; + } + + @Override + public String toString() { + return "Sort [" + orders + "]"; + } +} diff --git a/weixin4j-mp/CHANGE.md b/weixin4j-mp/CHANGE.md new file mode 100644 index 00000000..a1b0e0ab --- /dev/null +++ b/weixin4j-mp/CHANGE.md @@ -0,0 +1,111 @@ +* 2014-10-27 + + + 用netty构建http服务器&消息分发 + +* 2014-10-28 + + + 调整`ActionMapping`抽象化 + +* 2014-10-31 + + + `weixin.properties`切分为API调用地址和公众号appid等信息两部分 + +* 2014-11-03 + + + 分离为`weixin-mp-api`和`weixin-mp-server`两个工程 + + + 新增`支付模块` + +* 2014-11-06 + + + 新增V3版本`退款申请`接口 + +* 2014-11-08 + + + 新增V2版本`退款申请`、`退款查询`、`对账单下载`三个接口 + + + 新增一个简单的`语义理解`接口 + +* 2014-11-11 + + + 自定义`assembly`将`weixin4j-base`工程也一起打包(`weixin4j-mp-api-full.jar`) + +* 2014-11-15 + + + 新增获取`微信服务器IP地址接口` + +* 2014-11-16 + + + 新增`多客服`接口 + +* 2014-11-17 + + + 新增`冲正`和`被扫支付`接口 + +* 2014-12-12 + + + 新增设置`模板消息所处行业`、`获取模板消息ID`接口 + +* 2014-12-16 + + + 调整方法上@see注解的文档说明接口url + + + 新增群发消息预览、状态查询接口 + + + 新增多客服添加账号、更新账号、上传头像、删除账号接口 + +* 2015-01-04 + + + 支付模块拆分为V2跟V3,新增WeixinPayProxy类 + + + 退款相关类拆分为V2跟V3 + + + 新增接口上报接口 + +* 2015-01-31 + + + 新增数据分析接口 + +* 2015-03-06 + + + 新增oauth授权接口 + +* 2015-03-21 + + + 新增群发消息给所有人接口 + + + 新增素材管理多个接口 + + + 新增多客服会话管理多个接口 + +* 2015-03-25 + + + 根据《微信商户平台文档》修缮[Pay3Api](./src/main/java/com/foxinmy/weixin4j/mp/api/Pay3Api.java)类 + +* 2015-03-29 + + + 单行注释调整为多行文档注释 + + + 新增[CouponApi](./src/main/java/com/foxinmy/weixin4j/mp/api/CouponApi.java)代金券接口 + +* 2015-04-01 + + + 新增[CashApi](./src/main/java/com/foxinmy/weixin4j/mp/api/CashApi.java)发红包、企业付款接口 + +* 2015-04-13 + + + 新增WeixinTokenCreator与WeixinJSTicketCreator类 + + + 新增用户分组批量移动、删除组别接口 + +* 2015-04-16 + + + **weixin4j-mp-api**: 调整[二维码参数](./src/main/java/com/foxinmy/weixin4j/mp/model/QRParameter.java)类 + + + **weixin4j-mp-api**: 新增获取[自定义菜单配置、自动回复配置](./src/main/java/com/foxinmy/weixin4j/mp/api/HelperApi.java)接口 + +* 2015-04-18 + + + 调整[客服接口](./src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java)类的方法名 + + + 在[二维码接口](./src/main/java/com/foxinmy/weixin4j/mp/api/QRApi.java)类新增获取二维码url方法 \ No newline at end of file diff --git a/weixin4j-mp/src/main/assembly.xml b/weixin4j-mp/src/main/assembly.xml new file mode 100644 index 00000000..fde1cf28 --- /dev/null +++ b/weixin4j-mp/src/main/assembly.xml @@ -0,0 +1,31 @@ + + full + + jar + + false + + + target/classes + / + + /** + + + *.properties + *.xml + + + + + + true + + com.foxinmy:weixin4j-base + + + + \ No newline at end of file diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinPayProxy.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinPayProxy.java new file mode 100644 index 00000000..743a488b --- /dev/null +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinPayProxy.java @@ -0,0 +1,624 @@ +package com.foxinmy.weixin4j.mp; + +import java.io.File; +import java.util.Date; + +import com.alibaba.fastjson.JSON; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.JsonResult; +import com.foxinmy.weixin4j.http.XmlResult; +import com.foxinmy.weixin4j.mp.api.CashApi; +import com.foxinmy.weixin4j.mp.api.CouponApi; +import com.foxinmy.weixin4j.mp.api.Pay2Api; +import com.foxinmy.weixin4j.mp.api.Pay3Api; +import com.foxinmy.weixin4j.mp.api.PayApi; +import com.foxinmy.weixin4j.mp.model.WeixinMpAccount; +import com.foxinmy.weixin4j.mp.payment.coupon.CouponDetail; +import com.foxinmy.weixin4j.mp.payment.coupon.CouponResult; +import com.foxinmy.weixin4j.mp.payment.coupon.CouponStock; +import com.foxinmy.weixin4j.mp.payment.v3.ApiResult; +import com.foxinmy.weixin4j.mp.payment.v3.MPPayment; +import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentResult; +import com.foxinmy.weixin4j.mp.payment.v3.Redpacket; +import com.foxinmy.weixin4j.mp.payment.v3.RedpacketSendResult; +import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator; +import com.foxinmy.weixin4j.mp.type.BillType; +import com.foxinmy.weixin4j.mp.type.CurrencyType; +import com.foxinmy.weixin4j.mp.type.IdQuery; +import com.foxinmy.weixin4j.mp.type.IdType; +import com.foxinmy.weixin4j.mp.type.RefundType; +import com.foxinmy.weixin4j.token.FileTokenHolder; +import com.foxinmy.weixin4j.token.TokenHolder; +import com.foxinmy.weixin4j.util.ConfigUtil; + +/** + * 微信支付接口实现 + * + * @className WeixinPayProxy + * @author jy + * @date 2015年1月3日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.mp.api.Pay2Api + * @see com.foxinmy.weixin4j.mp.api.Pay3Api + * @see 商户平台支付API + */ +public class WeixinPayProxy { + + private final PayApi payApi; + private final Pay2Api pay2Api; + private final Pay3Api pay3Api; + private final CouponApi couponApi; + private final CashApi cashApi; + + public WeixinPayProxy() { + this(JSON.parseObject(ConfigUtil.getValue("account"), + WeixinMpAccount.class), new FileTokenHolder( + new WeixinTokenCreator())); + } + + /** + * WeixinAccount对象 + * + * @param weixinAccount + * 微信账户 + */ + public WeixinPayProxy(WeixinMpAccount weixinAccount, TokenHolder tokenHolder) { + this.pay2Api = new Pay2Api(weixinAccount, tokenHolder); + this.pay3Api = new Pay3Api(weixinAccount, tokenHolder); + int version = weixinAccount.getVersion(); + if (version == 2) { + this.payApi = this.pay2Api; + } else if (version == 3) { + this.payApi = this.pay3Api; + } else { + this.payApi = this.pay3Api; + } + this.couponApi = new CouponApi(weixinAccount); + this.cashApi = new CashApi(weixinAccount); + } + + /** + * 发货通知 + * + * @param openId + * 用户ID + * @param transid + * 交易单号 + * @param outTradeNo + * 订单号 + * @param status + * 成功|失败 + * @param statusMsg + * status为失败时携带的信息 + * @return 发货处理结果 + * @since V2 & V3 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @throws WeixinException + */ + public JsonResult deliverNotify(String openId, String transid, + String outTradeNo, boolean status, String statusMsg) + throws WeixinException { + return payApi.deliverNotify(openId, transid, outTradeNo, status, + statusMsg); + } + + /** + * 维权处理 + * + * @param openId + * 用户ID + * @param feedbackId + * 维权单号 + * @return 调用结果 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @since V2 & V3 + * @throws WeixinException + */ + public JsonResult updateFeedback(String openId, String feedbackId) + throws WeixinException { + return payApi.updateFeedback(openId, feedbackId); + } + + /** + * V2订单查询 + * + * @param idQuery + * 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @since V2 + * @see com.foxinmy.weixin4j.mp.payment.v2.Order + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay2Api + * @return 订单详情 + * @throws WeixinException + */ + public com.foxinmy.weixin4j.mp.payment.v2.Order orderQueryV2( + String outTradeNo) throws WeixinException { + return pay2Api.orderQuery(new IdQuery(outTradeNo, IdType.TRADENO)); + } + + /** + * V3订单查询 + *

+ * 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
调用支付接口后,返回系统错误或未知交易状态情况;
+ * 调用被扫支付API,返回USERPAYING的状态;
调用关单或撤销接口API之前,需确认支付状态; + *

+ * + * @param idQuery + * 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @since V3 + * @see com.foxinmy.weixin4j.mp.payment.v3.Order + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay3Api + * @see 订单查询API + * @return 订单详情 + * @throws WeixinException + */ + public com.foxinmy.weixin4j.mp.payment.v3.Order orderQueryV3(IdQuery idQuery) + throws WeixinException { + return pay3Api.orderQuery(idQuery); + } + + /** + * V2申请退款(请求需要双向证书)
+ *

+ * 交易时间超过 1 年的订单无法提交退款;
支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失 + * 败后重新提交,要采用原来的 out_refund_no。总退款金额不能超过用户实际支付金额。
+ *

+ * + * @param caFile + * 证书文件(后缀为*.pfx) + * @param idQuery + * ) 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @param outRefundNo + * 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔 + * @param totalFee + * 订单总金额,单位为元 + * @param refundFee + * 退款总金额,单位为元,可以做部分退款 + * @param opUserId + * 操作员帐号, 默认为商户号 + * @param opUserPasswd + * 操作员密码 + * + * @return 退款申请结果 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay2Api + * @see com.foxinmy.weixin4j.mp.payment.v2.RefundResult + * @since V2 + * @throws WeixinException + */ + public com.foxinmy.weixin4j.mp.payment.v2.RefundResult refundV2( + File caFile, IdQuery idQuery, String outRefundNo, double totalFee, + double refundFee, String opUserId, String opUserPasswd) + throws WeixinException { + return pay2Api.refund(caFile, idQuery, outRefundNo, totalFee, + refundFee, opUserId, opUserPasswd); + } + + /** + * V2退款申请采用properties中配置的ca文件 + * + * @see {@link com.foxinmy.weixin4j.mp.WeixinPayProxy#refundV2(File, IdQuery, String, double, double, String,String)} + */ + public com.foxinmy.weixin4j.mp.payment.v2.RefundResult refundV2( + IdQuery idQuery, String outRefundNo, double totalFee, + double refundFee, String opUserId, String opUserPasswd) + throws WeixinException { + File caFile = new File(ConfigUtil.getClassPathValue("ca_file")); + return refundV2(caFile, idQuery, outRefundNo, totalFee, refundFee, + opUserId, opUserPasswd); + } + + /** + * V2退款申请 + * + * @param caFile + * 证书文件(V2版本后缀为*.pfx) + * @param idQuery + * 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @param outRefundNo + * 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔 + * @param totalFee + * 订单总金额,单位为元 + * @param refundFee + * 退款总金额,单位为元,可以做部分退款 + * @param opUserId + * 操作员帐号, 默认为商户号 + * @param opUserPasswd + * 操作员密码,默认为商户后台登录密码 + * @param recvUserId + * 转账退款接收退款的财付通帐号。 一般无需填写,只有退银行失败,资金转入商 户号现金账号时(即状态为转入代发,查询返 回的 + * refund_status 是 7 或 11),填写原退款 单号并填写此字段,资金才会退到指定财付通 + * 账号。其他情况此字段忽略 + * @param reccvUserName + * 转账退款接收退款的姓名(需与接收退款的财 付通帐号绑定的姓名一致) + * @param refundType + * 为空或者填 1:商户号余额退款;2:现金帐号 退款;3:优先商户号退款,若商户号余额不足, 再做现金帐号退款。使用 2 或 + * 3 时,需联系财 付通开通此功能 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay2Api + * @see com.foxinmy.weixin4j.mp.payment.v2.RefundResult + * @return 退款结果 + */ + public com.foxinmy.weixin4j.mp.payment.v2.RefundResult refundV2( + File caFile, IdQuery idQuery, String outRefundNo, double totalFee, + double refundFee, String opUserId, String opUserPasswd, + String recvUserId, String reccvUserName, RefundType refundType) + throws WeixinException { + return pay2Api.refund(caFile, idQuery, outRefundNo, totalFee, + refundFee, opUserId, opUserPasswd, recvUserId, reccvUserName, + refundType); + } + + /** + * V2退款查询
退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态 + * + * @param idQuery + * 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id + * 四个参数必填一个,优先级为: + * refund_id>out_refund_no>transaction_id>out_trade_no + * @return 退款记录 + * @see com.foxinmy.weixin4j.mp.payment.v2.RefundRecord + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay2Api + * @since V2 + * @throws WeixinException + */ + public com.foxinmy.weixin4j.mp.payment.v2.RefundRecord refundQueryV2( + IdQuery idQuery) throws WeixinException { + return pay2Api.refundQuery(idQuery); + } + + /** + * V3申请退款(请求需要双向证书)
+ *

+ * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后, + * 按照退款规则将支付款按原路退到买家帐号上。 + *

+ *

+ * 1.交易时间超过半年的订单无法提交退款; + * 2.微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交 + * ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。 + *

+ * + * @param caFile + * 证书文件(后缀为*.p12) + * @param idQuery + * 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @param outRefundNo + * 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔 + * @param totalFee + * 订单总金额,单位为元 + * @param refundFee + * 退款总金额,单位为元,可以做部分退款 + * @param refundFeeType + * 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY + * @param opUserId + * 操作员帐号, 默认为商户号 + * + * @return 退款申请结果 + * @see com.foxinmy.weixin4j.mp.payment.v3.RefundResult + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay3Api + * @see 申请退款API + * @since V3 + * @throws WeixinException + */ + public com.foxinmy.weixin4j.mp.payment.v3.RefundResult refundV3( + File caFile, IdQuery idQuery, String outRefundNo, double totalFee, + double refundFee, CurrencyType refundFeeType, String opUserId) + throws WeixinException { + return pay3Api.refund(caFile, idQuery, outRefundNo, totalFee, + refundFee, refundFeeType, opUserId); + } + + /** + * V3退款申请采用properties中配置的ca文件 + * + * @see {@link com.foxinmy.weixin4j.mp.WeixinPayProxy#refundV3(File, IdQuery, String, double, double,CurrencyType, String)} + */ + public com.foxinmy.weixin4j.mp.payment.v3.RefundResult refundV3( + IdQuery idQuery, String outRefundNo, double totalFee, + double refundFee, String opUserId) throws WeixinException { + File caFile = new File(ConfigUtil.getClassPathValue("ca_file")); + return pay3Api.refund(caFile, idQuery, outRefundNo, totalFee, + refundFee, CurrencyType.CNY, opUserId); + } + + /** + * V3退款查询 + *

+ * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。 + *

+ * + * @param idQuery + * 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id + * 四个参数必填一个,优先级为: + * refund_id>out_refund_no>transaction_id>out_trade_no + * @return 退款记录 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay3Api + * @see com.foxinmy.weixin4j.mp.payment.v3.RefundRecord + * @see 退款查询API + * @since V3 + * @throws WeixinException + */ + public com.foxinmy.weixin4j.mp.payment.v3.RefundRecord refundQueryV3( + IdQuery idQuery) throws WeixinException { + return pay3Api.refundQuery(idQuery); + } + + /** + * 下载对账单
+ * 1.微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账 单中,跟原支付单订单号一致,bill_type 为 + * REVOKED;
+ * 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;
+ * 3.对账单中涉及金额的字段单位为“元”。
+ * + * @param billDate + * 下载对账单的日期 + * @param billType + * 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单 + * REFUND,返回当日退款订单 + * @return excel表格 + * @since V2 & V3 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see 下载对账单API + * @throws WeixinException + */ + public File downloadbill(Date billDate, BillType billType) + throws WeixinException { + return payApi.downloadbill(billDate, billType); + } + + /** + * 冲正订单(需要证书)
当支付返回失败,或收银系统超时需要取消交易,可以调用该接口
接口逻辑:支 + * 付失败的关单,支付成功的撤销支付
7天以内的单可撤销,其他正常支付的单 + * 如需实现相同功能请调用退款接口
调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销
+ * + * @param ca + * 证书文件(V2版本后缀为*.pfx,V3版本后缀为*.p12) + * @param idQuery + * 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @return 撤销结果 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay2Api + * @see com.foxinmy.weixin4j.mp.api.Pay3Api + * @since V3 + * @throws WeixinException + */ + public ApiResult reverse(File caFile, IdQuery idQuery) + throws WeixinException { + return payApi.reverse(caFile, idQuery); + } + + /** + * 冲正撤销:默认采用properties中配置的ca文件 + * + * @param idQuery + * transaction_id、out_trade_no 二选一 + * @return 撤销结果 + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#reverse(File, IdQuery)} + * @throws WeixinException + */ + public ApiResult reverse(IdQuery idQuery) throws WeixinException { + File caFile = new File(ConfigUtil.getClassPathValue("ca_file")); + return payApi.reverse(caFile, idQuery); + } + + /** + * 关闭订单 + *

+ * 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续 + * ,请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。 + *

+ * + * @param outTradeNo + * 商户系统内部的订单号 + * @return 执行结果 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay3Api + * @since V3 + * @throws WeixinException + * @see 关闭订单API + */ + public ApiResult closeOrder(String outTradeNo) throws WeixinException { + return payApi.closeOrder(outTradeNo); + } + + /** + * native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量 + * ,提升扫描速度和精确度。 + * + * @param url + * 具有native标识的支付URL + * @return 转换后的短链接 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay2Api + * @see com.foxinmy.weixin4j.mp.api.Pay3Api + * @see 转换短链接API + * @since V2 & V3 + * @throws WeixinException + */ + public String getPayShorturl(String url) throws WeixinException { + return payApi.getShorturl(url); + } + + /** + * 接口上报 + * + * @param interfaceUrl + * 上报对应的接口的完整 URL, 类似: https://api.mch.weixin.q + * q.com/pay/unifiedorder + * @param executeTime + * 接口耗时情况,单位为毫秒 + * @param outTradeNo + * 商户系统内部的订单号,商 户可以在上报时提供相关商户订单号方便微信支付更好 的提高服务质量。 + * @param ip + * 发起接口调用时的机器 IP + * @param time + * 商户调用该接口时商户自己 系统的时间 + * @param returnXml + * 调用接口返回的基本数据 + * @return 处理结果 + * @see com.foxinmy.weixin4j.mp.api.PayApi + * @see com.foxinmy.weixin4j.mp.api.Pay3Api + * @see 接口测试上报API + * @throws WeixinException + */ + public XmlResult interfaceReport(String interfaceUrl, int executeTime, + String outTradeNo, String ip, Date time, XmlResult returnXml) + throws WeixinException { + return pay3Api.interfaceReport(interfaceUrl, executeTime, outTradeNo, + ip, time, returnXml); + } + + /** + * 发放代金券(需要证书) + * + * @param caFile + * 证书文件(后缀为*.p12) + * @param couponStockId + * 代金券批次id + * @param partnerTradeNo + * 商户发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性 + * @param openId + * 用户的openid + * @param opUserId + * 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限 可为空 + * @return 发放结果 + * @see com.foxinmy.weixin4j.mp.api.CouponApi + * @see com.foxinmy.weixin4j.mp.payment.coupon.CouponResult + * @see 发放代金券接口 + * @throws WeixinException + */ + public CouponResult sendCoupon(File caFile, String couponStockId, + String partnerTradeNo, String openId, String opUserId) + throws WeixinException { + return couponApi.sendCoupon(caFile, couponStockId, partnerTradeNo, + openId, opUserId); + } + + /** + * 发放代金券采用properties中配置的ca文件 + * + * @see {@link com.foxinmy.weixin4j.mp.WeixinPayProxy#sendCoupon(File, String, String, String, String)} + */ + public CouponResult sendCoupon(String couponStockId, String partnerTradeNo, + String openId) throws WeixinException { + File caFile = new File(ConfigUtil.getClassPathValue("ca_file")); + return couponApi.sendCoupon(caFile, couponStockId, partnerTradeNo, + openId, null); + } + + /** + * 查询代金券批次 + * + * @param couponStockId + * 代金券批次ID + * @return 代金券批次信息 + * @see com.foxinmy.weixin4j.mp.api.CouponApi + * @see com.foxinmy.weixin4j.mp.payment.coupon.CouponStock + * @see 查询代金券信息 + * @throws WeixinException + */ + public CouponStock queryCouponStock(String couponStockId) + throws WeixinException { + return couponApi.queryCouponStock(couponStockId); + } + + /** + * 查询代金券详细 + * + * @param couponId + * 代金券ID + * @return 代金券详细信息 + * @see com.foxinmy.weixin4j.mp.api.CouponApi + * @see com.foxinmy.weixin4j.mp.payment.coupon.CouponDetail + * @see 查询代金券详细信息 + * @throws WeixinException + */ + public CouponDetail queryCouponDetail(String couponId) + throws WeixinException { + return couponApi.queryCouponDetail(couponId); + } + + /** + * 发放红包 企业向微信用户个人发现金红包 + * + * @param caFile + * 证书文件(V3版本后缀为*.p12) + * @param redpacket + * 红包信息 + * @return 发放结果 + * @see com.foxinmy.weixin4j.mp.api.CashApi + * @see com.foxinmy.weixin4j.mp.payment.v3.Redpacket + * @see com.foxinmy.weixin4j.mp.payment.v3.RedpacketSendResult + * @see 红包接口说明 + * @throws WeixinException + */ + public RedpacketSendResult sendRedpack(File caFile, Redpacket redpacket) + throws WeixinException { + return cashApi.sendRedpack(caFile, redpacket); + } + + /** + * 发放红包采用properties中配置的ca文件 + * + * @see {@link com.foxinmy.weixin4j.mp.WeixinPayProxy#sendRedpack(File, Redpacket)} + */ + public RedpacketSendResult sendRedpack(Redpacket redpacket) + throws WeixinException { + File caFile = new File(ConfigUtil.getClassPathValue("ca_file")); + return cashApi.sendRedpack(caFile, redpacket); + } + + /** + * 企业付款 实现企业向个人付款,针对部分有开发能力的商户, 提供通过API完成企业付款的功能。 比如目前的保险行业向客户退保、给付、理赔。 + * + * @param caFile + * 证书文件(V3版本后缀为*.p12) + * @param mpPayment + * 付款信息 + * @return 付款结果 + * @see com.foxinmy.weixin4j.mp.api.CashApi + * @see com.foxinmy.weixin4j.mp.payment.v3.MPPayment + * @see com.foxinmy.weixin4j.mp.payment.v3.MPPaymentResult + * @see 企业付款 + * @throws WeixinException + */ + public MPPaymentResult mpPayment(File caFile, MPPayment mpPayment) + throws WeixinException { + return cashApi.mpPayment(caFile, mpPayment); + } + + /** + * 企业付款采用properties中配置的ca文件 + * + * @see {@link com.foxinmy.weixin4j.mp.WeixinPayProxy#mpPayment(File, MPPayment)} + */ + public MPPaymentResult mpPayment(MPPayment mpPayment) + throws WeixinException { + File caFile = new File(ConfigUtil.getClassPathValue("ca_file")); + return cashApi.mpPayment(caFile, mpPayment); + } +} diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java new file mode 100644 index 00000000..bbe000d7 --- /dev/null +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java @@ -0,0 +1,1333 @@ +package com.foxinmy.weixin4j.mp; + +import java.io.File; +import java.io.IOException; +import java.util.Date; +import java.util.List; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.JsonResult; +import com.foxinmy.weixin4j.model.Button; +import com.foxinmy.weixin4j.mp.api.CustomApi; +import com.foxinmy.weixin4j.mp.api.DataApi; +import com.foxinmy.weixin4j.mp.api.GroupApi; +import com.foxinmy.weixin4j.mp.api.HelperApi; +import com.foxinmy.weixin4j.mp.api.MassApi; +import com.foxinmy.weixin4j.mp.api.MediaApi; +import com.foxinmy.weixin4j.mp.api.MenuApi; +import com.foxinmy.weixin4j.mp.api.NotifyApi; +import com.foxinmy.weixin4j.mp.api.QrApi; +import com.foxinmy.weixin4j.mp.api.TmplApi; +import com.foxinmy.weixin4j.mp.api.UserApi; +import com.foxinmy.weixin4j.mp.message.NotifyMessage; +import com.foxinmy.weixin4j.mp.message.TemplateMessage; +import com.foxinmy.weixin4j.mp.model.AutoReplySetting; +import com.foxinmy.weixin4j.mp.model.CustomRecord; +import com.foxinmy.weixin4j.mp.model.Following; +import com.foxinmy.weixin4j.mp.model.Group; +import com.foxinmy.weixin4j.mp.model.KfAccount; +import com.foxinmy.weixin4j.mp.model.KfSession; +import com.foxinmy.weixin4j.mp.model.MediaCounter; +import com.foxinmy.weixin4j.mp.model.MediaItem; +import com.foxinmy.weixin4j.mp.model.MediaRecord; +import com.foxinmy.weixin4j.mp.model.MenuSetting; +import com.foxinmy.weixin4j.mp.model.QRParameter; +import com.foxinmy.weixin4j.mp.model.SemQuery; +import com.foxinmy.weixin4j.mp.model.SemResult; +import com.foxinmy.weixin4j.mp.model.User; +import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator; +import com.foxinmy.weixin4j.mp.type.DatacubeType; +import com.foxinmy.weixin4j.mp.type.IndustryType; +import com.foxinmy.weixin4j.mp.type.Lang; +import com.foxinmy.weixin4j.token.FileTokenHolder; +import com.foxinmy.weixin4j.token.TokenHolder; +import com.foxinmy.weixin4j.tuple.MassTuple; +import com.foxinmy.weixin4j.tuple.MpArticle; +import com.foxinmy.weixin4j.tuple.Tuple; +import com.foxinmy.weixin4j.tuple.Video; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 微信公众平台接口实现 + * + * @className WeixinProxy + * @author jy.hu + * @date 2014年3月23日 + * @since JDK 1.7 + * @see api文档 + */ +public class WeixinProxy { + + private final MediaApi mediaApi; + private final NotifyApi notifyApi; + private final CustomApi customApi; + private final MassApi massApi; + private final UserApi userApi; + private final GroupApi groupApi; + private final MenuApi menuApi; + private final QrApi qrApi; + private final TmplApi tmplApi; + private final HelperApi helperApi; + private final DataApi dataApi; + + /** + * 默认采用文件存放Token信息 + */ + public WeixinProxy() { + this(new FileTokenHolder(new WeixinTokenCreator())); + } + + /** + * + * @param appid + * @param appsecret + */ + public WeixinProxy(String appid, String appsecret) { + this(new FileTokenHolder(new WeixinTokenCreator(appid, appsecret))); + } + + /** + * TokenHolder对象 + * + * @see com.foxinmy.weixin4j.token.TokenHolder + * @param tokenHolder + */ + public WeixinProxy(TokenHolder tokenHolder) { + this.mediaApi = new MediaApi(tokenHolder); + this.notifyApi = new NotifyApi(tokenHolder); + this.customApi = new CustomApi(tokenHolder); + this.massApi = new MassApi(tokenHolder); + this.userApi = new UserApi(tokenHolder); + this.groupApi = new GroupApi(tokenHolder); + this.menuApi = new MenuApi(tokenHolder); + this.qrApi = new QrApi(tokenHolder); + this.tmplApi = new TmplApi(tokenHolder); + this.helperApi = new HelperApi(tokenHolder); + this.dataApi = new DataApi(tokenHolder); + } + + /** + * 上传媒体文件 + * + * @param file + * 媒体对象 + * @param isMaterial + * 是否永久上传 + * @return 上传到微信服务器返回的媒体标识 + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#uploadMedia(File, MediaType)} + * @throws WeixinException + * @throws IOException + */ + public String uploadMedia(File file, boolean isMaterial) + throws WeixinException, IOException { + return mediaApi.uploadMedia(file, isMaterial); + } + + /** + * 上传媒体文件 + * + * @param file + * 文件对象 + * @param mediaType + * 媒体类型 + * @param isMaterial + * 是否永久上传 + * @return 上传到微信服务器返回的媒体标识 + * @throws WeixinException + * @throws IOException + * @see com.foxinmy.weixin4j.type.MediaType + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#uploadMedia(String, byte[],String)} + */ + public String uploadMedia(File file, MediaType mediaType, boolean isMaterial) + throws WeixinException, IOException { + return mediaApi.uploadMedia(file, mediaType, isMaterial); + } + + /** + * 上传媒体文件 + *

+ * 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789}, + * 否则抛出异常. + *

+ * + * @param fileName + * 文件名 + * @param data + * 媒体数据包 + * @param mediaType + * 媒体类型 + * @param isMaterial + * 是否永久上传 + * @return 上传到微信服务器返回的媒体标识 + * @see 上传下载说明 + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @throws WeixinException + */ + public String uploadMedia(String fileName, byte[] data, String mediaType, + boolean isMaterial) throws WeixinException { + return mediaApi.uploadMedia(fileName, data, mediaType, isMaterial); + } + + /** + * 下载媒体文件 + *

+ * 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常. + *

+ * + * @param mediaId + * 存储在微信服务器上的媒体标识 + * @param mediaType + * 媒体类型 + * @param isMaterial + * 是否永久素材 + * @return 写入硬盘后的文件对象 + * @throws WeixinException + * @see 上传下载说明 + * @see com.foxinmy.weixin4j.type.MediaType + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#downloadMedia(String)} + */ + public File downloadMedia(String mediaId, MediaType mediaType, + boolean isMaterial) throws WeixinException { + return mediaApi.downloadMedia(mediaId, mediaType, isMaterial); + } + + /** + * 下载媒体文件 + * + * @param mediaId + * 媒体ID + * @param isMaterial + * 是否永久素材 + * @return 二进制数据包 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @see 上传下载说明 + */ + public byte[] downloadMedia(String mediaId, boolean isMaterial) + throws WeixinException { + return mediaApi.downloadMedia(mediaId, isMaterial); + } + + /** + * 上传永久图文素材 + *

+ * 、新增的永久素材也可以在公众平台官网素材管理模块中看到,永久素材的数量是有上限的,请谨慎新增。图文消息素材和图片素材的上限为5000, + * 其他类型为1000 + *

+ * + * @param articles + * 图文列表 + * @return 上传到微信服务器返回的媒体标识 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @see com.foxinmy.weixin4j.tuple.MpArticle + * @see 上传永久媒体素材 + */ + public String uploadMaterialArticle(List articles) + throws WeixinException { + return mediaApi.uploadMaterialArticle(articles); + } + + /** + * 下载永久图文素材 + * + * @param mediaId + * 媒体ID + * @return 图文列表 + * @throws WeixinException + * @see 下载永久媒体素材 + * @see com.foxinmy.weixin4j.tuple.MpArticle + * @see com.foxinmy.weixin4j.mp.api.MediaApi + */ + public List downloadArticle(String mediaId) + throws WeixinException { + return mediaApi.downloadArticle(mediaId); + } + + /** + * 更新永久图文素材 + * + * @param mediaId + * 要修改的图文消息的id + * @param index + * 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为0 + * @param articles + * 图文列表 + * @return 处理结果 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @see com.foxinmy.weixin4j.tuple.MpArticle + * @see 更新永久图文素材 + */ + public JsonResult updateMaterialArticle(String mediaId, int index, + List articles) throws WeixinException { + return mediaApi.updateMaterialArticle(mediaId, index, articles); + } + + /** + * 删除永久媒体素材 + * + * @param mediaId + * 媒体素材的media_id + * @return 处理结果 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @see 删除永久媒体素材 + */ + public JsonResult deleteMaterialMedia(String mediaId) + throws WeixinException { + return mediaApi.deleteMaterialMedia(mediaId); + } + + /** + * 上传永久视频素材 + * + * @param file + * 大小不超过1M且格式为MP4的视频文件 + * @param title + * 视频标题 + * @param introduction + * 视频描述 + * @return 上传到微信服务器返回的媒体标识 + * @see 上传永久媒体素材 + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @throws WeixinException + * @throws IOException + */ + public String uploadMaterialVideo(File file, String title, + String introduction) throws WeixinException, IOException { + return mediaApi.uploadMaterialVideo(file, title, introduction); + } + + /** + * 获取永久媒体素材的总数
.图片和图文消息素材(包括单图文和多图文)的总数上限为5000,其他素材的总数上限为1000 + * + * @return 总数对象 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.model.MediaCounter + * @see 获取素材总数 + * @see com.foxinmy.weixin4j.mp.api.MediaApi + */ + public MediaCounter countMaterialMedia() throws WeixinException { + return mediaApi.countMaterialMedia(); + } + + /** + * 获取媒体素材记录列表 + * + * @param mediaType + * 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news) + * @param offset + * 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 + * @param count + * 返回素材的数量,取值在1到20之间 + * @return 媒体素材的记录对象 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @see com.foxinmy.weixin4j.mp.model.MediaRecord + * @see com.foxinmy.weixin4j.type.MediaType + * @see com.foxinmy.weixin4j.mp.model.MediaItem + * @see 获取素材列表 + */ + public MediaRecord listMaterialMedia(MediaType mediaType, int offset, + int count) throws WeixinException { + return mediaApi.listMaterialMedia(mediaType, offset, count); + } + + /** + * 获取全部的媒体素材 + * + * @param mediaType + * 媒体类型 + * @return 素材列表 + * @see com.foxinmy.weixin4j.mp.api.MediaApi + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#listMaterialMedia(MediaType, int, int)} + * @throws WeixinException + */ + public List listAllMaterialMedia(MediaType mediaType) + throws WeixinException { + return mediaApi.listAllMaterialMedia(mediaType); + } + + /** + * 发送客服消息(在48小时内不限制发送次数) + * + * @param notify + * 客服消息对象 + * @return 处理结果 + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#sendNotify(NotifyMessage,String) } + * @throws WeixinException + */ + public JsonResult sendNotify(NotifyMessage notify) throws WeixinException { + return notifyApi.sendNotify(notify); + } + + /** + * 发送客服消息(在48小时内不限制发送次数) + * + * @param notify + * 客服消息对象 + * @param kfAccount + * 客服账号 可为空 + * @throws WeixinException + * @return 处理结果 + * @see 发送客服消息 + * @see com.foxinmy.weixin4j.tuple.Text + * @see com.foxinmy.weixin4j.tuple.Image + * @see com.foxinmy.weixin4j.tuple.Voice + * @see com.foxinmy.weixin4j.tuple.Video + * @see com.foxinmy.weixin4j.tuple.Music + * @see com.foxinmy.weixin4j.tuple.News + * @see com.foxinmy.weixin4j.mp.api.NotifyApi + */ + public JsonResult sendNotify(NotifyMessage notify, String kfAccount) + throws WeixinException { + return notifyApi.sendNotify(notify, kfAccount); + } + + /** + * 客服聊天记录 + * + * @param openId + * 用户标识 为空时则查询全部记录 + * @param starttime + * 查询开始时间 + * @param endtime + * 查询结束时间 每次查询不能跨日查询 + * @param pagesize + * 每页大小 每页最多拉取50条 + * @param pageindex + * 查询第几页 从1开始 + * @see com.foxinmy.weixin4j.mp.model.CustomRecord + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 查询客服聊天记录 + * @see 查询客服聊天记录 + * @throws WeixinException + */ + public List getCustomRecord(String openId, Date starttime, + Date endtime, int pagesize, int pageindex) throws WeixinException { + return customApi.getCustomRecord(openId, starttime, endtime, pagesize, + pageindex); + } + + /** + * 获取公众号中所设置的客服基本信息,包括客服工号、客服昵称、客服登录账号 + * + * @param isOnline + * 是否在线 为ture时可以可以获取客服在线状态(手机在线、PC客户端在线、手机和PC客户端全都在线)、客服自动接入最大值、 + * 客服当前接待客户数 + * @return 多客服信息列表 + * @see com.foxinmy.weixin4j.mp.model.KfAccount + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 获取客服基本信息 + * @see 获取客服基本信息 + * @see 获取在线客服接待信息 + * @see 获取在线客服接待信息 + * @throws WeixinException + */ + public List getKfAccountList(boolean isOnline) + throws WeixinException { + return customApi.getKfAccountList(isOnline); + } + + /** + * 新增客服账号 + * + * @param id + * 完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符。如果没有公众号微信号, + * 请前往微信公众平台设置。 + * @param name + * 客服昵称,最长6个汉字或12个英文字符 + * @param pwd + * 客服账号登录密码 + * @return 处理结果 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 客服管理接口返回码 + * @see 新增客服账号 + */ + public JsonResult addAccount(String id, String name, String pwd) + throws WeixinException { + return customApi.addAccount(id, name, pwd); + } + + /** + * 更新客服账号 + * + * @param id + * 完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符。如果没有公众号微信号, + * 请前往微信公众平台设置。 + * @param name + * 客服昵称,最长6个汉字或12个英文字符 + * @param pwd + * 客服账号登录密码 + * @return 处理结果 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 客服管理接口返回码 + * @see 新增客服账号 + */ + public JsonResult updateAccount(String id, String name, String pwd) + throws WeixinException { + return customApi.updateAccount(id, name, pwd); + } + + /** + * 上传客服头像 + * + * @param id + * 完整客服账号,格式为:账号前缀@公众号微信号 + * @param headimg + * 头像图片文件必须是jpg格式,推荐使用640*640大小的图片以达到最佳效果 + * @return 处理结果 + * @throws WeixinException + * @throws IOException + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 客服管理接口返回码 + * @see 上传客服头像 + */ + public JsonResult uploadAccountHeadimg(String id, File headimg) + throws WeixinException, IOException { + return customApi.uploadAccountHeadimg(id, headimg); + } + + /** + * 删除客服账号 + * + * @param id + * 完整客服账号,格式为:账号前缀@公众号微信号 + * @return 处理结果 + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @throws WeixinException + * @see 客服管理接口返回码 + * @see 删除客服账号 + */ + public JsonResult deleteAccount(String id) throws WeixinException { + return customApi.deleteAccount(id); + } + + /** + * 创建客服会话 + *

+ * 开发者可以使用本接口,为多客服的客服工号创建会话,将某个客户直接指定给客服工号接待,需要注意此接口不会受客服自动接入数以及自动接入开关限制。 + * 只能为在线的客服(PC客户端在线,或者已绑定多客服助手)创建会话。 + *

+ * + * @param userOpenId + * 用户的userOpenId + * @param kfAccount + * 完整客服账号,格式为:账号前缀@公众号微信号 + * @param text + * 附加信息,文本会展示在客服人员的多客服客户端 + * @return 处理结果 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 创建会话 + */ + public JsonResult createKfSession(String userOpenId, String kfAccount, + String text) throws WeixinException { + return customApi.createKfSession(userOpenId, kfAccount, text); + } + + /** + * 关闭客服会话 + * + * @param userOpenId + * 用户的userOpenId + * @param kfAccount + * 完整客服账号,格式为:账号前缀@公众号微信号 + * @param text + * 附加信息,文本会展示在客服人员的多客服客户端 + * @return 处理结果 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 创建会话 + */ + public JsonResult closeKfSession(String userOpenId, String kfAccount, + String text) throws WeixinException { + return customApi.closeKfSession(userOpenId, kfAccount, text); + } + + /** + * 获取客户的会话状态:获取客户当前的会话状态。 + * + * @param userOpenId + * 用户的openid + * @return 会话对象 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see com.foxinmy.weixin4j.mp.model.KfSession + * @see 获取会话状态 + */ + public KfSession getKfSession(String userOpenId) throws WeixinException { + return customApi.getKfSession(userOpenId); + } + + /** + * 获取客服的会话列表:获取某个客服正在接待的会话列表。 + * + * @param kfAccount + * 完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符。 + * @return 会话列表 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see com.foxinmy.weixin4j.mp.model.KfSession + * @see 获取客服的会话列表 + */ + public List getKfSessionList(String kfAccount) + throws WeixinException { + return customApi.getKfSessionList(kfAccount); + } + + /** + * 获取未接入会话列表:获取当前正在等待队列中的会话列表,此接口最多返回最早进入队列的100个未接入会话。
缺陷:没有count字段 + * + * @return 会话列表 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see com.foxinmy.weixin4j.mp.model.KfSession + * @see 获取客服的会话列表 + */ + public List getKfSessionWaitList() throws WeixinException { + return customApi.getKfSessionWaitList(); + } + + /** + * 上传群发的图文消息,一个图文消息支持1到10条图文 + * + * @param articles + * 图片消息 + * @return 媒体ID + * @throws WeixinException + * @see 上传图文素材 + * @see com.foxinmy.weixin4j.tuple.MpArticle + * @see com.foxinmy.weixin4j.mp.api.MassApi + */ + public String uploadMassArticle(List articles) + throws WeixinException { + return massApi.uploadArticle(articles); + } + + /** + * 上传分组群发的视频素材 + * + * @param video + * 视频对象 其中mediaId媒体文件中上传得到的Id 不能为空 + * @return 上传后的ID + * @throws WeixinException + * + * @see 高级群发 + * @see com.foxinmy.weixin4j.mp.api.MassApi + * @see com.foxinmy.weixin4j.tuple.Video + * @see com.foxinmy.weixin4j.tuple.MpVideo + * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)} + */ + public String uploadMassVideo(Video video) throws WeixinException { + return massApi.uploadVideo(video); + } + + /** + * 分组群发 + * + * @param tuple + * 消息元件 + * @param groupId + * 分组ID + * @return 群发后的消息ID + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massMessage(MassTuple,boolean,int)} + * @throws WeixinException + */ + public String massByGroupId(MassTuple tuple, int groupId) + throws WeixinException { + return massApi.massByGroupId(tuple, groupId); + } + + /** + * 群发消息 + *

+ * 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息, + * 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕 + *

+ * + * @param MassTuple + * 消息元件 + * @param isToAll + * 用于设定是否向全部用户发送,值为true或false,选择true该消息群发给所有用户, + * 选择false可根据group_id发送给指定群组的用户 + * @param groupId + * 分组ID + * @return 群发后的消息ID + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.model.Group + * @see com.foxinmy.weixin4j.tuple.Text + * @see com.foxinmy.weixin4j.tuple.Image + * @see com.foxinmy.weixin4j.tuple.Voice + * @see com.foxinmy.weixin4j.tuple.MpVideo + * @see com.foxinmy.weixin4j.tuple.MpNews + * @see com.foxinmy.weixin4j.mp.api.MassApi + * @see com.foxinmy.weixin4j.tuple.MassTuple + * @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()} + * @see 根据分组群发 + */ + public String massMessage(MassTuple tuple, boolean isToAll, int groupId) + throws WeixinException { + return massApi.massMessage(tuple, isToAll, groupId); + } + + /** + * 分组ID群发图文消息 + * + * @param articles + * 图文列表 + * @param groupId + * 分组ID + * @return 群发后的消息ID + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroupId(Tuple,int)} + * @see 根据分组群发 + * @see com.foxinmy.weixin4j.tuple.MpArticle + * @throws WeixinException + */ + public String massArticleByGroupId(List articles, int groupId) + throws WeixinException { + return massApi.massArticleByGroupId(articles, groupId); + } + + /** + * openId群发 + * + *

+ * 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息, + * 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕 + *

+ * + * @param tuple + * 消息元件 + * @param openIds + * openId列表 + * @return 群发后的消息ID + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.model.User + * @see com.foxinmy.weixin4j.tuple.Text + * @see com.foxinmy.weixin4j.tuple.Image + * @see com.foxinmy.weixin4j.tuple.Voice + * @see com.foxinmy.weixin4j.tuple.MpVideo + * @see com.foxinmy.weixin4j.tuple.MpNews + * @see com.foxinmy.weixin4j.mp.api.MassApi + * @see com.foxinmy.weixin4j.tuple.MassTuple + * @see 根据openid群发 + * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)} + * @see {@link com.foxinmy.weixin4j.mp.api.UserApi#getUser(String)} + */ + public String massByOpenIds(MassTuple tuple, String... openIds) + throws WeixinException { + return massApi.massByOpenIds(tuple, openIds); + } + + /** + * 根据openid群发图文消息 + * + * @param articles + * 图文列表 + * @param openIds + * openId列表 + * @return 群发后的消息ID + * @see 根据openid群发 + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(Tuple,String...)} + * @see com.foxinmy.weixin4j.tuple.MpArticle + * @throws WeixinException + */ + public String massArticleByOpenIds(List articles, + String... openIds) throws WeixinException { + return massApi.massArticleByOpenIds(articles, openIds); + } + + /** + * 删除群发消息 + *

+ * 请注意,只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效,已经收到的用户,还是能在其本地看到消息卡片 + *

+ * + * @param msgid + * 发送出去的消息ID + * @throws WeixinException + * @see 删除群发 + * @see com.foxinmy.weixin4j.mp.api.MassApi + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroupId(Tuple, int)} + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(Tuple, String...) + */ + public JsonResult deleteMassNews(String msgid) throws WeixinException { + return massApi.deleteMassNews(msgid); + } + + /** + * 预览群发消息
开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版 + * + * @param openId + * 接收用户的ID + * @param tuple + * 消息元件 + * @return 处理结果 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.MassApi + * @see com.foxinmy.weixin4j.tuple.MassTuple + * @see 预览群发消息 + */ + public JsonResult previewMassNews(String openId, MassTuple tuple) + throws WeixinException { + return massApi.previewMassNews(openId, tuple); + } + + /** + * 查询群发发送状态 + * + * @param msgId + * 消息ID + * @return 消息发送状态 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.api.MassApi + * @see {@link com.foxinmy.weixin4j.mp.event.MassEventMessage#getStatusDesc(String)} + * @see 查询群发状态 + */ + public String getMassNews(String msgId) throws WeixinException { + return massApi.getMassNews(msgId); + } + + /** + * 获取用户信息 + * + * @param openId + * 用户对应的ID + * @return 用户对象 + * @throws WeixinException + * @see 获取用户信息 + * @see com.foxinmy.weixin4j.mp.model.User + * @see com.foxinmy.weixin4j.mp.api.UserApi + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#getUser(String,Lang)} + */ + public User getUser(String openId) throws WeixinException { + return userApi.getUser(openId); + } + + /** + * 获取用户信息 + *

+ * 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的,对于不同公众号, + * 同一用户的openid不同),公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间 + *

+ * + * @param openId + * 用户对应的ID + * @param lang + * 国家地区语言版本 + * @return 用户对象 + * @throws WeixinException + * @see 获取用户信息 + * @see com.foxinmy.weixin4j.mp.type.Lang + * @see com.foxinmy.weixin4j.mp.model.User + * @see com.foxinmy.weixin4j.mp.api.UserApi + */ + public User getUser(String openId, Lang lang) throws WeixinException { + return userApi.getUser(openId, lang); + } + + /** + * 获取用户一定数量(10000)的关注者列表 + * + * @param nextOpenId + * 第一个拉取的OPENID,不填默认从头开始拉取 + * @return 关注信息 + * @throws WeixinException + * @see 获取关注者列表 + * @see com.foxinmy.weixin4j.mp.model.Following + * @see com.foxinmy.weixin4j.mp.api.UserApi + */ + public Following getFollowing(String nextOpenId) throws WeixinException { + return userApi.getFollowing(nextOpenId); + } + + /** + * 获取用户全部的关注者列表 + *

+ * 当公众号关注者数量超过10000时,可通过填写next_openid的值,从而多次拉取列表的方式来满足需求, + * 将上一次调用得到的返回中的next_openid值,作为下一次调用中的next_openid值 + *

+ * + * @return 用户对象集合 + * @throws WeixinException + * @see 获取关注者列表 + * @see com.foxinmy.weixin4j.mp.model.Following + * @see com.foxinmy.weixin4j.mp.api.UserApi + * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#getFollowing(String)} + */ + public List getAllFollowing() throws WeixinException { + return userApi.getAllFollowing(); + } + + /** + * 设置用户备注名 + * + * @param openId + * 用户ID + * @param remark + * 备注名 + * @throws WeixinException + * @see 设置用户备注名 + * @see com.foxinmy.weixin4j.mp.api.UserApi + */ + public JsonResult remarkUserName(String openId, String remark) + throws WeixinException { + return userApi.remarkUserName(openId, remark); + } + + /** + * 创建分组 + * + * @param name + * 组名称 + * @return group对象 + * @throws WeixinException + * @see 创建分组 + * @see com.foxinmy.weixin4j.mp.model.Group + * @see com.foxinmy.weixin4j.mp.model.Group#toCreateJson() + * @see com.foxinmy.weixin4j.mp.api.GroupApi + */ + public Group createGroup(String name) throws WeixinException { + return groupApi.createGroup(name); + } + + /** + * 查询所有分组 + * + * @return 组集合 + * @throws WeixinException + * @see 查询所有分组 + * @see com.foxinmy.weixin4j.mp.model.Group + * @see com.foxinmy.weixin4j.mp.api.GroupApi + */ + public List getGroups() throws WeixinException { + return groupApi.getGroups(); + } + + /** + * 查询用户所在分组 + * + * @param openId + * 用户对应的ID + * @return 组ID + * @throws WeixinException + * @see 查询用户所在分组 + * @see com.foxinmy.weixin4j.mp.model.Group + * @see com.foxinmy.weixin4j.mp.api.GroupApi + */ + public int getGroupByOpenId(String openId) throws WeixinException { + return groupApi.getGroupByOpenId(openId); + } + + /** + * 修改分组名 + * + * @param groupId + * 组ID + * @param name + * 组名称 + * @throws WeixinException + * @see 修改分组名 + * @see com.foxinmy.weixin4j.mp.model.Group + * @see com.foxinmy.weixin4j.mp.api.GroupApi + */ + public JsonResult modifyGroup(int groupId, String name) + throws WeixinException { + return groupApi.modifyGroup(groupId, name); + } + + /** + * 移动用户到分组 + * + * @param groupId + * 组ID + * @param openId + * 用户对应的ID + * @throws WeixinException + * @see 移动分组 + * @see com.foxinmy.weixin4j.mp.model.Group + * @see com.foxinmy.weixin4j.mp.api.GroupApi + */ + public JsonResult moveGroup(int groupId, String openId) + throws WeixinException { + return groupApi.moveGroup(groupId, openId); + } + + /** + * 批量移动分组 + * + * @param groupId + * 组ID + * @param openIds + * 用户ID列表(不能超过50个) + * @throws WeixinException + * @see 批量移动分组 + * @see com.foxinmy.weixin4j.mp.model.Group + * @see com.foxinmy.weixin4j.mp.api.GroupApi + */ + public JsonResult moveGroup(int groupId, String... openIds) + throws WeixinException { + return groupApi.moveGroup(groupId, openIds); + } + + /** + * 删除用户分组,所有该分组内的用户自动进入默认分组. + * + * @param groupId + * 组ID + * @throws WeixinException + * @see 删除用户分组 + * @see com.foxinmy.weixin4j.mp.model.Group + * @see com.foxinmy.weixin4j.mp.api.GroupApi + */ + public JsonResult deleteGroup(int groupId) throws WeixinException { + return groupApi.deleteGroup(groupId); + } + + /** + * 自定义菜单 + * + * @param btnList + * 菜单列表 + * @throws WeixinException + * @see 创建自定义菜单 + * @see com.foxinmy.weixin4j.model.Button + * @see com.foxinmy.weixin4j.type.ButtonType + * @see com.foxinmy.weixin4j.mp.api.MenuApi + */ + public JsonResult createMenu(List