支付宝和微信支付的接入基本只需要看官方文档就能很好的弄明白,这里我做记录一些我在接入是写demo
首先需要创建一个配置管理的类:
public final class ZhifubaoConfig {
/**
* 应用号
*/
public static String APP_ID = "2018080360956028";
/**
* 商户的私钥
*/
public static String APP_PRIVATE_KEY = ""; //这是在支付宝给的秘钥生成器 生成的私钥 用于用户加签
/**
*
* 编码
*/
public static String CHARSET = "UTF-8";
/**
* 支付宝公钥
*/
public static String ALIPAY_PUBLIC_KEY = " "; //这是支付宝平台的分配的支付公钥,主要用于验签支付宝平台返回给商户的信息, 这里需要特别主要的是要区分清楚 支付宝公钥 和 商户公钥的不同,商户公钥是用户自己生成的,需要上传至支付宝平台。
/**
* 支付宝网关地址
*/
private static String GATEWAY = "https://openapi.alipay.com/gateway.do";
/**
* 成功付款回调
*/
public static String PAY_NOTIFY = ""; // 商户的回调地址
/**
* 参数类型
*/
public static String PARAM_TYPE = "json";
/**
* 成功标识
*/
public static final String SUCCESS_REQUEST = "TRADE_SUCCESS";
/**
* 交易关闭回调(当该笔订单全部退款完毕,则交易关闭)
*/
public static final String TRADE_CLOSED = "TRADE_CLOSED";
/**
* 收款方账号
*/
public static final String SELLER_ID = ""; // 可以不用配置
/**
* 加密类型
*/
public static String SIGNTYPE = "RSA2";
/**
* 支付宝请求客户端入口
*/
private volatile static ZhifubaoConfig zhifubaoConfig= null;
/**
* 不可实例化
*/
private ZhifubaoConfig(){};
/**
* 双重锁单例
* @return 支付宝请求客户端实例
*/
public static ZhifubaoConfiggetInstance(){
if (alipayClient == null){
synchronized (AliPayConfig.class){
if (alipayClient == null){
zhifubaoConfig = new DefaultAlipayClient(GATEWAY,APP_ID,APP_PRIVATE_KEY,PARAM_TYPE,CHARSET,ALIPAY_PUBLIC_KEY,SIGNTYPE);
}
}
}
return alipayClient;
}
2.我这边把调用支付宝的逻辑代码封装了一下
public class ZhifubaoTrade {
private Logger logger = LoggerFactory.getLogger(ZhifubaoTrade .class);
/**
* APP支付下单并支付(APP支付在安卓中是可以直接唤醒支付宝APP的)
* url
* @return App支付单
*/
public String TradeWapPayRequest(AlipayTradeAppPayModel model){
AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest ();
alipayRequest.setReturnUrl(ZhifubaoConfig.RETURN_URL);
alipayRequest.setNotifyUrl(ZhifubaoConfig.PAY_NOTIFY);
alipayRequest.setBizModel(model);
String form = "";
try {
form = ZhifubaoConfig.getInstance().sdkExecute(alipayRequest).getBody();
System.err.println(form);
} catch (AlipayApiException e) {
logger.error("支付宝构造表单失败",e);
}
logger.debug("支付宝支付表单构造:"+form);
return form;
}
/**
* 申请退款
* @param sParaTemp 退款参数
* @return true成功,回调中处理
*/
public AlipayTradeRefundResponse tradeRefundRequest(Map sParaTemp) throws AlipayApiException {
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
request.setReturnUrl(ZhifubaoConfig.RETURN_URL);
request.setNotifyUrl(ZhifubaoConfig.REFUND_NOTIFY);
// 待请求参数数组
request.setBizContent(JSON.toJSONString(sParaTemp));
AlipayTradeRefundResponse response = ZhifubaoConfig.getInstance().execute(request);
System.err.println(response.getBody());
return response;
}
/**
* 支付宝回调验签
* @param request 回调请求
* @return true成功
* 备注:验签成功后,按照支付结果异步通知中的描述(二次验签接口,貌似称为历史接口了)
*/
public boolean verifyNotify(HttpServletRequest request) throws AlipayApiException {
Map paranMap = SignUtil.request2Map(request);
logger.debug("支付宝回调参数:"+paranMap.toString());
boolean isVerify = false;
if (ZhifubaoConfig.SUCCESS_REQUEST.equals(paranMap.get("trade_status")) || ZhifubaoConfig.TRADE_CLOSED.equals(paranMap.get("trade_status"))) {
isVerify = AlipaySignature.rsaCheckV1(paranMap, ZhifubaoConfig.ALIPAY_PUBLIC_KEY, ZhifubaoConfig.CHARSET); //调用SDK验证签名
}
logger.debug("支付宝验签结果"+isVerify);
return isVerify;
}
/**
* 查询订单支付状态
* @param sParaTemp
* @return
* @throws AlipayApiException
*/
public Map searchBill(Map sParaTemp) throws AlipayApiException{
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent(JSON.toJSONString(sParaTemp));
AlipayTradeQueryResponse response = ZhifubaoConfig.getInstance().execute(request);
System.err.println(response.isSuccess());
System.err.println(response.getBody());
if(response.isSuccess()){
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}
return null;
}
3 业务代码可以根据自己的需要组装,我这里贴一下我的
//-----------------支付相关--------------------------
int payType = Integer.valueOf(String.valueOf(data.get("payment_operation_way")));
Map paramMap = new HashMap<>();
paramMap.put("body", "时租看房");
paramMap.put("subject", "时租看房");
paramMap.put("code", code);
paramMap.put("amount", String.valueOf(data.get("amount")));
String resultStr = payMentService.doPay(payType, paramMap);
String payCode = "";
//创建支付订单
Map paymentM = new HashMap<>();
paymentM.put("trade_no", payCode);
paymentM.put("payment_operation_order_code", code);
paymentM.put("user_id", String.valueOf(data.get("user_id")));
paymentM.put("payment_operation_way", payType+"");
paymentM.put("payment_operation_type", "0");
paymentM.put("payment_operation_pay_way", "0");
paymentM.put("payment_amount", String.valueOf(data.get("amount")));
paymentM.put("status", "2");
paymentDao.createPaymentOperation(paymentM);
//预下单订单信息(返回给客户端)
map.put("payment_content", resultStr);
map.put("is_payment", "0");
//-----------------支付相关--------------------------
4 支付宝的部分回调代码
public String doCallback(HttpServletRequest request, HttpServletResponse reponse){
//获取支付宝POST过来反馈信息
String status = "";
Map params = new HashMap();
System.out.println("异步通知参数:");
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
if(name.equals("trade_status")){
status= valueStr;
System.out.println("交易状态为:"+valueStr);
}
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
System.out.println("params"+params);
String pk = "自己的支付宝公钥";
//验签 如果成功则说明是来自支付宝的回调
// 处理回调业务 成功后给支付宝返回成功 详细的可以看官方文档
}
配置文件:
public final class WechatConfig {
/**
* 用户的id
*/
public static final String APP_ID = "";
/**
* 身份密钥
*/
public static final String APP_SECRET = "";
/**
* 商户id
*/
public static final String MCH_ID = "";
/**
* 统一下单地址
*/
public static final String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
/**
* 交易退款地址
*/
public static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
/**
* 交易退款查询地址
*/
public static final String REFUND_QUERY = "https://api.mch.weixin.qq.com/pay/refundquery";
/**
* 支付成功回调
*/
public static final String NOTIFY_PAY = "";
/**
* 支付类型
*/
public static final String TRADE_TYPE = "APP";
/**
* 证书地址
*/
public static final String CERT_PATH = "C:\\Users\\hzcf\\Desktop\\微信\\apiclient_cert.p12";
/**
* 成功标识
*/
public static final String SUCCESS_REQUEST = "SUCCUSS";
/**
* 不可实例化
*/
private WechatConfig(){}
private volatile static WechatClient wechatClient = null;
/**
* 双重锁单例
* @return WechatClient实例
*/
public static WechatClient getInstance(){
if (wechatClient == null){
synchronized (WechatConfig.class){
if (wechatClient == null){
return new WechatClient(APP_ID,MCH_ID,APP_SECRET,TRADE_TYPE);
}
}
}
return wechatClient;
}
}
public class WechatClient {
private String app_id;
private String mch_id;
private String app_secret;
private String trade_type;
private static Logger logger = LoggerFactory.getLogger(WechatClient.class);
public WechatClient(String app_id, String mch_id, String app_secret, String trade_type) {
this.app_id = app_id;
this.mch_id = mch_id;
this.app_secret = app_secret;
this.trade_type = trade_type;
}
/**
* 统一下单,会自动签名和补上noce_str
* @return 下单后返回信息
*/
public WechatUnifiedOrder.Response unifiedOrder(WechatUnifiedOrder unifiedOrder){
unifiedOrder.setAppid(this.app_id);
unifiedOrder.setMch_id(this.mch_id);
unifiedOrder.setTrade_type(this.trade_type);
unifiedOrder.setNotify_url(WechatConfig.NOTIFY_PAY);
unifiedOrder.setNonce_str(nonce_str(16));
unifiedOrder.setSign(sign(SignUtil.bean2TreeMap(unifiedOrder)).toUpperCase());
String tempXmlStr = XmlUtil.beanToXml(new ByteArrayOutputStream(), unifiedOrder);
String requestXml = tempXmlStr!= null?tempXmlStr.substring(55):"";
logger.debug("xml转义后内容:"+requestXml);
try {
InputStreamEntity inputStreamEntity = new InputStreamEntity(
new ByteArrayInputStream(requestXml.getBytes("UTF-8")), ContentType.APPLICATION_XML);
String resultXml = WebUtils.post(WechatConfig.UNIFIEDORDER_URL,inputStreamEntity);
logger.debug("微信返回内容:"+resultXml);
return resultXml!= null
?XmlUtil.xmlToBean(resultXml, WechatUnifiedOrder.Response.class)
:new WechatUnifiedOrder.Response("FAIL");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new WechatUnifiedOrder.Response("FAIL");
}
/**
* 微信退货请求
* @param wechatRefund 退货请求参数
* @return 请求返回内容
*/
public WechatRefund.Response refund(WechatRefund wechatRefund){
wechatRefund.setAppid(this.app_id);
wechatRefund.setMch_id(this.mch_id);
wechatRefund.setNonce_str(nonce_str(16));
wechatRefund.setSign(sign(SignUtil.bean2TreeMap(wechatRefund)).toUpperCase());
String tempXmlStr = XmlUtil.beanToXml(new ByteArrayOutputStream(), wechatRefund);
String requestXml = tempXmlStr!= null?tempXmlStr.substring(55):"";
try {
InputStreamEntity inputStreamEntity = new InputStreamEntity(
new ByteArrayInputStream(requestXml.getBytes("UTF-8")), ContentType.APPLICATION_XML);
String resultXml = WebUtils.post(WechatConfig.CERT_PATH,WechatConfig.MCH_ID,WechatConfig.REFUND_URL,inputStreamEntity);
logger.debug("微信退货返回内容:"+resultXml);
return resultXml!= null
?XmlUtil.xmlToBean(resultXml, WechatRefund.Response.class)
:new WechatRefund.Response("FAIL");
} catch (Exception e) {
e.printStackTrace();
}
return new WechatRefund.Response("FAIL");
}
/**
* 微信退款查询
* @param wechatRefundQuery 要查询的请求
* @return 查询结果
*/
public WechatRefundQuery.Response refundQuery(WechatRefundQuery wechatRefundQuery){
wechatRefundQuery.setAppid(this.app_id);
wechatRefundQuery.setMch_id(this.mch_id);
wechatRefundQuery.setNonce_str(nonce_str(16));
wechatRefundQuery.setSign(sign(SignUtil.bean2TreeMap(wechatRefundQuery)).toUpperCase());
String tempXmlStr = XmlUtil.beanToXml(new ByteArrayOutputStream(), wechatRefundQuery);
String requestXml = tempXmlStr!= null?tempXmlStr.substring(55):"";
try {
InputStreamEntity inputStreamEntity = new InputStreamEntity(
new ByteArrayInputStream(requestXml.getBytes("UTF-8")), ContentType.APPLICATION_XML);
String resultXml = WebUtils.post(WechatConfig.REFUND_QUERY,inputStreamEntity);
logger.debug("微信退货查询内容:"+resultXml);
return resultXml!= null
?XmlUtil.xmlToBean(resultXml, WechatRefundQuery.Response.class)
:new WechatRefundQuery.Response("FAIL");
} catch (Exception e) {
e.printStackTrace();
}
return new WechatRefundQuery.Response("FAIL");
}
/**
* 对请求进行签名
* @param param 要签名的参数
* @return
*/
public String sign(TreeMap param){
String paramUrl = SignUtil.joinKeyValue(new TreeMap(param),null,"&key="+this.app_secret,"&",true,"sign_type","sign");
logger.debug("微信待签名串:"+paramUrl);
/* MessageDigest digestUtils = DigestUtils.getMd5Digest();
digestUtils.update(paramUrl.getBytes());
byte[] sign = digestUtils.digest();
String result = Hex.encodeHexString(sign);*/
String result = MD5Util.MD5Encode(paramUrl.toString(),"UTF-8").toUpperCase();
logger.debug("签名结果:"+result);
return result;
}
public String create_nonce_str() {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String res = "";
for (int i = 0; i < 32; i++) {
Random rd = new Random();
res += chars.charAt(rd.nextInt(chars.length() - 1));
}
return res;
}
/**
* 微信nonce_str生成算法
* @param bits 生成位数,选择64bit
* @return 生成后的nonce_str
*/
public String nonce_str(int bits) {
final byte[] bytes;
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
if ((bits % 8) != 0) {
throw new IllegalArgumentException("Size is not divisible by 8!");
}
bytes = new byte[bits / 8];
secureRandom.nextBytes(bytes);
return Hex.encodeHexString(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return System.currentTimeMillis()+"";
}
}
public class WechatTrade {
private static Logger logger = LoggerFactory.getLogger(WechatTrade.class);
/**
* 微信统一下单
* @param unifiedOrder 要下单的内容
* @return 返回H5下单请求需要内容
*/
public TreeMap unifiedOrderRequest(WechatUnifiedOrder unifiedOrder){
WechatUnifiedOrder.Response response = WechatConfig.getInstance().unifiedOrder(unifiedOrder);
if (response.getResult_code().equals(WechatConfig.SUCCESS_REQUEST)){
TreeMap prepareH5Pay = new TreeMap();
prepareH5Pay.put("appid", WechatConfig.APP_ID);
prepareH5Pay.put("partnerid", WechatConfig.MCH_ID);
prepareH5Pay.put("noncestr", WechatConfig.getInstance().nonce_str(16));
prepareH5Pay.put("package", "Sign=WXPay");
prepareH5Pay.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
prepareH5Pay.put("prepayid",response.getPrepay_id());
prepareH5Pay.put("sign", WechatConfig.getInstance().sign(prepareH5Pay));
return prepareH5Pay;
}
return null;
}
/**
* 微信退款请求
* @param refund 退款请求参数
* @return 返回参数(同步接口,直接返回),只有return_code和result_code都成功则退款成功
*/
public WechatRefund.Response refundRequest(WechatRefund refund){
WechatRefund.Response response = WechatConfig.getInstance().refund(refund);
return response;
}
/**
* 微信退款查询请求
* @param refund 退款请求参数
* @return 返回参数(同步接口,直接返回),只有return_code和result_code都成功则查询成功
*/
public WechatRefundQuery.Response refundQueryRequest(WechatRefundQuery refund){
WechatRefundQuery.Response response = WechatConfig.getInstance().refundQuery(refund);
return response;
}
/**
* 微信回调验签
* @param request 回调请求
* @return true成功
*/
public boolean verifyNotify(HttpServletRequest request){
try {
InputStream inputStream = request.getInputStream();
WechatPayNotify notice = XmlUtil.xmlToBean(inputStream, WechatPayNotify.class);
if (notice == null) return false;
logger.debug("微信回调参数:"+ JSON.toJSONString(notice));
String sign = WechatConfig.getInstance().sign(SignUtil.bean2TreeMap(notice));
boolean ischeck = sign.equals(notice.getSign());
logger.debug("微信验签结果:"+ischeck);
return ischeck;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}