mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-07-16 07:59:43 +08:00
commit
edf558adde
@ -1,4 +1,4 @@
|
||||
Weixin Java Tools —— 微信公众号&企业号开发 Java SDK
|
||||
WeixinJavaTools 微信支付、公众号&企业号开发Java SDK
|
||||
=====================================
|
||||
[](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent)
|
||||
[](https://travis-ci.org/Wechat-Group/weixin-java-tools)
|
||||
@ -48,7 +48,7 @@ Weixin Java Tools —— 微信公众号&企业号开发 Java SDK
|
||||
|
||||
## Maven & Gradle 最新正式版本
|
||||
|
||||
* 公众号(订阅号、服务号):
|
||||
* 公众号(订阅号、服务号及微信支付):
|
||||
|
||||
maven:
|
||||
```xml
|
||||
|
5
pom.xml
5
pom.xml
@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>2.6.0-SNAPSHOT</version>
|
||||
<version>2.5.2.BETA</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>WeiXin Java Tools - Parent</name>
|
||||
<description>微信公众号、企业号上级POM</description>
|
||||
@ -86,7 +86,8 @@
|
||||
<module>weixin-java-common</module>
|
||||
<module>weixin-java-cp</module>
|
||||
<module>weixin-java-mp</module>
|
||||
<module>weixin-java-osgi</module>
|
||||
<module>weixin-java-pay</module>
|
||||
<!--module>weixin-java-osgi</module-->
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>2.6.0-SNAPSHOT</version>
|
||||
<version>2.5.2.BETA</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-common</artifactId>
|
||||
|
@ -101,6 +101,7 @@ public class WxConsts {
|
||||
public static final String EVT_KF_CLOSE_SESSION = "kf_close_session"; // 客服关闭会话
|
||||
public static final String EVT_KF_SWITCH_SESSION = "kf_switch_session"; // 客服转接会话
|
||||
public static final String EVT_POI_CHECK_NOTIFY = "poi_check_notify"; //门店审核事件推送
|
||||
public static final String EVN_SUBMIT_MEMBERCARD_USER_INFO = "submit_membercard_user_info"; //接收会员信息事件推送
|
||||
//以下为微信认证事件
|
||||
/**
|
||||
* 资质认证成功
|
||||
@ -135,13 +136,6 @@ public class WxConsts {
|
||||
public static final String MEDIA_VIDEO = "video";
|
||||
public static final String MEDIA_THUMB = "thumb";
|
||||
public static final String MEDIA_FILE = "file";
|
||||
///////////////////////
|
||||
// 文件类型
|
||||
///////////////////////
|
||||
public static final String FILE_JPG = "jpeg";
|
||||
public static final String FILE_MP3 = "mp3";
|
||||
public static final String FILE_AMR = "amr";
|
||||
public static final String FILE_MP4 = "mp4";
|
||||
/**
|
||||
* 点击推事件
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>2.6.0-SNAPSHOT</version>
|
||||
<version>2.5.2.BETA</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-cp</artifactId>
|
||||
|
@ -0,0 +1,17 @@
|
||||
package me.chanjar.weixin.cp.api;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 仅供测试使用的一些常量
|
||||
* Created by Binary Wang on 2017-3-9.
|
||||
* </pre>
|
||||
*/
|
||||
public class TestConstants {
|
||||
///////////////////////
|
||||
// 文件类型
|
||||
///////////////////////
|
||||
public static final String FILE_JPG = "jpeg";
|
||||
public static final String FILE_MP3 = "mp3";
|
||||
public static final String FILE_AMR = "amr";
|
||||
public static final String FILE_MP4 = "mp4";
|
||||
}
|
@ -54,10 +54,10 @@ public class WxCpMediaAPITest {
|
||||
@DataProvider
|
||||
public Object[][] uploadMedia() {
|
||||
return new Object[][]{
|
||||
new Object[]{WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg"},
|
||||
new Object[]{WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3"},
|
||||
new Object[]{WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4"},
|
||||
new Object[]{WxConsts.MEDIA_FILE, WxConsts.FILE_JPG, "mm.jpeg"}
|
||||
new Object[]{WxConsts.MEDIA_IMAGE, TestConstants.FILE_JPG, "mm.jpeg"},
|
||||
new Object[]{WxConsts.MEDIA_VOICE, TestConstants.FILE_MP3, "mm.mp3"},
|
||||
new Object[]{WxConsts.MEDIA_VIDEO, TestConstants.FILE_MP4, "mm.mp4"},
|
||||
new Object[]{WxConsts.MEDIA_FILE, TestConstants.FILE_JPG, "mm.jpeg"}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>2.6.0-SNAPSHOT</version>
|
||||
<version>2.5.2.BETA</version>
|
||||
</parent>
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
<name>WeiXin Java Tools - MP</name>
|
||||
@ -18,21 +18,11 @@
|
||||
<artifactId>weixin-java-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
@ -54,16 +44,6 @@
|
||||
<version>2.9.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>xml-path</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>qrcode-utils</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -3,7 +3,6 @@ package me.chanjar.weixin.mp.api;
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.File;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
@ -82,27 +81,6 @@ public interface WxMpConfigStorage {
|
||||
|
||||
String getSecret();
|
||||
|
||||
String getPartnerId();
|
||||
|
||||
String getPartnerKey();
|
||||
|
||||
/**
|
||||
* 微信支付异步回掉地址,通知url必须为直接可访问的url,不能携带参数。
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
String getNotifyURL();
|
||||
|
||||
/**
|
||||
* 交易类型
|
||||
* <pre>
|
||||
* JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
|
||||
* </pre>
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
String getTradeType();
|
||||
|
||||
String getToken();
|
||||
|
||||
String getAesKey();
|
||||
@ -121,17 +99,6 @@ public interface WxMpConfigStorage {
|
||||
|
||||
File getTmpDirFile();
|
||||
|
||||
SSLContext getSslContext();
|
||||
|
||||
void setSslContext(SSLContext sslContext);
|
||||
|
||||
/**
|
||||
* 在此之前,必须将partnerId进行赋值
|
||||
*
|
||||
* @param filePath apiclient_cert.p12的文件的绝对路径
|
||||
*/
|
||||
void setSslContextFilePath(String filePath) throws Exception;
|
||||
|
||||
/**
|
||||
* http client builder
|
||||
*
|
||||
@ -144,8 +111,4 @@ public interface WxMpConfigStorage {
|
||||
*/
|
||||
boolean autoRefreshToken();
|
||||
|
||||
/**
|
||||
* 微信支付是否使用仿真测试环境
|
||||
*/
|
||||
boolean useSandboxForWxPay();
|
||||
}
|
||||
|
@ -3,12 +3,8 @@ package me.chanjar.weixin.mp.api;
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.util.ToStringUtils;
|
||||
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder;
|
||||
import org.apache.http.ssl.SSLContexts;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ -21,10 +17,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
|
||||
protected volatile String appId;
|
||||
protected volatile String secret;
|
||||
protected volatile String partnerId;
|
||||
protected volatile String partnerKey;
|
||||
protected volatile String notifyURL;
|
||||
protected volatile String tradeType;
|
||||
protected volatile String token;
|
||||
protected volatile String accessToken;
|
||||
protected volatile String aesKey;
|
||||
@ -52,8 +44,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
*/
|
||||
protected volatile File tmpDirFile;
|
||||
|
||||
protected volatile SSLContext sslContext;
|
||||
|
||||
protected volatile ApacheHttpClientBuilder apacheHttpClientBuilder;
|
||||
|
||||
@Override
|
||||
@ -61,10 +51,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getAccessTokenLock() {
|
||||
return this.accessTokenLock;
|
||||
@ -96,23 +82,11 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
return this.jsapiTicket;
|
||||
}
|
||||
|
||||
public void setJsapiTicket(String jsapiTicket) {
|
||||
this.jsapiTicket = jsapiTicket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getJsapiTicketLock() {
|
||||
return this.jsapiTicketLock;
|
||||
}
|
||||
|
||||
public long getJsapiTicketExpiresTime() {
|
||||
return this.jsapiTicketExpiresTime;
|
||||
}
|
||||
|
||||
public void setJsapiTicketExpiresTime(long jsapiTicketExpiresTime) {
|
||||
this.jsapiTicketExpiresTime = jsapiTicketExpiresTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJsapiTicketExpired() {
|
||||
return System.currentTimeMillis() > this.jsapiTicketExpiresTime;
|
||||
@ -255,41 +229,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
return ToStringUtils.toSimpleString(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPartnerId() {
|
||||
return this.partnerId;
|
||||
}
|
||||
|
||||
public void setPartnerId(String partnerId) {
|
||||
this.partnerId = partnerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPartnerKey() {
|
||||
return this.partnerKey;
|
||||
}
|
||||
|
||||
public void setPartnerKey(String partnerKey) {
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
|
||||
public String getNotifyURL() {
|
||||
return notifyURL;
|
||||
}
|
||||
|
||||
public void setNotifyURL(String notifyURL) {
|
||||
this.notifyURL = notifyURL;
|
||||
}
|
||||
|
||||
public String getTradeType() {
|
||||
return tradeType;
|
||||
}
|
||||
|
||||
public void setTradeType(String tradeType) {
|
||||
this.tradeType = tradeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getTmpDirFile() {
|
||||
return this.tmpDirFile;
|
||||
@ -299,38 +238,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
this.tmpDirFile = tmpDirFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLContext getSslContext() {
|
||||
return this.sslContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSslContext(SSLContext context) {
|
||||
this.sslContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSslContextFilePath(String filePath) {
|
||||
if (null == partnerId) {
|
||||
throw new IllegalArgumentException("请设置partnerId的值");
|
||||
}
|
||||
|
||||
File file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("证书文件:【" + file.getPath() + "】不存在!");
|
||||
}
|
||||
|
||||
try {
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
KeyStore keystore = KeyStore.getInstance("PKCS12");
|
||||
char[] partnerId2charArray = partnerId.toCharArray();
|
||||
keystore.load(inputStream, partnerId2charArray);
|
||||
this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("证书文件有问题,请核实!", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApacheHttpClientBuilder getApacheHttpClientBuilder() {
|
||||
return this.apacheHttpClientBuilder;
|
||||
@ -340,13 +247,37 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
this.apacheHttpClientBuilder = apacheHttpClientBuilder;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public void setJsapiTicket(String jsapiTicket) {
|
||||
this.jsapiTicket = jsapiTicket;
|
||||
}
|
||||
|
||||
public long getJsapiTicketExpiresTime() {
|
||||
return this.jsapiTicketExpiresTime;
|
||||
}
|
||||
|
||||
public void setJsapiTicketExpiresTime(long jsapiTicketExpiresTime) {
|
||||
this.jsapiTicketExpiresTime = jsapiTicketExpiresTime;
|
||||
}
|
||||
|
||||
public void setCardApiTicket(String cardApiTicket) {
|
||||
this.cardApiTicket = cardApiTicket;
|
||||
}
|
||||
|
||||
public long getCardApiTicketExpiresTime() {
|
||||
return this.cardApiTicketExpiresTime;
|
||||
}
|
||||
|
||||
public void setCardApiTicketExpiresTime(long cardApiTicketExpiresTime) {
|
||||
this.cardApiTicketExpiresTime = cardApiTicketExpiresTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean autoRefreshToken() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useSandboxForWxPay() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -311,13 +311,6 @@ public interface WxMpService {
|
||||
*/
|
||||
WxMpCardService getCardService();
|
||||
|
||||
/**
|
||||
* 返回微信支付相关接口方法的实现类对象,以方便调用其各个接口
|
||||
*
|
||||
* @return WxMpPayService
|
||||
*/
|
||||
WxMpPayService getPayService();
|
||||
|
||||
/**
|
||||
* 返回数据分析统计相关接口方法的实现类对象,以方便调用其各个接口
|
||||
*
|
||||
|
@ -28,9 +28,6 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
//import org.apache.http.conn.ssl.DefaultHostnameVerifier;
|
||||
//import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
|
||||
public class WxMpServiceImpl implements WxMpService {
|
||||
|
||||
private static final JsonParser JSON_PARSER = new JsonParser();
|
||||
@ -45,7 +42,6 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this);
|
||||
private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this);
|
||||
private WxMpCardService cardService = new WxMpCardServiceImpl(this);
|
||||
private WxMpPayService payService = new WxMpPayServiceImpl(this);
|
||||
private WxMpStoreService storeService = new WxMpStoreServiceImpl(this);
|
||||
private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this);
|
||||
private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this);
|
||||
@ -59,7 +55,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
@Override
|
||||
public boolean checkSignature(String timestamp, String nonce, String signature) {
|
||||
try {
|
||||
return SHA1.gen(this.wxMpConfigStorage.getToken(), timestamp, nonce)
|
||||
return SHA1.gen(this.getWxMpConfigStorage().getToken(), timestamp, nonce)
|
||||
.equals(signature);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
@ -73,18 +69,18 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
|
||||
@Override
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
Lock lock = this.wxMpConfigStorage.getAccessTokenLock();
|
||||
Lock lock = this.getWxMpConfigStorage().getAccessTokenLock();
|
||||
try {
|
||||
lock.lock();
|
||||
|
||||
if (forceRefresh) {
|
||||
this.wxMpConfigStorage.expireAccessToken();
|
||||
this.getWxMpConfigStorage().expireAccessToken();
|
||||
}
|
||||
|
||||
if (this.wxMpConfigStorage.isAccessTokenExpired()) {
|
||||
if (this.getWxMpConfigStorage().isAccessTokenExpired()) {
|
||||
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
|
||||
"&appid=" + this.wxMpConfigStorage.getAppId() + "&secret="
|
||||
+ this.wxMpConfigStorage.getSecret();
|
||||
"&appid=" + this.getWxMpConfigStorage().getAppId() + "&secret="
|
||||
+ this.getWxMpConfigStorage().getSecret();
|
||||
try {
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
if (this.httpProxy != null) {
|
||||
@ -98,7 +94,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
|
||||
this.wxMpConfigStorage.updateAccessToken(accessToken.getAccessToken(),
|
||||
this.getWxMpConfigStorage().updateAccessToken(accessToken.getAccessToken(),
|
||||
accessToken.getExpiresIn());
|
||||
} finally {
|
||||
httpGet.releaseConnection();
|
||||
@ -110,7 +106,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return this.wxMpConfigStorage.getAccessToken();
|
||||
return this.getWxMpConfigStorage().getAccessToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -120,27 +116,27 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
|
||||
@Override
|
||||
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
|
||||
Lock lock = this.wxMpConfigStorage.getJsapiTicketLock();
|
||||
Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock();
|
||||
try {
|
||||
lock.lock();
|
||||
|
||||
if (forceRefresh) {
|
||||
this.wxMpConfigStorage.expireJsapiTicket();
|
||||
this.getWxMpConfigStorage().expireJsapiTicket();
|
||||
}
|
||||
|
||||
if (this.wxMpConfigStorage.isJsapiTicketExpired()) {
|
||||
if (this.getWxMpConfigStorage().isJsapiTicketExpired()) {
|
||||
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
|
||||
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
|
||||
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent);
|
||||
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
|
||||
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
|
||||
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
|
||||
this.wxMpConfigStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds);
|
||||
this.getWxMpConfigStorage().updateJsapiTicket(jsapiTicket, expiresInSeconds);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return this.wxMpConfigStorage.getJsapiTicket();
|
||||
return this.getWxMpConfigStorage().getJsapiTicket();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -151,7 +147,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket,
|
||||
"noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url);
|
||||
WxJsapiSignature jsapiSignature = new WxJsapiSignature();
|
||||
jsapiSignature.setAppId(this.wxMpConfigStorage.getAppId());
|
||||
jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId());
|
||||
jsapiSignature.setTimestamp(timestamp);
|
||||
jsapiSignature.setNonceStr(noncestr);
|
||||
jsapiSignature.setUrl(url);
|
||||
@ -216,7 +212,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) {
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append("https://open.weixin.qq.com/connect/oauth2/authorize?");
|
||||
url.append("appid=").append(this.wxMpConfigStorage.getAppId());
|
||||
url.append("appid=").append(this.getWxMpConfigStorage().getAppId());
|
||||
url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI));
|
||||
url.append("&response_type=code");
|
||||
url.append("&scope=").append(scope);
|
||||
@ -232,7 +228,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
String state) {
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append("https://open.weixin.qq.com/connect/qrconnect?");
|
||||
url.append("appid=").append(this.wxMpConfigStorage.getAppId());
|
||||
url.append("appid=").append(this.getWxMpConfigStorage().getAppId());
|
||||
url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI));
|
||||
url.append("&response_type=code");
|
||||
url.append("&scope=").append(scope);
|
||||
@ -258,8 +254,8 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException {
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append("https://api.weixin.qq.com/sns/oauth2/access_token?");
|
||||
url.append("appid=").append(this.wxMpConfigStorage.getAppId());
|
||||
url.append("&secret=").append(this.wxMpConfigStorage.getSecret());
|
||||
url.append("appid=").append(this.getWxMpConfigStorage().getAppId());
|
||||
url.append("&secret=").append(this.getWxMpConfigStorage().getSecret());
|
||||
url.append("&code=").append(code);
|
||||
url.append("&grant_type=authorization_code");
|
||||
|
||||
@ -270,7 +266,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException {
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?");
|
||||
url.append("appid=").append(this.wxMpConfigStorage.getAppId());
|
||||
url.append("appid=").append(this.getWxMpConfigStorage().getAppId());
|
||||
url.append("&grant_type=refresh_token");
|
||||
url.append("&refresh_token=").append(refreshToken);
|
||||
|
||||
@ -397,8 +393,8 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
*/
|
||||
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) {
|
||||
// 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
|
||||
this.wxMpConfigStorage.expireAccessToken();
|
||||
if (this.wxMpConfigStorage.autoRefreshToken()) {
|
||||
this.getWxMpConfigStorage().expireAccessToken();
|
||||
if (this.getWxMpConfigStorage().autoRefreshToken()) {
|
||||
return this.execute(executor, uri, data);
|
||||
}
|
||||
}
|
||||
@ -424,26 +420,19 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
}
|
||||
|
||||
private void initHttpClient() {
|
||||
ApacheHttpClientBuilder apacheHttpClientBuilder = this.wxMpConfigStorage
|
||||
.getApacheHttpClientBuilder();
|
||||
WxMpConfigStorage configStorage = this.getWxMpConfigStorage();
|
||||
ApacheHttpClientBuilder apacheHttpClientBuilder = configStorage.getApacheHttpClientBuilder();
|
||||
if (null == apacheHttpClientBuilder) {
|
||||
apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get();
|
||||
}
|
||||
|
||||
apacheHttpClientBuilder.httpProxyHost(this.wxMpConfigStorage.getHttpProxyHost())
|
||||
.httpProxyPort(this.wxMpConfigStorage.getHttpProxyPort())
|
||||
.httpProxyUsername(this.wxMpConfigStorage.getHttpProxyUsername())
|
||||
.httpProxyPassword(this.wxMpConfigStorage.getHttpProxyPassword());
|
||||
apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost())
|
||||
.httpProxyPort(configStorage.getHttpProxyPort())
|
||||
.httpProxyUsername(configStorage.getHttpProxyUsername())
|
||||
.httpProxyPassword(configStorage.getHttpProxyPassword());
|
||||
|
||||
// if (this.wxMpConfigStorage.getSSLContext() != null) {
|
||||
// SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
|
||||
// this.wxMpConfigStorage.getSSLContext(), new String[] { "TLSv1" }, null,
|
||||
// new DefaultHostnameVerifier());
|
||||
// apacheHttpClientBuilder.sslConnectionSocketFactory(sslsf);
|
||||
// }
|
||||
|
||||
if (this.wxMpConfigStorage.getHttpProxyHost() != null && this.wxMpConfigStorage.getHttpProxyPort() > 0) {
|
||||
this.httpProxy = new HttpHost(this.wxMpConfigStorage.getHttpProxyHost(), this.wxMpConfigStorage.getHttpProxyPort());
|
||||
if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) {
|
||||
this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort());
|
||||
}
|
||||
|
||||
this.httpClient = apacheHttpClientBuilder.build();
|
||||
@ -505,11 +494,6 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
return this.cardService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMpPayService getPayService() {
|
||||
return this.payService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMpDataCubeService getDataCubeService() {
|
||||
return this.dataCubeService;
|
||||
|
@ -1,392 +0,0 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import me.chanjar.weixin.common.util.BeanUtils;
|
||||
import me.chanjar.weixin.common.util.ToStringUtils;
|
||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyCoupon;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyResultConverter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付结果通用通知 ,文档见:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
|
||||
* @author aimilin6688
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 5389718115223345496L;
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 设备号
|
||||
* device_info
|
||||
* 否
|
||||
* String(32)
|
||||
* 013467007045764
|
||||
* 微信支付分配的终端设备号,
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("device_info")
|
||||
private String deviceInfo;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 用户标识
|
||||
* openid
|
||||
* 是
|
||||
* String(128)
|
||||
* wxd930ea5d5a258f4f
|
||||
* 用户在商户appid下的唯一标识
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 是否关注公众账号
|
||||
* is_subscribe
|
||||
* 否
|
||||
* String(1)
|
||||
* Y
|
||||
* 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("is_subscribe")
|
||||
private String isSubscribe;
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 交易类型
|
||||
* trade_type
|
||||
* 是
|
||||
* String(16)
|
||||
* JSAPI JSAPI、NATIVE、APP
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("trade_type")
|
||||
private String tradeType;
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 付款银行
|
||||
* bank_type
|
||||
* 是
|
||||
* String(16)
|
||||
* CMC
|
||||
* 银行类型,采用字符串类型的银行标识,银行类型见银行列表
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("bank_type")
|
||||
private String bankType;
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 订单金额
|
||||
* total_fee
|
||||
* 是
|
||||
* Int
|
||||
* 100
|
||||
* 订单总金额,单位为分
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("total_fee")
|
||||
private Integer totalFee;
|
||||
/**
|
||||
* <pre>
|
||||
* 应结订单金额
|
||||
* settlement_total_fee
|
||||
* 否
|
||||
* Int
|
||||
* 100
|
||||
* 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("settlement_total_fee")
|
||||
private Integer settlementTotalFee;
|
||||
/**
|
||||
* <pre>
|
||||
* 货币种类
|
||||
* fee_type
|
||||
* 否
|
||||
* String(8)
|
||||
* CNY
|
||||
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("fee_type")
|
||||
private String feeType;
|
||||
/**
|
||||
* <pre>
|
||||
* 现金支付金额
|
||||
* cash_fee
|
||||
* 是
|
||||
* Int
|
||||
* 100
|
||||
* 现金支付金额订单现金支付金额,详见支付金额
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("cash_fee")
|
||||
private Integer cashFee;
|
||||
/**
|
||||
* <pre>
|
||||
* 现金支付货币类型
|
||||
* cash_fee_type
|
||||
* 否
|
||||
* String(16)
|
||||
* CNY
|
||||
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("cash_fee_type")
|
||||
private String cashFeeType;
|
||||
/**
|
||||
* <pre>
|
||||
* 总代金券金额
|
||||
* coupon_fee
|
||||
* 否
|
||||
* Int
|
||||
* 10
|
||||
* 代金券金额<=订单金额,订单金额-代金券金额=现金支付金额,详见支付金额
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("coupon_fee")
|
||||
private Integer couponFee;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 代金券使用数量
|
||||
* coupon_count
|
||||
* 否
|
||||
* Int
|
||||
* 1
|
||||
* 代金券使用数量
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("coupon_count")
|
||||
private Integer couponCount;
|
||||
|
||||
private List<WxPayOrderNotifyCoupon> couponList;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付订单号
|
||||
* transaction_id
|
||||
* 是
|
||||
* String(32)
|
||||
* 1217752501201407033233368018
|
||||
* 微信支付订单号
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("transaction_id")
|
||||
private String transactionId;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 商户订单号
|
||||
* out_trade_no
|
||||
* 是
|
||||
* String(32)
|
||||
* 1212321211201407033568112322
|
||||
* 商户系统的订单号,与请求一致。
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("out_trade_no")
|
||||
private String outTradeNo;
|
||||
/**
|
||||
* <pre>
|
||||
* 商家数据包
|
||||
* attach
|
||||
* 否
|
||||
* String(128)
|
||||
* 123456
|
||||
* 商家数据包,原样返回
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("attach")
|
||||
private String attach;
|
||||
/**
|
||||
* <pre>
|
||||
* 支付完成时间
|
||||
* time_end
|
||||
* 是
|
||||
* String(14)
|
||||
* 20141030133525
|
||||
* 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("time_end")
|
||||
private String timeEnd;
|
||||
|
||||
public Integer getCouponCount() {
|
||||
return couponCount;
|
||||
}
|
||||
|
||||
public void setCouponCount(Integer couponCount) {
|
||||
this.couponCount = couponCount;
|
||||
}
|
||||
|
||||
public List<WxPayOrderNotifyCoupon> getCouponList() {
|
||||
return couponList;
|
||||
}
|
||||
|
||||
public void setCouponList(List<WxPayOrderNotifyCoupon> couponList) {
|
||||
this.couponList = couponList;
|
||||
}
|
||||
|
||||
public String getDeviceInfo() {
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
public void setDeviceInfo(String deviceInfo) {
|
||||
this.deviceInfo = deviceInfo;
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
public String getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
|
||||
public void setIsSubscribe(String isSubscribe) {
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public String getTradeType() {
|
||||
return tradeType;
|
||||
}
|
||||
|
||||
public void setTradeType(String tradeType) {
|
||||
this.tradeType = tradeType;
|
||||
}
|
||||
|
||||
public String getBankType() {
|
||||
return bankType;
|
||||
}
|
||||
|
||||
public void setBankType(String bankType) {
|
||||
this.bankType = bankType;
|
||||
}
|
||||
|
||||
public Integer getTotalFee() {
|
||||
return totalFee;
|
||||
}
|
||||
|
||||
public void setTotalFee(Integer totalFee) {
|
||||
this.totalFee = totalFee;
|
||||
}
|
||||
|
||||
public Integer getSettlementTotalFee() {
|
||||
return settlementTotalFee;
|
||||
}
|
||||
|
||||
public void setSettlementTotalFee(Integer settlementTotalFee) {
|
||||
this.settlementTotalFee = settlementTotalFee;
|
||||
}
|
||||
|
||||
public String getFeeType() {
|
||||
return feeType;
|
||||
}
|
||||
|
||||
public void setFeeType(String feeType) {
|
||||
this.feeType = feeType;
|
||||
}
|
||||
|
||||
public Integer getCashFee() {
|
||||
return cashFee;
|
||||
}
|
||||
|
||||
public void setCashFee(Integer cashFee) {
|
||||
this.cashFee = cashFee;
|
||||
}
|
||||
|
||||
public String getCashFeeType() {
|
||||
return cashFeeType;
|
||||
}
|
||||
|
||||
public void setCashFeeType(String cashFeeType) {
|
||||
this.cashFeeType = cashFeeType;
|
||||
}
|
||||
|
||||
public Integer getCouponFee() {
|
||||
return couponFee;
|
||||
}
|
||||
|
||||
public void setCouponFee(Integer couponFee) {
|
||||
this.couponFee = couponFee;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public void setOutTradeNo(String outTradeNo) {
|
||||
this.outTradeNo = outTradeNo;
|
||||
}
|
||||
|
||||
public String getAttach() {
|
||||
return attach;
|
||||
}
|
||||
|
||||
public void setAttach(String attach) {
|
||||
this.attach = attach;
|
||||
}
|
||||
|
||||
public String getTimeEnd() {
|
||||
return timeEnd;
|
||||
}
|
||||
|
||||
public void setTimeEnd(String timeEnd) {
|
||||
this.timeEnd = timeEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,String> toMap(){
|
||||
Map<String,String> resultMap = BeanUtils.xmlBean2Map(this);
|
||||
if(this.getCouponCount() != null && this.getCouponCount() > 0){
|
||||
for (int i = 0; i < this.getCouponCount(); i++) {
|
||||
WxPayOrderNotifyCoupon coupon = couponList.get(i);
|
||||
resultMap.putAll(coupon.toMap(i));
|
||||
}
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringUtils.toSimpleString(this);
|
||||
}
|
||||
|
||||
public static WxPayOrderNotifyResult fromXML(String xmlString) {
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.processAnnotations(WxPayOrderNotifyResult.class);
|
||||
xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider()));
|
||||
WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlString);
|
||||
result.setXmlString(xmlString);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.test.ApiTestModule;
|
||||
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
|
||||
import me.chanjar.weixin.mp.api.test.TestConstants;
|
||||
import me.chanjar.weixin.mp.bean.WxMpMassNews;
|
||||
import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpMassTagMessage;
|
||||
@ -101,7 +102,7 @@ public class WxMpMassMessageAPITest {
|
||||
.getSystemResourceAsStream("mm.mp4")) {
|
||||
// 上传视频到媒体库
|
||||
WxMediaUploadResult uploadMediaRes = this.wxService.getMaterialService()
|
||||
.mediaUpload(WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, inputStream);
|
||||
.mediaUpload(WxConsts.MEDIA_VIDEO, TestConstants.FILE_MP4, inputStream);
|
||||
Assert.assertNotNull(uploadMediaRes);
|
||||
Assert.assertNotNull(uploadMediaRes.getMediaId());
|
||||
|
||||
@ -122,7 +123,7 @@ public class WxMpMassMessageAPITest {
|
||||
try (InputStream inputStream = ClassLoader
|
||||
.getSystemResourceAsStream("mm.jpeg")) {
|
||||
WxMediaUploadResult uploadMediaRes = this.wxService.getMaterialService()
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream);
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, TestConstants.FILE_JPG, inputStream);
|
||||
Assert.assertNotNull(uploadMediaRes);
|
||||
Assert.assertNotNull(uploadMediaRes.getMediaId());
|
||||
messages[1] = new Object[]{WxConsts.MASS_MSG_IMAGE, uploadMediaRes.getMediaId()};
|
||||
@ -134,7 +135,7 @@ public class WxMpMassMessageAPITest {
|
||||
try (InputStream inputStream = ClassLoader
|
||||
.getSystemResourceAsStream("mm.mp3")) {
|
||||
WxMediaUploadResult uploadMediaRes = this.wxService.getMaterialService()
|
||||
.mediaUpload(WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, inputStream);
|
||||
.mediaUpload(WxConsts.MEDIA_VOICE, TestConstants.FILE_MP3, inputStream);
|
||||
Assert.assertNotNull(uploadMediaRes);
|
||||
Assert.assertNotNull(uploadMediaRes.getMediaId());
|
||||
messages[2] = new Object[]{WxConsts.MASS_MSG_VOICE, uploadMediaRes.getMediaId()};
|
||||
@ -147,7 +148,7 @@ public class WxMpMassMessageAPITest {
|
||||
.getSystemResourceAsStream("mm.jpeg")) {
|
||||
// 上传照片到媒体库
|
||||
WxMediaUploadResult uploadMediaRes = this.wxService.getMaterialService()
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream);
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, TestConstants.FILE_JPG, inputStream);
|
||||
Assert.assertNotNull(uploadMediaRes);
|
||||
Assert.assertNotNull(uploadMediaRes.getMediaId());
|
||||
|
||||
|
@ -7,6 +7,7 @@ import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.fs.FileUtils;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.api.test.ApiTestModule;
|
||||
import me.chanjar.weixin.mp.api.test.TestConstants;
|
||||
import me.chanjar.weixin.mp.bean.material.*;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
@ -45,10 +46,10 @@ public class WxMpMaterialServiceImplTest {
|
||||
@DataProvider
|
||||
public Object[][] mediaFiles() {
|
||||
return new Object[][]{
|
||||
new Object[]{WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg"},
|
||||
new Object[]{WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3"},
|
||||
new Object[]{WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4"},
|
||||
new Object[]{WxConsts.MEDIA_THUMB, WxConsts.FILE_JPG, "mm.jpeg"}
|
||||
new Object[]{WxConsts.MEDIA_IMAGE, TestConstants.FILE_JPG, "mm.jpeg"},
|
||||
new Object[]{WxConsts.MEDIA_VOICE, TestConstants.FILE_MP3, "mm.mp3"},
|
||||
new Object[]{WxConsts.MEDIA_VIDEO, TestConstants.FILE_MP4, "mm.mp4"},
|
||||
new Object[]{WxConsts.MEDIA_THUMB, TestConstants.FILE_JPG, "mm.jpeg"}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,195 +0,0 @@
|
||||
package me.chanjar.weixin.mp.api.impl;
|
||||
|
||||
import com.github.binarywang.utils.qrcode.QrcodeUtils;
|
||||
import com.google.inject.Inject;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.api.test.ApiTestModule;
|
||||
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
|
||||
import me.chanjar.weixin.mp.bean.pay.request.*;
|
||||
import me.chanjar.weixin.mp.bean.pay.result.*;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* 测试支付相关接口
|
||||
* Created by Binary Wang on 2016/7/28.
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
@Test
|
||||
@Guice(modules = ApiTestModule.class)
|
||||
public class WxMpPayServiceImplTest {
|
||||
|
||||
@Inject
|
||||
protected WxMpService wxService;
|
||||
|
||||
@Test
|
||||
public void testGetPayInfo() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDownloadBill() throws Exception {
|
||||
File file = this.wxService.getPayService().downloadBill("20170101", "ALL", "GZIP", "1111111");
|
||||
assertNotNull(file);
|
||||
//必填字段为空时,抛出异常
|
||||
this.wxService.getPayService().downloadBill("", "", "", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReport() throws Exception {
|
||||
WxPayReportRequest request = new WxPayReportRequest();
|
||||
request.setInterfaceUrl("hahahah");
|
||||
request.setSignType("HMAC-SHA256");//貌似接口未校验此字段
|
||||
request.setExecuteTime(1000);
|
||||
request.setReturnCode("aaa");
|
||||
request.setResultCode("aaa");
|
||||
request.setUserIp("8.8.8");
|
||||
this.wxService.getPayService().report(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要证书的接口需要先执行该方法
|
||||
*/
|
||||
@Test
|
||||
public void setSSLKey() {
|
||||
TestConfigStorage config = (TestConfigStorage) this.wxService.getWxMpConfigStorage();
|
||||
config.setSslContextFilePath(config.getKeyPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refund(WxPayRefundRequest)} .
|
||||
*/
|
||||
@Test(dependsOnMethods = {"setSSLKey"})
|
||||
public void testRefund() throws Exception {
|
||||
WxPayRefundRequest request = new WxPayRefundRequest();
|
||||
request.setOutRefundNo("aaa");
|
||||
request.setOutTradeNo("1111");
|
||||
request.setTotalFee(1222);
|
||||
request.setRefundFee(111);
|
||||
WxPayRefundResult result = this.wxService.getPayService().refund(request);
|
||||
System.err.println(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refundQuery(String, String, String, String)} .
|
||||
*/
|
||||
@Test
|
||||
public void testRefundQuery() throws Exception {
|
||||
WxPayRefundQueryResult result;
|
||||
|
||||
result = this.wxService.getPayService().refundQuery("1", "", "", "");
|
||||
System.err.println(result);
|
||||
result = this.wxService.getPayService().refundQuery("", "2", "", "");
|
||||
System.err.println(result);
|
||||
result = this.wxService.getPayService().refundQuery("", "", "3", "");
|
||||
System.err.println(result);
|
||||
result = this.wxService.getPayService().refundQuery("", "", "", "4");
|
||||
System.err.println(result);
|
||||
//测试四个参数都填的情况,应该报异常的
|
||||
result = this.wxService.getPayService().refundQuery("1", "2", "3", "4");
|
||||
System.err.println(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#sendRedpack(WxPaySendRedpackRequest)} .
|
||||
*/
|
||||
@Test(dependsOnMethods = {"setSSLKey"})
|
||||
public void testSendRedpack() throws Exception {
|
||||
WxPaySendRedpackRequest request = new WxPaySendRedpackRequest();
|
||||
request.setActName("abc");
|
||||
request.setClientIp("aaa");
|
||||
request.setMchBillNo("aaaa");
|
||||
request
|
||||
.setReOpenid(((TestConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid());
|
||||
WxPaySendRedpackResult redpackResult = this.wxService.getPayService().sendRedpack(request);
|
||||
System.err.println(redpackResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryRedpack(String)}.
|
||||
*/
|
||||
@Test(dependsOnMethods = {"setSSLKey"})
|
||||
public void testQueryRedpack() throws Exception {
|
||||
WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa");
|
||||
System.err.println(redpackResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#unifiedOrder(WxPayUnifiedOrderRequest)}.
|
||||
*/
|
||||
@Test
|
||||
public void testUnifiedOrder() throws WxErrorException {
|
||||
WxPayUnifiedOrderResult result = this.wxService.getPayService()
|
||||
.unifiedOrder(WxPayUnifiedOrderRequest.builder().body("1111111")
|
||||
.totalFee(1).spbillCreateIp("111111").notifyURL("111111")
|
||||
.tradeType("JSAPI").openid("122").outTradeNo("111111").build());
|
||||
System.err.println(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryOrder(String, String)} .
|
||||
*/
|
||||
@Test
|
||||
public final void testQueryOrder() throws WxErrorException {
|
||||
//System.err.println(this.wxService.getPayService().queryOrder(null, null));
|
||||
System.err.println(this.wxService.getPayService().queryOrder("11212121", null));
|
||||
System.err.println(this.wxService.getPayService().queryOrder(null, "11111"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#closeOrder(String)} .
|
||||
*/
|
||||
@Test
|
||||
public final void testCloseOrder() throws WxErrorException {
|
||||
System.err.println(this.wxService.getPayService().closeOrder("11212121"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#entPay(WxEntPayRequest)}.
|
||||
*/
|
||||
@Test(dependsOnMethods = {"setSSLKey"})
|
||||
public final void testEntPay() throws WxErrorException {
|
||||
WxEntPayRequest request = new WxEntPayRequest();
|
||||
System.err.println(this.wxService.getPayService().entPay(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryEntPay(String)}.
|
||||
*/
|
||||
@Test(dependsOnMethods = {"setSSLKey"})
|
||||
public final void testQueryEntPay() throws WxErrorException {
|
||||
System.err.println(this.wxService.getPayService().queryEntPay("11212121"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateScanPayQrcodeMode1() throws Exception {
|
||||
String productId = "abc";
|
||||
byte[] bytes = this.wxService.getPayService().createScanPayQrcodeMode1(productId, null, null);
|
||||
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
|
||||
Files.write(qrcodeFilePath, bytes);
|
||||
String qrcodeContent = QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile());
|
||||
System.out.println(qrcodeContent);
|
||||
|
||||
assertTrue(qrcodeContent.startsWith("weixin://wxpay/bizpayurl?"));
|
||||
assertTrue(qrcodeContent.contains("product_id=" + productId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateScanPayQrcodeMode2() throws Exception {
|
||||
String qrcodeContent = "abc";
|
||||
byte[] bytes = this.wxService.getPayService().createScanPayQrcodeMode2(qrcodeContent, null, null);
|
||||
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
|
||||
Files.write(qrcodeFilePath, bytes);
|
||||
|
||||
assertEquals(QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile()), qrcodeContent);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -17,8 +17,7 @@ public class ApiTestModule implements Module {
|
||||
@Override
|
||||
public void configure(Binder binder) {
|
||||
try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) {
|
||||
TestConfigStorage config = this
|
||||
.fromXml(TestConfigStorage.class, is1);
|
||||
TestConfigStorage config = this.fromXml(TestConfigStorage.class, is1);
|
||||
config.setAccessTokenLock(new ReentrantLock());
|
||||
WxMpService wxService = new WxMpServiceImpl();
|
||||
wxService.setWxMpConfigStorage(config);
|
||||
|
@ -64,10 +64,4 @@ public class TestConfigStorage extends WxMpInMemoryConfigStorage {
|
||||
super.accessTokenLock = lock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useSandboxForWxPay() {
|
||||
return false;
|
||||
//沙箱环境不成熟,有问题无法使用,暂时屏蔽掉
|
||||
// return true;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package me.chanjar.weixin.mp.api.test;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 仅供测试使用的一些常量
|
||||
* Created by Binary Wang on 2017-3-9.
|
||||
* </pre>
|
||||
*/
|
||||
public class TestConstants {
|
||||
///////////////////////
|
||||
// 文件类型
|
||||
///////////////////////
|
||||
public static final String FILE_JPG = "jpeg";
|
||||
public static final String FILE_MP3 = "mp3";
|
||||
public static final String FILE_AMR = "amr";
|
||||
public static final String FILE_MP4 = "mp4";
|
||||
}
|
@ -6,6 +6,7 @@ import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.api.test.TestConstants;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
@ -18,7 +19,7 @@ public class DemoImageHandler implements WxMpMessageHandler {
|
||||
WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||
try {
|
||||
WxMediaUploadResult wxMediaUploadResult = wxMpService.getMaterialService()
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, TestConstants.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
|
||||
WxMpXmlOutImageMessage m
|
||||
= WxMpXmlOutMessage
|
||||
.IMAGE()
|
||||
|
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>2.6.0-SNAPSHOT</version>
|
||||
<version>2.5.2.BETA</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-osgi</artifactId>
|
||||
|
52
weixin-java-pay/pom.xml
Normal file
52
weixin-java-pay/pom.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>2.5.2.BETA</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>weixin-java-pay</artifactId>
|
||||
<name>WeiXin Java Tools - PAY</name>
|
||||
<description>微信支付 Java SDK</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jodd</groupId>
|
||||
<artifactId>jodd-http</artifactId>
|
||||
<version>3.7</version>
|
||||
<!-- 由于较新的3.8版本需要jdk8,故而此处采用较低版本 -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>xml-path</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>qrcode-utils</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -1,64 +1,63 @@
|
||||
package me.chanjar.weixin.mp.bean.pay;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 支付异步通知代金券详细
|
||||
*/
|
||||
public class WxPayOrderNotifyCoupon implements Serializable {
|
||||
/**
|
||||
* @fields serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -4165343733538156097L;
|
||||
|
||||
@XStreamAlias("coupon_id")
|
||||
private String couponId;
|
||||
@XStreamAlias("coupon_type")
|
||||
private String couponType;
|
||||
@XStreamAlias("coupon_fee")
|
||||
private Integer couponFee;
|
||||
|
||||
public String getCouponId() {
|
||||
return couponId;
|
||||
}
|
||||
|
||||
public void setCouponId(String couponId) {
|
||||
this.couponId = couponId;
|
||||
}
|
||||
|
||||
public String getCouponType() {
|
||||
return couponType;
|
||||
}
|
||||
|
||||
public void setCouponType(String couponType) {
|
||||
this.couponType = couponType;
|
||||
}
|
||||
|
||||
public Integer getCouponFee() {
|
||||
return couponFee;
|
||||
}
|
||||
|
||||
public void setCouponFee(Integer couponFee) {
|
||||
this.couponFee = couponFee;
|
||||
}
|
||||
|
||||
public Map<String, String> toMap(int index) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("coupon_id_" + index, this.getCouponId());
|
||||
map.put("coupon_type_" + index, this.getCouponType());
|
||||
map.put("coupon_fee_" + index, this.getCouponFee() + "");
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
|
||||
}
|
||||
}
|
||||
package com.github.binarywang.wxpay.bean;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付异步通知代金券详细
|
||||
*/
|
||||
public class WxPayOrderNotifyCoupon implements Serializable {
|
||||
/**
|
||||
* @fields serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -4165343733538156097L;
|
||||
|
||||
@XStreamAlias("coupon_id")
|
||||
private String couponId;
|
||||
@XStreamAlias("coupon_type")
|
||||
private String couponType;
|
||||
@XStreamAlias("coupon_fee")
|
||||
private Integer couponFee;
|
||||
|
||||
public String getCouponId() {
|
||||
return couponId;
|
||||
}
|
||||
|
||||
public void setCouponId(String couponId) {
|
||||
this.couponId = couponId;
|
||||
}
|
||||
|
||||
public String getCouponType() {
|
||||
return couponType;
|
||||
}
|
||||
|
||||
public void setCouponType(String couponType) {
|
||||
this.couponType = couponType;
|
||||
}
|
||||
|
||||
public Integer getCouponFee() {
|
||||
return couponFee;
|
||||
}
|
||||
|
||||
public void setCouponFee(Integer couponFee) {
|
||||
this.couponFee = couponFee;
|
||||
}
|
||||
|
||||
public Map<String, String> toMap(int index) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("coupon_id_" + index, this.getCouponId());
|
||||
map.put("coupon_type_" + index, this.getCouponType());
|
||||
map.put("coupon_fee_" + index, this.getCouponFee() + "");
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
|
||||
}
|
||||
}
|
@ -1,60 +1,59 @@
|
||||
package me.chanjar.weixin.mp.bean.pay;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||
|
||||
@XStreamAlias("xml")
|
||||
public class WxPayOrderNotifyResponse {
|
||||
@XStreamOmitField
|
||||
private transient static final String FAIL = "FAIL";
|
||||
@XStreamOmitField
|
||||
private transient static final String SUCCESS = "SUCCESS";
|
||||
|
||||
@XStreamAlias("return_code")
|
||||
private String returnCode;
|
||||
@XStreamAlias("return_msg")
|
||||
private String returnMsg;
|
||||
|
||||
public String getReturnCode() {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(String returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
|
||||
public String getReturnMsg() {
|
||||
return returnMsg;
|
||||
}
|
||||
|
||||
public void setReturnMsg(String returnMsg) {
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
public WxPayOrderNotifyResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public WxPayOrderNotifyResponse(String returnCode, String returnMsg) {
|
||||
super();
|
||||
this.returnCode = returnCode;
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
public static String fail(String msg) {
|
||||
WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(FAIL, msg);
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.autodetectAnnotations(true);
|
||||
return xstream.toXML(response);
|
||||
}
|
||||
|
||||
public static String success(String msg) {
|
||||
WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(SUCCESS, msg);
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.autodetectAnnotations(true);
|
||||
return xstream.toXML(response);
|
||||
}
|
||||
}
|
||||
package com.github.binarywang.wxpay.bean;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||
|
||||
@XStreamAlias("xml")
|
||||
public class WxPayOrderNotifyResponse {
|
||||
@XStreamOmitField
|
||||
private transient static final String FAIL = "FAIL";
|
||||
@XStreamOmitField
|
||||
private transient static final String SUCCESS = "SUCCESS";
|
||||
|
||||
@XStreamAlias("return_code")
|
||||
private String returnCode;
|
||||
@XStreamAlias("return_msg")
|
||||
private String returnMsg;
|
||||
|
||||
public WxPayOrderNotifyResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public WxPayOrderNotifyResponse(String returnCode, String returnMsg) {
|
||||
super();
|
||||
this.returnCode = returnCode;
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
public static String fail(String msg) {
|
||||
WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(FAIL, msg);
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.autodetectAnnotations(true);
|
||||
return xstream.toXML(response);
|
||||
}
|
||||
|
||||
public static String success(String msg) {
|
||||
WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(SUCCESS, msg);
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.autodetectAnnotations(true);
|
||||
return xstream.toXML(response);
|
||||
}
|
||||
|
||||
public String getReturnCode() {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(String returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
|
||||
public String getReturnMsg() {
|
||||
return returnMsg;
|
||||
}
|
||||
|
||||
public void setReturnMsg(String returnMsg) {
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import me.chanjar.weixin.common.annotation.Required;
|
||||
@ -16,6 +16,7 @@ import me.chanjar.weixin.common.util.ToStringUtils;
|
||||
* <li>描述
|
||||
* </pre>
|
||||
* Created by Binary Wang on 2016/10/19.
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
@ -29,20 +30,20 @@ public class WxEntPayQueryRequest extends WxPayBaseRequest {
|
||||
* String(32)
|
||||
* 微信支付分配的商户号
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("mchid")
|
||||
private String mchId;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 商户订单号
|
||||
* partner_trade_no
|
||||
* 是
|
||||
* 10000098201411111234567890
|
||||
* String
|
||||
* 商户订单号
|
||||
* 商户订单号
|
||||
* partner_trade_no
|
||||
* 是
|
||||
* 10000098201411111234567890
|
||||
* String
|
||||
* 商户订单号
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@Required
|
||||
@XStreamAlias("partner_trade_no")
|
||||
private String partnerTradeNo;
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import me.chanjar.weixin.common.util.ToStringUtils;
|
||||
@ -15,140 +15,141 @@ import me.chanjar.weixin.common.util.ToStringUtils;
|
||||
* <li>描述
|
||||
* </pre>
|
||||
* Created by Binary Wang on 2016/10/02.
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class WxEntPayRequest extends WxPayBaseRequest{
|
||||
public class WxEntPayRequest extends WxPayBaseRequest {
|
||||
/**
|
||||
* <pre>
|
||||
* 公众账号appid
|
||||
* mch_appid
|
||||
* 是
|
||||
* wx8888888888888888
|
||||
* String
|
||||
* 微信分配的公众账号ID(企业号corpid即为此appId)
|
||||
* 公众账号appid
|
||||
* mch_appid
|
||||
* 是
|
||||
* wx8888888888888888
|
||||
* String
|
||||
* 微信分配的公众账号ID(企业号corpid即为此appId)
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("mch_appid")
|
||||
private String mchAppid;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 商户号
|
||||
* mchid
|
||||
* 是
|
||||
* 1900000109
|
||||
* String(32)
|
||||
* 微信支付分配的商户号
|
||||
* 商户号
|
||||
* mchid
|
||||
* 是
|
||||
* 1900000109
|
||||
* String(32)
|
||||
* 微信支付分配的商户号
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("mchid")
|
||||
private String mchId;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 设备号
|
||||
* device_info
|
||||
* 否
|
||||
* 13467007045764
|
||||
* String(32)
|
||||
*微信支付分配的终端设备号
|
||||
* 设备号
|
||||
* device_info
|
||||
* 否
|
||||
* 13467007045764
|
||||
* String(32)
|
||||
* 微信支付分配的终端设备号
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("device_info")
|
||||
private String deviceInfo;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 商户订单号
|
||||
* partner_trade_no
|
||||
* 是
|
||||
* 10000098201411111234567890
|
||||
* String
|
||||
* 商户订单号
|
||||
* 商户订单号
|
||||
* partner_trade_no
|
||||
* 是
|
||||
* 10000098201411111234567890
|
||||
* String
|
||||
* 商户订单号
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("partner_trade_no")
|
||||
private String partnerTradeNo;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 需保持唯一性 用户openid
|
||||
* openid
|
||||
* 是
|
||||
* oxTWIuGaIt6gTKsQRLau2M0yL16E
|
||||
* String
|
||||
* 商户appid下,某用户的openid
|
||||
* 需保持唯一性 用户openid
|
||||
* openid
|
||||
* 是
|
||||
* oxTWIuGaIt6gTKsQRLau2M0yL16E
|
||||
* String
|
||||
* 商户appid下,某用户的openid
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 校验用户姓名选项
|
||||
* check_name
|
||||
* 是
|
||||
* OPTION_CHECK
|
||||
* String
|
||||
* NO_CHECK:不校验真实姓名
|
||||
* FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账)
|
||||
* OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
|
||||
* 校验用户姓名选项
|
||||
* check_name
|
||||
* 是
|
||||
* OPTION_CHECK
|
||||
* String
|
||||
* NO_CHECK:不校验真实姓名
|
||||
* FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账)
|
||||
* OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("check_name")
|
||||
private String checkName;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 收款用户姓名
|
||||
* re_user_name
|
||||
* 可选
|
||||
* 马花花
|
||||
* String
|
||||
* 收款用户真实姓名。
|
||||
* 如果check_name设置为FORCE_CHECK或OPTION_CHECK, 则必填用户真实姓名
|
||||
* 收款用户姓名
|
||||
* re_user_name
|
||||
* 可选
|
||||
* 马花花
|
||||
* String
|
||||
* 收款用户真实姓名。
|
||||
* 如果check_name设置为FORCE_CHECK或OPTION_CHECK, 则必填用户真实姓名
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("re_user_name")
|
||||
private String reUserName;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 金额
|
||||
* amount
|
||||
* 是
|
||||
* 10099
|
||||
* int
|
||||
* 企业付款金额, 单位为分
|
||||
* 金额
|
||||
* amount
|
||||
* 是
|
||||
* 10099
|
||||
* int
|
||||
* 企业付款金额, 单位为分
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("amount")
|
||||
private Integer amount;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 企业付款描述信息
|
||||
* desc
|
||||
* 是
|
||||
* 理赔
|
||||
* String
|
||||
* 企业付款操作说明信息。必填。
|
||||
* 企业付款描述信息
|
||||
* desc
|
||||
* 是
|
||||
* 理赔
|
||||
* String
|
||||
* 企业付款操作说明信息。必填。
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("desc")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Ip地址
|
||||
* spbill_create_ip
|
||||
* 是
|
||||
* 192.168.0.1
|
||||
* String(32)
|
||||
* 调用接口的机器Ip地址
|
||||
* Ip地址
|
||||
* spbill_create_ip
|
||||
* 是
|
||||
* 192.168.0.1
|
||||
* String(32)
|
||||
* 调用接口的机器Ip地址
|
||||
* </pre>
|
||||
*/
|
||||
*/
|
||||
@XStreamAlias("spbill_create_ip")
|
||||
private String spbillCreateIp;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
@ -47,6 +47,32 @@ public abstract class WxPayBaseRequest {
|
||||
*/
|
||||
@XStreamAlias("mch_id")
|
||||
protected String mchId;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 服务商模式下的子商户公众账号ID
|
||||
* sub_appid
|
||||
* 是
|
||||
* String(32)
|
||||
* wxd678efh567hg6787
|
||||
* 微信分配的子商户公众账号ID
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("sub_appid")
|
||||
protected String subAppId;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 服务商模式下的子商户号
|
||||
* sub_mch_id
|
||||
* 是
|
||||
* String(32)
|
||||
* 1230000109
|
||||
* 微信支付分配的子商户号,开发者模式下必填
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("sub_mch_id")
|
||||
protected String subMchId;
|
||||
/**
|
||||
* <pre>
|
||||
* 随机字符串
|
||||
@ -128,6 +154,22 @@ public abstract class WxPayBaseRequest {
|
||||
this.sign = sign;
|
||||
}
|
||||
|
||||
public String getSubAppId() {
|
||||
return subAppId;
|
||||
}
|
||||
|
||||
public void setSubAppId(String subAppId) {
|
||||
this.subAppId = subAppId;
|
||||
}
|
||||
|
||||
public String getSubMchId() {
|
||||
return subMchId;
|
||||
}
|
||||
|
||||
public void setSubMchId(String subMchId) {
|
||||
this.subMchId = subMchId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringUtils.toSimpleString(this);
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import me.chanjar.weixin.common.annotation.Required;
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
@ -10,7 +10,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class WxPayOrderCloseRequest extends WxPayBaseRequest{
|
||||
public class WxPayOrderCloseRequest extends WxPayBaseRequest {
|
||||
|
||||
/**
|
||||
* <pre>
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
@ -14,6 +14,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
* <li>示例值
|
||||
* <li>描述
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
|
||||
*/
|
||||
@XStreamAlias("xml")
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import me.chanjar.weixin.common.annotation.Required;
|
||||
@ -143,6 +143,28 @@ public class WxPayRefundRequest extends WxPayBaseRequest {
|
||||
@XStreamAlias("refund_account")
|
||||
private String refundAccount;
|
||||
|
||||
private WxPayRefundRequest(Builder builder) {
|
||||
setDeviceInfo(builder.deviceInfo);
|
||||
setAppid(builder.appid);
|
||||
setTransactionId(builder.transactionId);
|
||||
setMchId(builder.mchId);
|
||||
setOutTradeNo(builder.outTradeNo);
|
||||
setSubAppId(builder.subAppId);
|
||||
setSubMchId(builder.subMchId);
|
||||
setOutRefundNo(builder.outRefundNo);
|
||||
setNonceStr(builder.nonceStr);
|
||||
setTotalFee(builder.totalFee);
|
||||
setSign(builder.sign);
|
||||
setRefundFee(builder.refundFee);
|
||||
setRefundFeeType(builder.refundFeeType);
|
||||
setOpUserId(builder.opUserId);
|
||||
setRefundAccount(builder.refundAccount);
|
||||
}
|
||||
|
||||
public static Builder newBuilder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public String getDeviceInfo() {
|
||||
return this.deviceInfo;
|
||||
}
|
||||
@ -215,4 +237,103 @@ public class WxPayRefundRequest extends WxPayBaseRequest {
|
||||
this.refundAccount = refundAccount;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String deviceInfo;
|
||||
private String appid;
|
||||
private String transactionId;
|
||||
private String mchId;
|
||||
private String outTradeNo;
|
||||
private String subAppId;
|
||||
private String subMchId;
|
||||
private String outRefundNo;
|
||||
private String nonceStr;
|
||||
private Integer totalFee;
|
||||
private String sign;
|
||||
private Integer refundFee;
|
||||
private String refundFeeType;
|
||||
private String opUserId;
|
||||
private String refundAccount;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder deviceInfo(String deviceInfo) {
|
||||
this.deviceInfo = deviceInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder appid(String appid) {
|
||||
this.appid = appid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder transactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder outTradeNo(String outTradeNo) {
|
||||
this.outTradeNo = outTradeNo;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder subAppId(String subAppId) {
|
||||
this.subAppId = subAppId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder subMchId(String subMchId) {
|
||||
this.subMchId = subMchId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder outRefundNo(String outRefundNo) {
|
||||
this.outRefundNo = outRefundNo;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder nonceStr(String nonceStr) {
|
||||
this.nonceStr = nonceStr;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder totalFee(Integer totalFee) {
|
||||
this.totalFee = totalFee;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder sign(String sign) {
|
||||
this.sign = sign;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder refundFee(Integer refundFee) {
|
||||
this.refundFee = refundFee;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder refundFeeType(String refundFeeType) {
|
||||
this.refundFeeType = refundFeeType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder opUserId(String opUserId) {
|
||||
this.opUserId = opUserId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder refundAccount(String refundAccount) {
|
||||
this.refundAccount = refundAccount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WxPayRefundRequest build() {
|
||||
return new WxPayRefundRequest(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import me.chanjar.weixin.common.annotation.Required;
|
@ -1,18 +1,19 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 发送红包请求参数对象
|
||||
* Created by Binary Wang on 2016/9/24.
|
||||
* 发送红包请求参数对象
|
||||
* Created by Binary Wang on 2016/9/24.
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class WxPaySendRedpackRequest extends WxPayBaseRequest{
|
||||
public class WxPaySendRedpackRequest extends WxPayBaseRequest {
|
||||
/**
|
||||
* mch_billno
|
||||
* 商户订单号(每个订单号必须唯一) 组成:mch_id+yyyymmdd+10位一天内不能重复的数字。 接口根据商户订单号支持重入,如出现超时可再调用。
|
||||
*/
|
||||
* mch_billno
|
||||
* 商户订单号(每个订单号必须唯一) 组成:mch_id+yyyymmdd+10位一天内不能重复的数字。 接口根据商户订单号支持重入,如出现超时可再调用。
|
||||
*/
|
||||
@XStreamAlias("mch_billno")
|
||||
private String mchBillNo;
|
||||
|
||||
@ -25,60 +26,60 @@ public class WxPaySendRedpackRequest extends WxPayBaseRequest{
|
||||
private String sendName;
|
||||
|
||||
/**
|
||||
* re_openid
|
||||
* 接受红包的用户 用户在wxappid下的openid
|
||||
* re_openid
|
||||
* 接受红包的用户 用户在wxappid下的openid
|
||||
*/
|
||||
@XStreamAlias("re_openid")
|
||||
private String reOpenid;
|
||||
|
||||
/**
|
||||
* total_amount
|
||||
* 红包总额
|
||||
* total_amount
|
||||
* 红包总额
|
||||
*/
|
||||
@XStreamAlias("total_amount")
|
||||
private Integer totalAmount;
|
||||
|
||||
/**
|
||||
* total_num
|
||||
* 红包发放总人数
|
||||
* total_num
|
||||
* 红包发放总人数
|
||||
*/
|
||||
@XStreamAlias("total_num")
|
||||
private Integer totalNum;
|
||||
|
||||
/**
|
||||
* amt_type
|
||||
* 红包金额设置方式
|
||||
* ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额
|
||||
* 裂变红包必填
|
||||
* amt_type
|
||||
* 红包金额设置方式
|
||||
* ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额
|
||||
* 裂变红包必填
|
||||
*/
|
||||
@XStreamAlias("amt_type")
|
||||
private String amtType;
|
||||
|
||||
/**
|
||||
* wishing
|
||||
* 红包祝福语
|
||||
* wishing
|
||||
* 红包祝福语
|
||||
*/
|
||||
@XStreamAlias("wishing")
|
||||
private String wishing;
|
||||
|
||||
/**
|
||||
* client_ip
|
||||
* 服务器Ip地址
|
||||
* 调用接口的机器Ip地址
|
||||
* client_ip
|
||||
* 服务器Ip地址
|
||||
* 调用接口的机器Ip地址
|
||||
*/
|
||||
@XStreamAlias("client_ip")
|
||||
private String clientIp;
|
||||
|
||||
/**
|
||||
* act_name
|
||||
* 活动名称
|
||||
* act_name
|
||||
* 活动名称
|
||||
*/
|
||||
@XStreamAlias("act_name")
|
||||
private String actName;
|
||||
|
||||
/**
|
||||
* remark
|
||||
* 备注
|
||||
* remark
|
||||
* 备注
|
||||
*/
|
||||
@XStreamAlias("remark")
|
||||
private String remark;
|
@ -1,7 +1,6 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.request;
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
import me.chanjar.weixin.common.annotation.Required;
|
||||
|
||||
/**
|
||||
@ -17,6 +16,7 @@ import me.chanjar.weixin.common.annotation.Required;
|
||||
* <li>描述
|
||||
* </pre>
|
||||
* Created by Binary Wang on 2016/9/25.
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
@ -56,35 +56,35 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
|
||||
* 否
|
||||
* 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 商品描述信息
|
||||
* {
|
||||
* "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")
|
||||
@ -267,6 +267,9 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
|
||||
@XStreamAlias("openid")
|
||||
private String openid;
|
||||
|
||||
public static WxUnifiedOrderRequestBuilder builder() {
|
||||
return new WxUnifiedOrderRequestBuilder();
|
||||
}
|
||||
|
||||
public String getDeviceInfo() {
|
||||
return this.deviceInfo;
|
||||
@ -362,6 +365,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
|
||||
|
||||
/**
|
||||
* 如果配置中已经设置,可以不设置值
|
||||
*
|
||||
* @param notifyURL
|
||||
*/
|
||||
public void setNotifyURL(String notifyURL) {
|
||||
@ -374,6 +378,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
|
||||
|
||||
/**
|
||||
* 如果配置中已经设置,可以不设置值
|
||||
*
|
||||
* @param tradeType 交易类型
|
||||
*/
|
||||
public void setTradeType(String tradeType) {
|
||||
@ -404,10 +409,6 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
public static WxUnifiedOrderRequestBuilder builder() {
|
||||
return new WxUnifiedOrderRequestBuilder();
|
||||
}
|
||||
|
||||
public static class WxUnifiedOrderRequestBuilder {
|
||||
private String appid;
|
||||
private String mchId;
|
@ -1,10 +1,11 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 企业付款查询返回结果
|
||||
* Created by Binary Wang on 2016/10/19.
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
@XStreamAlias("xml")
|
@ -1,10 +1,11 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 企业付款返回结果
|
||||
* Created by Binary Wang on 2016/10/02.
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
@XStreamAlias("xml")
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
@ -61,6 +61,16 @@ public abstract class WxPayBaseResult {
|
||||
*/
|
||||
@XStreamAlias("mch_id")
|
||||
private String mchId;
|
||||
/**
|
||||
* 服务商模式下的子公众账号ID
|
||||
*/
|
||||
@XStreamAlias("appid")
|
||||
private String subAppId;
|
||||
/**
|
||||
* 服务商模式下的子商户号
|
||||
*/
|
||||
@XStreamAlias("sub_mch_id")
|
||||
private String subMchId;
|
||||
/**
|
||||
* 随机字符串
|
||||
*/
|
||||
@ -181,6 +191,22 @@ public abstract class WxPayBaseResult {
|
||||
this.sign = sign;
|
||||
}
|
||||
|
||||
public String getSubAppId() {
|
||||
return subAppId;
|
||||
}
|
||||
|
||||
public void setSubAppId(String subAppId) {
|
||||
this.subAppId = subAppId;
|
||||
}
|
||||
|
||||
public String getSubMchId() {
|
||||
return subMchId;
|
||||
}
|
||||
|
||||
public void setSubMchId(String subMchId) {
|
||||
this.subMchId = subMchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将bean通过保存的xml字符串转换成map
|
||||
*/
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
@ -0,0 +1,392 @@
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.WxPayOrderNotifyCoupon;
|
||||
import com.github.binarywang.wxpay.converter.WxPayOrderNotifyResultConverter;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import me.chanjar.weixin.common.util.BeanUtils;
|
||||
import me.chanjar.weixin.common.util.ToStringUtils;
|
||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付结果通用通知 ,文档见:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
|
||||
*
|
||||
* @author aimilin6688
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 5389718115223345496L;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 设备号
|
||||
* device_info
|
||||
* 否
|
||||
* String(32)
|
||||
* 013467007045764
|
||||
* 微信支付分配的终端设备号,
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("device_info")
|
||||
private String deviceInfo;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 用户标识
|
||||
* openid
|
||||
* 是
|
||||
* String(128)
|
||||
* wxd930ea5d5a258f4f
|
||||
* 用户在商户appid下的唯一标识
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 是否关注公众账号
|
||||
* is_subscribe
|
||||
* 否
|
||||
* String(1)
|
||||
* Y
|
||||
* 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("is_subscribe")
|
||||
private String isSubscribe;
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 交易类型
|
||||
* trade_type
|
||||
* 是
|
||||
* String(16)
|
||||
* JSAPI JSAPI、NATIVE、APP
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("trade_type")
|
||||
private String tradeType;
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 付款银行
|
||||
* bank_type
|
||||
* 是
|
||||
* String(16)
|
||||
* CMC
|
||||
* 银行类型,采用字符串类型的银行标识,银行类型见银行列表
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("bank_type")
|
||||
private String bankType;
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 订单金额
|
||||
* total_fee
|
||||
* 是
|
||||
* Int
|
||||
* 100
|
||||
* 订单总金额,单位为分
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("total_fee")
|
||||
private Integer totalFee;
|
||||
/**
|
||||
* <pre>
|
||||
* 应结订单金额
|
||||
* settlement_total_fee
|
||||
* 否
|
||||
* Int
|
||||
* 100
|
||||
* 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("settlement_total_fee")
|
||||
private Integer settlementTotalFee;
|
||||
/**
|
||||
* <pre>
|
||||
* 货币种类
|
||||
* fee_type
|
||||
* 否
|
||||
* String(8)
|
||||
* CNY
|
||||
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("fee_type")
|
||||
private String feeType;
|
||||
/**
|
||||
* <pre>
|
||||
* 现金支付金额
|
||||
* cash_fee
|
||||
* 是
|
||||
* Int
|
||||
* 100
|
||||
* 现金支付金额订单现金支付金额,详见支付金额
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("cash_fee")
|
||||
private Integer cashFee;
|
||||
/**
|
||||
* <pre>
|
||||
* 现金支付货币类型
|
||||
* cash_fee_type
|
||||
* 否
|
||||
* String(16)
|
||||
* CNY
|
||||
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("cash_fee_type")
|
||||
private String cashFeeType;
|
||||
/**
|
||||
* <pre>
|
||||
* 总代金券金额
|
||||
* coupon_fee
|
||||
* 否
|
||||
* Int
|
||||
* 10
|
||||
* 代金券金额<=订单金额,订单金额-代金券金额=现金支付金额,详见支付金额
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("coupon_fee")
|
||||
private Integer couponFee;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 代金券使用数量
|
||||
* coupon_count
|
||||
* 否
|
||||
* Int
|
||||
* 1
|
||||
* 代金券使用数量
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("coupon_count")
|
||||
private Integer couponCount;
|
||||
|
||||
private List<WxPayOrderNotifyCoupon> couponList;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付订单号
|
||||
* transaction_id
|
||||
* 是
|
||||
* String(32)
|
||||
* 1217752501201407033233368018
|
||||
* 微信支付订单号
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("transaction_id")
|
||||
private String transactionId;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 商户订单号
|
||||
* out_trade_no
|
||||
* 是
|
||||
* String(32)
|
||||
* 1212321211201407033568112322
|
||||
* 商户系统的订单号,与请求一致。
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("out_trade_no")
|
||||
private String outTradeNo;
|
||||
/**
|
||||
* <pre>
|
||||
* 商家数据包
|
||||
* attach
|
||||
* 否
|
||||
* String(128)
|
||||
* 123456
|
||||
* 商家数据包,原样返回
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("attach")
|
||||
private String attach;
|
||||
/**
|
||||
* <pre>
|
||||
* 支付完成时间
|
||||
* time_end
|
||||
* 是
|
||||
* String(14)
|
||||
* 20141030133525
|
||||
* 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
|
||||
* </pre>
|
||||
*/
|
||||
@XStreamAlias("time_end")
|
||||
private String timeEnd;
|
||||
|
||||
public static WxPayOrderNotifyResult fromXML(String xmlString) {
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.processAnnotations(WxPayOrderNotifyResult.class);
|
||||
xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider()));
|
||||
WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlString);
|
||||
result.setXmlString(xmlString);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Integer getCouponCount() {
|
||||
return couponCount;
|
||||
}
|
||||
|
||||
public void setCouponCount(Integer couponCount) {
|
||||
this.couponCount = couponCount;
|
||||
}
|
||||
|
||||
public List<WxPayOrderNotifyCoupon> getCouponList() {
|
||||
return couponList;
|
||||
}
|
||||
|
||||
public void setCouponList(List<WxPayOrderNotifyCoupon> couponList) {
|
||||
this.couponList = couponList;
|
||||
}
|
||||
|
||||
public String getDeviceInfo() {
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
public void setDeviceInfo(String deviceInfo) {
|
||||
this.deviceInfo = deviceInfo;
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
public String getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
|
||||
public void setIsSubscribe(String isSubscribe) {
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public String getTradeType() {
|
||||
return tradeType;
|
||||
}
|
||||
|
||||
public void setTradeType(String tradeType) {
|
||||
this.tradeType = tradeType;
|
||||
}
|
||||
|
||||
public String getBankType() {
|
||||
return bankType;
|
||||
}
|
||||
|
||||
public void setBankType(String bankType) {
|
||||
this.bankType = bankType;
|
||||
}
|
||||
|
||||
public Integer getTotalFee() {
|
||||
return totalFee;
|
||||
}
|
||||
|
||||
public void setTotalFee(Integer totalFee) {
|
||||
this.totalFee = totalFee;
|
||||
}
|
||||
|
||||
public Integer getSettlementTotalFee() {
|
||||
return settlementTotalFee;
|
||||
}
|
||||
|
||||
public void setSettlementTotalFee(Integer settlementTotalFee) {
|
||||
this.settlementTotalFee = settlementTotalFee;
|
||||
}
|
||||
|
||||
public String getFeeType() {
|
||||
return feeType;
|
||||
}
|
||||
|
||||
public void setFeeType(String feeType) {
|
||||
this.feeType = feeType;
|
||||
}
|
||||
|
||||
public Integer getCashFee() {
|
||||
return cashFee;
|
||||
}
|
||||
|
||||
public void setCashFee(Integer cashFee) {
|
||||
this.cashFee = cashFee;
|
||||
}
|
||||
|
||||
public String getCashFeeType() {
|
||||
return cashFeeType;
|
||||
}
|
||||
|
||||
public void setCashFeeType(String cashFeeType) {
|
||||
this.cashFeeType = cashFeeType;
|
||||
}
|
||||
|
||||
public Integer getCouponFee() {
|
||||
return couponFee;
|
||||
}
|
||||
|
||||
public void setCouponFee(Integer couponFee) {
|
||||
this.couponFee = couponFee;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public void setOutTradeNo(String outTradeNo) {
|
||||
this.outTradeNo = outTradeNo;
|
||||
}
|
||||
|
||||
public String getAttach() {
|
||||
return attach;
|
||||
}
|
||||
|
||||
public void setAttach(String attach) {
|
||||
this.attach = attach;
|
||||
}
|
||||
|
||||
public String getTimeEnd() {
|
||||
return timeEnd;
|
||||
}
|
||||
|
||||
public void setTimeEnd(String timeEnd) {
|
||||
this.timeEnd = timeEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> toMap() {
|
||||
Map<String, String> resultMap = BeanUtils.xmlBean2Map(this);
|
||||
if (this.getCouponCount() != null && this.getCouponCount() > 0) {
|
||||
for (int i = 0; i < this.getCouponCount(); i++) {
|
||||
WxPayOrderNotifyCoupon coupon = couponList.get(i);
|
||||
resultMap.putAll(coupon.toMap(i));
|
||||
}
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringUtils.toSimpleString(this);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
@ -396,7 +396,7 @@ public class WxPayOrderQueryResult extends WxPayBaseResult {
|
||||
if (this.couponCount != null && this.couponCount > 0) {
|
||||
this.coupons = Lists.newArrayList();
|
||||
XmlPath xmlPath = new XmlPath(this.getXmlString());
|
||||
for (int i = 0; i < this.couponCount; i++){
|
||||
for (int i = 0; i < this.couponCount; i++) {
|
||||
this.coupons.add(new Coupon(this.getXmlValue(xmlPath, "xml.coupon_type_" + i, String.class),
|
||||
this.getXmlValue(xmlPath, "xml.coupon_id_" + i, String.class),
|
||||
this.getXmlValue(xmlPath, "xml.coupon_fee_" + i, Integer.class)));
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
@ -186,7 +186,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
|
||||
|
||||
/**
|
||||
* 组装生成退款记录属性的内容
|
||||
*/
|
||||
*/
|
||||
public void composeRefundRecords() {
|
||||
if (this.refundCount != null && this.refundCount > 0) {
|
||||
this.refundRecords = Lists.newArrayList();
|
@ -1,19 +1,19 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
|
||||
import java.io.Serializable;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付-申请退款返回结果
|
||||
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
|
||||
* </pre>
|
||||
* @author liukaitj
|
||||
*
|
||||
* @author liukaitj
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class WxPayRefundResult extends WxPayBaseResult implements Serializable{
|
||||
public class WxPayRefundResult extends WxPayBaseResult implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@XStreamAlias("device_info")
|
@ -1,14 +1,14 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
|
||||
import java.io.Serializable;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 向微信用户个人发现金红包返回结果
|
||||
* https://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5
|
||||
* @author kane
|
||||
*
|
||||
* @author kane
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class WxPaySendRedpackResult extends WxPayBaseResult implements Serializable {
|
@ -1,11 +1,11 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"返回的结果
|
||||
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
|
||||
* 统一下单(详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
|
||||
* </pre>
|
||||
*
|
||||
* @author chanjarster
|
@ -0,0 +1,157 @@
|
||||
package com.github.binarywang.wxpay.config;
|
||||
|
||||
import org.apache.http.ssl.SSLContexts;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.KeyStore;
|
||||
|
||||
/**
|
||||
* 微信支付配置
|
||||
*
|
||||
* @author Binary Wang (https://github.com/binarywang)
|
||||
*/
|
||||
public class WxPayConfig {
|
||||
private String appId;
|
||||
private String subAppId;
|
||||
private String mchId;
|
||||
private String mchKey;
|
||||
private String subMchId;
|
||||
private String notifyUrl;
|
||||
private String tradeType;
|
||||
private SSLContext sslContext;
|
||||
private String keyPath;
|
||||
|
||||
public void setNotifyUrl(String notifyUrl) {
|
||||
this.notifyUrl = notifyUrl;
|
||||
}
|
||||
|
||||
public void setTradeType(String tradeType) {
|
||||
this.tradeType = tradeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置证书
|
||||
* @param keyPath apiclient_cert.p12的文件的绝对路径
|
||||
*/
|
||||
public void setKeyPath(String keyPath) {
|
||||
this.keyPath = keyPath;
|
||||
}
|
||||
|
||||
public String getKeyPath() {
|
||||
return keyPath;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public void setSubAppId(String subAppId) {
|
||||
this.subAppId = subAppId;
|
||||
}
|
||||
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
public void setMchKey(String mchKey) {
|
||||
this.mchKey = mchKey;
|
||||
}
|
||||
|
||||
public void setSubMchId(String subMchId) {
|
||||
this.subMchId = subMchId;
|
||||
}
|
||||
|
||||
public void setSslContext(SSLContext sslContext) {
|
||||
this.sslContext = sslContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
public String getMchId() {
|
||||
return this.mchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户密钥
|
||||
*/
|
||||
public String getMchKey() {
|
||||
return this.mchKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公众号appid
|
||||
*/
|
||||
public String getAppId() {
|
||||
return this.appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务商模式下的子商户公众账号ID
|
||||
*/
|
||||
public String getSubAppId() {
|
||||
return this.subAppId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务商模式下的子商户号
|
||||
*/
|
||||
public String getSubMchId() {
|
||||
return this.subMchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付异步回掉地址,通知url必须为直接可访问的url,不能携带参数。
|
||||
*/
|
||||
public String getNotifyUrl() {
|
||||
return this.notifyUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 交易类型
|
||||
* <pre>
|
||||
* JSAPI--公众号支付
|
||||
* NATIVE--原生扫码支付
|
||||
* APP--app支付
|
||||
* </pre>
|
||||
*/
|
||||
public String getTradeType() {
|
||||
return this.tradeType;
|
||||
}
|
||||
|
||||
public SSLContext getSslContext() {
|
||||
return this.sslContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付是否使用仿真测试环境
|
||||
* 默认不使用
|
||||
*/
|
||||
public boolean useSandboxForWxPay() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public SSLContext initSSLContext() {
|
||||
if (null == mchId) {
|
||||
throw new IllegalArgumentException("请確保mchId已設置");
|
||||
}
|
||||
|
||||
File file = new File(this.keyPath);
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("证书文件:【" + file.getPath() + "】不存在!");
|
||||
}
|
||||
|
||||
try {
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
KeyStore keystore = KeyStore.getInstance("PKCS12");
|
||||
char[] partnerId2charArray = mchId.toCharArray();
|
||||
keystore.load(inputStream, partnerId2charArray);
|
||||
this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build();
|
||||
return this.sslContext;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("证书文件有问题,请核实!", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,130 +1,129 @@
|
||||
package me.chanjar.weixin.mp.bean.pay;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter;
|
||||
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.mapper.Mapper;
|
||||
|
||||
import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderNotifyResult;
|
||||
|
||||
public class WxPayOrderNotifyResultConverter extends AbstractReflectionConverter {
|
||||
|
||||
public WxPayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
|
||||
super(mapper, reflectionProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean canConvert(Class type) {
|
||||
return type.equals(WxPayOrderNotifyResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(Object original, HierarchicalStreamWriter writer, MarshallingContext context) {
|
||||
super.marshal(original, writer, context);
|
||||
WxPayOrderNotifyResult obj = (WxPayOrderNotifyResult) original;
|
||||
List<WxPayOrderNotifyCoupon> list = obj.getCouponList();
|
||||
if (list == null || list.size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
WxPayOrderNotifyCoupon coupon = list.get(i);
|
||||
writer.startNode("coupon_id_" + i);
|
||||
writer.setValue(coupon.getCouponId());
|
||||
writer.endNode();
|
||||
writer.startNode("coupon_type_" + i);
|
||||
writer.setValue(coupon.getCouponType());
|
||||
writer.endNode();
|
||||
writer.startNode("coupon_fee_" + i);
|
||||
writer.setValue(coupon.getCouponFee() + "");
|
||||
writer.endNode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshallField(MarshallingContext context, Object newObj, Field field) {
|
||||
if (field.getName().equals("couponList")) {
|
||||
return;
|
||||
} else {
|
||||
super.marshallField(context, newObj, field);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
|
||||
WxPayOrderNotifyResult obj = new WxPayOrderNotifyResult();
|
||||
|
||||
List<Field> fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields()));
|
||||
fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));
|
||||
Map<String, Field> fieldMap = getFieldMap(fields);
|
||||
|
||||
List<WxPayOrderNotifyCoupon> coupons = new ArrayList<>(10);
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
if (fieldMap.containsKey(reader.getNodeName())) {
|
||||
Field field = fieldMap.get(reader.getNodeName());
|
||||
setFieldValue(context, obj, field);
|
||||
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_id_")) {
|
||||
String id = (String) context.convertAnother(obj, String.class);
|
||||
getIndex(coupons, reader.getNodeName()).setCouponId(id);
|
||||
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_type_")) {
|
||||
String type = (String) context.convertAnother(obj, String.class);
|
||||
getIndex(coupons, reader.getNodeName()).setCouponType(type);
|
||||
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_fee_")) {
|
||||
Integer fee = (Integer) context.convertAnother(obj, Integer.class);
|
||||
getIndex(coupons, reader.getNodeName()).setCouponFee(fee);
|
||||
}
|
||||
reader.moveUp();
|
||||
}
|
||||
|
||||
obj.setCouponList(coupons);
|
||||
return obj;
|
||||
}
|
||||
|
||||
private void setFieldValue(UnmarshallingContext context, WxPayOrderNotifyResult obj, Field field) {
|
||||
Object val = context.convertAnother(obj, field.getType());
|
||||
try {
|
||||
if (val != null) {
|
||||
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
|
||||
pd.getWriteMethod().invoke(obj, val);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Field> getFieldMap(List<Field> fields) {
|
||||
Map<String, Field> fieldMap = Maps.uniqueIndex(fields, new Function<Field, String>() {
|
||||
@Override
|
||||
public String apply(Field field) {
|
||||
if (field.isAnnotationPresent(XStreamAlias.class)) {
|
||||
return field.getAnnotation(XStreamAlias.class).value();
|
||||
}
|
||||
return field.getName();
|
||||
}
|
||||
});
|
||||
return fieldMap;
|
||||
}
|
||||
|
||||
private WxPayOrderNotifyCoupon getIndex(List<WxPayOrderNotifyCoupon> coupons, String nodeName) {
|
||||
Integer index = Integer.valueOf(StringUtils.substring(nodeName, nodeName.lastIndexOf("_") + 1));
|
||||
if (index >= coupons.size() || coupons.get(index) == null) {
|
||||
coupons.add(index, new WxPayOrderNotifyCoupon());
|
||||
}
|
||||
return coupons.get(index);
|
||||
}
|
||||
}
|
||||
package com.github.binarywang.wxpay.converter;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.WxPayOrderNotifyCoupon;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayOrderNotifyResult;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter;
|
||||
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.mapper.Mapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class WxPayOrderNotifyResultConverter extends AbstractReflectionConverter {
|
||||
|
||||
public WxPayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
|
||||
super(mapper, reflectionProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean canConvert(Class type) {
|
||||
return type.equals(WxPayOrderNotifyResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(Object original, HierarchicalStreamWriter writer, MarshallingContext context) {
|
||||
super.marshal(original, writer, context);
|
||||
WxPayOrderNotifyResult obj = (WxPayOrderNotifyResult) original;
|
||||
List<WxPayOrderNotifyCoupon> list = obj.getCouponList();
|
||||
if (list == null || list.size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
WxPayOrderNotifyCoupon coupon = list.get(i);
|
||||
writer.startNode("coupon_id_" + i);
|
||||
writer.setValue(coupon.getCouponId());
|
||||
writer.endNode();
|
||||
writer.startNode("coupon_type_" + i);
|
||||
writer.setValue(coupon.getCouponType());
|
||||
writer.endNode();
|
||||
writer.startNode("coupon_fee_" + i);
|
||||
writer.setValue(coupon.getCouponFee() + "");
|
||||
writer.endNode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void marshallField(MarshallingContext context, Object newObj, Field field) {
|
||||
if (field.getName().equals("couponList")) {
|
||||
return;
|
||||
} else {
|
||||
super.marshallField(context, newObj, field);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
|
||||
WxPayOrderNotifyResult obj = new WxPayOrderNotifyResult();
|
||||
|
||||
List<Field> fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields()));
|
||||
fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));
|
||||
Map<String, Field> fieldMap = getFieldMap(fields);
|
||||
|
||||
List<WxPayOrderNotifyCoupon> coupons = new ArrayList<>(10);
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
if (fieldMap.containsKey(reader.getNodeName())) {
|
||||
Field field = fieldMap.get(reader.getNodeName());
|
||||
setFieldValue(context, obj, field);
|
||||
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_id_")) {
|
||||
String id = (String) context.convertAnother(obj, String.class);
|
||||
getIndex(coupons, reader.getNodeName()).setCouponId(id);
|
||||
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_type_")) {
|
||||
String type = (String) context.convertAnother(obj, String.class);
|
||||
getIndex(coupons, reader.getNodeName()).setCouponType(type);
|
||||
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_fee_")) {
|
||||
Integer fee = (Integer) context.convertAnother(obj, Integer.class);
|
||||
getIndex(coupons, reader.getNodeName()).setCouponFee(fee);
|
||||
}
|
||||
reader.moveUp();
|
||||
}
|
||||
|
||||
obj.setCouponList(coupons);
|
||||
return obj;
|
||||
}
|
||||
|
||||
private void setFieldValue(UnmarshallingContext context, WxPayOrderNotifyResult obj, Field field) {
|
||||
Object val = context.convertAnother(obj, field.getType());
|
||||
try {
|
||||
if (val != null) {
|
||||
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
|
||||
pd.getWriteMethod().invoke(obj, val);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Field> getFieldMap(List<Field> fields) {
|
||||
Map<String, Field> fieldMap = Maps.uniqueIndex(fields, new Function<Field, String>() {
|
||||
@Override
|
||||
public String apply(Field field) {
|
||||
if (field.isAnnotationPresent(XStreamAlias.class)) {
|
||||
return field.getAnnotation(XStreamAlias.class).value();
|
||||
}
|
||||
return field.getName();
|
||||
}
|
||||
});
|
||||
return fieldMap;
|
||||
}
|
||||
|
||||
private WxPayOrderNotifyCoupon getIndex(List<WxPayOrderNotifyCoupon> coupons, String nodeName) {
|
||||
Integer index = Integer.valueOf(StringUtils.substring(nodeName, nodeName.lastIndexOf("_") + 1));
|
||||
if (index >= coupons.size() || coupons.get(index) == null) {
|
||||
coupons.add(index, new WxPayOrderNotifyCoupon());
|
||||
}
|
||||
return coupons.get(index);
|
||||
}
|
||||
}
|
@ -1,23 +1,26 @@
|
||||
package me.chanjar.weixin.mp.api;
|
||||
package com.github.binarywang.wxpay.service;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.mp.bean.pay.request.*;
|
||||
import me.chanjar.weixin.mp.bean.pay.result.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付相关接口
|
||||
* Created by Binary Wang on 2016/7/28.
|
||||
* </pre>
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
public interface WxMpPayService {
|
||||
public interface WxPayService {
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
|
||||
* 查询订单(详见https://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
|
||||
* 该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
|
||||
* 需要调用查询接口的情况:
|
||||
* ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
|
||||
@ -49,7 +52,7 @@ public interface WxMpPayService {
|
||||
WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
|
||||
* 统一下单(详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
|
||||
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
|
||||
* 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder
|
||||
*
|
||||
@ -65,6 +68,16 @@ public interface WxMpPayService {
|
||||
*/
|
||||
Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取配置
|
||||
*/
|
||||
WxPayConfig getConfig();
|
||||
|
||||
/**
|
||||
* 设置配置对象
|
||||
*/
|
||||
void setConfig(WxPayConfig config);
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付-申请退款
|
||||
@ -81,7 +94,8 @@ public interface WxMpPayService {
|
||||
* <pre>
|
||||
* 微信支付-查询退款
|
||||
* 应用场景:
|
||||
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
|
||||
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,
|
||||
* 银行卡支付的退款3个工作日后重新查询退款状态。
|
||||
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
|
||||
* 接口链接:https://api.mch.weixin.qq.com/pay/refundquery
|
||||
* </pre>
|
||||
@ -93,11 +107,12 @@ public interface WxMpPayService {
|
||||
* @param refundId 微信退款单号
|
||||
* @return 退款信息
|
||||
*/
|
||||
WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId) throws WxErrorException;
|
||||
WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId)
|
||||
throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 读取支付结果通知
|
||||
* 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
|
||||
* 详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
|
||||
*/
|
||||
WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException;
|
||||
|
@ -1,20 +1,21 @@
|
||||
package me.chanjar.weixin.mp.api.impl;
|
||||
package com.github.binarywang.wxpay.service.impl;
|
||||
|
||||
import com.github.binarywang.utils.qrcode.QrcodeUtils;
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.google.common.collect.Maps;
|
||||
import jodd.http.HttpRequest;
|
||||
import jodd.http.HttpResponse;
|
||||
import me.chanjar.weixin.common.bean.result.WxError;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.BeanUtils;
|
||||
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
|
||||
import me.chanjar.weixin.mp.api.WxMpPayService;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.pay.request.*;
|
||||
import me.chanjar.weixin.mp.bean.pay.result.*;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.CharEncoding;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
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.conn.ssl.DefaultHostnameVerifier;
|
||||
@ -28,7 +29,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -36,28 +37,31 @@ import java.util.*;
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
public class WxPayServiceImpl implements WxPayService {
|
||||
|
||||
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
|
||||
private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"};
|
||||
private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS", "REFUND_SOURCE_UNSETTLED_FUNDS"};
|
||||
private static final String[] BILL_TYPE = new String[]{"ALL","REFUND","SUCCESS"};;
|
||||
private static final String[] BILL_TYPE = new String[]{"ALL", "REFUND", "SUCCESS"};
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
private WxMpService wxMpService;
|
||||
|
||||
public WxMpPayServiceImpl(WxMpService wxMpService) {
|
||||
this.wxMpService = wxMpService;
|
||||
private WxPayConfig config;
|
||||
|
||||
@Override
|
||||
public WxPayConfig getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
private WxMpConfigStorage getConfig() {
|
||||
return wxMpService.getWxMpConfigStorage();
|
||||
@Override
|
||||
public void setConfig(WxPayConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private String getPayBaseUrl(){
|
||||
if(this.getConfig().useSandboxForWxPay()){
|
||||
private String getPayBaseUrl() {
|
||||
if (this.getConfig().useSandboxForWxPay()) {
|
||||
return PAY_BASE_URL + "/sandboxnew";
|
||||
}
|
||||
|
||||
return PAY_BASE_URL;
|
||||
}
|
||||
|
||||
@ -65,22 +69,27 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException {
|
||||
this.initRequest(request);
|
||||
if (StringUtils.isBlank(request.getOpUserId())) {
|
||||
request.setOpUserId(this.getConfig().getPartnerId());
|
||||
request.setOpUserId(this.getConfig().getMchId());
|
||||
}
|
||||
|
||||
this.checkParameters(request);
|
||||
request.setSign(this.createSign(request));
|
||||
|
||||
String url = this.getPayBaseUrl() + "/secapi/pay/refund";
|
||||
String responseContent = this.executeWithKey(url, request.toXML());
|
||||
String responseContent = this.postWithKey(url, request.toXML());
|
||||
WxPayRefundResult result = WxPayRefundResult.fromXML(responseContent, WxPayRefundResult.class);
|
||||
this.checkResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId) throws WxErrorException {
|
||||
if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo) && StringUtils.isBlank(outRefundNo) && StringUtils.isBlank(refundId)) ||
|
||||
(StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo) && StringUtils.isNotBlank(outRefundNo) && StringUtils.isNotBlank(refundId))) {
|
||||
public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo,
|
||||
String outRefundNo, String refundId)
|
||||
throws WxErrorException {
|
||||
if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo)
|
||||
&& StringUtils.isBlank(outRefundNo) && StringUtils.isBlank(refundId)) ||
|
||||
(StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo)
|
||||
&& StringUtils.isNotBlank(outRefundNo) && StringUtils.isNotBlank(refundId))) {
|
||||
throw new IllegalArgumentException("transaction_id , out_trade_no,out_refund_no, refund_id 必须四选一");
|
||||
}
|
||||
|
||||
@ -93,18 +102,17 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
request.setSign(this.createSign(request));
|
||||
|
||||
String url = this.getPayBaseUrl() + "/pay/refundquery";
|
||||
String responseContent = this.executeRequest(url, request.toXML());
|
||||
String responseContent = this.post(url, request.toXML());
|
||||
WxPayRefundQueryResult result = WxPayRefundQueryResult.fromXML(responseContent, WxPayRefundQueryResult.class);
|
||||
result.composeRefundRecords();
|
||||
this.checkResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private void checkResult(WxPayBaseResult result) throws WxErrorException {
|
||||
//校验返回结果签名
|
||||
Map<String, String> map = result.toMap();
|
||||
if (result.getSign() != null &&!this.checkSign(map)) {
|
||||
if (result.getSign() != null && !this.checkSign(map)) {
|
||||
log.debug("校验结果签名失败,参数:{}", map);
|
||||
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build());
|
||||
}
|
||||
@ -112,12 +120,28 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
//校验结果是否成功
|
||||
if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode())
|
||||
|| !"SUCCESS".equalsIgnoreCase(result.getResultCode())) {
|
||||
WxError error = WxError.newBuilder().setErrorCode(-1)
|
||||
.setErrorMsg("返回代码: " + result.getReturnCode() + ", 返回信息: "
|
||||
+ result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: "
|
||||
+ result.getErrCode() + ", 错误详情: " + result.getErrCodeDes())
|
||||
StringBuilder errorMsg = new StringBuilder();
|
||||
if (result.getReturnCode() != null) {
|
||||
errorMsg.append("返回代码:" + result.getReturnCode());
|
||||
}
|
||||
if (result.getReturnMsg() != null) {
|
||||
errorMsg.append(",返回信息:" + result.getReturnMsg());
|
||||
}
|
||||
if (result.getResultCode() != null) {
|
||||
errorMsg.append(",结果代码:" + result.getResultCode());
|
||||
}
|
||||
if (result.getErrCode() != null) {
|
||||
errorMsg.append(",错误代码:" + result.getErrCode());
|
||||
}
|
||||
if (result.getErrCodeDes() != null) {
|
||||
errorMsg.append(",错误详情:" + result.getErrCodeDes());
|
||||
}
|
||||
|
||||
WxError error = WxError.newBuilder()
|
||||
.setErrorCode(-1)
|
||||
.setErrorMsg(errorMsg.toString())
|
||||
.build();
|
||||
log.error("结果业务代码异常,参数:{},详细:{}", map, error);
|
||||
log.error("\n结果业务代码异常,返回結果:{},\n{}", map, error);
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
}
|
||||
@ -129,8 +153,9 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
throw new IllegalArgumentException("tar_type值如果存在,只能为GZIP");
|
||||
}
|
||||
|
||||
if ( !ArrayUtils.contains(BILL_TYPE, request.getBillType())) {
|
||||
throw new IllegalArgumentException("bill_tpye目前必须为" + Arrays.toString(BILL_TYPE) + "其中之一,实际值:" + request.getBillType());
|
||||
if (!ArrayUtils.contains(BILL_TYPE, request.getBillType())) {
|
||||
throw new IllegalArgumentException("bill_tpye目前必须为" + Arrays.toString(BILL_TYPE)
|
||||
+ "其中之一,实际值:" + request.getBillType());
|
||||
}
|
||||
|
||||
}
|
||||
@ -140,7 +165,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
if (StringUtils.isNotBlank(request.getRefundAccount())) {
|
||||
if (!ArrayUtils.contains(REFUND_ACCOUNT, request.getRefundAccount())) {
|
||||
throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT) + "其中之一,实际值:" + request.getRefundAccount());
|
||||
throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT)
|
||||
+ "其中之一,实际值:" + request.getRefundAccount());
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +178,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
@Override
|
||||
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException {
|
||||
try {
|
||||
log.trace("微信支付回调参数详细:{}", xmlData);
|
||||
log.debug("微信支付回调参数详细:{}", xmlData);
|
||||
WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
|
||||
log.debug("微信支付回调结果对象:{}", result);
|
||||
this.checkResult(result);
|
||||
@ -177,7 +203,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
//裂变红包
|
||||
url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack";
|
||||
}
|
||||
String responseContent = this.executeWithKey(url, request.toXML());
|
||||
String responseContent = this.postWithKey(url, request.toXML());
|
||||
WxPaySendRedpackResult result = WxPaySendRedpackResult.fromXML(responseContent, WxPaySendRedpackResult.class);
|
||||
//毋须校验,因为没有返回签名信息
|
||||
// this.checkResult(result);
|
||||
@ -193,7 +219,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
request.setSign(this.createSign(request));
|
||||
|
||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo";
|
||||
String responseContent = this.executeWithKey(url, request.toXML());
|
||||
String responseContent = this.postWithKey(url, request.toXML());
|
||||
WxPayRedpackQueryResult result = WxPayRedpackQueryResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
|
||||
this.checkResult(result);
|
||||
return result;
|
||||
@ -213,7 +239,11 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
request.setSign(this.createSign(request));
|
||||
|
||||
String url = this.getPayBaseUrl() + "/pay/orderquery";
|
||||
String responseContent = this.executeRequest(url, request.toXML());
|
||||
String responseContent = this.post(url, request.toXML());
|
||||
if (StringUtils.isBlank(responseContent)) {
|
||||
throw new WxErrorException(WxError.newBuilder().setErrorMsg("无响应结果").build());
|
||||
}
|
||||
|
||||
WxPayOrderQueryResult result = WxPayOrderQueryResult.fromXML(responseContent, WxPayOrderQueryResult.class);
|
||||
result.composeCoupons();
|
||||
this.checkResult(result);
|
||||
@ -223,17 +253,17 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
@Override
|
||||
public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException {
|
||||
if (StringUtils.isBlank(outTradeNo)) {
|
||||
throw new IllegalArgumentException("out_trade_no 不能为空");
|
||||
throw new IllegalArgumentException("out_trade_no不能为空");
|
||||
}
|
||||
|
||||
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest();
|
||||
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
|
||||
initRequest(request);
|
||||
this.initRequest(request);
|
||||
request.setSign(this.createSign(request));
|
||||
|
||||
String url = this.getPayBaseUrl() + "/pay/closeorder";
|
||||
String responseContent = this.executeRequest(url, request.toXML());
|
||||
WxPayOrderCloseResult result = WxPayOrderCloseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
|
||||
String responseContent = this.post(url, request.toXML());
|
||||
WxPayOrderCloseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
|
||||
this.checkResult(result);
|
||||
|
||||
return result;
|
||||
@ -242,23 +272,20 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
@Override
|
||||
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request)
|
||||
throws WxErrorException {
|
||||
|
||||
this.initRequest(request);
|
||||
if (StringUtils.isBlank(request.getNotifyURL())) {
|
||||
request.setNotifyURL(getConfig().getNotifyURL());
|
||||
request.setNotifyURL(getConfig().getNotifyUrl());
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(request.getTradeType())) {
|
||||
request.setTradeType(getConfig().getTradeType());
|
||||
}
|
||||
checkParameters(request);//校验参数
|
||||
|
||||
this.checkParameters(request);//校验参数
|
||||
request.setSign(this.createSign(request));
|
||||
|
||||
String url = this.getPayBaseUrl() + "/pay/unifiedorder";
|
||||
String xmlParam = request.toXML();
|
||||
log.debug("微信统一下单接口,URL:{},参数:{}", url, xmlParam);
|
||||
|
||||
String responseContent = this.executeRequest(url, xmlParam);
|
||||
log.debug("微信统一下单接口,URL:{},结果:{}", url, responseContent);
|
||||
String responseContent = this.post(url, request.toXML());
|
||||
WxPayUnifiedOrderResult result = WxPayUnifiedOrderResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
|
||||
this.checkResult(result);
|
||||
return result;
|
||||
@ -266,11 +293,21 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
private void initRequest(WxPayBaseRequest request) {
|
||||
if (StringUtils.isBlank(request.getAppid())) {
|
||||
request.setAppid(getConfig().getAppId());
|
||||
request.setAppid(this.getConfig().getAppId());
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(request.getMchId())) {
|
||||
request.setMchId(getConfig().getPartnerId());
|
||||
request.setMchId(this.getConfig().getMchId());
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(request.getSubAppId())) {
|
||||
request.setSubAppId(this.getConfig().getSubAppId());
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(request.getSubMchId())) {
|
||||
request.setSubMchId(this.getConfig().getSubMchId());
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(request.getNonceStr())) {
|
||||
request.setNonceStr(String.valueOf(System.currentTimeMillis()));
|
||||
}
|
||||
@ -297,13 +334,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request);
|
||||
String prepayId = unifiedOrderResult.getPrepayId();
|
||||
if (StringUtils.isBlank(prepayId)) {
|
||||
throw new RuntimeException(String.format("Failed to get prepay id due to error code '%s'(%s).",
|
||||
throw new RuntimeException(String.format("无法获取prepay id,错误代码: '%s',信息:%s。",
|
||||
unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes()));
|
||||
}
|
||||
|
||||
Map<String, String> payInfo = new HashMap<>();
|
||||
payInfo.put("appId", getConfig().getAppId());
|
||||
// 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
|
||||
// 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。
|
||||
// 但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
|
||||
payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
|
||||
payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis()));
|
||||
payInfo.put("package", "prepay_id=" + prepayId);
|
||||
@ -323,7 +361,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers";
|
||||
|
||||
String responseContent = this.executeWithKey(url, request.toXML());
|
||||
String responseContent = this.postWithKey(url, request.toXML());
|
||||
WxEntPayResult result = WxEntPayResult.fromXML(responseContent, WxEntPayResult.class);
|
||||
this.checkResult(result);
|
||||
return result;
|
||||
@ -336,7 +374,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
request.setSign(this.createSign(request));
|
||||
|
||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo";
|
||||
String responseContent = this.executeWithKey(url, request.toXML());
|
||||
String responseContent = this.postWithKey(url, request.toXML());
|
||||
WxEntPayQueryResult result = WxEntPayQueryResult.fromXML(responseContent, WxEntPayQueryResult.class);
|
||||
this.checkResult(result);
|
||||
return result;
|
||||
@ -348,7 +386,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?");
|
||||
Map<String, String> params = Maps.newHashMap();
|
||||
params.put("appid", this.getConfig().getAppId());
|
||||
params.put("mch_id", this.getConfig().getPartnerId());
|
||||
params.put("mch_id", this.getConfig().getMchId());
|
||||
params.put("product_id", productId);
|
||||
params.put("time_stamp", String.valueOf(System.currentTimeMillis()));
|
||||
params.put("nonce_str", String.valueOf(System.currentTimeMillis()));
|
||||
@ -383,7 +421,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
request.setSign(this.createSign(request));
|
||||
|
||||
String url = this.getPayBaseUrl() + "/payitil/report";
|
||||
String responseContent = this.wxMpService.post(url, request.toXML());
|
||||
String responseContent = this.post(url, request.toXML());
|
||||
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
|
||||
this.checkResult(result);
|
||||
}
|
||||
@ -401,7 +439,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
String url = this.getPayBaseUrl() + "/pay/downloadbill";
|
||||
//TODO 返回的内容可能是文件流,也有可能是xml,需要区分对待
|
||||
String responseContent = this.wxMpService.post(url, request.toXML());
|
||||
String responseContent = this.post(url, request.toXML());
|
||||
|
||||
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
|
||||
this.checkResult(result);
|
||||
@ -409,42 +447,41 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String executeRequest(String url, String requestStr) throws WxErrorException {
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
if (this.wxMpService.getHttpProxy() != null) {
|
||||
httpPost.setConfig(RequestConfig.custom().setProxy(this.wxMpService.getHttpProxy()).build());
|
||||
private String post(String url, String xmlParam) {
|
||||
String requestString = null;
|
||||
try {
|
||||
requestString = new String(xmlParam.getBytes(CharEncoding.UTF_8), CharEncoding.ISO_8859_1);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try (CloseableHttpClient httpclient = HttpClients.custom().build()) {
|
||||
httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1")));
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
|
||||
String result = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
|
||||
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result);
|
||||
return result;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", url, requestStr, e.getMessage());
|
||||
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e);
|
||||
} finally {
|
||||
httpPost.releaseConnection();
|
||||
HttpRequest request = HttpRequest.post(url).body(requestString);
|
||||
HttpResponse response = request.send();
|
||||
String responseString = null;
|
||||
try {
|
||||
responseString = new String(response.bodyText().getBytes(CharEncoding.ISO_8859_1), CharEncoding.UTF_8);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, xmlParam, responseString);
|
||||
return responseString;
|
||||
}
|
||||
|
||||
private String executeWithKey(String url, String requestStr) throws WxErrorException {
|
||||
/**
|
||||
* 由于暂时未找到使用jodd-http实现证书配置的办法,故而暂时使用httpclient
|
||||
*/
|
||||
private String postWithKey(String url, String requestStr) throws WxErrorException {
|
||||
try {
|
||||
SSLContext sslContext = getConfig().getSslContext();
|
||||
SSLContext sslContext = this.getConfig().getSslContext();
|
||||
if (null == sslContext) {
|
||||
throw new IllegalArgumentException("请先初始化配置类(即WxMpConfigStorage的实现类)中的SSLContext!");
|
||||
sslContext = this.getConfig().initSSLContext();
|
||||
}
|
||||
|
||||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null,
|
||||
new DefaultHostnameVerifier());
|
||||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
|
||||
new String[]{"TLSv1"}, null, new DefaultHostnameVerifier());
|
||||
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
if (this.wxMpService.getHttpProxy() != null) {
|
||||
httpPost.setConfig(RequestConfig.custom().setProxy(this.wxMpService.getHttpProxy()).build());
|
||||
}
|
||||
|
||||
try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) {
|
||||
httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1")));
|
||||
@ -464,7 +501,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
@Override
|
||||
public String createSign(Object xmlBean) {
|
||||
return this.createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
|
||||
return this.createSign(BeanUtils.xmlBean2Map(xmlBean), this.getConfig().getMchKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -474,14 +511,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
@Override
|
||||
public String createSign(Map<String, String> params) {
|
||||
return this.createSign(params, this.getConfig().getPartnerKey());
|
||||
return this.createSign(params, this.getConfig().getMchKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createSign(Map<String, String> params, String signKey) {
|
||||
if(this.getConfig().useSandboxForWxPay()){
|
||||
if (this.getConfig().useSandboxForWxPay()) {
|
||||
//使用仿真测试环境
|
||||
//TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用这个仿真测试环境
|
||||
//TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用仿真测试环境
|
||||
signKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
|
||||
//return "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
|
||||
}
|
||||
@ -502,7 +539,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
@Override
|
||||
public boolean checkSign(Object xmlBean) {
|
||||
return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
|
||||
return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getMchKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -512,7 +549,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
@Override
|
||||
public boolean checkSign(Map<String, String> params) {
|
||||
return this.checkSign(params, getConfig().getPartnerKey());
|
||||
return this.checkSign(params, getConfig().getMchKey());
|
||||
}
|
||||
|
||||
@Override
|
@ -1,5 +1,6 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
|
||||
import org.testng.*;
|
||||
import org.testng.annotations.*;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import org.testng.*;
|
||||
import org.testng.annotations.*;
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
|
||||
import org.testng.*;
|
@ -1,4 +1,4 @@
|
||||
package me.chanjar.weixin.mp.bean.pay.result;
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
@ -0,0 +1,196 @@
|
||||
package com.github.binarywang.wxpay.service.impl;
|
||||
|
||||
import com.github.binarywang.utils.qrcode.QrcodeUtils;
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.github.binarywang.wxpay.testbase.ApiTestModule;
|
||||
import com.github.binarywang.wxpay.testbase.XmlWxPayConfig;
|
||||
import com.google.inject.Inject;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* 测试支付相关接口
|
||||
* Created by Binary Wang on 2016/7/28.
|
||||
*
|
||||
* @author binarywang (https://github.com/binarywang)
|
||||
*/
|
||||
@Test
|
||||
@Guice(modules = ApiTestModule.class)
|
||||
public class WxMpPayServiceImplTest {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Inject
|
||||
protected WxPayService wxService;
|
||||
|
||||
@Test
|
||||
public void testGetPayInfo() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDownloadBill() throws Exception {
|
||||
File file = this.wxService.downloadBill("20170101", "ALL", "GZIP", "1111111");
|
||||
assertNotNull(file);
|
||||
//必填字段为空时,抛出异常
|
||||
this.wxService.downloadBill("", "", "", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReport() throws Exception {
|
||||
WxPayReportRequest request = new WxPayReportRequest();
|
||||
request.setInterfaceUrl("hahahah");
|
||||
request.setSignType("HMAC-SHA256");//貌似接口未校验此字段
|
||||
request.setExecuteTime(1000);
|
||||
request.setReturnCode("aaa");
|
||||
request.setResultCode("aaa");
|
||||
request.setUserIp("8.8.8");
|
||||
this.wxService.report(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#refund(WxPayRefundRequest)} .
|
||||
*/
|
||||
@Test//(dependsOnMethods = {"setSSLKey"})
|
||||
public void testRefund() throws Exception {
|
||||
WxPayRefundResult result = this.wxService.refund(
|
||||
WxPayRefundRequest.newBuilder()
|
||||
.outRefundNo("aaa")
|
||||
.outTradeNo("1111")
|
||||
.totalFee(1222)
|
||||
.refundFee(111)
|
||||
.build());
|
||||
this.logger.info(result.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#refundQuery(java.lang.String, java.lang.String, java.lang.String, java.lang.String)} .
|
||||
*/
|
||||
@Test
|
||||
public void testRefundQuery() throws Exception {
|
||||
WxPayRefundQueryResult result;
|
||||
|
||||
result = this.wxService.refundQuery("1", "", "", "");
|
||||
this.logger.info(result.toString());
|
||||
|
||||
result = this.wxService.refundQuery("", "2", "", "");
|
||||
this.logger.info(result.toString());
|
||||
|
||||
result = this.wxService.refundQuery("", "", "3", "");
|
||||
this.logger.info(result.toString());
|
||||
|
||||
result = this.wxService.refundQuery("", "", "", "4");
|
||||
this.logger.info(result.toString());
|
||||
|
||||
//测试四个参数都填的情况,应该报异常的
|
||||
result = this.wxService.refundQuery("1", "2", "3", "4");
|
||||
this.logger.info(result.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#sendRedpack(WxPaySendRedpackRequest)} .
|
||||
*/
|
||||
@Test//(dependsOnMethods = {"setSSLKey"})
|
||||
public void testSendRedpack() throws Exception {
|
||||
WxPaySendRedpackRequest request = new WxPaySendRedpackRequest();
|
||||
request.setActName("abc");
|
||||
request.setClientIp("aaa");
|
||||
request.setMchBillNo("aaaa");
|
||||
request.setReOpenid(((XmlWxPayConfig) this.wxService.getConfig()).getOpenid());
|
||||
WxPaySendRedpackResult redpackResult = this.wxService.sendRedpack(request);
|
||||
this.logger.info(redpackResult.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#queryRedpack(java.lang.String)}.
|
||||
*/
|
||||
@Test//(dependsOnMethods = {"setSSLKey"})
|
||||
public void testQueryRedpack() throws Exception {
|
||||
WxPayRedpackQueryResult redpackResult = this.wxService.queryRedpack("aaaa");
|
||||
this.logger.info(redpackResult.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#unifiedOrder(WxPayUnifiedOrderRequest)}.
|
||||
*/
|
||||
@Test
|
||||
public void testUnifiedOrder() throws WxErrorException {
|
||||
WxPayUnifiedOrderResult result = this.wxService
|
||||
.unifiedOrder(WxPayUnifiedOrderRequest.builder()
|
||||
.body("我去")
|
||||
.totalFee(1)
|
||||
.spbillCreateIp("111111")
|
||||
.notifyURL("111111")
|
||||
.tradeType("JSAPI")
|
||||
.openid(((XmlWxPayConfig) this.wxService.getConfig()).getOpenid())
|
||||
.outTradeNo("111111")
|
||||
.build());
|
||||
this.logger.info(result.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#queryOrder(java.lang.String, java.lang.String)} .
|
||||
*/
|
||||
@Test
|
||||
public void testQueryOrder() throws WxErrorException {
|
||||
this.logger.info(this.wxService.queryOrder("11212121", null).toString());
|
||||
this.logger.info(this.wxService.queryOrder(null, "11111").toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#closeOrder(java.lang.String)} .
|
||||
*/
|
||||
@Test
|
||||
public void testCloseOrder() throws WxErrorException {
|
||||
this.logger.info(this.wxService.closeOrder("11212121").toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#entPay(WxEntPayRequest)}.
|
||||
*/
|
||||
@Test//(dependsOnMethods = {"setSSLKey"})
|
||||
public void testEntPay() throws WxErrorException {
|
||||
WxEntPayRequest request = new WxEntPayRequest();
|
||||
this.logger.info(this.wxService.entPay(request).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link WxPayService#queryEntPay(java.lang.String)}.
|
||||
*/
|
||||
@Test//(dependsOnMethods = {"setSSLKey"})
|
||||
public void testQueryEntPay() throws WxErrorException {
|
||||
this.logger.info(this.wxService.queryEntPay("11212121").toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateScanPayQrcodeMode1() throws Exception {
|
||||
String productId = "abc";
|
||||
byte[] bytes = this.wxService.createScanPayQrcodeMode1(productId, null, null);
|
||||
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
|
||||
Files.write(qrcodeFilePath, bytes);
|
||||
String qrcodeContent = QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile());
|
||||
this.logger.info(qrcodeContent);
|
||||
|
||||
assertTrue(qrcodeContent.startsWith("weixin://wxpay/bizpayurl?"));
|
||||
assertTrue(qrcodeContent.contains("product_id=" + productId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateScanPayQrcodeMode2() throws Exception {
|
||||
String qrcodeContent = "abc";
|
||||
byte[] bytes = this.wxService.createScanPayQrcodeMode2(qrcodeContent, null, null);
|
||||
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
|
||||
Files.write(qrcodeFilePath, bytes);
|
||||
assertEquals(QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile()), qrcodeContent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.github.binarywang.wxpay.testbase;
|
||||
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Module;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ApiTestModule implements Module {
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder) {
|
||||
try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) {
|
||||
XmlWxPayConfig config = this.fromXml(XmlWxPayConfig.class, is1);
|
||||
WxPayService wxService = new WxPayServiceImpl();
|
||||
wxService.setConfig(config);
|
||||
|
||||
binder.bind(WxPayService.class).toInstance(wxService);
|
||||
binder.bind(WxPayConfig.class).toInstance(config);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T fromXml(Class<T> clazz, InputStream is) {
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.alias("xml", clazz);
|
||||
xstream.processAnnotations(clazz);
|
||||
return (T) xstream.fromXML(is);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.github.binarywang.wxpay.testbase;
|
||||
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.http.ssl.SSLContexts;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.KeyStore;
|
||||
|
||||
@XStreamAlias("xml")
|
||||
public class XmlWxPayConfig extends WxPayConfig {
|
||||
private String openid;
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useSandboxForWxPay() {
|
||||
//沙箱环境不成熟,有问题无法使用,暂时屏蔽掉
|
||||
// return true;
|
||||
return false;
|
||||
}
|
||||
}
|
16
weixin-java-pay/src/test/resources/logback-test.xml
Normal file
16
weixin-java-pay/src/test/resources/logback-test.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!-- encoders are assigned the type
|
||||
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="debug">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
|
||||
<logger name="com.github.binarywang.wxpay" level="debug"/>
|
||||
</configuration>
|
13
weixin-java-pay/src/test/resources/test-config.sample.xml
Normal file
13
weixin-java-pay/src/test/resources/test-config.sample.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<xml>
|
||||
<appId>公众号appid</appId>
|
||||
<mchId>微信商户平台ID</mchId>
|
||||
<mchKey>商户平台设置的API密钥</mchKey>
|
||||
<!---
|
||||
以下为官网文档所提供样例参数,仅供部分接口测试使用
|
||||
<appId>wxd930ea5d5a258f4f</appId>
|
||||
<mchId>10000100</mchId>
|
||||
<mchKey>192006250b4c09247ec02edce69f6a2d</mchKey>
|
||||
-->
|
||||
<keyPath>商户平台的证书文件地址</keyPath>
|
||||
<openid>某个openId</openid>
|
||||
</xml>
|
Loading…
Reference in New Issue
Block a user