Merge branch 'develop' into store

This commit is contained in:
BinaryWang 2016-09-26 19:13:49 +08:00
commit 18e7f7e123
23 changed files with 1751 additions and 438 deletions

View File

@ -20,16 +20,16 @@
=========== ===========
## 版本说明 ## 版本说明
* 本项目定为每月发布一次正式版版本号格式为X.X.0如2.0.02.1.0等月初或月底发布新版本遇到重大问题需修复会及时提交新版本欢迎大家随时提交Pull Request。 * 本项目定为每月发布一次正式版版本号格式为X.X.0如2.0.02.1.0等月初或月底发布新版本遇到重大问题需修复会及时提交新版本欢迎大家随时提交Pull Request
* BUG修复和新特性一般会先发布成小版本作为临时版本如2.0.12.0.2等即尾号不为0以区别于正式版 * BUG修复和新特性一般会先发布成小版本作为临时版本如2.0.12.0.2等即尾号不为0以区别于正式版
* 目前最新版本号为 ![Maven Central](https://img.shields.io/maven-central/v/com.github.binarywang/weixin-java-parent.svg) ,也可以通过访问如下地址查看所有最新的版本: * 目前最新版本号为 ![Maven Central](https://img.shields.io/maven-central/v/com.github.binarywang/weixin-java-parent.svg) ,也可以通过访问链接[【公众号】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-mp%22) [【企业号】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-cp%22)
- [【公众号】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-mp%22) 分别查看所有最新的版本。
- [【企业号】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-cp%22)
## Maven & Gradle ## Maven & Gradle
* 公众号(订阅号、服务号): * 公众号(订阅号、服务号):
maven
```xml ```xml
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
@ -37,12 +37,14 @@
<version>2.1.0</version> <version>2.1.0</version>
</dependency> </dependency>
``` ```
gradle
```groovy ```groovy
compile 'com.github.binarywang:weixin-java-mp:2.1.0' compile 'com.github.binarywang:weixin-java-mp:2.1.0'
``` ```
* 企业号: * 企业号:
maven
```xml ```xml
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
@ -50,7 +52,7 @@ compile 'com.github.binarywang:weixin-java-mp:2.1.0'
<version>2.1.0</version> <version>2.1.0</version>
</dependency> </dependency>
``` ```
gradle
```groovy ```groovy
compile 'com.github.binarywang:weixin-java-cp:2.1.0' compile 'com.github.binarywang:weixin-java-cp:2.1.0'
``` ```
@ -63,16 +65,14 @@ compile 'com.github.binarywang:weixin-java-cp:2.1.0'
* https://git.coding.net/binarywang/weixin-java-tools.git * https://git.coding.net/binarywang/weixin-java-tools.git
## 目前可参考的Demo项目: ## 目前可参考的Demo项目有两个:
* https://github.com/wechat-group/weixin-java-tools-springmvc 1. https://github.com/wechat-group/weixin-mp-demo
* https://github.com/wechat-group/weixin-mp-demo 1. https://github.com/wechat-group/weixin-java-tools-springmvc
* ===========以下为备份仓库,会保持跟主仓库同步
* http://git.oschina.net/binary/weixin-mp-demo
* https://bitbucket.org/binarywang/weixin-mp-demo
## 关于代码贡献 ## 关于代码贡献
* 非常欢迎和感谢对本项目发起Pull Request的同学本项目代码风格为使用2个空格代表一个Tab因此在提交代码时请注意一下否则很容易在IDE格式化代码后与原代码产生大量diff这样会给其他人阅读代码带来极大的困扰。
* 为了便于设置本项目引入editorconfig插件请使用eclipse的同学在贡献代码前安装相关插件IntelliJ IDEA则自带支持无需额外安装插件。
* 本项目可以采用两种方式接受代码贡献:
* 非常欢迎和感谢对本项目发起Pull Request的同学本项目可以采用两种方式接受代码贡献 1. 第一种就是基于[Git Flow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow)开发流程因此在发起Pull Request的时候请选择develop分支。
* 第一种就是基于[Git Flow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow)开发流程因此在发起Pull Request的时候请选择develop分支。 1. 另外一种贡献代码的方式就是加入SDK Developers开发组如果对自己的代码足够自信可以随时提交代码注意要随时进行单元测试保证提交代码没有明显问题具体加入方式请咨询管理员。
* 另外一种贡献代码的方式就是加入SDK Developers开发组如果对自己的代码足够自信可以随时提交代码注意要随时进行单元测试保证提交代码没有明显问题具体加入方式请咨询管理员。
* 本项目代码风格为使用2个空格代表一个Tab因此在提交代码时请注意一下否则很容易在IDE格式化代码后与原代码产生大量diff这样会给其他人阅读代码带来极大的困扰。

View File

@ -13,8 +13,8 @@ subprojects {
repositories { repositories {
mavenLocal() mavenLocal()
maven { url "http://central.maven.org/maven2" }
maven { url "http://maven.aliyun.com/nexus/content/groups/public" } //maven { url "http://maven.aliyun.com/nexus/content/groups/public" }
} }
@ -24,6 +24,8 @@ subprojects {
compile group: 'org.apache.httpcomponents', name: 'httpmime', version:'4.5' compile group: 'org.apache.httpcomponents', name: 'httpmime', version:'4.5'
compile group: 'org.jodd', name: 'jodd-http', version:'3.6.7' compile group: 'org.jodd', name: 'jodd-http', version:'3.6.7'
compile group: 'com.google.code.gson', name: 'gson', version:'2.7' compile group: 'com.google.code.gson', name: 'gson', version:'2.7'
compile group: 'com.google.guava', name: 'guava', version:'19.0'
compile group: 'org.jooq', name: 'joor', version:'0.9.6'
compile group: 'commons-codec', name: 'commons-codec', version:'1.10' compile group: 'commons-codec', name: 'commons-codec', version:'1.10'
compile group: 'commons-io', name: 'commons-io', version:'2.5' compile group: 'commons-io', name: 'commons-io', version:'2.5'
compile group: 'org.apache.commons', name: 'commons-lang3', version:'3.4' compile group: 'org.apache.commons', name: 'commons-lang3', version:'3.4'

20
pom.xml
View File

@ -51,6 +51,8 @@
<jodd-http.version>3.6.7</jodd-http.version> <jodd-http.version>3.6.7</jodd-http.version>
<jedis.version>2.9.0</jedis.version> <jedis.version>2.9.0</jedis.version>
<gson.version>2.7</gson.version> <gson.version>2.7</gson.version>
<guava.version>19.0</guava.version>
<joor.version>0.9.6</joor.version>
<commons-lang3.version>3.4</commons-lang3.version> <commons-lang3.version>3.4</commons-lang3.version>
<commons-io.version>2.5</commons-io.version> <commons-io.version>2.5</commons-io.version>
<commons-codec.version>1.10</commons-codec.version> <commons-codec.version>1.10</commons-codec.version>
@ -111,6 +113,14 @@
<version>${jedis.version}</version> <version>${jedis.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>joor</artifactId>
</dependency>
</dependencies> </dependencies>
<dependencyManagement> <dependencyManagement>
@ -151,6 +161,16 @@
<version>${jetty.version}</version> <version>${jetty.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>joor</artifactId>
<version>${joor.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -0,0 +1,19 @@
package me.chanjar.weixin.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标识某个字段是否是必填的
*
* Created by Binary Wang on 2016/9/25.
* @author binarywang (https://github.com/binarywang)
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Required {
}

View File

@ -19,14 +19,8 @@ package me.chanjar.weixin.common.util.crypto;
import java.io.StringReader; import java.io.StringReader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
@ -36,7 +30,6 @@ import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
@ -79,33 +72,6 @@ public class WxCryptUtil {
this.aesKey = Base64.decodeBase64(encodingAesKey + "="); this.aesKey = Base64.decodeBase64(encodingAesKey + "=");
} }
/**
* 微信公众号支付签名算法(详见:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3)
* @param packageParams 原始参数
* @param signKey 加密Key( 商户Key)
* @return 签名字符串
*/
public static String createSign(Map<String, String> packageParams,
String signKey) {
SortedMap<String, String> sortedMap = new TreeMap<>();
sortedMap.putAll(packageParams);
List<String> keys = new ArrayList<>(packageParams.keySet());
Collections.sort(keys);
StringBuffer toSign = new StringBuffer();
for (String key : keys) {
String value = packageParams.get(key);
if (null != value && !"".equals(value) && !"sign".equals(key)
&& !"key".equals(key)) {
toSign.append(key + "=" + value + "&");
}
}
toSign.append("key=" + signKey);
String sign = DigestUtils.md5Hex(toSign.toString()).toUpperCase();
return sign;
}
static String extractEncryptPart(String xml) { static String extractEncryptPart(String xml) {
try { try {
DocumentBuilder db = builderLocal.get(); DocumentBuilder db = builderLocal.get();

View File

@ -1,7 +1,7 @@
package me.chanjar.weixin.common.util.http; package me.chanjar.weixin.common.util.http;
import me.chanjar.weixin.common.bean.result.WxError; import java.io.IOException;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.http.Consts; import org.apache.http.Consts;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
@ -10,7 +10,8 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import java.io.IOException; import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
/** /**
* 简单的POST请求执行器请求的参数是String, 返回的结果也是String * 简单的POST请求执行器请求的参数是String, 返回的结果也是String
@ -34,6 +35,17 @@ public class SimplePostRequestExecutor implements RequestExecutor<String, String
try (CloseableHttpResponse response = httpclient.execute(httpPost)) { try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
if (responseContent.isEmpty()) {
throw new WxErrorException(
WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容")
.build());
}
if (responseContent.startsWith("<xml>")) {
//xml格式输出直接返回
return responseContent;
}
WxError error = WxError.fromJson(responseContent); WxError error = WxError.fromJson(responseContent);
if (error.getErrorCode() != 0) { if (error.getErrorCode() != 0) {
throw new WxErrorException(error); throw new WxErrorException(error);

View File

@ -1,5 +1,7 @@
package me.chanjar.weixin.common.util.xml; package me.chanjar.weixin.common.util.xml;
import java.io.Writer;
import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter; import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
@ -8,8 +10,6 @@ import com.thoughtworks.xstream.io.xml.XppDriver;
import com.thoughtworks.xstream.security.NullPermission; import com.thoughtworks.xstream.security.NullPermission;
import com.thoughtworks.xstream.security.PrimitiveTypePermission; import com.thoughtworks.xstream.security.PrimitiveTypePermission;
import java.io.Writer;
public class XStreamInitializer { public class XStreamInitializer {
public static XStream getInstance() { public static XStream getInstance() {
@ -34,6 +34,11 @@ public class XStreamInitializer {
} }
} }
@Override
public String encodeNode(String name) {
return name;//防止将_转换成__
}
}; };
} }
}); });

View File

@ -1,10 +1,17 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.result.*;
import java.util.Map; import java.util.Map;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.pay.WxMpPayCallback;
import me.chanjar.weixin.mp.bean.pay.WxMpPayRefundResult;
import me.chanjar.weixin.mp.bean.pay.WxMpPayResult;
import me.chanjar.weixin.mp.bean.pay.WxMpPrepayIdResult;
import me.chanjar.weixin.mp.bean.pay.WxRedpackResult;
import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest;
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderRequest;
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderResult;
/** /**
* 微信支付相关接口 * 微信支付相关接口
* Created by Binary Wang on 2016/7/28. * Created by Binary Wang on 2016/7/28.
@ -12,7 +19,6 @@ import java.util.Map;
*/ */
public interface WxMpPayService { public interface WxMpPayService {
/** /**
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) * 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识" * 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识"
@ -24,22 +30,39 @@ public interface WxMpPayService {
* @param tradeType 交易类型 JSAPINATIVEAPPWAP * @param tradeType 交易类型 JSAPINATIVEAPPWAP
* @param ip 发起支付的客户端IP * @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址 * @param notifyUrl 通知地址
* @throws WxErrorException
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPrepayId(Map<String, String>) instead * @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPrepayId(Map<String, String>) instead
*/ */
@Deprecated @Deprecated
WxMpPrepayIdResult getPrepayId(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String notifyUrl); WxMpPrepayIdResult getPrepayId(String openId, String outTradeNo, double amt,
String body, String tradeType, String ip, String notifyUrl)
throws WxErrorException;
/** /**
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) * 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识" * 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识"
* *
* @param parameters All required/optional parameters for weixin payment * @param parameters All required/optional parameters for weixin payment
* @throws WxErrorException
* @deprecated use me.chanjar.weixin.mp.api.WxMpPayService.unifiedOrder(WxUnifiedOrderRequest) instead
*/ */
WxMpPrepayIdResult getPrepayId(Map<String, String> parameters); @Deprecated
WxMpPrepayIdResult getPrepayId(Map<String, String> parameters)
throws WxErrorException;
/**
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识"
* 接口地址https://api.mch.weixin.qq.com/pay/unifiedorder
* @throws WxErrorException
*
*/
WxUnifiedOrderResult unifiedOrder(WxUnifiedOrderRequest request)
throws WxErrorException;
/** /**
* 该接口调用统一下单接口并拼装发起支付请求需要的参数 * 该接口调用统一下单接口并拼装发起支付请求需要的参数
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 * 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* *
* @param parameters the required or optional parameters * @param parameters the required or optional parameters
*/ */
@ -47,7 +70,7 @@ public interface WxMpPayService {
/** /**
* 该接口调用统一下单接口并拼装NATIVE发起支付请求需要的参数 * 该接口调用统一下单接口并拼装NATIVE发起支付请求需要的参数
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 * 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* tradeType 交易类型 NATIVE 其他交易类型JSAPIAPPWAP * tradeType 交易类型 NATIVE 其他交易类型JSAPIAPPWAP
* *
* @param productId 商户商品ID * @param productId 商户商品ID
@ -56,14 +79,14 @@ public interface WxMpPayService {
* @param body 商品描述 * @param body 商品描述
* @param ip 发起支付的客户端IP * @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址 * @param notifyUrl 通知地址
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map<String, String>) instead * @deprecated Use me.chanjar.weixin.mp.api.WxMpPayService.getPayInfo(Map<String, String>) instead
*/ */
@Deprecated @Deprecated
Map<String, String> getNativePayInfo(String productId, String outTradeNo, double amt, String body, String ip, String notifyUrl) throws WxErrorException; Map<String, String> getNativePayInfo(String productId, String outTradeNo, double amt, String body, String ip, String notifyUrl) throws WxErrorException;
/** /**
* 该接口调用统一下单接口并拼装JSAPI发起支付请求需要的参数 * 该接口调用统一下单接口并拼装JSAPI发起支付请求需要的参数
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 * 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* tradeType 交易类型 JSAPI(其他交易类型NATIVEAPPWAP) * tradeType 交易类型 JSAPI(其他交易类型NATIVEAPPWAP)
* *
* @param openId 支付人openId * @param openId 支付人openId
@ -72,7 +95,7 @@ public interface WxMpPayService {
* @param body 商品描述 * @param body 商品描述
* @param ip 发起支付的客户端IP * @param ip 发起支付的客户端IP
* @param notifyUrl 通知地址 * @param notifyUrl 通知地址
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map<String, String>) instead * @deprecated Use me.chanjar.weixin.mp.api.WxMpPayService.getPayInfo(Map<String, String>) instead
*/ */
@Deprecated @Deprecated
Map<String, String> getJsapiPayInfo(String openId, String outTradeNo, double amt, String body, String ip, String notifyUrl) throws WxErrorException; Map<String, String> getJsapiPayInfo(String openId, String outTradeNo, double amt, String body, String ip, String notifyUrl) throws WxErrorException;
@ -80,9 +103,11 @@ public interface WxMpPayService {
/** /**
* 该接口提供所有微信支付订单的查询,当支付通知处理异常戒丢失的情冴,商户可以通过该接口查询订单支付状态 * 该接口提供所有微信支付订单的查询,当支付通知处理异常戒丢失的情冴,商户可以通过该接口查询订单支付状态
* 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2 * 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
* @throws WxErrorException
* *
*/ */
WxMpPayResult getJSSDKPayResult(String transactionId, String outTradeNo); WxMpPayResult getJSSDKPayResult(String transactionId, String outTradeNo)
throws WxErrorException;
/** /**
* 读取支付结果通知 * 读取支付结果通知
@ -115,8 +140,8 @@ public interface WxMpPayService {
boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature); boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature);
/** /**
* 发送微信红包给个人用户 * 发送普通微信红包给个人用户
* <p> * <pre>
* 需要传入的必填参数如下: * 需要传入的必填参数如下:
* mch_billno//商户订单号 * mch_billno//商户订单号
* send_name//商户名称 * send_name//商户名称
@ -127,12 +152,25 @@ public interface WxMpPayService {
* client_ip//服务器Ip地址 * client_ip//服务器Ip地址
* act_name//活动名称 * act_name//活动名称
* remark //备注 * remark //备注
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5 * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
* <p>
* 使用现金红包功能需要在xml配置文件中额外设置: * 使用现金红包功能需要在xml配置文件中额外设置:
* </pre>
* <partnerId></partnerId>微信商户平台ID * <partnerId></partnerId>微信商户平台ID
* <partnerKey></partnerKey>商户平台设置的API密钥 * <partnerKey></partnerKey>商户平台设置的API密钥
* @deprecated use me.chanjar.weixin.mp.api.WxMpPayService.sendRedpack(WxSendRedpackRequest) instead
* *
*/ */
@Deprecated
WxRedpackResult sendRedpack(Map<String, String> parameters) throws WxErrorException; WxRedpackResult sendRedpack(Map<String, String> parameters) throws WxErrorException;
/**
* 发送微信红包给个人用户
* <pre>
* 文档详见:
* 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
* 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
* </pre>
*/
WxRedpackResult sendRedpack(WxSendRedpackRequest request) throws WxErrorException;
} }

View File

@ -1,29 +1,38 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;
import com.thoughtworks.xstream.XStream; import java.lang.reflect.Field;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
import me.chanjar.weixin.common.util.http.Utf8ResponseHandler;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.api.WxMpPayService;
import me.chanjar.weixin.mp.bean.result.*;
import org.apache.http.Consts;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TreeMap; import java.util.TreeMap;
import org.apache.commons.codec.digest.DigestUtils;
import org.joor.Reflect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.api.WxMpPayService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.pay.WxMpPayCallback;
import me.chanjar.weixin.mp.bean.pay.WxMpPayRefundResult;
import me.chanjar.weixin.mp.bean.pay.WxMpPayResult;
import me.chanjar.weixin.mp.bean.pay.WxMpPrepayIdResult;
import me.chanjar.weixin.mp.bean.pay.WxRedpackResult;
import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest;
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderRequest;
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderResult;
/** /**
* Created by Binary Wang on 2016/7/28. * Created by Binary Wang on 2016/7/28.
* *
@ -31,22 +40,23 @@ import java.util.TreeMap;
*/ */
public class WxMpPayServiceImpl implements WxMpPayService { public class WxMpPayServiceImpl implements WxMpPayService {
private static final List<String> TRADE_TYPES = Lists.newArrayList("JSAPI",
"NATIVE", "APP");
private final Logger log = LoggerFactory.getLogger(WxMpPayServiceImpl.class); private final Logger log = LoggerFactory.getLogger(WxMpPayServiceImpl.class);
private final String[] REQUIRED_ORDER_PARAMETERS = new String[]{"appid", private final String[] REQUIRED_ORDER_PARAMETERS = new String[] { "appid",
"mch_id", "body", "out_trade_no", "total_fee", "spbill_create_ip", "mch_id", "body", "out_trade_no", "total_fee", "spbill_create_ip",
"notify_url", "trade_type"}; "notify_url", "trade_type" };
private HttpHost httpProxy; private WxMpService wxMpService;
private WxMpServiceImpl wxMpService;
public WxMpPayServiceImpl(WxMpServiceImpl wxMpService) { public WxMpPayServiceImpl(WxMpService wxMpService) {
this.wxMpService = wxMpService; this.wxMpService = wxMpService;
this.httpProxy = wxMpService.getHttpProxy();
} }
@Override @Override
@Deprecated
public WxMpPrepayIdResult getPrepayId(String openId, String outTradeNo, public WxMpPrepayIdResult getPrepayId(String openId, String outTradeNo,
double amt, String body, String tradeType, String ip, double amt, String body, String tradeType, String ip,
String callbackUrl) { String callbackUrl) throws WxErrorException {
Map<String, String> packageParams = new HashMap<>(); Map<String, String> packageParams = new HashMap<>();
packageParams.put("appid", packageParams.put("appid",
this.wxMpService.getWxMpConfigStorage().getAppId()); this.wxMpService.getWxMpConfigStorage().getAppId());
@ -64,7 +74,9 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }
@Override @Override
public WxMpPrepayIdResult getPrepayId(final Map<String, String> parameters) { @Deprecated
public WxMpPrepayIdResult getPrepayId(final Map<String, String> parameters)
throws WxErrorException {
final SortedMap<String, String> packageParams = new TreeMap<>(parameters); final SortedMap<String, String> packageParams = new TreeMap<>(parameters);
packageParams.put("appid", packageParams.put("appid",
this.wxMpService.getWxMpConfigStorage().getAppId()); this.wxMpService.getWxMpConfigStorage().getAppId());
@ -73,7 +85,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
packageParams.put("nonce_str", System.currentTimeMillis() + ""); packageParams.put("nonce_str", System.currentTimeMillis() + "");
checkParameters(packageParams); checkParameters(packageParams);
String sign = WxCryptUtil.createSign(packageParams, String sign = this.createSign(packageParams,
this.wxMpService.getWxMpConfigStorage().getPartnerKey()); this.wxMpService.getWxMpConfigStorage().getPartnerKey());
packageParams.put("sign", sign); packageParams.put("sign", sign);
@ -85,29 +97,11 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.append("</xml>"); request.append("</xml>");
HttpPost httpPost = new HttpPost( String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
"https://api.mch.weixin.qq.com/pay/unifiedorder"); String responseContent = this.wxMpService.post(url, request.toString());
if (this.httpProxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy)
.build();
httpPost.setConfig(config);
}
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = this.wxMpService.getHttpclient()
.execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE
.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance(); XStream xstream = XStreamInitializer.getInstance();
xstream.alias("xml", WxMpPrepayIdResult.class); xstream.alias("xml", WxMpPrepayIdResult.class);
return (WxMpPrepayIdResult) xstream.fromXML(responseContent); return (WxMpPrepayIdResult) xstream.fromXML(responseContent);
} catch (IOException e) {
throw new RuntimeException("Failed to get prepay id due to IO exception.",
e);
} finally {
httpPost.releaseConnection();
}
} }
private void checkParameters(Map<String, String> parameters) { private void checkParameters(Map<String, String> parameters) {
@ -132,6 +126,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }
@Override @Override
@Deprecated
public Map<String, String> getJsapiPayInfo(String openId, String outTradeNo, public Map<String, String> getJsapiPayInfo(String openId, String outTradeNo,
double amt, String body, String ip, String callbackUrl) double amt, String body, String ip, String callbackUrl)
throws WxErrorException { throws WxErrorException {
@ -152,6 +147,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }
@Override @Override
@Deprecated
public Map<String, String> getNativePayInfo(String productId, public Map<String, String> getNativePayInfo(String productId,
String outTradeNo, double amt, String body, String ip, String callbackUrl) String outTradeNo, double amt, String body, String ip, String callbackUrl)
throws WxErrorException { throws WxErrorException {
@ -207,7 +203,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
payInfo.put("codeUrl", wxMpPrepayIdResult.getCode_url()); payInfo.put("codeUrl", wxMpPrepayIdResult.getCode_url());
} }
String finalSign = WxCryptUtil.createSign(payInfo, String finalSign = this.createSign(payInfo,
this.wxMpService.getWxMpConfigStorage().getPartnerKey()); this.wxMpService.getWxMpConfigStorage().getPartnerKey());
payInfo.put("paySign", finalSign); payInfo.put("paySign", finalSign);
return payInfo; return payInfo;
@ -215,7 +211,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override @Override
public WxMpPayResult getJSSDKPayResult(String transactionId, public WxMpPayResult getJSSDKPayResult(String transactionId,
String outTradeNo) { String outTradeNo) throws WxErrorException {
String nonce_str = System.currentTimeMillis() + ""; String nonce_str = System.currentTimeMillis() + "";
SortedMap<String, String> packageParams = new TreeMap<>(); SortedMap<String, String> packageParams = new TreeMap<>();
@ -234,7 +230,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }
packageParams.put("nonce_str", nonce_str); packageParams.put("nonce_str", nonce_str);
packageParams.put("sign", WxCryptUtil.createSign(packageParams, packageParams.put("sign", this.createSign(packageParams,
this.wxMpService.getWxMpConfigStorage().getPartnerKey())); this.wxMpService.getWxMpConfigStorage().getPartnerKey()));
StringBuilder request = new StringBuilder("<xml>"); StringBuilder request = new StringBuilder("<xml>");
@ -244,27 +240,11 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }
request.append("</xml>"); request.append("</xml>");
HttpPost httpPost = new HttpPost( String url = "https://api.mch.weixin.qq.com/pay/orderquery";
"https://api.mch.weixin.qq.com/pay/orderquery"); String responseContent = this.wxMpService.post(url, request.toString());
if (this.httpProxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy)
.build();
httpPost.setConfig(config);
}
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = this.wxMpService.getHttpclient()
.execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE
.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance(); XStream xstream = XStreamInitializer.getInstance();
xstream.alias("xml", WxMpPayResult.class); xstream.alias("xml", WxMpPayResult.class);
return (WxMpPayResult) xstream.fromXML(responseContent); return (WxMpPayResult) xstream.fromXML(responseContent);
} catch (IOException e) {
throw new RuntimeException("Failed to query order due to IO exception.",
e);
}
} }
@Override @Override
@ -291,7 +271,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
refundParams.put("nonce_str", System.currentTimeMillis() + ""); refundParams.put("nonce_str", System.currentTimeMillis() + "");
refundParams.put("op_user_id", refundParams.put("op_user_id",
this.wxMpService.getWxMpConfigStorage().getPartnerId()); this.wxMpService.getWxMpConfigStorage().getPartnerId());
String sign = WxCryptUtil.createSign(refundParams, String sign = this.createSign(refundParams,
this.wxMpService.getWxMpConfigStorage().getPartnerKey()); this.wxMpService.getWxMpConfigStorage().getPartnerKey());
refundParams.put("sign", sign); refundParams.put("sign", sign);
@ -302,20 +282,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }
request.append("</xml>"); request.append("</xml>");
HttpPost httpPost = new HttpPost( String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
"https://api.mch.weixin.qq.com/secapi/pay/refund"); String responseContent = this.wxMpService.post(url, request.toString());
if (this.httpProxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy)
.build();
httpPost.setConfig(config);
}
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = this.wxMpService.getHttpclient()
.execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE
.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance(); XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpPayRefundResult.class); xstream.processAnnotations(WxMpPayRefundResult.class);
WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream
@ -327,34 +295,24 @@ public class WxMpPayServiceImpl implements WxMpPayService {
error.setErrorCode(-1); error.setErrorCode(-1);
error.setErrorMsg("return_code:" + wxMpPayRefundResult.getReturnCode() error.setErrorMsg("return_code:" + wxMpPayRefundResult.getReturnCode()
+ ";return_msg:" + wxMpPayRefundResult.getReturnMsg() + ";return_msg:" + wxMpPayRefundResult.getReturnMsg()
+ ";result_code:" + wxMpPayRefundResult.getResultCode() + ";result_code:" + wxMpPayRefundResult.getResultCode() + ";err_code"
+ ";err_code" + wxMpPayRefundResult.getErrCode() + ";err_code_des" + wxMpPayRefundResult.getErrCode() + ";err_code_des"
+ wxMpPayRefundResult.getErrCodeDes()); + wxMpPayRefundResult.getErrCodeDes());
throw new WxErrorException(error); throw new WxErrorException(error);
} }
return wxMpPayRefundResult; return wxMpPayRefundResult;
} catch (IOException e) {
String message = MessageFormatter
.format("Exception happened when sending refund '{}'.",
request.toString())
.getMessage();
this.log.error(message, e);
throw new WxErrorException(
WxError.newBuilder().setErrorMsg(message).build());
} finally {
httpPost.releaseConnection();
}
} }
@Override @Override
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm,
String signature) { String signature) {
return signature.equals(WxCryptUtil.createSign(kvm, return signature.equals(this.createSign(kvm,
this.wxMpService.getWxMpConfigStorage().getPartnerKey())); this.wxMpService.getWxMpConfigStorage().getPartnerKey()));
} }
@Override @Override
@Deprecated
public WxRedpackResult sendRedpack(Map<String, String> parameters) public WxRedpackResult sendRedpack(Map<String, String> parameters)
throws WxErrorException { throws WxErrorException {
SortedMap<String, String> packageParams = new TreeMap<>(parameters); SortedMap<String, String> packageParams = new TreeMap<>(parameters);
@ -364,7 +322,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
this.wxMpService.getWxMpConfigStorage().getPartnerId()); this.wxMpService.getWxMpConfigStorage().getPartnerId());
packageParams.put("nonce_str", System.currentTimeMillis() + ""); packageParams.put("nonce_str", System.currentTimeMillis() + "");
String sign = WxCryptUtil.createSign(packageParams, String sign = this.createSign(packageParams,
this.wxMpService.getWxMpConfigStorage().getPartnerKey()); this.wxMpService.getWxMpConfigStorage().getPartnerKey());
packageParams.put("sign", sign); packageParams.put("sign", sign);
@ -376,32 +334,160 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.append("</xml>"); request.append("</xml>");
HttpPost httpPost = new HttpPost( String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
"https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack");
if (this.httpProxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy)
.build();
httpPost.setConfig(config);
}
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8); String responseContent = this.wxMpService.post(url, request.toString());
httpPost.setEntity(entity);
try (CloseableHttpResponse response = this.wxMpService.getHttpclient()
.execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE
.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance(); XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxRedpackResult.class); xstream.processAnnotations(WxRedpackResult.class);
return (WxRedpackResult) xstream.fromXML(responseContent); return (WxRedpackResult) xstream.fromXML(responseContent);
} catch (IOException e) { }
String message = MessageFormatter
.format("Exception occured when sending redpack '{}'.", @Override
request.toString()) public WxRedpackResult sendRedpack(WxSendRedpackRequest request)
.getMessage(); throws WxErrorException {
this.log.error(message, e); XStream xstream = XStreamInitializer.getInstance();
throw new WxErrorException(WxError.newBuilder().setErrorMsg(message).build()); xstream.processAnnotations(WxSendRedpackRequest.class);
} finally { xstream.processAnnotations(WxRedpackResult.class);
httpPost.releaseConnection();
request.setWxAppid(this.wxMpService.getWxMpConfigStorage().getAppId());
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId());
request.setNonceStr(System.currentTimeMillis() + "");
String sign = this.createSign(xmlBean2Map(request),
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
request.setSign(sign);
String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
if (request.getAmtType() != null) {
//裂变红包
url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack";
}
String responseContent = this.wxMpService.post(url, xstream.toXML(request));
WxRedpackResult redpackResult = (WxRedpackResult) xstream
.fromXML(responseContent);
if ("FAIL".equals(redpackResult.getResultCode())) {
throw new WxErrorException(WxError.newBuilder()
.setErrorMsg(
redpackResult.getErrCode() + ":" + redpackResult.getErrCodeDes())
.build());
}
return redpackResult;
}
private Map<String, String> xmlBean2Map(Object bean) {
Map<String, String> result = Maps.newHashMap();
for (Entry<String, Reflect> entry : Reflect.on(bean).fields().entrySet()) {
Reflect reflect = entry.getValue();
if (reflect.get() == null) {
continue;
}
try {
Field field = bean.getClass().getDeclaredField(entry.getKey());
if (field.isAnnotationPresent(XStreamAlias.class)) {
result.put(field.getAnnotation(XStreamAlias.class).value(),
reflect.get().toString());
}
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
}
return result;
}
/**
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
* @param packageParams 原始参数
* @param signKey 加密Key( 商户Key)
* @return 签名字符串
*/
private String createSign(Map<String, String> packageParams, String signKey) {
SortedMap<String, String> sortedMap = new TreeMap<>(packageParams);
StringBuffer toSign = new StringBuffer();
for (String key : sortedMap.keySet()) {
String value = packageParams.get(key);
if (null != value && !"".equals(value) && !"sign".equals(key)
&& !"key".equals(key)) {
toSign.append(key + "=" + value + "&");
}
}
toSign.append("key=" + signKey);
return DigestUtils.md5Hex(toSign.toString()).toUpperCase();
}
@Override
public WxUnifiedOrderResult unifiedOrder(WxUnifiedOrderRequest request)
throws WxErrorException {
checkParameters(request);
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxUnifiedOrderRequest.class);
xstream.processAnnotations(WxUnifiedOrderResult.class);
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId());
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId());
request.setNonceStr(System.currentTimeMillis() + "");
String sign = this.createSign(xmlBean2Map(request),
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
request.setSign(sign);
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
String responseContent = this.wxMpService.post(url, xstream.toXML(request));
WxUnifiedOrderResult result = (WxUnifiedOrderResult) xstream
.fromXML(responseContent);
if ("FAIL".equals(result.getResultCode())) {
throw new WxErrorException(WxError.newBuilder()
.setErrorMsg(result.getErrCode() + ":" + result.getErrCodeDes())
.build());
}
return result;
}
private void checkParameters(WxUnifiedOrderRequest request) {
List<String> nullFields = Lists.newArrayList();
for (Entry<String, Reflect> entry : Reflect.on(request).fields()
.entrySet()) {
Reflect reflect = entry.getValue();
try {
Field field = request.getClass().getDeclaredField(entry.getKey());
if (field.isAnnotationPresent(Required.class)
&& reflect.get() == null) {
nullFields.add(entry.getKey());
}
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
}
if (!nullFields.isEmpty()) {
throw new IllegalArgumentException("必填字段[" + nullFields + "]必须提供值");
}
if (!TRADE_TYPES.contains(request.getTradeType())) {
throw new IllegalArgumentException(
"trade_type目前必须为" + TRADE_TYPES + "其中之一");
}
if ("JSAPI".equals(request.getTradeType()) && request.getOpenid() == null) {
throw new IllegalArgumentException("当 trade_type是'JSAPI'时未指定openid");
}
if ("NATIVE".equals(request.getTradeType())
&& request.getProductId() == null) {
throw new IllegalArgumentException("当 trade_type是'NATIVE'时未指定product_id");
} }
} }

