package com.ishop.mobile.api; import com.iplatform.base.PlatformRuntimeException; import com.iplatform.base.WechatConstants; import com.ishop.merchant.Constants; import com.ishop.merchant.OrderConstants; import com.ishop.merchant.PayConstants; import com.ishop.merchant.util.PayUtils; import com.ishop.mobile.BaseApi; import com.ishop.mobile.util.WechatUtils; import com.ishop.model.po.EbRechargeOrder; import com.ishop.model.request.UserRechargeRequest; import com.ishop.model.response.OrderPayResultResponse; import com.ishop.model.response.RechargeItemResponse; import com.ishop.model.response.RechargePackageResponse; import com.ishop.model.vo.WxPayJsResultVo; import com.walker.infrastructure.utils.DateUtils; import com.walker.infrastructure.utils.MD5; import com.walker.infrastructure.utils.NumberGenerator; import com.walker.infrastructure.utils.StringUtils; import com.walker.pay.Order; import com.walker.pay.PayEngineManager; import com.walker.pay.exception.OrderException; import com.walker.pay.wechat.v2.H5ResponsePay; import com.walker.web.ResponseValue; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/front/recharge") public class RechargeApi extends BaseApi { private PayEngineManager payEngineManager; @Autowired public RechargeApi(PayEngineManager payEngineManager){ this.payEngineManager = payEngineManager; } /** * 获取用户充值说明。 * @return * @date 2023-09-11 */ @RequestMapping(value = "/get/user/package", method = RequestMethod.GET) public ResponseValue acquireRechargePackage(){ RechargePackageResponse userRechargeResponse = new RechargePackageResponse(); List list = this.acquireGroupDataList(Constants.GROUP_DATA_ID_RECHARGE_PACKAGE, true, RechargeItemResponse.class, null); userRechargeResponse.setPackageList(list); String rechargeAttention = this.getArgumentVariable(Constants.CONFIG_RECHARGE_ATTENTION).getStringValue(); if(StringUtils.isNotEmpty(rechargeAttention)){ List attentionList = StringUtils.asList(StringUtils.delimitedListToStringArray(rechargeAttention, "\n")); userRechargeResponse.setNoticeList(attentionList); } return ResponseValue.success(userRechargeResponse); } /** * 生成用户充值订单 * @return */ @RequestMapping(value = "/user/create", method = RequestMethod.POST) public ResponseValue userCreate(@RequestBody UserRechargeRequest request){ if(request == null || (request.getPrice() == null && request.getGroupDataId() == null)){ return ResponseValue.error("请选择充值套餐或填写自定义充值金额"); } double rechargePrice = 0; // 充值金额 double gainPrice = 0; // 赠送金额 if(request.getPrice() != null){ // 输入金额 rechargePrice = request.getPrice(); if(rechargePrice <= 0){ return ResponseValue.error("充值金额必须大于0"); } } else { // 选择套餐 RechargeItemResponse rechargePackage = this.acquireGroupDataNormal(request.getGroupDataId(), RechargeItemResponse.class, null); if(rechargePackage == null){ return ResponseValue.error("您选择的充值方式已下架"); } rechargePrice = Double.parseDouble(rechargePackage.getPrice()); gainPrice = Double.parseDouble(rechargePackage.getGiveMoney()); } double rechargeMinAmount = this.getArgumentVariable(Constants.USER_RECHARGE_MIN_AMOUNT).getDoubleValue(); if(rechargePrice < rechargeMinAmount){ return ResponseValue.error("充值金额小于最低充值金额"); } long userId = this.getCurrentUserId(); // 生成充值订单号 String rechargeNo = new StringBuilder(OrderConstants.RECHARGE_ORDER_PREFIX) .append(System.currentTimeMillis()).append(StringUtils.generateRandomNumber(6)).toString(); EbRechargeOrder rechargeOrder = new EbRechargeOrder(NumberGenerator.getLongSequenceNumber()); rechargeOrder.setOrderNo(rechargeNo); rechargeOrder.setCreateTime(DateUtils.getDateTimeNumber()); rechargeOrder.setUid(userId); rechargeOrder.setPrice(rechargePrice); rechargeOrder.setGivePrice(gainPrice); OrderPayResultResponse response = new OrderPayResultResponse(); response.setOrderNo(rechargeNo); response.setPayType(request.getPayType()); response.setPayChannel(request.getPayChannel()); if (request.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) { String userOpenId = this.getCurrentUser().getWx_open_id(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // 2023-08-28 不知道为啥openId字符串会带双引号, // 目前没找到原因,先直接剔除,后面要找到(初步估计是redis取出来带的) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(StringUtils.isNotEmpty(userOpenId) && userOpenId.indexOf("\"") >= 0){ userOpenId = userOpenId.replaceAll("\"", StringUtils.EMPTY_STRING); } //~~~~~~~~~~~~~~~~~~~~~~~ end ~~~~~~~~~~~~~~~~~~~~~~~ if(StringUtils.isEmpty(userOpenId)){ return ResponseValue.error("您还未授权(绑定)微信登录,无法完成微信支付"); } WxPayJsResultVo vo = null; // 生成第三方支付使用的订单编号 rechargeOrder.setOutTradeNo(PayUtils.acquirePayOutTradeNo(PayConstants.PAY_TYPE_WE_CHAT)); if(request.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_PUBLIC) || request.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)){ rechargeOrder.setPayType(PayConstants.PAY_TYPE_WE_CHAT); rechargeOrder.setPayChannel(request.getPayChannel()); vo = this.wechatH5Recharge(rechargeOrder, userOpenId); } else { throw new UnsupportedOperationException("还未实现微信其他支付方式:" + request.getPayChannel()); } response.setStatus(true); response.setJsConfig(vo); logger.debug("微信(充值)预下单成功"); this.getUserRechargeService().insert(rechargeOrder); } else if (request.getPayType().equals(PayConstants.PAY_TYPE_ALI_PAY)) { throw new UnsupportedOperationException("未实现支付宝充值代码"); } return ResponseValue.success(response); } private WxPayJsResultVo wechatH5Recharge(EbRechargeOrder order, String userOpenId){ String apiDomain = this.getArgumentVariable(Constants.CONFIG_KEY_API_URL).getStringValue(); String siteName = this.getArgumentVariable(Constants.CONFIG_KEY_SITE_NAME).getStringValue(); String signKey = this.getArgumentVariable(WechatConstants.WECHAT_PAY_PUBLIC_KEY).getStringValue(); String attach = PayConstants.PAY_SERVICE_TYPE_RECHARGE + "," + order.getUid(); double payPriceFen = order.getPrice().doubleValue() * 100; Order platformPayOrder = PayUtils.acquirePlatformOrderH5WechatV2((long)payPriceFen , order.getId(), siteName, attach, "127.0.0.1", apiDomain + PayConstants.WX_PAY_NOTIFY_API_URI, userOpenId); H5ResponsePay responsePay = null; try { responsePay = (H5ResponsePay) this.payEngineManager.generatePrepareOrder(platformPayOrder); } catch (OrderException e) { throw new PlatformRuntimeException("发起微信预订单(充值)错误:" + e.getMessage() + ", orderId=" + e.getOrderId(), e); } if(!responsePay.getStatus()){ throw new PlatformRuntimeException("微信支付H5订单(充值)返回错误:" + responsePay.getMessage(), null); } Map map = new HashMap<>(); map.put("appId", responsePay.getAppId()); map.put("nonceStr", responsePay.getAppId()); map.put("package", "prepay_id=" + responsePay.getPrepayId()); map.put("signType", MD5.MD5_NAME); map.put("timeStamp", String.valueOf(System.currentTimeMillis()/1000)); WxPayJsResultVo vo = new WxPayJsResultVo(); vo.setAppId(responsePay.getAppId()); vo.setNonceStr(responsePay.getAppId()); vo.setPackages("prepay_id=" + responsePay.getPrepayId()); vo.setSignType(MD5.MD5_NAME); vo.setTimeStamp(String.valueOf(System.currentTimeMillis()/1000)); vo.setMwebUrl(responsePay.getCodeUrl()); try { vo.setPaySign(WechatUtils.getSign(map, signKey)); } catch (Exception e) { throw new PlatformRuntimeException("设置返回值签名错误:" + e.getMessage(), e); } return vo; } }