小编在此说一声,建议去看一下微信官方提供的支付流程图,以及其他的之后再看下面的。小编在此就不提供账号申请,那些准备工作了,直接上代码。
流程总结:首先APP发送一个请求,想购买的商品。后台生成一个预支付订单,然后将APP支付所需要的信息返回给App支付即可。支付成功后,微信服务器回调你请求预支付订单告诉微信服务器的回调地址。收到回调后执行你的业务逻辑。并在最后一定要告诉微信服务器你已收到回调,不然微信会无限回调你。
以下有几个注意事项:
1、建议订单金额不在交互中直接暴露传输,防止篡改。
2、一般流程是在请求预支付的订单的时候在自己数据库中设计两张表,一张是支付订单表,一张是订单流水表。支付订单表设计一个状态,未支付,已支付。在预支付订单中可传输自己的订单号out_trade_no,通过这个标识。收到该订单的标识就将状态改成已支付,且在流水表中记录充值金额之类的信息。
3、在回调中需要订单是否已被处理过,再判断实际支付金额和订单金额是否匹配。防止实际支付金额被篡改。
4、微信的单位是分哦,所以记得处理一下。
好的现在我们就直接上代码:
controller
package com.irandoo.support.wxpay.action;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.alibaba.fastjson.JSON;
import com.irandoo.app.interf.json.PrivateRoomJson;
import com.irandoo.app.interf.service.PrivateRoomJsonService;
import com.irandoo.support.wxpay.handler.PrepayIdRequestHandler;
import com.irandoo.support.wxpay.model.RechargeOrder;
import com.irandoo.support.wxpay.service.RechargeOrderService;
import com.irandoo.support.wxpay.util.ConstantUtil;
import com.irandoo.support.wxpay.util.MD5Util;
import com.irandoo.support.wxpay.util.OrderUtil;
import com.irandoo.support.wxpay.util.WXUtil;
import com.irandoo.support.wxpay.util.XMLUtil;
import com.irandoo.xhep.base.action.BaseAction;
import com.irandoo.xhep.base.model.Meal;
import com.irandoo.xhep.base.service.MealService;
import com.irandoo.xhep.base.service.RechargeRecordService;
import com.irandoo.xhep.base.service.UserAccountService;
import com.irandoo.xhep.base.util.WawaConstantUtil;
/**
*<p>Title:WeiXinPayController </p>
*<p>Description:</p>
*<p>Company:</p>
*@author sun
*@date 2018年1月22日10:01:19
*/
@Controller("wechatPayAction")
@Scope("prototype")
public class WechatPayAction extends BaseAction {
/**
*
*/
private static final long serialVersionUID = 4071603624936342541L;
private Log logger = LogFactory.getLog(WechatPayAction.class);
@Autowired
MealService mealService;
@Autowired
RechargeOrderService rechargeOrderService;
@Autowired
UserAccountService userAccountService;
@Autowired
RechargeRecordService rechargeRecordService;
@Autowired
PrivateRoomJsonService privateRoomJsonService;
/**
* 生成预支付订单,获取prepayId
* @param request
* @param response
* @return
* @throws Exception
*/
public String wxPay(){
String o = request.getParameter("object");
Map<String,Object> paramMap = (Map<String,Object>)JSON.parse(o);
//----------------------获取App传过来的参数-------------------
//获取套餐id
String meals = (String) paramMap.get("mealId");
Long mealId = Long.parseLong(meals);
//获取套餐详细信息
Meal meal = mealService.getInfoByMealId(mealId);
//获取用户id
String userId = (String) request.getAttribute("userId");
logger.info("套餐价格:"+meal.getPrice());
//获取充值渠道
String channelName = (String) paramMap.get("channelName");
//房间id
String roomId = (String) paramMap.get("roomId");
String privateRoomId = null;
String receiveUserId = null;
RechargeOrder rechargeOrder =new RechargeOrder();
if (null != paramMap.get("roomId")){//它充
//获取房间id
roomId = (String) paramMap.get("roomId");
rechargeOrder.setRoomId(Long.parseLong(roomId));
if (null != paramMap.get("privateRoomId")) {
//获取包房id
privateRoomId = (String) paramMap.get("privateRoomId");
//根据包房id获取被充人
Map<String, Object> mealmap = new HashMap<>();
mealmap.put("id", privateRoomId);
List<PrivateRoomJson> m = privateRoomJsonService.returnInfo(mealmap);
//获取被充人id
receiveUserId = m.get(0).getCreator();;
rechargeOrder.setReceiveUserId(Long.parseLong(receiveUserId));
rechargeOrder.setPrivateRoomId(Long.parseLong(privateRoomId));
}
}else{//自充
receiveUserId = userId;
rechargeOrder.setReceiveUserId(Long.parseLong(receiveUserId));
}
Map<String, Object> map=new HashMap<String, Object>();
//2.5 订单号,此处用时间加随机数生成,商户根据自己情况调整,只要保持全局唯一就行
String strReq =OrderUtil.createOrderId();
//设置充值订单实体
rechargeOrder.setOrderId(strReq);
rechargeOrder.setBuyUserId(Long.parseLong(userId));
rechargeOrder.setMealId(mealId);
rechargeOrder.setPayMoney(meal.getPrice());
rechargeOrder.setPayType(channelName);
//生成交易订单
try {
rechargeOrderService.insert(rechargeOrder);
logger.info("成功交易单成功!");
} catch (Exception e) {
e.printStackTrace();
logger.info("生成交易单失败!");
}
//获取充值金额;
String total_fee= meal.getPrice()*100+""; //充值金额
String out_trade_no=strReq; //订单号
String timestamp = WXUtil.getTimeStamp(); //超时时间
String nonce_str = WXUtil.getNonceStr(); // 生成随机字符串
//---------------------------------------------- ***** 统一下单开始 ***** -----------------------------------------------------------
//3.获取生成预支付订单的请求类
PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID); //平台应用appId
prepayReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID); //商户号
prepayReqHandler.setParameter("nonce_str", nonce_str); //随机字符串
prepayReqHandler.setParameter("body", ConstantUtil.BUY_BODY); //商品描述
prepayReqHandler.setParameter("out_trade_no", out_trade_no); //订单号
prepayReqHandler.setParameter("total_fee",String.valueOf(total_fee)); //订单价格
prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr()); //获取客户端ip
prepayReqHandler.setParameter("notify_url", ConstantUtil.NOTIFY_URL); //回调通知
prepayReqHandler.setParameter("trade_type", "APP"); //支付类型
prepayReqHandler.setParameter("time_start", timestamp); //时间戳
prepayReqHandler.setGateUrl(ConstantUtil.GATEURL); //设置预支付id的接口url
//3.3 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
prepayReqHandler.setParameter("sign", prepayReqHandler.createMD5Sign()); //sign 签名
//3.4 提交预支付,获取prepayid
String prepayid = null;
try {
prepayid = prepayReqHandler.sendPrepay();
logger.debug("预支付订单id----:"+prepayid);
} catch (Exception e) {
e.printStackTrace();
}
//---------------------------------------------- ***** 统一下单 结束 ***** --------------------------------------------------------------
//3.5 若获取prepayid成功,将相关信息返回客户端
String result = null;
String errmsg = null;
if (prepayid != null && !prepayid.equals("")) {
String signs =
"appid=" + ConstantUtil.APP_ID +
"&noncestr=" + nonce_str +
"&package=Sign=WXPay"+
"&partnerid="+ ConstantUtil.PARTNER_ID +
"&prepayid=" + prepayid +
"×tamp=" + timestamp+
"&key="+ ConstantUtil.APP_KEY;
map.put("appid", ConstantUtil.APP_ID);
map.put("partnerid", ConstantUtil.PARTNER_ID); //商家id
map.put("prepayid", prepayid); //预支付id
map.put("package", "Sign=WXPay"); //固定常量
map.put("noncestr", nonce_str); //与请求prepayId时值一致
map.put("timestamp", timestamp); //等于请求prepayId时的time_start
map.put("sign", MD5Util.MD5Encode(signs, "utf8").toUpperCase());//签名方式与上面类似
result = "0";
errmsg = "";
} else {
result = "-1";
errmsg = "获取prepayid失败";
logger.info("获取prepayid失败");
}
return returnJson(map, result, errmsg);
}
/**
* 9.2 接收微信支付成功通知
* @param request
* @param response
* @throws IOException
* @throws java.io.IOException
* @throws ParseException
*/
public void getnotify()throws IOException, ParseException {
//1.创建输入输出流
PrintWriter writer = response.getWriter();
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
//2.将结果转换
String result = new String(outSteam.toByteArray(), "utf-8");
logger.info("微信支付通知结果:" + result);
Map<String, String> map = null;
try {
//3.解析微信通知返回的信息
map = XMLUtil.doXMLParse(result);
logger.info("微信返回结果:" + map);
} catch (JDOMException e) {
e.printStackTrace();
}
// 4.若支付成功,则告知微信服务器收到通知
if (map != null && map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {
String out_trade_no = map.get("out_trade_no");
String wechatMoney = map.get("total_fee");
rechargeOrderService.unifiedOrder(WawaConstantUtil.SYS_PAY_WECHAT, out_trade_no, wechatMoney);
}
String notifyStr = XMLUtil.setXML("ERROR", "");
writer.write(notifyStr);
writer.flush();
}
}
serviceImpl (因为牵扯到支付宝支付,所以回调中将两个整合到一起了)
@Override
public boolean unifiedOrder(String pay_type,String out_trade_no,String money) {
log.info("------支付成功-----");
boolean flag = true;
try {
//查询订单实体
RechargeOrder rechargeOrder = rechargeOrderMapper.getInfoByOrderId(out_trade_no);
if("2".equals(rechargeOrder.getState())||2==rechargeOrder.getState()){
log.info("....已经回调成功过了.....");
} else if(rechargeOrder.getState().equals("1")||rechargeOrder.getState()==1){
//判断实付金额与订单金额是否一致
String payMoney = money;
log.info("订单金额 :"+rechargeOrder.getPayMoney());
String orderPayMoney = null;
if(WawaConstantUtil.SYS_PAY_WECHAT.equalsIgnoreCase(pay_type)){ //微信支付
orderPayMoney = rechargeOrder.getPayMoney()*100+"";
} else { //否则支付宝支付
orderPayMoney = rechargeOrder.getPayMoney()+"";
}
log.info("orderPayMoney"+orderPayMoney+"----payMoney"+payMoney);
if(orderPayMoney.equals(payMoney)){
//修改订单状态
rechargeOrder.setState(Long.parseLong("2"));
int n = rechargeOrderMapper.updateState(rechargeOrder);
if(n>0){//修改成功,执行添加账户的操作
//获取充值人的id
Long receiveUserId = rechargeOrder.getReceiveUserId();
//根据套餐id获取套餐信息
Meal meal= mealMapper.getInfoByMealId(rechargeOrder.getMealId());
//获取套餐里的币
Long doll_coin = meal.getDoll_coin();
//获取套餐奖励的币
Long reward_coin = meal.getReward_coin();
//判断是否是首充
int sumCount = 0;
UserGameConnectionJson userGameConnectionJson = userGameConnectionJsonMapper.getInfoById(rechargeOrder.getBuyUserId());
//添加首充系统消息
SysInformation sysInformation = new SysInformation();
if("1".equals(userGameConnectionJson.getIsFirstPay())){
sumCount=(int) (doll_coin+reward_coin);
sysInformation.setUser_id(receiveUserId);
sysInformation.setContent("恭喜您充值成功,获得"+sumCount+"个币。");
sysInformation.setType(WawaConstantUtil.SYS_PAY);
}else{
sumCount=(int) (doll_coin+reward_coin+meal.getFirst_reward_coin());
sysInformation.setUser_id(receiveUserId);
Long sum = doll_coin+reward_coin;
sysInformation.setContent("恭喜您首充次充值成功,获得"+sum+"个币。奖励您"+meal.getFirst_reward_coin()+"个币。");
sysInformation.setType(WawaConstantUtil.SYS_FIRSTPAY);
//修改首充状态
userGameConnectionJson.setIsFirstPay("1");
}
/**执行会员升级**/
UpgradeMembershipUtil.member(rechargeOrder.getBuyUserId()+"", rechargeOrder.getPayMoney()+"");
//添加累计充值金额
userGameConnectionJson.setSumPayMoney(userGameConnectionJson.getSumPayMoney()+meal.getPrice());
//修改用户关联
userGameConnectionJsonMapper.update(userGameConnectionJson);
sysInformationMapper.insert(sysInformation);
//执行添加币的服务
Map<String, Object> accountMap =new HashMap<String, Object>();
accountMap.put("userId", receiveUserId);
//默认充值币账户
accountMap.put("accountType", 1);
accountMap.put("balance", sumCount);
int m = userAccountMapper.addBalance(accountMap);
//----执行每日任务----
Map<String,Object> map = new HashMap<String,Object>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date = sdf.format(new Date());
log.info("当前日期:"+date);
map.put("userId", receiveUserId);
map.put("statisticsDate",date);
map.put("taskDate",date);
DayTaskThread.startDayTask(InterfaceConstantUtil.PAY, map);
if(m>0){//添加成功
//添加充值流水
RechargeRecord rechargeRecord = new RechargeRecord();
if(null!=rechargeOrder.getRoomId()){
rechargeRecord.setRoom_id(rechargeOrder.getRoomId());
}
rechargeRecord.setUser_id(rechargeOrder.getBuyUserId());
rechargeRecord.setMeal_id(rechargeOrder.getMealId());
rechargeRecord.setRecharge_order_id(out_trade_no);
rechargeRecord.setRecharge_user_id(rechargeOrder.getReceiveUserId());
rechargeRecord.setOrder_money(meal.getPrice());
rechargeRecord.setExchange_coin(new Integer(meal.getDoll_coin()+""));
rechargeRecord.setReward_coin(new Integer(meal.getReward_coin()+""));
rechargeRecord.setPay_type(rechargeOrder.getPayType());
rechargeRecord.setPay_money(rechargeOrder.getPayMoney());
rechargeRecord.setType(1); //默认充值充值流水为充值
rechargeRecordMapper.insert(rechargeRecord);
}else{
log.info(out_trade_no+"------充值账户失败-----");
}
}else{
//修改订单状态(失败)
rechargeOrder.setState(Long.parseLong("0"));
rechargeOrderMapper.updateState(rechargeOrder);
log.info("------修改订单状态失败-----");
}
}else{
log.info("非法回调,订单金额与回调金额不一致.");
}
}else{
log.info("失败订单");
}
} catch (Exception e) {
flag=false;
e.printStackTrace();
}
return flag;
}
最后提示:将里面的业务逻辑改成你自己的业务逻辑就好了。
小编在此就不细细说明了,有什么问题注释应该都写了,还有要问题的,可以联系QQ985548426.小编长期在线。
配上源码下载地址:https://download.csdn.net/download/a985548426/10752519