上一篇写了关于支付宝支付的相关问题,本篇主要介绍微信支付的模块
微信支付可以大体分为5块:1.网页支付、2.App支付、3.H5外部浏览器支付、4.小程序支付、5.H5微信内部浏览器支付。这篇文章主要讲解 2、3、4、5这4种支付。
整体难度来说:H5微信内部浏览器支付>H5外部浏览器支付>小程序支付>App支付>网页支付。
编程语言为JAVA,采用的框架是SpringBoot+Mybatis.
控制层代码:
1.createPayOrder为三端统一调起的接口 只用appType和code区分出到底是调用哪个方法
2.因为H5外部浏览器支付需要获取用户的Ip地址所以主动去获取了请求的ip地址
3.isPayEarnest只是区分是否定金
@RestController
@RequestMapping("/wechatpay")
public class WeChatPayController {
@Autowired
private WeChatPayService weChatPayService;
/**
* 发起统一下单
* @param appType 0为H5端 1为小程序 2为app
* @param billNo Code是微信通过授权后获取的
* @return Result
*/
@RequestMapping(value = "/createPayOrder", method = RequestMethod.POST)
public @ResponseBody Result createAppWeChatPayOrder(HttpServletRequest request, int appType, String billNo,
String code, int isPayEarnest) {
if (appType == 0) {
if (code != null) {
return weChatPayService.h5CreateInnerPayOrder(billNo,code,isPayEarnest);
}
// h5
return weChatPayService.h5CreatePayOrder(billNo, getIpAddr(request), isPayEarnest);
} else if (appType == 1) {
// 小程序
return weChatPayService.wxAppCreatePayOrder(code, billNo, isPayEarnest);
} else {
// app
return weChatPayService.appCreatePayOrder(appType, billNo, isPayEarnest);
}
}
/**
* 获取访问者IP
*
* 在一般情况下使用Request.getRemoteAddr()即可,但是经过nginx等反向代理软件后,这个方法会失效。
*
* 本方法先从Header中获取X-Real-IP,如果不存在再从X-Forwarded-For获得第一个IP(用,分割),
* 如果还不存在则调用Request .getRemoteAddr()。
*
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Real-IP");
if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
ip = request.getHeader("X-Forwarded-For");
if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
// 多次反向代理后会有多个IP值,第一个为真实IP。
int index = ip.indexOf(',');
if (index != -1) {
return ip.substring(0, index);
} else {
return ip;
}
} else {
return request.getRemoteAddr();
}
}
/**
* 查询订单
* @param appType String
* @param wxBillNo String
* @param erpBillNo String
* @return
*/
@RequestMapping(value = "/orderquery")
public @ResponseBody Result orderQuery(WeChatPayOrderQueryRequest request) {
return weChatPayService.orderQuery(request);
}
}
业务层代码:
```
@Service
public class WeChatPayServiceImpl implements WeChatPayService {
private static Logger LOG = Logger.getLogger(WeChatPayServiceImpl.class);
//微信支付配置参数
@Autowired
private WeChatPayProperties weChatPayProperties;
private String orderDetail = "XXXX业务:";
//支付业务
@Autowired
private PayService payService;
@Override
public Result wxAppCreatePayOrder(String code, String billNo, int isPayEarnest) {
// 向微信请求获取openId
Map<String, Object> openIdMap = getOpenId(initWxAppOpenIdParmMap(code));
if (openIdMap == null) {
return new Result(Constants.FAILURE_CODE, ErrorMsg.GET_WECHATPAY_OPENID);
}
String openId = (String) openIdMap.get("openid");
if (openId == null) {
return new Result(Constants.FAILURE_CODE, ErrorMsg.GET_WECHATPAY_OPENID);
}
// String session_key = (String) openIdMap.get("session_key");
// 获取订单信息
CarRentOrderPerson dto = payService.findOrder(billNo);
//为了能多次吊起支付,调起支付订单号要加上时间戳
String newbillNo = payService.createNewOrderNo(billNo);
//保存吊起支付请求记录,方便维护(可有可无)
payService.savePayRequest(newbillNo, dto, PayTypeEnums.WXAPP.getIndex(), SourceTypeEnums.WXAPP.getIndex());
// 初始化微信小程序统一下单参数
Map<String, String> params = initWxAppCreatePayBillParams(openId, orderDetail + dto.getModelname(), newbillNo,isPayEarnest == 1 ? dto.getPrepaydeposit().multiply((new BigDecimal(100))): dto.getReceivableamount().multiply((new BigDecimal(100))));
// 向微信平台请求
Result result = sendCreateOrderRequest(params);
if (result.getCode() == Constants.FAILURE_CODE) {
return result;
}
String prePayid = (String) result.getData();
// 封装prePayId到返回参数中,直接返回给前端,前端直接拿着这个就可以调起支付
return new Result(Constants.SUCCESS_CODE, "", initWxAppCreatePayBillReturnParams(prePayid));
}
@Override
public Result appCreatePayOrder(int appType, String billNo, int isPayEarnest) {
// 判断app类型 获取相应appId
String appId = weChatPayProperties.getAppAppid();
if (!(appType == 3 || appType == 2)) {
return new Result(Constants.FAILURE_CODE, ErrorMsg.NO_SUCH_APP_TYPE);
}
// 获取预订单
CarRentOrderPerson dto = payService.findOrder(billNo);
if (dto == null) {
return new Result(Constants.F