Merge pull request #2 from wechat-group/develop

Develop
This commit is contained in:
Keung 2016-12-05 12:35:42 +08:00 committed by GitHub
commit 0d56d6c4ca
27 changed files with 1773 additions and 191 deletions

View File

@ -2,7 +2,7 @@ language: java
jdk:
- oraclejdk7
script: "mvn clean install -Dmaven.test.skip=true"
script: "mvn clean package -Dmaven.test.skip=true"
branches:
only:
@ -10,4 +10,4 @@ branches:
notifications:
email:
- binarywang@qq.com
- binaryw@qq.com

View File

@ -7,7 +7,7 @@ Weixin Java Tools 微信公众号/企业号开发Java SDK
1. ***本项目Fork自chanjarster/weixin-java-tools但由于原项目已停止维护故单独维护和发布且发布到maven上的groupId也会不同详细信息见下文。***
1. ***自2.0.0版本以来,公众号的接口调整比较大,主要是为了解决主接口类过于庞大不方便管理的问题,将接口实现代码按模块进行拆分。***
1. 本SDK要求的最低JDK版本是7为满足少量还在使用JDK6的用户的需求特意抽出独立的代码分支项目请参考 https://github.com/binarywang/weixin-java-tools-for-jdk6 其他更早的JDK版本则需要自己改造实现
1. 最新更新2016-10-31 发布2.3.0正式版!
1. 最新更新2016-11-30 发布2.4.0正式版!
===========
@ -39,12 +39,12 @@ maven
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>2.3.0</version>
<version>2.4.0</version>
</dependency>
```
gradle
```groovy
compile 'com.github.binarywang:weixin-java-mp:2.3.0'
compile 'com.github.binarywang:weixin-java-mp:2.4.0'
```
* 企业号:
@ -54,12 +54,12 @@ maven
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-cp</artifactId>
<version>2.3.0</version>
<version>2.4.0</version>
</dependency>
```
gradle
```groovy
compile 'com.github.binarywang:weixin-java-cp:2.3.0'
compile 'com.github.binarywang:weixin-java-cp:2.4.0'
```
===========

View File

