@@ -1,4 +1,4 @@ | |||||
Weixin Java Tools —— 微信公众号&企业号开发 Java SDK | |||||
WeixinJavaTools 微信支付、公众号&企业号开发Java SDK | |||||
===================================== | ===================================== | ||||
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent) | ||||
[![Build Status](https://travis-ci.org/Wechat-Group/weixin-java-tools.svg?branch=develop)](https://travis-ci.org/Wechat-Group/weixin-java-tools) | [![Build Status](https://travis-ci.org/Wechat-Group/weixin-java-tools.svg?branch=develop)](https://travis-ci.org/Wechat-Group/weixin-java-tools) | ||||
@@ -48,7 +48,7 @@ Weixin Java Tools —— 微信公众号&企业号开发 Java SDK | |||||
## Maven & Gradle 最新正式版本 | ## Maven & Gradle 最新正式版本 | ||||
* 公众号(订阅号、服务号): | |||||
* 公众号(订阅号、服务号及微信支付): | |||||
maven: | maven: | ||||
```xml | ```xml | ||||
@@ -5,7 +5,7 @@ | |||||
<modelVersion>4.0.0</modelVersion> | <modelVersion>4.0.0</modelVersion> | ||||
<groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>2.6.0-SNAPSHOT</version> | |||||
<version>2.5.2.BETA</version> | |||||
<packaging>pom</packaging> | <packaging>pom</packaging> | ||||
<name>WeiXin Java Tools - Parent</name> | <name>WeiXin Java Tools - Parent</name> | ||||
<description>微信公众号、企业号上级POM</description> | <description>微信公众号、企业号上级POM</description> | ||||
@@ -86,7 +86,8 @@ | |||||
<module>weixin-java-common</module> | <module>weixin-java-common</module> | ||||
<module>weixin-java-cp</module> | <module>weixin-java-cp</module> | ||||
<module>weixin-java-mp</module> | <module>weixin-java-mp</module> | ||||
<module>weixin-java-osgi</module> | |||||
<module>weixin-java-pay</module> | |||||
<!--module>weixin-java-osgi</module--> | |||||
</modules> | </modules> | ||||
<properties> | <properties> | ||||
@@ -6,7 +6,7 @@ | |||||
<parent> | <parent> | ||||
<groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>2.6.0-SNAPSHOT</version> | |||||
<version>2.5.2.BETA</version> | |||||
</parent> | </parent> | ||||
<artifactId>weixin-java-common</artifactId> | <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_CLOSE_SESSION = "kf_close_session"; // 客服关闭会话 | ||||
public static final String EVT_KF_SWITCH_SESSION = "kf_switch_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 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_VIDEO = "video"; | ||||
public static final String MEDIA_THUMB = "thumb"; | public static final String MEDIA_THUMB = "thumb"; | ||||
public static final String MEDIA_FILE = "file"; | 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> | <parent> | ||||
<groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>2.6.0-SNAPSHOT</version> | |||||
<version>2.5.2.BETA</version> | |||||
</parent> | </parent> | ||||
<artifactId>weixin-java-cp</artifactId> | <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 | @DataProvider | ||||
public Object[][] uploadMedia() { | public Object[][] uploadMedia() { | ||||
return new Object[][]{ | 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> | <parent> | ||||
<groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>2.6.0-SNAPSHOT</version> | |||||
<version>2.5.2.BETA</version> | |||||
</parent> | </parent> | ||||
<artifactId>weixin-java-mp</artifactId> | <artifactId>weixin-java-mp</artifactId> | ||||
<name>WeiXin Java Tools - MP</name> | <name>WeiXin Java Tools - MP</name> | ||||
@@ -18,21 +18,11 @@ | |||||
<artifactId>weixin-java-common</artifactId> | <artifactId>weixin-java-common</artifactId> | ||||
<version>${project.version}</version> | <version>${project.version}</version> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>junit</groupId> | |||||
<artifactId>junit</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | <dependency> | ||||
<groupId>org.testng</groupId> | <groupId>org.testng</groupId> | ||||
<artifactId>testng</artifactId> | <artifactId>testng</artifactId> | ||||
<scope>test</scope> | <scope>test</scope> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>org.mockito</groupId> | |||||
<artifactId>mockito-all</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | <dependency> | ||||
<groupId>com.google.inject</groupId> | <groupId>com.google.inject</groupId> | ||||
<artifactId>guice</artifactId> | <artifactId>guice</artifactId> | ||||
@@ -54,16 +44,6 @@ | |||||
<version>2.9.4</version> | <version>2.9.4</version> | ||||
<scope>test</scope> | <scope>test</scope> | ||||
</dependency> | </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> | </dependencies> | ||||
<build> | <build> | ||||
@@ -3,7 +3,6 @@ package me.chanjar.weixin.mp.api; | |||||
import me.chanjar.weixin.common.bean.WxAccessToken; | import me.chanjar.weixin.common.bean.WxAccessToken; | ||||
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; | ||||
import javax.net.ssl.SSLContext; | |||||
import java.io.File; | import java.io.File; | ||||
import java.util.concurrent.locks.Lock; | import java.util.concurrent.locks.Lock; | ||||
@@ -82,27 +81,6 @@ public interface WxMpConfigStorage { | |||||
String getSecret(); | 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 getToken(); | ||||
String getAesKey(); | String getAesKey(); | ||||
@@ -121,17 +99,6 @@ public interface WxMpConfigStorage { | |||||
File getTmpDirFile(); | File getTmpDirFile(); | ||||
SSLContext getSslContext(); | |||||
void setSslContext(SSLContext sslContext); | |||||
/** | |||||
* 在此之前,必须将partnerId进行赋值 | |||||
* | |||||
* @param filePath apiclient_cert.p12的文件的绝对路径 | |||||
*/ | |||||
void setSslContextFilePath(String filePath) throws Exception; | |||||
/** | /** | ||||
* http client builder | * http client builder | ||||
* | * | ||||
@@ -144,8 +111,4 @@ public interface WxMpConfigStorage { | |||||
*/ | */ | ||||
boolean autoRefreshToken(); | 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.bean.WxAccessToken; | ||||
import me.chanjar.weixin.common.util.ToStringUtils; | import me.chanjar.weixin.common.util.ToStringUtils; | ||||
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; | 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.File; | ||||
import java.io.FileInputStream; | |||||
import java.security.KeyStore; | |||||
import java.util.concurrent.locks.Lock; | import java.util.concurrent.locks.Lock; | ||||
import java.util.concurrent.locks.ReentrantLock; | import java.util.concurrent.locks.ReentrantLock; | ||||
@@ -21,10 +17,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
protected volatile String appId; | protected volatile String appId; | ||||
protected volatile String secret; | 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 token; | ||||
protected volatile String accessToken; | protected volatile String accessToken; | ||||
protected volatile String aesKey; | protected volatile String aesKey; | ||||
@@ -52,8 +44,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
*/ | */ | ||||
protected volatile File tmpDirFile; | protected volatile File tmpDirFile; | ||||
protected volatile SSLContext sslContext; | |||||
protected volatile ApacheHttpClientBuilder apacheHttpClientBuilder; | protected volatile ApacheHttpClientBuilder apacheHttpClientBuilder; | ||||
@Override | @Override | ||||
@@ -61,10 +51,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
return this.accessToken; | return this.accessToken; | ||||
} | } | ||||
public void setAccessToken(String accessToken) { | |||||
this.accessToken = accessToken; | |||||
} | |||||
@Override | @Override | ||||
public Lock getAccessTokenLock() { | public Lock getAccessTokenLock() { | ||||
return this.accessTokenLock; | return this.accessTokenLock; | ||||
@@ -96,23 +82,11 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
return this.jsapiTicket; | return this.jsapiTicket; | ||||
} | } | ||||
public void setJsapiTicket(String jsapiTicket) { | |||||
this.jsapiTicket = jsapiTicket; | |||||
} | |||||
@Override | @Override | ||||
public Lock getJsapiTicketLock() { | public Lock getJsapiTicketLock() { | ||||
return this.jsapiTicketLock; | return this.jsapiTicketLock; | ||||
} | } | ||||
public long getJsapiTicketExpiresTime() { | |||||
return this.jsapiTicketExpiresTime; | |||||
} | |||||
public void setJsapiTicketExpiresTime(long jsapiTicketExpiresTime) { | |||||
this.jsapiTicketExpiresTime = jsapiTicketExpiresTime; | |||||
} | |||||
@Override | @Override | ||||
public boolean isJsapiTicketExpired() { | public boolean isJsapiTicketExpired() { | ||||
return System.currentTimeMillis() > this.jsapiTicketExpiresTime; | return System.currentTimeMillis() > this.jsapiTicketExpiresTime; | ||||
@@ -256,88 +230,49 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
} | } | ||||
@Override | @Override | ||||
public String getPartnerId() { | |||||
return this.partnerId; | |||||
public File getTmpDirFile() { | |||||
return this.tmpDirFile; | |||||
} | } | ||||
public void setPartnerId(String partnerId) { | |||||
this.partnerId = partnerId; | |||||
public void setTmpDirFile(File tmpDirFile) { | |||||
this.tmpDirFile = tmpDirFile; | |||||
} | } | ||||
@Override | @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 ApacheHttpClientBuilder getApacheHttpClientBuilder() { | |||||
return this.apacheHttpClientBuilder; | |||||
} | } | ||||
public void setTradeType(String tradeType) { | |||||
this.tradeType = tradeType; | |||||
public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) { | |||||
this.apacheHttpClientBuilder = apacheHttpClientBuilder; | |||||
} | } | ||||
@Override | |||||
public File getTmpDirFile() { | |||||
return this.tmpDirFile; | |||||
public void setAccessToken(String accessToken) { | |||||
this.accessToken = accessToken; | |||||
} | } | ||||
public void setTmpDirFile(File tmpDirFile) { | |||||
this.tmpDirFile = tmpDirFile; | |||||
public void setJsapiTicket(String jsapiTicket) { | |||||
this.jsapiTicket = jsapiTicket; | |||||
} | } | ||||
@Override | |||||
public SSLContext getSslContext() { | |||||
return this.sslContext; | |||||
public long getJsapiTicketExpiresTime() { | |||||
return this.jsapiTicketExpiresTime; | |||||
} | } | ||||
@Override | |||||
public void setSslContext(SSLContext context) { | |||||
this.sslContext = context; | |||||
public void setJsapiTicketExpiresTime(long jsapiTicketExpiresTime) { | |||||
this.jsapiTicketExpiresTime = jsapiTicketExpiresTime; | |||||
} | } | ||||
@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); | |||||
} | |||||
public void setCardApiTicket(String cardApiTicket) { | |||||
this.cardApiTicket = cardApiTicket; | |||||
} | } | ||||
@Override | |||||
public ApacheHttpClientBuilder getApacheHttpClientBuilder() { | |||||
return this.apacheHttpClientBuilder; | |||||
public long getCardApiTicketExpiresTime() { | |||||
return this.cardApiTicketExpiresTime; | |||||
} | } | ||||
public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) { | |||||
this.apacheHttpClientBuilder = apacheHttpClientBuilder; | |||||
public void setCardApiTicketExpiresTime(long cardApiTicketExpiresTime) { | |||||
this.cardApiTicketExpiresTime = cardApiTicketExpiresTime; | |||||
} | } | ||||
@Override | @Override | ||||
@@ -345,8 +280,4 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
return true; | return true; | ||||
} | } | ||||
@Override | |||||
public boolean useSandboxForWxPay() { | |||||
return false; | |||||
} | |||||
} | } |
@@ -311,13 +311,6 @@ public interface WxMpService { | |||||
*/ | */ | ||||
WxMpCardService getCardService(); | WxMpCardService getCardService(); | ||||
/** | |||||
* 返回微信支付相关接口方法的实现类对象,以方便调用其各个接口 | |||||
* | |||||
* @return WxMpPayService | |||||
*/ | |||||
WxMpPayService getPayService(); | |||||
/** | /** | ||||
* 返回数据分析统计相关接口方法的实现类对象,以方便调用其各个接口 | * 返回数据分析统计相关接口方法的实现类对象,以方便调用其各个接口 | ||||
* | * | ||||
@@ -28,9 +28,6 @@ import org.slf4j.LoggerFactory; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.util.concurrent.locks.Lock; | 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 { | public class WxMpServiceImpl implements WxMpService { | ||||
private static final JsonParser JSON_PARSER = new JsonParser(); | private static final JsonParser JSON_PARSER = new JsonParser(); | ||||
@@ -45,7 +42,6 @@ public class WxMpServiceImpl implements WxMpService { | |||||
private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this); | private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this); | ||||
private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); | private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); | ||||
private WxMpCardService cardService = new WxMpCardServiceImpl(this); | private WxMpCardService cardService = new WxMpCardServiceImpl(this); | ||||
private WxMpPayService payService = new WxMpPayServiceImpl(this); | |||||
private WxMpStoreService storeService = new WxMpStoreServiceImpl(this); | private WxMpStoreService storeService = new WxMpStoreServiceImpl(this); | ||||
private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); | private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); | ||||
private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); | private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); | ||||
@@ -59,7 +55,7 @@ public class WxMpServiceImpl implements WxMpService { | |||||
@Override | @Override | ||||
public boolean checkSignature(String timestamp, String nonce, String signature) { | public boolean checkSignature(String timestamp, String nonce, String signature) { | ||||
try { | try { | ||||
return SHA1.gen(this.wxMpConfigStorage.getToken(), timestamp, nonce) | |||||
return SHA1.gen(this.getWxMpConfigStorage().getToken(), timestamp, nonce) | |||||
.equals(signature); | .equals(signature); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
return false; | return false; | ||||
@@ -73,18 +69,18 @@ public class WxMpServiceImpl implements WxMpService { | |||||
@Override | @Override | ||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException { | public String getAccessToken(boolean forceRefresh) throws WxErrorException { | ||||
Lock lock = this.wxMpConfigStorage.getAccessTokenLock(); | |||||
Lock lock = this.getWxMpConfigStorage().getAccessTokenLock(); | |||||
try { | try { | ||||
lock.lock(); | lock.lock(); | ||||
if (forceRefresh) { | 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" + | 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 { | try { | ||||
HttpGet httpGet = new HttpGet(url); | HttpGet httpGet = new HttpGet(url); | ||||
if (this.httpProxy != null) { | if (this.httpProxy != null) { | ||||
@@ -98,7 +94,7 @@ public class WxMpServiceImpl implements WxMpService { | |||||
throw new WxErrorException(error); | throw new WxErrorException(error); | ||||
} | } | ||||
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); | WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); | ||||
this.wxMpConfigStorage.updateAccessToken(accessToken.getAccessToken(), | |||||
this.getWxMpConfigStorage().updateAccessToken(accessToken.getAccessToken(), | |||||
accessToken.getExpiresIn()); | accessToken.getExpiresIn()); | ||||
} finally { | } finally { | ||||
httpGet.releaseConnection(); | httpGet.releaseConnection(); | ||||
@@ -110,7 +106,7 @@ public class WxMpServiceImpl implements WxMpService { | |||||
} finally { | } finally { | ||||
lock.unlock(); | lock.unlock(); | ||||
} | } | ||||
return this.wxMpConfigStorage.getAccessToken(); | |||||
return this.getWxMpConfigStorage().getAccessToken(); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -120,27 +116,27 @@ public class WxMpServiceImpl implements WxMpService { | |||||
@Override | @Override | ||||
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { | public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { | ||||
Lock lock = this.wxMpConfigStorage.getJsapiTicketLock(); | |||||
Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock(); | |||||
try { | try { | ||||
lock.lock(); | lock.lock(); | ||||
if (forceRefresh) { | 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 url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; | ||||
String responseContent = execute(new SimpleGetRequestExecutor(), url, null); | String responseContent = execute(new SimpleGetRequestExecutor(), url, null); | ||||
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); | JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); | ||||
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); | JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); | ||||
String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); | String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); | ||||
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); | int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); | ||||
this.wxMpConfigStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds); | |||||
this.getWxMpConfigStorage().updateJsapiTicket(jsapiTicket, expiresInSeconds); | |||||
} | } | ||||
} finally { | } finally { | ||||
lock.unlock(); | lock.unlock(); | ||||
} | } | ||||
return this.wxMpConfigStorage.getJsapiTicket(); | |||||
return this.getWxMpConfigStorage().getJsapiTicket(); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -151,7 +147,7 @@ public class WxMpServiceImpl implements WxMpService { | |||||
String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, | String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, | ||||
"noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url); | "noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url); | ||||
WxJsapiSignature jsapiSignature = new WxJsapiSignature(); | WxJsapiSignature jsapiSignature = new WxJsapiSignature(); | ||||
jsapiSignature.setAppId(this.wxMpConfigStorage.getAppId()); | |||||
jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId()); | |||||
jsapiSignature.setTimestamp(timestamp); | jsapiSignature.setTimestamp(timestamp); | ||||
jsapiSignature.setNonceStr(noncestr); | jsapiSignature.setNonceStr(noncestr); | ||||
jsapiSignature.setUrl(url); | jsapiSignature.setUrl(url); | ||||
@@ -216,7 +212,7 @@ public class WxMpServiceImpl implements WxMpService { | |||||
public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { | public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { | ||||
StringBuilder url = new StringBuilder(); | StringBuilder url = new StringBuilder(); | ||||
url.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); | 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("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); | ||||
url.append("&response_type=code"); | url.append("&response_type=code"); | ||||
url.append("&scope=").append(scope); | url.append("&scope=").append(scope); | ||||
@@ -232,7 +228,7 @@ public class WxMpServiceImpl implements WxMpService { | |||||
String state) { | String state) { | ||||
StringBuilder url = new StringBuilder(); | StringBuilder url = new StringBuilder(); | ||||
url.append("https://open.weixin.qq.com/connect/qrconnect?"); | 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("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); | ||||
url.append("&response_type=code"); | url.append("&response_type=code"); | ||||
url.append("&scope=").append(scope); | url.append("&scope=").append(scope); | ||||
@@ -258,8 +254,8 @@ public class WxMpServiceImpl implements WxMpService { | |||||
public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { | public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { | ||||
StringBuilder url = new StringBuilder(); | StringBuilder url = new StringBuilder(); | ||||
url.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); | 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("&code=").append(code); | ||||
url.append("&grant_type=authorization_code"); | url.append("&grant_type=authorization_code"); | ||||
@@ -270,7 +266,7 @@ public class WxMpServiceImpl implements WxMpService { | |||||
public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { | public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { | ||||
StringBuilder url = new StringBuilder(); | StringBuilder url = new StringBuilder(); | ||||
url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); | 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("&grant_type=refresh_token"); | ||||
url.append("&refresh_token=").append(refreshToken); | url.append("&refresh_token=").append(refreshToken); | ||||
@@ -397,8 +393,8 @@ public class WxMpServiceImpl implements WxMpService { | |||||
*/ | */ | ||||
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { | if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { | ||||
// 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | // 强制设置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); | return this.execute(executor, uri, data); | ||||
} | } | ||||
} | } | ||||
@@ -424,26 +420,19 @@ public class WxMpServiceImpl implements WxMpService { | |||||
} | } | ||||
private void initHttpClient() { | private void initHttpClient() { | ||||
ApacheHttpClientBuilder apacheHttpClientBuilder = this.wxMpConfigStorage | |||||
.getApacheHttpClientBuilder(); | |||||
WxMpConfigStorage configStorage = this.getWxMpConfigStorage(); | |||||
ApacheHttpClientBuilder apacheHttpClientBuilder = configStorage.getApacheHttpClientBuilder(); | |||||
if (null == apacheHttpClientBuilder) { | if (null == apacheHttpClientBuilder) { | ||||
apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); | apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); | ||||
} | } | ||||
apacheHttpClientBuilder.httpProxyHost(this.wxMpConfigStorage.getHttpProxyHost()) | |||||
.httpProxyPort(this.wxMpConfigStorage.getHttpProxyPort()) | |||||
.httpProxyUsername(this.wxMpConfigStorage.getHttpProxyUsername()) | |||||
.httpProxyPassword(this.wxMpConfigStorage.getHttpProxyPassword()); | |||||
// if (this.wxMpConfigStorage.getSSLContext() != null) { | |||||
// SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( | |||||
// this.wxMpConfigStorage.getSSLContext(), new String[] { "TLSv1" }, null, | |||||
// new DefaultHostnameVerifier()); | |||||
// apacheHttpClientBuilder.sslConnectionSocketFactory(sslsf); | |||||
// } | |||||
apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost()) | |||||
.httpProxyPort(configStorage.getHttpProxyPort()) | |||||
.httpProxyUsername(configStorage.getHttpProxyUsername()) | |||||
.httpProxyPassword(configStorage.getHttpProxyPassword()); | |||||
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(); | this.httpClient = apacheHttpClientBuilder.build(); | ||||
@@ -505,11 +494,6 @@ public class WxMpServiceImpl implements WxMpService { | |||||
return this.cardService; | return this.cardService; | ||||
} | } | ||||
@Override | |||||
public WxMpPayService getPayService() { | |||||
return this.payService; | |||||
} | |||||
@Override | @Override | ||||
public WxMpDataCubeService getDataCubeService() { | public WxMpDataCubeService getDataCubeService() { | ||||
return this.dataCubeService; | 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.common.exception.WxErrorException; | ||||
import me.chanjar.weixin.mp.api.test.ApiTestModule; | import me.chanjar.weixin.mp.api.test.ApiTestModule; | ||||
import me.chanjar.weixin.mp.api.test.TestConfigStorage; | 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.WxMpMassNews; | ||||
import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; | import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; | ||||
import me.chanjar.weixin.mp.bean.WxMpMassTagMessage; | import me.chanjar.weixin.mp.bean.WxMpMassTagMessage; | ||||
@@ -101,7 +102,7 @@ public class WxMpMassMessageAPITest { | |||||
.getSystemResourceAsStream("mm.mp4")) { | .getSystemResourceAsStream("mm.mp4")) { | ||||
// 上传视频到媒体库 | // 上传视频到媒体库 | ||||
WxMediaUploadResult uploadMediaRes = this.wxService.getMaterialService() | 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); | ||||
Assert.assertNotNull(uploadMediaRes.getMediaId()); | Assert.assertNotNull(uploadMediaRes.getMediaId()); | ||||
@@ -122,7 +123,7 @@ public class WxMpMassMessageAPITest { | |||||
try (InputStream inputStream = ClassLoader | try (InputStream inputStream = ClassLoader | ||||
.getSystemResourceAsStream("mm.jpeg")) { | .getSystemResourceAsStream("mm.jpeg")) { | ||||
WxMediaUploadResult uploadMediaRes = this.wxService.getMaterialService() | 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); | ||||
Assert.assertNotNull(uploadMediaRes.getMediaId()); | Assert.assertNotNull(uploadMediaRes.getMediaId()); | ||||
messages[1] = new Object[]{WxConsts.MASS_MSG_IMAGE, uploadMediaRes.getMediaId()}; | messages[1] = new Object[]{WxConsts.MASS_MSG_IMAGE, uploadMediaRes.getMediaId()}; | ||||
@@ -134,7 +135,7 @@ public class WxMpMassMessageAPITest { | |||||
try (InputStream inputStream = ClassLoader | try (InputStream inputStream = ClassLoader | ||||
.getSystemResourceAsStream("mm.mp3")) { | .getSystemResourceAsStream("mm.mp3")) { | ||||
WxMediaUploadResult uploadMediaRes = this.wxService.getMaterialService() | 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); | ||||
Assert.assertNotNull(uploadMediaRes.getMediaId()); | Assert.assertNotNull(uploadMediaRes.getMediaId()); | ||||
messages[2] = new Object[]{WxConsts.MASS_MSG_VOICE, uploadMediaRes.getMediaId()}; | messages[2] = new Object[]{WxConsts.MASS_MSG_VOICE, uploadMediaRes.getMediaId()}; | ||||
@@ -147,7 +148,7 @@ public class WxMpMassMessageAPITest { | |||||
.getSystemResourceAsStream("mm.jpeg")) { | .getSystemResourceAsStream("mm.jpeg")) { | ||||
// 上传照片到媒体库 | // 上传照片到媒体库 | ||||
WxMediaUploadResult uploadMediaRes = this.wxService.getMaterialService() | 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); | ||||
Assert.assertNotNull(uploadMediaRes.getMediaId()); | 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.common.util.fs.FileUtils; | ||||
import me.chanjar.weixin.mp.api.WxMpService; | import me.chanjar.weixin.mp.api.WxMpService; | ||||
import me.chanjar.weixin.mp.api.test.ApiTestModule; | import me.chanjar.weixin.mp.api.test.ApiTestModule; | ||||
import me.chanjar.weixin.mp.api.test.TestConstants; | |||||
import me.chanjar.weixin.mp.bean.material.*; | import me.chanjar.weixin.mp.bean.material.*; | ||||
import org.testng.annotations.*; | import org.testng.annotations.*; | ||||
@@ -45,10 +46,10 @@ public class WxMpMaterialServiceImplTest { | |||||
@DataProvider | @DataProvider | ||||
public Object[][] mediaFiles() { | public Object[][] mediaFiles() { | ||||
return new Object[][]{ | 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 | @Override | ||||
public void configure(Binder binder) { | public void configure(Binder binder) { | ||||
try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) { | 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()); | config.setAccessTokenLock(new ReentrantLock()); | ||||
WxMpService wxService = new WxMpServiceImpl(); | WxMpService wxService = new WxMpServiceImpl(); | ||||
wxService.setWxMpConfigStorage(config); | wxService.setWxMpConfigStorage(config); | ||||
@@ -64,10 +64,4 @@ public class TestConfigStorage extends WxMpInMemoryConfigStorage { | |||||
super.accessTokenLock = lock; | 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.common.session.WxSessionManager; | ||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler; | import me.chanjar.weixin.mp.api.WxMpMessageHandler; | ||||
import me.chanjar.weixin.mp.api.WxMpService; | 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.WxMpXmlMessage; | ||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; | ||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | ||||
@@ -18,7 +19,7 @@ public class DemoImageHandler implements WxMpMessageHandler { | |||||
WxMpService wxMpService, WxSessionManager sessionManager) { | WxMpService wxMpService, WxSessionManager sessionManager) { | ||||
try { | try { | ||||
WxMediaUploadResult wxMediaUploadResult = wxMpService.getMaterialService() | 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 | WxMpXmlOutImageMessage m | ||||
= WxMpXmlOutMessage | = WxMpXmlOutMessage | ||||
.IMAGE() | .IMAGE() | ||||
@@ -6,7 +6,7 @@ | |||||
<parent> | <parent> | ||||
<groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>2.6.0-SNAPSHOT</version> | |||||
<version>2.5.2.BETA</version> | |||||
</parent> | </parent> | ||||
<artifactId>weixin-java-osgi</artifactId> | <artifactId>weixin-java-osgi</artifactId> | ||||
@@ -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 com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.annotation.Required; | import me.chanjar.weixin.common.annotation.Required; | ||||
@@ -16,6 +16,7 @@ import me.chanjar.weixin.common.util.ToStringUtils; | |||||
* <li>描述 | * <li>描述 | ||||
* </pre> | * </pre> | ||||
* Created by Binary Wang on 2016/10/19. | * Created by Binary Wang on 2016/10/19. | ||||
* | |||||
* @author binarywang (https://github.com/binarywang) | * @author binarywang (https://github.com/binarywang) | ||||
*/ | */ | ||||
@XStreamAlias("xml") | @XStreamAlias("xml") | ||||
@@ -29,20 +30,20 @@ public class WxEntPayQueryRequest extends WxPayBaseRequest { | |||||
* String(32) | * String(32) | ||||
* 微信支付分配的商户号 | * 微信支付分配的商户号 | ||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("mchid") | @XStreamAlias("mchid") | ||||
private String mchId; | private String mchId; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 商户订单号 | |||||
* partner_trade_no | |||||
* 是 | |||||
* 10000098201411111234567890 | |||||
* String | |||||
* 商户订单号 | |||||
* 商户订单号 | |||||
* partner_trade_no | |||||
* 是 | |||||
* 10000098201411111234567890 | |||||
* String | |||||
* 商户订单号 | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@Required | @Required | ||||
@XStreamAlias("partner_trade_no") | @XStreamAlias("partner_trade_no") | ||||
private String partnerTradeNo; | 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 com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.util.ToStringUtils; | import me.chanjar.weixin.common.util.ToStringUtils; | ||||
@@ -15,140 +15,141 @@ import me.chanjar.weixin.common.util.ToStringUtils; | |||||
* <li>描述 | * <li>描述 | ||||
* </pre> | * </pre> | ||||
* Created by Binary Wang on 2016/10/02. | * Created by Binary Wang on 2016/10/02. | ||||
* | |||||
* @author binarywang (https://github.com/binarywang) | * @author binarywang (https://github.com/binarywang) | ||||
*/ | */ | ||||
@XStreamAlias("xml") | @XStreamAlias("xml") | ||||
public class WxEntPayRequest extends WxPayBaseRequest{ | |||||
public class WxEntPayRequest extends WxPayBaseRequest { | |||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 公众账号appid | |||||
* mch_appid | |||||
* 是 | |||||
* wx8888888888888888 | |||||
* String | |||||
* 微信分配的公众账号ID(企业号corpid即为此appId) | |||||
* 公众账号appid | |||||
* mch_appid | |||||
* 是 | |||||
* wx8888888888888888 | |||||
* String | |||||
* 微信分配的公众账号ID(企业号corpid即为此appId) | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("mch_appid") | @XStreamAlias("mch_appid") | ||||
private String mchAppid; | private String mchAppid; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 商户号 | |||||
* mchid | |||||
* 是 | |||||
* 1900000109 | |||||
* String(32) | |||||
* 微信支付分配的商户号 | |||||
* 商户号 | |||||
* mchid | |||||
* 是 | |||||
* 1900000109 | |||||
* String(32) | |||||
* 微信支付分配的商户号 | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("mchid") | @XStreamAlias("mchid") | ||||
private String mchId; | private String mchId; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 设备号 | |||||
* device_info | |||||
* 否 | |||||
* 13467007045764 | |||||
* String(32) | |||||
*微信支付分配的终端设备号 | |||||
* 设备号 | |||||
* device_info | |||||
* 否 | |||||
* 13467007045764 | |||||
* String(32) | |||||
* 微信支付分配的终端设备号 | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("device_info") | @XStreamAlias("device_info") | ||||
private String deviceInfo; | private String deviceInfo; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 商户订单号 | |||||
* partner_trade_no | |||||
* 是 | |||||
* 10000098201411111234567890 | |||||
* String | |||||
* 商户订单号 | |||||
* 商户订单号 | |||||
* partner_trade_no | |||||
* 是 | |||||
* 10000098201411111234567890 | |||||
* String | |||||
* 商户订单号 | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("partner_trade_no") | @XStreamAlias("partner_trade_no") | ||||
private String partnerTradeNo; | private String partnerTradeNo; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 需保持唯一性 用户openid | |||||
* openid | |||||
* 是 | |||||
* oxTWIuGaIt6gTKsQRLau2M0yL16E | |||||
* String | |||||
* 商户appid下,某用户的openid | |||||
* 需保持唯一性 用户openid | |||||
* openid | |||||
* 是 | |||||
* oxTWIuGaIt6gTKsQRLau2M0yL16E | |||||
* String | |||||
* 商户appid下,某用户的openid | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("openid") | @XStreamAlias("openid") | ||||
private String openid; | private String openid; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 校验用户姓名选项 | |||||
* check_name | |||||
* 是 | |||||
* OPTION_CHECK | |||||
* String | |||||
* NO_CHECK:不校验真实姓名 | |||||
* FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账) | |||||
* OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功) | |||||
* 校验用户姓名选项 | |||||
* check_name | |||||
* 是 | |||||
* OPTION_CHECK | |||||
* String | |||||
* NO_CHECK:不校验真实姓名 | |||||
* FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账) | |||||
* OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功) | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("check_name") | @XStreamAlias("check_name") | ||||
private String checkName; | private String checkName; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 收款用户姓名 | |||||
* re_user_name | |||||
* 可选 | |||||
* 马花花 | |||||
* String | |||||
* 收款用户真实姓名。 | |||||
* 如果check_name设置为FORCE_CHECK或OPTION_CHECK, 则必填用户真实姓名 | |||||
* 收款用户姓名 | |||||
* re_user_name | |||||
* 可选 | |||||
* 马花花 | |||||
* String | |||||
* 收款用户真实姓名。 | |||||
* 如果check_name设置为FORCE_CHECK或OPTION_CHECK, 则必填用户真实姓名 | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("re_user_name") | @XStreamAlias("re_user_name") | ||||
private String reUserName; | private String reUserName; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 金额 | |||||
* amount | |||||
* 是 | |||||
* 10099 | |||||
* int | |||||
* 企业付款金额, 单位为分 | |||||
* 金额 | |||||
* amount | |||||
* 是 | |||||
* 10099 | |||||
* int | |||||
* 企业付款金额, 单位为分 | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("amount") | @XStreamAlias("amount") | ||||
private Integer amount; | private Integer amount; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 企业付款描述信息 | |||||
* desc | |||||
* 是 | |||||
* 理赔 | |||||
* String | |||||
* 企业付款操作说明信息。必填。 | |||||
* 企业付款描述信息 | |||||
* desc | |||||
* 是 | |||||
* 理赔 | |||||
* String | |||||
* 企业付款操作说明信息。必填。 | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("desc") | @XStreamAlias("desc") | ||||
private String description; | private String description; | ||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* Ip地址 | |||||
* spbill_create_ip | |||||
* 是 | |||||
* 192.168.0.1 | |||||
* String(32) | |||||
* 调用接口的机器Ip地址 | |||||
* Ip地址 | |||||
* spbill_create_ip | |||||
* 是 | |||||
* 192.168.0.1 | |||||
* String(32) | |||||
* 调用接口的机器Ip地址 | |||||
* </pre> | * </pre> | ||||
*/ | |||||
*/ | |||||
@XStreamAlias("spbill_create_ip") | @XStreamAlias("spbill_create_ip") | ||||
private String spbillCreateIp; | 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.XStream; | ||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
@@ -47,6 +47,32 @@ public abstract class WxPayBaseRequest { | |||||
*/ | */ | ||||
@XStreamAlias("mch_id") | @XStreamAlias("mch_id") | ||||
protected String mchId; | 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> | * <pre> | ||||
* 随机字符串 | * 随机字符串 | ||||
@@ -128,6 +154,22 @@ public abstract class WxPayBaseRequest { | |||||
this.sign = sign; | 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 | @Override | ||||
public String toString() { | public String toString() { | ||||
return ToStringUtils.toSimpleString(this); | 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 com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.annotation.Required; | 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; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
@@ -10,7 +10,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; | |||||
* </pre> | * </pre> | ||||
*/ | */ | ||||
@XStreamAlias("xml") | @XStreamAlias("xml") | ||||
public class WxPayOrderCloseRequest extends WxPayBaseRequest{ | |||||
public class WxPayOrderCloseRequest extends WxPayBaseRequest { | |||||
/** | /** | ||||
* <pre> | * <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; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
@@ -14,6 +14,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; | |||||
* <li>示例值 | * <li>示例值 | ||||
* <li>描述 | * <li>描述 | ||||
* </pre> | * </pre> | ||||
* | |||||
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> | * @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> | ||||
*/ | */ | ||||
@XStreamAlias("xml") | @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; | 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 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 com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.annotation.Required; | import me.chanjar.weixin.common.annotation.Required; | ||||
@@ -143,6 +143,28 @@ public class WxPayRefundRequest extends WxPayBaseRequest { | |||||
@XStreamAlias("refund_account") | @XStreamAlias("refund_account") | ||||
private String refundAccount; | 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() { | public String getDeviceInfo() { | ||||
return this.deviceInfo; | return this.deviceInfo; | ||||
} | } | ||||
@@ -215,4 +237,103 @@ public class WxPayRefundRequest extends WxPayBaseRequest { | |||||
this.refundAccount = refundAccount; | 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 com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.annotation.Required; | 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; | 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) | * @author binarywang (https://github.com/binarywang) | ||||
*/ | */ | ||||
@XStreamAlias("xml") | @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") | @XStreamAlias("mch_billno") | ||||
private String mchBillNo; | private String mchBillNo; | ||||
@@ -25,60 +26,60 @@ public class WxPaySendRedpackRequest extends WxPayBaseRequest{ | |||||
private String sendName; | private String sendName; | ||||
/** | /** | ||||
* re_openid | |||||
* 接受红包的用户 用户在wxappid下的openid | |||||
* re_openid | |||||
* 接受红包的用户 用户在wxappid下的openid | |||||
*/ | */ | ||||
@XStreamAlias("re_openid") | @XStreamAlias("re_openid") | ||||
private String reOpenid; | private String reOpenid; | ||||
/** | /** | ||||
* total_amount | |||||
* 红包总额 | |||||
* total_amount | |||||
* 红包总额 | |||||
*/ | */ | ||||
@XStreamAlias("total_amount") | @XStreamAlias("total_amount") | ||||
private Integer totalAmount; | private Integer totalAmount; | ||||
/** | /** | ||||
* total_num | |||||
* 红包发放总人数 | |||||
* total_num | |||||
* 红包发放总人数 | |||||
*/ | */ | ||||
@XStreamAlias("total_num") | @XStreamAlias("total_num") | ||||
private Integer totalNum; | private Integer totalNum; | ||||
/** | /** | ||||
* amt_type | |||||
* 红包金额设置方式 | |||||
* ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额 | |||||
* 裂变红包必填 | |||||
* amt_type | |||||
* 红包金额设置方式 | |||||
* ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额 | |||||
* 裂变红包必填 | |||||
*/ | */ | ||||
@XStreamAlias("amt_type") | @XStreamAlias("amt_type") | ||||
private String amtType; | private String amtType; | ||||
/** | /** | ||||
* wishing | |||||
* 红包祝福语 | |||||
* wishing | |||||
* 红包祝福语 | |||||
*/ | */ | ||||
@XStreamAlias("wishing") | @XStreamAlias("wishing") | ||||
private String wishing; | private String wishing; | ||||
/** | /** | ||||
* client_ip | |||||
* 服务器Ip地址 | |||||
* 调用接口的机器Ip地址 | |||||
* client_ip | |||||
* 服务器Ip地址 | |||||
* 调用接口的机器Ip地址 | |||||
*/ | */ | ||||
@XStreamAlias("client_ip") | @XStreamAlias("client_ip") | ||||
private String clientIp; | private String clientIp; | ||||
/** | /** | ||||
* act_name | |||||
* 活动名称 | |||||
* act_name | |||||
* 活动名称 | |||||
*/ | */ | ||||
@XStreamAlias("act_name") | @XStreamAlias("act_name") | ||||
private String actName; | private String actName; | ||||
/** | /** | ||||
* remark | |||||
* 备注 | |||||
* remark | |||||
* 备注 | |||||
*/ | */ | ||||
@XStreamAlias("remark") | @XStreamAlias("remark") | ||||
private String 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 com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.annotation.Required; | import me.chanjar.weixin.common.annotation.Required; | ||||
/** | /** | ||||
@@ -17,6 +16,7 @@ import me.chanjar.weixin.common.annotation.Required; | |||||
* <li>描述 | * <li>描述 | ||||
* </pre> | * </pre> | ||||
* Created by Binary Wang on 2016/9/25. | * Created by Binary Wang on 2016/9/25. | ||||
* | |||||
* @author binarywang (https://github.com/binarywang) | * @author binarywang (https://github.com/binarywang) | ||||
*/ | */ | ||||
@XStreamAlias("xml") | @XStreamAlias("xml") | ||||
@@ -56,35 +56,35 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { | |||||
* 否 | * 否 | ||||
* String(6000) | * String(6000) | ||||
* { "goods_detail":[ | * { "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> | * </pre> | ||||
*/ | */ | ||||
@XStreamAlias("detail") | @XStreamAlias("detail") | ||||
@@ -267,6 +267,9 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { | |||||
@XStreamAlias("openid") | @XStreamAlias("openid") | ||||
private String openid; | private String openid; | ||||
public static WxUnifiedOrderRequestBuilder builder() { | |||||
return new WxUnifiedOrderRequestBuilder(); | |||||
} | |||||
public String getDeviceInfo() { | public String getDeviceInfo() { | ||||
return this.deviceInfo; | return this.deviceInfo; | ||||
@@ -362,6 +365,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { | |||||
/** | /** | ||||
* 如果配置中已经设置,可以不设置值 | * 如果配置中已经设置,可以不设置值 | ||||
* | |||||
* @param notifyURL | * @param notifyURL | ||||
*/ | */ | ||||
public void setNotifyURL(String notifyURL) { | public void setNotifyURL(String notifyURL) { | ||||
@@ -374,6 +378,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { | |||||
/** | /** | ||||
* 如果配置中已经设置,可以不设置值 | * 如果配置中已经设置,可以不设置值 | ||||
* | |||||
* @param tradeType 交易类型 | * @param tradeType 交易类型 | ||||
*/ | */ | ||||
public void setTradeType(String tradeType) { | public void setTradeType(String tradeType) { | ||||
@@ -404,10 +409,6 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { | |||||
this.openid = openid; | this.openid = openid; | ||||
} | } | ||||
public static WxUnifiedOrderRequestBuilder builder() { | |||||
return new WxUnifiedOrderRequestBuilder(); | |||||
} | |||||
public static class WxUnifiedOrderRequestBuilder { | public static class WxUnifiedOrderRequestBuilder { | ||||
private String appid; | private String appid; | ||||
private String mchId; | 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; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
/** | /** | ||||
* 企业付款查询返回结果 | * 企业付款查询返回结果 | ||||
* Created by Binary Wang on 2016/10/19. | * Created by Binary Wang on 2016/10/19. | ||||
* | |||||
* @author binarywang (https://github.com/binarywang) | * @author binarywang (https://github.com/binarywang) | ||||
*/ | */ | ||||
@XStreamAlias("xml") | @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; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
/** | /** | ||||
* 企业付款返回结果 | * 企业付款返回结果 | ||||
* Created by Binary Wang on 2016/10/02. | * Created by Binary Wang on 2016/10/02. | ||||
* | |||||
* @author binarywang (https://github.com/binarywang) | * @author binarywang (https://github.com/binarywang) | ||||
*/ | */ | ||||
@XStreamAlias("xml") | @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.google.common.collect.Maps; | ||||
import com.thoughtworks.xstream.XStream; | import com.thoughtworks.xstream.XStream; | ||||
@@ -61,6 +61,16 @@ public abstract class WxPayBaseResult { | |||||
*/ | */ | ||||
@XStreamAlias("mch_id") | @XStreamAlias("mch_id") | ||||
private String mchId; | 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; | 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 | * 将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; | 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; | 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.google.common.collect.Lists; | ||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
@@ -396,7 +396,7 @@ public class WxPayOrderQueryResult extends WxPayBaseResult { | |||||
if (this.couponCount != null && this.couponCount > 0) { | if (this.couponCount != null && this.couponCount > 0) { | ||||
this.coupons = Lists.newArrayList(); | this.coupons = Lists.newArrayList(); | ||||
XmlPath xmlPath = new XmlPath(this.getXmlString()); | 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.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_id_" + i, String.class), | ||||
this.getXmlValue(xmlPath, "xml.coupon_fee_" + i, Integer.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; | 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.google.common.collect.Lists; | ||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
@@ -186,7 +186,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { | |||||
/** | /** | ||||
* 组装生成退款记录属性的内容 | * 组装生成退款记录属性的内容 | ||||
*/ | |||||
*/ | |||||
public void composeRefundRecords() { | public void composeRefundRecords() { | ||||
if (this.refundCount != null && this.refundCount > 0) { | if (this.refundCount != null && this.refundCount > 0) { | ||||
this.refundRecords = Lists.newArrayList(); | 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 com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import java.io.Serializable; | |||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 微信支付-申请退款返回结果 | * 微信支付-申请退款返回结果 | ||||
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4 | * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4 | ||||
* </pre> | * </pre> | ||||
* @author liukaitj | |||||
* | * | ||||
* @author liukaitj | |||||
*/ | */ | ||||
@XStreamAlias("xml") | @XStreamAlias("xml") | ||||
public class WxPayRefundResult extends WxPayBaseResult implements Serializable{ | |||||
public class WxPayRefundResult extends WxPayBaseResult implements Serializable { | |||||
private static final long serialVersionUID = 1L; | private static final long serialVersionUID = 1L; | ||||
@XStreamAlias("device_info") | @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 com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import java.io.Serializable; | |||||
/** | /** | ||||
* 向微信用户个人发现金红包返回结果 | * 向微信用户个人发现金红包返回结果 | ||||
* https://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5 | * https://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5 | ||||
* @author kane | |||||
* | * | ||||
* @author kane | |||||
*/ | */ | ||||
@XStreamAlias("xml") | @XStreamAlias("xml") | ||||
public class WxPaySendRedpackResult extends WxPayBaseResult implements Serializable { | 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; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
/** | /** | ||||
* <pre> | * <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> | * </pre> | ||||
* | * | ||||
* @author chanjarster | * @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.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.io.File; | ||||
import java.util.Map; | import java.util.Map; | ||||
/** | /** | ||||
* <pre> | |||||
* 微信支付相关接口 | * 微信支付相关接口 | ||||
* Created by Binary Wang on 2016/7/28. | * Created by Binary Wang on 2016/7/28. | ||||
* </pre> | |||||
* | * | ||||
* @author binarywang (https://github.com/binarywang) | * @author binarywang (https://github.com/binarywang) | ||||
*/ | */ | ||||
public interface WxMpPayService { | |||||
public interface WxPayService { | |||||
/** | /** | ||||
* <pre> | * <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; | 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 | * 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder | ||||
* | * | ||||
@@ -65,6 +68,16 @@ public interface WxMpPayService { | |||||
*/ | */ | ||||
Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException; | Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException; | ||||
/** | |||||
* 获取配置 | |||||
*/ | |||||
WxPayConfig getConfig(); | |||||
/** | |||||
* 设置配置对象 | |||||
*/ | |||||
void setConfig(WxPayConfig config); | |||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 微信支付-申请退款 | * 微信支付-申请退款 | ||||
@@ -81,7 +94,8 @@ public interface WxMpPayService { | |||||
* <pre> | * <pre> | ||||
* 微信支付-查询退款 | * 微信支付-查询退款 | ||||
* 应用场景: | * 应用场景: | ||||
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。 | |||||
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账, | |||||
* 银行卡支付的退款3个工作日后重新查询退款状态。 | |||||
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5 | * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5 | ||||
* 接口链接:https://api.mch.weixin.qq.com/pay/refundquery | * 接口链接:https://api.mch.weixin.qq.com/pay/refundquery | ||||
* </pre> | * </pre> | ||||
@@ -93,11 +107,12 @@ public interface WxMpPayService { | |||||
* @param refundId 微信退款单号 | * @param refundId 微信退款单号 | ||||
* @return 退款信息 | * @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; | 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.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 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.bean.result.WxError; | ||||
import me.chanjar.weixin.common.exception.WxErrorException; | import me.chanjar.weixin.common.exception.WxErrorException; | ||||
import me.chanjar.weixin.common.util.BeanUtils; | 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.codec.digest.DigestUtils; | ||||
import org.apache.commons.lang3.ArrayUtils; | import org.apache.commons.lang3.ArrayUtils; | ||||
import org.apache.commons.lang3.CharEncoding; | |||||
import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
import org.apache.http.Consts; | 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.CloseableHttpResponse; | ||||
import org.apache.http.client.methods.HttpPost; | import org.apache.http.client.methods.HttpPost; | ||||
import org.apache.http.conn.ssl.DefaultHostnameVerifier; | import org.apache.http.conn.ssl.DefaultHostnameVerifier; | ||||
@@ -28,7 +29,7 @@ import org.slf4j.LoggerFactory; | |||||
import javax.net.ssl.SSLContext; | import javax.net.ssl.SSLContext; | ||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | |||||
import java.io.UnsupportedEncodingException; | |||||
import java.util.*; | import java.util.*; | ||||
/** | /** | ||||
@@ -36,28 +37,31 @@ import java.util.*; | |||||
* | * | ||||
* @author binarywang (https://github.com/binarywang) | * @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 PAY_BASE_URL = "https://api.mch.weixin.qq.com"; | ||||
private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"}; | 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[] 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 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 + "/sandboxnew"; | ||||
} | } | ||||
return PAY_BASE_URL; | return PAY_BASE_URL; | ||||
} | } | ||||
@@ -65,22 +69,27 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException { | public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException { | ||||
this.initRequest(request); | this.initRequest(request); | ||||
if (StringUtils.isBlank(request.getOpUserId())) { | if (StringUtils.isBlank(request.getOpUserId())) { | ||||
request.setOpUserId(this.getConfig().getPartnerId()); | |||||
request.setOpUserId(this.getConfig().getMchId()); | |||||
} | } | ||||
this.checkParameters(request); | this.checkParameters(request); | ||||
request.setSign(this.createSign(request)); | request.setSign(this.createSign(request)); | ||||
String url = this.getPayBaseUrl() + "/secapi/pay/refund"; | 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); | WxPayRefundResult result = WxPayRefundResult.fromXML(responseContent, WxPayRefundResult.class); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
return result; | return result; | ||||
} | } | ||||
@Override | @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 必须四选一"); | 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)); | request.setSign(this.createSign(request)); | ||||
String url = this.getPayBaseUrl() + "/pay/refundquery"; | 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); | WxPayRefundQueryResult result = WxPayRefundQueryResult.fromXML(responseContent, WxPayRefundQueryResult.class); | ||||
result.composeRefundRecords(); | result.composeRefundRecords(); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
return result; | return result; | ||||
} | } | ||||
private void checkResult(WxPayBaseResult result) throws WxErrorException { | private void checkResult(WxPayBaseResult result) throws WxErrorException { | ||||
//校验返回结果签名 | //校验返回结果签名 | ||||
Map<String, String> map = result.toMap(); | Map<String, String> map = result.toMap(); | ||||
if (result.getSign() != null &&!this.checkSign(map)) { | |||||
if (result.getSign() != null && !this.checkSign(map)) { | |||||
log.debug("校验结果签名失败,参数:{}", map); | log.debug("校验结果签名失败,参数:{}", map); | ||||
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); | throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); | ||||
} | } | ||||
@@ -112,12 +120,28 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
//校验结果是否成功 | //校验结果是否成功 | ||||
if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode()) | if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode()) | ||||
|| !"SUCCESS".equalsIgnoreCase(result.getResultCode())) { | || !"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(); | .build(); | ||||
log.error("结果业务代码异常,参数:{},详细:{}", map, error); | |||||
log.error("\n结果业务代码异常,返回結果:{},\n{}", map, error); | |||||
throw new WxErrorException(error); | throw new WxErrorException(error); | ||||
} | } | ||||
} | } | ||||
@@ -129,8 +153,9 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
throw new IllegalArgumentException("tar_type值如果存在,只能为GZIP"); | 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 (StringUtils.isNotBlank(request.getRefundAccount())) { | ||||
if (!ArrayUtils.contains(REFUND_ACCOUNT, request.getRefundAccount())) { | if (!ArrayUtils.contains(REFUND_ACCOUNT, request.getRefundAccount())) { | ||||
throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT) + "其中之一,实际值:" + request.getRefundAccount()); | |||||
throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT) | |||||
+ "其中之一,实际值:" + request.getRefundAccount()); | |||||
} | } | ||||
} | } | ||||
@@ -152,7 +178,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
@Override | @Override | ||||
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException { | public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException { | ||||
try { | try { | ||||
log.trace("微信支付回调参数详细:{}", xmlData); | |||||
log.debug("微信支付回调参数详细:{}", xmlData); | |||||
WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData); | WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData); | ||||
log.debug("微信支付回调结果对象:{}", result); | log.debug("微信支付回调结果对象:{}", result); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
@@ -177,7 +203,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
//裂变红包 | //裂变红包 | ||||
url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack"; | 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); | WxPaySendRedpackResult result = WxPaySendRedpackResult.fromXML(responseContent, WxPaySendRedpackResult.class); | ||||
//毋须校验,因为没有返回签名信息 | //毋须校验,因为没有返回签名信息 | ||||
// this.checkResult(result); | // this.checkResult(result); | ||||
@@ -193,7 +219,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
request.setSign(this.createSign(request)); | request.setSign(this.createSign(request)); | ||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo"; | 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); | WxPayRedpackQueryResult result = WxPayRedpackQueryResult.fromXML(responseContent, WxPayRedpackQueryResult.class); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
return result; | return result; | ||||
@@ -213,7 +239,11 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
request.setSign(this.createSign(request)); | request.setSign(this.createSign(request)); | ||||
String url = this.getPayBaseUrl() + "/pay/orderquery"; | 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); | WxPayOrderQueryResult result = WxPayOrderQueryResult.fromXML(responseContent, WxPayOrderQueryResult.class); | ||||
result.composeCoupons(); | result.composeCoupons(); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
@@ -223,17 +253,17 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
@Override | @Override | ||||
public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException { | public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException { | ||||
if (StringUtils.isBlank(outTradeNo)) { | if (StringUtils.isBlank(outTradeNo)) { | ||||
throw new IllegalArgumentException("out_trade_no 不能为空"); | |||||
throw new IllegalArgumentException("out_trade_no不能为空"); | |||||
} | } | ||||
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); | WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); | ||||
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); | request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); | ||||
initRequest(request); | |||||
this.initRequest(request); | |||||
request.setSign(this.createSign(request)); | request.setSign(this.createSign(request)); | ||||
String url = this.getPayBaseUrl() + "/pay/closeorder"; | 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); | this.checkResult(result); | ||||
return result; | return result; | ||||
@@ -242,23 +272,20 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
@Override | @Override | ||||
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) | public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) | ||||
throws WxErrorException { | throws WxErrorException { | ||||
this.initRequest(request); | this.initRequest(request); | ||||
if (StringUtils.isBlank(request.getNotifyURL())) { | if (StringUtils.isBlank(request.getNotifyURL())) { | ||||
request.setNotifyURL(getConfig().getNotifyURL()); | |||||
request.setNotifyURL(getConfig().getNotifyUrl()); | |||||
} | } | ||||
if (StringUtils.isBlank(request.getTradeType())) { | if (StringUtils.isBlank(request.getTradeType())) { | ||||
request.setTradeType(getConfig().getTradeType()); | request.setTradeType(getConfig().getTradeType()); | ||||
} | } | ||||
checkParameters(request);//校验参数 | |||||
this.checkParameters(request);//校验参数 | |||||
request.setSign(this.createSign(request)); | request.setSign(this.createSign(request)); | ||||
String url = this.getPayBaseUrl() + "/pay/unifiedorder"; | 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); | WxPayUnifiedOrderResult result = WxPayUnifiedOrderResult.fromXML(responseContent, WxPayUnifiedOrderResult.class); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
return result; | return result; | ||||
@@ -266,11 +293,21 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
private void initRequest(WxPayBaseRequest request) { | private void initRequest(WxPayBaseRequest request) { | ||||
if (StringUtils.isBlank(request.getAppid())) { | if (StringUtils.isBlank(request.getAppid())) { | ||||
request.setAppid(getConfig().getAppId()); | |||||
request.setAppid(this.getConfig().getAppId()); | |||||
} | } | ||||
if (StringUtils.isBlank(request.getMchId())) { | 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())) { | if (StringUtils.isBlank(request.getNonceStr())) { | ||||
request.setNonceStr(String.valueOf(System.currentTimeMillis())); | request.setNonceStr(String.valueOf(System.currentTimeMillis())); | ||||
} | } | ||||
@@ -297,13 +334,14 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request); | WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request); | ||||
String prepayId = unifiedOrderResult.getPrepayId(); | String prepayId = unifiedOrderResult.getPrepayId(); | ||||
if (StringUtils.isBlank(prepayId)) { | 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())); | unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes())); | ||||
} | } | ||||
Map<String, String> payInfo = new HashMap<>(); | Map<String, String> payInfo = new HashMap<>(); | ||||
payInfo.put("appId", getConfig().getAppId()); | payInfo.put("appId", getConfig().getAppId()); | ||||
// 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 | |||||
// 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。 | |||||
// 但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 | |||||
payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); | payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); | ||||
payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis())); | payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis())); | ||||
payInfo.put("package", "prepay_id=" + prepayId); | payInfo.put("package", "prepay_id=" + prepayId); | ||||
@@ -323,7 +361,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers"; | 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); | WxEntPayResult result = WxEntPayResult.fromXML(responseContent, WxEntPayResult.class); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
return result; | return result; | ||||
@@ -336,7 +374,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
request.setSign(this.createSign(request)); | request.setSign(this.createSign(request)); | ||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo"; | 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); | WxEntPayQueryResult result = WxEntPayQueryResult.fromXML(responseContent, WxEntPayQueryResult.class); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
return result; | return result; | ||||
@@ -348,7 +386,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?"); | StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?"); | ||||
Map<String, String> params = Maps.newHashMap(); | Map<String, String> params = Maps.newHashMap(); | ||||
params.put("appid", this.getConfig().getAppId()); | 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("product_id", productId); | ||||
params.put("time_stamp", String.valueOf(System.currentTimeMillis())); | params.put("time_stamp", String.valueOf(System.currentTimeMillis())); | ||||
params.put("nonce_str", 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)); | request.setSign(this.createSign(request)); | ||||
String url = this.getPayBaseUrl() + "/payitil/report"; | 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); | WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
} | } | ||||
@@ -401,7 +439,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
String url = this.getPayBaseUrl() + "/pay/downloadbill"; | String url = this.getPayBaseUrl() + "/pay/downloadbill"; | ||||
//TODO 返回的内容可能是文件流,也有可能是xml,需要区分对待 | //TODO 返回的内容可能是文件流,也有可能是xml,需要区分对待 | ||||
String responseContent = this.wxMpService.post(url, request.toXML()); | |||||
String responseContent = this.post(url, request.toXML()); | |||||
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); | WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); | ||||
this.checkResult(result); | this.checkResult(result); | ||||
@@ -409,42 +447,41 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
return null; | 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 { | try { | ||||
SSLContext sslContext = getConfig().getSslContext(); | |||||
SSLContext sslContext = this.getConfig().getSslContext(); | |||||
if (null == sslContext) { | 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); | 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()) { | try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) { | ||||
httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1"))); | httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1"))); | ||||
@@ -464,7 +501,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
@Override | @Override | ||||
public String createSign(Object xmlBean) { | public String createSign(Object xmlBean) { | ||||
return this.createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); | |||||
return this.createSign(BeanUtils.xmlBean2Map(xmlBean), this.getConfig().getMchKey()); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -474,14 +511,14 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
@Override | @Override | ||||
public String createSign(Map<String, String> params) { | public String createSign(Map<String, String> params) { | ||||
return this.createSign(params, this.getConfig().getPartnerKey()); | |||||
return this.createSign(params, this.getConfig().getMchKey()); | |||||
} | } | ||||
@Override | @Override | ||||
public String createSign(Map<String, String> params, String signKey) { | public String createSign(Map<String, String> params, String signKey) { | ||||
if(this.getConfig().useSandboxForWxPay()){ | |||||
if (this.getConfig().useSandboxForWxPay()) { | |||||
//使用仿真测试环境 | //使用仿真测试环境 | ||||
//TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用这个仿真测试环境 | |||||
//TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用仿真测试环境 | |||||
signKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456"; | signKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456"; | ||||
//return "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456"; | //return "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456"; | ||||
} | } | ||||
@@ -502,7 +539,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
@Override | @Override | ||||
public boolean checkSign(Object xmlBean) { | public boolean checkSign(Object xmlBean) { | ||||
return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); | |||||
return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getMchKey()); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -512,7 +549,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
@Override | @Override | ||||
public boolean checkSign(Map<String, String> params) { | public boolean checkSign(Map<String, String> params) { | ||||
return this.checkSign(params, getConfig().getPartnerKey()); | |||||
return this.checkSign(params, getConfig().getMchKey()); | |||||
} | } | ||||
@Override | @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.*; | ||||
import org.testng.annotations.*; | 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.*; | ||||
import org.testng.annotations.*; | 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.*; |
@@ -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 com.thoughtworks.xstream.XStream; | ||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer; | 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; | |||||
} | |||||
} |
@@ -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> |
@@ -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> |