| java110-bean/src/main/java/com/java110/vo/ResultVo.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| java110-utils/src/main/java/com/java110/utils/constant/WechatConstant.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| service-acct/pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| service-acct/src/main/java/com/java110/acct/AcctServiceApplicationStart.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| service-acct/src/main/java/com/java110/acct/cmd/payment/QrCodePaymentCmd.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| service-acct/src/main/java/com/java110/acct/smo/IQrCodePaymentSMO.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| service-acct/src/main/java/com/java110/acct/smo/impl/QrCodeAliPaymentAdapt.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| service-acct/src/main/java/com/java110/acct/smo/impl/QrCodeWechatPaymentAdapt.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| service-api/src/main/java/com/java110/api/listener/fee/DeleteFeeListener.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
java110-bean/src/main/java/com/java110/vo/ResultVo.java
@@ -42,6 +42,8 @@ public static final int DEFAULT_RECORD = 1; public static final int DEFAULT_TOTAL = 1; public static final int CODE_WAIT_PAY = 41;// 支付未完成 // 分页页数 private int page; // 行数 java110-utils/src/main/java/com/java110/utils/constant/WechatConstant.java
@@ -64,5 +64,8 @@ public static final String PAY_NOTIFY_ADAPT = "PAY_NOTIFY_ADAPT"; public static final String PAY_OWE_FEE_NOTIFY_ADAPT = "PAY_OWE_FEE_NOTIFY_ADAPT"; public static final String wxMicropayUnifiedOrder="https://api.mch.weixin.qq.com/pay/micropay"; public static final String wxOrderQuery="https://api.mch.weixin.qq.com/pay/orderquery"; } pom.xml
@@ -492,6 +492,12 @@ <artifactId>aliyun-sdk-oss</artifactId> <version>${oss.aliyun}</version> </dependency> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.10.111.ALL</version> </dependency> </dependencies> </dependencyManagement> service-acct/pom.xml
@@ -25,7 +25,10 @@ <groupId>com.java110</groupId> <artifactId>java110-service</artifactId> </dependency> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> </dependency> </dependencies> service-acct/src/main/java/com/java110/acct/AcctServiceApplicationStart.java
@@ -1,7 +1,9 @@ package com.java110.acct; import com.java110.core.annotation.Java110CmdDiscovery; import com.java110.core.annotation.Java110ListenerDiscovery; import com.java110.core.client.RestTemplate; import com.java110.core.event.cmd.ServiceCmdEventPublishing; import com.java110.core.event.service.BusinessServiceDataFlowEventPublishing; import com.java110.service.init.ServiceStartInit; import org.slf4j.Logger; @@ -35,6 +37,8 @@ @EnableDiscoveryClient @Java110ListenerDiscovery(listenerPublishClass = BusinessServiceDataFlowEventPublishing.class, basePackages = {"com.java110.acct.listener"}) @Java110CmdDiscovery(cmdPublishClass = ServiceCmdEventPublishing.class, basePackages = {"com.java110.acct.cmd"}) @EnableFeignClients(basePackages = {"com.java110.intf.community","com.java110.intf.common","com.java110.intf.store", "com.java110.intf.fee","com.java110.intf.order","com.java110.intf.user"}) public class AcctServiceApplicationStart { @@ -66,4 +70,16 @@ RestTemplate restTemplate = new RestTemplateBuilder().additionalMessageConverters(m).build(RestTemplate.class); return restTemplate; } /** * 实例化RestTemplate,通过@LoadBalanced注解开启均衡负载能力. * * @return restTemplate */ @Bean public RestTemplate outRestTemplate() { StringHttpMessageConverter m = new StringHttpMessageConverter(Charset.forName("UTF-8")); RestTemplate restTemplate = new RestTemplateBuilder().additionalMessageConverters(m).build(RestTemplate.class); return restTemplate; } } service-acct/src/main/java/com/java110/acct/cmd/payment/QrCodePaymentCmd.java
New file @@ -0,0 +1,33 @@ package com.java110.acct.cmd.payment; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradeAppPayModel; import com.alipay.api.request.AlipayTradeAppPayRequest; import com.alipay.api.response.AlipayTradeAppPayResponse; import com.java110.core.annotation.Java110Cmd; import com.java110.core.context.ICmdDataFlowContext; import com.java110.core.event.cmd.AbstractServiceCmdListener; import com.java110.core.event.cmd.CmdEvent; import com.java110.utils.exception.CmdException; /** * 扫码付 */ @Java110Cmd(serviceCode = "payment.qrCodePayment") public class QrCodePaymentCmd extends AbstractServiceCmdListener { @Override public void validate(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) { } @Override public void doCmd(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) throws CmdException { } } service-acct/src/main/java/com/java110/acct/smo/IQrCodePaymentSMO.java
New file @@ -0,0 +1,26 @@ package com.java110.acct.smo; import com.java110.vo.ResultVo; /** * 扫码枪支付 */ public interface IQrCodePaymentSMO { /** * 扫码支付 * * @return */ ResultVo pay(String communityId, String orderNum, double money, String authCode, String feeName) throws Exception; /** * 检查是否支付完成 * * @param communityId * @param orderNum * @return */ ResultVo checkPayFinish(String communityId, String orderNum); } service-acct/src/main/java/com/java110/acct/smo/impl/QrCodeAliPaymentAdapt.java
New file @@ -0,0 +1,112 @@ package com.java110.acct.smo.impl; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.request.AlipayTradePayRequest; import com.alipay.api.request.AlipayTradeQueryRequest; import com.alipay.api.response.AlipayTradePayResponse; import com.alipay.api.response.AlipayTradeQueryResponse; import com.java110.acct.smo.IQrCodePaymentSMO; import com.java110.utils.cache.MappingCache; import com.java110.utils.constant.WechatConstant; import com.java110.vo.ResultVo; /** * 阿里支付 */ public class QrCodeAliPaymentAdapt implements IQrCodePaymentSMO { /** * APP_ID 应用id */ public final static String APP_ID = "2016093000630181"; /** * 应用私钥 */ public final static String APP_PRIVATE_KEY = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCTO5ERumMOQlwy2+2hrSUgqFd+PsQ5Au+sK7+xNrB6fmR2oSWSn+X8EEjQBWq21RWV1ekABWSsG2BtOWlnWxT77tfyXLOzejR3vujFhwLPshzA9lfR2R5fH/F3l0MGmWvb3GGYqp2q2SR7jXUtOU5dEEGHUYRd9zoy9CPEM2Iu1xWA5ks51C5XH2AJV62ZDCc82sAJt7xfrDLCZbwKGp0a4b6ZgA1OoZDn7Jzp160fFA81EbkfrKK+qOoyMV9dbHSotHHQfD3+49o1coz3vpPY9r/kD6FhZ3ZdU1SfYccaEpyMAbdfR/RAtHlRiA9JUgXXFiExavKUEwdEGizwug45AgMBAAECggEAftF2GXEUVXnvdJdfTj2Xl1OpWUKzPfA7hW+BhCF5TWmFG3GerXcxYDaeoR+pVaahGxjPw4bhuiUyn6IuGiqoHoESXN5gox2GCAbW9R1f3IqsncESz9xWftVC5iHSR+LqtsxS/G8ps7mp5QppffS4fQy9hNNAUrfa13zXOe6QiYq/BHiBzJKT4Bp4P5iQMM4/J/Y4fPOHTHEo4iZX+a2WC2ZBMbAXZWfMmIKenqZVDuf7GO8/TpHMpkI9pEePU7njSqRX2+zixcVJ/M8EgSj0JCFZUUCKDz78Nuu2UvdTrLfFTYTIrr4nhVdsduDpJ0LKSJEcvaxku1AhgRgWBgfj6QKBgQDzugV2tnWG495gQyipqPXIYd2JVIdWfAgUfNdDD8bd/FZ/grATQo4R4zDdgXS5a2c0AFzJU7MMkWo4DTKpjU6aZIdY8PdgnI3SefKJzw3ndBGPou5RbVFVkrehahU4u1LVKldmo/pvlMCqpp00UBkO2Tzl4v6lLQsRKXvJCDJvjwKBgQCapZpIW+nk8QjkArsqY2j9NQeRz3JRQ6UJkW4sf+4JgbtXgXgu/arpCTevCi50zqv8TE4nmJj8YtE0H7qbBgOSgJV2i+0/eRCsV8oNu9WzQVM8qyGtoQ4fKxhMNN2CcWGh5gXk2wRG6qFz69MxEJ+RAK5ev4w1bDu89SS4d5dBtwKBgDqEZEFvZ2JenYqxNTce6PwWezE4yVG7b9kzbB+ezxmHN2FgCFRne2LSEG5uYY8POXUjzSNNZETVORKCILLSyZeKIXD6UfqxO9/YBaKOwwDaPkklTmDghVGta0dnB/daCnZBt0BeiId3yJZwcHgZ7xpAkD2FtawE145kTmMjA7EDAoGAEqpGMtGVK2LENfD2cilJdLY/0aN+IrzNYJhC+e/+5PrZh7hCrzlCtZm9NM0/yi1fqLX1AOZ0IJI0udvSg/930ujeIU7GNdEA6Cw4YOv44QfTahEloXU85Roodpoy2hmhNQ80Suj8XSrYjcs61EMzXyb75MetvozvsODNq84TXYUCgYB11cFAnLXztA2wKjRSsPP8Hm1vDLmq4CoM2qyqeDSdVCeRqQJ4VSwtsFsGRPXfrrx4CbTKDRiV04hJTVYtnpX67bo34GIXxW1RtLYeCk1lWBI7u3D398qMGcpbo3FzwJ+v8pD3uzTTnk88Xx2qUeghRoLvQd/KP0dcfpZLllBOFA=="; /** * 编码 */ public final static String CHARSET = "UTF-8"; /** * 支付宝公钥 */ public final static String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjeZA25b4mJZpWWXHR0joM8eOSm1DuBDKKgq5ZYDkxKUPhLuXfK588EcFaSGlW9yzpvNkxBbq3QEzqx5K3zYaVHjzh0y+8vlfCcFINMpcYgy3q8NsQHgipO994TqIUwukac8GzezVAT7avtwBeWMNGJDnpQAJNkOD6se2sMu2IXFa7GkfRxhJCMNi/e/d16j0D/YfT2F1c1hRzH1Ey0I3Rkx1WxZTPYH+lCSVaIkxVtolYIpoktE70ZVcD1ERy5eipWCT4sdl/UMifgTnj+PyL+R6lzMUVPKQ+xk5G5PoJUiRSAOkqcaB+KTaerL0h0VzOXKqQ2O/3ppdrTn4X+mAgQIDAQAB"; /** * (沙箱)网关 */ public final static String GETEWAY_URL = "https://openapi.alipaydev.com/gateway.do"; /** * 格式化 */ public final static String FORMAT = "json"; /** * 签名类型 */ public final static String SIGN_TYPE = "RSA2"; @Override public ResultVo pay(String communityId, String orderNum, double money, String authCode, String feeName) throws Exception { String systemName = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, WechatConstant.PAY_GOOD_NAME); AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", "app_id", "your private_key", "json", "GBK", "alipay_public_key", "RSA2"); AlipayTradePayRequest request = new AlipayTradePayRequest(); JSONObject bizContent = new JSONObject(); bizContent.put("out_trade_no", orderNum); bizContent.put("total_amount", money); bizContent.put("subject", systemName + feeName); bizContent.put("scene", "bar_code"); bizContent.put("auth_code", authCode); request.setBizContent(bizContent.toString()); AlipayTradePayResponse response = alipayClient.execute(request); if (response.isSuccess()) { System.out.println("调用成功"); } else { System.out.println("调用失败"); } if (response.isSuccess()) { return new ResultVo(ResultVo.CODE_OK, "成功"); } else { return new ResultVo(ResultVo.CODE_ERROR, response.getSubMsg()); } } @Override public ResultVo checkPayFinish(String communityId, String orderNum) { AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", "app_id", "your private_key", "json", "GBK", "alipay_public_key", "RSA2"); AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); request.setBizContent("{" + " \"out_trade_no\":\"20150320010101001\"," + " \"trade_no\":\"2014112611001004680 073956707\"," + " \"query_options\":[" + " \"trade_settle_info\"" + " ]" + "}"); AlipayTradeQueryResponse response = null; try { response = alipayClient.execute(request); } catch (AlipayApiException e) { return new ResultVo(ResultVo.CODE_ERROR, "查询失败" + e.getErrMsg()); } if (!"10000".equals(response.getCode())) { return new ResultVo(ResultVo.CODE_ERROR, response.getMsg()); } String tradeStatus = response.getTradeStatus(); if ("WAIT_BUYER_PAY".equals(tradeStatus)) { return new ResultVo(ResultVo.CODE_WAIT_PAY, "等待支付完成"); } else if ("TRADE_SUCCESS".equals(tradeStatus)) { return new ResultVo(ResultVo.CODE_OK, "支付成功"); } else { return new ResultVo(ResultVo.CODE_ERROR, "未知错误" + tradeStatus); } } } service-acct/src/main/java/com/java110/acct/smo/impl/QrCodeWechatPaymentAdapt.java
New file @@ -0,0 +1,164 @@ package com.java110.acct.smo.impl; import com.java110.acct.smo.IQrCodePaymentSMO; import com.java110.core.client.RestTemplate; import com.java110.dto.smallWeChat.SmallWeChatDto; import com.java110.intf.store.ISmallWeChatInnerServiceSMO; import com.java110.utils.cache.MappingCache; import com.java110.utils.constant.WechatConstant; import com.java110.utils.util.PayUtil; import com.java110.vo.ResultVo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; /** * 微信支付 */ public class QrCodeWechatPaymentAdapt implements IQrCodePaymentSMO { private static Logger logger = LoggerFactory.getLogger(QrCodeWechatPaymentAdapt.class); //微信支付 public static final String DOMAIN_WECHAT_PAY = "WECHAT_PAY"; // 微信服务商支付开关 public static final String WECHAT_SERVICE_PAY_SWITCH = "WECHAT_SERVICE_PAY_SWITCH"; //开关ON打开 public static final String WECHAT_SERVICE_PAY_SWITCH_ON = "ON"; private static final String WECHAT_SERVICE_APP_ID = "SERVICE_APP_ID"; private static final String WECHAT_SERVICE_MCH_ID = "SERVICE_MCH_ID"; @Autowired private ISmallWeChatInnerServiceSMO smallWeChatInnerServiceSMOImpl; @Autowired private RestTemplate outRestTemplate; @Override public ResultVo pay(String communityId, String orderNum, double money, String authCode, String feeName) throws Exception { logger.info("【小程序支付】 统一下单开始, 订单编号=" + orderNum); SortedMap<String, String> resultMap = new TreeMap<String, String>(); //生成支付金额,开发环境处理支付金额数到0.01、0.02、0.03元 double payAmount = PayUtil.getPayAmountByEnv(MappingCache.getValue("HC_ENV"), money); //添加或更新支付记录(参数跟进自己业务需求添加) Map<String, String> resMap = null; logger.debug("resMap=" + resMap); String systemName = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, WechatConstant.PAY_GOOD_NAME); SmallWeChatDto shopSmallWeChatDto = null; SmallWeChatDto smallWeChatDto = new SmallWeChatDto(); smallWeChatDto.setObjId(communityId); List<SmallWeChatDto> smallWeChatDtos = smallWeChatInnerServiceSMOImpl.querySmallWeChats(smallWeChatDto); if (smallWeChatDtos == null && smallWeChatDtos.size() < 1) { shopSmallWeChatDto = new SmallWeChatDto(); shopSmallWeChatDto.setObjId(communityId); shopSmallWeChatDto.setAppId(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "appId")); shopSmallWeChatDto.setAppSecret(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "appSecret")); shopSmallWeChatDto.setMchId(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "mchId")); shopSmallWeChatDto.setPayPassword(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "payPassword")); } else { shopSmallWeChatDto = smallWeChatDtos.get(0); } SortedMap<String, String> paramMap = new TreeMap<String, String>(); paramMap.put("appid", shopSmallWeChatDto.getAppId()); paramMap.put("mch_id", shopSmallWeChatDto.getMchId()); paramMap.put("nonce_str", PayUtil.makeUUID(32)); paramMap.put("body", systemName + feeName); paramMap.put("out_trade_no", orderNum); paramMap.put("total_fee", PayUtil.moneyToIntegerStr(payAmount)); paramMap.put("spbill_create_ip", PayUtil.getLocalIp()); paramMap.put("auth_code", authCode); String paySwitch = MappingCache.getValue(DOMAIN_WECHAT_PAY, WECHAT_SERVICE_PAY_SWITCH); if (WECHAT_SERVICE_PAY_SWITCH_ON.equals(paySwitch)) { paramMap.put("appid", MappingCache.getValue(DOMAIN_WECHAT_PAY, WECHAT_SERVICE_APP_ID)); //服务商appid,是服务商注册时公众号的id paramMap.put("mch_id", MappingCache.getValue(DOMAIN_WECHAT_PAY, WECHAT_SERVICE_MCH_ID)); //服务商商户号 paramMap.put("sub_appid", smallWeChatDto.getAppId());//起调小程序appid paramMap.put("sub_mch_id", smallWeChatDto.getMchId());//起调小程序的商户号 paramMap.remove("openid"); } paramMap.put("sign", PayUtil.createSign(paramMap, smallWeChatDto.getPayPassword())); //转换为xml String xmlData = PayUtil.mapToXml(paramMap); logger.debug("调用支付统一下单接口" + xmlData); ResponseEntity<String> responseEntity = outRestTemplate.postForEntity( WechatConstant.wxMicropayUnifiedOrder, xmlData, String.class); logger.debug("统一下单返回" + responseEntity); //请求微信后台,获取预支付ID if (responseEntity.getStatusCode() != HttpStatus.OK) { throw new IllegalArgumentException("支付失败" + responseEntity.getBody()); } resMap = PayUtil.xmlStrToMap(responseEntity.getBody()); if ("SUCCESS".equals(resMap.get("return_code")) && "SUCCESS".equals(resMap.get("result_code"))) { return new ResultVo(ResultVo.CODE_OK, "成功"); } else { return new ResultVo(ResultVo.CODE_ERROR, resMap.get("msg")); } } public ResultVo checkPayFinish(String communityId, String orderNum) { SmallWeChatDto shopSmallWeChatDto = null; Map<String, String> result = null; try { SmallWeChatDto smallWeChatDto = new SmallWeChatDto(); smallWeChatDto.setObjId(communityId); List<SmallWeChatDto> smallWeChatDtos = smallWeChatInnerServiceSMOImpl.querySmallWeChats(smallWeChatDto); if (smallWeChatDtos == null && smallWeChatDtos.size() < 1) { shopSmallWeChatDto = new SmallWeChatDto(); shopSmallWeChatDto.setObjId(communityId); shopSmallWeChatDto.setAppId(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "appId")); shopSmallWeChatDto.setAppSecret(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "appSecret")); shopSmallWeChatDto.setMchId(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "mchId")); shopSmallWeChatDto.setPayPassword(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "payPassword")); } else { shopSmallWeChatDto = smallWeChatDtos.get(0); } SortedMap<String, String> paramMap = new TreeMap<String, String>(); paramMap.put("appid", shopSmallWeChatDto.getAppId()); paramMap.put("mch_id", shopSmallWeChatDto.getMchId()); paramMap.put("nonce_str", PayUtil.makeUUID(32)); paramMap.put("out_trade_no", orderNum); paramMap.put("sign", PayUtil.createSign(paramMap, smallWeChatDto.getPayPassword())); //转换为xml String xmlData = PayUtil.mapToXml(paramMap); logger.debug("调用支付统一下单接口" + xmlData); ResponseEntity<String> responseEntity = outRestTemplate.postForEntity( WechatConstant.wxOrderQuery, xmlData, String.class); logger.debug("统一下单返回" + responseEntity); //请求微信后台,获取预支付ID if (responseEntity.getStatusCode() != HttpStatus.OK) { throw new IllegalArgumentException("支付失败" + responseEntity.getBody()); } result = PayUtil.xmlStrToMap(responseEntity.getBody()); } catch (Exception e) { logger.error("请求失败", e); return new ResultVo(ResultVo.CODE_WAIT_PAY, e.getLocalizedMessage()); } if (!"SUCCESS".equals(result.get("trade_state"))) { return new ResultVo(ResultVo.CODE_WAIT_PAY, "等待支付完成"); } return new ResultVo(ResultVo.CODE_OK, "支付成功"); } } service-api/src/main/java/com/java110/api/listener/fee/DeleteFeeListener.java
@@ -79,7 +79,11 @@ feeDetailDto.setFeeId(reqJson.getString("feeId")); feeDetailDto.setStates(new String[]{"1400", "1000"}); List<FeeDetailDto> feeDetailDtos = feeDetailInnerServiceSMOImpl.queryFeeDetails(feeDetailDto); Assert.listOnlyOne(feeDetailDtos, "存在缴费记录,不能取消,如果需要取消,请先退费"); //Assert.listOnlyOne(feeDetailDtos, "存在缴费记录,不能取消,如果需要取消,请先退费"); if(feeDetailDtos != null && feeDetailDtos.size()>0){ throw new IllegalArgumentException("存在缴费记录,不能取消,如果需要取消,请先退费"); } }