Skip to content

Commit

Permalink
* prerelease of 0.4.0
Browse files Browse the repository at this point in the history
* completely refactored version, whose functionality is similar to 0.3.3
! not production ready, need further test.
  • Loading branch information
cuter44 committed May 20, 2015
1 parent f65c782 commit e4daf28
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 77 deletions.
3 changes: 2 additions & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<property name="rtlibdir" value="lib" />
<property name="javadocdir" value="javadoc" />
<property name="destdir" value="bin" />
<property name="version" value="0.3.3" />
<property name="version" value="0.4.0" />
<property name="wxpay-api-version" value="3.3.7" />

<property name="webdir" value="web" />
Expand Down Expand Up @@ -54,6 +54,7 @@
<antcall target="copy-config" />
<javac srcdir="${srcdir}" destdir="${destdir}" failonerror="true" debug="true" includeantruntime="false" encoding="utf-8">
<compilerarg value="-Xlint:unchecked"/>
<compilerarg value="-Xlint:deprecation"/>
<classpath refid="classpath" />
</javac>
</target>
Expand Down
59 changes: 57 additions & 2 deletions src/com/github/cuter44/wxpay/WxpayFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.MissingResourceException;

import com.github.cuter44.wxpay.reqs.*;
import com.github.cuter44.wxmp.util.*;

/** 微信支付工厂
* <br />
Expand All @@ -15,8 +16,9 @@ public class WxpayFactory
{
// CONSTANT
private static final String RESOURCE_WXPAY_PROPERTIES = "/wxpay.properties";
//protected static final String KEY_APPID = "appid";
//protected static final String KEY_SECRET = "SECRET";

protected static final String KEY_APPID = "appid";
protected static final String KEY_SECRET = "SECRET";

// CONFIG
protected Properties conf;
Expand All @@ -26,6 +28,54 @@ public Properties getConf()
return(this.conf);
}

// KEEPER
protected TokenKeeper tokenKeeper;

public TokenKeeper getTokenKeeper()
{
return(this.tokenKeeper);
}

/** 如果需要从工厂生成 pay请求, 且构造方法中未传入 appid 和 secret,
* 则需要以此方法手动初始化 TokenKeeper. 带参的构造方法会尝试在配置完成后调用这个方法, 如果传参
* 包含 appid 和 secret 则无需再手动配置.
* TokenKeeper 为所有请求及默认实现的 servlet 保持 access token 和 jsapi ticket 的缓存及刷新服务.
* 必需在 servlet 初始化前完成对这个方法的调用, 并且在 WxpayFactory 生命周期中只调用一次.
*/
public WxpayFactory initTokenKeeper(String appid, String secret)
{
this.tokenKeeper = TokenKeeper.getInstance(appid, secret);

return(this);
}

/** Initialize TokenKeeper according to <code>conf</code>.
* Invoke once only.
* Auto invoked by <code>new WxpayFactory(Properties conf)</code> and <code>new WxpayFactory(String resource)</code>.
*/
public WxpayFactory initTokenKeeper()
{
this.initTokenKeeper(
this.conf.getProperty(KEY_APPID),
this.conf.getProperty(KEY_SECRET)
);

return(this);
}

/** Initialize WxmpRequestBase (loading certificates) according to <code>conf</code>.
* Invoke once only.
* Auto invoked by <code>new WxpayFactory(Properties conf)</code> and <code>new WxpayFactory(String resource)</code>.
*/
public WxpayFactory initRequestBase()
{
WxpayRequestBase.configDefaultHC(
new CertificateLoader().config(this.conf).asSSLContext()
);

return(this);
}

// CONSTRUCT
/** Construct a new instance with blank config.
*/
Expand All @@ -42,6 +92,9 @@ public WxpayFactory(Properties aConf)
{
this.conf = aConf;

this.initTokenKeeper();
this.initRequestBase();

return;
}

Expand All @@ -60,6 +113,8 @@ public WxpayFactory(String resource)
"utf-8"
));

this.initTokenKeeper();
this.initRequestBase();

