支付宝相关
package com.jg.controller.alipay;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.jg.constants.AlipayConfig;
import com.jg.domain.AlipayRefund;
import com.jg.domain.AlipayRequest;
import com.jg.query.AlipayQuery;
import com.jg.util.SerialNumber;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
*/
@Controller
@RequestMapping("/alipay")
public class AlipayController {
private static final Log logger = LogFactory.getLog(AlipayController.class);
@RequestMapping("/list")
public String returnPay(HttpServletResponse response)throws Exception{
/* response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=" + CHARSET);
PrintWriter out = response.getWriter();
out.println("<form name=\"punchout_form\" method=\"post\" action=\"https://openapi.alipay.com/gateway.do?charset=utf-8&method=alipay.trade.page.pay&sign=TDahjscloUt5vpwxRUH0ZwZAikCg37dI1nTst%2BpOoilt4AGFlJKHmLqsVDAViim%2FPkfLNhb%2Bp3faVMw9pF%2FpugTjLsxIeYVBRoWsZCmToJXxSp7YtwaLvVBzybUdvQ3E584AJQGcU8UaRzhCQTFQeQO1Juh6hFNS5mk3sf9g2DJuxWi9ub2Z4h%2BKTx2rD9gt%2FAykKJ0bb%2BgD3B3ymiJo3tWS%2BnWJwTDAvI%2BpPFtgtCRhrrEMxoAEI4PBTwBfNFz08OyTE0iNv%2B1%2FgM2BMIQ1tEPhY74GLdRpuHNN87jiN3HMUxxfALUU7gCa7QfZJGIwtohvkX2sDDKUefdsDGv6Nw%3D%3D&return_url=http%3A%2F%2F127.0.0.1%3A8080%2Falipay%2FreturnUrl¬ify_url=http%3A%2F%2F127.0.0.1%3A8080%2Falipay%2FnotifyUrl&version=1.0&app_id=2017101209270409&sign_type=RSA2×tamp=2018-12-19+17%3A59%3A08&alipay_sdk=alipay-sdk-java-dynamicVersionNo&format=json\">\n" +
"<input type=\"hidden\" name=\"biz_content\" value=\"{ "out_trade_no":"DDH20181219175908151", "product_code":"FAST_INSTANT_TRADE_PAY", "total_amount":0.01, "subject":"测试测试:0.01", "body":"测试测试:0.01" }\">\n" +
"<input type=\"submit\" value=\"立即支付\" style=\"display:none\" >\n" +
"</form>\n" +
"<script>document.forms[0].submit();</script>");
out.close();*/
return "pay";
}
@RequestMapping(value="/pay",method= RequestMethod.POST)
public void doPay( AlipayRequest aliRequest,ModelMap map, HttpServletRequest httpRequest, HttpServletResponse response) throws ServletException, IOException {
//获得初始化的AlipayClient
AlipayClient alipayClient = initAlipayClient();
//创建API对应的request
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
//在公共参数中设置回跳和通知地址
alipayRequest.setReturnUrl(AlipayConfig.PAY_URL + AlipayConfig.RETURN_URL);
alipayRequest.setNotifyUrl(AlipayConfig.PAY_URL + AlipayConfig.NOTIFY_URL);
response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
PrintWriter out = response.getWriter();
if(aliRequest.getTotalAmount()<0.01){
out.println("充值金额不能小于0.01元");
out.close();
}
//填充业务参数
// String subject = aliRequest.getSubject();
/* alipayRequest.setBizContent("{" +
" \"out_trade_no\":\"" + SerialNumber.generaterNextNumber("DDH") + "\"," +
" \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
" \"total_amount\":" + aliRequest.getTotalAmount() + "," +
" \"subject\":\"" + subject + "\"," +
" \"body\":\"" + aliRequest.getBody() + "\"" +
" }");*/
//第二种封装方式
//商户订单号,商户网站订单系统中唯一订单号,必填
String out_trade_no = SerialNumber.generaterNextNumber("DDH");
// 订单名称,必填
String subject = "充值金额:"+0.01;
// 付款金额,必填
String total_amount="0.01";
// 商品描述,可空
String body = "张三充值¥:"+total_amount;
// 封装请求支付信息
AlipayTradePagePayModel model=new AlipayTradePagePayModel();
model.setOutTradeNo(out_trade_no);
model.setSubject(subject);
model.setTotalAmount(total_amount);
model.setBody(body);
model.setTimeoutExpress("");
model.setPassbackParams("123");
// 销售产品码 必填
model.setProductCode("FAST_INSTANT_TRADE_PAY");
alipayRequest.setBizModel(model);
String form = "";
try {
form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
} catch (AlipayApiException e) {
e.printStackTrace();
}
out.println(form);
out.close();
}
/**
* pc端同步通知
* 不做业务
* @param
*/
@RequestMapping(value="/returnUrl")
public String returnUrl(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws Exception{
logger.info("------------------------------------pc同步通知-------------------------------------------");
//获取支付宝GET过来反馈信息
Map<String,String> params = getParamToMap(request.getParameterMap());
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGN_TYPE); //调用SDK验证签名
//——请在这里编写您的程序(以下代码仅作参考)——
if(signVerified) {
//商户订单号
String out_trade_no = params.get("out_trade_no");
//支付宝交易号
String trade_no = params.get("trade_no");
//付款金额
String total_amount = params.get("total_amount");
response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
logger.info("-----------------out_trade_no:"+out_trade_no+"trade_no:"+trade_no+"total_amount:"+total_amount+"---------------------");
map.put("result", "支付宝支付成功");
}else {
response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
map.put("result", "支付宝支付失败");
}
//——请在这里编写您的程序(以上代码仅作参考)——
return "alipayResult";
}
/**
* pc端异步通知
* 做相应的业务处理
*/
@RequestMapping(value="/notifyUrl",method= RequestMethod.POST)
public void notifyUrl(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws Exception{
try {
logger.info("------------------------------------pc异步通知-------------------------------------------");
//获取支付宝POST过来反馈信息并转为map
Map<String,String> params = getParamToMap(request.getParameterMap());
//logger.info("---------------------------------------------------------------params=========="+params);
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
//商户订单号
String out_trade_no = params.get("out_trade_no");
//支付宝交易号
String trade_no = params.get("trade_no");
//交易状态
String trade_status = params.get("trade_status");
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
//计算得出通知验证结果
//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");
logger.info("------------------------------------------支付宝异步通知页面验证成功:trade_finished------------------------------verify_result="+verify_result);
if(verify_result){//验证成功
//
//请在这里加上商户的业务逻辑程序代码
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
if(trade_status.equals("TRADE_FINISHED")){
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
//如果有做过处理,不执行商户的业务程序
logger.info("------------------------------------------支付宝异步通知页面验证成功:trade_finished------------------------------");
//注意:
//如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
//如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
} else if (trade_status.equals("TRADE_SUCCESS")){
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
//如果有做过处理,不执行商户的业务程序
logger.info("------------------------------------------支付宝异步通知页面验证成功:trade_success------------------------------");
//注意:
//如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
}
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
response.getWriter().println("success");
response.getWriter().close();
//
}else{//验证失败
response.getWriter().println("fail");
response.getWriter().close();
logger.info("-------------------------------fail-------------------------------");
}
} catch (Exception e) {
response.getWriter().println("fail");
response.getWriter().close();
logger.info("跳转到pc网站支付宝支付-同步不通知-页面-error");
e.printStackTrace();
}
}
/**
* 获取对应的参数转为map
* @param requestParams
* @return
*/
private Map<String,String> getParamToMap(Map<String,String[]> requestParams){
Map<String,String> params = new HashMap<String,String>();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
String valueStr = "";
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化。
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
params.put(name, valueStr);
}
return params;
}
/**
* 支付宝退款,签约的是可退款协议
* 可使用官方实体类:AlipayTradeRefundModel(setBizModel)
* @param map
* @throws Exception
*/
@RequestMapping(value="/refund",method= RequestMethod.POST)
public void refund(AlipayRefund refund, ModelMap map) throws Exception{
//获得初始化的AlipayClient
AlipayClient alipayClient = initAlipayClient();
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
//标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
request.setBizContent("{" +
" \"out_trade_no\":\""+refund.getOutTradeNo()+"\"," +
" \"trade_no\":\""+refund.getTradeNo()+"\"," +
" \"refund_amount\":"+refund.getRefundAmount()+"," +
" \"refund_reason\":\""+refund.getRefundReason()+"\"," +
" \"out_request_no\":\""+refund.getOutRequestNo()+"\"" +
" }");
AlipayTradeRefundResponse response = alipayClient.execute(request);
if(response.isSuccess()){
logger.info("-------------------------------调用成功-------------------------------");
} else {
logger.info("-------------------------------调用失败-------------------------------");
}
}
/**
* 支付宝退款查询
* @param map
* @throws Exception
*/
@RequestMapping(value="/refundQuery",method= RequestMethod.POST)
@ResponseBody
public AlipayTradeFastpayRefundQueryResponse refundQuery(AlipayRefund refund,ModelMap map) throws Exception{
//获得初始化的AlipayClient
AlipayClient alipayClient = initAlipayClient();
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
//out_request_no必填如为空则为out_trade_no
request.setBizContent("{" +
" \"out_trade_no\":\""+refund.getOutTradeNo()+"\"," +
" \"trade_no\":\""+refund.getTradeNo()+"\"," +
" \"out_request_no\":\""+refund.getOutRequestNo()+"\"" +
" }");
AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
if(response.isSuccess()){
logger.info("-------------------------------调用成功-------------------------------");
} else {
logger.info("-------------------------------调用失败-------------------------------");
}
return response;
}
/**
* 支付宝交易查询
* @param map
* @throws Exception
*/
@RequestMapping("/tradeQuery")
@ResponseBody
public AlipayTradeQueryResponse tradeQuery(ModelMap map,AlipayQuery query) throws Exception{
//获得初始化的AlipayClient
AlipayClient alipayClient = initAlipayClient();
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("{" +
" \"out_trade_no\":\""+query.getOutTradeNo()+"\"," +
" \"trade_no\":\""+query.getTradeNo()+"\"" +
" }");
AlipayTradeQueryResponse response = alipayClient.execute(request);
if(response.isSuccess()){
logger.info("-------------------------------调用成功-------------------------------");
} else {
logger.info("-------------------------------调用失败-------------------------------");
}
return response;
}
/**
* 支付宝交易关闭
* @param map
* @throws Exception
*/
@RequestMapping("/tradeClose")
public void tradeClose(ModelMap map) throws Exception{
//获得初始化的AlipayClient
AlipayClient alipayClient = initAlipayClient();
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
request.setBizContent("{" +
" \"trade_no\":\"2013112611001004680073956707\"," +
" \"out_trade_no\":\"HZ0120131127001\"," +
" \"operator_id\":\"YX01\"" +
" }");
AlipayTradeCloseResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}
}
/**
* 支付宝账单下载
* 不能下载当天的
* @param map
* @throws Exception
*/
@RequestMapping("/billDownLoad")
public void billDownLoad(ModelMap map,AlipayQuery query) throws Exception{
//获得初始化的AlipayClient
AlipayClient alipayClient = initAlipayClient();
//先查询账单下载地址
AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();//创建API对应的request类
request.setBizContent("{" +
" \"bill_type\":\""+query.getBillType()+"\"," +
" \"bill_date\":\""+query.getBillDate()+"\"" +
" }");//设置业务参数
AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);
String billDownloadUrl = response.getBillDownloadUrl();
if(billDownloadUrl ==null||billDownloadUrl.length()==0){
return;
}
//根据response中的结果继续业务逻辑处理
//将接口返回的对账单下载地址传入urlStr
String urlStr = billDownloadUrl;
logger.info("-------------------------------urlStr-------------------------------:::"+urlStr);
//指定希望保存的文件路径
String filePath = "/bill/20181218.csv.zip";
URL url = null;
HttpURLConnection httpUrlConnection = null;
InputStream fis = null;
FileOutputStream fos = null;
try {
url = new URL(urlStr);
httpUrlConnection = (HttpURLConnection) url.openConnection();
httpUrlConnection.setConnectTimeout(5 * 1000);
httpUrlConnection.setDoInput(true);
httpUrlConnection.setDoOutput(true);
httpUrlConnection.setUseCaches(false);
httpUrlConnection.setRequestMethod("GET");
httpUrlConnection.setRequestProperty("Charsert", "UTF-8");
httpUrlConnection.connect();
fis = httpUrlConnection.getInputStream();
byte[] temp = new byte[1024];
int b;
fos = new FileOutputStream(new File(filePath));
while ((b = fis.read(temp)) != -1) {
fos.write(temp, 0, b);
fos.flush();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) fis.close();
if (fos != null) fos.close();
if (httpUrlConnection != null) httpUrlConnection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 初始化AlipayClient
* @return
*/
private AlipayClient initAlipayClient(){
AlipayClient alipayClient = new DefaultAlipayClient(
AlipayConfig.GATEWAY_URL,
AlipayConfig.APP_ID,
AlipayConfig.APP_PRIVATE_KEY,
AlipayConfig.FORMAT,
AlipayConfig.CHARSET,
AlipayConfig.ALIPAY_PUBLIC_KEY,
AlipayConfig.SIGN_TYPE);
return alipayClient;
}
/**
* 支付宝app支付未测试
* 可使用官方实体:AlipayTradeAppPayModel(setBizModel)
* @param httpRequest
* @param response
* @throws Exception
*/
@RequestMapping("/app")
public void appPay(HttpServletRequest httpRequest, HttpServletResponse httpResponse)throws Exception{
AlipayClient alipayClient = initAlipayClient();
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setBizContent("{" +
"\"timeout_express\":\"90m\"," +
"\"total_amount\":\"0.01\"," +
"\"seller_id\":\""+AlipayConfig.APP_ID+"\"," +
"\"product_code\":\"QUICK_MSECURITY_PAY\"," +
"\"body\":\"测试\"," +
"\"subject\":\"测试\"," +
"\"out_trade_no\":\""+SerialNumber.generaterNextNumber("DDH")+"\"," +
"\"time_expire\":\"2018-12-21 11:40\"," +
"\"goods_type\":\"0\"" +
" }");
request.setReturnUrl(AlipayConfig.PAY_URL + AlipayConfig.RETURN_URL);
request.setNotifyUrl(AlipayConfig.PAY_URL + AlipayConfig.NOTIFY_URL);
AlipayTradeAppPayResponse response = alipayClient.pageExecute(request);
if(response.isSuccess()){
logger.info("-------------------------------调用成功-------------------------------");
} else {
logger.info("-------------------------------调用失败-------------------------------");
}
httpResponse.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
PrintWriter out = httpResponse.getWriter();
out.println(response.getBody());
out.close();
}
/**
* 手机网站支付接口2.0
* @throws AlipayApiException
*/
@RequestMapping("/mobileWeb")
public void alipayMobileWeb(HttpServletRequest httpRequest, HttpServletResponse httpResponse)throws Exception{
AlipayClient alipayClient = initAlipayClient();
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setBizContent("{" +
"\"body\":\"测试测试。\"," +
"\"subject\":\"测试测试\"," +
"\"out_trade_no\":\"70501111111S00111129\"," +
"\"timeout_express\":\"90m\"," +
"\"time_expire\":\"2018-12-21 11:40\"," +
"\"total_amount\":0.01," +
"\"seller_id\":\""+AlipayConfig.APP_ID+"\"," +
"\"goods_type\":\"0\"," +
"\"quit_url\":\""+"http://localhost:8080/alipay/list"+"\"," +
"\"product_code\":\"QUICK_WAP_WAY\"" +
" }");
request.setReturnUrl(AlipayConfig.PAY_URL + AlipayConfig.RETURN_URL);
request.setNotifyUrl(AlipayConfig.PAY_URL + AlipayConfig.NOTIFY_URL);
AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
if(response.isSuccess()){
logger.info("-------------------------------调用成功-------------------------------");
} else {
logger.info("-------------------------------调用失败-------------------------------");
}
httpResponse.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
PrintWriter out = httpResponse.getWriter();
out.println(response.getBody());
out.close();
}
}
微信:
package com.jg.controller.wechatpay;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.jg.constants.WeChatPayConfig;
import com.jg.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static com.jg.constants.AlipayConfig.PAY_URL;
/**
*/
@Controller
@RequestMapping("/wx")
public class WxPayController {
private static final Log logger = LogFactory.getLog(WxPayController.class);
@RequestMapping("/wxPayH5")
@ResponseBody
public Result<String> wxPayH5(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
Result<String> result = Result.isFail();
String url = "";
// 付款金额,必填
String total_fee = request.getParameter("total_fee");
// ip地址获取
String basePath = request.getServerName() + ":" + request.getServerPort();
//初始化请求参数
SortedMap<String, Object> packageParams = initMapParamsOfH5(total_fee);
try {
//生成签名
String sign = PayCommonUtil.createSign("UTF-8", packageParams, WeChatPayConfig.API_KEY);
packageParams.put("sign", sign);
//转为xml格式
String requestXML = PayCommonUtil.getRequestXml(packageParams);
//统一下单
String resXml = HttpUtil.postData(WeChatPayConfig.UNIFIED_ORDER_URL, requestXML);
//返回xml解析为map
Map map = PayCommonUtil.doXMLParse(resXml);
String return_code = (String) map.get("return_code");
String return_msg = (String) map.get("return_msg");
String result_code = (String) map.get("result_code");
if ("SUCCESS".equals(return_code) && "OK".equals(return_msg) && "SUCCESS".equals(result_code)) {
url = (String) map.get("mweb_url");//调微信支付接口地址
if (!StringUtils.isEmpty(url)) {
//确认支付过后跳的地址,需要经过urlencode处理
//String urlString = URLEncoder.encode("http://localhost:8080/alipay/list", "UTF-8");
//String mweb_url = url+"&redirect_url="+urlString;
result.setStatus(0);
result.setData(url);
return result;
} else {
result.setMsg("统一支付接口获取预支付订单出错:" + return_msg);
return result;
}
} else {
result.setMsg("支付错误:" + return_msg);
return result;
}
} catch (Exception e) {
result.setMsg("支付错误");
return result;
}
}
/**
* 执行回调 确认支付后处理事件 例如添加金额到数据库等操作
*
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/notify")
public void weixin_notify(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
logger.info("进入支付h5回调=====================");
String xmlMsg = readData(request);
logger.info("pay notice---------" + xmlMsg);
Map params = PayCommonUtil.doXMLParse(xmlMsg);
// String appid = params.get("appid");
// //商户号
// String mch_id = params.get("mch_id");
String result_code = params.get("result_code") + "";
// String openId = params.get("openid");
// //交易类型
// String trade_type = params.get("trade_type");
// //付款银行
// String bank_type = params.get("bank_type");
// // 总金额
// String total_fee = params.get("total_fee");
// //现金支付金额
// String cash_fee = params.get("cash_fee");
// // 微信支付订单号
// String transaction_id = params.get("transaction_id");
// // 商户订单号
// String out_trade_no = params.get("out_trade_no");
// // 支付完成时间,格式为yyyyMMddHHmmss
// String time_end = params.get("time_end");
/以下是附加参数///
String attach = params.get("attach") + "";
// String fee_type = params.get("fee_type");
// String is_subscribe = params.get("is_subscribe");
// String err_code = params.get("err_code");
// String err_code_des = params.get("err_code_des");
// 过滤空 设置 TreeMap
/* SortedMap<String, String> packageParams = new TreeMap<String, String>();
Iterator it = params.keySet().iterator();
while (it.hasNext()) {
String parameter = (String) it.next();
String parameterValue = params.get(parameter) + "";
String v = "";
if (null != parameterValue) {
v = parameterValue.trim();
}
logger.info("value===============" + v);
packageParams.put(parameter, v);
}*/
//判断签名是否正确
if(PayCommonUtil.isTenpaySign(params,WeChatPayConfig.API_KEY)) {
//------------------------------
//处理业务开始
//------------------------------
String resXml = "";
if("SUCCESS".equals(params.get("result_code"))){
// 这里是支付成功
//执行自己的业务逻辑
String mch_id = (String)params.get("mch_id");
String openid = (String)params.get("openid");
String is_subscribe = (String)params.get("is_subscribe");
String out_trade_no = (String)params.get("out_trade_no");
String total_fee = (String)params.get("total_fee");
System.out.println("mch_id:"+mch_id);
System.out.println("openid:"+openid);
logger.info("is_subscribe:"+is_subscribe);
logger.info("out_trade_no:"+out_trade_no);
logger.info("total_fee:"+total_fee);
//执行自己的业务逻辑
logger.info("支付成功============支付金额:" + total_fee);
//通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
} else {
logger.info("支付失败,错误信息:" + params.get("err_code"));
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
}
//------------------------------
//处理业务完毕
//------------------------------
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
} catch (Exception e) {
e.printStackTrace();
logger.info("关闭流失败:"+e.getMessage());
} finally {
if (out != null) {
out.close();
}
}
} else{
logger.info("通知签名验证失败");
}
}
/**
* 用户扫二维码付
*
* @param request
* @param response
* @param model
* @return
* @throws Exception
*/
@RequestMapping("/scanQRCode")
@ResponseBody
public Result<String> scanQRCode(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
Result<String> result = Result.isFail();
String url = "";
// 付款金额,必填
String total_fee = request.getParameter("total_fee");
// ip地址获取
String basePath = request.getServerName() + ":" + request.getServerPort();
//初始化请求参数
SortedMap<String, Object> packageParams = initMapParams(total_fee);
// 回调接口
String notify_url = PAY_URL + WeChatPayConfig.NOTIFY_URL;
packageParams.put("notify_url", notify_url);
//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,H5支付的交易类型为MWEB
packageParams.put("trade_type", "NATIVE");
try {
//生成签名
String sign = PayCommonUtil.createSign("UTF-8", packageParams, WeChatPayConfig.API_KEY);
packageParams.put("sign", sign);
//转为xml格式
String requestXML = PayCommonUtil.getRequestXml(packageParams);
//统一下单
String resXml = HttpUtil.postData(WeChatPayConfig.UNIFIED_ORDER_URL, requestXML);
//返回xml解析为map
Map map = PayCommonUtil.doXMLParse(resXml);
String return_code = (String) map.get("return_code");
String return_msg = (String) map.get("return_msg");
String result_code = (String) map.get("result_code");
if ("SUCCESS".equals(return_code) && "OK".equals(return_msg) && "SUCCESS".equals(result_code)) {
//mweb_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟。
url = (String) map.get("code_url");//用来生成二维码
ByteArrayOutputStream out = new ByteArrayOutputStream();
//将返回预支付交易链接(code_url)生成二维码图片
//这里使用的是zxing <span style="color:#ff0000;"><strong>说明1(见文末)</strong></span>
try {
int width = 200;
int height = 200;
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
hints.put(EncodeHintType.MARGIN, 2);
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, width, height, hints);
BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
ImageIO.write(image, "png", out);
/**
* 原生转码前面没有 data:image/png;base64 这些字段,返回给前端是无法被解析,可以让前端加,也可以在下面加上
* import com.sun.org.apache.xml.internal.security.utils.Base64;
* import sun.misc.BASE64Encoder;
* 但还是java8的速度快
*/
url = new String("data:image/png;base64," + Base64.getEncoder().encodeToString(out.toByteArray()));
} catch (Exception e) {
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (!StringUtils.isEmpty(url)) {
result.setStatus(0);
result.setData(url);
return result;
} else {
result.setMsg("统一支付接口获取预支付订单出错:" + return_msg);
return result;
}
} else {
result.setMsg("支付错误:" + return_msg);
return result;
}
} catch (Exception e) {
result.setMsg("支付错误");
return result;
}
}
public static String readData(HttpServletRequest request) {
BufferedReader br = null;
try {
StringBuilder result = new StringBuilder();
br = request.getReader();
for (String line; (line = br.readLine()) != null; ) {
if (result.length() > 0) {
result.append("\n");
}
result.append(line);
}
return result.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null)
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 付款码支付
*
*收银员使用扫码设备读取微信用户付款码以后,二维码或条码信息会传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付。
*提醒1:提交支付请求后微信会同步返回支付结果。当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】,查询支付实际交易结果;当返回结果为“USERPAYING”时,商户系统可设置间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒);
*提醒2:在调用查询接口返回后,如果交易状况不明晰,请调用【撤销订单API】,此时如果交易失败则关闭订单,该单不能再支付成功;如果交易成功,则将扣款退回到用户账户。当撤销无返回或错误时,请再次调用。注意:请勿扣款后立即调用【撤销订单API】,建议至少15秒后再调用。撤销订单API需要双向证书。
* @param request
* @param response
* @param model
* @return
* @throws Exception
*/
@RequestMapping("/paymentCode")
@ResponseBody
public Result<String> paymentCode(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
Result<String> result = Result.isFail();
String url = "";
// 付款金额,必填
String total_fee = request.getParameter("total_fee");
//用户的付款码
String auth_code = request.getParameter("auth_code");
// ip地址获取
String basePath = request.getServerName() + ":" + request.getServerPort();
//初始化请求参数
SortedMap<String, Object> packageParams = initMapParams(total_fee);
//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,H5支付的交易类型为MWEB,付款码支付不需要
packageParams.put("auth_code", auth_code);
try {
//生成签名
String sign = PayCommonUtil.createSign("UTF-8", packageParams, WeChatPayConfig.API_KEY);
packageParams.put("sign", sign);
//转为xml格式
String requestXML = PayCommonUtil.getRequestXml(packageParams);
//付款码支付
String resXml = HttpUtil.postData(WeChatPayConfig.PAYMENT_CODE_URL, requestXML);
//返回xml解析为map
Map map = PayCommonUtil.doXMLParse(resXml);
//通信标识
String return_code = (String) map.get("return_code");
String err_code = (String) map.get("err_code");
if ("SUCCESS".equals(return_code)) {
String result_code = (String) map.get("result_code");
if ("SUCCESS".equals(result_code)) {
//openid用户在商户appid 下的唯一标识
url = (String) map.get("openid") + "----支付金额:" + (String) map.get("total_fee")+"分";
if (!StringUtils.isEmpty(url)) {
result.setStatus(0);
result.setData(url);
return result;
}
}else if("SYSTEMERROR".equals(err_code)){
//如果当前交易返回的支付状态是明确的错误原因造成的支付失败(支付确认失败),请重新下单支付;
// 如果当前交易返回的支付状态是不明错误(支付结果未知),请调用查询订单接口确认状态,如果长时间(建议30秒)都得不到明确状态请调用撤销订单接口。
//当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】
TimeUnit.SECONDS.sleep(5);
String queryXml = HttpUtil.postData(WeChatPayConfig.CHECK_ORDER_URL, requestXML);
//返回xml解析为map
Map queryMap = PayCommonUtil.doXMLParse(queryXml);
//交易状态,SUCCESS—支付成功
//REFUND—转入退款 NOTPAY—未支付 CLOSED—已关闭 REVOKED—已撤销(付款码支付)USERPAYING--用户支付中(付款码支付)PAYERROR--支付失败(其他原因,如银行返回失败)
String trade_state = (String) queryMap.get("trade_state");
result_code = (String) queryMap.get("result_code");
if("SUCCESS".equals(trade_state)&&"SUCCESS".equals(result_code)){
url = (String) map.get("total_fee");
result.setStatus(0);
result.setData(url);
return result;
}else if("USERPAYING".equals(trade_state)){
//间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒)
int i =0;
while(true){
TimeUnit.SECONDS.sleep(10);
String queryPayxml = HttpUtil.postData(WeChatPayConfig.CHECK_ORDER_URL, requestXML);
//返回xml解析为map
Map queryPayMap = PayCommonUtil.doXMLParse(queryPayxml);
trade_state = (String) queryPayMap.get("trade_state");
if("SUCCESS".equals(trade_state)){
url = (String) map.get("total_fee");
result.setStatus(0);
result.setData(url);
return result;
}else{
i++;
}
//已超过30秒等待
if(i==2){
String err_code_des = (String) queryPayMap.get("err_code_des");
//订单撤销
String cancelPayxml = HttpUtil.postData(WeChatPayConfig.CANCEL_URL, requestXML);
result.setMsg(err_code_des);
return result;
}
}
}
//ORDERPAID
//撤销订单,调用支付接口后请勿立即调用撤销订单API,建议支付后至少15s后再调用撤销订单接口
String cancelPayxml = HttpUtil.postData(WeChatPayConfig.CANCEL_URL, requestXML);
//返回错误原因
result.setMsg("付款码支付错误"+queryMap.get("err_code_des"));
return result;
}
//撤销订单
String cancelPayxml = HttpUtil.postData(WeChatPayConfig.CANCEL_URL, requestXML);
//返回错误原因
result.setMsg("付款码支付错误"+map.get("err_code_des"));
return result;
} else {
//撤销订单
String cancelPayxml = HttpUtil.postData(WeChatPayConfig.CANCEL_URL, requestXML);
result.setMsg("付款码支付错误"+map.get("err_code_des"));
return result;
}
} catch (Exception e) {
result.setMsg("付款码支付错误");
return result;
}
}
/**
* 订单查询
* @param request
* @param response
* @return
* @throws Exception
*/
@RequestMapping("/query")
@ResponseBody
public Result<String> queryOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
Result<String> result = Result.isFail();
//商户订单号或微信订单号(transaction_id)二选一
String out_trade_no = request.getParameter("out_trade_no");
//随机字符串
String nonce_str = request.getParameter("nonce_str");
//初始化请求参数
SortedMap<String, Object> packageParams = initMapQueryParams(out_trade_no,nonce_str);
try {
//生成签名
String sign = PayCommonUtil.createSign("UTF-8", packageParams, WeChatPayConfig.API_KEY);
packageParams.put("sign", sign);
//转为xml格式
String requestXML = PayCommonUtil.getRequestXml(packageParams);
//付款码支付
String resXml = HttpUtil.postData(WeChatPayConfig.CHECK_ORDER_URL, requestXML);
//返回xml解析为map
Map map = PayCommonUtil.doXMLParse(resXml);
String return_code = (String) map.get("return_code");
String return_msg = (String) map.get("return_msg");
result.setData(map.toString());
result.setStatus(0);
return result;
}catch (Exception e){
}
return result;
}
/**
* 账号信息初始化
* 可用实体类来封装,本测试未使用
*/
private void initClient() {
// 账号信息
String appid = WeChatPayConfig.APP_ID; // appid
String mch_id = WeChatPayConfig.MCH_ID; // 商业号
String key = WeChatPayConfig.API_KEY; // key
}
/**
* 初始化公共参数
*
* @param total_fee
* @return
*/
private SortedMap<String, Object> initMapParams(String total_fee) {
String currTime = PayCommonUtil.getCurrTime();
String strTime = currTime.substring(8, currTime.length());
String strRandom = PayCommonUtil.buildRandom(4) + "";
String nonce_str = strTime + strRandom;
// 价格 注意:价格的单位是分
String order_price = new BigDecimal(total_fee).multiply(new BigDecimal(100)).toString().split("\\.")[0];
// 自己网站上的订单号
String out_trade_no = SerialNumber.generaterNextNumber("DDH");
// 获取发起电脑 ip
String spbill_create_ip = "127.0.0.1";
// 设置package订单参数
SortedMap<String, Object> packageParams = new TreeMap<String, Object>();
packageParams.put("appid", WeChatPayConfig.APP_ID);
packageParams.put("body", "测试测试");
packageParams.put("mch_id", WeChatPayConfig.MCH_ID);
// 生成签名的时候需要你自己设置随机字符串
packageParams.put("nonce_str", nonce_str);
packageParams.put("out_trade_no", out_trade_no);
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("total_fee", order_price);
return packageParams;
}
/**
* 初始化H5参数
*
* @param total_fee
* @return
*/
private SortedMap<String, Object> initMapParamsOfH5(String total_fee) {
SortedMap<String, Object> packageParams = initMapParams(total_fee);
// 回调接口
String notify_url = PAY_URL + WeChatPayConfig.NOTIFY_URL;
packageParams.put("notify_url", notify_url);
//扫码支付参数
packageParams.put("scene_info", "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"http://localhost:8080\",\"wap_name\": \"测试测试\"}}");
//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,H5支付的交易类型为MWEB
packageParams.put("trade_type", "MWEB");
return packageParams;
}
/**
* 初始化查询参数
*
* @param total_fee
* @return
*/
private SortedMap<String, Object> initMapQueryParams(String out_trade_no,String nonce_str) {
// 设置package订单参数
SortedMap<String, Object> packageParams = new TreeMap<String, Object>();
packageParams.put("appid", WeChatPayConfig.APP_ID);
packageParams.put("mch_id", WeChatPayConfig.MCH_ID);
// 生成签名的时候需要你自己设置随机字符串
packageParams.put("nonce_str", nonce_str);
packageParams.put("out_trade_no", out_trade_no);
return packageParams;
}
}