View File

@ -23,6 +23,7 @@ public final class WxCardBuilder extends BaseBuilder<WxCardBuilder> {
return this; return this;
} }
@Override
public WxMpCustomMessage build() { public WxMpCustomMessage build() {
WxMpCustomMessage m = super.build(); WxMpCustomMessage m = super.build();
m.setCardId(this.cardId); m.setCardId(this.cardId);

View File

@ -1,4 +1,4 @@
package me.chanjar.weixin.mp.bean.result; package me.chanjar.weixin.mp.bean.pay;
import java.io.Serializable; import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package me.chanjar.weixin.mp.bean.result; package me.chanjar.weixin.mp.bean.pay;
import java.io.Serializable; import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package me.chanjar.weixin.mp.bean.result; package me.chanjar.weixin.mp.bean.pay;
import java.io.Serializable; import java.io.Serializable;

View File

@ -0,0 +1,124 @@
package me.chanjar.weixin.mp.bean.pay;
import java.io.Serializable;
/**
* <pre>
* 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识"返回的结果
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* </pre>
*
* @author chanjarster
*/
@Deprecated
public class WxMpPrepayIdResult implements Serializable {
private static final long serialVersionUID = -8970574397788396143L;
private String return_code;
private String return_msg;
private String appid;
private String mch_id;
private String nonce_str;
private String sign;
private String result_code;
private String prepay_id;
private String trade_type;
private String err_code;
private String err_code_des;
private String code_url;
public String getReturn_code() {
return this.return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return this.return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getAppid() {
return this.appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMch_id() {
return this.mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getNonce_str() {
return this.nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getSign() {
return this.sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getResult_code() {
return this.result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getPrepay_id() {
return this.prepay_id;
}
public void setPrepay_id(String prepay_id) {
this.prepay_id = prepay_id;
}
public String getTrade_type() {
return this.trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getErr_code() {
return this.err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return this.err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getCode_url() {
return this.code_url;
}
public void setCode_url(String code_url) {
this.code_url = code_url;
}
}

View File

@ -1,7 +1,10 @@
package me.chanjar.weixin.mp.bean.result; package me.chanjar.weixin.mp.bean.pay;
import java.io.Serializable; import java.io.Serializable;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
/** /**
@ -13,38 +16,35 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("xml") @XStreamAlias("xml")
public class WxRedpackResult implements Serializable { public class WxRedpackResult implements Serializable {
/**
*
*/
private static final long serialVersionUID = -4837415036337132073L; private static final long serialVersionUID = -4837415036337132073L;
@XStreamAlias("return_code") @XStreamAlias("return_code")
String returnCode; private String returnCode;
@XStreamAlias("return_msg") @XStreamAlias("return_msg")
String returnMsg; private String returnMsg;
@XStreamAlias("sign") @XStreamAlias("sign")
String sign; private String sign;
@XStreamAlias("result_code") @XStreamAlias("result_code")
String resultCode; private String resultCode;
@XStreamAlias("err_code") @XStreamAlias("err_code")
String errCode; private String errCode;
@XStreamAlias("err_code_des") @XStreamAlias("err_code_des")
String errCodeDes; private String errCodeDes;
@XStreamAlias("mch_billno") @XStreamAlias("mch_billno")
String mchBillno; private String mchBillno;
@XStreamAlias("mch_id") @XStreamAlias("mch_id")
String mchId; private String mchId;
@XStreamAlias("wxappid") @XStreamAlias("wxappid")
String wxappid; private String wxappid;
@XStreamAlias("re_openid") @XStreamAlias("re_openid")
String reOpenid; private String reOpenid;
@XStreamAlias("total_amount") @XStreamAlias("total_amount")
int totalAmount; private int totalAmount;
@XStreamAlias("send_time") @XStreamAlias("send_time")
String sendTime; private String sendTime;
@XStreamAlias("send_listid") @XStreamAlias("send_listid")
String sendListid; private String sendListid;
public String getErrCode() { public String getErrCode() {
return this.errCode; return this.errCode;
@ -100,19 +100,6 @@ public class WxRedpackResult implements Serializable {
@Override @Override
public String toString() { public String toString() {
return "WxRedpackResult{" + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
"returnCode=" + this.returnCode +
", returnMsg=" + this.returnMsg +
", sign=" + this.sign +
", errCode=" + this.errCode +
", errCodeDes=" + this.errCodeDes +
", mchBillno=" + this.mchBillno +
", mchId=" + this.mchId +
", wxappid=" + this.wxappid +
", reOpenid=" + this.reOpenid +
", totalAmount=" + this.totalAmount +
", sendTime=" + this.sendTime +
", sendListid=" + this.sendListid +
'}';
} }
} }

View File

@ -0,0 +1,296 @@
package me.chanjar.weixin.mp.bean.pay;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 发送红包请求参数对象
* Created by Binary Wang on 2016/9/24.
* @author binarywang (https://github.com/binarywang)
*/
@XStreamAlias("xml")
public class WxSendRedpackRequest {
/**
* mch_billno
* 商户订单号每个订单号必须唯一 组成mch_id+yyyymmdd+10位一天内不能重复的数字 接口根据商户订单号支持重入如出现超时可再调用
*/
@XStreamAlias("mch_billno")
private String mchBillno;
/**
* send_name
* 商户名称
* 红包发送者名称
*/
@XStreamAlias("send_name")
private String sendName;
/**
* re_openid
* 接受红包的用户 用户在wxappid下的openid
*/
@XStreamAlias("re_openid")
private String reOpenid;
/**
* total_amount
* 红包总额
*/
@XStreamAlias("total_amount")
private Integer totalAmount;
/**
* total_num
* 红包发放总人数
*/
@XStreamAlias("total_num")
private Integer totalNum;
/**
* amt_type
* 红包金额设置方式
* ALL_RAND全部随机,商户指定总金额和红包发放总人数由微信支付随机计算出各红包金额
* 裂变红包必填
*/
@XStreamAlias("amt_type")
private String amtType;
/**
* wishing
* 红包祝福语
*/
@XStreamAlias("wishing")
private String wishing;
/**
* client_ip
* 服务器Ip地址
* 调用接口的机器Ip地址
*/
@XStreamAlias("client_ip")
private String clientIp;
/**
* act_name
* 活动名称
*/
@XStreamAlias("act_name")
private String actName;
/**
* remark
* 备注
*/
@XStreamAlias("remark")
private String remark;
/**
* wxappid
* 微信分配的公众账号ID企业号corpid即为此appId接口传入的所有appid应该为公众号的appid在mp.weixin.qq.com申请的不能为APP的appid在open.weixin.qq.com申请的
*/
@XStreamAlias("wxappid")
private String wxAppid;
/**
* mch_id
* 微信支付分配的商户号
*/
@XStreamAlias("mch_id")
private String mchId;
/**
* nonce_str
* 随机字符串不长于32位
*/
@XStreamAlias("nonce_str")
private String nonceStr;
/**
* sign
* 详见<a href="https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3">签名生成算法</a>
*/
@XStreamAlias("sign")
private String sign;
/**
* <pre>
* scene_id
* 场景id
* PRODUCT_1:商品促销
* PRODUCT_2:抽奖
* PRODUCT_3:虚拟物品兑奖
* PRODUCT_4:企业内部福利
* PRODUCT_5:渠道分润
* PRODUCT_6:保险回馈
* PRODUCT_7:彩票派奖
* PRODUCT_8:税务刮奖
* 非必填字段
* </pre>
*/
@XStreamAlias("scene_id")
private String sceneId;
/**
* <pre>
* risk_info
* 活动信息
* posttime:用户操作的时间戳
* mobile:业务系统账号的手机号国家代码-手机号不需要+
* deviceid :mac 地址或者设备唯一标识
* clientversion :用户操作的客户端版本
* 把值为非空的信息用key=value进行拼接再进行urlencode
* urlencode(posttime=xx&mobile=xx&deviceid=xx)
* 非必填字段
* </pre>
*/
@XStreamAlias("risk_info")
private String riskInfo;
/**
* <pre>
* consume_mch_id
* 资金授权商户号
* 资金授权商户号
* 服务商替特约商户发放时使用
* 非必填字段
* </pre>
*/
@XStreamAlias("consume_mch_id")
private String consumeMchId;
public String getMchBillno() {
return this.mchBillno;
}
public void setMchBillno(String mchBillno) {
this.mchBillno = mchBillno;
}
public String getSendName() {
return this.sendName;
}
public void setSendName(String sendName) {
this.sendName = sendName;
}
public String getReOpenid() {
return this.reOpenid;
}
public void setReOpenid(String reOpenid) {
this.reOpenid = reOpenid;
}
public Integer getTotalAmount() {
return this.totalAmount;
}
public void setTotalAmount(Integer totalAmount) {
this.totalAmount = totalAmount;
}
public Integer getTotalNum() {
return this.totalNum;
}
public void setTotalNum(Integer totalNum) {
this.totalNum = totalNum;
}
public String getAmtType() {
return this.amtType;
}
public void setAmtType(String amtType) {
this.amtType = amtType;
}
public String getWishing() {
return this.wishing;
}
public void setWishing(String wishing) {
this.wishing = wishing;
}
public String getClientIp() {
return this.clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public String getActName() {
return this.actName;
}
public void setActName(String actName) {
this.actName = actName;
}
public String getRemark() {
return this.remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getWxAppid() {
return this.wxAppid;
}
public void setWxAppid(String wxAppid) {
this.wxAppid = wxAppid;
}
public String getMchId() {
return this.mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getNonceStr() {
return this.nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return this.sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getSceneId() {
return this.sceneId;
}
public void setSceneId(String sceneId) {
this.sceneId = sceneId;
}
public String getRiskInfo() {
return this.riskInfo;
}
public void setRiskInfo(String riskInfo) {
this.riskInfo = riskInfo;
}
public String getConsumeMchId() {
return this.consumeMchId;
}
public void setConsumeMchId(String consumeMchId) {
this.consumeMchId = consumeMchId;
}
}

View File

@ -0,0 +1,666 @@
package me.chanjar.weixin.mp.bean.pay;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;
/**
* <pre>
* 统一下单请求参数对象
* 参考文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
* 每个字段描述对应如下
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
* Created by Binary Wang on 2016/9/25.
* @author binarywang (https://github.com/binarywang)
*/
@XStreamAlias("xml")
public class WxUnifiedOrderRequest {
/**
* <pre>
* 公众账号ID
* appid
*
* String(32)
* wxd678efh567hg6787
* 微信分配的公众账号ID企业号corpid即为此appId
* </pre>
*/
@XStreamAlias("appid")
private String appid;
/**
* <pre>
* 商户号
* mch_id
*
* String(32)
* 1230000109
* 微信支付分配的商户号
* </pre>
*/
@XStreamAlias("mch_id")
private String mchId;
/**
* <pre>
* 设备号
* device_info
*
* String(32)
* 013467007045764
* 终端设备号(门店号或收银设备Id)注意PC网页或公众号内支付请传"WEB"
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 随机字符串
* nonce_str
*
* String(32)
* 5K8264ILTKCH16CQ2502SI8ZNMTM67VS
* 随机字符串不长于32位推荐随机数生成算法
* </pre>
*/
@XStreamAlias("nonce_str")
private String nonceStr;
/**
* <pre>
* 签名
* sign
*
* String(32)
* C380BEC2BFD727A4B6845133519F3AD6
* 签名详见签名生成算法
* </pre>
*/
@XStreamAlias("sign")
private String sign;
/**
* <pre>
* 商品描述
* body
*
* String(128)
* 腾讯充值中心-QQ会员充值
* 商品简单描述该字段须严格按照规范传递具体请见参数规定
* </pre>
*/
@Required
@XStreamAlias("body")
private String body;
/**
* <pre>
* 商品详情
* detail
*
* String(6000)
* { "goods_detail":[
{
"goods_id":"iphone6s_16G",
"wxpay_goods_id":"1001",
"goods_name":"iPhone6s 16G",
"goods_num":1,
"price":528800,
"goods_category":"123456",
"body":"苹果手机"
},
{
"goods_id":"iphone6s_32G",
"wxpay_goods_id":"1002",
"goods_name":"iPhone6s 32G",
"quantity":1,
"price":608800,
"goods_category":"123789",
"body":"苹果手机"
}
]
}
商品详细列表使用Json格式传输签名前请务必使用CDATA标签将JSON文本串保护起来
goods_detail []
goods_id String 必填 32 商品的编号
wxpay_goods_id String 可选 32 微信支付定义的统一商品编号
goods_name String 必填 256 商品名称
goods_num Int 必填 商品数量
price Int 必填 商品单价单位为分
goods_category String 可选 32 商品类目Id
body String 可选 1000 商品描述信息
* </pre>
*/
@XStreamAlias("detail")
private String detail;
/**
* <pre>
* 附加数据
* attach
*
* String(127)
* 深圳分店
* 附加数据在查询API和支付通知中原样返回该字段主要用于商户携带订单的自定义数据
* </pre>
*/
@XStreamAlias("attach")
private String attach;
/**
* <pre>
* 商户订单号
* out_trade_no
*
* String(32)
* 20150806125346
* 商户系统内部的订单号,32个字符内可包含字母, 其他说明见商户订单号
* </pre>
*/
@Required
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 货币类型
* fee_type
*
* String(16)
* CNY
* 符合ISO 4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("fee_type")
private String feeType;
/**
* <pre>
* 总金额
* total_fee
*
* Int
* 888
* 订单总金额单位为分详见支付金额
* </pre>
*/
@Required
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>
* 终端IP
* spbill_create_ip
*
* String(16)
* 123.12.12.123
* APP和网页支付提交用户端ipNative支付填调用微信支付API的机器IP
* </pre>
*/
@Required
@XStreamAlias("spbill_create_ip")
private String spbillCreateIp;
/**
* <pre>
* 交易起始时间
* time_start
*
* String(14)
* 20091225091010
* 订单生成时间格式为yyyyMMddHHmmss如2009年12月25日9点10分10秒表示为20091225091010其他详见时间规则
* </pre>
*/
@XStreamAlias("time_start")
private String timeStart;
/**
* <pre>
* 交易结束时间
* time_expire
*
* String(14)
* 20091227091010
* 订单失效时间格式为yyyyMMddHHmmss如2009年12月27日9点10分10秒表示为20091227091010其他详见时间规则
* 注意最短失效时间间隔必须大于5分钟
* </pre>
*/
@XStreamAlias("time_expire")
private String timeExpire;
/**
* <pre>
* 商品标记
* goods_tag
*
* String(32)
* WXG
* 商品标记代金券或立减优惠功能的参数说明详见代金券或立减优惠
* </pre>
*/
@XStreamAlias("goods_tag")
private String goodsTag;
/**
* <pre>
* 通知地址
* notify_url
*
* String(256)
* http://www.weixin.qq.com/wxpay/pay.php
* 接收微信支付异步通知回调地址通知url必须为直接可访问的url不能携带参数
* </pre>
*/
@Required
@XStreamAlias("notify_url")
private String notifyURL;
/**
* <pre>
* 交易类型
* trade_type
*
* String(16)
* JSAPI
* 取值如下JSAPINATIVEAPP详细说明见参数规定:
* JSAPI--公众号支付NATIVE--原生扫码支付APP--app支付统一下单接口trade_type的传参可参考这里
* </pre>
*/
@Required
@XStreamAlias("trade_type")
private String tradeType;
/**
* <pre>
* 商品Id
* product_id
*
* String(32)
* 12235413214070356458058
* trade_type=NATIVE此参数必传此id为二维码中包含的商品Id商户自行定义
* </pre>
*/
@XStreamAlias("product_id")
private String productId;
/**
* <pre>
* 指定支付方式
* limit_pay
*
* String(32)
* no_credit no_credit--指定不能使用信用卡支付
* </pre>
*/
@XStreamAlias("limit_pay")
private String limitPay;
/**
* <pre>
* 用户标识
* openid
*
* String(128)
* oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
* trade_type=JSAPI此参数必传用户在商户appid下的唯一标识
* openid如何获取可参考获取openid
* 企业号请使用企业号OAuth2.0接口获取企业号内成员userid再调用企业号userid转openid接口进行转换
* </pre>
*/
@XStreamAlias("openid")
private String openid;
public String getAppid() {
return this.appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMchId() {
return this.mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getDeviceInfo() {
return this.deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getNonceStr() {
return this.nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return this.sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getBody() {
return this.body;
}
public void setBody(String body) {
this.body = body;
}
public String getDetail() {
return this.detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getAttach() {
return this.attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getOutTradeNo() {
return this.outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getFeeType() {
return this.feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getTotalFee() {
return this.totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public String getSpbillCreateIp() {
return this.spbillCreateIp;
}
public void setSpbillCreateIp(String spbillCreateIp) {
this.spbillCreateIp = spbillCreateIp;
}
public String getTimeStart() {
return this.timeStart;
}
public void setTimeStart(String timeStart) {
this.timeStart = timeStart;
}
public String getTimeExpire() {
return this.timeExpire;
}
public void setTimeExpire(String timeExpire) {
this.timeExpire = timeExpire;
}
public String getGoodsTag() {
return this.goodsTag;
}
public void setGoodsTag(String goodsTag) {
this.goodsTag = goodsTag;
}
public String getNotifyURL() {
return this.notifyURL;
}
public void setNotifyURL(String notifyURL) {
this.notifyURL = notifyURL;
}
public String getTradeType() {
return this.tradeType;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getProductId() {
return this.productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getLimitPay() {
return this.limitPay;
}
public void setLimitPay(String limitPay) {
this.limitPay = limitPay;
}
public String getOpenid() {
return this.openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
public static WxUnifiedOrderRequestBuilder builder() {
return new WxUnifiedOrderRequestBuilder();
}
public static class WxUnifiedOrderRequestBuilder {
private String appid;
private String mchId;
private String deviceInfo;
private String nonceStr;
private String sign;
private String body;
private String detail;
private String attach;
private String outTradeNo;
private String feeType;
private Integer totalFee;
private String spbillCreateIp;
private String timeStart;
private String timeExpire;
private String goodsTag;
private String notifyURL;
private String tradeType;
private String productId;
private String limitPay;
private String openid;
public WxUnifiedOrderRequestBuilder appid(String appid) {
this.appid = appid;
return this;
}
public WxUnifiedOrderRequestBuilder mchId(String mchId) {
this.mchId = mchId;
return this;
}
public WxUnifiedOrderRequestBuilder deviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
return this;
}
public WxUnifiedOrderRequestBuilder nonceStr(String nonceStr) {
this.nonceStr = nonceStr;
return this;
}
public WxUnifiedOrderRequestBuilder sign(String sign) {
this.sign = sign;
return this;
}
public WxUnifiedOrderRequestBuilder body(String body) {
this.body = body;
return this;
}
public WxUnifiedOrderRequestBuilder detail(String detail) {
this.detail = detail;
return this;
}
public WxUnifiedOrderRequestBuilder attach(String attach) {
this.attach = attach;
return this;
}
public WxUnifiedOrderRequestBuilder outTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
return this;
}
public WxUnifiedOrderRequestBuilder feeType(String feeType) {
this.feeType = feeType;
return this;
}
public WxUnifiedOrderRequestBuilder totalFee(Integer totalFee) {
this.totalFee = totalFee;
return this;
}
public WxUnifiedOrderRequestBuilder spbillCreateIp(String spbillCreateIp) {
this.spbillCreateIp = spbillCreateIp;
return this;
}
public WxUnifiedOrderRequestBuilder timeStart(String timeStart) {
this.timeStart = timeStart;
return this;
}
public WxUnifiedOrderRequestBuilder timeExpire(String timeExpire) {
this.timeExpire = timeExpire;
return this;
}
public WxUnifiedOrderRequestBuilder goodsTag(String goodsTag) {
this.goodsTag = goodsTag;
return this;
}
public WxUnifiedOrderRequestBuilder notifyURL(String notifyURL) {
this.notifyURL = notifyURL;
return this;
}
public WxUnifiedOrderRequestBuilder tradeType(String tradeType) {
this.tradeType = tradeType;
return this;
}
public WxUnifiedOrderRequestBuilder productId(String productId) {
this.productId = productId;
return this;
}
public WxUnifiedOrderRequestBuilder limitPay(String limitPay) {
this.limitPay = limitPay;
return this;
}
public WxUnifiedOrderRequestBuilder openid(String openid) {
this.openid = openid;
return this;
}
public WxUnifiedOrderRequestBuilder from(WxUnifiedOrderRequest origin) {
this.appid(origin.appid);
this.mchId(origin.mchId);
this.deviceInfo(origin.deviceInfo);
this.nonceStr(origin.nonceStr);
this.sign(origin.sign);
this.body(origin.body);
this.detail(origin.detail);
this.attach(origin.attach);
this.outTradeNo(origin.outTradeNo);
this.feeType(origin.feeType);
this.totalFee(origin.totalFee);
this.spbillCreateIp(origin.spbillCreateIp);
this.timeStart(origin.timeStart);
this.timeExpire(origin.timeExpire);
this.goodsTag(origin.goodsTag);
this.notifyURL(origin.notifyURL);
this.tradeType(origin.tradeType);
this.productId(origin.productId);
this.limitPay(origin.limitPay);
this.openid(origin.openid);
return this;
}
public WxUnifiedOrderRequest build() {
WxUnifiedOrderRequest m = new WxUnifiedOrderRequest();
m.appid = this.appid;
m.mchId = this.mchId;
m.deviceInfo = this.deviceInfo;
m.nonceStr = this.nonceStr;
m.sign = this.sign;
m.body = this.body;
m.detail = this.detail;
m.attach = this.attach;
m.outTradeNo = this.outTradeNo;
m.feeType = this.feeType;
m.totalFee = this.totalFee;
m.spbillCreateIp = this.spbillCreateIp;
m.timeStart = this.timeStart;
m.timeExpire = this.timeExpire;
m.goodsTag = this.goodsTag;
m.notifyURL = this.notifyURL;
m.tradeType = this.tradeType;
m.productId = this.productId;
m.limitPay = this.limitPay;
m.openid = this.openid;
return m;
}
}
}

View File

@ -0,0 +1,155 @@
package me.chanjar.weixin.mp.bean.pay;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识"返回的结果
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* </pre>
*
* @author chanjarster
*/
@XStreamAlias("xml")
public class WxUnifiedOrderResult {
@XStreamAlias("return_code")
private String returnCode;
@XStreamAlias("return_msg")
private String returnMsg;
@XStreamAlias("appid")
private String appid;
@XStreamAlias("mch_id")
private String mchId;
@XStreamAlias("nonce_str")
private String nonceStr;
@XStreamAlias("sign")
private String sign;
@XStreamAlias("result_code")
private String resultCode;
@XStreamAlias("prepay_id")
private String prepayId;
@XStreamAlias("trade_type")
private String tradeType;
@XStreamAlias("err_code")
private String errCode;
@XStreamAlias("err_code_des")
private String errCodeDes;
@XStreamAlias("code_url")
private String codeURL;
public String getReturnCode() {
return this.returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return this.returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
public String getAppid() {
return this.appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMchId() {
return this.mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getNonceStr() {
return this.nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return this.sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getResultCode() {
return this.resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public String getPrepayId() {
return this.prepayId;
}
public void setPrepayId(String prepayId) {
this.prepayId = prepayId;
}
public String getTradeType() {
return this.tradeType;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getErrCode() {
return this.errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrCodeDes() {
return this.errCodeDes;
}
public void setErrCodeDes(String errCodeDes) {
this.errCodeDes = errCodeDes;
}
public String getCodeURL() {
return this.codeURL;
}
public void setCodeURL(String codeURL) {
this.codeURL = codeURL;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}

View File

@ -1,128 +0,0 @@
package me.chanjar.weixin.mp.bean.result;
import java.io.Serializable;
/**
* <pre>
* 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识"返回的结果
*
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
*
* </pre>
*
* @author chanjarster
*/
public class WxMpPrepayIdResult implements Serializable {
/**
*
*/
private static final long serialVersionUID = -8970574397788396143L;
private String return_code;
private String return_msg;
private String appid;
private String mch_id;
private String nonce_str;
private String sign;
private String result_code;
private String prepay_id;
private String trade_type;
private String err_code;
private String err_code_des;
private String code_url;
public String getReturn_code() {
return this.return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return this.return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getAppid() {
return this.appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMch_id() {
return this.mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getNonce_str() {
return this.nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getSign() {
return this.sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getResult_code() {
return this.result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getPrepay_id() {
return this.prepay_id;
}
public void setPrepay_id(String prepay_id) {
this.prepay_id = prepay_id;
}
public String getTrade_type() {
return this.trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getErr_code() {
return this.err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return this.err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getCode_url() {
return this.code_url;
}
public void setCode_url(String code_url) {
this.code_url = code_url;
}
}

View File

@ -1,22 +1,34 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;
import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.bean.pay.WxRedpackResult;
import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest;
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderRequest;
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderResult;
/** /**
* 测试支付相关接口
* Created by Binary Wang on 2016/7/28. * Created by Binary Wang on 2016/7/28.
* @author binarywang (https://github.com/binarywang) * @author binarywang (https://github.com/binarywang)
*/ */
@Test
@Guice(modules = ApiTestModule.class)
public class WxMpPayServiceImplTest { public class WxMpPayServiceImplTest {
@Inject
protected WxMpServiceImpl wxService;
@Test @Test
public void testGetPrepayId() throws Exception { public void testGetPrepayId() throws Exception {
} }
@Test
public void testGetPrepayId1() throws Exception {
}
@Test @Test
public void testGetJsapiPayInfo() throws Exception { public void testGetJsapiPayInfo() throws Exception {
@ -54,7 +66,26 @@ public class WxMpPayServiceImplTest {
@Test @Test
public void testSendRedpack() throws Exception { public void testSendRedpack() throws Exception {
WxSendRedpackRequest request = new WxSendRedpackRequest();
request.setActName("abc");
request.setClientIp("aaa");
request.setMchBillno("aaaa");
request
.setReOpenid(((ApiTestModule.WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid());
WxRedpackResult redpackResult = this.wxService.getPayService().sendRedpack(request);
System.err.println(redpackResult);
} }
/**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#unifiedOrder(me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderRequest)}.
* @throws WxErrorException
*/
@Test
public void testUnifiedOrder() throws WxErrorException {
WxUnifiedOrderResult result = this.wxService.getPayService()
.unifiedOrder(WxUnifiedOrderRequest.builder().body("1111111")
.totalFee(1).spbillCreateIp("111111").notifyURL("111111")
.tradeType("JSAPI1").openid("122").outTradeNo("111111").build());
System.err.println(result);
}
} }

View File

@ -8,7 +8,7 @@ import org.junit.Test;
import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.bean.result.WxRedpackResult; import me.chanjar.weixin.mp.bean.pay.WxRedpackResult;
public class WxRedpackResultTest { public class WxRedpackResultTest {

View File

@ -0,0 +1,33 @@
package me.chanjar.weixin.mp.bean.pay;
import java.lang.reflect.Field;
import java.util.Map.Entry;
import org.joor.Reflect;
import org.testng.annotations.Test;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@Test
public class WxSendRedpackRequestTest {
public void test() throws NoSuchFieldException, SecurityException {
WxSendRedpackRequest request = new WxSendRedpackRequest();
request.setMchBillno("123");
request.setActName("ab");
for (Entry<String, Reflect> entry : Reflect.on(request).fields().entrySet()) {
Reflect reflect = entry.getValue();
if (reflect.get() == null) {
continue;
}
Field field = WxSendRedpackRequest.class.getDeclaredField(entry.getKey());
if (field.isAnnotationPresent(XStreamAlias.class)) {
System.err.println(reflect.get() + " = " + field.getAnnotation(XStreamAlias.class).value());
}
}
}
}