Commit d53783a9 authored by jmdhappy's avatar jmdhappy
Browse files

初始化提交

parent 324ccaaf
package org.xxpay.service.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.util.MyBase64;
import org.xxpay.common.util.MyLog;
import org.xxpay.dal.dao.model.MchInfo;
import org.xxpay.service.channel.alipay.sign.Base64;
import org.xxpay.service.service.MchInfoService;
/**
* @Description: 商户信息接口
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class MchInfoServiceController {
private final MyLog _log = MyLog.getLog(MchInfoServiceController.class);
@Autowired
private MchInfoService mchInfoService;
@RequestMapping(value = "/mch_info/select")
public String selectMchInfo(@RequestParam String jsonParam) {
// TODO 参数校验
String param = new String(MyBase64.decode(jsonParam));
JSONObject paramObj = JSON.parseObject(param);
String mchId = paramObj.getString("mchId");
MchInfo mchInfo = mchInfoService.selectMchInfo(mchId);
JSONObject retObj = new JSONObject();
if(mchInfo == null) {
retObj.put("result", "");
return retObj.toJSONString();
}
retObj.put("result", JSON.toJSON(mchInfo));
_log.info("result:{}", retObj.toJSONString());
return retObj.toJSONString();
}
}
package org.xxpay.service.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.util.MyLog;
import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.service.channel.alipay.config.AlipayConfig;
import org.xxpay.service.channel.alipay.util.AlipayNotify;
import org.xxpay.service.channel.tencent.common.Util;
import org.xxpay.service.channel.tencent.protocol.notify_protocol.NotifyUnifiedOrderResData;
import org.xxpay.service.service.PayChannelService;
import org.xxpay.service.service.PayOrderService;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @Description: 接收处理支付宝通知
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class Notify4AliPayController extends Notify4BasePay {
private static final MyLog _log = MyLog.getLog(Notify4AliPayController.class);
@Autowired
private PayOrderService payOrderService;
@Autowired
private PayChannelService payChannelService;
@Autowired
private AlipayConfig alipayConfig;
/**
* 支付宝移动支付后台通知响应
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
@RequestMapping(value = "/pay/aliPayNotifyRes.htm")
@ResponseBody
public String aliPayNotifyRes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return doAliPayRes(request, response);
}
public String doAliPayRes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String logPrefix = "【支付宝支付回调通知】";
_log.info("====== 开始接收支付宝支付回调通知 ======");
//获取支付宝POST过来反馈信息
Map<String,String> params = new HashMap<>();
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] + ",";
}
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
_log.info("{}通知请求数据:reqStr={}", logPrefix, params);
if(params.isEmpty()) {
_log.error("{}请求参数为空", logPrefix);
return makeRetData(PayConstant.RETURN_VALUE_FAIL, "请求参数为空");
}
Map<String, Object> payContext = new HashMap();
PayOrder payOrder;
payContext.put("parameters", params);
if(!verifyAliPayParams(payContext)) {
return makeRetData(PayConstant.RETURN_VALUE_FAIL, (String) payContext.get("retMsg"));
}
_log.info("{}验证请求数据及签名通过", logPrefix);
String out_trade_no = params.get("out_trade_no"); // 商户订单号
String trade_no = params.get("trade_no"); // 支付宝订单号
String trade_status = params.get("trade_status"); // 交易状态
String buyer_email = params.get("buyer_email"); // 买家支付宝账号
// 支付状态成功或者完成
if (trade_status.equals(PayConstant.AlipayConstant.TRADE_STATUS_SUCCESS) ||
trade_status.equals(PayConstant.AlipayConstant.TRADE_STATUS_FINISHED)) {
int updatePayOrderRows;
payOrder = (PayOrder)payContext.get("payOrder");
byte payStatus = payOrder.getStatus(); // 0:订单生成,1:支付中,-1:支付失败,2:支付成功,3:业务处理完成,-2:订单过期
if (payStatus != PayConstant.PAY_STATUS_SUCCESS && payStatus != PayConstant.PAY_STATUS_COMPLETE) {
updatePayOrderRows = payOrderService.updateStatus4Success(payOrder.getPayOrderId());
if (updatePayOrderRows != 1) {
_log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
_log.info("{}响应给支付宝结果:{}", logPrefix, PayConstant.RETURN_ALIPAY_VALUE_FAIL);
return PayConstant.RETURN_ALIPAY_VALUE_FAIL;
}
_log.info("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);
}
}else{
// 其他状态
_log.info("{}支付状态trade_status={},不做业务处理", logPrefix, trade_status);
_log.info("{}响应给支付宝结果:{}", logPrefix, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS);
return PayConstant.RETURN_ALIPAY_VALUE_SUCCESS;
}
doNotify(payOrder, response, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS);
_log.info("====== 完成接收支付宝支付回调通知 ======");
return null;
}
/**
* 验证支付宝支付通知参数
* @return
*/
public boolean verifyAliPayParams(Map<String, Object> payContext) {
Map<String,String> params = (Map<String,String>)payContext.get("parameters");
String out_trade_no = params.get("out_trade_no"); // 商户订单号
String seller_email = params.get("seller_email"); // 卖家支付宝账号
String total_fee = params.get("total_fee"); // 支付金额
String buyer_email = params.get("buyer_email"); // 买家支付宝账号
String sign = params.get("sign"); // 签名
if (StringUtils.isEmpty(out_trade_no)) {
_log.error("AliPay Notify parameter out_trade_no is empty. out_trade_no={}", out_trade_no);
payContext.put("retMsg", "out_trade_no is empty");
return false;
}
if (StringUtils.isEmpty(seller_email)) {
_log.error("AliPay Notify parameter seller_email is empty. seller_email={}", seller_email);
payContext.put("retMsg", "seller_email is empty");
return false;
}
if (StringUtils.isEmpty(total_fee)) {
_log.error("AliPay Notify parameter total_fee is empty. total_fee={}", total_fee);
payContext.put("retMsg", "total_fee is empty");
return false;
}
if (StringUtils.isEmpty(buyer_email)) {
_log.error("AliPay Notify parameter buyer_email is empty. buyer_email={}", buyer_email);
payContext.put("retMsg", "buyer_email is empty");
return false;
}
if (StringUtils.isEmpty(sign)) {
_log.error("AliPay Notify parameter sign is empty. sign={}", sign);
payContext.put("retMsg", "sign is empty");
return false;
}
String errorMessage;
// 查询payOrder记录
String payOrderId = out_trade_no;
PayOrder payOrder = payOrderService.selectPayOrder(payOrderId);
if (payOrder == null) {
_log.error("Can't found payOrder form db. payOrderId={}, ", payOrderId);
payContext.put("retMsg", "Can't found payOrder");
return false;
}
// 查询payChannel记录
String mchId = payOrder.getMchId();
String channelId = payOrder.getChannelId();
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
if(payChannel == null) {
_log.error("Can't found payChannel form db. mchId={} channelId={}, ", payOrderId, mchId, channelId);
payContext.put("retMsg", "Can't found payChannel");
return false;
}
// 验证签名
if (!AlipayNotify.verify(alipayConfig.init(payChannel.getParam()), params)) {
errorMessage = "Verify VV pay sign failed.";
_log.error("AliPay Notify parameter {}", errorMessage);
payContext.put("retMsg", errorMessage);
return false;
}
// 核对金额
long aliPayAmt = new BigDecimal(total_fee).movePointRight(2).longValue();
long dbPayAmt = payOrder.getAmount().longValue();
if (dbPayAmt != aliPayAmt) {
_log.error("db payOrder record payPrice not equals total_fee. total_fee={},payOrderId={}", total_fee, payOrderId);
payContext.put("retMsg", "");
return false;
}
payContext.put("payOrder", payOrder);
return true;
}
String makeRetData(String retCode, String retMsg) {
NotifyUnifiedOrderResData data = new NotifyUnifiedOrderResData();
data.setReturn_code(retCode);
data.setReturn_msg(retMsg);
return Util.objectToXML(data);
}
String makeRetData(String retCode) {
return makeRetData(retCode, "");
}
}
package org.xxpay.service.controller;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.util.MyLog;
import org.xxpay.common.util.PayDigestUtil;
import org.xxpay.common.util.XXPayUtil;
import org.xxpay.service.mq.Mq4PayNotify;
import org.xxpay.dal.dao.model.MchInfo;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.service.service.MchInfoService;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: 支付通知处理基类
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@Component
public class Notify4BasePay {
private static final MyLog _log = MyLog.getLog(Notify4BasePay.class);
@Autowired
private Mq4PayNotify mq4PayNotify;
@Autowired
private MchInfoService mchInfoService;
/**
* 创建响应URL
* @param payOrder
* @param backType 1:前台页面;2:后台接口
* @return
*/
public String createNotifyUrl(PayOrder payOrder, String backType) {
String mchId = payOrder.getMchId();
MchInfo mchInfo = mchInfoService.selectMchInfo(mchId);
String resKey = mchInfo.getResKey();
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("payOrderId", payOrder.getPayOrderId() == null ? "" : payOrder.getPayOrderId()); // 支付订单号
paramMap.put("mchId", payOrder.getMchId() == null ? "" : payOrder.getMchId()); // 商户ID
paramMap.put("mchOrderNo", payOrder.getMchOrderNo() == null ? "" : payOrder.getMchOrderNo()); // 商户订单号
paramMap.put("channelId", payOrder.getChannelId() == null ? "" : payOrder.getChannelId()); // 渠道ID
paramMap.put("amount", payOrder.getAmount() == null ? "" : payOrder.getAmount()); // 支付金额
paramMap.put("currency", payOrder.getCurrency() == null ? "" : payOrder.getCurrency()); // 货币类型
paramMap.put("status", payOrder.getStatus() == null ? "" : payOrder.getStatus()); // 支付状态
paramMap.put("clientIp", payOrder.getClientIp()==null ? "" : payOrder.getClientIp()); // 客户端IP
paramMap.put("device", payOrder.getDevice()==null ? "" : payOrder.getDevice()); // 设备
paramMap.put("subject", payOrder.getSubject()==null ? "" : payOrder.getSubject()); // 商品标题
paramMap.put("channelOrderNo", payOrder.getChannelOrderNo()==null ? "" : payOrder.getChannelOrderNo()); // 渠道订单号
paramMap.put("param1", payOrder.getParam1()==null ? "" : payOrder.getParam1()); // 扩展参数1
paramMap.put("param2", payOrder.getParam2()==null ? "" : payOrder.getParam2()); // 扩展参数2
paramMap.put("paySuccTime", payOrder.getPaySuccTime()==null ? "" : payOrder.getPaySuccTime()); // 支付成功时间
paramMap.put("backType", backType==null ? "" : backType);
// 先对原文签名
String reqSign = PayDigestUtil.getSign(paramMap, resKey);
paramMap.put("sign", reqSign); // 签名
// 签名后再对有中文参数编码
try {
paramMap.put("device", URLEncoder.encode(payOrder.getDevice()==null ? "" : payOrder.getDevice(), PayConstant.RESP_UTF8));
paramMap.put("subject", URLEncoder.encode(payOrder.getSubject()==null ? "" : payOrder.getSubject(), PayConstant.RESP_UTF8));
paramMap.put("param1", URLEncoder.encode(payOrder.getParam1()==null ? "" : payOrder.getParam1(), PayConstant.RESP_UTF8));
paramMap.put("param2", URLEncoder.encode(payOrder.getParam2()==null ? "" : payOrder.getParam2(), PayConstant.RESP_UTF8));
}catch (UnsupportedEncodingException e) {
_log.error("URL Encode exception.", e);
return null;
}
String param = XXPayUtil.genUrlParams(paramMap);
StringBuffer sb = new StringBuffer();
sb.append(payOrder.getNotifyUrl()).append("?").append(param);
return sb.toString();
}
/**
* 处理支付结果前台页面跳转
*/
public boolean doPage(PayOrder payOrder, HttpServletResponse response) {
String redirectUrl = createNotifyUrl(payOrder, "1");
_log.info("redirect to respUrl:"+redirectUrl);
// 前台跳转业务系统
try {
response.sendRedirect(redirectUrl);
} catch (IOException e) {
_log.error("XxPay sendRedirect exception. respUrl="+redirectUrl, e);
return false;
}
return true;
}
/**
* 处理支付结果后台服务器通知
*/
public void doNotify(PayOrder payOrder, HttpServletResponse response, String message) {
_log.info(">>>>>> PAY开始回调通知业务系统 <<<<<<");
// 发起后台通知业务系统
JSONObject object = createNotifyInfo(payOrder);
try {
mq4PayNotify.send(object.toJSONString());
} catch (Exception e) {
_log.error("payOrderId={},sendMessage error.", payOrder != null ? payOrder.getPayOrderId() : "", e);
}
// 响应给支付公司
_log.info("payOrderId={},channelId={},响应支付公司结果:{}", payOrder != null ? payOrder.getPayOrderId() : "", payOrder != null ? payOrder.getChannelId() : "", message);
response.setContentType("text/html");
PrintWriter pw;
try {
pw = response.getWriter();
pw.print(message);
} catch (IOException e) {
_log.error("JDPay response write exception.", e);
}
_log.info(">>>>>> PAY回调通知业务系统完成 <<<<<<");
}
public JSONObject createNotifyInfo(PayOrder payOrder) {
JSONObject object = new JSONObject();
object.put("method", "GET");
object.put("url", createNotifyUrl(payOrder, "2"));
object.put("orderId", payOrder.getPayOrderId());
object.put("count", 0);
object.put("createTime", System.currentTimeMillis());
return object;
}
}
package org.xxpay.service.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.xml.sax.SAXException;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.util.MyLog;
import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.Signature;
import org.xxpay.service.channel.tencent.common.Util;
import org.xxpay.service.channel.tencent.protocol.notify_protocol.NotifyUnifiedOrderReqData;
import org.xxpay.service.channel.tencent.protocol.notify_protocol.NotifyUnifiedOrderResData;
import org.xxpay.service.service.PayChannelService;
import org.xxpay.service.service.PayOrderService;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: 接收处理微信通知
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class Notify4WxPayController extends Notify4BasePay {
private static final MyLog _log = MyLog.getLog(Notify4WxPayController.class);
@Autowired
private PayOrderService payOrderService;
@Autowired
private PayChannelService payChannelService;
@Autowired
private Configure configure;
/**
* 微信支付(统一下单接口)后台通知响应
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
@RequestMapping("/pay/wxPayNotifyRes.htm")
@ResponseBody
public String wxPayNotifyRes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return doWxPayRes(request, response);
}
public String doWxPayRes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String logPrefix = "【微信支付回调通知】";
_log.info("====== 开始接收微信支付回调通知 ======");
String reqStr = Util.inputStreamToString(request.getInputStream());
_log.info("{}通知请求数据:reqStr={}", logPrefix, reqStr);
if(reqStr == null || "".equals(reqStr.trim())) {
_log.error("{}请求参数为空", logPrefix);
return makeRetData(PayConstant.RETURN_VALUE_FAIL, "请求参数解析错误");
}
NotifyUnifiedOrderReqData reqData = (NotifyUnifiedOrderReqData) Util.getObjectFromXML(reqStr, NotifyUnifiedOrderReqData.class);
if (reqData == null || reqData.getReturn_code() == null) {
_log.error("{}请求数据解析数据异常或return_code为空", logPrefix);
return makeRetData(PayConstant.RETURN_VALUE_FAIL, "请求参数解析错误");
}
Map<String, Object> payContext = new HashMap();
PayOrder payOrder = null;
payContext.put("parameters", reqData);
payContext.put("reqStr", reqStr);
if (PayConstant.RETURN_VALUE_FAIL.equals(reqData.getReturn_code())) {
_log.error("{}请求数据return_code=FAIL", logPrefix);
return makeRetData(PayConstant.RETURN_VALUE_SUCCESS);
} else {
_log.info("{}请求数据return_code=SUCCESS,开始验证请求数据", logPrefix);
//--------------------------------------------------------------------
//收到通知数据的时候得先验证一下数据有没有被第三方篡改,确保安全
//--------------------------------------------------------------------
if(!verifyWxPayParams(payContext)) {
return makeRetData(PayConstant.RETURN_VALUE_FAIL, (String) payContext.get("retMsg"));
}
_log.info("{}验证请求数据及签名通过", logPrefix);
//获取错误码
String errorCode = reqData.getErr_code();
//获取错误描述
String errorCodeDes = reqData.getErr_code_des();
if (reqData.getResult_code().equals(PayConstant.RETURN_VALUE_SUCCESS)) {
int updatePayOrderRows;
payOrder = (PayOrder) payContext.get("payOrder");
byte payStatus = payOrder.getStatus(); // 0:订单生成,1:支付中,-1:支付失败,2:支付成功,3:业务处理完成,-2:订单过期
if (payStatus != PayConstant.PAY_STATUS_SUCCESS && payStatus != PayConstant.PAY_STATUS_COMPLETE) {
updatePayOrderRows = payOrderService.updateStatus4Success(payOrder.getPayOrderId());
if (updatePayOrderRows != 1) {
_log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
return makeRetData(PayConstant.RETURN_VALUE_FAIL, "更新订单失败");
}
_log.error("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);
}
}else{
//出现业务错误
_log.info("{}请求数据result_code=FAIL", logPrefix);
_log.info("err_code:", errorCode);
_log.info("err_code_des:", errorCodeDes);
return makeRetData(PayConstant.RETURN_VALUE_SUCCESS);
}
}
doNotify(payOrder, response, makeRetData(PayConstant.RETURN_VALUE_SUCCESS));
return null;
}
/**
* 验证微信支付通知参数
* @return
*/
public boolean verifyWxPayParams(Map<String, Object> payContext) {
NotifyUnifiedOrderReqData params = (NotifyUnifiedOrderReqData)payContext.get("parameters");
String return_code = params.getReturn_code(); // 返回码
String appid = params.getAppid(); // 公众账号ID
String mch_id = params.getMch_id(); // 商户号
String sign = params.getSign(); // 签名
String result_code = params.getResult_code(); // 业务结果
String openid = params.getOpenid(); // 用户标识
String trade_type = params.getTrade_type(); // 交易类型
String bank_type = params.getBank_type(); // 付款银行
String total_fee = params.getTotal_fee(); // 总金额
String cash_fee = params.getCash_fee(); // 现金支付金额
String transaction_id = params.getTransaction_id(); // 微信支付订单号
String out_trade_no = params.getOut_trade_no(); // 商户系统订单号
String time_end = params.getTime_end(); // 支付完成时间
if (StringUtils.isEmpty(return_code)) {
_log.error("WXPay parameter return_code is empty. return_code={}", result_code);
payContext.put("retMsg", "return_code is empty");
return false;
}
if (PayConstant.RETURN_VALUE_FAIL.equals(return_code)) {
_log.error("WXPay return_code is FAIL. return_code={}", result_code);
payContext.put("retMsg", "return_code is FAIL");
return false;
}
if (StringUtils.isEmpty(appid)) {
_log.error("WXPay parameter appid is empty. appid={}", appid);
payContext.put("retMsg", "appid is empty");
return false;
}
if (StringUtils.isEmpty(mch_id)) {
_log.error("XWPay parameter mch_id is empty. mch_id={}", mch_id);
payContext.put("retMsg", "mch_id is empty");
return false;
}
if (StringUtils.isEmpty(sign)) {
_log.error("XWPay parameter sign is empty. sign={}", sign);
payContext.put("retMsg", "sign is empty");
return false;
}
if (StringUtils.isEmpty(result_code)) {
_log.error("XWPay parameter result_code is empty. result_code={}", result_code);
payContext.put("retMsg", "result_code is empty");
return false;
}
if (StringUtils.isEmpty(openid)) {
_log.error("XWPay parameter openid is empty. openid={}", openid);
payContext.put("retMsg", "openid is empty");
return false;
}
if (StringUtils.isEmpty(trade_type)) {
_log.error("XWPay parameter trade_type is empty. trade_type={}", trade_type);
payContext.put("retMsg", "trade_type is empty");
return false;
}
if (StringUtils.isEmpty(bank_type)) {
_log.error("XWPay parameter bank_type is empty. bank_type={}", bank_type);
payContext.put("retMsg", "bank_type is empty");
return false;
}
if (StringUtils.isEmpty(total_fee)) {
_log.error("XWPay parameter total_fee is empty. total_fee={}", total_fee);
payContext.put("retMsg", "total_fee is empty");
return false;
}
if (StringUtils.isEmpty(cash_fee)) {
_log.error("XWPay parameter cash_fee is empty. cash_fee={}", cash_fee);
payContext.put("retMsg", "cash_fee is empty");
return false;
}
if (StringUtils.isEmpty(transaction_id)) {
_log.error("XWPay parameter transaction_id is empty. transaction_id={}", transaction_id);
payContext.put("retMsg", "transaction_id is empty");
return false;
}
if (StringUtils.isEmpty(out_trade_no)) {
_log.error("XWPay parameter out_trade_no is empty. out_trade_no={}", out_trade_no);
payContext.put("retMsg", "out_trade_no is empty");
return false;
}
if (StringUtils.isEmpty(time_end)) {
_log.error("XWPay parameter time_end is empty. time_end={}", time_end);
payContext.put("retMsg", "time_end is empty");
return false;
}
// 查询payOrder记录
String payOrderId = out_trade_no;
PayOrder payOrder = payOrderService.selectPayOrder(payOrderId);
if (payOrder==null) {
_log.error("Can't found payOrder form db. payOrderId={}, ", payOrderId);
payContext.put("retMsg", "Can't found payOrder");
return false;
}
// 查询payChannel记录
String mchId = payOrder.getMchId();
String channelId = payOrder.getChannelId();
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
if(payChannel == null) {
_log.error("Can't found payChannel form db. mchId={} channelId={}, ", payOrderId, mch_id, channelId);
payContext.put("retMsg", "Can't found payChannel");
return false;
}
// 验证微信支付结果签名
try {
if(!Signature.checkIsSignValidFromResponseString((String)payContext.get("reqStr"), configure.init(payChannel.getParam()).getKey())) {
_log.error("WXPay parameter sign verified failed. sign={}", sign);
payContext.put("retMsg", "sign is verified failed");
return false;
}
} catch (ParserConfigurationException e) {
_log.error(e, "");
} catch (IOException e) {
_log.error(e, "");
} catch (SAXException e) {
_log.error(e, "");
}
// 核对金额
long wxPayAmt = new BigDecimal(total_fee).longValue();
long dbPayAmt = payOrder.getAmount().longValue();
if (dbPayAmt != wxPayAmt) {
_log.error("db payOrder record payPrice not equals total_fee. total_fee={},payOrderId={}", total_fee, payOrderId);
payContext.put("retMsg", "");
return false;
}
payContext.put("payOrder", payOrder);
return true;
}
String makeRetData(String retCode, String retMsg) {
NotifyUnifiedOrderResData data = new NotifyUnifiedOrderResData();
data.setReturn_code(retCode);
data.setReturn_msg(retMsg);
return Util.objectToXML(data);
}
String makeRetData(String retCode) {
return makeRetData(retCode, "");
}
}
package org.xxpay.service.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.constant.PayEnum;
import org.xxpay.common.util.*;
import org.xxpay.dal.dao.model.MchInfo;
import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.service.channel.alipay.config.AlipayConfig;
import org.xxpay.service.channel.alipay.sign.RSA;
import org.xxpay.service.channel.alipay.util.AlipayCore;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.Signature;
import org.xxpay.service.channel.tencent.common.Util;
import org.xxpay.service.channel.tencent.protocol.order_protocol.UnifiedOrderReqData;
import org.xxpay.service.channel.tencent.protocol.order_protocol.UnifiedOrderResData;
import org.xxpay.service.channel.tencent.service.UnifiedOrderService;
import org.xxpay.service.service.MchInfoService;
import org.xxpay.service.service.PayChannelService;
import org.xxpay.service.service.PayOrderService;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: 支付渠道接口:支付宝
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class PayChannel4AlipayController {
private final MyLog _log = MyLog.getLog(PayChannel4AlipayController.class);
@Autowired
private DiscoveryClient client;
@Autowired
private PayOrderService payOrderService;
@Autowired
private PayChannelService payChannelService;
@Autowired
UnifiedOrderService unifiedOrderService;
@Autowired
private AlipayConfig alipayConfig;
@Autowired
private MchInfoService mchInfoService;
/**
* 支付宝WAP支付
* 文档:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.ZGobeF&treeId=60&articleId=104790&docType=1
* @param jsonParam
* @return
*/
@RequestMapping(value = "/pay/channel/ali_wap")
public String doAliPayWapReq(@RequestParam String jsonParam) {
String logPrefix = "【支付宝WAP支付下单】";
JSONObject paramObj = JSON.parseObject(new String(MyBase64.decode(jsonParam)));
PayOrder payOrder = paramObj.getObject("payOrder", PayOrder.class);
String payOrderId = payOrder.getPayOrderId();
String mchId = payOrder.getMchId();
String channelId = payOrder.getChannelId();
MchInfo mchInfo = mchInfoService.selectMchInfo(mchId);
String resKey = mchInfo == null ? "" : mchInfo.getResKey();
if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001));
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
alipayConfig.init(payChannel.getParam());
Map<String, String> payMap = new HashMap<>();
payMap.put("service", "alipay.wap.create.direct.pay.by.user"); // 接口名称
payMap.put("partner", alipayConfig.getPartner()); // 签约的支付宝账号对应的支付宝唯一用户号
payMap.put("_input_charset", "utf-8"); // 商户网站使用的编码格式,仅支持UTF-8
payMap.put("notify_url", alipayConfig.getNotify_url()); // 支付宝服务器主动通知商户网站里指定的页面http路径
//if (!StringUtils.isEmpty(params.get("respUrl"))) {
// payMap.put("return_url", params.get("respUrl")); // 支付宝处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径(该字段可以不参与签名,但值不能为空!)
//}
payMap.put("out_trade_no", payOrderId); // 支付宝合作商户网站唯一订单号
payMap.put("subject", payOrder.getSubject()); // 商品的标题/交易标题/订单标题/订单关键字等
payMap.put("total_fee", AmountUtil.convertCent2Dollar(payOrder.getAmount().toString())); // 该笔订单的资金总额,单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位
payMap.put("seller_id", alipayConfig.getPartner()); // 卖家支付宝账号对应的支付宝唯一用户号
payMap.put("payment_type", "1"); // 支付类型。仅支持:1(商品购买)
// 获取objParams参数
String objParams = payOrder.getExtra();
String show_url = "http://www.xxpay.org";
if (!org.springframework.util.StringUtils.isEmpty(objParams)) {
try {
JSONObject objParamsJson = JSONObject.parseObject(objParams);
show_url = ObjectUtils.toString(objParamsJson.getString("ali_show_url"), "http://www.xxpay.org");
} catch (Exception e) {
_log.error("{}objParams参数格式错误!", logPrefix);
}
}
payMap.put("show_url", show_url); // 用户付款中途退出返回商户网站的地址
payMap.put("body", payOrder.getBody()); // 对一笔交易的具体描述信息
payMap.put("it_b_pay", "60m"); // 设置未付款交易的超时时间,一旦超时,该笔交易就会自动被关闭
payMap.put("app_pay", "Y"); // app_pay=Y:尝试唤起支付宝客户端进行支付,若用户未安装支付宝,则继续使用wap收银台进行支付
String signContent = AlipayCore.createLinkString(payMap);
String paySign = RSA.sign(signContent, alipayConfig.getPrivate_key(), AlipayConfig.input_charset);
try {
/**
* 仅需对sign 做URL编码
*/
paySign = URLEncoder.encode(paySign, "UTF-8");
} catch (UnsupportedEncodingException e) {
_log.error(e, "URLEncoder AliPay Sign Exception");
}
_log.info("{}生成请求支付宝签名,sign={}", logPrefix, paySign);
payMap.put("sign_type", "RSA"); // 签名类型
payMap.put("sign", paySign); // 签名
// 对有中文的参数转码
try {
payMap.put("subject", URLEncoder.encode(payOrder.getSubject(), "UTF-8"));
payMap.put("body", URLEncoder.encode(payOrder.getBody(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String payUrl = alipayConfig.getGateway().concat("?").concat(AlipayCore.createLinkString(payMap));
_log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl);
payOrderService.updateStatus4Ing(payOrderId, null);
_log.info("{}生成请求支付宝数据,req={}", logPrefix, payMap);
_log.info("###### 商户统一下单处理完成 ######");
Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("payOrderId", payOrderId);
map.put("payUrl", payUrl);
return XXPayUtil.makeRetData(map, resKey);
}
/**
* 支付宝PC支付(即时到帐接口)
* 文档:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.M7NEo1&treeId=62&articleId=104743&docType=1
* @param jsonParam
* @return
*/
@RequestMapping(value = "/pay/channel/ali_pc")
public String doAliPayPcReq(@RequestParam String jsonParam) {
String logPrefix = "【支付宝PC支付下单】";
JSONObject paramObj = JSON.parseObject(new String(MyBase64.decode(jsonParam)));
PayOrder payOrder = paramObj.getObject("payOrder", PayOrder.class);
String payOrderId = payOrder.getPayOrderId();
String mchId = payOrder.getMchId();
String channelId = payOrder.getChannelId();
MchInfo mchInfo = mchInfoService.selectMchInfo(mchId);
String resKey = mchInfo == null ? "" : mchInfo.getResKey();
if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001));
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
alipayConfig.init(payChannel.getParam());
Map<String, String> payMap = new HashMap<>();
payMap.put("service", "create_direct_pay_by_user"); // 接口名称
payMap.put("partner", alipayConfig.getPartner()); // 签约的支付宝账号对应的支付宝唯一用户号
payMap.put("_input_charset", "utf-8"); // 编码字符集
payMap.put("notify_url", alipayConfig.getNotify_url()); // 支付宝服务器主动通知商户网站里指定的页面http路径
//if (!StringUtils.isEmpty(params.get("respUrl"))) {
// payMap.put("return_url", params.get("respUrl")); // 支付宝处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径(该字段可以不参与签名,但值不能为空!)
//}
payMap.put("out_trade_no", payOrderId); // 商户网站唯一订单号
payMap.put("subject", payOrder.getSubject()); // 订单标题
payMap.put("payment_type", "1"); // 支付类型,只支持取值为1(商品购买)
payMap.put("total_fee", AmountUtil.convertCent2Dollar(payOrder.getAmount().toString())); // 订单总金额
payMap.put("seller_id", alipayConfig.getPartner()); // 卖家支付宝用户号
payMap.put("body", payOrder.getBody()); // 对交易或商品的描述
// 附加参数
payMap.put("qr_pay_mode", "4");
String objParams = payOrder.getExtra();
if (!org.springframework.util.StringUtils.isEmpty(objParams)) {
try {
JSONObject objParamsJson = JSONObject.parseObject(objParams);
payMap.put("qr_pay_mode", ObjectUtils.toString(objParamsJson.getString("qr_pay_mode"), "4")); // 扫码支付的方式,支持前置模式和跳转模式。(4:直接显示二维码)
payMap.put("qrcode_width", ObjectUtils.toString(objParamsJson.getString("qrcode_width"), "200")); // 扫码支付的方式,支持前置模式和跳转模式。(定义二维码大小)
} catch (Exception e) {
_log.error("{}objParams参数格式错误!", logPrefix);
}
}
String signContent = AlipayCore.createLinkString(payMap);
String paySign = RSA.sign(signContent, alipayConfig.getPrivate_key(), AlipayConfig.input_charset);
try {
/**
* 仅需对sign 做URL编码
*/
paySign = URLEncoder.encode(paySign, "UTF-8");
} catch (UnsupportedEncodingException e) {
_log.error(e, "URLEncoder AliPay Sign Exception");
}
_log.info("{}生成请求支付宝签名,sign={}", logPrefix, paySign);
payMap.put("sign_type", "RSA"); // 签名类型
payMap.put("sign", paySign); // 签名
// 对有中文的参数转码
try {
payMap.put("subject", URLEncoder.encode(payOrder.getSubject(), "UTF-8"));
payMap.put("body", URLEncoder.encode(payOrder.getBody(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String payUrl = alipayConfig.getGateway().concat("?").concat(AlipayCore.createLinkString(payMap));
_log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl);
payOrderService.updateStatus4Ing(payOrderId, null);
_log.info("{}生成请求支付宝数据,req={}", logPrefix, payMap);
_log.info("###### 商户统一下单处理完成 ######");
Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("payOrderId", payOrderId);
map.put("payUrl", payUrl);
return XXPayUtil.makeRetData(map, resKey);
}
/**
* 支付宝支付,生产签名及请求支付宝的参数(注:不会向支付宝发请求)
* @param jsonParam
* @return
*/
@RequestMapping(value = "/pay/channel/ali_mobile")
public String doAliPayMobileReq(@RequestParam String jsonParam) {
String logPrefix = "【支付宝支付下单】";
JSONObject paramObj = JSON.parseObject(new String(MyBase64.decode(jsonParam)));
PayOrder payOrder = paramObj.getObject("payOrder", PayOrder.class);
String payOrderId = payOrder.getPayOrderId();
String mchId = payOrder.getMchId();
String channelId = payOrder.getChannelId();
MchInfo mchInfo = mchInfoService.selectMchInfo(mchId);
String resKey = mchInfo == null ? "" : mchInfo.getResKey();
if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001));
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
alipayConfig.init(payChannel.getParam());
Map<String, String> payMap = new HashMap<>();
payMap.put("service", "mobile.securitypay.pay"); // 接口名称
payMap.put("partner", alipayConfig.getPartner()); // 合作者身份ID
payMap.put("_input_charset", "utf-8"); // 参数编码字符集
payMap.put("notify_url", alipayConfig.getNotify_url()); // 服务器异步通知页面路径
//payMap.put("app_id", ""); // 客户端号
//payMap.put("appenv", ""); // 客户端来源
payMap.put("out_trade_no", payOrderId); // 商户网站唯一订单号
payMap.put("subject", payOrder.getSubject()); // 商品名称
payMap.put("payment_type", "1"); // 支付类型
payMap.put("seller_id", alipayConfig.getAli_account()); // 卖家支付宝账号
payMap.put("total_fee", AmountUtil.convertCent2Dollar(payOrder.getAmount().toString())); // 总金额,需要分转元.
payMap.put("body", payOrder.getBody()); // 商品详情
//payMap.put("goods_type", ""); // 商品类型
//payMap.put("hb_fq_param", ""); // 花呗分期参数
//payMap.put("rn_check", ""); // 是否发起实名校验
//payMap.put("it_b_pay", "30m"); // 未付款交易的超时时间
//payMap.put("extern_token", ""); // 授权令牌
String signContent = AlipayCore.createLinkString(payMap);
String paySign = RSA.sign(signContent, alipayConfig.getPrivate_key(), AlipayConfig.input_charset);
try {
/**
* 仅需对sign 做URL编码
*/
paySign = URLEncoder.encode(paySign, "UTF-8");
} catch (UnsupportedEncodingException e) {
_log.error(e, "URLEncoder AliPay Sign Exception");
}
_log.info("{}生成请求支付宝签名,sign={}", logPrefix, paySign);
payMap.put("sign_type", "RSA"); // 签名类型
payMap.put("sign", paySign); // 签名
payOrderService.updateStatus4Ing(payOrderId, null);
_log.info("{}生成请求支付宝数据,req={}", logPrefix, payMap);
_log.info("###### 商户统一下单处理完成 ######");
Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("payOrderId", payOrderId);
map.put("payParams", payMap);
return XXPayUtil.makeRetData(map, resKey);
}
}
package org.xxpay.service.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.constant.PayEnum;
import org.xxpay.common.util.MyBase64;
import org.xxpay.common.util.MyLog;
import org.xxpay.common.util.PayDigestUtil;
import org.xxpay.common.util.XXPayUtil;
import org.xxpay.dal.dao.model.MchInfo;
import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.Signature;
import org.xxpay.service.channel.tencent.common.Util;
import org.xxpay.service.channel.tencent.protocol.order_protocol.UnifiedOrderReqData;
import org.xxpay.service.channel.tencent.protocol.order_protocol.UnifiedOrderResData;
import org.xxpay.service.channel.tencent.service.UnifiedOrderService;
import org.xxpay.service.service.MchInfoService;
import org.xxpay.service.service.PayChannelService;
import org.xxpay.service.service.PayOrderService;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: 支付渠道接口:微信
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class PayChannel4WxController {
private final MyLog _log = MyLog.getLog(PayChannel4WxController.class);
@Autowired
private DiscoveryClient client;
@Autowired
private PayOrderService payOrderService;
@Autowired
private PayChannelService payChannelService;
@Autowired
private MchInfoService mchInfoService;
@Autowired
private UnifiedOrderService unifiedOrderService;
@Autowired
private Configure configure;
/**
* 发起微信支付(统一下单)
* @param
* @return
*/
@RequestMapping(value = "/pay/channel/wx")
public String doWxPayReq(@RequestParam String jsonParam) {
// TODO 参数校验
JSONObject paramObj = JSON.parseObject(new String(MyBase64.decode(jsonParam)));
PayOrder payOrder = paramObj.getObject("payOrder", PayOrder.class);
String tradeType = paramObj.getString("tradeType");
String logPrefix = "【微信支付统一下单】";
String mchId = payOrder.getMchId();
String channelId = payOrder.getChannelId();
MchInfo mchInfo = mchInfoService.selectMchInfo(mchId);
String resKey = mchInfo == null ? "" : mchInfo.getResKey();
if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001));
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
configure.init(payChannel.getParam());
String payOrderId = payOrder.getPayOrderId();
UnifiedOrderReqData unifiedOrderReqData = buildUnifiedOrderReqData(tradeType, payOrder, configure);
try {
_log.info("{}发起支付请求,请求数据:{}", logPrefix, unifiedOrderReqData.toMap());
// 设置CRT
unifiedOrderService.init(configure);
String responseStr = unifiedOrderService.request(unifiedOrderReqData);
// 打印回包数据
_log.info("{}发起支付请求,返回数据:{}", logPrefix, responseStr);
// 转换为返回数据类型
UnifiedOrderResData unifiedOrderResData = (UnifiedOrderResData) Util.getObjectFromXML(responseStr, UnifiedOrderResData.class);
if (unifiedOrderResData == null || unifiedOrderResData.getReturn_code() == null) {
_log.error("{}【支付失败】支付请求逻辑错误,请仔细检测传过去的每一个参数是否合法,或是看API能否被正常访问", logPrefix);
return XXPayUtil.makeRetData(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0111), resKey);
}
if (unifiedOrderResData.getReturn_code().equals("FAIL")) {
//注意:一般这里返回FAIL是出现系统级参数错误,请检测Post给API的数据是否规范合法
_log.error("{}【支付失败】支付API系统返回失败,请检测Post给API的数据是否规范合法", logPrefix);
return XXPayUtil.makeRetData(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0111), resKey);
} else {
_log.info("{}支付API系统成功返回数据", logPrefix);
//--------------------------------------------------------------------
//收到API的返回数据的时候得先验证一下数据有没有被第三方篡改,确保安全
//--------------------------------------------------------------------
if (!Signature.checkIsSignValidFromResponseString(responseStr, configure.getKey())) {
_log.error("{}【支付失败】支付请求API返回的数据签名验证失败,有可能数据被篡改了", logPrefix);
return XXPayUtil.makeRetData(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0111), resKey);
}
_log.info("{}支付请求返回数据验签通过", logPrefix);
//获取错误码
String errorCode = unifiedOrderResData.getErr_code();
//获取错误描述
String errorCodeDes = unifiedOrderResData.getErr_code_des();
if (unifiedOrderResData.getResult_code().equals("SUCCESS")) {
_log.info("{} >>> 下单成功", logPrefix);
Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("payOrderId", payOrderId);
map.put("prepayId", unifiedOrderResData.getPrepay_id());
int result = payOrderService.updateStatus4Ing(payOrderId, unifiedOrderResData.getPrepay_id());
_log.info("更新第三方支付订单号:payOrderId={},prepayId={},result={}", payOrderId, unifiedOrderResData.getPrepay_id(), result);
//map.put("rechargeId", String.valueOf(rechargeId));
if(tradeType.equals(PayConstant.WxConstant.TRADE_TYPE_NATIVE)) {
map.put("codeUrl", unifiedOrderResData.getCode_url());
}else if (tradeType.equals(PayConstant.WxConstant.TRADE_TYPE_APP)) {
Map<String, Object> m = new HashMap<>();
m.put("appid", unifiedOrderReqData.getAppid());
m.put("partnerid", unifiedOrderReqData.getMch_id());
m.put("prepayid", unifiedOrderResData.getPrepay_id());
m.put("package", "Sign=WXPay");
m.put("noncestr", unifiedOrderReqData.getNonce_str());
m.put("timestamp", System.currentTimeMillis()/1000);
String wxSign = Signature.getSign(m, configure.getKey());
m.put("sign", wxSign);
map.put("payParams", m);
map.put("payPrice", payOrder.getAmount());
}else if(tradeType.equals(PayConstant.WxConstant.TRADE_TYPE_JSPAI)) {
Map<String, Object> m = new HashMap<>();
m.put("appId", unifiedOrderReqData.getAppid());
m.put("timeStamp", System.currentTimeMillis()/1000);
m.put("nonceStr", unifiedOrderReqData.getNonce_str());
m.put("package", "prepay_id=" + unifiedOrderResData.getPrepay_id());
m.put("signType", "MD5");
String wxSign = Signature.getSign(m, configure.getKey());
m.put("paySign", wxSign);
map.put("payParams", m);
map.put("payPrice", payOrder.getAmount());
}
return XXPayUtil.makeRetData(map, resKey);
}else{
//出现业务错误
_log.info("{}下单返回失败", logPrefix);
_log.info("err_code:{}", errorCode);
_log.info("err_code_des:{}", errorCodeDes);
return XXPayUtil.makeRetData(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_FAIL, "0111", "调用微信支付失败," + errorCode + ":" + errorCodeDes), resKey);
}
}
} catch (Exception e) {
_log.error(e, "请求异常,%s", e.getMessage());
}
_log.info("###### 商户统一下单处理完成 ######");
return XXPayUtil.makeRetData(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null), resKey);
}
/**
* 构建统一下单请求数据
* @param tradeType
* @param payOrder
* @param configure
* @return
*/
UnifiedOrderReqData buildUnifiedOrderReqData(String tradeType, PayOrder payOrder, Configure configure) {
String payOrderId = payOrder.getPayOrderId();
String payPrice = payOrder.getAmount()+"";
String deviceInfo = payOrder.getDevice();
String body = payOrder.getBody();
String detail = null;
String attach = null;
String outTradeNo = payOrderId;
String feeType = "CNY";
String totalFee = payPrice; // 支付金额,单位分
String spBillCreateIP = payOrder.getClientIp();
String timeStart = null;
String timeExpire = null;
String goodsTag = null;
String notifyUrl = configure.getNotify_url();
String productId = null;
if(tradeType.equals(PayConstant.WxConstant.TRADE_TYPE_NATIVE)) productId = JSON.parseObject(payOrder.getExtra()).getString("productId");
String limitPay = null;
String openId = null;
if(tradeType.equals(PayConstant.WxConstant.TRADE_TYPE_JSPAI)) openId = JSON.parseObject(payOrder.getExtra()).getString("openId");
UnifiedOrderReqData unifiedOrderReqData = new UnifiedOrderReqData(configure, deviceInfo, body, detail, attach,
outTradeNo, feeType, totalFee, spBillCreateIP, timeStart, timeExpire, goodsTag, notifyUrl,
tradeType, productId, limitPay, openId);
return unifiedOrderReqData;
}
}
package org.xxpay.service.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.util.MyBase64;
import org.xxpay.common.util.MyLog;
import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.service.service.PayChannelService;
/**
* @Description: 支付渠道接口
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class PayChannelServiceController {
private final MyLog _log = MyLog.getLog(PayChannelServiceController.class);
@Autowired
private PayChannelService payChannelService;
@RequestMapping(value = "/pay_channel/select")
public String selectPayChannel(@RequestParam String jsonParam) {
// TODO 参数校验
_log.info("selectPayChannel << {}", jsonParam);
JSONObject retObj = new JSONObject();
retObj.put("code", "0000");
if(StringUtils.isBlank(jsonParam)) {
retObj.put("code", "0001"); // 参数错误
}
JSONObject paramObj = JSON.parseObject(new String(MyBase64.decode(jsonParam)));
String channelId = paramObj.getString("channelId");
String mchId = paramObj.getString("mchId");
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
if(payChannel == null) {
retObj.put("result", "");
}else {
retObj.put("result", JSON.toJSON(payChannel));
}
_log.info("selectPayChannel >> {}", retObj);
return retObj.toJSONString();
}
}
package org.xxpay.service.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.util.MyBase64;
import org.xxpay.common.util.MyLog;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.service.channel.tencent.service.UnifiedOrderService;
import org.xxpay.service.service.PayOrderService;
/**
* @Description: 支付订单接口
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class PayOrderServiceController {
private final MyLog _log = MyLog.getLog(PayOrderServiceController.class);
@Autowired
private DiscoveryClient client;
@Autowired
private PayOrderService payOrderService;
@Autowired
UnifiedOrderService unifiedOrderService;
@RequestMapping(value = "/pay/create")
public String createPayOrder(@RequestParam String jsonParam) {
// TODO 参数校验
PayOrder payOrder = JSON.parseObject(new String(MyBase64.decode(jsonParam)), PayOrder.class);
int result = payOrderService.createPayOrder(payOrder);
JSONObject retObj = new JSONObject();
retObj.put("result", result);
return retObj.toJSONString();
}
}
package org.xxpay.service.mq;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.activemq.ScheduledMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.xxpay.common.util.MyLog;
import org.xxpay.service.service.PayOrderService;
import javax.jms.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Description: 业务通知MQ实现
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@Component
public class Mq4PayNotify {
@Autowired
private JmsTemplate jmsTemplate;
@Autowired
private Queue payNotifyQueue;
@Autowired
private PayOrderService payOrderService;
private static final MyLog _log = MyLog.getLog(Mq4PayNotify.class);
public void send(String msg) {
_log.info("发送MQ消息:msg={}", msg);
this.jmsTemplate.convertAndSend(this.payNotifyQueue, msg);
}
/**
* 发送延迟消息
* @param msg
* @param delay
*/
public void send(String msg, long delay) {
_log.info("发送MQ延时消息:msg={},delay={}", msg, delay);
jmsTemplate.send(this.payNotifyQueue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
TextMessage tm = session.createTextMessage(msg);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1*1000);
tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, 1);
return tm;
}
});
}
private static class TrustAnyTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
@JmsListener(destination = MqConfig.PAY_NOTIFY_QUEUE_NAME)
public void receive(String msg) {
_log.info("do notify task, msg={}", msg);
JSONObject msgObj = JSON.parseObject(msg);
String respUrl = msgObj.getString("url");
String orderId = msgObj.getString("orderId");
int count = msgObj.getInteger("count");
if(StringUtils.isEmpty(respUrl)) {
_log.warn("notify url is empty. respUrl={}", respUrl);
return;
}
try {
StringBuffer sb = new StringBuffer();
URL console = new URL(respUrl);
_log.info("==>MQ通知业务系统开始[orderId:{}][count:{}][time:{}]", orderId, count, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
if("https".equals(console.getProtocol())) {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { new TrustAnyTrustManager() },
new java.security.SecureRandom());
HttpsURLConnection con = (HttpsURLConnection) console.openConnection();
con.setSSLSocketFactory(sc.getSocketFactory());
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setConnectTimeout(10 * 1000);
con.setReadTimeout(5 * 1000);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()), 1024*1024);
while (true) {
String line = in.readLine();
if (line == null) {
break;
}
sb.append(line);
}
in.close();
}else if("http".equals(console.getProtocol())) {
HttpURLConnection con = (HttpURLConnection) console.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setConnectTimeout(10 * 1000);
con.setReadTimeout(5 * 1000);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()), 1024*1024);
while (true) {
String line = in.readLine();
if (line == null) {
break;
}
sb.append(line);
}
in.close();
}else {
_log.error("not do protocol. protocol=%s", console.getProtocol());
return;
}
_log.info("<==MQ通知业务系统结束[orderId:{}][count:{}][time:{}]", orderId, count, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
// 验证结果
_log.info("notify response , OrderID={}", orderId);
if(sb.toString().trim().equalsIgnoreCase("success")){
//_log.info("{} notify success, url:{}", _notifyInfo.getBusiId(), respUrl);
//修改订单表
try {
int result = payOrderService.updateStatus4Complete(orderId);
_log.info("修改payOrderId={},订单状态为处理完成->{}", orderId, result == 1 ? "成功" : "失败");
} catch (Exception e) {
_log.error(e, "修改订单状态为处理完成异常");
}
return ; // 通知成功结束
}else {
// 通知失败,延时再通知
int cnt = count++;
if (cnt > 5) {
_log.info("notify count>5 stop. url={}", respUrl);
return ;
}
// 修改通知次数
try {
int result = payOrderService.updateNotify(orderId);
_log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败");
}catch (Exception e) {
_log.error(e, "修改通知次数异常");
}
msgObj.put("count", cnt);
this.send(msgObj.toJSONString(), cnt*60*1000);
}
_log.warn("notify failed. url:{}, response body:{}", respUrl, sb.toString());
} catch(Exception e) {
_log.info("<==MQ通知业务系统结束[orderId:{}][count:{}][time:{}]", orderId, count, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
_log.error(e, "notify exception. url:%s", respUrl);
}
}
}
package org.xxpay.service.mq;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.jms.Queue;
/**
* @Description:
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@Configuration
public class MqConfig {
public static final String PAY_NOTIFY_QUEUE_NAME = "pay.notify.queue";
@Bean
public Queue payNotifyQueue() {
return new ActiveMQQueue(PAY_NOTIFY_QUEUE_NAME);
}
}
package org.xxpay.service.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xxpay.dal.dao.mapper.MchInfoMapper;
import org.xxpay.dal.dao.model.MchInfo;
/**
* @Description:
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@Component
public class MchInfoService {
@Autowired
private MchInfoMapper mchInfoMapper;
public MchInfo selectMchInfo(String mchId) {
return mchInfoMapper.selectByPrimaryKey(mchId);
}
}
package org.xxpay.service.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.xxpay.dal.dao.mapper.PayChannelMapper;
import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.dal.dao.model.PayChannelExample;
import java.util.List;
/**
* @Description:
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@Component
public class PayChannelService {
@Autowired
private PayChannelMapper payChannelMapper;
public PayChannel selectPayChannel(String channelId, String mchId) {
PayChannelExample example = new PayChannelExample();
PayChannelExample.Criteria criteria = example.createCriteria();
criteria.andChannelIdEqualTo(channelId);
criteria.andMchIdEqualTo(mchId);
List<PayChannel> payChannelList = payChannelMapper.selectByExample(example);
if(CollectionUtils.isEmpty(payChannelList)) return null;
return payChannelList.get(0);
}
}
package org.xxpay.service.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.dal.dao.mapper.PayOrderMapper;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.dal.dao.model.PayOrderExample;
/**
* @Description:
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@Component
public class PayOrderService {
@Autowired
private PayOrderMapper payOrderMapper;
public int createPayOrder(PayOrder payOrder) {
return payOrderMapper.insertSelective(payOrder);
}
public PayOrder selectPayOrder(String payOrderId) {
return payOrderMapper.selectByPrimaryKey(payOrderId);
}
public int updateStatus4Ing(String payOrderId, String channelOrderNo) {
PayOrder payOrder = new PayOrder();
payOrder.setStatus(PayConstant.PAY_STATUS_PAYING);
if(channelOrderNo != null) payOrder.setChannelOrderNo(channelOrderNo);
payOrder.setPaySuccTime(System.currentTimeMillis());
PayOrderExample example = new PayOrderExample();
PayOrderExample.Criteria criteria = example.createCriteria();
criteria.andPayOrderIdEqualTo(payOrderId);
criteria.andStatusEqualTo(PayConstant.PAY_STATUS_INIT);
return payOrderMapper.updateByExampleSelective(payOrder, example);
}
public int updateStatus4Success(String payOrderId) {
PayOrder payOrder = new PayOrder();
payOrder.setPayOrderId(payOrderId);
payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);
payOrder.setPaySuccTime(System.currentTimeMillis());
PayOrderExample example = new PayOrderExample();
PayOrderExample.Criteria criteria = example.createCriteria();
criteria.andPayOrderIdEqualTo(payOrderId);
criteria.andStatusEqualTo(PayConstant.PAY_STATUS_PAYING);
return payOrderMapper.updateByExampleSelective(payOrder, example);
}
public int updateStatus4Complete(String payOrderId) {
PayOrder payOrder = new PayOrder();
payOrder.setPayOrderId(payOrderId);
payOrder.setStatus(PayConstant.PAY_STATUS_COMPLETE);
PayOrderExample example = new PayOrderExample();
PayOrderExample.Criteria criteria = example.createCriteria();
criteria.andPayOrderIdEqualTo(payOrderId);
criteria.andStatusEqualTo(PayConstant.PAY_STATUS_SUCCESS);
return payOrderMapper.updateByExampleSelective(payOrder, example);
}
public int updateNotify(String payOrderId) {
PayOrder payOrder = selectPayOrder(payOrderId);
PayOrder newPayOrder = new PayOrder();
newPayOrder.setNotifyCount((byte) (payOrder.getNotifyCount()+1));
newPayOrder.setLastNotifyTime(System.currentTimeMillis());
newPayOrder.setPayOrderId(payOrderId);
return payOrderMapper.updateByPrimaryKeySelective(newPayOrder);
}
public int updateNotify(PayOrder payOrder) {
return payOrderMapper.updateByPrimaryKeySelective(payOrder);
}
}
spring:
application:
name: xxpay-service
cloud:
config:
discovery:
enabled: true # 默认false,设为true表示使用注册中心中的configserver配置而不自己配置configserver的uri
serviceId: xxpay-config # 指定config server在服务发现中的serviceId,默认为:configserver
profile: dev
fail-fast: true
password: xxpay
username: user
eureka:
client:
serviceUrl:
defaultZone: http://localhost:2000/eureka/
\ No newline at end of file
#!/bin/sh
#
#该脚本为Linux下启动java程序的通用脚本。即可以作为开机自启动service脚本被调用,
#也可以作为启动java程序的独立脚本来使用。
#
#JDK所在路径
JAVA_HOME="/usr/local/jdk/jdk1.8.0_121"
#Java程序所在的目录(classes的上一级目录)
APP_HOME=/home/xxpay/service/xxpay-service
#需要启动的Java主程序(main方法类)
APP_MAINCLASS=org.xxpay.XxPayServiceApplication
#拼凑完整的classpath参数,包括指定lib目录下所有的jar
CLASSPATH=$APP_HOME/classes
for i in "$APP_HOME"/lib/*.jar; do
CLASSPATH="$CLASSPATH":"$i"
done
#java虚拟机启动参数
JAVA_OPTS="-ms512m -mx512m -Xmn128m -Djava.awt.headless=true -XX:MaxPermSize=64m"
###################################
#(函数)判断程序是否已启动
#
#说明:
#使用JDK自带的JPS命令及grep命令组合,准确查找pid
#jps 加 l 参数,表示显示java的完整包路径
#使用awk,分割出pid ($1部分),及Java程序名称($2部分)
#当jps命令不可用时,使用: ps -ef | grep $APP_MAINCLASS | grep -v "grep" | awk '{print $2}' 代替
###################################
#初始化psid变量(全局)
psid=0
checkpid() {
javaps=`$JAVA_HOME/bin/jps -l | grep $APP_MAINCLASS`
#javaps=`ps -ef | grep $APP_MAINCLASS | grep -v "grep" | awk '{print $2}'`
if [ -n "$javaps" ]; then
psid=`echo $javaps | awk '{print $1}'`
else
psid=0
fi
}
###################################
#(函数)启动程序
#
#说明:
#1. 首先调用checkpid函数,刷新$psid全局变量
#2. 如果程序已经启动($psid不等于0),则提示程序已启动
#3. 如果程序没有被启动,则执行启动命令行
#4. 启动命令执行后,再次调用checkpid函数
#5. 如果步骤4的结果能够确认程序的pid,则打印[OK],否则打印[Failed]
#注意:echo -n 表示打印字符后,不换行
#注意: "nohup 某命令 >/dev/null 2>&1 &" 的用法
###################################
start() {
checkpid
if [ $psid -ne 0 ]; then
echo "================================"
echo "warn: $APP_MAINCLASS already started! (pid=$psid)"
echo "================================"
else
echo -n "Starting $APP_MAINCLASS ..."
# -DlogFn=active 指的是生产日志文件名为active
nohup $JAVA_HOME/bin/java $JAVA_OPTS -DlogFn=level -classpath $CLASSPATH $APP_MAINCLASS >/dev/null 2>&1 &
checkpid
if [ $psid -ne 0 ]; then
echo "(pid=$psid) [OK]"
else
echo "[Failed]"
fi
fi
}
###################################
#(函数)停止程序
#
#说明:
#1. 首先调用checkpid函数,刷新$psid全局变量
#2. 如果程序已经启动($psid不等于0),则开始执行停止,否则,提示程序未运行
#3. 使用kill -9 pid命令进行强制杀死进程
#4. 执行kill命令行紧接其后,马上查看上一句命令的返回值: $?
#5. 如果步骤4的结果$?等于0,则打印[OK],否则打印[Failed]
#6. 为了防止java程序被启动多次,这里增加反复检查进程,反复杀死的处理(递归调用stop)。
#注意:echo -n 表示打印字符后,不换行
#注意: 在shell编程中,"$?" 表示上一句命令或者一个函数的返回值
###################################
stop() {
checkpid
if [ $psid -ne 0 ]; then
echo -n "Stopping $APP_MAINCLASS ...(pid=$psid) "
kill -9 $psid
if [ $? -eq 0 ]; then
echo "[OK]"
else
echo "[Failed]"
fi
checkpid
if [ $psid -ne 0 ]; then
stop
fi
else
echo "================================"
echo "warn: $APP_MAINCLASS is not running"
echo "================================"
fi
}
###################################
#(函数)检查程序运行状态
#
#说明:
#1. 首先调用checkpid函数,刷新$psid全局变量
#2. 如果程序已经启动($psid不等于0),则提示正在运行并表示出pid
#3. 否则,提示程序未运行
###################################
status() {
checkpid
if [ $psid -ne 0 ]; then
echo "$APP_MAINCLASS is running! (pid=$psid)"
else
echo "$APP_MAINCLASS is not running"
fi
}
###################################
#(函数)打印系统环境参数
###################################
info() {
echo "System Information:"
echo "****************************"
echo `head -n 1 /etc/issue`
echo `uname -a`
echo
echo "JAVA_HOME=$JAVA_HOME"
echo `$JAVA_HOME/bin/java -version`
echo
echo "APP_HOME=$APP_HOME"
echo "APP_MAINCLASS=$APP_MAINCLASS"
echo "****************************"
}
###################################
#读取脚本的第一个参数($1),进行判断
#参数取值范围:{start|stop|restart|status|info}
#如参数不在指定范围之内,则打印帮助信息
###################################
case "$1" in
'start')
start
;;
'stop')
stop
;;
'restart')
stop
start
;;
'status')
status
;;
'info')
info
;;
*)
echo "Usage: $0 {start|stop|restart|status|info}"
exit 1
esac
exit 0
\ No newline at end of file
package org.xxpay.service.dal;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class ApplicationTests {
private MockMvc mvc;
@Before
/*public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new ComputeController()).build();
}*/
@Test
public void getHello() throws Exception {
}
}
package org.xxpay.service.dal;
import com.alibaba.fastjson.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class MchInfoTest {
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
/*MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(
new MgrController()
).build();*/
}
@Test
public void addMchInfo() throws Exception {
JSONObject params = new JSONObject();
params.put("mchId", "20001222");
params.put("name", "骏易科技");
params.put("type", "1");
params.put("reqKey", "298332323231231313");
params.put("resKey", "883435353534543534");
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/mch/add").param("params", params.toJSONString()))
// .andExpect(MockMvcResultMatchers.status().isOk())
// .andExpect(MockMvcResultMatchers.model().attributeExists("user"))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
}
package org.xxpay.service.dal;
import com.alibaba.fastjson.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class PayOrderTest {
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
/*MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(
new PayOrderController()
).build();*/
}
@Test
public void payOrder() throws Exception {
// mockMvc.perform(MockMvcRequestBuilders.post("/secured/resources/incoterms/create").accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON)
// .content("{\"code\" : \"EXW\", \"description\" : \"code exw\", \"locationQualifier\" : \"DEPARTURE\"}".getBytes()))
// //.andDo(print())
// .andExpect(status().isOk())
// .andExpect(jsonPath("id.value").exists())
// .andExpect(jsonPath("id.value").value("6305ff33-295e-11e5-ae37-54ee7534021a"))
// .andExpect(jsonPath("code").value("EXW"));
//params={mchId:20001222,mchOrderNo:3132121212,channelId:"alipay-app",amount:100,currentcy:"cny",clientIp:"127.0.0.1",device:"app",notifyUrl:"www.baidu.com",sign:1111111}
JSONObject params = new JSONObject();
params.put("mchId", "20001222");
params.put("mchOrderNo", "20001222");
params.put("channelId", "20001222");
params.put("amount", "20001222");
params.put("currentcy", "20001222");
params.put("clientIp", "20001222");
params.put("device", "20001222");
params.put("notifyUrl", "20001222");
params.put("sign", "20001222");
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/pay_order").param("params", params.toJSONString()))
// .andExpect(MockMvcResultMatchers.status().isOk())
// .andExpect(MockMvcResultMatchers.model().attributeExists("user"))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.xxpay</groupId>
<artifactId>xxpay-web</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>xxpay-web</name>
<description>xxpay4spring-cloud</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.xxpay</groupId>
<artifactId>xxpay-common</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/package.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>-->
</plugins>
</build>
</project>
\ No newline at end of file
package org.xxpay;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Description: xxpay支付产品服务,提供各商户支付产品接口
* @author dingzhiwei jmdhappy@126.com
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker
public class XxPayWebApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(XxPayWebApplication.class, args);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment