@kangwg
2017-04-09T14:38:31.000000Z
字数 7452
阅读 1053
layout: post
title: "微信支付"
subtitle: "微信app支付,微信公众号支付,微信扫码支付"
date: 2017-04-09 12:00:00
author: "kangwg"
header-img: "img/post-bg-2015.jpg"
catalog: true
先导入微信的第三方依赖
<dependency>
<groupId>me.hao0</groupId>
<artifactId>wepay-core</artifactId>
<version>1.1.2</version>
</dependency>
先建微信支付的基类,然后各种支付类型的实现继承它
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Map;
import org.slf4j.*;
import com.google.common.base.Strings;
import cn.swao.baselib.util.*;
import me.hao0.wepay.core.*;
import me.hao0.wepay.exception.WepayException;
import me.hao0.wepay.model.order.WePayOrder;
import me.hao0.wepay.model.refund.*;
public class WxPayService {
private static Logger log = LoggerFactory.getLogger(WxPayService.class);
public Wepay wepay = null;
public final static SimpleDateFormat wxTimeFormat = new SimpleDateFormat("yyyyMMddHHmmss");
public String merchant = null;
public void setMerchant(String merchant) {
this.merchant = merchant;
}
public Wepay initWepay(String certPath, String appId, String payKey, String payMerchant, String certPasswd) {
if (Strings.isNullOrEmpty(certPath)) {
log.info("WxPay : no init.");
} else {
log.info("WxPay : init. " + certPath);
byte[] data = FsUtils.readBinaryFile(certPath);//读取证书
if (data == null)
log.error("WxPay : read cert error. " + certPath);
else
this.wepay = WepayBuilder.newBuilder(appId, payKey, payMerchant).certPasswd(certPasswd).certs(data).build();
}
return this.wepay;
}
public Notifies getNotifies() {
return this.wepay.notifies();
}
// 异步通知检验
public boolean notifyVerify(Map<String, ?> map) {
return getNotifies().verifySign(map);
}
// 订单查询
public WePayOrder getOrder(String outTradeNo) {
try {
return this.wepay.order().queryByOutTradeNo(outTradeNo);
} catch (WepayException e) {
log.error("WxPay getOrder", e);
return null;
}
}
// 退款
public RefundApplyResponse refund(String outTradeNo, BigDecimal fee) {
try {
log.info(LogUtils.gen("WxPay refund", "out_trade_no", outTradeNo));
Integer totalFee = fee.multiply(new BigDecimal(100)).intValue();
RefundApplyRequest req = new RefundApplyRequest();
req.setOutTradeNo(outTradeNo);
req.setOutRefundNo(outTradeNo);
req.setTotalFee(totalFee);
req.setRefundFee(totalFee);
req.setOpUserId(this.merchant);
RefundApplyResponse result = this.wepay.refund().apply(req);
log.info(LogUtils.gen("WxPay sucess", "RefundApplyResponse", result.toString()));
return result;
} catch (WepayException e) {
log.error("WxPay refund", e);
return null;
}
}
// 退款查询
public RefundQueryResponse getRefund(String outTradeNo) {
try {
return wepay.refund().queryByOutTradeNo(outTradeNo);
} catch (WepayException e) {
log.error("WxPay getRefund", e);
return null;
}
}
}
initWepay是对微信支付client对象初始化,其中还有通用的退款、查询、异步通知校验的方法。
1.app支付
import java.math.BigDecimal;
import java.net.*;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.slf4j.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.gson.JsonObject;
import cn.swao.baselib.util.*;
import me.hao0.wepay.model.pay.*;
@Service
public class WxAppService extends WxPayService {
private static Logger log = LoggerFactory.getLogger(WeixinMpService.class);
@Value("${open.appId:}")
private String appId = null;
@Value("${open.appSecret:}")
private String appSecret = null;
@Value("${open.pay.Merchant:}")
private String payMerchant = null;
@Value("${open.pay.Key:}")
private String payKey = null;
@Value("${open.pay.CertPasswd:}")
private String certPasswd = null;
@Value("${open.pay.CertPath:}")
private String certPath = null;
@Value("${open.pay.notifyUrl:}")
private String payNotifyUrl = null;
@PostConstruct
private void init() {
initWepay(certPath, appId, payKey, payMerchant, certPasswd);
setMerchant(this.payMerchant);
}
// app支付
public AppPayResponse getAppPay(String outTradeNo, BigDecimal fee, String body, String ip) {
log.info(LogUtils.gen("wxapp下单", "out_trade_no", outTradeNo, "body", body, "ip", ip));
PayRequest app = new PayRequest();
int totalFee = FinanceUtils.toFen(fee);
app.setBody(body);
app.setNotifyUrl(this.payNotifyUrl);
app.setOutTradeNo(outTradeNo);
app.setTotalFee(totalFee);
if (Strings.isNullOrEmpty(ip)) {
try {
ip = InetAddress.getLocalHost().getHostAddress();//如果ip为空,那么拿本机ip(防止拿不到ip导致的异常)
} catch (UnknownHostException e) {
}
}
app.setClientId(ip);
app.setTimeStart(DateUtils.nowString(wxTimeFormat));
Map<String, Object> attachMap = Maps.newHashMap();
attachMap.put("out_trade_no", outTradeNo);
attachMap.put("wxPayWay", "JSAPI");
app.setAttach(JSONUtils.toJson(attachMap));
try {
log.info(LogUtils.gen("app", app.toString()));
AppPayResponse appPay = super.wepay.pay().appPay(app);
log.info(LogUtils.gen("wxapp下单成功", "appPay", appPay.toString()));
return appPay;
} catch (Exception e) {
log.error("WxAppService getAppPay", e);
return null;
}
}
}
其中的方法是app统一支付下单的方法,其他的查询和异步验签只需要用父类的方法。@Value中的参数写在配置文件中,这些参数是app支付必要的一些参数 ,@PostConstruct项目启动后调用,获取微信支付的对象。
2.微信公众号支付和扫码支付
import cn.swao.baselib.model.NotifyTemplates;
import cn.swao.baselib.util.*;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.gson.JsonObject;
import me.hao0.wepay.exception.WepayException;
import me.hao0.wepay.model.pay.JsPayRequest;
import me.hao0.wepay.model.pay.JsPayResponse;
import me.hao0.wepay.model.pay.QrPayRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.*;
@Service
public class WeixinMpService extends WxPayService {
private static Logger log = LoggerFactory.getLogger(WeixinMpService.class);
@Value("${mp.appId:}")
private String appId = null;
@Value("${mp.appSecret:}")
private String appSecret = null;
@Value("${mp.pay.Merchant:}")
private String payMerchant = null;
@Value("${mp.pay.Key:}")
private String payKey = null;
@Value("${mp.pay.CertPasswd:}")
private String certPasswd = null;
@Value("${mp.pay.CertPath:}")
private String certPath = null;
@Value("${mp.pay.notifyUrl:}")
private String payNotifyUrl = null;
@PostConstruct
private void init() {
initWepay(this.certPath, this.appId, this.payKey, this.payMerchant, this.certPasswd);
setMerchant(this.payMerchant);
}
// 微信公众号支付
public JsPayResponse getJsPay(String outTradeNo, BigDecimal fee, String body, String ip, String openid) {
log.info(LogUtils.gen("开始统一下单", "out_trade_no", outTradeNo, "body", body, "ip", ip, "openid", openid));
int totalFee = FinanceUtils.toFen(fee);
JsPayRequest jpr = new JsPayRequest();
jpr.setBody(body);
jpr.setNotifyUrl(this.payNotifyUrl);
jpr.setOutTradeNo(outTradeNo);
jpr.setTotalFee(totalFee);
if (Strings.isNullOrEmpty(ip))
ip = SysUtils.getIp();
jpr.setClientId(ip);
jpr.setOpenId(openid);
jpr.setTimeStart(DateUtils.nowString(wxTimeFormat));
Map<String, Object> attachMap = Maps.newHashMap();
attachMap.put("out_trade_no", outTradeNo);
attachMap.put("wxPayWay", "JSAPI");
jpr.setAttach(JSONUtils.toJson(attachMap));
try {
log.info(LogUtils.gen("jpr", jpr.toString()));
JsPayResponse jsPay = this.wepay.pay().jsPay(jpr);
log.info(LogUtils.gen("统一下单成功", "JsPayResponse", jsPay.toString()));
return jsPay;
} catch (WepayException e) {
log.error("WeixinService getJsPay", e);
return null;
}
}
//扫码支付
public String getQrPay(String outTradeNo, BigDecimal fee, String body, String ip, String productId) {
log.info(LogUtils.gen("开始统一下单", "out_trade_no", outTradeNo, "body", body, "ip", ip, "productId", productId));
QrPayRequest qr = new QrPayRequest();
int totalFee = FinanceUtils.toFen(fee);
qr.setBody(body);
qr.setNotifyUrl(this.payNotifyUrl);
qr.setOutTradeNo(outTradeNo);
qr.setTotalFee(totalFee);
if (Strings.isNullOrEmpty(ip))
ip = SysUtils.getIp();//获取本机地址ip
qr.setClientId(ip);
qr.setTimeStart(DateUtils.nowString(wxTimeFormat));
qr.setProductId(productId);
String codeUrl = null;
try {
codeUrl = this.wepay.pay().qrPay(qr);
log.info("扫码支付 codeUrl:{}", codeUrl);
} catch (Exception e) {
log.error("扫码支付下单失败", e);
}
return codeUrl;
}
}