Merge branches 'develop-Actinia' and 'master' of https://git.oschina.net/egzosn/pay-java-parent into develop-Actinia

# Conflicts:
#	README.md
This commit is contained in:
Actinia-517
2017-12-05 16:32:06 +08:00
9 changed files with 107 additions and 42 deletions

View File

@@ -1,21 +1,25 @@
#pay-java-parent
## 整合支付模块
##整合支付模块(微信支付,支付宝)
声明: 本项目最初想法自 https://github.com/chanjarster/weixin-java-tools, 15年1月左右关注chanjarster/weixin-java-tools并将其回调处理修改并进行使用。
开发版 https://git.oschina.net/egzosn/pay-java-parent/tree/develop
##### 详细文档请看 [wiki](https://gitee.com/egzosn/pay-java-parent/wikis/Home)。
### 特性
1. 不依赖任何 mvc 框架
2. 也不依赖 servlet仅仅作为工具使用可轻松嵌入到任何系统里项目例子利用spring mvc的 @PathVariable进行,推荐使用类似的框架)
3. 支付请求调用支持HTTP和异步、支持http代理
4. 控制层统一异常处理
5. LogBack日志记录
6. 简单快速完成支付模块的开发
7. 支持多种支付类型多支付账户扩展
7. 支持多种支付类型多支付账户扩展(目前已支持微信支付,支付宝支付,友店支付)
### 本项目包含 3 个部分:
@@ -55,8 +59,8 @@
###### 单一支付教程
[基础模块支付宝微信讲解](pay-java-parent/wikis/Home)
[基础模块支付宝微信讲解](https://gitee.com/egzosn/pay-java-parent/wikis/Home)
[友店微信](pay-java-wx-youdian?dir=1&filepath=pay-java-youdian)
[富友](pay-java-fuiou?dir=1&filepath=pay-java-fuiou)

View File

@@ -25,7 +25,7 @@ public class PayTest {
AliPayConfigStorage aliPayConfigStorage = new AliPayConfigStorage();
aliPayConfigStorage.setPid("合作者id");
aliPayConfigStorage.setAppId("应用id");
aliPayConfigStorage.setAliPublicKey("支付宝公钥");
aliPayConfigStorage.setKeyPublic("支付宝公钥");
aliPayConfigStorage.setKeyPrivate("应用私钥");
aliPayConfigStorage.setNotifyUrl("异步回调地址");
aliPayConfigStorage.setReturnUrl("同步回调地址");

View File

@@ -190,4 +190,23 @@ public class PayOrder {
public void setOpenid(String openid) {
this.openid = openid;
}
@Override
public String toString() {
return "PayOrder{" +
"subject='" + subject + '\'' +
", body='" + body + '\'' +
", price=" + price +
", outTradeNo='" + outTradeNo + '\'' +
", bankType='" + bankType + '\'' +
", deviceInfo='" + deviceInfo + '\'' +
", spbillCreateIp='" + spbillCreateIp + '\'' +
", authCode='" + authCode + '\'' +
", wapUrl='" + wapUrl + '\'' +
", wapName='" + wapName + '\'' +
", openid='" + openid + '\'' +
", transactionType=" + transactionType +
", curType=" + curType +
'}';
}
}

View File

@@ -153,9 +153,10 @@ public class Base64 {
Objects.requireNonNull(lineSeparator);
int[] base64 = Decoder.fromBase64;
for (byte b : lineSeparator) {
if (base64[b & 0xff] != -1)
if (base64[b & 0xff] != -1){
throw new IllegalArgumentException(
"Illegal base64 line separator character 0x" + Integer.toString(b, 16));
}
}
if (lineLength <= 0) {
return Encoder.RFC4648;
@@ -264,8 +265,9 @@ public class Base64 {
int n = srclen % 3;
len = 4 * (srclen / 3) + (n == 0 ? 0 : n + 1);
}
if (linemax > 0) // line separators
if (linemax > 0) { // line separators
len += (len - 1) / linemax * newline.length;
}
return len;
}
@@ -283,8 +285,9 @@ public class Base64 {
int len = outLength(src.length); // dst array size
byte[] dst = new byte[len];
int ret = encode0(src, 0, src.length, dst);
if (ret != dst.length)
if (ret != dst.length) {
return Arrays.copyOf(dst, ret);
}
return dst;
}
@@ -367,8 +370,9 @@ public class Base64 {
buffer.get(src);
ret = encode0(src, 0, src.length, dst);
}
if (ret != dst.length)
if (ret != dst.length) {
dst = Arrays.copyOf(dst, ret);
}
return ByteBuffer.wrap(dst);
}
@@ -415,8 +419,9 @@ public class Base64 {
int sp = off;
int slen = (end - off) / 3 * 3;
int sl = off + slen;
if (linemax > 0 && slen > linemax / 4 * 3)
if (linemax > 0 && slen > linemax / 4 * 3){
slen = linemax / 4 * 3;
}
int dp = 0;
while (sp < sl) {
int sl0 = Math.min(sp + slen, sl);
@@ -507,8 +512,9 @@ public class Base64 {
private static final int[] fromBase64 = new int[256];
static {
Arrays.fill(fromBase64, -1);
for (int i = 0; i < Encoder.toBase64.length; i++)
for (int i = 0; i < Encoder.toBase64.length; i++){
fromBase64[Encoder.toBase64[i]] = i;
}
fromBase64['='] = -2;
}
@@ -520,8 +526,9 @@ public class Base64 {
static {
Arrays.fill(fromBase64URL, -1);
for (int i = 0; i < Encoder.toBase64URL.length; i++)
for (int i = 0; i < Encoder.toBase64URL.length; i++){
fromBase64URL[Encoder.toBase64URL[i]] = i;
}
fromBase64URL['='] = -2;
}
@@ -568,6 +575,9 @@ public class Base64 {
* if {@code src} is not in valid Base64 scheme
*/
public byte[] decode(String src) {
if (null != src){
src = src.replaceAll("[\r\n]", "");
}
return decode(src.getBytes(StandardCharsets.ISO_8859_1));
}
@@ -673,11 +683,13 @@ public class Base64 {
int[] base64 = isURL ? fromBase64URL : fromBase64;
int paddings = 0;
int len = sl - sp;
if (len == 0)
if (len == 0){
return 0;
}
if (len < 2) {
if (isMIME && base64[0] == -1)
if (isMIME && base64[0] == -1){
return 0;
}
throw new IllegalArgumentException(
"Input byte[] should at least have 2 bytes for base64 bytes");
}
@@ -698,12 +710,14 @@ public class Base64 {
} else {
if (src[sl - 1] == '=') {
paddings++;
if (src[sl - 2] == '=')
if (src[sl - 2] == '=') {
paddings++;
}
}
}
if (paddings == 0 && (len & 0x3) != 0)
if (paddings == 0 && (len & 0x3) != 0) {
paddings = 4 - (len & 0x3);
}
return 3 * ((len + 3) / 4) - paddings;
}
@@ -728,12 +742,14 @@ public class Base64 {
}
break;
}
if (isMIME) // skip if for rfc2045
if (isMIME){ // skip if for rfc2045
continue;
else
}
else{
throw new IllegalArgumentException(
"Illegal base64 character " +
Integer.toString(src[sp - 1], 16));
}
}
bits |= (b << shiftto);
shiftto -= 6;
@@ -759,8 +775,9 @@ public class Base64 {
// anything left is invalid, if is not MIME.
// if MIME, ignore all non-base64 character
while (sp < sl) {
if (isMIME && base64[src[sp++]] < 0)
if (isMIME && base64[src[sp++]] < 0) {
continue;
}
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
}
@@ -808,12 +825,15 @@ public class Base64 {
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (closed)
if (closed) {
throw new IOException("Stream is closed");
if (off < 0 || len < 0 || off + len > b.length)
}
if (off < 0 || len < 0 || off + len > b.length) {
throw new ArrayIndexOutOfBoundsException();
if (len == 0)
}
if (len == 0) {
return;
}
if (leftover != 0) {
if (leftover == 1) {
b1 = b[off++] & 0xff;
@@ -911,17 +931,21 @@ public class Base64 {
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (closed)
if (closed) {
throw new IOException("Stream is closed");
if (eof && nextout < 0) // eof and no leftover
}
if (eof && nextout < 0) { // eof and no leftover
return -1;
if (off < 0 || len < 0 || len > b.length - off)
}
if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
int oldOff = off;
if (nextout >= 0) { // leftover output byte(s) in bits buf
do {
if (len == 0)
if (len == 0) {
return off - oldOff;
}
b[off++] = (byte)(bits >> nextout);
len--;
nextout -= 8;
@@ -933,8 +957,9 @@ public class Base64 {
if (v == -1) {
eof = true;
if (nextin != 18) {
if (nextin == 12)
if (nextin == 12) {
throw new IOException("Base64 stream has one un-decoded dangling byte.");
}
// treat ending xx/xxx without padding character legal.
// same logic as v == '=' below
b[off++] = (byte)(bits >> (16));
@@ -948,10 +973,11 @@ public class Base64 {
}
}
}
if (off == oldOff)
if (off == oldOff) {
return -1;
else
}else {
return off - oldOff;
}
}
if (v == '=') { // padding byte(s)
// = shiftto==18 unnecessary padding
@@ -976,11 +1002,12 @@ public class Base64 {
break;
}
if ((v = base64[v]) == -1) {
if (isMIME) // skip if for rfc2045
if (isMIME) { // skip if for rfc2045
continue;
else
}else {
throw new IOException("Illegal base64 character " +
Integer.toString(v, 16));
}
}
bits |= (v << nextin);
if (nextin == 0) {
@@ -1004,8 +1031,9 @@ public class Base64 {
@Override
public int available() throws IOException {
if (closed)
if (closed) {
throw new IOException("Stream is closed");
}
return is.available(); // TBD:
}

View File

@@ -51,8 +51,8 @@ public class ApyAccountRepository {
apyAccount2.setPartner("1469188802");
apyAccount2.setAppid("wx3344f4aed352deae");
// TODO 2017/2/9 16:20 author: egan sign_type只有单一key时public_key与private_key相等比如sign_type=MD5的情况
apyAccount2.setPublicKey("991ded0800933ccf8736ab4f7fc61095");
apyAccount2.setPrivateKey("991ded0800933ccf8736ab4f7fc61095");
apyAccount2.setPublicKey("991ded080***************f7fc61095");
apyAccount2.setPrivateKey("991ded080***************f7fc61095");
apyAccount2.setNotifyUrl("http://pay.egzosn.com/payBack2.json");
// 无需同步回调可不填
apyAccount2.setReturnUrl("http://pay.egzosn.com");

View File

@@ -111,4 +111,20 @@ public class QueryOrder {
public void setTransactionType(String transactionType) {
this.transactionType = transactionType;
}
@Override
public String toString() {
return "QueryOrder{" +
"payId=" + payId +
", tradeNo='" + tradeNo + '\'' +
", outTradeNo='" + outTradeNo + '\'' +
", refundAmount=" + refundAmount +
", totalAmount=" + totalAmount +
", billDate=" + billDate +
", billType='" + billType + '\'' +
", tradeNoOrBillDate=" + tradeNoOrBillDate +
", outTradeNoBillType='" + outTradeNoBillType + '\'' +
", transactionType='" + transactionType + '\'' +
'}';
}
}

View File

@@ -45,7 +45,6 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
* @see #getPid()
*/
@Deprecated
@Override
public String getPartner () {
return merId;
}

View File

@@ -20,6 +20,7 @@ import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
@@ -153,7 +154,7 @@ public class WxPayService extends BasePayService {
parameters.put("body", order.getSubject());// 购买支付信息
parameters.put("out_trade_no", order.getOutTradeNo());// 订单号
parameters.put("spbill_create_ip", "192.168.1.150");
parameters.put("spbill_create_ip", StringUtils.isEmpty(order.getSpbillCreateIp()) ? "192.168.1.150" : order.getSpbillCreateIp() );
parameters.put("total_fee", order.getPrice().multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue());// 总金额单位为分
parameters.put("attach", order.getBody());
@@ -224,16 +225,14 @@ public class WxPayService extends BasePayService {
SortedMap<String, Object> params = new TreeMap<String, Object>();
params.put("partnerid", payConfigStorage.getPid());
params.put("package", "prepay_id=" + result.get("prepay_id"));
if (WxTransactionType.JSAPI == order.getTransactionType()) {
params.put("signType", payConfigStorage.getSignType());
params.put("appId", payConfigStorage.getAppid());
params.put("prepayid", result.get("prepay_id"));
params.put("timeStamp", System.currentTimeMillis() / 1000);
params.put("nonceStr", result.get("nonce_str"));
} else if (WxTransactionType.APP == order.getTransactionType()) {
params.put("partnerid", payConfigStorage.getPid());
params.put("appid", payConfigStorage.getAppid());
params.put("prepayid", result.get("prepay_id"));
params.put("timestamp", System.currentTimeMillis() / 1000);
@@ -328,8 +327,8 @@ public class WxPayService extends BasePayService {
if (!"SUCCESS".equals(orderInfo.get("return_code"))) {
throw new PayErrorException(new WxPayError((String) orderInfo.get("return_code"), (String) orderInfo.get("return_msg")));
}
if (WxTransactionType.MWEB.equals(orderInfo.get("trade_type"))) {
return "<script type=\"text/javascript\">location.href=\"" + orderInfo.get("mweb_url") + ";\"</script>";
if (WxTransactionType.MWEB.name().equals(orderInfo.get("trade_type"))) {
return String.format("<script type=\"text/javascript\">location.href=\"%s%s\"</script>",orderInfo.get("mweb_url"), StringUtils.isEmpty(payConfigStorage.getReturnUrl()) ? "" : "&redirect_url=" + URLEncoder.encode(payConfigStorage.getReturnUrl()));
}
throw new UnsupportedOperationException();
@@ -584,7 +583,7 @@ public class WxPayService extends BasePayService {
}
//获取公共参数
Map<String, Object> parameters = new HashMap<>();//getPublicParameters();
Map<String, Object> parameters = getPublicParameters();
if (StringUtils.isEmpty((String)transactionIdOrBillDate)){
parameters.put("out_trade_no", outTradeNoBillType);
}else {