return;
}
Expand Down
3 changes: 1 addition & 2 deletions src/com/github/cuter44/wxpay/reqs/GetBrandWCPayRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ public String toJSON()

// EXECUTE
@Override
public ResponseBase execute()

public WxpayResponseBase execute()
{
throw(
new UnsupportedOperationException("This request does not execute on server side")
Expand Down
12 changes: 8 additions & 4 deletions src/com/github/cuter44/wxpay/reqs/UnifiedOrder.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.List;
import java.util.Properties;
import java.io.UnsupportedEncodingException;
import java.io.IOException;

import com.github.cuter44.wxpay.*;
import com.github.cuter44.wxpay.constants.*;
Expand Down Expand Up @@ -79,11 +80,14 @@ public String toURL()
// EXECUTE
@Override
public UnifiedOrderResponse execute()
throws IOException
{
return(
new UnifiedOrderResponse(
this.execute(URL_API_BASE, KEYS_PARAM_NAME)
));
String url = URL_API_BASE;
String body = this.toXml(KEYS_PARAM_NAME);

String respXml = this.executePostXML(url, body);

return(new UnifiedOrderResponse(respXml));
}

// PROPERTY
Expand Down
142 changes: 88 additions & 54 deletions src/com/github/cuter44/wxpay/reqs/WxpayRequestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@
import java.net.URL;
import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.net.URISyntaxException;
import javax.net.ssl.SSLContext;

import com.github.cuter44.nyafx.crypto.*;
import com.github.cuter44.nyafx.text.*;
import org.apache.http.client.fluent.*;
import org.apache.http.entity.ContentType;
import org.apache.http.*;
import org.apache.http.entity.*;
import org.apache.http.impl.client.*;
//import org.apache.http.client.*;
import org.apache.http.client.methods.*;

import com.github.cuter44.wxpay.WxpayException;
import com.github.cuter44.wxpay.WxpayProtocolException;
import com.github.cuter44.wxpay.resps.ResponseBase;
import static com.github.cuter44.wxpay.util.XMLParser.parseXML;
import com.github.cuter44.wxpay.resps.WxpayResponseBase;

/**
* @author galin<[email protected]>
Expand All @@ -31,18 +35,54 @@ public abstract class WxpayRequestBase
protected static final String KEY_NOTIFY_URL = "notify_url";
protected static final String KEY_NONCE_STR = "nonce_str";

protected static final String KEY_RETURN_CODE = "return_code";
protected static final String KEY_RETURN_MSG = "return_msg";
protected static final String KEY_ERR_CODE = "err_code";
protected static final String KEY_ERR_CODE_DES = "err_code_des";

protected static final String VALUE_SUCCESS = "SUCCESS";
protected static final String VALUE_FAIL = "FAIL";

protected static CryptoBase crypto = CryptoBase.getInstance();

/** Length of generated nonceStr, default to 8, in bytes
*/
protected static final int NONCE_STR_BYTES = 8;

// SSL
/** Default http client to use to send request to weixin server.
* Provide class-scope http client, which is used when <code>httpClient</code> is null, major for single-account use.
* You can tweak this with your own. This will takes effect on follow-up request whose <code>httpClient</code> is unset.
*/
public static CloseableHttpClient defaultHttpClient;

/** Http client to use to send request to weixin server.
* Provide object-scope http client, major for multi-account use.
* You can directly set this field. This will takes effect on time when <code>.execute()</code> is called.
* It is supposed that
*/
public CloseableHttpClient httpClient;

protected static CloseableHttpClient buildHttpClient(SSLContext ctx)
{
HttpClientBuilder hcb = HttpClientBuilder.create()
.disableAuthCaching()
.disableCookieManagement();

return(hcb.build());
}

/** Config defualt http client
* The existing <code>defaultHttpClient</code> will be dropped, without closing.
*/
public static void configDefaultHC(SSLContext ctx)
{
defaultHttpClient = buildHttpClient(ctx);
}

/** Config http client
* The existing <code>httpClient</code> will be dropped, without closing.
* @return this
*/
public WxpayRequestBase configHC(SSLContext ctx)
{
this.httpClient = buildHttpClient(ctx);

return(this);
}

// CONSTRUCT
public WxpayRequestBase(Properties aConf)
{
Expand Down Expand Up @@ -125,7 +165,7 @@ protected String signMD5(List<String> paramNames, String key)
throws UnsupportedEncodingException
{
if (key == null)
throw(new IllegalArgumentException("No KEY, no sign. Please check your configuration."));
throw(new IllegalArgumentException("KEY required to sign, but not found."));

StringBuilder sb = new StringBuilder()
.append(this.toQueryString(paramNames))
Expand Down Expand Up @@ -189,49 +229,43 @@ protected String toXml(List<String> paramNames)
// EXECUTE
/** Execute the constructed query
*/
public abstract ResponseBase execute()
throws WxpayException, WxpayProtocolException, UnsupportedOperationException;
public abstract WxpayResponseBase execute()
throws WxpayException, WxpayProtocolException, IOException;

/**
* @exception WxpayException if <code>err_code</code> is FAIL
* @exception WxpayProtocolException if <code>err_code</code> is FAIL
*/
public ResponseBase execute(String urlBase, List<String> paramNames)
throws WxpayException, WxpayProtocolException
protected static String toString(HttpResponse resp)
throws IOException
{
try
{
Properties prop = new Properties();

String content = Request.Post(urlBase)
.bodyString(
this.toXml(paramNames),
ContentType.create("text/xml", "utf-8")
)
.execute()
.returnContent()
.asString();

prop.putAll(parseXML(content));

if (VALUE_FAIL.equals(prop.getProperty(KEY_RETURN_CODE)))
throw(
new WxpayProtocolException(
prop.getProperty(KEY_RETURN_MSG)
));

if (VALUE_FAIL.equals(prop.getProperty(KEY_ERR_CODE)))
throw(
new WxpayException(
prop.getProperty(KEY_ERR_CODE)
));

return(new ResponseBase(content, prop));
}
catch (IOException ex)
{
throw(new WxpayException(ex));
}
HttpEntity he = resp.getEntity();

Long l = he.getContentLength();
ByteArrayOutputStream buffer = (l > 0) ? new ByteArrayOutputStream(l.intValue()) : new ByteArrayOutputStream();
resp.getEntity().writeTo(buffer);

String content = buffer.toString("utf-8");

return(content);
}

public String executePostXML(String fullURL, String bodyXML)
throws IOException
{
CloseableHttpClient hc = (this.httpClient != null) ? this.httpClient : defaultHttpClient;

HttpPost req = new HttpPost(fullURL);
req.setEntity(
new StringEntity(
bodyXML,
ContentType.create("text/xml", "utf-8")
)
);

CloseableHttpResponse resp = hc.execute(req);

String content = toString(resp);

resp.close();

return(content);
}

// MISC
Expand Down
4 changes: 2 additions & 2 deletions src/com/github/cuter44/wxpay/resps/Notify.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import com.github.cuter44.wxpay.constants.*;

public class Notify extends ResponseBase
public class Notify extends WxpayResponseBase
{
// CONSTANTS
//protected Boolean validity = null;
Expand Down Expand Up @@ -44,7 +44,7 @@ public class Notify extends ResponseBase


// CONSTRUCT
public Notify(ResponseBase resp)
public Notify(WxpayResponseBase resp)
{
this(resp.respString, resp.respProp);

Expand Down
6 changes: 3 additions & 3 deletions src/com/github/cuter44/wxpay/resps/UnifiedOrderResponse.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.github.cuter44.wxpay.resps;

public class UnifiedOrderResponse extends ResponseBase
public class UnifiedOrderResponse extends WxpayResponseBase
{
public UnifiedOrderResponse(ResponseBase resp)
public UnifiedOrderResponse(String respXml)
{
super(resp.respString, resp.respProp);
super(respXml);

return;
}
Expand Down
Loading

0 comments on commit e4daf28

Please sign in to comment.