Merge pull request #107 from fengyapengwyy/wyying

增加摇一摇部分接口,会员接口
This commit is contained in:
jinyu 2016-12-26 13:23:00 +08:00 committed by GitHub
commit c990ff5770
60 changed files with 3742 additions and 467 deletions

44
pom.xml
View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.7.3</version>
<version>1.7.4-SNAPSHOT</version>
<packaging>pom</packaging>
<name>weixin4j</name>
<url>https://github.com/foxinmy/weixin4j</url>
@ -44,7 +44,6 @@
<module>weixin4j-mp</module>
<module>weixin4j-qy</module>
<module>weixin4j-server</module>
<module>weixin4j-example</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -54,6 +53,18 @@
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@ -211,8 +222,8 @@
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>*.xml</include>
<include>*.properties</include>
</includes>
</resource>
</resources>
@ -248,14 +259,27 @@
</dependency>
</dependencies>
</dependencyManagement>
<distributionManagement>
<snapshotRepository>
<id>oss-snapshot</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>oss-release</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
<id>Project Releases</id>
<name>Project Releases</name>
<url>http://repo.wyying.com/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>Project Snapshots</id>
<name>Project Snapshots</name>
<url>http://repo.wyying.com/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<!--<distributionManagement>-->
<!--<snapshotRepository>-->
<!--<id>oss-snapshot</id>-->
<!--<url>https://oss.sonatype.org/content/repositories/snapshots/</url>-->
<!--</snapshotRepository>-->
<!--<repository>-->
<!--<id>oss-release</id>-->
<!--<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>-->
<!--</repository>-->
<!--</distributionManagement>-->
</project>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.7.3</version>
<version>1.7.4-SNAPSHOT</version>
</parent>
<artifactId>weixin4j-base</artifactId>
<name>weixin4j-base</name>

View File