@ -2,7 +2,7 @@ allprojects {
apply plugin: 'maven'
group = 'com.github.binarywang'
version = '2.4.0-SNAPSHOT'
version = '2.5.0-SNAPSHOT'
}
subprojects {

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WeiXin Java Tools - Parent</name>
<description>微信公众号、企业号上级POM</description>
@ -64,6 +64,11 @@
<email>withinthefog@gmail.com</email>
<url>https://github.com/withinthefog</url>
</developer>
<developer>
<name>Keung</name>
<email>dongfuqiang1988@163.com</email>
<url>https://github.com/johnnytung</url>
</developer>
</developers>
<scm>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>weixin-java-common</artifactId>

View File

@ -1,5 +1,8 @@
package me.chanjar.weixin.common.bean.menu;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
@ -7,11 +10,8 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
/**
* 企业号菜单
* 菜单公众号和企业号共用的
*
* @author Daniel Qian
*/
@ -61,9 +61,7 @@ public class WxMenu implements Serializable {
@Override
public String toString() {
return "WxMenu{" +
"buttons=" + this.buttons +
'}';
return ToStringUtils.toSimpleString(this);
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>weixin-java-cp</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>weixin-java-mp</artifactId>
<name>WeiXin Java Tools - MP</name>

View File

@ -2,6 +2,7 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult;
/**
* 菜单相关操作接口
@ -56,4 +57,20 @@ public interface WxMpMenuService {
*/
WxMenu menuTryMatch(String userid) throws WxErrorException;
/**
* <pre>
* 获取自定义菜单配置接口
* 本接口将会提供公众号当前使用的自定义菜单的配置如果公众号是通过API调用设置的菜单则返回菜单的开发配置而如果公众号是在公众平台官网通过网站功能发布菜单则本接口返回运营者设置的菜单配置
请注意
1第三方平台开发者可以通过本接口在旗下公众号将业务授权给你后立即通过本接口检测公众号的自定义菜单配置并通过接口再次给公众号设置好自动回复规则以提升公众号运营者的业务体验
2本接口与自定义菜单查询接口的不同之处在于本接口无论公众号的接口是如何设置的都能查询到接口而自定义菜单查询接口则仅能查询到使用API设置的菜单配置
3认证/未认证的服务号/订阅号以及接口测试号均拥有该接口权限
4从第三方平台的公众号登录授权机制上来说该接口从属于消息与菜单权限集
5本接口中返回的图片/语音/视频为临时素材临时素材每次获取都不同3天内有效通过素材管理-获取临时素材接口来获取这些素材本接口返回的图文消息为永久素材素材通过素材管理-获取永久素材接口来获取这些素材
* 接口调用请求说明:
http请求方式: GET请使用https协议
https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN
*</pre>
*/
WxMpGetSelfMenuInfoResult getSelfMenuInfo() throws WxErrorException;
}

View File

@ -2,7 +2,6 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback;
import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderCloseResult;
import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest;
@ -13,8 +12,9 @@ import java.io.File;
import java.util.Map;
/**
* 微信支付相关接口
* Created by Binary Wang on 2016/7/28.
* 微信支付相关接口
* Created by Binary Wang on 2016/7/28.
*
* @author binarywang (https://github.com/binarywang)
*/
public interface WxMpPayService {
@ -24,14 +24,15 @@ public interface WxMpPayService {
* 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
* 该接口提供所有微信支付订单的查询商户可以通过查询订单接口主动查询订单状态完成下一步的业务逻辑
* 需要调用查询接口的情况
当商户后台网络服务器等出现异常商户系统最终未接收到支付通知
调用支付接口后返回系统错误或未知交易状态情况
调用被扫支付API返回USERPAYING的状态
调用关单或撤销接口API之前需确认支付状态
* 当商户后台网络服务器等出现异常商户系统最终未接收到支付通知
* 调用支付接口后返回系统错误或未知交易状态情况
* 调用被扫支付API返回USERPAYING的状态
* 调用关单或撤销接口API之前需确认支付状态
* 接口地址https://api.mch.weixin.qq.com/pay/orderquery
* </pre>
*
* @param transactionId 微信支付分配的商户号
* @param outTradeNo 商户系统内部的订单号当没提供transaction_id时需要传这个
* @param outTradeNo 商户系统内部的订单号当没提供transaction_id时需要传这个
* @throws WxErrorException
*/
WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException;
@ -47,6 +48,7 @@ public interface WxMpPayService {
* 接口地址https://api.mch.weixin.qq.com/pay/closeorder
* 是否需要证书 不需要
* </pre>
*
* @param outTradeNo 商户系统内部的订单号当没提供transaction_id时需要传这个
* @throws WxErrorException
*/
@ -56,16 +58,18 @@ public interface WxMpPayService {
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识"
* 接口地址https://api.mch.weixin.qq.com/pay/unifiedorder
* @throws WxErrorException
* @param request 请求对象
*
* @param request 请求对象注意一些参数如appidmchid等不用设置方法内会自动从配置对象中获取到前提是对应配置中已经设置
* @throws WxErrorException
*/
WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxErrorException;
/**
* 该接口调用统一下单接口并拼装发起支付请求需要的参数
* 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* @param request 请求对象
*
* @param request 请求对象注意一些参数如appidmchid等不用设置方法内会自动从配置对象中获取到前提是对应配置中已经设置
* @throws WxErrorException
*/
Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException;
@ -75,16 +79,33 @@ public interface WxMpPayService {
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
* 接口链接https://api.mch.weixin.qq.com/secapi/pay/refund
* </pre>
*
* @param request 请求对象
* @param keyFile 证书文件对象
* @param keyFile 证书文件对象
* @return 退款操作结果
*/
WxPayRefundResult refund(WxPayRefundRequest request, File keyFile) throws WxErrorException;
/**
* <pre>
* 微信支付-查询退款
* 应用场景
* 提交退款申请后通过调用该接口查询退款状态退款有一定延时用零钱支付的退款20分钟内到账银行卡支付的退款3个工作日后重新查询退款状态
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
* 接口链接https://api.mch.weixin.qq.com/pay/refundquery
* </pre>
* 以下四个参数四选一
* @param transactionId 微信订单号
* @param outTradeNo 商户订单号
* @param outRefundNo 商户退款单号
* @param refundId 微信退款单号
* @return 退款信息
*/
WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId) throws WxErrorException;
/**
* 读取支付结果通知
* 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
*
*/
WxPayJsSDKCallback getJSSDKCallbackData(String xmlData) throws WxErrorException;
@ -93,7 +114,6 @@ public interface WxMpPayService {
* 计算Map键值对是否和签名相符,
* 按照字段名的 ASCII 码从小到大排序(字典序),使用 URL 键值对的 格式( key1=value1&key2=value2...)拼接成字符串
* </pre>
*
*/
boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature);
@ -102,13 +122,29 @@ public interface WxMpPayService {
* <pre>
* 文档详见:
* 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
* 接口地址https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
* 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
* 接口地址https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack
* </pre>
*
* @param request 请求对象
* @param keyFile 证书文件对象
* @param keyFile 证书文件对象
*/
WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile) throws WxErrorException;
/**
* <pre>
* 查询红包记录
* 用于商户对已发放的红包进行查询红包的具体信息可支持普通红包和裂变包
* 请求Url https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
* 是否需要证书 证书及使用说明详见商户证书
* 请求方式 POST
* </pre>
* @param mchBillNo 商户发放红包的商户订单号比如10000098201411111234567890
* @param keyFile 证书文件对象
*/
WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException;
/**
* <pre>
* 企业付款业务是基于微信支付商户平台的资金管理能力为了协助商户方便地实现企业向个人付款针对部分有开发能力的商户提供通过API完成企业付款的功能
@ -118,8 +154,9 @@ public interface WxMpPayService {
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
* 接口链接https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
* </pre>
*
* @param request 请求对象
* @param keyFile 证书文件对象
* @param keyFile 证书文件对象
*/
WxEntPayResult entPay(WxEntPayRequest request, File keyFile) throws WxErrorException;
@ -130,8 +167,9 @@ public interface WxMpPayService {
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
* 接口链接https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo
* </pre>
*
* @param partnerTradeNo 商户订单号
* @param keyFile 证书文件对象
* @param keyFile 证书文件对象
*/
WxEntPayQueryResult queryEntPay(String partnerTradeNo, File keyFile) throws WxErrorException;

View File

@ -14,8 +14,8 @@ public interface WxMpService {
/**
* <pre>
* 验证推送过来的消息的正确性
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=验证消息真实性
* 验证消息的确来自微信服务器
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
* </pre>
*/
boolean checkSignature(String timestamp, String nonce, String signature);
@ -36,7 +36,7 @@ public interface WxMpService {
*
* 程序员在非必要情况下尽量不要主动调用此方法
*
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183&token=&lang=zh_CN
* </pre>
*
* @param forceRefresh 强制刷新
@ -55,7 +55,7 @@ public interface WxMpService {
* 获得jsapi_ticket
* 获得时会检查jsapiToken是否过期如果过期了那么就刷新一下否则就什么都不干
*
* 详情请见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95
* 详情请见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* </pre>
*
* @param forceRefresh 强制刷新
@ -66,7 +66,7 @@ public interface WxMpService {
* <pre>
* 创建调用jsapi时所需要的签名
*
* 详情请见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95
* 详情请见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* </pre>
*/
WxJsapiSignature createJsapiSignature(String url) throws WxErrorException;
@ -75,7 +75,7 @@ public interface WxMpService {
* <pre>
* 上传群发用的图文消息上传后才能群发图文消息
*
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
* </pre>
*
* @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassTagMessage)
@ -86,7 +86,7 @@ public interface WxMpService {
/**
* <pre>
* 上传群发用的视频上传后才能群发视频消息
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
* </pre>
*
* @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassTagMessage)
@ -99,7 +99,7 @@ public interface WxMpService {
* 分组群发消息
* 如果发送图文消息必须先使用 {@link #massNewsUpload(me.chanjar.weixin.mp.bean.WxMpMassNews)} 获得media_id然后再发送
* 如果发送视频消息必须先使用 {@link #massVideoUpload(me.chanjar.weixin.mp.bean.WxMpMassVideo)} 获得media_id然后再发送
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
* </pre>
*/
WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException;
@ -109,7 +109,7 @@ public interface WxMpService {
* 按openId列表群发消息
* 如果发送图文消息必须先使用 {@link #massNewsUpload(me.chanjar.weixin.mp.bean.WxMpMassNews)} 获得media_id然后再发送
* 如果发送视频消息必须先使用 {@link #massVideoUpload(me.chanjar.weixin.mp.bean.WxMpMassVideo)} 获得media_id然后再发送
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
* </pre>
*/
WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException;
@ -263,84 +263,84 @@ public interface WxMpService {
WxMpConfigStorage getWxMpConfigStorage();
/**
* 返回客服接口方法实现类以方便调用个其各种接口
* 返回客服接口方法实现类以方便调用其各个接口
*
* @return WxMpKefuService
*/
WxMpKefuService getKefuService();
/**
* 返回素材相关接口方法的实现类对象以方便调用个其各种接口
* 返回素材相关接口方法的实现类对象以方便调用其各个接口
*
* @return WxMpMaterialService
*/
WxMpMaterialService getMaterialService();
/**
* 返回菜单相关接口方法的实现类对象以方便调用个其各种接口
* 返回菜单相关接口方法的实现类对象以方便调用其各个接口
*
* @return WxMpMenuService
*/
WxMpMenuService getMenuService();
/**
* 返回用户相关接口方法的实现类对象以方便调用个其各种接口
* 返回用户相关接口方法的实现类对象以方便调用其各个接口
*
* @return WxMpUserService
*/
WxMpUserService getUserService();
/**
* 返回用户标签相关接口方法的实现类对象以方便调用个其各种接口
* 返回用户标签相关接口方法的实现类对象以方便调用其各个接口
*
* @return WxMpUserTagService
*/
WxMpUserTagService getUserTagService();
/**
* 返回二维码相关接口方法的实现类对象以方便调用个其各种接口
* 返回二维码相关接口方法的实现类对象以方便调用其各个接口
*
* @return WxMpQrcodeService
*/
WxMpQrcodeService getQrcodeService();
/**
* 返回卡券相关接口方法的实现类对象以方便调用个其各种接口
* 返回卡券相关接口方法的实现类对象以方便调用其各个接口
*
* @return WxMpCardService
*/
WxMpCardService getCardService();
/**
* 返回微信支付相关接口方法的实现类对象以方便调用个其各种接口
* 返回微信支付相关接口方法的实现类对象以方便调用其各个接口
*
* @return WxMpPayService
*/
WxMpPayService getPayService();
/**
* 返回数据分析统计相关接口方法的实现类对象以方便调用个其各种接口
* 返回数据分析统计相关接口方法的实现类对象以方便调用其各个接口
*
* @return WxMpDataCubeService
*/
WxMpDataCubeService getDataCubeService();
/**
* 返回用户黑名单管理相关接口方法的实现类对象以方便调用其各接口
* 返回用户黑名单管理相关接口方法的实现类对象以方便调用其各接口
*
* @return WxMpUserBlacklistService
*/
WxMpUserBlacklistService getBlackListService();
/**
* 返回门店管理相关接口方法的实现类对象以方便调用其各接口
* 返回门店管理相关接口方法的实现类对象以方便调用其各接口
*
* @return WxMpStoreService
*/
WxMpStoreService getStoreService();
/**
* 返回模板消息相关接口方法的实现类对象以方便调用其各接口
* 返回模板消息相关接口方法的实现类对象以方便调用其各接口
*
* @return WxMpTemplateMsgService
*/

View File

@ -1,12 +1,13 @@
package me.chanjar.weixin.mp.api.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMenuService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult;
import me.chanjar.weixin.mp.bean.menu.WxMpSelfMenuInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by Binary Wang on 2016/7/21.
@ -14,7 +15,7 @@ import me.chanjar.weixin.mp.api.WxMpService;
public class WxMpMenuServiceImpl implements WxMpMenuService {
private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/menu";
private static Logger log = LoggerFactory
.getLogger(WxMpMenuServiceImpl.class);
.getLogger(WxMpMenuServiceImpl.class);
private WxMpService wxMpService;
@ -74,10 +75,17 @@ public class WxMpMenuServiceImpl implements WxMpMenuService {
} catch (WxErrorException e) {
// 46003 不存在的菜单数据 46002 不存在的菜单版本
if (e.getError().getErrorCode() == 46003
|| e.getError().getErrorCode() == 46002) {
|| e.getError().getErrorCode() == 46002) {
return null;
}
throw e;
}
}
@Override
public WxMpGetSelfMenuInfoResult getSelfMenuInfo() throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info";
String resultContent = this.wxMpService.get(url, null);
return WxMpGetSelfMenuInfoResult.fromJson(resultContent);
}
}

View File

@ -8,7 +8,6 @@ import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.api.WxMpPayService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback;
import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderCloseResult;
import me.chanjar.weixin.mp.bean.pay.request.*;
import me.chanjar.weixin.mp.bean.pay.result.*;
import org.apache.commons.codec.digest.DigestUtils;
@ -42,13 +41,11 @@ import java.util.*;
*/
public class WxMpPayServiceImpl implements WxMpPayService {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
private static final String[] TRADE_TYPES = new String[]{"JSAPI","NATIVE", "APP"};
private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS",
private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"};
private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS",
"REFUND_SOURCE_UNSETTLED_FUNDS"};
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private WxMpService wxMpService;
public WxMpPayServiceImpl(WxMpService wxMpService) {
@ -57,7 +54,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile)
throws WxErrorException {
throws WxErrorException {
checkParameters(request);
XStream xstream = XStreamInitializer.getInstance();
@ -67,7 +64,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId());
String partnerId = this.wxMpService.getWxMpConfigStorage().getPartnerId();
request.setMchId(partnerId);
request.setNonceStr( System.currentTimeMillis() + "");
request.setNonceStr(System.currentTimeMillis() + "");
request.setOpUserId(partnerId);
String sign = this.createSign(BeanUtils.xmlBean2Map(request), this.wxMpService.getWxMpConfigStorage().getPartnerKey());
request.setSign(sign);
@ -79,11 +76,45 @@ public class WxMpPayServiceImpl implements WxMpPayService {
return result;
}
@Override
public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId) throws WxErrorException {
if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo) && StringUtils.isBlank(outRefundNo) && StringUtils.isBlank(refundId)) ||
(StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo) && StringUtils.isNotBlank(outRefundNo) && StringUtils.isNotBlank(refundId))) {
throw new IllegalArgumentException("transaction_id out_trade_noout_refund_no refund_id 必须四选一");
}
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayRefundQueryRequest.class);
xstream.processAnnotations(WxPayRefundQueryResult.class);
WxPayRefundQueryRequest request = new WxPayRefundQueryRequest();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
request.setTransactionId(StringUtils.trimToNull(transactionId));
request.setOutRefundNo(StringUtils.trimToNull(outRefundNo));
request.setRefundId(StringUtils.trimToNull(refundId));
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId());
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId());
request.setNonceStr(System.currentTimeMillis() + "");
String sign = this.createSign(BeanUtils.xmlBean2Map(request),
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
request.setSign(sign);
String url = PAY_BASE_URL + "/pay/refundquery";
String responseContent = this.executeRequest(url, xstream.toXML(request));
WxPayRefundQueryResult result = (WxPayRefundQueryResult) xstream.fromXML(responseContent);
result.composeRefundRecords(responseContent);
this.checkResult(result);
return result;
}
private void checkResult(WxPayBaseResult result) throws WxErrorException {
if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode())
|| !"SUCCESS".equalsIgnoreCase(result.getResultCode())) {
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1)
.setErrorMsg("返回代码:" + result.getReturnCode() + ", 返回信息: "
.setErrorMsg("返回代码: " + result.getReturnCode() + ", 返回信息: "
+ result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: "
+ result.getErrCode() + ", 错误详情: " + result.getErrCodeDes())
.build());
@ -94,7 +125,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
BeanUtils.checkRequiredFields(request);
if (StringUtils.isNotBlank(request.getRefundAccount())) {
if(!ArrayUtils.contains(REFUND_ACCOUNT, request.getRefundAccount())){
if (!ArrayUtils.contains(REFUND_ACCOUNT, request.getRefundAccount())) {
throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT) + "其中之一");
}
}
@ -118,14 +149,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm,
String signature) {
String signature) {
return signature.equals(this.createSign(kvm,
this.wxMpService.getWxMpConfigStorage().getPartnerKey()));
this.wxMpService.getWxMpConfigStorage().getPartnerKey()));
}
@Override
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile)
throws WxErrorException {
throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPaySendRedpackRequest.class);
xstream.processAnnotations(WxPaySendRedpackResult.class);
@ -136,7 +167,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setNonceStr(System.currentTimeMillis() + "");
String sign = this.createSign(BeanUtils.xmlBean2Map(request),
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
request.setSign(sign);
String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack";
@ -147,25 +178,52 @@ public class WxMpPayServiceImpl implements WxMpPayService {
String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), mchId);
WxPaySendRedpackResult result = (WxPaySendRedpackResult) xstream
.fromXML(responseContent);
.fromXML(responseContent);
this.checkResult(result);
return result;
}
@Override
public WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayRedpackQueryRequest.class);
xstream.processAnnotations(WxPayRedpackQueryResult.class);
WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest();
request.setMchBillNo(mchBillNo);
request.setBillType("MCHT");
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId());
String mchId = this.wxMpService.getWxMpConfigStorage().getPartnerId();
request.setMchId(mchId);
request.setNonceStr(System.currentTimeMillis() + "");
String sign = this.createSign(BeanUtils.xmlBean2Map(request),
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
request.setSign(sign);
String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo";
String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), mchId);
WxPayRedpackQueryResult result = (WxPayRedpackQueryResult) xstream.fromXML(responseContent);
this.checkResult(result);
return result;
}
/**
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
*
* @param packageParams 原始参数
* @param signKey 加密Key( 商户Key)
* @param signKey 加密Key( 商户Key)
* @return 签名字符串
*/
private String createSign(Map<String, String> packageParams, String signKey) {
SortedMap<String, String> sortedMap = new TreeMap<>(packageParams);
StringBuffer toSign = new StringBuffer();
StringBuilder toSign = new StringBuilder();
for (String key : sortedMap.keySet()) {
String value = packageParams.get(key);
if (null != value && !"".equals(value) && !"sign".equals(key)
&& !"key".equals(key)) {
&& !"key".equals(key)) {
toSign.append(key + "=" + value + "&");
}
}
@ -237,7 +295,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request)
throws WxErrorException {
throws WxErrorException {
checkParameters(request);
XStream xstream = XStreamInitializer.getInstance();
@ -249,14 +307,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setNonceStr(System.currentTimeMillis() + "");
String sign = this.createSign(BeanUtils.xmlBean2Map(request),
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
request.setSign(sign);
String url = PAY_BASE_URL + "/pay/unifiedorder";
String responseContent = this.executeRequest(url, xstream.toXML(request));
WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult) xstream
.fromXML(responseContent);
.fromXML(responseContent);
this.checkResult(result);
return result;
}
@ -264,7 +322,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
private void checkParameters(WxPayUnifiedOrderRequest request) throws WxErrorException {
BeanUtils.checkRequiredFields(request);
if (! ArrayUtils.contains(TRADE_TYPES, request.getTradeType())) {
if (!ArrayUtils.contains(TRADE_TYPES, request.getTradeType())) {
throw new IllegalArgumentException("trade_type目前必须为" + Arrays.toString(TRADE_TYPES) + "其中之一");
}
@ -283,7 +341,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
String prepayId = unifiedOrderResult.getPrepayId();
if (StringUtils.isBlank(prepayId)) {
throw new RuntimeException(String.format("Failed to get prepay id due to error code '%s'(%s).",
unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes()));
unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes()));
}
Map<String, String> payInfo = new HashMap<>();
@ -347,7 +405,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
return result;
}
private String executeRequest( String url, String requestStr) throws WxErrorException {
private String executeRequest(String url, String requestStr) throws WxErrorException {
HttpPost httpPost = new HttpPost(url);
if (this.wxMpService.getHttpProxy() != null) {
httpPost.setConfig(RequestConfig.custom().setProxy(this.wxMpService.getHttpProxy()).build());
@ -358,25 +416,25 @@ public class WxMpPayServiceImpl implements WxMpPayService {
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
String result = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}",url, requestStr, result);
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result);
return result;
}
} catch (IOException e) {
this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", url, requestStr, e.getMessage());
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e);
}finally {
} finally {
httpPost.releaseConnection();
}
}
private String executeRequestWithKeyFile( String url, File keyFile, String requestStr, String mchId) throws WxErrorException {
private String executeRequestWithKeyFile(String url, File keyFile, String requestStr, String mchId) throws WxErrorException {
try (FileInputStream inputStream = new FileInputStream(keyFile)) {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(inputStream, mchId.toCharArray());
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
new DefaultHostnameVerifier());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
new DefaultHostnameVerifier());
HttpPost httpPost = new HttpPost(url);
if (this.wxMpService.getHttpProxy() != null) {
@ -387,10 +445,10 @@ public class WxMpPayServiceImpl implements WxMpPayService {
httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1")));
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
String result = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}",url, requestStr, result);
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result);
return result;
}
}finally {
} finally {
httpPost.releaseConnection();
}
} catch (Exception e) {

View File

@ -89,7 +89,7 @@ public class WxMpServiceImpl implements WxMpService {
@Override
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
Lock lock = configStorage.getAccessTokenLock();
Lock lock = this.configStorage.getAccessTokenLock();
try {
lock.lock();
@ -136,7 +136,7 @@ public class WxMpServiceImpl implements WxMpService {
@Override
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
Lock lock = configStorage.getJsapiTicketLock();
Lock lock = this.configStorage.getJsapiTicketLock();
try {
lock.lock();

View File

@ -0,0 +1,44 @@
package me.chanjar.weixin.mp.bean.menu;
import com.google.gson.annotations.SerializedName;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
/**
* <pre>
* Created by Binary Wang on 2016-11-25.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxMpGetSelfMenuInfoResult {
@SerializedName("selfmenu_info")
private WxMpSelfMenuInfo selfMenuInfo;
@SerializedName("is_menu_open")
private Integer isMenuOpen;
public static WxMpGetSelfMenuInfoResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpGetSelfMenuInfoResult.class);
}
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
public WxMpSelfMenuInfo getSelfMenuInfo() {
return selfMenuInfo;
}
public void setSelfMenuInfo(WxMpSelfMenuInfo selfMenuInfo) {
this.selfMenuInfo = selfMenuInfo;
}
public Integer getIsMenuOpen() {
return isMenuOpen;
}
public void setIsMenuOpen(Integer isMenuOpen) {
this.isMenuOpen = isMenuOpen;
}
}

View File

@ -0,0 +1,288 @@
package me.chanjar.weixin.mp.bean.menu;
import com.google.gson.annotations.SerializedName;
import me.chanjar.weixin.common.util.ToStringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* <pre>
* Created by Binary Wang on 2016-11-25.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxMpSelfMenuInfo {
/**
* 菜单按钮
*/
@SerializedName("button")
private List<WxMpSelfMenuButton> buttons;
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
public static class WxMpSelfMenuButton {
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
/**
* <pre>
* 菜单的类型公众平台官网上能够设置的菜单类型有view跳转网页text返回文本下同imgphotovideovoice
* 使用API设置的则有8种详见<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN">自定义菜单创建接口</a>
* </pre>
*/
@SerializedName("type")
private String type;
/**
* 菜单名称
*/
@SerializedName("name")
private String name;
/**
* <pre>
* 对于不同的菜单类型value的值意义不同
* 官网上设置的自定义菜单
* <li>Text:保存文字到value
* <li>Imgvoice保存mediaID到value
* <li>Video保存视频下载链接到value
* <li>News保存图文消息到news_info同时保存mediaID到value
* <li>View保存链接到url</li>
*
* 使用API设置的自定义菜单
* <li>clickscancode_pushscancode_waitmsgpic_sysphotopic_photo_or_album pic_weixinlocation_select保存值到key
* <li>view保存链接到url
* </pre>
*/
@SerializedName("key")
private String key;
/**
* @see #key
*/
@SerializedName("url")
private String url;
/**
* @see #key
*/
@SerializedName("value")
private String value;
/**
* 子菜单信息
*/
@SerializedName("sub_button")
private SubButtons subButtons;
public SubButtons getSubButtons() {
return subButtons;
}
public void setSubButtons(SubButtons subButtons) {
this.subButtons = subButtons;
}
public static class SubButtons {
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
@SerializedName("list")
private List<WxMpSelfMenuButton> subButtons = new ArrayList<>();
public List<WxMpSelfMenuButton> getSubButtons() {
return subButtons;
}
public void setSubButtons(List<WxMpSelfMenuButton> subButtons) {
this.subButtons = subButtons;
}
}
/**
* 图文消息的信息
*/
@SerializedName("news_info")
private NewsInfo newsInfo;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public NewsInfo getNewsInfo() {
return newsInfo;
}
public void setNewsInfo(NewsInfo newsInfo) {
this.newsInfo = newsInfo;
}
public static class NewsInfo {
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
@SerializedName("list")
private List<NewsInButton> news = new ArrayList<>();
public List<NewsInButton> getNews() {
return news;
}
public void setNews(List<NewsInButton> news) {
this.news = news;
}
public static class NewsInButton {
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
/**
* 图文消息的标题
*/
@SerializedName("title")
private String title;
/**
* 摘要
*/
@SerializedName("digest")
private String digest;
/**
* 作者
*/
@SerializedName("author")
private String author;
/**
* show_cover
* 是否显示封面0为不显示1为显示
*/
@SerializedName("show_cover")
private Integer showCover;
/**
* 封面图片的URL
*/
@SerializedName("cover_url")
private String coverUrl;
/**
* 正文的URL
*/
@SerializedName("content_url")
private String contentUrl;
/**
* 原文的URL若置空则无查看原文入口
*/
@SerializedName("source_url")
private String sourceUrl;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDigest() {
return digest;
}
public void setDigest(String digest) {
this.digest = digest;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Integer getShowCover() {
return showCover;
}
public void setShowCover(Integer showCover) {
this.showCover = showCover;
}
public String getCoverUrl() {
return coverUrl;
}
public void setCoverUrl(String coverUrl) {
this.coverUrl = coverUrl;
}
public String getContentUrl() {
return contentUrl;
}
public void setContentUrl(String contentUrl) {
this.contentUrl = contentUrl;
}
public String getSourceUrl() {
return sourceUrl;
}
public void setSourceUrl(String sourceUrl) {
this.sourceUrl = sourceUrl;
}
}
}
}
}

View File

@ -297,6 +297,43 @@ public class WxMpXmlMessage implements Serializable {
@XStreamAlias("DeviceStatus")
private Integer deviceStatus;
public static WxMpXmlMessage fromXml(String xml) {
return XStreamTransformer.fromXml(WxMpXmlMessage.class, xml);
}
public static WxMpXmlMessage fromXml(InputStream is) {
return XStreamTransformer.fromXml(WxMpXmlMessage.class, is);
}
/**
* 从加密字符串转换
*
* @param encryptedXml
* @param wxMpConfigStorage
* @param timestamp
* @param nonce
* @param msgSignature
*/
public static WxMpXmlMessage fromEncryptedXml(String encryptedXml,
WxMpConfigStorage wxMpConfigStorage, String timestamp, String nonce,
String msgSignature) {
WxMpCryptUtil cryptUtil = new WxMpCryptUtil(wxMpConfigStorage);
String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce,
encryptedXml);
return fromXml(plainText);
}
public static WxMpXmlMessage fromEncryptedXml(InputStream is,
WxMpConfigStorage wxMpConfigStorage, String timestamp, String nonce,
String msgSignature) {
try {
return fromEncryptedXml(IOUtils.toString(is, "UTF-8"), wxMpConfigStorage,
timestamp, nonce, msgSignature);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Integer getOpType() {
return opType;
}
@ -611,43 +648,6 @@ public class WxMpXmlMessage implements Serializable {
this.fromUser = fromUser;
}
public static WxMpXmlMessage fromXml(String xml) {
return XStreamTransformer.fromXml(WxMpXmlMessage.class, xml);
}
public static WxMpXmlMessage fromXml(InputStream is) {
return XStreamTransformer.fromXml(WxMpXmlMessage.class, is);
}
/**
* 从加密字符串转换
*
* @param encryptedXml
* @param wxMpConfigStorage
* @param timestamp
* @param nonce
* @param msgSignature
*/
public static WxMpXmlMessage fromEncryptedXml(String encryptedXml,
WxMpConfigStorage wxMpConfigStorage, String timestamp, String nonce,
String msgSignature) {
WxMpCryptUtil cryptUtil = new WxMpCryptUtil(wxMpConfigStorage);
String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce,
encryptedXml);
return fromXml(plainText);
}
public static WxMpXmlMessage fromEncryptedXml(InputStream is,
WxMpConfigStorage wxMpConfigStorage, String timestamp, String nonce,
String msgSignature) {
try {
return fromEncryptedXml(IOUtils.toString(is, "UTF-8"), wxMpConfigStorage,
timestamp, nonce, msgSignature);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public String getStatus() {
return this.status;
}
@ -757,7 +757,7 @@ public class WxMpXmlMessage implements Serializable {
}
public void setSendLocationInfo(
WxMpXmlMessage.SendLocationInfo sendLocationInfo) {
WxMpXmlMessage.SendLocationInfo sendLocationInfo) {
this.sendLocationInfo = sendLocationInfo;
}
@ -793,20 +793,19 @@ public class WxMpXmlMessage implements Serializable {
this.fromKfAccount = fromKfAccount;
}
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
@XStreamAlias("HardWare")
public static class HardWare {
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
/**
* 消息展示目前支持myrank(排行榜)
*/
@XStreamAlias("MessageView")
@XStreamConverter(value = XStreamCDataConverter.class)
private String messageView;
/**
* 消息点击动作目前支持ranklist(点击跳转排行榜)
*/
@ -814,6 +813,11 @@ public class WxMpXmlMessage implements Serializable {
@XStreamConverter(value = XStreamCDataConverter.class)
private String messageAction;
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
public String getMessageView() {
return messageView;
}
@ -833,19 +837,18 @@ public class WxMpXmlMessage implements Serializable {
@XStreamAlias("ScanCodeInfo")
public static class ScanCodeInfo {
@XStreamAlias("ScanType")
@XStreamConverter(value = XStreamCDataConverter.class)
private String scanType;
@XStreamAlias("ScanResult")
@XStreamConverter(value = XStreamCDataConverter.class)
private String scanResult;
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
@XStreamAlias("ScanType")
@XStreamConverter(value = XStreamCDataConverter.class)
private String scanType;
@XStreamAlias("ScanResult")
@XStreamConverter(value = XStreamCDataConverter.class)
private String scanResult;
/**
* 扫描类型一般是qrcode
*/
@ -873,17 +876,16 @@ public class WxMpXmlMessage implements Serializable {
@XStreamAlias("SendPicsInfo")
public static class SendPicsInfo {
@XStreamAlias("PicList")
protected final List<Item> picList = new ArrayList<>();
@XStreamAlias("Count")
private Long count;
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
@XStreamAlias("Count")
private Long count;
@XStreamAlias("PicList")
protected final List<Item> picList = new ArrayList<>();
public Long getCount() {
return this.count;
}
@ -898,15 +900,15 @@ public class WxMpXmlMessage implements Serializable {
@XStreamAlias("item")
public static class Item {
@XStreamAlias("PicMd5Sum")
@XStreamConverter(value = XStreamCDataConverter.class)
private String picMd5Sum;
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
@XStreamAlias("PicMd5Sum")
@XStreamConverter(value = XStreamCDataConverter.class)
private String picMd5Sum;
public String getPicMd5Sum() {
return this.picMd5Sum;
}
@ -985,9 +987,4 @@ public class WxMpXmlMessage implements Serializable {
this.poiname = poiname;
}
}
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
}

View File

@ -0,0 +1,57 @@
package me.chanjar.weixin.mp.bean.pay.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 注释中各行对应含义
* 字段名
* 字段
* 必填
* 示例值
* 类型
* 说明
* Created by Binary Wang on 2016-11-28.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayRedpackQueryRequest extends WxPayBaseRequest {
/**
* 商户订单号
* mch_billno
*
* 10000098201411111234567890
* String(28)
* 商户发放红包的商户订单号
*/
@XStreamAlias("mch_billno")
private String mchBillNo;
/**
* 订单类型
* bill_type
*
* MCHT
* String(32)
* MCHT:通过商户订单号获取红包信息
*/
@XStreamAlias("bill_type")
private String billType;
public String getBillType() {
return billType;
}
public void setBillType(String billType) {
this.billType = billType;
}
public String getMchBillNo() {
return mchBillNo;
}
public void setMchBillNo(String mchBillNo) {
this.mchBillNo = mchBillNo;
}
}

View File

@ -0,0 +1,135 @@
package me.chanjar.weixin.mp.bean.pay.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* Created by Binary Wang on 2016-11-24.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayRefundQueryRequest extends WxPayBaseRequest {
/**
* <pre>
* 设备号
* device_info
*
* String(32)
* 013467007045764
* 商户自定义的终端设备号如门店编号设备的ID等
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 签名类型
* sign_type
*
* String(32)
* HMAC-SHA256
* 签名类型目前支持HMAC-SHA256和MD5默认为MD5
* </pre>
*/
@XStreamAlias("sign_type")
private String signType;
//************以下四选一************
/**
* <pre>
* 微信订单号
* transaction_id
* String(32)
* 1217752501201407033233368018
* 微信订单号
* </pre>
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>
* 商户订单号
* out_trade_no
* String(32)
* 1217752501201407033233368018
* 商户系统内部的订单号
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 商户退款单号
* out_refund_no
* String(32)
* 1217752501201407033233368018
* 商户侧传给微信的退款单号
* </pre>
*/
@XStreamAlias("out_refund_no")
private String outRefundNo;
/**
* <pre>
* 微信退款单号
* refund_id
* String(28)
* 1217752501201407033233368018
* 微信生成的退款单号在申请退款接口有返回
* </pre>
*/
@XStreamAlias("refund_id")
private String refundId;
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getSignType() {
return signType;
}
public void setSignType(String signType) {
this.signType = signType;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getOutRefundNo() {
return outRefundNo;
}
public void setOutRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
}
public String getRefundId() {
return refundId;
}
public void setRefundId(String refundId) {
this.refundId = refundId;
}
}

View File

@ -14,7 +14,7 @@ public class WxPaySendRedpackRequest {
* 商户订单号每个订单号必须唯一 组成mch_id+yyyymmdd+10位一天内不能重复的数字 接口根据商户订单号支持重入如出现超时可再调用
*/
@XStreamAlias("mch_billno")
private String mchBillno;
private String mchBillNo;
/**
* send_name
@ -157,12 +157,12 @@ public class WxPaySendRedpackRequest {
@XStreamAlias("consume_mch_id")
private String consumeMchId;
public String getMchBillno() {
return this.mchBillno;
public String getMchBillNo() {
return mchBillNo;
}
public void setMchBillno(String mchBillno) {
this.mchBillno = mchBillno;
public void setMchBillNo(String mchBillNo) {
this.mchBillNo = mchBillNo;
}
public String getSendName() {

View File

@ -1,10 +1,10 @@
package me.chanjar.weixin.mp.bean.pay.result;
import java.util.List;
import com.google.common.collect.Lists;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.List;
/**
* <pre>
* 查询订单 返回结果对象

View File

@ -0,0 +1,405 @@
package me.chanjar.weixin.mp.bean.pay.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 注释中各行对应含义
* 字段名
* 字段
* 必填
* 示例值
* 类型
* 说明
* Created by Binary Wang on 2016-11-28.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxPayRedpackQueryResult extends WxPayBaseResult {
/**
* <pre>
* 商户订单号
* mch_billno
*
* 10000098201411111234567890
* String(28)
* 商户使用查询API填写的商户单号的原路返回
* </pre>
*/
@XStreamAlias("mch_billno")
private String mchBillNo;
/**
* <pre>
* 红包单号
* detail_id
*
* 1000000000201503283103439304
* String(32)
* 使用API发放现金红包时返回的红包单号
* </pre>
*/
@XStreamAlias("detail_id")
private String detailId;
/**
* <pre>
* 红包状态
* status
*
* RECEIVED
* string(16)
* SENDING:发放中
* SENT:已发放待领取
* FAILED发放失败
* RECEIVED:已领取
* RFUND_ING:退款中
* REFUND:已退款
* </pre>
*/
@XStreamAlias("status")
private String status;
/**
* <pre>
* 发放类型
* send_type
*
* API
* String(32)
* API:通过API接口发放
* UPLOAD:通过上传文件方式发放
* ACTIVITY:通过活动方式发放
* </pre>
*/
@XStreamAlias("send_type")
private String sendType;
/**
* <pre>
* 红包类型
* hb_type
*
* GROUP
* String(32)
* GROUP:裂变红包
* NORMAL:普通红包
* </pre>
*/
@XStreamAlias("hb_type")
private String hbType;
/**
* <pre>
* 红包个数
* total_num
*
* 1
* int
* 红包个数
* </pre>
*/
@XStreamAlias("total_num")
private Integer totalNum;
/**
* <pre>
* 红包金额
* total_amount
*
* 5000
* int
* 红包总金额单位分
* </pre>
*/
@XStreamAlias("total_amount")
private Integer totalAmount;
/**
* <pre>
* 失败原因
* reason
*
* 余额不足
* String(32)
* 发送失败原因
* </pre>
*/
@XStreamAlias("reason")
private String reason;
/**
* <pre>
* 红包发送时间
* send_time
*
* 2015-04-21 20:00:00
* String(32)
* 红包的发送时间
* </pre>
*/
@XStreamAlias("send_time")
private String sendTime;
/**
* <pre>
* 红包退款时间
* refund_time
*
* 2015-04-21 23:03:00
* String(32)
* 红包的退款时间如果其未领取的退款
* </pre>
*/
@XStreamAlias("refund_time")
private String refundTime;
/**
* <pre>
* 红包退款金额
* refund_amount
*
* 8000
* Int
* 红包退款金额
* </pre>
*/
@XStreamAlias("refund_amount")
private Integer refundAmount;
/**
* <pre>
* 祝福语
* wishing
*
* 新年快乐
* String(128)
* 祝福语
* </pre>
*/
@XStreamAlias("wishing")
private String wishing;
/**
* <pre>
* 活动描述
* remark
*
* 新年红包
* String(256)
* 活动描述低版本微信可见
* </pre>
*/
@XStreamAlias("remark")
private String remark;
/**
* <pre>
* 活动名称
* act_name
*
* 新年红包
* String(32)
* 发红包的活动名称
* </pre>
*/
@XStreamAlias("act_name")
private String actName;
/**
* <pre>
* 裂变红包领取列表
* hblist
*
*
*
* 裂变红包的领取列表
* </pre>
*/
@XStreamAlias("hblist")
private String hblist;
/**
* <pre>
* 领取红包的Openid
* openid
*
* ohO4GtzOAAYMp2yapORH3dQB3W18
* String(32)
* 领取红包的openid
* </pre>
*/
@XStreamAlias("openid")
private String openid;
/**
* <pre>
* 金额
* amount
*
* 100
* int
* 领取金额
* </pre>
*/
@XStreamAlias("amount")
private Integer amount;
/**
* <pre>
* 接收时间
* rcv_time
*
* 2015-04-21 20:00:00
* String(32)
* 领取红包的时间
* </pre>
*/
@XStreamAlias("rcv_time")
private String receiveTime;
public String getMchBillNo() {
return mchBillNo;
}
public void setMchBillNo(String mchBillNo) {
this.mchBillNo = mchBillNo;
}
public String getDetailId() {
return detailId;
}
public void setDetailId(String detailId) {
this.detailId = detailId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getSendType() {
return sendType;
}
public void setSendType(String sendType) {
this.sendType = sendType;
}
public String getHbType() {
return hbType;
}
public void setHbType(String hbType) {
this.hbType = hbType;
}
public Integer getTotalNum() {
return totalNum;
}
public void setTotalNum(Integer totalNum) {
this.totalNum = totalNum;
}
public Integer getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(Integer totalAmount) {
this.totalAmount = totalAmount;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getSendTime() {
return sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getRefundTime() {
return refundTime;
}
public void setRefundTime(String refundTime) {
this.refundTime = refundTime;
}
public Integer getRefundAmount() {
return refundAmount;
}
public void setRefundAmount(Integer refundAmount) {
this.refundAmount = refundAmount;
}
public String getWishing() {
return wishing;
}
public void setWishing(String wishing) {
this.wishing = wishing;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getActName() {
return actName;
}
public void setActName(String actName) {
this.actName = actName;
}
public String getHblist() {
return hblist;
}
public void setHblist(String hblist) {
this.hblist = hblist;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public String getReceiveTime() {
return receiveTime;
}
public void setReceiveTime(String receiveTime) {
this.receiveTime = receiveTime;
}
}

View File

@ -0,0 +1,488 @@
package me.chanjar.weixin.mp.bean.pay.result;
import com.google.common.collect.Lists;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.List;
/**
* <pre>
* Created by Binary Wang on 2016-11-24.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayRefundQueryResult extends WxPayBaseResult {
/**
* <pre>
* 设备号
* device_info
*
* String(32)
* 013467007045764
* 终端设备号
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 微信订单号
* transaction_id
*
* String(32)
* 1217752501201407033233368018
* 微信订单号
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>
* 商户订单号
* out_trade_no
*
* String(32)
* 1217752501201407033233368018
* 商户系统内部的订单号
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 订单金额
* total_fee
*
* Int
* 100
* 订单总金额单位为分只能为整数详见支付金额
*/
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>
* 应结订单金额
* settlement_total_fee
*
* Int
* 100
* 应结订单金额=订单金额-非充值代金券金额应结订单金额<=订单金额
*/
@XStreamAlias("settlement_total_fee")
private Integer settlementTotalFee;
/**
* <pre>
* 货币种类
* fee_type
*
* String(8)
* CNY
* 订单金额货币类型符合ISO 4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
*/
@XStreamAlias("fee_type")
private String feeType;
/**
* <pre>
* 现金支付金额
* cash_fee
*
* Int
* 100
* 现金支付金额单位为分只能为整数详见支付金额
*/
@XStreamAlias("cash_fee")
private Integer cashFee;
/**
* <pre>
* 退款笔数
* refund_count
*
* Int
* 1
* 退款记录数
*/
@XStreamAlias("refund_count")
private Integer refundCount;
private List<RefundRecord> refundRecords;
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public Integer getTotalFee() {
return totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public Integer getSettlementTotalFee() {
return settlementTotalFee;
}
public void setSettlementTotalFee(Integer settlementTotalFee) {
this.settlementTotalFee = settlementTotalFee;
}
public String getFeeType() {
return feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getCashFee() {
return cashFee;
}
public void setCashFee(Integer cashFee) {
this.cashFee = cashFee;
}
public Integer getRefundCount() {
return refundCount;
}
public void setRefundCount(Integer refundCount) {
this.refundCount = refundCount;
}
public List<RefundRecord> getRefundRecords() {
return refundRecords;
}
public void setRefundRecords(List<RefundRecord> refundRecords) {
this.refundRecords = refundRecords;
}
public void composeRefundRecords(String xmlString) {
if (this.refundCount != null && this.refundCount > 0) {
this.refundRecords = Lists.newArrayList();
//TODO 暂时待实现
}
}
public static class RefundRecord {
/**
* <pre>
* 商户退款单号
* out_refund_no_$n
*
* String(32)
* 1217752501201407033233368018
* 商户退款单号
* </pre>
*/
@XStreamAlias("out_refund_no")
private String outRefundNo;
/**
* <pre>
* 微信退款单号
* refund_id_$n
*
* String(28)
* 1217752501201407033233368018
* 微信退款单号
* </pre>
*/
@XStreamAlias("refund_id")
private String refundId;
/**
* <pre>
* 退款渠道
* refund_channel_$n
*
* String(16)
* ORIGINAL
* ORIGINAL原路退款 BALANCE退回到余额
* </pre>
*/
@XStreamAlias("refund_channel")
private String refundChannel;
/**
* <pre>
* 申请退款金额
* refund_fee_$n
*
* Int
* 100
* 退款总金额,单位为分,可以做部分退款
* </pre>
*/
@XStreamAlias("refund_fee")
private String refundFee;
/**
* <pre>
* 退款金额
* settlement_refund_fee_$n
*
* Int
* 100
* 退款金额=申请退款金额-非充值代金券退款金额退款金额<=申请退款金额
* </pre>
*/
@XStreamAlias("settlement_refund_fee")
private String settlementRefundFee;
/**
* <pre>
* 退款资金来源
* refund_account
*
* String(30)
* REFUND_SOURCE_RECHARGE_FUNDS
* REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款/基本账户, REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款
* </pre>
*/
@XStreamAlias("refund_account")
private String refundAccount;
/**
* <pre>
* 代金券类型
* coupon_type_$n
*
* Int
* CASH
* CASH--充值代金券 , NO_CASH---非充值代金券订单使用代金券时有返回取值CASHNO_CASH$n为下标,从0开始编号举例coupon_type_$0
* </pre>
*/
@XStreamAlias("coupon_type")
private String couponType;
/**
* <pre>
* 代金券退款金额
* coupon_refund_fee_$n
*
* Int
* 100
* 代金券退款金额<=退款金额退款金额-代金券或立减优惠退款金额为现金说明详见代金券或立减优惠
* </pre>
*/
@XStreamAlias("coupon_refund_fee")
private String couponRefundFee;
/**
* <pre>
* 退款代金券使用数量
* coupon_refund_count_$n
*
* Int
* 1
* 退款代金券使用数量 ,$n为下标,从0开始编号
* </pre>
*/
@XStreamAlias("coupon_refund_count")
private String couponRefundCount;
private List<RefundCoupon> refundCoupons;
/**
* <pre>
* 退款状态
* refund_status_$n
*
* String(16)
* SUCCESS
* 退款状态
* SUCCESS退款成功
* FAIL退款失败
* PROCESSING退款处理中
* CHANGE转入代发
* 退款到银行发现用户的卡作废或者冻结了导致原路退款银行卡失败资金回流到商户的现金帐号需要商户人工干预通过线下或者财付通转账的方式进行退款
* </pre>
*/
@XStreamAlias("refund_status")
private String refundStatus;
/**
* <pre>
* 退款入账账户
* refund_recv_accout_$n
*
* String(64)
* 招商银行信用卡0403
* 取当前退款单的退款入账方1退回银行卡{银行名称}{卡类型}{卡尾号}2退回支付用户零钱:支付用户零钱
* </pre>
*/
@XStreamAlias("refund_recv_accout")
private String refundRecvAccout;
public String getOutRefundNo() {
return outRefundNo;
}
public void setOutRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
}
public String getRefundId() {
return refundId;
}
public void setRefundId(String refundId) {
this.refundId = refundId;
}
public String getRefundChannel() {
return refundChannel;
}
public void setRefundChannel(String refundChannel) {
this.refundChannel = refundChannel;
}
public String getRefundFee() {
return refundFee;
}
public void setRefundFee(String refundFee) {
this.refundFee = refundFee;
}
public String getSettlementRefundFee() {
return settlementRefundFee;
}
public void setSettlementRefundFee(String settlementRefundFee) {
this.settlementRefundFee = settlementRefundFee;
}
public String getRefundAccount() {
return refundAccount;
}
public void setRefundAccount(String refundAccount) {
this.refundAccount = refundAccount;
}
public String getCouponType() {
return couponType;
}
public void setCouponType(String couponType) {
this.couponType = couponType;
}
public String getCouponRefundFee() {
return couponRefundFee;
}
public void setCouponRefundFee(String couponRefundFee) {
this.couponRefundFee = couponRefundFee;
}
public String getCouponRefundCount() {
return couponRefundCount;
}
public void setCouponRefundCount(String couponRefundCount) {
this.couponRefundCount = couponRefundCount;
}
public List<RefundCoupon> getRefundCoupons() {
return refundCoupons;
}
public void setRefundCoupons(List<RefundCoupon> refundCoupons) {
this.refundCoupons = refundCoupons;
}
public String getRefundStatus() {
return refundStatus;
}
public void setRefundStatus(String refundStatus) {
this.refundStatus = refundStatus;
}
public String getRefundRecvAccout() {
return refundRecvAccout;
}
public void setRefundRecvAccout(String refundRecvAccout) {
this.refundRecvAccout = refundRecvAccout;
}
public static class RefundCoupon {
/**
* <pre>
* 退款代金券批次ID
* coupon_refund_batch_id_$n_$m
*
* String(20)
* 100
* 退款代金券批次ID ,$n为下标$m为下标从0开始编号
* </pre>
*/
@XStreamAlias("coupon_refund_batch_id")
private String couponRefundBatchId;
/**
* <pre>
* 退款代金券ID
* coupon_refund_id_$n_$m
*
* String(20)
* 10000
* 退款代金券ID, $n为下标$m为下标从0开始编号
* </pre>
*/
@XStreamAlias("coupon_refund_id")
private String couponRefundId;
/**
* <pre>
* 单个退款代金券支付金额
* coupon_refund_fee_$n_$m
*
* Int
* 100
* 单个退款代金券支付金额, $n为下标$m为下标从0开始编号
* </pre>
*/
@XStreamAlias("coupon_refund_fee")
private String couponRefundFee;
public RefundCoupon(String couponRefundBatchId, String couponRefundId, String couponRefundFee) {
this.couponRefundBatchId = couponRefundBatchId;
this.couponRefundId = couponRefundId;
this.couponRefundFee = couponRefundFee;
}
}
}
}

View File

@ -1,18 +1,17 @@
package me.chanjar.weixin.mp.api.impl;
import me.chanjar.weixin.mp.api.WxMpService;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
/**
* 测试菜单
@ -28,11 +27,22 @@ public class WxMpMenuServiceImplTest {
protected WxMpService wxService;
@Test(dataProvider = "menu")
public void testCreateMenu(WxMenu wxMenu) throws WxErrorException {
public void testMenuCreate(WxMenu wxMenu) throws WxErrorException {
System.out.println(wxMenu.toJson());
this.wxService.getMenuService().menuCreate(wxMenu);
}
@Test
public void testMenuTryMatch() throws Exception {
//TODO
}
@Test
public void testGetSelfMenuInfo() throws Exception {
WxMpGetSelfMenuInfoResult selfMenuInfo = this.wxService.getMenuService().getSelfMenuInfo();
System.out.println(selfMenuInfo);
}
@Test
public void testCreateMenu2() throws WxErrorException {
String a = "{\n"
@ -77,15 +87,15 @@ public class WxMpMenuServiceImplTest {
this.wxService.getMenuService().menuCreate(menu);
}
@Test(dependsOnMethods = { "testCreateMenu"})
public void testGetMenu() throws WxErrorException {
@Test(dependsOnMethods = { "testMenuCreate"})
public void testMenuGet() throws WxErrorException {
WxMenu wxMenu = this.wxService.getMenuService().menuGet();
Assert.assertNotNull(wxMenu);
System.out.println(wxMenu.toJson());
}
@Test(dependsOnMethods = { "testGetMenu"})
public void testDeleteMenu() throws WxErrorException {
@Test(dependsOnMethods = { "testMenuGet"})
public void testMenuDelete() throws WxErrorException {
this.wxService.getMenuService().menuDelete();
}

View File

@ -9,9 +9,7 @@ import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest;
import me.chanjar.weixin.mp.bean.pay.result.WxPayRefundResult;
import me.chanjar.weixin.mp.bean.pay.result.WxPaySendRedpackResult;
import me.chanjar.weixin.mp.bean.pay.result.WxPayUnifiedOrderResult;
import me.chanjar.weixin.mp.bean.pay.result.*;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
@ -20,6 +18,7 @@ import java.io.File;
/**
* 测试支付相关接口
* Created by Binary Wang on 2016/7/28.
*
* @author binarywang (https://github.com/binarywang)
*/
@Test
@ -34,6 +33,9 @@ public class WxMpPayServiceImplTest {
}
/**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refund(WxPayRefundRequest, File)} .
*/
@Test
public void testRefund() throws Exception {
WxPayRefundRequest request = new WxPayRefundRequest();
@ -46,33 +48,64 @@ public class WxMpPayServiceImplTest {
System.err.println(result);
}
/**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refundQuery(String, String, String, String)} .
*/
@Test
public void testRefundQuery() throws Exception {
WxPayRefundQueryResult result = this.wxService.getPayService().refundQuery("1", "", "", "");
result = this.wxService.getPayService().refundQuery("", "2", "", "");
System.err.println(result);
result = this.wxService.getPayService().refundQuery("", "", "3", "");
System.err.println(result);
result = this.wxService.getPayService().refundQuery("", "", "", "4");
System.err.println(result);
//测试四个参数都填的情况应该报异常的
result = this.wxService.getPayService().refundQuery("1", "2", "3", "4");
System.err.println(result);
}
@Test
public void testCheckJSSDKCallbackDataSignature() throws Exception {
}
/**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#sendRedpack(WxPaySendRedpackRequest, File)} .
*/
@Test
public void testSendRedpack() throws Exception {
WxPaySendRedpackRequest request = new WxPaySendRedpackRequest();
request.setActName("abc");
request.setClientIp("aaa");
request.setMchBillno("aaaa");
request.setMchBillNo("aaaa");
request
.setReOpenid(((WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid());
.setReOpenid(((WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid());
File keyFile = new File("E:\\dlt.p12");
WxPaySendRedpackResult redpackResult = this.wxService.getPayService().sendRedpack(request, keyFile);
System.err.println(redpackResult);
}
/**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryRedpack(String, File)}.
*/
@Test
public void testQueryRedpack() throws Exception {
File keyFile = new File("E:\\dlt.p12");
WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa", keyFile);
System.err.println(redpackResult);
}
/**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#unifiedOrder(WxPayUnifiedOrderRequest)}.
*/
@Test
public void testUnifiedOrder() throws WxErrorException {
WxPayUnifiedOrderResult result = this.wxService.getPayService()
.unifiedOrder(WxPayUnifiedOrderRequest.builder().body("1111111")
.totalFee(1).spbillCreateIp("111111").notifyURL("111111")
.tradeType("JSAPI").openid("122").outTradeNo("111111").build());
.unifiedOrder(WxPayUnifiedOrderRequest.builder().body("1111111")
.totalFee(1).spbillCreateIp("111111").notifyURL("111111")
.tradeType("JSAPI").openid("122").outTradeNo("111111").build());
System.err.println(result);
}

View File

@ -39,9 +39,10 @@ public class WxMpTemplateMsgServiceImplTest {
.toUser(configStorage.getOpenid())
.templateId(configStorage.getTemplateId()).build();
templateMessage.addWxMpTemplateData(
new WxMpTemplateData("first", dateFormat.format(new Date())));
new WxMpTemplateData("first", dateFormat.format(new Date()),"#FF00FF"));
templateMessage.addWxMpTemplateData(
new WxMpTemplateData("remark", RandomStringUtils.randomAlphanumeric(100), "#FF00FF"));
templateMessage.setUrl(" ");
String msgId = this.wxService.getTemplateMsgService().sendTemplateMsg(templateMessage);
Assert.assertNotNull(msgId);
System.out.println(msgId);

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>weixin-java-osgi</artifactId>