@ -20,6 +20,8 @@ public abstract class BaseApi {
protected final WeixinRequestExecutor weixinExecutor;
private final Pattern uriPattern = Pattern.compile("(\\{[^\\}]*\\})");
public BaseApi() {
this.weixinExecutor = new WeixinRequestExecutor();
}
@ -28,8 +30,7 @@ public abstract class BaseApi {
protected String getRequestUri(String key) {
String url = weixinBundle().getString(key);
Pattern p = Pattern.compile("(\\{[^\\}]*\\})");
Matcher m = p.matcher(url);
Matcher m = uriPattern.matcher(url);
StringBuffer sb = new StringBuffer();
String sub = null;
while (m.find()) {

View File

@ -36,7 +36,7 @@ public class MchApi extends BaseApi {
}
protected final WeixinPayAccount weixinAccount;
protected final WeixinSignature weixinSignature;
protected final WeixinPaymentSignature weixinSignature;
private volatile WeixinRequestExecutor weixinSSLExecutor;
public MchApi(WeixinPayAccount weixinAccount) {

View File

@ -16,6 +16,7 @@ import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.exception.WeixinPayException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
@ -85,8 +86,14 @@ public class PayApi extends MchApi {
String payJsRequestXml = XmlStream.toXML(payPackage);
WeixinResponse response = weixinExecutor.post(
getRequestUri("order_create_uri"), payJsRequestXml);
return response.getAsObject(new TypeReference<PrePay>() {
});
boolean validatePaySign = weixinSignature.validatePaySign(response);
if(validatePaySign) {
PrePay prePay = response.getAsObject(new TypeReference<PrePay>() {
});
prePay.setResponse(response.getAsString());
return prePay;
}
throw new WeixinPayException("验证签名信息失败,返回数据可能被篡改");
}
/**
@ -124,19 +131,20 @@ public class PayApi extends MchApi {
MICROPayRequest microPayRequest = response
.getAsObject(new TypeReference<MICROPayRequest>() {
});
microPayRequest.setResponse(response.getAsString());
microPayRequest.setPaymentAccount(weixinAccount);
return microPayRequest;
}
PrePay prePay = createPrePay(payPackage);
if (TradeType.APP.name().equals(tradeType)) {
return new APPPayRequest(prePay.getPrepayId(), weixinAccount);
return new APPPayRequest(prePay, weixinAccount);
} else if (TradeType.JSAPI.name().equals(tradeType)) {
return new JSAPIPayRequest(prePay.getPrepayId(), weixinAccount);
return new JSAPIPayRequest(prePay, weixinAccount);
} else if (TradeType.NATIVE.name().equals(tradeType)) {
return new NATIVEPayRequest(prePay.getPrepayId(),
return new NATIVEPayRequest(prePay,
prePay.getCodeUrl(), weixinAccount);
} else if (TradeType.WAP.name().equals(tradeType)) {
return new WAPPayRequest(prePay.getPrepayId(), weixinAccount);
return new WAPPayRequest(prePay, weixinAccount);
} else {
throw new WeixinException("unknown tradeType:" + tradeType);
}
@ -172,6 +180,36 @@ public class PayApi extends MchApi {
return createPayRequest(payPackage);
}
/**
* 创建JSAPI支付请求对象
*
* @param openId
* 用户ID
* @param body
* 订单描述
* @param outTradeNo
* 订单号
* @param totalFee
* 订单总额()
* @param notifyUrl
* 支付通知地址
* @param createIp
* ip地址
* @param attach
* 附加数据 非必填
* @see com.foxinmy.weixin4j.payment.mch.JSAPIPayRequest
* @return JSAPI支付对象
* @throws WeixinException
*/
public MchPayRequest createJSPayRequest(String openId, String body,
String outTradeNo, long totalFee, String notifyUrl,
String createIp, String attach) throws WeixinException {
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
totalFee, notifyUrl, createIp, TradeType.JSAPI, openId, null,
null, attach);
return createPayRequest(payPackage);
}
/**
* <p>
* 生成编辑地址请求
@ -273,6 +311,43 @@ public class PayApi extends MchApi {
return new NativePayResponse(weixinAccount, prePay.getPrepayId());
}
/**
* 创建Native支付(扫码支付)回调对象模式一
*
* @param productId
* 商品ID
* @param body
* 商品描述
* @param outTradeNo
* 商户内部唯一订单号
* @param totalFee
* 商品总额 单位元
* @param notifyUrl
* 支付回调URL
* @param createIp
* 订单生成的机器 IP
* @param attach
* 附加数据 非必填
* @return Native回调对象
* @see com.foxinmy.weixin4j.payment.mch.NativePayResponse
* @see <a href=
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">扫码支付
* </a>
* @see <a href=
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
* </a>
* @throws WeixinException
*/
public NativePayResponse createNativePayResponse(String productId,
String body, String outTradeNo, long totalFee, String notifyUrl,
String createIp, String attach) throws WeixinException {
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
totalFee, notifyUrl, createIp, TradeType.NATIVE, null, null,
productId, attach);
PrePay prePay = createPrePay(payPackage);
return new NativePayResponse(weixinAccount, prePay.getPrepayId());
}
/**
* 创建Native支付(扫码支付)链接模式二
*
@ -309,6 +384,42 @@ public class PayApi extends MchApi {
return createPayRequest(payPackage);
}
/**
* 创建Native支付(扫码支付)链接模式二
*
* @param productId
* 商品ID
* @param body
* 商品描述
* @param outTradeNo
* 商户内部唯一订单号
* @param totalFee
* 商品总额 单位元
* @param notifyUrl
* 支付回调URL
* @param createIp
* 订单生成的机器 IP
* @param attach
* 附加数据 非必填
* @return Native支付对象
* @see com.foxinmy.weixin4j.payment.mch.NATIVEPayRequest
* @see <a href=
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1">扫码支付
* </a>
* @see <a href=
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5">模式二
* </a>
* @throws WeixinException
*/
public MchPayRequest createNativePayRequest(String productId, String body,
String outTradeNo, long totalFee, String notifyUrl,
String createIp, String attach) throws WeixinException {
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
totalFee, notifyUrl, createIp, TradeType.NATIVE, null, null,
productId, attach);
return createPayRequest(payPackage);
}
/**
* 创建APP支付请求对象
*
@ -340,6 +451,37 @@ public class PayApi extends MchApi {
return createPayRequest(payPackage);
}
/**
* 创建APP支付请求对象
*
* @param body
* 商品描述
* @param outTradeNo
* 商户内部唯一订单号
* @param totalFee
* 商品总额 单位元
* @param notifyUrl
* 支付回调URL
* @param createIp
* 订单生成的机器 IP
* @param attach
* 附加数据 非必填
* @return APP支付对象
* @see com.foxinmy.weixin4j.payment.mch.APPPayRequest
* @see <a href=
* "https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1">
* APP支付</a>
* @throws WeixinException
*/
public MchPayRequest createAppPayRequest(String body, String outTradeNo,
long totalFee, String notifyUrl, String createIp, String attach)
throws WeixinException {
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
totalFee, notifyUrl, createIp, TradeType.APP, null, null, null,
attach);
return createPayRequest(payPackage);
}
/**
* 创建WAP支付请求对象
*
@ -371,6 +513,37 @@ public class PayApi extends MchApi {
return createPayRequest(payPackage);
}
/**
* 创建WAP支付请求对象
*
* @param body
* 商品描述
* @param outTradeNo
* 商户内部唯一订单号
* @param totalFee
* 商品总额 单位元
* @param notifyUrl
* 支付回调URL
* @param createIp
* 订单生成的机器 IP
* @param attach
* 附加数据 非必填
* @return WAP支付对象
* @see com.foxinmy.weixin4j.payment.mch.WAPPayRequest
* @see <a href=
* "https://pay.weixin.qq.com/wiki/doc/api/wap.php?chapter=15_1">WAP支付
* </a>
* @throws WeixinException
*/
public MchPayRequest createWapPayRequest(String body, String outTradeNo,
long totalFee, String notifyUrl, String createIp, String attach)
throws WeixinException {
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
totalFee, notifyUrl, createIp, TradeType.WAP, null, null, null,
attach);
return createPayRequest(payPackage);
}
/**
* 提交被扫支付
*
@ -395,11 +568,43 @@ public class PayApi extends MchApi {
* @throws WeixinException
*/
public MchPayRequest createMicroPayRequest(String authCode, String body,
String outTradeNo, double totalFee, String createIp, String attach)
String outTradeNo, double totalFee, String createIp, String attach)
throws WeixinException {
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
totalFee, null, createIp, TradeType.MICROPAY, null, authCode,
null, attach);
totalFee, null, createIp, TradeType.MICROPAY, null, authCode,
null, attach);
return createPayRequest(payPackage);
}
/**
* 提交被扫支付
*
* @param authCode
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
* @param body
* 商品描述
* @param outTradeNo
* 商户内部唯一订单号
* @param totalFee
* 商品总额 单位元
* @param createIp
* 订单生成的机器 IP
* @param attach
* 附加数据 非必填
* @return 支付的订单信息
* @see com.foxinmy.weixin4j.payment.mch.MICROPayRequest
* @see com.foxinmy.weixin4j.payment.mch.Order
* @see <a href=
* "http://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10">
* 提交被扫支付API</a>
* @throws WeixinException
*/
public MchPayRequest createMicroPayRequest(String authCode, String body,
String outTradeNo, long totalFee, String createIp, String attach)
throws WeixinException {
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
totalFee, null, createIp, TradeType.MICROPAY, null, authCode,
null, attach);
return createPayRequest(payPackage);
}
@ -470,13 +675,51 @@ public class PayApi extends MchApi {
double totalFee, double refundFee, CurrencyType refundFeeType,
String opUserId, RefundAccountType refundAccountType)
throws WeixinException {
return applyRefund(idQuery, outRefundNo, DateUtil.formatYuan2Fen(totalFee), DateUtil.formatYuan2Fen(refundFee), refundFeeType, opUserId,
refundAccountType);
}
/**
* 申请退款(请求需要双向证书)
* <p>
* 当交易发生之后一段时间内由于买家或者卖家的原因需要退款时卖家可以通过退款接口将支付款退还给买家微信支付将在收到退款请求并且验证成功之后
* 按照退款规则将支付款按原路退到买家帐号上
* </p>
* <p style="color:red">
* 1.交易时间超过半年的订单无法提交退款
* 2.微信支付退款支持单笔交易分多次退款多次退款需要提交原支付订单的商户订单号和设置不同的退款单号一笔退款失败后重新提交
* 要采用原来的退款单号总退款金额不能超过用户实际支付金额
* </p>
*
* @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
* 操作员帐号, 默认为商户号
* @param refundAccountType
* @return 退款申请结果
* @see com.foxinmy.weixin4j.payment.mch.RefundResult
* @see <a href=
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4">
* 申请退款API</a>
* @since V3
* @throws WeixinException
*/
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo, long totalFee, long refundFee, CurrencyType refundFeeType,
String opUserId, RefundAccountType refundAccountType) throws WeixinException {
WeixinResponse response = null;
Map<String, String> map = createBaseRequestMap(idQuery);
map.put("out_refund_no", outRefundNo);
map.put("total_fee",
Integer.toString(DateUtil.formatYuan2Fen(totalFee)));
map.put("refund_fee",
Integer.toString(DateUtil.formatYuan2Fen(refundFee)));
map.put("total_fee", String.valueOf(totalFee));
map.put("refund_fee", String.valueOf(refundFee));
if (StringUtil.isBlank(opUserId)) {
opUserId = weixinAccount.getMchId();
}
@ -507,7 +750,7 @@ public class PayApi extends MchApi {
* 商户系统内部的退款单号, 户系统内部唯一,同一退款单号多次请求只退一笔
* @param totalFee
* 订单总金额,单位为元
* @see {@link #applyRefund(IdQuery, String, double, double,CurrencyType, String)}
* @see {@link #applyRefund(IdQuery, String, double, double,CurrencyType, String,RefundAccountType)}
*/
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
double totalFee) throws WeixinException {
@ -515,6 +758,23 @@ public class PayApi extends MchApi {
null, null);
}
/**
* 退款申请(全额退款)
*
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
* @param outRefundNo
* 商户系统内部的退款单号, 户系统内部唯一,同一退款单号多次请求只退一笔
* @param totalFee
* 订单总金额,单位为元
* @see {@link #applyRefund(IdQuery, String, double, double,CurrencyType, String,RefundAccountType)}
*/
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
long totalFee) throws WeixinException {
return applyRefund(idQuery, outRefundNo, totalFee, totalFee, null, null, null);
}
/**
* 冲正订单(需要证书)</br> 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br> 接口逻辑:
* 付失败的关单,支付成功的撤销支付</br> <font color="red">7天以内的单可撤销,其他正常支付的单
@ -764,4 +1024,6 @@ public class PayApi extends MchApi {
return response.getAsObject(new TypeReference<OpenIdResult>() {
});
}
}

View File

@ -2,65 +2,82 @@ package com.foxinmy.weixin4j.exception;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.WeixinErrorUtil;
import com.foxinmy.weixin4j.util.WeixinErrorUtil2;
/**
* 调用微信接口抛出的异常
*
* @className WeixinException
* @author jinyu(foxinmy@gmail.com)
* @className WeixinException
* @date 2014年4月10日
* @since JDK 1.6
* @see
* @since JDK 1.6
*/
public class WeixinException extends Exception {
private static final long serialVersionUID = 7148145661883468514L;
private static final long serialVersionUID = 7148145661883468514L;
private String code;
private String desc;
private String code;
private String desc;
private String describeErrorMsg;
public WeixinException(String code, String desc) {
this.code = code;
this.desc = desc;
}
public WeixinException(String code, String desc) {
this(code, desc, null);
}
public WeixinException(String desc) {
this.code = "-1";
this.desc = desc;
}
public WeixinException(Throwable e) {
super(e);
}
public WeixinException(String errorCode, String errorMsg, String describeErrorMsg) {
this.code = errorCode;
this.desc = errorMsg;
if (describeErrorMsg == null) {
this.describeErrorMsg = errorMsg;
} else {
this.describeErrorMsg = describeErrorMsg;
}
}
public WeixinException(String message, Throwable cause) {
super(message, cause);
}
public WeixinException(String desc) {
this.code = "-1";
this.desc = desc;
}
public String getErrorCode() {
return code;
}
public String getDescribeErrorMsg() {
return describeErrorMsg;
}
public String getErrorDesc() {
return desc;
}
public String getErrorText() {
return WeixinErrorUtil.getText(code);
}
public WeixinException(Throwable e) {
super(e);
}
@Override
public String getMessage() {
if (StringUtil.isNotBlank(code)) {
StringBuilder buf = new StringBuilder();
buf.append(code).append(" >> ").append(desc);
String text = getErrorText();
if (StringUtil.isNotBlank(text)) {
buf.append(" >> ").append(text);
}
return buf.toString();
} else {
return super.getMessage();
}
}
public WeixinException(String message, Throwable cause) {
super(message, cause);
}
public String getErrorCode() {
return code;
}
public String getErrorDesc() {
return desc;
}
public String getErrorText() {
return WeixinErrorUtil2.getText(code);
}
@Override
public String getMessage() {
if (StringUtil.isNotBlank(code)) {
StringBuilder buf = new StringBuilder();
buf.append(code).append(" >> ").append(desc);
String text = getErrorText();
if (StringUtil.isNotBlank(text)) {
buf.append(" >> ").append(text);
}
return buf.toString();
} else {
return super.getMessage();
}
}
}

View File

@ -6,9 +6,11 @@ import java.io.InputStream;
import java.io.OutputStream;
import com.foxinmy.weixin4j.http.ContentType;
import com.foxinmy.weixin4j.util.Consts;
public class StringEntity implements HttpEntity {
private final byte[] content;
private final byte[] content;
private final ContentType contentType;
public StringEntity(String body) {
@ -40,4 +42,10 @@ public class StringEntity implements HttpEntity {
outstream.write(this.content);
outstream.flush();
}
public String getContentString() {
return new String(this.content, Consts.UTF_8);
}
}

View File

@ -28,21 +28,24 @@ import com.foxinmy.weixin4j.http.message.XmlMessageConverter;
import com.foxinmy.weixin4j.logging.InternalLogLevel;
import com.foxinmy.weixin4j.logging.InternalLogger;
import com.foxinmy.weixin4j.logging.InternalLoggerFactory;
import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.WeixinErrorUtil2;
/**
* 负责微信请求的执行
*
* @author jy
* @className WeixinRequestExecutor
* @author jinyu(foxinmy@gmail.com)
* @date 2015年8月15日
* @since JDK 1.6
* @see
* @since JDK 1.6
*/
public class WeixinRequestExecutor {
protected final InternalLogger logger = InternalLoggerFactory
.getInstance(getClass());
protected final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());
private static final String SUCCESS_CODE = ",0,success,";
@ -58,7 +61,7 @@ public class WeixinRequestExecutor {
/**
* Post方法执行微信请求
*
*
* @param url
* 请求URL
* @param body
@ -75,7 +78,7 @@ public class WeixinRequestExecutor {
/**
* Post方法执行微信请求用于文件上传
*
*
* @param url
* 请求URL
* @param bodyParts
@ -97,7 +100,7 @@ public class WeixinRequestExecutor {
/**
* Get方法执行微信请求
*
*
* @param url
* 请求URLhttps://api.weixin.qq.com/cgi-bin/token
* @param parameters
@ -118,7 +121,7 @@ public class WeixinRequestExecutor {
/**
* 执行微信请求
*
*
* @param request
* 微信请求
* @return 微信响应
@ -130,6 +133,9 @@ public class WeixinRequestExecutor {
logger.debug("weixin request >> " + request.getMethod() + " "
+ request.getURI().toString());
}
if(request.getEntity() instanceof StringEntity){
logger.debug("weixin request body >> " + ((StringEntity) request.getEntity()).getContentString());
}
HttpResponse httpResponse = httpClient.execute(request);
WeixinResponse response = new WeixinResponse(httpResponse);
handleResponse(response);
@ -141,7 +147,7 @@ public class WeixinRequestExecutor {
/**
* 响应内容是否为流
*
*
* @param response
* 微信响应
* @return true/false
@ -159,7 +165,7 @@ public class WeixinRequestExecutor {
/**
* handle the weixin response
*
*
* @param response
* 微信请求响应
* @throws WeixinException
@ -182,7 +188,7 @@ public class WeixinRequestExecutor {
if (!SUCCESS_CODE.contains(String.format(",%s,", result.getReturnCode()
.toLowerCase()))) {
throw new WeixinException(result.getReturnCode(),
result.getReturnMsg());
result.getReturnMsg(),WeixinErrorUtil2.getText(result.getReturnCode()));
}
if (XmlMessageConverter.GLOBAL.canConvert(XmlResult.class, response)) {
try {
@ -191,7 +197,7 @@ public class WeixinRequestExecutor {
if (!SUCCESS_CODE.contains(String.format(",%s,", xmlResult
.getResultCode().toLowerCase()))) {
throw new WeixinException(xmlResult.getErrCode(),
xmlResult.getErrCodeDes());
xmlResult.getErrCodeDes(),WeixinErrorUtil2.getText(xmlResult.getErrCode()));
}
} catch (IOException e) {
;
@ -205,7 +211,7 @@ public class WeixinRequestExecutor {
/**
* 创建 SSL微信请求对象
*
*
* @param password
* 加载密钥
* @param inputStream

View File

@ -2,14 +2,16 @@
<!-- 公众平台错误码:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433747234&token=&lang=zh_CN -->
<!-- 企业号错误码:http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E -->
<errors>
<error>
<code>-1</code>
<text>系统繁忙,请稍后再试</text>
</error>
<error>
<code>0</code>
<text>请求成功</text>
</error>
<error>
<code>-1</code>
<desc>system error</desc>
<text>微信系统繁忙,请稍候再试</text>
</error>
<!-- 公众平台&企业号API错误 -->
<error>
<code>40001</code>
<text>获取access_token时AppSecret错误或者access_token无效</text>
@ -36,7 +38,8 @@
</error>
<error>
<code>40007</code>
<text>无效的media_id</text>
<desc>invalid media_id</desc>
<text>请检查您的素材!</text>
</error>
<error>
<code>40008</code>
@ -133,7 +136,7 @@
</error>
<error>
<code>40031</code>
<text>不合法的openid列表</text>
<text>不合法的粉丝列表</text>
</error>
<error>
<code>40032</code>
@ -261,7 +264,7 @@
</error>
<error>
<code>40073</code>
<text>不合法的openid</text>
<text>不合法的cardid</text>
</error>
<error>
<code>40074</code>
@ -339,6 +342,10 @@
<code>40116</code>
<text>不合法的Code码。</text>
</error>
<error>
<code>40113</code>
<text>不支持的文件类型</text>
</error>
<error>
<code>40117</code>
<text>分组名字不合法</text>
@ -375,6 +382,15 @@
<code>40132</code>
<text>微信号不合法</text>
</error>
<error>
<code>40130</code>
<text>最少选择两名粉丝</text>
</error>
<error>
<code>40132</code>
<desc>invalid username</desc>
<text>无效的微信号</text>
</error>
<error>
<code>40137</code>
<text>不支持的图片格式</text>
@ -533,7 +549,8 @@
</error>
<error>
<code>43004</code>
<text>需要接收者关注</text>
<desc>require subscribe</desc>
<text>未关注公众号</text>
</error>
<error>
<code>43005</code>
@ -593,19 +610,23 @@
</error>
<error>
<code>45001</code>
<text>多媒体文件大小超过限制</text>
<desc>media size out of limit</desc>
<text>多媒体文件大小超过微信限制</text>
</error>
<error>
<code>45002</code>
<text>消息内容超过限制</text>
<desc>content size out of limit</desc>
<text>发送内容超过限制</text>
</error>
<error>
<code>45003</code>
<text>标题字段超过限制</text>
<desc>title size out of limit</desc>
<text>标题超过限制</text>
</error>
<error>
<code>45004</code>
<text>描述字段超过限制</text>
<desc>description size out of limit</desc>
<text>描述超过限制</text>
</error>
<error>
<code>45005</code>
@ -651,6 +672,10 @@
<code>45021</code>
<text>字段超过长度限制,请参考相应接口的字段说明。</text>
</error>
<error>
<code>45028</code>
<text>群发次数超过限制</text>
</error>
<error>
<code>45022</code>
<text>应用名字长度不合法合法长度为2-16个字</text>
@ -715,10 +740,32 @@
<code>45058</code>
<text>不能修改0/1/2这三个系统默认保留的标签</text>
</error>
<error>
<code>48001</code>
<text>公众号没有调用该接口的权限</text>
</error>
<error>
<code>48002</code>
<text>公众号没有调用该接口的权限</text>
</error>
<error>
<code>48003</code>
<text>请登录公众号后台,打开“群发功能”,同意腾讯群发消息声明</text>
</error>
<!-- 多客服API错误 -->
<error>
<code>45059</code>
<text>有粉丝身上的标签数已经超过限制</text>
</error>
<error>
<code>48005</code>
<text>此素材被自定义菜单引用,请先解除引用关系再编辑素材</text>
<desc>forbid to delete material used by auto-reply or menu hint: [JMOD7a0063e292]</desc>
</error>
<error>
<code>61450</code>
<text>系统错误(system error)</text>
</error>
<error>
<code>45157</code>
<text>标签名非法,请注意不能和其他标签重名</text>
@ -2420,8 +2467,8 @@
<text>金额不匹配,报关的订单金额必须和支付的金额一致,请检查报关订单的金额是否正确</text>
</error>
<error>
<code>POST_DATA_EMPTY</code>
<text>post数据为空,post数据不能为空,请检查post数据是否为空</text>
<code>9001007</code>
<text>上传文件无效</text>
</error>
<error>
<code>REQUIRE_POST_METHOD</code>
@ -2432,9 +2479,8 @@
<text>输入的参数xml格式有误,检查输入的xml格式是否正确</text>
</error>
<error>
<code>SECOND_OVER_LIMITED</code>
<text>企业红包的按分钟发放受限,每分钟发送红包数量不得超过1800个可联系微信支付wxhongbao@tencent.com调高额度
</text>
<code>9001010</code>
<text>文件上传到微信失败</text>
</error>
<error>
<code>SENDNUM_LIMIT</code>

View File

@ -3,6 +3,7 @@ package com.foxinmy.weixin4j.model;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.cache.Cacheable;
/**
@ -25,10 +26,12 @@ public class Token implements Cacheable {
/**
* 获取到的凭证
*/
@JSONField(name = "access_token")
private String accessToken;
/**
* 凭证有效时间单位毫秒
*/
@JSONField(name = "expires_in")
private long expires;
/**
* token创建的时间,单位毫秒
@ -39,6 +42,11 @@ public class Token implements Cacheable {
*/
private Map<String, String> extra;
/**
* 请求返回的原始结果
*/
private String originalResult;
/**
* 永不过期创建时间为当前时间戳的token对象
*
@ -55,7 +63,7 @@ public class Token implements Cacheable {
* @param accessToken
* 凭证字符串
* @param expires
* 过期时间 单位
* 过期时间 单位
*/
public Token(String accessToken, long expires) {
this(accessToken, expires, System.currentTimeMillis());
@ -77,6 +85,26 @@ public class Token implements Cacheable {
this.extra = new HashMap<String, String>();
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public void setExpires(long expires) {
this.expires = expires;
}
public void setCreateTime(long createTime) {
this.createTime = createTime;
}
public String getOriginalResult() {
return originalResult;
}
public void setOriginalResult(String originalResult) {
this.originalResult = originalResult;
}
public String getAccessToken() {
return accessToken;
}
@ -100,6 +128,8 @@ public class Token implements Cacheable {
return this;
}
@Override
public String toString() {
return "Token [accessToken=" + accessToken + ", expires=" + expires

View File

@ -33,6 +33,9 @@ public abstract class CardCoupon {
this.couponBaseInfo = couponBaseInfo;
}
public void cleanCantUpdateField(){
this.couponBaseInfo.cleanCantUpdateField();
}
/**
* 卡券类型
*

View File

@ -35,6 +35,9 @@ public final class CardCoupons {
return new CouponAdvanceInfo.Builder();
}
public static MemberCard.Builder customMemberCard(){
return new MemberCard.Builder();
}
/**
* 创建代金券
*
@ -112,4 +115,11 @@ public final class CardCoupons {
GrouponCoupon coupon = new GrouponCoupon(couponBaseInfo, explain);
return coupon;
}
public static MemberCard createMemberCard(CouponBaseInfo.Builder baseBuilder, MemberCard.Builder memberCardBudiler) {
baseBuilder.build();
MemberCard memberCard = new MemberCard(baseBuilder.build(), memberCardBudiler);
return memberCard;
}
}

View File

@ -60,6 +60,27 @@ public class CouponAdvanceInfo implements Serializable {
this.businessServices = builder.businessServices;
}
public JSONObject getUseCondition() {
return useCondition;
}
public JSONObject getAbstractConver() {
return abstractConver;
}
public List<JSONObject> getSlideImages() {
return slideImages;
}
public List<JSONObject> getTimeLimits() {
return timeLimits;
}
public List<BusinessService> getBusinessServices() {
return businessServices;
}
/**
* 卡券高级信息构造器
*
@ -91,13 +112,10 @@ public class CouponAdvanceInfo implements Serializable {
private List<BusinessService> businessServices;
public Builder() {
this.useCondition = new JSONObject();
this.abstractConver = new JSONObject();
this.slideImages = new ArrayList<JSONObject>();
this.timeLimits = new ArrayList<JSONObject>();
this.businessServices = new ArrayList<BusinessService>();
}
/**
* 设置使用门槛条件字段若不填写使用条件则在券面拼写 无最低消费限制全场通用不限品类并在使用说明显示 可与其他优惠共享
*
@ -143,6 +161,8 @@ public class CouponAdvanceInfo implements Serializable {
public Builder useCondition(String acceptCategory,
String rejectCategory, int leastCost, String objectUseFor,
boolean canUseWithOtherDiscount) {
if(useCondition == null)
useCondition = new JSONObject();
useCondition.clear();
if (StringUtil.isNotBlank(acceptCategory)) {
useCondition.put("accept_category", acceptCategory);
@ -171,6 +191,8 @@ public class CouponAdvanceInfo implements Serializable {
* @return
*/
public Builder abstractConver(String abstracts, String... convers) {
if(abstractConver == null)
abstractConver = new JSONObject();
abstractConver.clear();
abstractConver.put("abstract", abstracts);
abstractConver.put("icon_url_list", convers);
@ -185,6 +207,8 @@ public class CouponAdvanceInfo implements Serializable {
* @return
*/
public Builder slideImages(NameValue... slideImages) {
if(this.slideImages == null)
this.slideImages = new ArrayList<JSONObject>();
this.slideImages.clear();
for (NameValue nv : slideImages) {
JSONObject slide = new JSONObject();
@ -205,6 +229,8 @@ public class CouponAdvanceInfo implements Serializable {
* @return
*/
public Builder slideImage(String title, String url) {
if(this.slideImages == null)
this.slideImages = new ArrayList<JSONObject>();
JSONObject slide = new JSONObject();
slide.put("text", title);
slide.put("image_url", url);
@ -250,6 +276,8 @@ public class CouponAdvanceInfo implements Serializable {
*/
public Builder timeLimit(Week week, int beginHour, int beignMinute,
int endHour, int endMinute) {
if(this.timeLimits == null)
this.timeLimits = new ArrayList<JSONObject>();
JSONObject timeLimit = new JSONObject();
if (week != null) {
timeLimit.put("type", week.name());
@ -262,6 +290,7 @@ public class CouponAdvanceInfo implements Serializable {
if (endMinute > 0) {
timeLimit.put("end_minute", endMinute);
}
this.timeLimits.add(timeLimit);
return this;
}
@ -273,9 +302,15 @@ public class CouponAdvanceInfo implements Serializable {
* @return
*/
public Builder businessServices(BusinessService... businessServices) {
if(this.businessServices == null)
this.businessServices = new ArrayList<BusinessService>();
this.businessServices.addAll(Arrays.asList(businessServices));
return this;
}
public CouponAdvanceInfo build(){
return new CouponAdvanceInfo(this);
}
}
/**

View File

@ -69,12 +69,12 @@ public class CouponBaseInfo implements Serializable {
* 是否自定义Code码
*/
@JSONField(name = "use_custom_code")
private boolean useCustomCode;
private Boolean useCustomCode;
/**
* 指定特殊用户群体
*/
@JSONField(name = "bind_openid")
private boolean bindOpenId;
private Boolean bindOpenId;
/**
* 客服电话
*/
@ -221,11 +221,11 @@ public class CouponBaseInfo implements Serializable {
return date;
}
public boolean isUseCustomCode() {
public Boolean isUseCustomCode() {
return useCustomCode;
}
public boolean isBindOpenId() {
public Boolean isBindOpenId() {
return bindOpenId;
}
@ -312,6 +312,14 @@ public class CouponBaseInfo implements Serializable {
+ ", canGiveFriend=" + canGiveFriend;
}
public void cleanCantUpdateField() {
this.brandName = null;
this.title = null;
this.sku = null;
this.bindOpenId = null;
this.useCustomCode = null;
}
/**
* 卡券基础信息构造器
*
@ -432,9 +440,13 @@ public class CouponBaseInfo implements Serializable {
*/
private boolean canGiveFriend;
/**
* 默认永久有效
*/
public Builder() {
this.sku = new JSONObject();
this.date = new JSONObject();
this.date.put("type",CardActiveType.DATE_TYPE_PERMANENT);
this.useAllLocation = true;
this.canShare = true;
this.canGiveFriend = true;
@ -534,6 +546,7 @@ public class CouponBaseInfo implements Serializable {
* @return
*/
public Builder quantity(int quantity) {
quantity = quantity > 100000000 ? 100000000 : quantity;
this.sku.put("quantity", quantity);
return this;
}
@ -576,6 +589,23 @@ public class CouponBaseInfo implements Serializable {
return this;
}
/**
* 设置卡券在领取多少天后有效
*
* @param days
* 表示自领取后多少天内有效不支持填写0
* @param beginDays
* 表示自领取后多少天开始生效领取后当天生效填写0单位为天
* @return
*/
public Builder activeAt(int days, int beginDays) {
this.date.clear();
this.date.put("type", CardActiveType.DATE_TYPE_FIX_TERM);
this.date.put("fixed_term", days);
this.date.put("fixed_begin_term", beginDays);
return this;
}
/**
* 设置是否自定义Code码
*
@ -807,7 +837,10 @@ public class CouponBaseInfo implements Serializable {
/**
* 表示固定时长 自领取后按天算
*/
DATE_TYPE_FIX_TERM;
DATE_TYPE_FIX_TERM, /**
* 永久有效
*/
DATE_TYPE_PERMANENT;
}
}
}

View File

@ -0,0 +1,118 @@
package com.foxinmy.weixin4j.model.card;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 会员卡积分规则
*
* @auther: Feng Yapeng
* @since: 2016/12/15 11:43
*/
public class MemCardBonusRule {
/**
* 消费金额以分为单位
*/
@JSONField(name = "cost_money_unit")
private int costMoneyUnit;
/**
* 对应增加的积分
*/
@JSONField(name = "increase_bonus")
private int increaseBonus;
/**
* 用户单次可获取的积分上限
*/
@JSONField(name = "max_increase_bonus ")
private int maxIncreaseBonus;
/**
* 初始设置积分可以理解为开卡积分
*/
@JSONField(name = "init_increase_bonus")
private int initIncreaseBonus;
/**
*每使用N 积分
*/
@JSONField(name = "cost_bonus_unit")
private int costBonusUnit;
/**
* 抵扣多少分
*/
@JSONField(name = "reduce_money")
private int reduceMoney;
/**
* 抵扣条件满xx分这里以分为单位可用
*/
@JSONField(name = "least_money_to_use_bonus")
private int leastMoneyToUseBonus;
/**
*
*/
@JSONField(name = "max_reduce_bonus")
private int maxReduceBonus;
public int getCostMoneyUnit() {
return costMoneyUnit;
}
public void setCostMoneyUnit(int costMoneyUnit) {
this.costMoneyUnit = costMoneyUnit;
}
public int getIncreaseBonus() {
return increaseBonus;
}
public void setIncreaseBonus(int increaseBonus) {
this.increaseBonus = increaseBonus;
}
public int getMaxIncreaseBonus() {
return maxIncreaseBonus;
}
public void setMaxIncreaseBonus(int maxIncreaseBonus) {
this.maxIncreaseBonus = maxIncreaseBonus;
}
public int getInitIncreaseBonus() {
return initIncreaseBonus;
}
public void setInitIncreaseBonus(int initIncreaseBonus) {
this.initIncreaseBonus = initIncreaseBonus;
}
public int getCostBonusUnit() {
return costBonusUnit;
}
public void setCostBonusUnit(int costBonusUnit) {
this.costBonusUnit = costBonusUnit;
}
public int getReduceMoney() {
return reduceMoney;
}
public void setReduceMoney(int reduceMoney) {
this.reduceMoney = reduceMoney;
}
public int getLeastMoneyToUseBonus() {
return leastMoneyToUseBonus;
}
public void setLeastMoneyToUseBonus(int leastMoneyToUseBonus) {
this.leastMoneyToUseBonus = leastMoneyToUseBonus;
}
public int getMaxReduceBonus() {
return maxReduceBonus;
}
public void setMaxReduceBonus(int maxReduceBonus) {
this.maxReduceBonus = maxReduceBonus;
}
}

View File

@ -0,0 +1,73 @@
package com.foxinmy.weixin4j.model.card;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.card.FieldNameType;
/**
* 会员卡自定义类型
*
* @auther: Feng Yapeng
* @since: 2016/12/15 10:49
*/
public class MemCardCustomField {
/**
*会员信息类目半自定义名称当开发者变更这类类目信息的value值时可以选择触发系统模板消息通知用户
*/
@JSONField(name = "name_type")
private FieldNameType nameType;
/**
* 会员信息类目自定义名称当开发者变更这类类目信息的value值时, 不会触发系统模板消息通知用户
*/
private String name;
/**
* 点击类目跳转外链url
*/
private String url;
/**
* s
*/
private String tips;
public MemCardCustomField(FieldNameType fieldNameType, String url) {
this.nameType = fieldNameType;
this.url = url;
}
public MemCardCustomField(FieldNameType fieldNameType, String name, String url) {
this.nameType = fieldNameType;
this.name = name;
this.url = url;
}
public MemCardCustomField(String name, String url, String tips) {
this.name = name;
this.url = url;
this.tips = tips;
}
public FieldNameType getNameType() {
return nameType;
}
public void setNameType(FieldNameType nameType) {
this.nameType = nameType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}

View File

@ -0,0 +1,391 @@
package com.foxinmy.weixin4j.model.card;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.card.CardType;
import com.foxinmy.weixin4j.type.card.FieldNameType;
/**
* 会员卡
* @auther: Feng Yapeng
* @since: 2016/12/15 10:09
*/
public class MemberCard extends CardCoupon {
/**
* 会员卡背景图 [商家自定义会员卡背景图须先调用上传图片接口将背景图上传至CDN否则报错
* 卡面设计请遵循微信会员卡自定义背景设计规范 ,像素大小控制在1000像素*600像素以下]
*/
@JSONField(name = "background_pic_url")
private String backgroundPicUrl;
/**
* 会员卡特权说明
*/
@JSONField(name = "prerogative")
private String prerogative;
/**
* 用户领取会员卡后系统自动将其激活无需调用激活接口详情见自动激活
*/
@JSONField(name = "auto_activate")
private boolean autoActivate;
/**
* 设置为true时会员卡支持一键开卡不允许同时传入activate_url字段否则设置wx_activate失效
*/
@JSONField(name = "wx_activate")
private boolean wxActivate;
/**
* 激活会员卡的url
*/
@JSONField(name = "activate_url")
private String activateUrl;
/**
* 显示积分 true:积分相关字段均为必填
*/
@JSONField(name = "supply_bonus")
private boolean supplyBonus;
/**
* 设置跳转外链查看积分详情仅适用于积分无法通过激活接口同步的情况下使用该字段
*/
@JSONField(name = "bonus_url")
private String bonusUrl;
/**
* 显示余额
*/
@JSONField(name = "supply_balance")
private boolean supplyBalance;
/**
* 设置跳转外链查看余额详情仅适用于余额无法通过激活接口同步的情况下使用该字段
*/
@JSONField(name = "balance_url")
private String balanceUrl;
/**
* 自定义会员信息类目
*/
@JSONField(name = "custom_field1")
private MemCardCustomField customField1;
/**
* 自定义会员信息类目
*/
@JSONField(name = "custom_field2")
private MemCardCustomField customField2;
/**
* 自定义会员信息类目
*/
@JSONField(name = "custom_field3")
private MemCardCustomField customField3;
/**
* 积分规则说明
*/
@JSONField(name = "bonus_rules")
private String bonusRules;
/**
* 储值说明
*/
@JSONField(name = "balance_rules")
private String balanceRules;
/**
* 积分清零规则
*/
@JSONField(name = "bonus_cleared")
private String bonusCleared;
/**
* 自定义会员信息类目会员卡激活后显示
*/
@JSONField(name = "custom_cell1")
private MemCardCustomField customCell1;
/**
* 折扣该会员卡享受的折扣优惠,填10就是九折
*/
private int discount;
@JSONField(name = "bonus_rule")
private MemCardBonusRule bonusRule;
/**
* 卡券
*
* @param couponBaseInfo 基础信息
*/
protected MemberCard(CouponBaseInfo couponBaseInfo, Builder builder) {
super(couponBaseInfo);
this.activateUrl = builder.activateUrl;
this.backgroundPicUrl = builder.backgroundPicUrl;
this.prerogative = builder.prerogative;
this.autoActivate = builder.autoActivate;
this.wxActivate = builder.wxActivate;
this.activateUrl = builder.activateUrl;
this.supplyBonus = builder.supplyBonus;
this.bonusUrl = builder.bonusUrl;
this.supplyBalance = builder.supplyBalance;
this.balanceUrl = builder.balanceUrl;
this.customField1 = builder.customField1;
this.customField2 = builder.customField2;
this.customField3 = builder.customField3;
this.bonusRules = builder.bonusRules;
this.balanceRules = builder.balanceRules;
this.bonusCleared = builder.bonusCleared;
this.customCell1 = builder.customCell1;
this.discount = builder.discount;
this.bonusRule = builder.bonusRule;
}
@JSONField(serialize = false)
@Override
public CardType getCardType() {
return CardType.MEMBER_CARD;
}
public String getBackgroundPicUrl() {
return backgroundPicUrl;
}
public String getPrerogative() {
return prerogative;
}
public boolean isAutoActivate() {
return autoActivate;
}
public boolean isWxActivate() {
return wxActivate;
}
public String getActivateUrl() {
return activateUrl;
}
public boolean isSupplyBonus() {
return supplyBonus;
}
public String getBonusUrl() {
return bonusUrl;
}
public boolean getSupplyBalance() {
return supplyBalance;
}
public String getBalanceUrl() {
return balanceUrl;
}
public MemCardCustomField getCustomField1() {
return customField1;
}
public MemCardCustomField getCustomField2() {
return customField2;
}
public MemCardCustomField getCustomField3() {
return customField3;
}
public String getBonusRules() {
return bonusRules;
}
public String getBalanceRules() {
return balanceRules;
}
public String getBonusCleared() {
return bonusCleared;
}
public MemCardCustomField getCustomCell1() {
return customCell1;
}
public int getDiscount() {
return discount;
}
public MemCardBonusRule getBonusRule() {
return bonusRule;
}
public static final class Builder {
/**
* 会员卡背景图 [商家自定义会员卡背景图须先调用上传图片接口将背景图上传至CDN否则报错
* 卡面设计请遵循微信会员卡自定义背景设计规范 ,像素大小控制在1000像素*600像素以下]
*/
private String backgroundPicUrl;
/**
* 会员卡特权说明
*/
private String prerogative;
/**
* 用户领取会员卡后系统自动将其激活无需调用激活接口详情见自动激活
*/
private boolean autoActivate;
/**
* 设置为true时会员卡支持一键开卡不允许同时传入activate_url字段否则设置wx_activate失效
*/
private boolean wxActivate;
/**
* 激活会员卡的url
*/
private String activateUrl;
/**
* 显示积分 true:积分相关字段均为必填
*/
private boolean supplyBonus;
/**
* 设置跳转外链查看积分详情仅适用于积分无法通过激活接口同步的情况下使用该字段
*/
private String bonusUrl;
/**
* 显示余额
*/
private boolean supplyBalance;
/**
* 设置跳转外链查看余额详情仅适用于余额无法通过激活接口同步的情况下使用该字段
*/
private String balanceUrl;
/**
* 自定义会员信息类目
*/
private MemCardCustomField customField1;
/**
* 自定义会员信息类目
*/
private MemCardCustomField customField2;
/**
* 自定义会员信息类目
*/
private MemCardCustomField customField3;
/**
* 积分规则说明
*/
private String bonusRules;
/**
* 储值说明
*/
private String balanceRules;
/**
* 积分清零规则
*/
private String bonusCleared;
/**
* 自定义会员信息类目会员卡激活后显示
*/
private MemCardCustomField customCell1;
/**
* 折扣该会员卡享受的折扣优惠,填10就是九折
*/
private int discount;
/**
* 积分规则
*/
private MemCardBonusRule bonusRule;
public Builder backgroundPicUrl(String backgroundPicUrl) {
this.backgroundPicUrl = backgroundPicUrl;
return this;
}
public Builder prerogative(String prerogative) {
this.prerogative = prerogative;
return this;
}
public Builder activateWithAuto(boolean autoActivate) {
this.autoActivate = autoActivate;
this.activateUrl = null;
this.wxActivate = false;
return this;
}
public Builder activateWithWx(boolean wxActivate) {
this.wxActivate = wxActivate;
this.autoActivate = false;
this.activateUrl = null;
return this;
}
public Builder activateUrl(String activateUrl) {
this.activateUrl = activateUrl;
this.autoActivate = false;
this.wxActivate = false;
return this;
}
public Builder supplyBonus(boolean supplyBonus) {
this.supplyBonus = supplyBonus;
return this;
}
public Builder bonusUrl(String bonusUrl) {
this.bonusUrl = bonusUrl;
return this;
}
public Builder supplyBalance(boolean supplyBalance) {
this.supplyBalance = supplyBalance;
return this;
}
public Builder balanceUrl(String balanceUrl) {
this.balanceUrl = balanceUrl;
return this;
}
public Builder customField1(FieldNameType type, String name, String url) {
this.customField1 = new MemCardCustomField(type, name, url);
return this;
}
public Builder customField2(FieldNameType type, String name, String url) {
this.customField2 = new MemCardCustomField(type, name, url);
return this;
}
public Builder customField3(FieldNameType type, String name, String url) {
this.customField3 = new MemCardCustomField(type, name, url);
return this;
}
public Builder bonusRules(String bonusRules) {
this.bonusRules = bonusRules;
return this;
}
public Builder balanceRules(String balanceRules) {
this.balanceRules = balanceRules;
return this;
}
public Builder bonusCleared(String bonusCleared) {
this.bonusCleared = bonusCleared;
return this;
}
public Builder customCell1(String name, String url, String tips) {
this.customCell1 = new MemCardCustomField(name, url, tips);
return this;
}
public Builder discount(int discount) {
this.discount = discount;
return this;
}
public Builder bonusRule(MemCardBonusRule bonusRule) {
this.bonusRule = bonusRule;
return this;
}
}
}

View File

@ -0,0 +1,171 @@
package com.foxinmy.weixin4j.model.card;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.Date;
/**
* 会员初始化的信息
*
* @auther: Feng Yapeng
* @since: 2016/12/20 15:00
*/
public class MemberInitInfo {
/**
* 会员卡编号由开发者填入作为序列号显示在用户的卡包里可与Code码保持等值
*/
@JSONField(name = "membership_number")
private String membershipNumber;
/**
* 领取会员卡用户获得的code
*/
private String code;
/**
* 卡券ID自定义code卡券必填
*/
@JSONField(name = "card_id")
private String cardId;
/**
* 商家自定义会员卡背景图 先调用上传图片接口将背景图上传至CDN否则报错
* 卡面设计请遵循微信会员卡自定义背景设计规范
*/
@JSONField(name = "background_pic_url")
private String backgroundPicUrl;
/**
* 激活后的有效起始时间若不填写默认以创建时的 date_info 为准Unix时间戳格式
*/
@JSONField(name = "activate_begin_time")
private long activateBeginTime;
/**
* 激活后的有效截至时间
*/
@JSONField(name = "activate_end_time")
private long activateEndTime;
/**
* 初始积分不填为0
*/
@JSONField(name = "init_bonus")
private Integer initBonus;
/**
* 积分同步说明
*/
@JSONField(name = "init_bonus_record")
private String initBonusRecord;
/**
* 初始余额不填为0
*/
@JSONField(name = "init_balance")
private Integer initBalance;
/**
* 创建时字段custom_field1定义类型的初始值限制为4个汉字12字节
*/
private String init_custom_field_value1;
/**
* 创建时字段custom_field2定义类型的初始值限制为4个汉字12字节
*/
private String init_custom_field_value2;
/**
* 创建时字段custom_field3定义类型的初始值限制为4个汉字12字节
*/
private String init_custom_field_value3;
public String getMembershipNumber() {
return membershipNumber;
}
public void setMembershipNumber(String membershipNumber) {
this.membershipNumber = membershipNumber;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public String getBackgroundPicUrl() {
return backgroundPicUrl;
}
public void setBackgroundPicUrl(String backgroundPicUrl) {
this.backgroundPicUrl = backgroundPicUrl;
}
public long getActivateBeginTime() {
return activateBeginTime;
}
public void setActivateBeginTime(Date activateBeginTime) {
this.activateBeginTime = activateBeginTime.getTime() / 1000;
}
public long getActivateEndTime() {
return activateEndTime;
}
public void setActivateEndTime(Date activateEndTime) {
this.activateEndTime = activateEndTime.getTime() / 1000;
}
public Integer getInitBonus() {
return initBonus;
}
public void setInitBonus(Integer initBonus) {
this.initBonus = initBonus;
}
public String getInitBonusRecord() {
return initBonusRecord;
}
public void setInitBonusRecord(String initBonusRecord) {
this.initBonusRecord = initBonusRecord;
}
public Integer getInitBalance() {
return initBalance;
}
public void setInitBalance(Integer initBalance) {
this.initBalance = initBalance;
}
public String getInit_custom_field_value1() {
return init_custom_field_value1;
}
public void setInit_custom_field_value1(String init_custom_field_value1) {
this.init_custom_field_value1 = init_custom_field_value1;
}
public String getInit_custom_field_value2() {
return init_custom_field_value2;
}
public void setInit_custom_field_value2(String init_custom_field_value2) {
this.init_custom_field_value2 = init_custom_field_value2;
}
public String getInit_custom_field_value3() {
return init_custom_field_value3;
}
public void setInit_custom_field_value3(String init_custom_field_value3) {
this.init_custom_field_value3 = init_custom_field_value3;
}
}

View File

@ -0,0 +1,210 @@
package com.foxinmy.weixin4j.model.card;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 会员更新的信息
*
* @auther: Feng Yapeng
* @since: 2016/12/20 15:01
*/
public class MemberUpdateInfo {
/**
* 卡券Code码
*/
private String code;
/**
* 卡券ID
*/
@JSONField(name = "card_id")
private String cardId;
/**
* 支持商家激活时针对单个会员卡分配自定义的会员卡背景
*/
@JSONField(name = "background_pic_url")
private String backgroundPicUrl;
/**
* 需要设置的积分全量值传入的数值会直接显示
*/
private Integer bonus;
/**
* 本次积分变动值传负数代表减少
*/
@JSONField(name = "add_bonus")
private Integer addBonus;
/**
* 商家自定义积分消耗记录不超过14个汉字
*/
@JSONField(name = "record_bonus")
private String recordBonus;
/*
* 需要设置的余额全量值传入的数值会直接显示在卡面
*/
private Integer balance;
/**
* 本次余额变动值传负数代表减少
*/
@JSONField(name = "add_balance")
private Integer addBalance;
/**
* 商家自定义金额消耗记录不超过14个汉字
*/
@JSONField(name = "record_balance")
private String recordBalance;
/**
* 创建时字段custom_field1定义类型的最新数值限制为4个汉字12字节
*/
@JSONField(name = "custom_field_value1")
private String customFieldValue1;
/**
* 同上
*/
@JSONField(name = "custom_field_value2")
private String customFieldValue2;
/**
* 同上
*/
@JSONField(name = "custom_field_value3")
private String customFieldValue3;
/**
*
*/
@JSONField(name = "notifyOptional")
private JSONObject notifyOptional;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public String getBackgroundPicUrl() {
return backgroundPicUrl;
}
public void setBackgroundPicUrl(String backgroundPicUrl) {
this.backgroundPicUrl = backgroundPicUrl;
}
public Integer getBonus() {
return bonus;
}
public void setBonus(Integer bonus) {
this.bonus = bonus;
}
public Integer getAddBonus() {
return addBonus;
}
public void setAddBonus(Integer addBonus) {
this.addBonus = addBonus;
}
public String getRecordBonus() {
return recordBonus;
}
public void setRecordBonus(String recordBonus) {
this.recordBonus = recordBonus;
}
public Integer getBalance() {
return balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
public Integer getAddBalance() {
return addBalance;
}
public void setAddBalance(Integer addBalance) {
this.addBalance = addBalance;
}
public String getRecordBalance() {
return recordBalance;
}
public void setRecordBalance(String recordBalance) {
this.recordBalance = recordBalance;
}
public String getCustomFieldValue1() {
return customFieldValue1;
}
public void setCustomFieldValue1(String customFieldValue1) {
this.customFieldValue1 = customFieldValue1;
}
public void setCustomFieldValue1(String customFieldValue1, boolean notify) {
this.customFieldValue1 = customFieldValue1;
if (notifyOptional == null) {
notifyOptional = new JSONObject();
}
notifyOptional.put("is_notify_custom_field1", notify);
}
public String getCustomFieldValue2() {
return customFieldValue2;
}
public void setCustomFieldValue2(String customFieldValue2) {
this.customFieldValue2 = customFieldValue2;
}
public void setCustomFieldValue2(String customFieldValue2, boolean notify) {
this.customFieldValue2 = customFieldValue2;
if (notifyOptional == null) {
notifyOptional = new JSONObject();
}
notifyOptional.put("is_notify_custom_field2", notify);
}
public String getCustomFieldValue3() {
return customFieldValue3;
}
public void setCustomFieldValue3(String customFieldValue3) {
this.customFieldValue3 = customFieldValue3;
}
public void setCustomFieldValue3(String customFieldValue3, boolean notify) {
this.customFieldValue3 = customFieldValue3;
if (notifyOptional == null) {
notifyOptional = new JSONObject();
}
notifyOptional.put("is_notify_custom_field3", notify);
}
public void setNOtify(boolean notifyBonus, boolean notifyBalance) {
if (notifyOptional == null) {
notifyOptional = new JSONObject();
}
notifyOptional.put("is_notify_bonus", notifyBonus);
notifyOptional.put("is_notify_balance", notifyBalance);
}
}

View File

@ -0,0 +1,187 @@
package com.foxinmy.weixin4j.model.card;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.card.ActivateCommonField;
import com.foxinmy.weixin4j.type.card.ActivateFormFieldType;
import java.util.HashSet;
/**
* 普通一键激活 中设置会员卡
*
* @auther: Feng Yapeng
* @since: 2016/12/20 16:25
*/
public class MemberUserForm {
/**
* 卡券ID
*/
@JSONField(name = "card_id")
private String cardId;
/**
* 服务声明用于放置商户会员卡守则
*/
@JSONField(name = "service_statement")
private JSONObject serviceStatement;
/**
* 绑定老会员链接
*/
@JSONField(name = "bind_old_card")
private JSONObject bindOldCard;
/**
*设置必填的from
*/
@JSONField(name = "required_form")
private FormBudiler requiredForm;
/**
* 设置选填的form
*/
@JSONField(name = "optional_form")
private FormBudiler optionalForm;
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public JSONObject getServiceStatement() {
return serviceStatement;
}
public void setServiceStatement(String name,String url) {
JSONObject serviceStatement = new JSONObject();
serviceStatement.put("name",name);
serviceStatement.put("url",url);
this.serviceStatement = serviceStatement;
}
public JSONObject getBindOldCard() {
return bindOldCard;
}
public void setBindOldCard(String name,String url) {
JSONObject bindOldCard = new JSONObject();
bindOldCard.put("name",name);
bindOldCard.put("url",url);
this.bindOldCard = bindOldCard;
}
public void setRequiredForm(FormBudiler formBudiler) {
this.requiredForm = formBudiler;
}
public void setOptionalForm(FormBudiler formBudiler) {
this.optionalForm = formBudiler;
}
public FormBudiler getRequiredForm() {
return requiredForm;
}
public FormBudiler getOptionalForm() {
return optionalForm;
}
public final static class FormBudiler {
/**
* 当前结构required_form或者optional_form
* 的字段是否允许用户激活后再次修改商户设置为true
* 需要接收相应事件通知处理修改事件
*/
@JSONField(name = "can_modify")
private boolean canModify;
/**
* 自定义富文本类型包含以下三个字段
*/
@JSONField(name = "rich_field_list")
private JSONArray richFieldList;
/**
* 微信格式化的选项类型
*/
@JSONField(name = "common_field_id_list")
private HashSet<ActivateCommonField> commonFieldIdList;
/**
* 自定义选项名称
*/
@JSONField(name = "custom_field_list")
private HashSet<String> customFieldList;
/**
* 自定义富文本类型
*/
public FormBudiler addRichField(ActivateFormFieldType fieldType, String name, String... values) {
if (richFieldList == null) {
richFieldList = new JSONArray();
}
JSONObject obj = new JSONObject();
obj.put("type", fieldType);
obj.put("name", name);
obj.put("values", values);
richFieldList.add(obj);
return this;
}
public FormBudiler canModify(boolean modify){
this.canModify = canModify;
return this;
}
/**
* 自定义公共字段
*/
public FormBudiler addCommonField(ActivateCommonField... fields) {
if (commonFieldIdList == null) {
commonFieldIdList = new HashSet<ActivateCommonField>();
}
for (ActivateCommonField field : fields) {
commonFieldIdList.add(field);
}
return this;
}
/**
* 增加自定义的内容
* @param names
*/
public FormBudiler addCustomField(String... names) {
if (customFieldList == null) {
customFieldList = new HashSet<String>();
}
for (String name : names) {
customFieldList.add(name);
}
return this;
}
public boolean isCanModify() {
return canModify;
}
public JSONArray getRichFieldList() {
return richFieldList;
}
public HashSet<ActivateCommonField> getCommonFieldIdList() {
return commonFieldIdList;
}
public HashSet<String> getCustomFieldList() {
return customFieldList;
}
}
}

View File

@ -0,0 +1,165 @@
package com.foxinmy.weixin4j.model.card;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType;
import com.foxinmy.weixin4j.type.Gender;
import com.foxinmy.weixin4j.type.card.UserCardStatus;
import com.foxinmy.weixin4j.util.NameValue;
import com.foxinmy.weixin4j.xml.ListsuffixResult;
import java.util.ArrayList;
import java.util.Map;
/**
* 会员卡的基本信息
*
* @auther: Feng Yapeng
* @since: 2016/12/21 11:33
*/
public class MemberUserInfo {
/**
* openId
*/
@JSONField(name = "openid")
private String openId;
/**
* 昵称
*/
@JSONField(name = "nickname")
private String nickName;
/**
* 会员卡编号
*/
@JSONField(name = "mmebership_number")
private String membershipNumber;
/**
* 积分
*/
private Integer bonus;
/**
* 余额
*/
private Integer balance;
/**
* 性别
*/
private String sex;
/**
* 用户会员卡状态
*/
@JSONField(name = "user_card_status")
private UserCardStatus userCardStatus;
/**
* 是否已经被激活true表示已经被激活false表示未被激活
*/
@JSONField(name = "has_active")
private boolean hasActive;
/**
* 用户信息
*/
@JSONField(name = "user_info")
private UserInfo userInfo;
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getMembershipNumber() {
return membershipNumber;
}
public void setMembershipNumber(String membershipNumber) {
this.membershipNumber = membershipNumber;
}
public Integer getBonus() {
return bonus;
}
public void setBonus(Integer bonus) {
this.bonus = bonus;
}
public Integer getBalance() {
return balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public UserCardStatus getUserCardStatus() {
return userCardStatus;
}
public void setUserCardStatus(UserCardStatus userCardStatus) {
this.userCardStatus = userCardStatus;
}
public boolean isHasActive() {
return hasActive;
}
public void setHasActive(boolean hasActive) {
this.hasActive = hasActive;
}
public UserInfo getUserInfo() {
return userInfo;
}
public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
public static final class UserInfo {
@JSONField(name = "common_field_list")
private ArrayList<NameValue> commonFieldValues;
@JSONField(name = "custom_field_list")
private ArrayList<NameValue> customFieldValues;
public ArrayList<NameValue> getCommonFieldValues() {
return commonFieldValues;
}
public void setCommonFieldValues(ArrayList<NameValue> commonFieldValues) {
this.commonFieldValues = commonFieldValues;
}
public ArrayList<NameValue> getCustomFieldValues() {
return customFieldValues;
}
public void setCustomFieldValues(ArrayList<NameValue> customFieldValues) {
this.customFieldValues = customFieldValues;
}
}
}

View File

@ -55,6 +55,10 @@ public class Pagedata<T> implements Serializable, Iterable<T> {
return pageable == null ? null : pageable.getSort();
}
public List<T> getContent() {
return content;
}
@Override
public Iterator<T> iterator() {
return hasContent() ? content.iterator() : null;

View File

@ -127,6 +127,47 @@ public class PayPackage extends MerchantResult {
this.goodsTag = goodsTag;
}
/**
* 订单对象
*
* @param body
* 订单描述 必填
* @param detail
* 订单详情 非必填
* @param outTradeNo
* 商户内部ID 必填
* @param totalFee
* 订单总额 必填 <font color="red">单位为分</font>
* @param notifyUrl
* 回调地址 必填
* @param createIp
* 生成订单数据的机器IP 必填
* @param attach
* 附加数据 非必填
* @param timeStart
* 订单生成时间 非必填
* @param timeExpire
* 订单失效时间 非必填
* @param goodsTag
* 订单标记 非必填
*/
public PayPackage(String body, String detail, String outTradeNo,
long totalFee, String notifyUrl, String createIp, String attach,
Date timeStart, Date timeExpire, String goodsTag) {
this.body = body;
this.detail = detail;
this.outTradeNo = outTradeNo;
this.totalFee = Long.valueOf(totalFee).intValue();
this.notifyUrl = notifyUrl;
this.createIp = createIp;
this.attach = attach;
this.timeStart = timeStart != null ? DateUtil
.fortmat2yyyyMMddHHmmss(timeStart) : null;
this.timeExpire = timeExpire != null ? DateUtil
.fortmat2yyyyMMddHHmmss(timeExpire) : null;
this.goodsTag = goodsTag;
}
public String getBody() {
return body;
}

View File

@ -36,6 +36,7 @@ public class PayRequest extends PayBaseInfo {
@JSONField(serialize = false)
private String partnerId;
protected PayRequest() {
// jaxb required
}
@ -69,6 +70,7 @@ public class PayRequest extends PayBaseInfo {
this.partnerId = partnerId;
}
@Override
public String toString() {
return "package" + packageInfo + ", prepayId=" + prepayId

View File

@ -469,7 +469,7 @@ public class WeixinPayProxy {
*
* @throws IOException
*
* @see {@link #applyRefund(IdQuery, String, double, double, String,CurrencyType)}
* @see {@link #applyRefund(IdQuery, String, double, double,CurrencyType,String,RefundAccountType)}
*/
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
double totalFee) throws WeixinException {

View File

@ -20,8 +20,8 @@ import com.foxinmy.weixin4j.util.MapUtil;
* href="https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1">APP支付</a>
*/
public class APPPayRequest extends AbstractPayRequest {
public APPPayRequest(String prePayId, WeixinPayAccount payAccount) {
super(prePayId, payAccount);
public APPPayRequest(PrePay prePay, WeixinPayAccount payAccount) {
super(prePay.getPrepayId(),prePay.getResponse(), payAccount);
}
@Override

View File

@ -10,10 +10,14 @@ public abstract class AbstractPayRequest implements MchPayRequest {
private final WeixinPayAccount paymentAccount;
protected final WeixinSignature weixinSignature;
public AbstractPayRequest(String prePayId, WeixinPayAccount paymentAccount) {
protected final String payResponse;
public AbstractPayRequest(String prePayId, String payResponse, WeixinPayAccount paymentAccount) {
this.prePayId = prePayId;
this.payResponse = payResponse;
this.paymentAccount = paymentAccount;
this.weixinSignature = new WeixinPaymentSignature(paymentAccount.getPaySignKey());
}
@Override
@ -25,4 +29,10 @@ public abstract class AbstractPayRequest implements MchPayRequest {
public WeixinPayAccount getPaymentAccount() {
return this.paymentAccount;
}
@Override
public String getResponseString() {
return payResponse;
}
}

View File

@ -25,8 +25,8 @@ import com.foxinmy.weixin4j.type.TradeType;
*/
public class JSAPIPayRequest extends AbstractPayRequest {
public JSAPIPayRequest(String prePayId, WeixinPayAccount payAccount) {
super(prePayId, payAccount);
public JSAPIPayRequest(PrePay prePay, WeixinPayAccount payAccount) {
super(prePay.getPrepayId(), prePay.getResponse(), payAccount);
}
@Override

View File

@ -27,6 +27,8 @@ public class MICROPayRequest extends Order implements MchPayRequest {
@JSONField(serialize = false)
private WeixinPayAccount paymentAccount;
private String response;
protected MICROPayRequest() {
// jaxb required
}
@ -55,6 +57,16 @@ public class MICROPayRequest extends Order implements MchPayRequest {
return null;
}
public void setResponse(String response) {
this.response = response;
}
@Override
public String getResponseString() {
return response;
}
/**
* <font color="red">返回null,请不要尝试作为支付请求</font>
*/

View File

@ -108,6 +108,38 @@ public class MchPayPackage extends PayPackage {
null, null, null, null);
}
/**
* 微信支付
*
* @param body
* 支付详情 必填
* @param outTradeNo
* 商户侧订单号 必填
* @param totalFee
* 支付金额(单位元) 必填
* @param notifyUrl
* 支付回调URL 必填
* @param createIp
* 发起支付的IP地址 必填
* @param tradeType
* 支付类型 必填
* @param openId
* 用户唯一标识 公众号JSAPI支付必填
* @param authCode
* 支付授权码 刷卡MICROPAY支付必填
* @param productId
* 商品ID 扫码NATIVE支付必填
* @param attach
* 支付时附加信息 非必填
*/
public MchPayPackage(String body, String outTradeNo, long totalFee,
String notifyUrl, String createIp, TradeType tradeType,
String openId, String authCode, String productId, String attach) {
this(body, null, outTradeNo, totalFee, notifyUrl, createIp, tradeType,
openId, authCode, productId, attach, null, null, null, null,
null);
}
/**
* 完整参数
*
@ -147,12 +179,12 @@ public class MchPayPackage extends PayPackage {
* 用户在子商户appid下的唯一标识 非必填
* openid和sub_openid可以选传其中之一如果选择传sub_openid ,则必须传sub_appid
*/
public MchPayPackage(String body, String detial, String outTradeNo,
public MchPayPackage(String body, String detail, String outTradeNo,
double totalFee, CurrencyType feeType, String notifyUrl,
String createIp, TradeType tradeType, String openId,
String authCode, String productId, String attach, Date timeStart,
Date timeExpire, String goodsTag, String limitPay, String subOpenId) {
super(body, detial, outTradeNo, totalFee, notifyUrl, createIp, attach,
super(body, detail, outTradeNo, totalFee, notifyUrl, createIp, attach,
timeStart, timeExpire, goodsTag);
this.tradeType = tradeType != null ? tradeType.name() : null;
this.feeType = feeType == null ? CurrencyType.CNY.name() : feeType
@ -164,6 +196,58 @@ public class MchPayPackage extends PayPackage {
this.subOpenId = subOpenId;
}
/**
* 完整参数
*
* @param body
* 商品描述 <font color="red">必填项</font>
* @param detail
* 商品名称明细列表 非必填项
* @param outTradeNo
* 商户内部唯一订单号 <font color="red">必填项</font>
* @param totalFee
* 商品总额 单位元 <font color="red">必填项</font>
* @param notifyUrl
* 支付回调URL <font color="red">必填项</font>
* @param createIp
* 订单生成的机器IP <font color="red">必填项</font>
* @param tradeType
* 交易类型 <font color="red">必填项</font>
* @param openId
* 用户ID <font color="red">tradeType=JSAPI时必填</font>
* @param authCode
* 刷卡支付授权码 <font color="red">tradeType=MICROPAY时必填</font>
* @param productId
* 产品ID <font color="red">tradeType=NATIVE时必填</font>
* @param attach
* 附加数据在查询API和支付通知中原样返回该字段主要用于商户携带订单的自定义数据 非必填项
* @param timeStart
* 订单生成时间格式为yyyyMMddHHmmss 非必填项
* @param timeExpire
* 订单失效时间格式为yyyyMMddHHmmss;注意最短失效时间间隔必须大于5分钟 非必填项
* @param goodsTag
* 商品标记代金券或立减优惠功能的参数 非必填项
* @param limitPay
* 指定支付方式:no_credit--指定不能使用信用卡支付 非必填项
* @param subOpenId
* 用户在子商户appid下的唯一标识 非必填
* openid和sub_openid可以选传其中之一如果选择传sub_openid ,则必须传sub_appid
*/
public MchPayPackage(String body, String detail, String outTradeNo,
long totalFee, String notifyUrl, String createIp,
TradeType tradeType, String openId, String authCode,
String productId, String attach, Date timeStart, Date timeExpire,
String goodsTag, String limitPay, String subOpenId) {
super(body, detail, outTradeNo, totalFee, notifyUrl, createIp, attach,
timeStart, timeExpire, goodsTag);
this.tradeType = tradeType.name();
this.openId = openId;
this.authCode = authCode;
this.productId = productId;
this.limitPay = limitPay;
this.subOpenId = subOpenId;
}
public String getTradeType() {
return tradeType;
}

View File

@ -52,4 +52,10 @@ public interface MchPayRequest {
* @return
*/
public PayRequest toRequestObject();
/**
* 支付请求返回的结果
* @return
*/
public String getResponseString();
}

View File

@ -20,9 +20,9 @@ public class NATIVEPayRequest extends AbstractPayRequest {
private final String codeUrl;
public NATIVEPayRequest(String prePayId, String codeUrl,
public NATIVEPayRequest(PrePay prePay, String codeUrl,
WeixinPayAccount payAccount) {
super(prePayId, payAccount);
super(prePay.getPrepayId(), prePay.getResponse(), payAccount);
this.codeUrl = codeUrl;
}

View File

@ -69,7 +69,7 @@ public class Order extends MerchantTradeResult {
/**
* 现金支付货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
*
* @see com.foxinmy.weixin4j.mp.type.CurrencyType
* @see com.foxinmy.weixin4j.type.CurrencyType
*/
@XmlElement(name = "cash_fee_type")
@JSONField(name = "cash_fee_type")

View File

@ -40,6 +40,8 @@ public class PrePay extends MerchantResult {
@XmlElement(name = "code_url")
private String codeUrl;
private String response;
protected PrePay() {
// jaxb required
}
@ -72,6 +74,14 @@ public class PrePay extends MerchantResult {
this.codeUrl = codeUrl;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
@Override
public String toString() {
return "PrePay [tradeType=" + tradeType + ", prepayId=" + prepayId

View File

@ -138,6 +138,43 @@ public class Redpacket extends MerchantResult {
this.amtType = totalNum > 1 ? "ALL_RAND" : null;
}
/**
* 红包
*
* @param outTradeNo
* 商户侧一天内不可重复的订单号 接口根据商户订单号支持重入 如出现超时可再调用 必填
* @param sendName
* 红包发送者名称 必填
* @param openId
* 接受收红包的用户的openid 必填
* @param totalAmount
* 付款金额 <font color="red">单位为分,自动格式化为分</font> 必填
* @param totalNum
* 红包发放总人数 大于1视为裂变红包 必填
* @param wishing
* 红包祝福语 必填
* @param clientIp
* Ip地址 必填
* @param actName
* 活动名称 必填
* @param remark
* 备注 必填
*/
public Redpacket(String outTradeNo, String sendName, String openId,
int totalAmount, int totalNum, String wishing, String clientIp,
String actName, String remark) {
this.outTradeNo = outTradeNo;
this.sendName = sendName;
this.openId = openId;
this.totalNum = totalNum;
this.wishing = wishing;
this.clientIp = clientIp;
this.actName = actName;
this.remark = remark;
this.totalAmount = totalAmount;
this.amtType = totalNum > 1 ? "ALL_RAND" : null;
}
public String getOutTradeNo() {
return outTradeNo;
}

View File

@ -22,8 +22,8 @@ import com.foxinmy.weixin4j.util.URLEncodingUtil;
*/
public class WAPPayRequest extends AbstractPayRequest {
public WAPPayRequest(String prePayId, WeixinPayAccount payAccount) {
super(prePayId, payAccount);
public WAPPayRequest(PrePay prePay, WeixinPayAccount payAccount) {
super(prePay.getPrepayId(),prePay.getResponse(), payAccount);
}
@Override

View File

@ -1,36 +1,60 @@
package com.foxinmy.weixin4j.sign;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.type.SignType;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.xml.XmlStream;
import java.util.Map;
/**
* 微信支付签名实现
*
* @className WeixinPaymentSignature
* @author jinyu(foxinmy@gmail.com)
* @className WeixinPaymentSignature
* @date 2016年3月26日
* @since JDK 1.6
* @see <a
* href="https://pay.weixin.qq.com/wiki/doc/api/external/jsapi.php?chapter=4_3">支付签名说明</a>
* href="https://pay.weixin.qq.com/wiki/doc/api/external/jsapi.php?chapter=4_3">支付签名说明</a>
* @since JDK 1.6
*/
public class WeixinPaymentSignature extends AbstractWeixinSignature {
/**
* 支付密钥
*/
private final String paySignKey;
public WeixinPaymentSignature(String paySignKey) {
this.paySignKey = paySignKey;
}
/**
* 支付密钥
*/
private final String paySignKey;
public WeixinPaymentSignature(String paySignKey) {
this.paySignKey = paySignKey;
}
@Override
public SignType getSignType() {
return SignType.MD5;
}
@Override
public String sign(Object obj) {
StringBuilder sb = join(obj).append("&key=").append(paySignKey);
return DigestUtil.MD5(sb.toString()).toUpperCase();
}
public boolean validatePaySign(WeixinResponse weixinResponse) {
return this.validatePaySign(weixinResponse.getAsString());
}
public boolean validatePaySign(String xmlResult) {
return this.validatePaySign(XmlStream.xml2map(xmlResult));
}
public boolean validatePaySign(Map<String, String> map) {
String sign1 = map.get("sign");
map.remove("sign");
String sign2 = this.sign(map);
return sign1.equals(sign2);
}
@Override
public SignType getSignType() {
return SignType.MD5;
}
@Override
public String sign(Object obj) {
StringBuilder sb = join(obj).append("&key=").append(paySignKey);
return DigestUtil.MD5(sb.toString()).toUpperCase();
}
}

View File

@ -0,0 +1,66 @@
package com.foxinmy.weixin4j.type.card;
/**
* 会员卡激活设置公共字段类型
*
* @auther: Feng Yapeng
* @since: 2016/12/20 14:49
*/
public enum ActivateCommonField {
/**
* 手机号
*/
USER_FORM_INFO_FLAG_MOBILE,
/**
* 性别
*/
USER_FORM_INFO_FLAG_SEX,
/**
* 姓名
*/
USER_FORM_INFO_FLAG_NAME,
/**
* 生日
*/
USER_FORM_INFO_FLAG_BIRTHDAY,
/**
* 身份证
*/
USER_FORM_INFO_FLAG_IDCARD,
/**
* 邮箱
*/
USER_FORM_INFO_FLAG_EMAIL,
/**
* 详细地址
*/
USER_FORM_INFO_FLAG_LOCATION,
/**
* 教育背景
*/
USER_FORM_INFO_FLAG_EDUCATION_BACKGRO,
/**
* 行业
*/
USER_FORM_INFO_FLAG_INDUSTRY,
/**
* 收入
*/
USER_FORM_INFO_FLAG_INCOME,
/**
* 兴趣爱好
*/
USER_FORM_INFO_FLAG_HABIT;
}

View File

@ -0,0 +1,16 @@
package com.foxinmy.weixin4j.type.card;
/**
* 激活form表单字段类型
*
* @auther: Feng Yapeng
* @since: 2016/12/20 15:34
*/
public enum ActivateFormFieldType {
FORM_FIELD_RADIO,/*自定义单选 */
FORM_FIELD_SELECT,/*自定义选择项 */
FORM_FIELD_CHECK_BOX,/*自定义多选*/;
}

View File

@ -0,0 +1,36 @@
package com.foxinmy.weixin4j.type.card;
/**
* 会员卡的状态
*
* @auther: Feng Yapeng
* @since: 2016/12/19 11:39
*/
public enum CardStatus {
/**
* 待审核
*/
CARD_STATUS_NOT_VERIFY,
/**
* 审核失败
*/
CARD_STATUS_VERIFY_FAIL,
/**
* 通过审核
*/
CARD_STATUS_VERIFY_OK,
/**
* 卡券被商户删除
*/
CARD_STATUS_DELETE,
/**
* 在公众平台投放过的卡券
*/
CARD_STATUS_DISPATCH;
}

View File

@ -29,5 +29,10 @@ public enum CardType {
/**
* 优惠券
*/
GENERAL_COUPON;
GENERAL_COUPON,
/**
* 会员卡
*/
MEMBER_CARD;
}

View File

@ -0,0 +1,42 @@
package com.foxinmy.weixin4j.type.card;
/**
* 会员信息类目半自定义名称
*
* @auther: Feng Yapeng
* @since: 2016/12/15 10:37
*/
public enum FieldNameType {
/**
* 等级
*/
FIELD_NAME_TYPE_LEVEL,
/**
* 优惠券
*/
FIELD_NAME_TYPE_COUPON,
/**
* 印花
*/
FIELD_NAME_TYPE_STAMP,
/**
* 折扣
*/
FIELD_NAME_TYPE_DISCOUNT,
/**
* 成就
*/
FIELD_NAME_TYPE_ACHIEVEMEN,
/**
* 里程
*/
FIELD_NAME_TYPE_MILEAGE,
/**
* 集点
*/
FIELD_NAME_TYPE_SET_POINTS,
/**
* 次数
*/
FIELD_NAME_TYPE_TIMS;
}

View File

@ -0,0 +1,19 @@
package com.foxinmy.weixin4j.type.card;
/**
* 用户的会员卡状态
*
* @auther: Feng Yapeng
* @since: 2016/12/21 11:42
*/
public enum UserCardStatus {
NORMAL,//正常
EXPIRE,//已过期
GIFTING,// 转赠中
GIFT_SUCC,// 转赠成功
GIFT_TIMEOUT,// 转赠超时
DELETE,//已删除
UNAVAILABLE,//已失效
;
}

View File

@ -11,152 +11,159 @@ import java.util.Map.Entry;
/**
* 文件工具类
*
* @className FileUtil
*
* @author jinyu(foxinmy@gmail.com)
* @className FileUtil
* @date 2014年11月21日
* @since JDK 1.6
* @see
* @since JDK 1.6
*/
public class FileUtil {
private final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();
private final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();
static {
FILE_TYPE_MAP.put("ffd8ffe000104a464946", "jpg");
FILE_TYPE_MAP.put("89504e470d0a1a0a0000", "png");
FILE_TYPE_MAP.put("47494638396126026f01", "gif");
FILE_TYPE_MAP.put("49492a00227105008037", "tif");
FILE_TYPE_MAP.put("424d228c010000000000", "bmp"); // 16色位图(bmp)
FILE_TYPE_MAP.put("424d8240090000000000", "bmp"); // 24位位图(bmp)
FILE_TYPE_MAP.put("424d8e1b030000000000", "bmp"); // 256色位图(bmp)
static {
FILE_TYPE_MAP.put("ffd8ffe000104a464946", "jpg");
FILE_TYPE_MAP.put("89504e470d0a1a0a0000", "png");
FILE_TYPE_MAP.put("47494638396126026f01", "gif");
FILE_TYPE_MAP.put("49492a00227105008037", "tif");
FILE_TYPE_MAP.put("424d228c010000000000", "bmp"); // 16色位图(bmp)
FILE_TYPE_MAP.put("424d8240090000000000", "bmp"); // 24位位图(bmp)
FILE_TYPE_MAP.put("424d8e1b030000000000", "bmp"); // 256色位图(bmp)
FILE_TYPE_MAP.put("49443303000000002176", "mp3");
FILE_TYPE_MAP.put("52494646", "wav");
FILE_TYPE_MAP.put("00005741", "wav");
FILE_TYPE_MAP.put("2321414d", "amr");
FILE_TYPE_MAP.put("520a3c91", "amr");
FILE_TYPE_MAP.put("2e524d46000000120001", "rmvb"); // rmvbrm
FILE_TYPE_MAP.put("464c5601050000000900", "flv"); // flvf4v
FILE_TYPE_MAP.put("667479706d70", "mp4");
FILE_TYPE_MAP.put("667479706973", "mp4");
FILE_TYPE_MAP.put("000001ba210001000180", "mpg");
FILE_TYPE_MAP.put("3026b2758e66cf11a6d9", "wmv"); // wmvasf
FILE_TYPE_MAP.put("52494646d07d60074156", "avi");
FILE_TYPE_MAP.put("49443303000000002176", "mp3");
FILE_TYPE_MAP.put("52494646", "wav");
FILE_TYPE_MAP.put("00005741", "wav");
FILE_TYPE_MAP.put("2321414d", "amr");
FILE_TYPE_MAP.put("520a3c91", "amr");
FILE_TYPE_MAP.put("41433130313500000000", "dwg");
FILE_TYPE_MAP.put("3c21444f435459504520", "html");
FILE_TYPE_MAP.put("3c21646f637479706520", "htm");
FILE_TYPE_MAP.put("48544d4c207b0d0a0942", "css");
FILE_TYPE_MAP.put("696b2e71623d696b2e71", "js");
FILE_TYPE_MAP.put("7b5c727466315c616e73", "rtf");
FILE_TYPE_MAP.put("38425053000100000000", "psd");
FILE_TYPE_MAP.put("46726f6d3a203d3f6762", "eml");
FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "doc"); // MS ExcelWordMsi
FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "vsd");
FILE_TYPE_MAP.put("5374616E64617264204A", "mdb");
FILE_TYPE_MAP.put("255044462d312e350d0a", "pdf");
FILE_TYPE_MAP.put("4d546864000000060001", "mid");
FILE_TYPE_MAP.put("504b0304140000000800", "zip");
FILE_TYPE_MAP.put("526172211a0700cf9073", "rar");
FILE_TYPE_MAP.put("235468697320636f6e66", "ini");
FILE_TYPE_MAP.put("504b03040a0000000000", "jar");
FILE_TYPE_MAP.put("4d5a9000030000000400", "exe");
FILE_TYPE_MAP.put("3c25402070616765206c", "jsp");
FILE_TYPE_MAP.put("4d616e69666573742d56", "mf");
FILE_TYPE_MAP.put("3c3f786d6c2076657273", "xml");
FILE_TYPE_MAP.put("494e5345525420494e54", "sql");
FILE_TYPE_MAP.put("7061636b616765207765", "java");
FILE_TYPE_MAP.put("406563686f206f66660d", "bat");
FILE_TYPE_MAP.put("1f8b0800000000000000", "gz");
FILE_TYPE_MAP.put("6c6f67346a2e726f6f74", "properties");
FILE_TYPE_MAP.put("cafebabe0000002e0041", "class");
FILE_TYPE_MAP.put("49545346030000006000", "chm");
FILE_TYPE_MAP.put("04000000010000001300", "mxp");
FILE_TYPE_MAP.put("504b0304140006000800", "docx");
FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "wps");// WPS(wpsetdps)
FILE_TYPE_MAP.put("6431303a637265617465", "torrent");
FILE_TYPE_MAP.put("6D6F6F76", "mov");
FILE_TYPE_MAP.put("FF575043", "wpd");
FILE_TYPE_MAP.put("CFAD12FEC5FD746F", "dbx");
FILE_TYPE_MAP.put("2142444E", "pst");
FILE_TYPE_MAP.put("AC9EBD8F", "qdf");
FILE_TYPE_MAP.put("E3828596", "pwl");
FILE_TYPE_MAP.put("2E7261FD", "ram");
}
FILE_TYPE_MAP.put("2e524d46000000120001", "rmvb"); // rmvbrm
FILE_TYPE_MAP.put("464c5601050000000900", "flv"); // flvf4v
FILE_TYPE_MAP.put("667479706d70", "mp4");
FILE_TYPE_MAP.put("667479706973", "mp4");
FILE_TYPE_MAP.put("000001ba210001000180", "mpg");
FILE_TYPE_MAP.put("3026b2758e66cf11a6d9", "wmv"); // wmvasf
FILE_TYPE_MAP.put("52494646d07d60074156", "avi");
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
FILE_TYPE_MAP.put("41433130313500000000", "dwg");
FILE_TYPE_MAP.put("3c21444f435459504520", "html");
FILE_TYPE_MAP.put("3c21646f637479706520", "htm");
FILE_TYPE_MAP.put("48544d4c207b0d0a0942", "css");
FILE_TYPE_MAP.put("696b2e71623d696b2e71", "js");
FILE_TYPE_MAP.put("7b5c727466315c616e73", "rtf");
FILE_TYPE_MAP.put("38425053000100000000", "psd");
FILE_TYPE_MAP.put("46726f6d3a203d3f6762", "eml");
FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "doc"); // MS ExcelWordMsi
FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "vsd");
FILE_TYPE_MAP.put("5374616E64617264204A", "mdb");
FILE_TYPE_MAP.put("255044462d312e350d0a", "pdf");
FILE_TYPE_MAP.put("4d546864000000060001", "mid");
FILE_TYPE_MAP.put("504b0304140000000800", "zip");
FILE_TYPE_MAP.put("526172211a0700cf9073", "rar");
FILE_TYPE_MAP.put("235468697320636f6e66", "ini");
FILE_TYPE_MAP.put("504b03040a0000000000", "jar");
FILE_TYPE_MAP.put("4d5a9000030000000400", "exe");
FILE_TYPE_MAP.put("3c25402070616765206c", "jsp");
FILE_TYPE_MAP.put("4d616e69666573742d56", "mf");
FILE_TYPE_MAP.put("3c3f786d6c2076657273", "xml");
FILE_TYPE_MAP.put("494e5345525420494e54", "sql");
FILE_TYPE_MAP.put("7061636b616765207765", "java");
FILE_TYPE_MAP.put("406563686f206f66660d", "bat");
FILE_TYPE_MAP.put("1f8b0800000000000000", "gz");
FILE_TYPE_MAP.put("6c6f67346a2e726f6f74", "properties");
FILE_TYPE_MAP.put("cafebabe0000002e0041", "class");
FILE_TYPE_MAP.put("49545346030000006000", "chm");
FILE_TYPE_MAP.put("04000000010000001300", "mxp");
FILE_TYPE_MAP.put("504b0304140006000800", "docx");
FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "wps");// WPS(wpsetdps)
FILE_TYPE_MAP.put("6431303a637265617465", "torrent");
FILE_TYPE_MAP.put("6D6F6F76", "mov");
FILE_TYPE_MAP.put("FF575043", "wpd");
FILE_TYPE_MAP.put("CFAD12FEC5FD746F", "dbx");
FILE_TYPE_MAP.put("2142444E", "pst");
FILE_TYPE_MAP.put("AC9EBD8F", "qdf");
FILE_TYPE_MAP.put("E3828596", "pwl");
FILE_TYPE_MAP.put("2E7261FD", "ram");
}
/**
* 获取文件类型
*
* @param is
* @return
*/
public static String getFileType(InputStream is) {
String fileType = "file";
try {
byte[] b = new byte[10];
int t = is.read(b, 0, b.length);
if (t > 0) {
String fileCode = bytesToHexString(b).toLowerCase();
for (Entry<String, String> entry : FILE_TYPE_MAP.entrySet()) {
String key = entry.getKey().toLowerCase();
if (key.startsWith(fileCode) || fileCode.startsWith(key)
|| key.endsWith(fileCode) || fileCode.endsWith(key)) {
fileType = entry.getValue();
break;
}
}
}
} catch (IOException e) {
;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ignore) {
;
}
}
}
return fileType;
}
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
/**
* 获取文件后缀
*
* @param fileName
* @return
*/
public static String getFileExtension(String fileName) {
int extensionPos = fileName.lastIndexOf(".");
if (extensionPos < 0) {
return "";
}
int lastUnixPos = fileName.lastIndexOf("/");
int lastWindowsPos = fileName.lastIndexOf("\\");
int lastSeparator = Math.max(lastUnixPos, lastWindowsPos);
return lastSeparator > extensionPos ? "" : fileName
.substring(extensionPos + 1);
}
/**
* 获取文件类型
*/
public static String getFileType(InputStream is) {
String fileType = "file";
try {
byte[] b = new byte[10];
int t = is.read(b, 0, b.length);
if (t > 0) {
String fileCode = bytesToHexString(b).toLowerCase();
for (Entry<String, String> entry : FILE_TYPE_MAP.entrySet()) {
String key = entry.getKey().toLowerCase();
if (key.startsWith(fileCode) || fileCode.startsWith(key) || key.endsWith(fileCode) || fileCode.endsWith(key)) {
fileType = entry.getValue();
break;
}
}
}
} catch (IOException e) {
;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ignore) {
;
}
}
}
return fileType;
}
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream(new File(
"/Users/jy/Downloads/test.mp4"));
System.err.println(getFileType(is));
System.err.println(URLConnection.guessContentTypeFromStream(is));
}
/**
* 获取文件后缀
*/
public static String getFileExtension(String fileName) {
int extensionPos = fileName.lastIndexOf(".");
if (extensionPos < 0) {
return "";
}
int lastUnixPos = fileName.lastIndexOf("/");
int lastWindowsPos = fileName.lastIndexOf("\\");
int lastSeparator = Math.max(lastUnixPos, lastWindowsPos);
return lastSeparator > extensionPos ? "" : fileName.substring(extensionPos + 1);
}
/**
* 删除文件
* @param filePath
* @return
*/
public static boolean deleteFile(String filePath) {
File file = new File(filePath);
if (!file.exists()) {
return true;
}
if (file.isFile()) {
return file.delete();
}
return false;
}
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream(new File("/Users/jy/Downloads/test.mp4"));
System.err.println(getFileType(is));
System.err.println(URLConnection.guessContentTypeFromStream(is));
}
}

View File

@ -1,6 +1,7 @@
package com.foxinmy.weixin4j.util;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -11,82 +12,84 @@ import java.nio.charset.Charset;
/**
* IOUtil
*
* @className IOUtil
*
* @author jinyu(foxinmy@gmail.com)
* @className IOUtil
* @date 2014年9月22日
* @since JDK 1.6
* @see org.apache.commons.io.IOUtils
* @since JDK 1.6
*/
public class IOUtil {
private static final int EOF = -1;
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
private static final int EOF = -1;
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
public static byte[] toByteArray(Reader input) throws IOException {
return toByteArray(input, Charset.defaultCharset());
}
public static byte[] toByteArray(Reader input) throws IOException {
return toByteArray(input, Charset.defaultCharset());
}
public static byte[] toByteArray(Reader input, Charset encoding)
throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
copy(input, output, encoding);
return output.toByteArray();
}
public static byte[] toByteArray(Reader input, Charset encoding) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
copy(input, output, encoding);
return output.toByteArray();
}
public static void copy(Reader input, OutputStream output, Charset encoding)
throws IOException {
OutputStreamWriter out = new OutputStreamWriter(output, encoding);
copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]);
out.flush();
}
public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException {
OutputStreamWriter out = new OutputStreamWriter(output, encoding);
copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]);
out.flush();
}
public static int copy(InputStream input, OutputStream output)
throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
public static int copy(InputStream input, OutputStream output) throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
private static long copyLarge(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
private static long copyLarge(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]);
return output.toByteArray();
}
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]);
return output.toByteArray();
}
private static long copyLarge(InputStream input, OutputStream output,
byte[] buffer) throws IOException {
long count = 0;
int n = 0;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException {
long count = 0;
int n = 0;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
private static long copyLarge(Reader input, Writer output, char[] buffer)
throws IOException {
long count = 0;
int n = 0;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException {
long count = 0;
int n = 0;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
public static void close(Closeable stream) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -16,21 +16,23 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
/**
* 接口调用错误获取
*
*
* @author jy
* @className WeixinErrorUtil
* @author jinyu(foxinmy@gmail.com)
* @date 2015年5月12日
* @since JDK 1.6
* @see
* @since JDK 1.6
*/
public final class WeixinErrorUtil {
private static byte[] errorXmlByteArray;
private static byte[] errorXmlByteArray;
private final static Map<String, String> errorCacheMap;
static {
errorCacheMap = new ConcurrentHashMap<String, String>();
try {
errorXmlByteArray = IOUtil.toByteArray(WeixinResponse.class
.getResourceAsStream("error.xml"));
errorXmlByteArray = IOUtil.toByteArray(WeixinResponse.class.getResourceAsStream("error.xml"));
} catch (IOException e) {
;
}
@ -44,26 +46,23 @@ public final class WeixinErrorUtil {
this.code = code;
}
private String text;
private String text;
private boolean codeElement;
private boolean textElement;
private boolean findElement;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
codeElement = qName.equalsIgnoreCase("code");
textElement = qName.equalsIgnoreCase("text");
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
public void endElement(String uri, String localName, String qName) throws SAXException {
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
public void characters(char[] ch, int start, int length) throws SAXException {
String _text = new String(ch, start, length);
if (codeElement && _text.equalsIgnoreCase(code)) {
findElement = true;
@ -88,8 +87,7 @@ public final class WeixinErrorUtil {
try {
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setContentHandler(textHandler);
xmlReader.parse(new InputSource(new ByteArrayInputStream(
errorXmlByteArray)));
xmlReader.parse(new InputSource(new ByteArrayInputStream(errorXmlByteArray)));
text = textHandler.getText();
errorCacheMap.put(code, text);
} catch (IOException e) {
@ -102,9 +100,10 @@ public final class WeixinErrorUtil {
return text;
}
public static void main(String[] args) {
System.out.println(getText("40001"));
System.out.println(getText("40001"));
System.out.println(getText("30002"));
System.out.println(getText("30002"));
System.out.println(getText("1234"));
}
}

View File

@ -0,0 +1,112 @@
package com.foxinmy.weixin4j.util;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 接口调用错误获取
*
* @author fengyapeng
* @className WeixinErrorUtil2
* @date
* @see
* @since JDK 1.6
*/
public final class WeixinErrorUtil2 {
private static byte[] errorXmlByteArray;
private final static Map<String, String> errorCacheMap;
static {
errorCacheMap = new ConcurrentHashMap<String, String>();
try {
errorXmlByteArray = IOUtil.toByteArray(WeixinResponse.class.getResourceAsStream("error.xml"));
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
ContentHandler textHandler = new ErrorTextHandler(errorCacheMap);
xmlReader.setContentHandler(textHandler);
xmlReader.parse(new InputSource(new ByteArrayInputStream(errorXmlByteArray)));
} catch (IOException e) {
;
} catch (SAXException e) {
}
}
private static class ErrorTextHandler extends DefaultHandler {
private Map<String, String> errorCacheMap;
public ErrorTextHandler(Map<String, String> errorCacheMap) {
this.errorCacheMap = errorCacheMap;
}
private String code;
private String text;
private boolean codeElement;
private boolean textElement;
private int isPair = 0;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
codeElement = qName.equalsIgnoreCase("code");
textElement = qName.equalsIgnoreCase("text");
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String _text = new String(ch, start, length);
if (codeElement) {
isPair++;
code = _text;
codeElement = false;
}
if (textElement) {
isPair++;
text = _text;
textElement = false;
}
if (isPair == 2) {
// 配对成功
errorCacheMap.put(code, text);
isPair = 0;
code = null;
text = null;
}
}
}
public static String getText(String code) throws RuntimeException {
return errorCacheMap.get(code);
}
public static String getText(String code, String defaultMsg) throws RuntimeException {
String text = getText(code);
if (StringUtil.isNotBlank(text)) {
return text;
}
return defaultMsg;
}
public static void main(String[] args) {
System.out.println(getText("40001"));
System.out.println(getText("30002"));
System.out.println(getText("1234"));
}
}

View File

@ -91,7 +91,7 @@ public class PayTest {
c.set(Calendar.DAY_OF_MONTH, 4);
System.err.println(c.getTime());
OutputStream os = new FileOutputStream("/tmp/bill20160813.txt");
PAY.downloadBill(c.getTime(), BillType.ALL, os);
PAY.downloadBill(c.getTime(), BillType.ALL, os,null);
}
@Test

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.7.3</version>
<version>1.7.4-SNAPSHOT</version>
</parent>
<artifactId>weixin4j-mp</artifactId>
<name>weixin4j-mp</name>

View File

@ -1005,7 +1005,8 @@ public class WeixinProxy {
* 删除群发</a>
* @see com.foxinmy.weixin4j.mp.api.MassApi
* @see {@link #massByGroupId(Tuple, int)}
* @see {@link #massByOpenIds(Tuple, String...)
* @see {@link #massByOpenIds(Tuple, String...)
*
*/
public ApiResult deleteMassNews(String msgid) throws WeixinException {

View File

@ -1,6 +1,7 @@
package com.foxinmy.weixin4j.mp.api;
import java.io.IOException;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@ -12,9 +13,15 @@ import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.card.CardCoupon;
import com.foxinmy.weixin4j.model.card.CardCoupons;
import com.foxinmy.weixin4j.model.card.CardQR;
import com.foxinmy.weixin4j.model.card.MemberInitInfo;
import com.foxinmy.weixin4j.model.card.MemberUpdateInfo;
import com.foxinmy.weixin4j.model.card.MemberUserForm;
import com.foxinmy.weixin4j.model.card.MemberUserInfo;
import com.foxinmy.weixin4j.model.qr.QRParameter;
import com.foxinmy.weixin4j.model.qr.QRResult;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.type.card.CardStatus;
import com.foxinmy.weixin4j.type.card.CardType;
import com.foxinmy.weixin4j.util.IOUtil;
/**
@ -28,7 +35,7 @@ import com.foxinmy.weixin4j.util.IOUtil;
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025056&token=&lang=zh_CN">卡券说明</a>
*/
public class CardApi extends MpApi {
private final TokenManager tokenManager;
protected final TokenManager tokenManager;
public CardApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
@ -155,4 +162,148 @@ public class CardApi extends MpApi {
}
return result;
}
/**
* 由于卡券有审核要求为方便公众号调试可以设置一些测试帐号这些帐号可领取未通过审核的卡券体验整个流程
* 1.同时支持openidusername两种字段设置白名单总数上限为10个
* 2.设置测试白名单接口为全量设置即测试名单发生变化时需调用该接口重新传入所有测试人员的ID.
* 3.白名单用户领取该卡券时将无视卡券失效状态请开发者注意
* @param openIds the open ids
* @param userNames the user names
* @author fengyapeng
* @since 2016 -12-20 11:22:57
* @see <a href='https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025062&token=&lang=zh_CN&anchor=6'>设置测试白名单</a>
*/
public void setTestWhiteList(List<String> openIds, List<String> userNames) throws WeixinException {
JSONObject requestObj = new JSONObject();
if (openIds != null && openIds.size() > 0) {
requestObj.put("openid", openIds);
}
if (userNames != null && userNames.size() > 0) {
requestObj.put("username", userNames);
}
String card_set_test_whitelist_uri = getRequestUri("card_set_test_whitelist_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(card_set_test_whitelist_uri, token.getAccessToken()),
requestObj.toJSONString());
}
/**
* 查看获取卡券的审核状态
* @see <a href='https://mp.weixin.qq.com/wiki?action=doc&id=mp1451025272&t=0.18670321276182844#3'> 查看卡券详情</a>
*
* @author fengyapeng
* @since 2016 -12-20 11:48:23
*/
public CardStatus queryCardStatus(String cardId) throws WeixinException {
JSONObject requestObj = new JSONObject();
requestObj.put("card_id",cardId);
String card_get_uri = getRequestUri("card_get_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(card_get_uri, token.getAccessToken()),requestObj.toJSONString());
JSONObject responseAsJson = response.getAsJson();
JSONObject card = responseAsJson.getJSONObject("card");
String cardType = card.getString("card_type");
JSONObject baseInfo = card.getJSONObject(cardType.toLowerCase()).getJSONObject("base_info");
String status = baseInfo.getString("status");
return CardStatus.valueOf(status);
}
/**
* 支持更新所有卡券类型的部分通用字段及特殊卡券会员卡飞机票电影票会议门票中特定字段的信息
*
* @param cardId the card id
* @param card the card
* @return 是否提交审核false为修改后不会重新提审true为修改字段后重新提审该卡券的状态变为审核中
* @throws WeixinException the weixin exception
* @author fengyapeng
* @see
* @since 2016 -12-21 15:29:10
*/
public Boolean updateCardCoupon(String cardId, CardCoupon card) throws WeixinException {
JSONObject request = new JSONObject();
request.put("card_id", cardId);
CardType cardType = card.getCardType();
card.cleanCantUpdateField();
request.put(cardType.name().toLowerCase(), card);
String card_update_uri = getRequestUri("card_update_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(card_update_uri,token.getAccessToken()),JSON.toJSONString(request));
JSONObject jsonObject= response.getAsJson();
return jsonObject.getBoolean("send_check");
}
/**
* 激活方式说明
* 接口激活通常需要开发者开发用户填写资料的网页通常有两种激活流程
* 1. 用户必须在填写资料后才能领卡领卡后开发者调用激活接口为用户激活会员卡
* 2. 是用户可以先领取会员卡点击激活会员卡跳转至开发者设置的资料填写页面填写完成后开发者调用激活接口为用户激活会员卡
*
* @see <a href='https://mp.weixin.qq.com/wiki?action=doc&id=mp1451025283&t=0.8029895777585161#6.1'>接口激活</a>
*/
public ApiResult activate(MemberInitInfo memberInitInfo) throws WeixinException {
String card_member_card_activate_uri = getRequestUri("card_member_card_activate_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor
.post(String.format(card_member_card_activate_uri, token.getAccessToken()), JSON.toJSONString(memberInitInfo));
return response.getAsResult();
}
/**
* 设置开卡字段接口
* 开发者在创建时填入wx_activate字段后
* 需要调用该接口设置用户激活时需要填写的选项否则一键开卡设置不生效
*
* @see <a href='https://mp.weixin.qq.com/wiki?action=doc&id=mp1451025283&t=0.8029895777585161#6.2'>一键激活</a>
*/
public ApiResult setActivateUserForm(MemberUserForm memberUserForm) throws WeixinException {
String user_form_uri = getRequestUri("card_member_card_activate_user_form_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor
.post(String.format(user_form_uri, token.getAccessToken()), JSON.toJSONString(memberUserForm));
return response.getAsResult();
}
/**
* 拉取会员信息接口
*
* @param cardId the card id
* @param code the code
* @author fengyapeng
* @since 2016 -12-21 11:28:45
*/
public MemberUserInfo getMemberUserInfo(String cardId, String code) throws WeixinException {
String user_info_uri = getRequestUri("card_member_card_user_info_uri");
Token token = tokenManager.getCache();
JSONObject jsonObject = new JSONObject();
jsonObject.put("card_id", cardId);
jsonObject.put("code", code);
WeixinResponse response = weixinExecutor.post(String.format(user_info_uri, token.getAccessToken()), JSON.toJSONString(jsonObject));
return response.getAsObject(new TypeReference<MemberUserInfo>() {
});
}
/**
* 更新会员
* @param updateInfo
* @return
* @throws WeixinException
*/
public JSONObject updateUserInfo(MemberUpdateInfo updateInfo) throws WeixinException {
String card_member_card_update_user_uri = getRequestUri("card_member_card_update_user_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor
.post(String.format(card_member_card_update_user_uri, token.getAccessToken()), JSON.toJSONString(updateInfo));
return response.getAsJson();
}
}

View File

@ -306,7 +306,8 @@ public class MassApi extends MpApi {
* @see <a
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN">删除群发</a>
* @see {@link #massByTagId(Tuple, int)}
* @see {@link #massByOpenIds(Tuple, String...)
* @see {@link #massByOpenIds(Tuple, String...)
*/
public ApiResult deleteMassNews(String msgid) throws WeixinException {
JSONObject obj = new JSONObject();

View File

@ -0,0 +1,275 @@
package com.foxinmy.weixin4j.mp.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.ApiResult;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.paging.Pageable;
import com.foxinmy.weixin4j.model.paging.Pagedata;
import com.foxinmy.weixin4j.mp.model.shakearound.Device;
import com.foxinmy.weixin4j.mp.model.shakearound.DeviceAuditState;
import com.foxinmy.weixin4j.mp.model.shakearound.ShakeUserInfo;
import com.foxinmy.weixin4j.token.TokenManager;
import com.sun.javafx.binding.StringFormatter;
import java.util.ArrayList;
import java.util.List;
/**
* 摇一摇周边
*
* @author fengyapeng
* @auther: Feng Yapeng feng27156@gmail.com
* @since: 2016 /10/12 21:13
* @since 2016 -10-13 10:49:39
*/
public class ShakeAroundApi extends MpApi {
private final TokenManager tokenManager;
/**
* Instantiates a new Shake around api.
*
* @param tokenManager the token manager
*/
public ShakeAroundApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
* 申请配置设备所需的UUIDMajorMinor申请成功后返回批次ID可用返回的批次ID通过查询设备ID申请状态接口查询目前申请的审核状态
* 若单次申请的设备ID数量小于500个系统会进行快速审核若单次申请的设备ID数量大于等 500个 会在三个工作日内完成审核
* 如果已审核通过可用返回的批次ID通过查询设备列表接口拉取本次申请的设备ID 通过接口申请的设备ID需先配置页面若未配置页面则摇不出页面信息
*
* @param quantity the quantity 申请的设备ID的数量单次新增设备超过500个需走人工审核流程
* @param applyReason the apply reason 申请理由不超过100个汉字或200个英文字母
* @param comment the comment 备注不超过15个汉字或30个英文字母
* @return the api result
* @throws WeixinException the weixin exception
* @author fengyapeng
* @see <a href= "http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1459246241&token=&lang=zh_CN"></a>
* @since 2016 -10-12 21:21:47
*/
public DeviceAuditState deviceApply(Integer quantity, String applyReason, String comment) throws WeixinException {
String device_apply_uri = getRequestUri("shake_around_device_apply");
Token token = this.tokenManager.getCache();
JSONObject jsonObject = new JSONObject();
jsonObject.put("quantity", quantity);
jsonObject.put("apply_reason", applyReason);
jsonObject.put("comment", comment);
WeixinResponse response = weixinExecutor.post(String.format(device_apply_uri, token.getAccessToken()), jsonObject.toJSONString());
DeviceAuditState result = JSON.parseObject(response.getAsJson().getString("data"), DeviceAuditState.class);
result.setApplyTime(System.currentTimeMillis() / 1000);
result.setAuditTime(0);
return result;
}
/**
* 查询设备ID申请的审核状态若单次申请的设备ID数量小于等于500个
* 系统会进行快速审核若单次申请的设备ID数量大于500个则在三个工作日内完成审核
*
* @param applyId the apply id 批次ID申请设备ID时所返回的批次ID
* @return the device audit state
* @throws WeixinException the weixin exception
* @author fengyapeng
* @see <a href= "http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1459246243&token=&lang=zh_CN"></a>
* @since 2016 -10-12 21:57:04
*/
public DeviceAuditState deviceQueryApplyStatus(int applyId) throws WeixinException {
String device_apply_status_uri = getRequestUri("shake_around_device_apply_status_uri");
Token token = this.tokenManager.getCache();
JSONObject jsonObject = new JSONObject();
jsonObject.put("apply_id", applyId);
WeixinResponse response = weixinExecutor
.post(String.format(device_apply_status_uri, token.getAccessToken()), jsonObject.toJSONString());
DeviceAuditState result = JSON.parseObject(response.getAsJson().getString("data"), DeviceAuditState.class);
result.setApplyId(applyId);
return result;
}
/**
* 查询已有的设备IDUUIDMajorMinor激活状态备注信息关联门店关联页面等信息
* 查询指定设备的信息
*
* @param device the device
* @return the list
* @throws WeixinException the weixin exception
* @author fengyapeng
* @since 2016 -10-13 10:11:34
*/
public List<Device> deviceSearchDevices(List<Device> device) throws WeixinException {
String device_search_uri = getRequestUri("shake_around_device_search_uri");
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", 1);
jsonObject.put("device_identifiers", device);
WeixinResponse response = weixinExecutor
.post(String.format(device_search_uri, tokenManager.getAccessToken()), jsonObject.toJSONString());
JSONObject json = response.getAsJson();
String deviceStr = json.getJSONObject("data").getString("devices");
return JSON.parseArray(deviceStr, Device.class);
}
/**
* 查询已有的设备IDUUIDMajorMinor激活状态备注信息关联门店关联页面等信息
* 按照分页信息查询设备
*
* @return the list
* @throws WeixinException the weixin exception
* @author fengyapeng
* @since 2016 -10-13 10:11:34
*/
public Pagedata<Device> deviceSearchDevices(int pageSize) throws WeixinException {
return this.deviceSearchDevices(0, pageSize);
}
/**
* 查询已有的设备IDUUIDMajorMinor激活状态备注信息关联门店关联页面等信息
* 根据上次查询的最后的设备编号按照分页查询
*
* @param lastDeviceId the last device id
* @param pageSize the page size
* @return list pagedata
* @throws WeixinException the weixin exception
* @author fengyapeng
* @since 2016 -10-13 10:52:20
*/
public Pagedata<Device> deviceSearchDevices(int lastDeviceId, int pageSize) throws WeixinException {
String device_search_uri = getRequestUri("shake_around_device_search_uri");
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", 2);
jsonObject.put("last_seen", lastDeviceId);
if (pageSize > 50) {
pageSize = 50;
}
jsonObject.put("count", pageSize);
WeixinResponse response = weixinExecutor
.post(String.format(device_search_uri, tokenManager.getAccessToken()), jsonObject.toJSONString());
JSONObject json = response.getAsJson();
JSONObject data = json.getJSONObject("data");
String deviceStr = data.getString("devices");
List<Device> devices = JSON.parseArray(deviceStr, Device.class);
Pagedata<Device> pagedata = new Pagedata<Device>(null, data.getIntValue("total_count"), devices);
return pagedata;
}
/**
* 查询已有的设备IDUUIDMajorMinor激活状态备注信息关联门店关联页面等信息
* 查询 设备Id 下的所有的设备
*
* @param applyId the apply id
* @return the list
* @author fengyapeng
* @since 2016 -10-13 10:49:39
*/
public List<Device> deviceSearchDevicesByApplyId(Integer applyId) throws WeixinException {
List<Device> devices = new ArrayList<Device>();
Pagedata<Device> pagedata = this.deviceSearchDevicesByApplyId(applyId, 50);
devices = pagedata.getContent();
for (int page = 50; page < pagedata.getTotalElements(); page = page + 50) {
List<Device> _devices = pagedata.getContent();
pagedata = this.deviceSearchDevicesByApplyId(applyId, _devices.get(_devices.size() - 1).getDeviceId(), 50);
_devices = pagedata.getContent();
devices.addAll(_devices);
}
return devices;
}
/**
* 查询已有的设备IDUUIDMajorMinor激活状态备注信息关联门店关联页面等信息
* 分页获取设备id下的前多少设备
*
* @param applyId the apply id
* @return the list
* @author fengyapeng
* @since 2016 -10-13 10:49:39
*/
public Pagedata<Device> deviceSearchDevicesByApplyId(Integer applyId, int pageSize) throws WeixinException {
return this.deviceSearchDevicesByApplyId(applyId, 0, pageSize);
}
/**
* 查询已有的设备IDUUIDMajorMinor激活状态备注信息关联门店关联页面等信息
* 分页获取设备id下的根据上次查询的最后的设备编号前多少设备
*
* @param applyId the apply id
* @return the list
* @author fengyapeng
* @since 2016 -10-13 10:49:39
*/
public Pagedata<Device> deviceSearchDevicesByApplyId(Integer applyId, int lastDeviceId, int pageSize) throws WeixinException {
String device_search_uri = getRequestUri("shake_around_device_search_uri");
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", 3);
jsonObject.put("apply_id", applyId);
jsonObject.put("last_seen", lastDeviceId);
if (pageSize > 50) {
pageSize = 50;
}
jsonObject.put("count", pageSize);
WeixinResponse response = weixinExecutor
.post(String.format(device_search_uri, tokenManager.getAccessToken()), jsonObject.toJSONString());
JSONObject json = response.getAsJson();
JSONObject data = json.getJSONObject("data");
String deviceStr = data.getString("devices");
List<Device> devices = JSON.parseArray(deviceStr, Device.class);
Pagedata<Device> pagedata = new Pagedata<Device>(null, data.getIntValue("total_count"), devices);
return pagedata;
}
/**
* 编辑设备的备注信息可用设备ID或完整的UUIDMajorMinor指定设备二者选其一
*
* @param device the device
* @param comment the comment
* @return api result
* @author fengyapeng
* @since 2016 -10-13 14:33:06
*/
public ApiResult deviceUpdateComment(Device device, String comment) throws WeixinException {
String device_update_uri = getRequestUri("shake_around_device_update_uri");
JSONObject jsonObject = new JSONObject();
JSONObject deviceJsonObj = new JSONObject();
jsonObject.put("device_identifier", deviceJsonObj);
jsonObject.put("comment", comment);
if (device.getDeviceId() == null) {
deviceJsonObj.put("uuid", device.getUuid());
deviceJsonObj.put("major", device.getMajor());
deviceJsonObj.put("minor", device.getMinor());
} else {
deviceJsonObj.put("device_id", device.getDeviceId());
}
WeixinResponse weixinResponse = weixinExecutor
.post(String.format(device_update_uri, tokenManager.getAccessToken()), jsonObject.toJSONString());
return weixinResponse.getAsResult();
}
/**
* 获取设备信息包括UUIDmajorminor以及距离openID等信息.
*
*
* <a herf="
* http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443447963&token=&lang=zh_CN"></a>
*
* @param ticket the ticket 摇周边业务的ticket可在摇到的URL中得到ticket生效时间为30分钟每一次摇都会重新生成新的ticket
* @return shake user info
* @author fengyapeng
* @since 2016 -10-21 19:34:38
*/
public ShakeUserInfo getShakeUserInfo(String ticket) throws WeixinException {
String user_get_shake_info_url = getRequestUri("shake_around_user_get_shake_info");
JSONObject jsonObject = new JSONObject();
jsonObject.put("ticket", ticket);
WeixinResponse weixinResponse = weixinExecutor
.post(String.format(user_get_shake_info_url, tokenManager.getAccessToken()), jsonObject.toJSONString());
return weixinResponse.getAsJson().getObject("data", ShakeUserInfo.class);
}
}

View File

@ -1,4 +1,4 @@
# \u5fae\u4fe1\u516c\u4f17\u5e73\u53f0\u6587\u6863\u8bf4\u660e
# \u5FAE\u4FE1\u516C\u4F17\u5E73\u53F0\u6587\u6863\u8BF4\u660E
# http://mp.weixin.qq.com/wiki/index.php
# ----------------------------------------------------------------------------
@ -9,208 +9,233 @@ tenpay_base_url=http://mch.tenpay.com
tenpay_ssl_base_url=https://mch.tenpay.com
tenpay_gw_base_url=https://gw.tenpay.com
# \u7f51\u9875oauth\u6388\u6743URL
# \u7F51\u9875oauth\u6388\u6743URL
sns_user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u4ee3\u516c\u4f17\u53f7\u7f51\u9875oauth\u6388\u6743URL
# \u7B2C\u4E09\u65B9\u7EC4\u4EF6\u4EE3\u516C\u4F17\u53F7\u7F51\u9875oauth\u6388\u6743URL
sns_component_user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s&component_appid=%s#wechat_redirect
# \u7f51\u9875oauth\u6388\u6743\u83b7\u53d6token
# \u7F51\u9875oauth\u6388\u6743\u83B7\u53D6token
sns_user_token_uri={api_base_url}/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u4ee3\u516c\u4f17\u53f7\u7f51\u9875oauth\u6388\u6743\u83b7\u53d6token
# \u7B2C\u4E09\u65B9\u7EC4\u4EF6\u4EE3\u516C\u4F17\u53F7\u7F51\u9875oauth\u6388\u6743\u83B7\u53D6token
sns_component_user_token_uri={api_base_url}/sns/oauth2/component/access_token?appid=%s&code=%s&grant_type=authorization_code&component_appid=%s&component_access_token=%s
# \u7f51\u9875oauth\u6388\u6743\u5237\u65b0token
# \u7F51\u9875oauth\u6388\u6743\u5237\u65B0token
sns_token_refresh_uri={api_base_url}/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u4ee3\u516c\u4f17\u53f7\u7f51\u9875oauth\u6388\u6743\u5237\u65b0token
# \u7B2C\u4E09\u65B9\u7EC4\u4EF6\u4EE3\u516C\u4F17\u53F7\u7F51\u9875oauth\u6388\u6743\u5237\u65B0token
sns_component_token_refresh_uri={api_base_url}/sns/oauth2/component/refresh_token?appid=%s&grant_type=refresh_token&component_appid=%s&component_access_token=%s&refresh_token=%s
# \u7f51\u9875oauthoauth\u6388\u6743\u9a8c\u8bc1token
# \u7F51\u9875oauthoauth\u6388\u6743\u9A8C\u8BC1token
sns_auth_token_uri={api_base_url}/sns/auth?access_token=%s&openid=%s
# \u7f51\u9875oauth\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f
# \u7F51\u9875oauth\u6388\u6743\u83B7\u53D6\u7528\u6237\u4FE1\u606F
sns_user_info_uri={api_base_url}/sns/userinfo?access_token=%s&openid=%s&lang=%s
# \u5f00\u653e\u5e73\u53f0\u626b\u7801\u767b\u9646\u6388\u6743
# \u5F00\u653E\u5E73\u53F0\u626B\u7801\u767B\u9646\u6388\u6743
open_user_auth_uri=https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
# \u76f4\u63a5\u83b7\u53d6\u7528\u6237\u4fe1\u606f
# \u76F4\u63A5\u83B7\u53D6\u7528\u6237\u4FE1\u606F
api_user_info_uri={api_cgi_url}/user/info?access_token=%s&openid=%s&lang=%s
# \u6279\u91cf\u83b7\u53d6\u7528\u6237\u4fe1\u606f
# \u6279\u91CF\u83B7\u53D6\u7528\u6237\u4FE1\u606F
api_users_info_uri={api_cgi_url}/user/info/batchget?access_token=%s
# \u83b7\u53d6token
# \u83B7\u53D6token
api_token_uri={api_cgi_url}/token?grant_type=client_credential&appid=%s&secret=%s
# \u83b7\u53d6\u4e8c\u7ef4\u7801
# \u83B7\u53D6\u4E8C\u7EF4\u7801
qr_ticket_uri={api_cgi_url}/qrcode/create?access_token=%s
qr_image_uri={mp_base_url}/showqrcode?ticket=%s
# \u4e0a\u4f20\u5a92\u4f53\u6587\u4ef6
# \u4E0A\u4F20\u5A92\u4F53\u6587\u4EF6
media_upload_uri={api_cgi_url}/media/upload?access_token=%s&type=%s
# \u4e0a\u4f20\u56fe\u7247
# \u4E0A\u4F20\u56FE\u7247
image_upload_uri={api_cgi_url}/media/uploadimg?access_token=%s
# \u4e0b\u8f7d\u5a92\u4f53\u6587\u4ef6
# \u4E0B\u8F7D\u5A92\u4F53\u6587\u4EF6
meida_download_uri={api_cgi_url}/media/get?access_token=%s&media_id=%s
# \u53d1\u9001\u5ba2\u670d\u6d88\u606f
# \u53D1\u9001\u5BA2\u670D\u6D88\u606F
custom_notify_uri={api_cgi_url}/message/custom/send?access_token=%s
# \u521b\u5efa\u5206\u7ec4
# \u521B\u5EFA\u5206\u7EC4
group_create_uri={api_cgi_url}/groups/create?access_token=%s
# \u67e5\u8be2\u5206\u7ec4
# \u67E5\u8BE2\u5206\u7EC4
group_get_uri={api_cgi_url}/groups/get?access_token=%s
# \u67e5\u8be2\u7528\u6237\u6240\u5728\u5206\u7ec4
# \u67E5\u8BE2\u7528\u6237\u6240\u5728\u5206\u7EC4
group_getid_uri={api_cgi_url}/groups/getid?access_token=%s
# \u4fee\u6539\u5206\u7ec4\u540d
# \u4FEE\u6539\u5206\u7EC4\u540D
group_modify_uri={api_cgi_url}/groups/update?access_token=%s
# \u79fb\u52a8\u7528\u6237\u5206\u7ec4
# \u79FB\u52A8\u7528\u6237\u5206\u7EC4
group_move_uri={api_cgi_url}/groups/members/update?access_token=%s
# \u6279\u91cf\u79fb\u52a8\u7528\u6237\u5206\u7ec4
# \u6279\u91CF\u79FB\u52A8\u7528\u6237\u5206\u7EC4
group_batchmove_uri={api_cgi_url}/groups/members/batchupdate?access_token=%s
# \u5220\u9664\u7528\u6237\u5206\u7ec4
# \u5220\u9664\u7528\u6237\u5206\u7EC4
group_delete_uri={api_cgi_url}/groups/delete?access_token=%s
# \u83b7\u53d6\u5173\u6ce8\u7740
# \u83B7\u53D6\u5173\u6CE8\u7740
following_uri={api_cgi_url}/user/get?access_token=%s&next_openid=%s
# \u81ea\u5b9a\u4e49\u83dc\u5355
# \u81EA\u5B9A\u4E49\u83DC\u5355
menu_create_uri={api_cgi_url}/menu/create?access_token=%s
# \u521b\u5efa\u4e2a\u6027\u5316\u83dc\u5355
# \u521B\u5EFA\u4E2A\u6027\u5316\u83DC\u5355
menu_custom_create_uri={api_cgi_url}/menu/addconditional?access_token=%s
# \u67e5\u8be2\u83dc\u5355
# \u67E5\u8BE2\u83DC\u5355
menu_get_uri={api_cgi_url}/menu/get?access_token=%s
# \u67e5\u8be2\u901a\u8fc7\u63a5\u53e3\u6216\u8005\u5728\u516c\u4f17\u5e73\u53f0\u4e0a\u8bbe\u7f6e\u7684\u83dc\u5355\u914d\u7f6e\u4fe1\u606f
# \u67E5\u8BE2\u901A\u8FC7\u63A5\u53E3\u6216\u8005\u5728\u516C\u4F17\u5E73\u53F0\u4E0A\u8BBE\u7F6E\u7684\u83DC\u5355\u914D\u7F6E\u4FE1\u606F
menu_get_selfmenu_uri={api_cgi_url}/get_current_selfmenu_info?access_token=%s
# \u5220\u9664\u83dc\u5355
# \u5220\u9664\u83DC\u5355
menu_delete_uri={api_cgi_url}/menu/delete?access_token=%s
# \u5220\u9664\u4e2a\u6027\u5316\u83dc\u5355
# \u5220\u9664\u4E2A\u6027\u5316\u83DC\u5355
menu_delete_custom_uri={api_cgi_url}/menu/delconditional?access_token=%s
# \u6d4b\u8bd5\u4e2a\u6027\u5316\u83dc\u5355\u5339\u914d\u7ed3\u679c
# \u6D4B\u8BD5\u4E2A\u6027\u5316\u83DC\u5355\u5339\u914D\u7ED3\u679C
menu_trymatch_uri={api_cgi_url}/menu/trymatch?access_token=%s
# \u4e0a\u4f20\u56fe\u6587
# \u4E0A\u4F20\u56FE\u6587
article_upload_uri={api_cgi_url}/media/uploadnews?access_token=%s
# \u4e0a\u4f20\u89c6\u9891
# \u4E0A\u4F20\u89C6\u9891
video_upload_uri={api_cgi_url}/media/uploadvideo?access_token=%s
# \u5206\u7ec4\u7fa4\u53d1
# \u5206\u7EC4\u7FA4\u53D1
mass_group_uri={api_cgi_url}/message/mass/sendall?access_token=%s
# openId\u7fa4\u53d1
# openId\u7FA4\u53D1
mass_openid_uri={api_cgi_url}/message/mass/send?access_token=%s
# \u5220\u9664\u7fa4\u53d1
# \u5220\u9664\u7FA4\u53D1
mass_delete_uri={api_cgi_url}/message/mass/delete?access_token=%s
# \u7fa4\u53d1\u9884\u89c8
# \u7FA4\u53D1\u9884\u89C8
mass_preview_uri={api_cgi_url}/message/mass/preview?access_token=%s
# \u67e5\u8be2\u7fa4\u53d1\u72b6\u6001
# \u67E5\u8BE2\u7FA4\u53D1\u72B6\u6001
mass_get_uri={api_cgi_url}/message/mass/get?access_token=%s
# \u5ba2\u670d\u804a\u5929\u8bb0\u5f55
# \u5BA2\u670D\u804A\u5929\u8BB0\u5F55
kf_chatrecord_uri={api_base_url}/customservice/msgrecord/getmsglist?access_token=%s
# \u5ba2\u670d\u57fa\u672c\u4fe1\u606f
# \u5BA2\u670D\u57FA\u672C\u4FE1\u606F
kf_list_uri={api_cgi_url}/customservice/getkflist?access_token=%s
# \u5728\u7ebf\u5ba2\u670d\u57fa\u672c\u4fe1\u606f
# \u5728\u7EBF\u5BA2\u670D\u57FA\u672C\u4FE1\u606F
kf_onlinelist_uri={api_cgi_url}/customservice/getonlinekflist?access_token=%s
# \u65b0\u589e\u591a\u5ba2\u670d\u8d26\u53f7
# \u65B0\u589E\u591A\u5BA2\u670D\u8D26\u53F7
kf_create_uri={api_base_url}/customservice/kfaccount/add?access_token=%s
# \u9080\u8bf7\u7ed1\u5b9a\u5ba2\u670d\u5e10\u53f7
# \u9080\u8BF7\u7ED1\u5B9A\u5BA2\u670D\u5E10\u53F7
kf_invite_uri={api_base_url}customservice/kfaccount/inviteworker?access_token=%s
# \u66f4\u65b0\u591a\u5ba2\u670d\u8d26\u53f7
# \u66F4\u65B0\u591A\u5BA2\u670D\u8D26\u53F7
kf_update_uri={api_base_url}/customservice/kfaccount/update?access_token=%s
# \u4e0a\u4f20\u5ba2\u670d\u5934\u50cf
# \u4E0A\u4F20\u5BA2\u670D\u5934\u50CF
kf_avatar_uri={api_base_url}/customservice/kfacount/uploadheadimg?access_token=%s&kf_account=%s
# \u5220\u9664\u5ba2\u670d\u8d26\u53f7
# \u5220\u9664\u5BA2\u670D\u8D26\u53F7
kf_delete_uri={api_base_url}/customservice/kfaccount/del?access_token=%s&kf_account=%s
# \u521b\u5efa\u5ba2\u670d\u4f1a\u8bdd
# \u521B\u5EFA\u5BA2\u670D\u4F1A\u8BDD
kfsession_create_uri={api_base_url}/customservice/kfsession/create?access_token=%s
# \u5173\u95ed\u5ba2\u670d\u4f1a\u8bdd
# \u5173\u95ED\u5BA2\u670D\u4F1A\u8BDD
kfsession_close_uri={api_base_url}/customservice/kfsession/close?access_token=%s
# \u83b7\u53d6\u5ba2\u670d\u4f1a\u8bdd\u72b6\u6001
# \u83B7\u53D6\u5BA2\u670D\u4F1A\u8BDD\u72B6\u6001
kfsession_get_uri={api_base_url}/customservice/kfsession/getsession?access_token=%s&openid=%s
# \u83b7\u53d6\u5ba2\u670d\u7684\u4f1a\u8bdd\u5217\u8868
# \u83B7\u53D6\u5BA2\u670D\u7684\u4F1A\u8BDD\u5217\u8868
kfsession_list_uri={api_base_url}/customservice/kfsession/getsessionlist?access_token=%s&kf_account=%s
# \u83b7\u53d6\u672a\u63a5\u5165\u4f1a\u8bdd\u5217\u8868
# \u83B7\u53D6\u672A\u63A5\u5165\u4F1A\u8BDD\u5217\u8868
kfsession_wait_uri={api_base_url}/customservice/kfsession/getwaitcase?access_token=%s
# \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5
# \u957F\u94FE\u63A5\u8F6C\u77ED\u94FE\u63A5
shorturl_uri={api_cgi_url}/shorturl?access_token=%s
# \u8bbe\u7f6e\u5907\u6ce8\u540d
# \u8BBE\u7F6E\u5907\u6CE8\u540D
username_remark_uri={api_cgi_url}/user/info/updateremark?access_token=%s
# \u8bbe\u7f6e\u6a21\u677f\u6d88\u606f\u6240\u5904\u884c\u4e1a
# \u8BBE\u7F6E\u6A21\u677F\u6D88\u606F\u6240\u5904\u884C\u4E1A
template_set_industry_uri={api_cgi_url}/template/api_set_industry?access_token=%s
# \u83b7\u53d6\u8bbe\u7f6e\u7684\u884c\u4e1a\u4fe1\u606f
# \u83B7\u53D6\u8BBE\u7F6E\u7684\u884C\u4E1A\u4FE1\u606F
template_get_industry_uri={api_cgi_url}/template/get_industry?access_token=%s
# \u83b7\u53d6\u6a21\u677f\u6d88\u606fID
# \u83B7\u53D6\u6A21\u677F\u6D88\u606FID
template_getid_uri={api_cgi_url}/template/api_add_template?access_token=%s
# \u83b7\u53d6\u6a21\u677f\u5217\u8868
# \u83B7\u53D6\u6A21\u677F\u5217\u8868
template_getall_uri={api_cgi_url}/template/get_all_private_template?access_token=%s
# \u5220\u9664\u6a21\u677f
# \u5220\u9664\u6A21\u677F
template_del_uri={api_cgi_url}/template/del_private_template?access_token=%s
# \u53d1\u9001\u6a21\u677f\u6d88\u606f
# \u53D1\u9001\u6A21\u677F\u6D88\u606F
template_send_uri={api_cgi_url}/message/template/send?access_token=%s
# \u8bed\u4e49\u7406\u89e3
# \u8BED\u4E49\u7406\u89E3
semantic_uri={api_base_url}/semantic/semproxy/search?access_token=%s
# \u5fae\u4fe1\u670d\u52a1\u5730\u5740
# \u5FAE\u4FE1\u670D\u52A1\u5730\u5740
getcallbackip_uri={api_cgi_url}/getcallbackip?access_token=%s
# \u63a5\u53e3\u8c03\u7528\u6b21\u6570\u6e05\u96f6
# \u63A5\u53E3\u8C03\u7528\u6B21\u6570\u6E05\u96F6
clearquota_uri={api_cgi_url}/clear_quota?access_token=%s
# \u6570\u636e\u7edf\u8ba1
# \u6570\u636E\u7EDF\u8BA1
datacube_uri={api_base_url}/datacube/%s?access_token=%s
##########################\u8001\u7248\u672c\u652f\u4ed8~start
# \u8ba2\u5355\u67e5\u8be2
##########################\u8001\u7248\u672C\u652F\u4ED8~start
# \u8BA2\u5355\u67E5\u8BE2
orderquery_old_uri={api_base_url}/pay/orderquery?access_token=%s
# \u53d1\u8d27\u901a\u77e5
# \u53D1\u8D27\u901A\u77E5
delivernotify_old_uri={api_base_url}/pay/delivernotify?access_token=%s
# \u7ef4\u6743\u5904\u7406
# \u7EF4\u6743\u5904\u7406
payfeedback_old_uri={api_base_url}/payfeedback/update?access_token=%s&openid=%s&feedbackid=%s
# \u5bf9\u8d26\u5355\u4e0b\u8f7d
# \u5BF9\u8D26\u5355\u4E0B\u8F7D
downloadbill_old_uri={tenpay_base_url}/cgi-bin/mchdown_real_new.cgi
# \u9000\u6b3e\u67e5\u8be2
# \u9000\u6B3E\u67E5\u8BE2
refundquery_old_uri={tenpay_gw_base_url}/gateway/normalrefundquery.xml
# \u9000\u6b3e\u7533\u8bf7
# \u9000\u6B3E\u7533\u8BF7
refundapply_old_uri={tenpay_ssl_base_url}/refundapi/gateway/refund.xml
# native\u652f\u4ed8
# native\u652F\u4ED8
nativepay_old_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s&timestamp=%s&noncestr=%s
##########################\u8001\u7248\u672c\u652f\u4ed8~end
##########################\u8001\u7248\u672C\u652F\u4ED8~end
# \u4e0a\u4f20\u6c38\u4e45\u56fe\u6587\u7d20\u6750
# \u4E0A\u4F20\u6C38\u4E45\u56FE\u6587\u7D20\u6750
material_article_upload_uri={api_cgi_url}/material/add_news?access_token=%s
# \u4e0a\u4f20\u6c38\u4e45\u5a92\u4f53\u7d20\u6750
# \u4E0A\u4F20\u6C38\u4E45\u5A92\u4F53\u7D20\u6750
material_media_upload_uri={api_cgi_url}/material/add_material?access_token=%s
# \u4e0b\u8f7d\u6c38\u4e45\u5a92\u4f53\u7d20\u6750
# \u4E0B\u8F7D\u6C38\u4E45\u5A92\u4F53\u7D20\u6750
material_media_download_uri={api_cgi_url}/material/get_material?access_token=%s
# \u66f4\u65b0\u6c38\u4e45\u56fe\u6587\u7d20\u6750
# \u66F4\u65B0\u6C38\u4E45\u56FE\u6587\u7D20\u6750
material_article_update_uri={api_cgi_url}/material/update_news?access_token=%s
# \u5220\u9664\u6c38\u4e45\u5a92\u4f53\u7d20\u6750
# \u5220\u9664\u6C38\u4E45\u5A92\u4F53\u7D20\u6750
material_media_del_uri={api_cgi_url}/material/del_material?access_token=%s
# \u83b7\u53d6\u5a92\u4f53\u7d20\u6750\u603b\u6570
# \u83B7\u53D6\u5A92\u4F53\u7D20\u6750\u603B\u6570
material_media_count_uri={api_cgi_url}/material/get_materialcount?access_token=%s
# \u83b7\u53d6\u5a92\u4f53\u7d20\u6750\u5217\u8868
# \u83B7\u53D6\u5A92\u4F53\u7D20\u6750\u5217\u8868
material_media_list_uri={api_cgi_url}/material/batchget_material?access_token=%s
# \u81ea\u52a8\u56de\u590d\u89c4\u5219
# \u81EA\u52A8\u56DE\u590D\u89C4\u5219
autoreply_setting_get_uri={api_cgi_url}/get_current_autoreply_info?access_token=%s
# \u521b\u5efa\u6807\u7b7e
# \u521B\u5EFA\u6807\u7B7E
tag_create_uri={api_cgi_url}/tags/create?access_token=%s
# \u83b7\u53d6\u6807\u7b7e
# \u83B7\u53D6\u6807\u7B7E
tag_get_uri={api_cgi_url}/tags/get?access_token=%s
# \u66f4\u65b0\u6807\u7b7e
# \u66F4\u65B0\u6807\u7B7E
tag_update_uri={api_cgi_url}/tags/update?access_token=%s
# \u5220\u9664\u6807\u7b7e
# \u5220\u9664\u6807\u7B7E
tag_delete_uri={api_cgi_url}/tags/delete?access_token=%s
# \u4e3a\u7528\u6237\u6253\u6807\u7b7e
# \u4E3A\u7528\u6237\u6253\u6807\u7B7E
tag_tagging_uri={api_cgi_url}/tags/members/batchtagging?access_token=%s
# \u4e3a\u7528\u6237\u53d6\u6d88\u6807\u7b7e
# \u4E3A\u7528\u6237\u53D6\u6D88\u6807\u7B7E
tag_untagging_uri={api_cgi_url}/tags/members/batchuntagging?access_token=%s
# \u83b7\u53d6\u7528\u6237\u8eab\u4e0a\u7684\u6807\u7b7e\u5217\u8868
# \u83B7\u53D6\u7528\u6237\u8EAB\u4E0A\u7684\u6807\u7B7E\u5217\u8868
tag_userids_uri={api_cgi_url}/tags/getidlist?access_token=%s
# \u83b7\u53d6\u6807\u7b7e\u4e0b\u7c89\u4e1d\u5217\u8868
# \u83B7\u53D6\u6807\u7B7E\u4E0B\u7C89\u4E1D\u5217\u8868
tag_user_uri={api_cgi_url}/user/tag/get?access_token=%s
# \u83b7\u53d6\u9ed1\u540d\u5355\u5217\u8868
# \u83B7\u53D6\u9ED1\u540D\u5355\u5217\u8868
getblacklist_uri={api_cgi_url}/tags/members/getblacklist?access_token=%s
# \u62c9\u9ed1\u7528\u6237
# \u62C9\u9ED1\u7528\u6237
batchblacklist_uri={api_cgi_url}/tags/members/batchblacklist?access_token=%s
# \u53d6\u6d88\u62c9\u9ed1\u7528\u6237
# \u53D6\u6D88\u62C9\u9ED1\u7528\u6237
batchunblacklist_uri={api_cgi_url}/tags/members/batchunblacklist?access_token=%s
# \u521b\u5efa\u5361\u5238
# \u521B\u5EFA\u5361\u5238
card_create_uri={api_base_url}/card/create?access_token=%s
# \u8bbe\u7f6e\u4e70\u5355\u63a5\u53e3
# \u8BBE\u7F6E\u4E70\u5355\u63A5\u53E3
card_paycell_uri={api_base_url}/card/paycell/set?access_token=%s
# \u8bbe\u7f6e\u81ea\u52a9\u6838\u9500\u63a5\u53e3
# \u8BBE\u7F6E\u81EA\u52A9\u6838\u9500\u63A5\u53E3
card_selfconsumecell_uri={api_base_url}/card/selfconsumecell/set?access_token=%s
# \u521b\u5efa\u5361\u5238\u4e8c\u7ef4\u7801\u63a5\u53e3
# \u521B\u5EFA\u5361\u5238\u4E8C\u7EF4\u7801\u63A5\u53E3
card_qr_ticket_uri={api_base_url}/card/qrcode/create?access_token=%s
# \u4FEE\u6539\u5361\u5238
card_update_uri={api_base_url}/card/update?access_token=%s
#\u8BBE\u7F6E\u6D4B\u8BD5\u767D\u540D\u5355\u63A5\u53E3
card_set_test_whitelist_uri={api_base_url}/card/testwhitelist/set?access_token=%s
#\u67E5\u770B\u5361\u5238\u8BE6\u60C5\u63A5\u53E3
card_get_uri={api_base_url}/card/get?access_token=%s
#\u4F1A\u5458\u5361\u6FC0\u6D3B\u63A5\u53E3
card_member_card_activate_uri={api_base_url}/card/membercard/activate?access_token=%s
#\u8BBE\u7F6E\u4F1A\u5458\u5361\u5F00\u5361\u5B57\u6BB5
card_member_card_activate_user_form_uri={api_base_url}/card/membercard/activateuserform/set?access_token=%s
#\u4F1A\u5458\u5361\u7528\u6237\u4FE1\u606F
card_member_card_user_info_uri={api_base_url}/card/membercard/userinfo/get?access_token=%s
#\u66F4\u65B0\u4F1A\u5458\u4FE1\u606F
card_member_card_update_user_uri={api_base_url}/card/membercard/updateuser?access_token=%s
# \u4f7f\u7528\u6388\u6743\u7801\u6362\u53d6\u516c\u4f17\u53f7\u7684\u63a5\u53e3\u8c03\u7528\u51ed\u636e\u548c\u6388\u6743\u4fe1\u606f
# \u4F7F\u7528\u6388\u6743\u7801\u6362\u53D6\u516C\u4F17\u53F7\u7684\u63A5\u53E3\u8C03\u7528\u51ED\u636E\u548C\u6388\u6743\u4FE1\u606F
component_exchange_authorizer_uri={api_cgi_url}/component/api_query_auth?component_access_token=%s
# \u83b7\u53d6\u6388\u6743\u65b9\u7684\u516c\u4f17\u53f7\u5e10\u53f7\u57fa\u672c\u4fe1\u606f
# \u83B7\u53D6\u6388\u6743\u65B9\u7684\u516C\u4F17\u53F7\u5E10\u53F7\u57FA\u672C\u4FE1\u606F
component_get_authorizer_uri={api_cgi_url}/component/api_get_authorizer_info?component_access_token=%s
# \u83b7\u53d6\u6388\u6743\u65b9\u7684\u9009\u9879\u8bbe\u7f6e\u4fe1\u606f
# \u83B7\u53D6\u6388\u6743\u65B9\u7684\u9009\u9879\u8BBE\u7F6E\u4FE1\u606F
component_get_authorizer_option_uri={api_cgi_url}/component/api_get_authorizer_option?component_access_token=%s
# \u8bbe\u7f6e\u6388\u6743\u65b9\u7684\u9009\u9879\u4fe1\u606f
component_set_authorizer_option_uri={api_cgi_url}component/api_set_authorizer_option?component_access_token=%s
# \u8BBE\u7F6E\u6388\u6743\u65B9\u7684\u9009\u9879\u4FE1\u606F
component_set_authorizer_option_uri={api_cgi_url}component/api_set_authorizer_option?component_access_token=%s
# \u6447\u4E00\u6447\u5468\u8FB9-\u7533\u8BF7\u8BBE\u5907ID
shake_around_device_apply_uri={api_base_url}/shakearound/device/applyid?access_token=%s
# \u6447\u4E00\u6447\u5468\u8FB9-\u8BBE\u5907ID\u7533\u8BF7\u72B6\u6001\u67E5\u8BE2
shake_around_device_apply_status_uri={api_base_url}/shakearound/device/applystatus?access_token=%s
#\u6447\u4E00\u6447\u5468\u8FB9-\u8BBE\u5907\u7F16\u8F91\u5907\u6CE8\u4FE1\u606F
shake_around_device_update_uri={api_base_url}/shakearound/device/update?access_token=%s
#\u6447\u4E00\u6447\u5468\u8FB9-\u67E5\u8BE2\u8BBE\u5907\u5217\u8868
shake_around_device_search_uri={api_base_url}/shakearound/device/search?access_token=%s
#\u6447\u4E00\u6447\u5468\u8FB9-\u83B7\u53D6\u8BBE\u5907\u548C\u7528\u6237\u4FE1\u606F
shake_around_user_get_shake_info={api_base_url}/shakearound/user/getshakeinfo?access_token=%s

View File

@ -0,0 +1,158 @@
package com.foxinmy.weixin4j.mp.model.shakearound;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 摇一摇设备信息device_id uuid major minor 可以2者选一
* @auther: Feng Yapeng
* @since: 2016/10/13 9:59
*/
public class Device {
/**
* 设备编号
*/
@JSONField(name = "device_id")
private Integer deviceId;
private String uuid;
private Integer major;
private Integer minor;
/**
* 激活状态0未激活1已激活
*/
private int status;
/**
* 设备最近一次被摇到的日期最早只能获取前一天的数据新申请的设备该字段值为0
*/
@JSONField(name = "last_active_time")
private String lastActiveTime;
/**
* 若配置了设备与其他公众账号门店关联关系则返回配置门店归属的公众账号appid
* <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1459246251">查看配置设备与其他公众账号门店关联关系接口</a>
*/
@JSONField(name = "poi_appid")
private String poiAppId;
/**
* 设备关联的门店ID关联门店后在门店1KM的范围内有优先摇出信息的机会
* <a href="https://mp.weixin.qq.com/zh_CN/htmledition/comm_htmledition/res/store_manage/store_manage_file.zip"></a>门店相关信息具体可查看门店相关的接口文档
*/
@JSONField(name = "poi_id")
private String poiId;
/**
* 设备的备注信息
*/
private String comment;
public Device() {
}
/**
*
* @param deviceId
*/
public Device(Integer deviceId) {
this.deviceId = deviceId;
}
public Device(String uuid, Integer major, Integer minor) {
this.uuid = uuid;
this.major = major;
this.minor = minor;
}
public Integer getDeviceId() {
return deviceId;
}
public void setDeviceId(int deviceId) {
this.deviceId = deviceId;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public Integer getMajor() {
return major;
}
public void setMajor(int major) {
this.major = major;
}
public Integer getMinor() {
return minor;
}
public void setMinor(int minor) {
this.minor = minor;
}
public void setDeviceId(Integer deviceId) {
this.deviceId = deviceId;
}
public void setMajor(Integer major) {
this.major = major;
}
public void setMinor(Integer minor) {
this.minor = minor;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getLastActiveTime() {
return lastActiveTime;
}
public void setLastActiveTime(String lastActiveTime) {
this.lastActiveTime = lastActiveTime;
}
public String getPoiAppId() {
return poiAppId;
}
public void setPoiAppId(String poiAppId) {
this.poiAppId = poiAppId;
}
public String getPoiId() {
return poiId;
}
public void setPoiId(String poiId) {
this.poiId = poiId;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}

View File

@ -0,0 +1,84 @@
package com.foxinmy.weixin4j.mp.model.shakearound;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.Date;
/**
* 摇一摇周边设备审核信息
*
* @auther: Feng Yapeng
* @since: 2016/10/12 21:47
*/
public class DeviceAuditState {
/**
* 申请设备ID时所返回的批次ID
*/
@JSONField(name = "apply_id")
private Integer applyId;
/**
* 审核状态0审核未通过1审核中2审核已通过
* 若单次申请的设备ID数量小于等于500个系统会进行快速审核
* 若单次申请的设备ID数量大于500个会在三个工作日内完成审核
*/
@JSONField(name = "audit_status")
private String auditStatus;
/**
* 审核备注对审核状态的文字说明
*/
@JSONField(name = "audit_comment")
private String auditComment;
/**
* 提交申请的时间戳
*/
@JSONField(name = "apply_time")
private long applyTime;
/**
* 确定审核结果的时间戳若状态为审核中则该时间值为0
*/
@JSONField(name = "audit_time")
private long auditTime;
public Integer getApplyId() {
return applyId;
}
public void setApplyId(Integer applyId) {
this.applyId = applyId;
}
public String getAuditStatus() {
return auditStatus;
}
public void setAuditStatus(String auditStatus) {
this.auditStatus = auditStatus;
}
public String getAuditComment() {
return auditComment;
}
public void setAuditComment(String auditComment) {
this.auditComment = auditComment;
}
public long getApplyTime() {
return applyTime;
}
public void setApplyTime(long applyTime) {
this.applyTime = applyTime;
}
public long getAuditTime() {
return auditTime;
}
public void setAuditTime(long auditTime) {
this.auditTime = auditTime;
}
}

View File

@ -0,0 +1,58 @@
package com.foxinmy.weixin4j.mp.model.shakearound;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 获取设备信息包括UUIDmajorminor以及距离openID等信息
*
* @author fengyapeng
* @auther: Feng Yapeng
* @since: 2016 /10/21 19:21
* @since 2016 -10-21 19:21:59
*/
public class ShakeUserInfo {
@JSONField(name = "page_id")
private Long pageId;
@JSONField(name = "beacon_info")
private Device device;
@JSONField(name = "poi_id")
private Long poiId;
@JSONField(name = "openid")
private String openId;
public Long getPageId() {
return pageId;
}
public void setPageId(Long pageId) {
this.pageId = pageId;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
public Long getPoiId() {
return poiId;
}
public void setPoiId(Long poiId) {
this.poiId = poiId;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
}

View File

@ -0,0 +1,35 @@
package com.foxinmy.weixin4j.mp.test;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.mp.api.HelperApi;
public class HelpTest extends TokenTest {
private HelperApi helperApi;
@Before
public void init() {
helperApi = new HelperApi(tokenManager);
}
@Test
public void getWechatServerIp() throws WeixinException {
List<String> ipList = helperApi.getWechatServerIp();
Assert.assertFalse(ipList.isEmpty());
}
@Test
public void getMenuSetting() throws WeixinException {
System.err.println(helperApi.getMenuSetting());
}
@Test
public void getAutoReplySetting() throws WeixinException {
System.err.println(helperApi.getAutoReplySetting());
}
}

View File

@ -0,0 +1,162 @@
package com.foxinmy.weixin4j.mp.test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.ApiResult;
import com.foxinmy.weixin4j.model.card.CardCoupons;
import com.foxinmy.weixin4j.model.card.CardQR;
import com.foxinmy.weixin4j.model.card.CouponAdvanceInfo;
import com.foxinmy.weixin4j.model.card.CouponBaseInfo;
import com.foxinmy.weixin4j.model.card.MemberCard;
import com.foxinmy.weixin4j.model.card.MemberInitInfo;
import com.foxinmy.weixin4j.model.card.MemberUpdateInfo;
import com.foxinmy.weixin4j.model.card.MemberUserForm;
import com.foxinmy.weixin4j.model.card.MemberUserInfo;
import com.foxinmy.weixin4j.model.qr.QRResult;
import com.foxinmy.weixin4j.mp.api.CardApi;
import com.foxinmy.weixin4j.type.card.ActivateCommonField;
import com.foxinmy.weixin4j.type.card.ActivateFormFieldType;
import com.foxinmy.weixin4j.type.card.CardCodeType;
import com.foxinmy.weixin4j.type.card.CardColor;
import com.foxinmy.weixin4j.type.card.FieldNameType;
import org.junit.Before;
import org.junit.Test;
/**
* 会员卡测试
*
* @auther: Feng Yapeng
* @since: 2016/12/21 16:37
*/
public class MemberCardTest extends TokenTest {
private CardApi cardApi;
@Before
public void init() {
cardApi = new CardApi(tokenManager);
}
/**
* pn-YDwk59Ft0JSFdGqObxUccUQHw
*/
@Test
public void create() throws WeixinException {
CouponBaseInfo.Builder builder = CardCoupons.customBase();
// 基础必填字段
builder.logoUrl(
"http://mmbiz.qpic.cn/mmbiz_jpg/LtkLicv5iclfqzGpaDqDoMibM6FcMVTrmYXjLu7bJ1tM5MzCxNONQiaZHqrYzs0fTk2T5bLAAXLpvx32hQLmJTGBxQ/0")
.codeType(CardCodeType.CODE_TYPE_BARCODE).brandName("***").title("***会员卡").cardColor(CardColor.Color010).notice("请出示会员卡")
.description("***的会员卡的描述").quantity(10000);
// 基础选填字段
builder.canShare(false).canGiveFriend(false);
builder.centerTitle("卡券居中按钮").centerSubTitle("显示在入口下方的提示语");
MemberCard.Builder memberCardBuilder = CardCoupons.customMemberCard();
//会员卡必填字段
// 会员卡选填字段
memberCardBuilder.prerogative("会员卡特权说明").supplyBalance(true).supplyBonus(false).activateWithWx(true);
memberCardBuilder.customField1(FieldNameType.FIELD_NAME_TYPE_LEVEL, "等级", null);
memberCardBuilder.backgroundPicUrl(
"https://mmbiz.qlogo.cn/mmbiz/2FyQ9TURqmdibM6nYBiagZT49lSlY9Aicw4P3vsoa7dEZIYfNkiaMyzNVYT9jmYhjBbeC8jnkibwbibB5tghC5XcgysQ/0?wx_fmt=jpeg");
MemberCard memberCard = CardCoupons.createMemberCard(builder, memberCardBuilder);
String cardId = cardApi.createCardCoupon(memberCard);
System.out.println(cardId);
}
@Test
public void createCardQR() throws WeixinException {
CardQR.Builder builder = new CardQR.Builder("pn-YDwk59Ft0JSFdGqObxUccUQHw");
QRResult qrResult = cardApi.createCardQR(36000, builder.build());
String showUrl = qrResult.getShowUrl();
System.out.println(showUrl);
}
@Test
public void setMemberUserForm() throws WeixinException {
MemberUserForm memberUserForm = new MemberUserForm();
memberUserForm.setCardId("pn-YDwk59Ft0JSFdGqObxUccUQHw");
MemberUserForm.FormBudiler requiredForm = new MemberUserForm.FormBudiler();
requiredForm.canModify(false);
requiredForm.addCommonField(ActivateCommonField.USER_FORM_INFO_FLAG_EMAIL, ActivateCommonField.USER_FORM_INFO_FLAG_BIRTHDAY,
ActivateCommonField.USER_FORM_INFO_FLAG_MOBILE)
.addRichField(ActivateFormFieldType.FORM_FIELD_CHECK_BOX, "checkBox", "value1", "value2", "value3");
memberUserForm.setRequiredForm(requiredForm);
MemberUserForm.FormBudiler optionalFormBuilder = new MemberUserForm.FormBudiler();
optionalFormBuilder.canModify(false);
optionalFormBuilder.addCommonField(ActivateCommonField.USER_FORM_INFO_FLAG_IDCARD)
.addRichField(ActivateFormFieldType.FORM_FIELD_CHECK_BOX, "checkBoxOPt", "value1", "value2", "value3");
memberUserForm.setOptionalForm(optionalFormBuilder);
memberUserForm.setServiceStatement("会员守则","https://www.baidu.com");
ApiResult apiResult = cardApi.setActivateUserForm(memberUserForm);
}
@Test
public void getMemberUserInfo() throws WeixinException {
MemberUserInfo memberUserInfo = cardApi.getMemberUserInfo("pn-YDwk59Ft0JSFdGqObxUccUQHw", "270869833860");
System.out.println(memberUserInfo);
}
@Test
public void initMemberUser() throws WeixinException {
MemberInitInfo memberInitInfo = new MemberInitInfo();
memberInitInfo.setCardId("pn-YDwk59Ft0JSFdGqObxUccUQHw");
memberInitInfo.setCode("270869833860");
memberInitInfo.setBackgroundPicUrl("https://mmbiz.qlogo.cn/mmbiz/2FyQ9TURqmdibM6nYBiagZT49lSlY9Aicw4HnSKzouD9iaksVA8vIbFT3RuqnWDVMNZib21NDdwKn5OMVMwfSsULXGw/0?wx_fmt=jpeg");
memberInitInfo.setInit_custom_field_value1("铂金");
memberInitInfo.setInitBalance(2);
memberInitInfo.setInitBonus(2);
memberInitInfo.setInitBonusRecord("初始化积分");
ApiResult activate = cardApi.activate(memberInitInfo);
System.out.println(activate);
}
@Test
public void updateMmemberUser() throws WeixinException {
MemberUpdateInfo memberUpdateInfo = new MemberUpdateInfo();
memberUpdateInfo.setCardId("pn-YDwk59Ft0JSFdGqObxUccUQHw");
memberUpdateInfo.setCode("270869833860");
memberUpdateInfo.setAddBalance(20);
memberUpdateInfo.setRecordBalance("充值");
memberUpdateInfo.setNOtify(true,true);
memberUpdateInfo.setCustomFieldValue1("至尊铂金",true);
cardApi.updateUserInfo(memberUpdateInfo);
}
@Test
public void update() throws WeixinException {
CouponBaseInfo.Builder builder = CardCoupons.customBase();
// 基础必填字段
builder.logoUrl(
"http://mmbiz.qpic.cn/mmbiz_jpg/LtkLicv5iclfqzGpaDqDoMibM6FcMVTrmYXjLu7bJ1tM5MzCxNONQiaZHqrYzs0fTk2T5bLAAXLpvx32hQLmJTGBxQ/0")
.codeType(CardCodeType.CODE_TYPE_BARCODE).brandName("***").title("***会员卡").cardColor(CardColor.Color010).notice("请出示会员卡")
.description("***的会员卡的描述").quantity(10000);
// 基础选填字段
builder.canShare(false).canGiveFriend(false);
builder.centerTitle("卡券居中按钮").centerSubTitle("显示在入口下方的提示语");
MemberCard.Builder memberCardBuilder = CardCoupons.customMemberCard();
//会员卡必填字段
// 会员卡选填字段
memberCardBuilder.prerogative("会员卡特权说明").supplyBalance(true).supplyBonus(false).activateWithWx(true);
memberCardBuilder.customField1(FieldNameType.FIELD_NAME_TYPE_LEVEL, "等级", null);
memberCardBuilder.backgroundPicUrl(
"https://mmbiz.qlogo.cn/mmbiz/2FyQ9TURqmdibM6nYBiagZT49lSlY9Aicw4P3vsoa7dEZIYfNkiaMyzNVYT9jmYhjBbeC8jnkibwbibB5tghC5XcgysQ/0?wx_fmt=jpeg");
MemberCard memberCard = CardCoupons.createMemberCard(builder, memberCardBuilder);
CouponAdvanceInfo.Builder advanceBuilder = new CouponAdvanceInfo.Builder();
advanceBuilder.slideImage("此菜品精选食材,以独特的烹饪方法,最大程度地刺激食 客的味蕾","http://mmbiz.qpic.cn/mmbiz/p98FjXy8LacgHxp3sJ3vn97bGLz0ib0Sfz1bjiaoOYA027iasqSG0sjpiby4vce3AtaPu6cIhBHkt6IjlkY9YnDsfw/0");
memberCard.setCouponAdvanceInfo(advanceBuilder.build());
Boolean cardCoupon = cardApi.updateCardCoupon("pn-YDwk59Ft0JSFdGqObxUccUQHw", memberCard);
System.out.println(cardCoupon);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.7.3</version>
<version>1.7.4-SNAPSHOT</version>
</parent>
<artifactId>weixin4j-qy</artifactId>
<name>weixin4j-qy</name>