目录

第二弹:支付回调

成果展示

1 订单设计思路

1.1设计思路

2.回调接口

2.1controller

2.2验证静态方法

2.3缓存参数 常量

2.4 service 校验金额

2.4.1金额静态方法校验

2.4.2总体校验

3. 定时任务 查询处理特殊订单

3.1 get请求 统一配置

3.2 查询订单service

3.3关闭订单

3.4 定时任务 处理订单

3.4.1 金额校验 (和微信回调处理金额校验相同)

3.4.2 定时任务处理


第二弹:支付回调

微信支付通过支付通知接口将用户支付成功消息通知给商户

定时任务处理特殊订单

(这些要根据直接项目的情况按需来安排)

成果展示

(只展示部分 这个设计到项目内容 不好全部展示)

1 订单设计思路

1.1设计思路

2.回调接口

2.1controller

 @PostMapping("/wechatPayCallback")@ApiOperation("支付回调给微信确认")@ApiIgnorepublic String wechatCallback(HttpServletRequest request) {ToolWxConfig wxConfig = iToolWxConfigService.find();log.info("微信退款回调通知调用=============================");Gson gson = new Gson();Map<String,String> result = new HashMap(SystemConstant.NUM_16);result.put("code", "FAIL");result.put("message","失败");try {//微信回调信息校验// 构建request,传入必要参数Notification notification = WxPayUtil.verifyBack(request, wxConfig);log.info("=================微信验证签名成功=======成功时间=={}=====",notification.getCreateTime());// 思路: 验证订单 订单号是否存在 订单状态 通过缓存来做到 一回调验证多订单的类型// 生成订单的时候 把订单信息放入缓存中 order:key key为订单号 30min 通过获取 订单消息做到 快速验证 插入操作 用if 进行if (iToolWxConfigService.verifyCreateOrder(notification.getDecryptData())) {log.info("==============================微信退款成功订单=====================================");result.put("code", WXOrderConstant.WX_BACK_OK);result.put("message", "支付回调成功");}} catch (ValidationException | ParseException | IOException e) {log.error("微信支付回调失败验证" + e);}log.info("微信返回结果"+result);return gson.toJson(result);}

2.2验证静态方法

 /***回调验证* @param request 微信回调请求* @param wxConfig 微信基本配置信息* @return String* @author zhangjunrong* @date 2022/4/21 15:02*/public static Notification verifyBack(HttpServletRequest request, ToolWxConfig wxConfig) throws IOException, ValidationException, ParseException {//应答报文主体BufferedReader br = request.getReader();String str;StringBuilder builder = new StringBuilder();while ((str = br.readLine()) != null) {builder.append(str);}// 构建request,传入必要参数//参数 1.微信序列号 2.应答随机串 3.应答时间戳 4.应答签名 5.应答报文主体NotificationRequest notificationRequest = new NotificationRequest.Builder().withSerialNumber(request.getHeader(WechatPayHttpHeaders.WECHATPAY_SERIAL)).withNonce(request.getHeader(WechatPayHttpHeaders.WECHATPAY_NONCE)).withTimestamp(request.getHeader(WechatPayHttpHeaders.WECHATPAY_TIMESTAMP)).withSignature(request.getHeader(WechatPayHttpHeaders.WECHATPAY_SIGNATURE)).withBody(builder.toString()).build();NotificationHandler handler = new NotificationHandler(WxPayUtil.getVerifier(wxConfig), wxConfig.getApiV3key().getBytes(StandardCharsets.UTF_8));// 验签和解析请求体log.info("验签和解析请求体==============================开始验证==============================");Notification notification = handler.parse(notificationRequest);Assert.assertNotNull(notification);return notification;}

2.3缓存参数 常量

package com.yqs.constant.wechatPay;/*** @Description 微信定时任务* @Author 小乌龟* @Date 2022/5/13 9:01*/
public class WxRedisKey {/***微信支付订单 list<对象>=>(订单详细信息key+订单类型+下单时间+支付状态) 有效时间6分钟*/public static final String WX_PAY_ORDER = "wxPayOrderList";/***微信退款订单 存微信基础信息 有效时间3分钟 wxRefundOrder::*/public static final String WX_REFUND_ORDER = "wxRefundOrder::";
}

2.4 service 校验金额

2.4.1金额静态方法校验

 /***验证用户支付金额 场景1.微信回调验证 2.定时任务核对订单* @param node 微信回调json 返回参数* @param redisTotal redis记录金额* @return Boolean* @author zhangjunrong* @date 2022/5/16 8:39*/public static Boolean verifyMoney(JsonNode node,Integer redisTotal){//总金额计数值 用户支付计算int userPayTotal = SystemConstant.NUM_ZERO;//1.验证订单金额//用户支付金额int payerTotal = node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_PAYER_TOTAL).asInt();userPayTotal = userPayTotal + payerTotal;//CASH充值型代金券 要加上优惠金额 银行优惠 获取//排空 如果没有优惠则跳过if (!ObjectUtil.isEmpty(node.get(WXOrderConstant.PROMOTION_DETAIL))) {for (JsonNode objNode : node.get(WXOrderConstant.PROMOTION_DETAIL)) {//如果优惠类型为CASH 则要和 用户支付金额 累加if (WXOrderConstant.WX_DISCOUNT_TYPE.equals(objNode.get(WXOrderConstant.PROMOTION_DETAIL_TYPE).textValue())) {userPayTotal = userPayTotal + objNode.get(WXOrderConstant.AMOUNT).asInt();}}}//2.总金额 预支付时的 金额 与 total 用户支付金额//微信端返回的支付总金额int wxTotal = node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_TOTAL).asInt();//redis缓存中的金额//校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。//缓存中存入的用户支付金额 totalRedisRO.getTicketOrder().getTotalMoney().movePointRight(SystemConstant.NUM_TWO).intValue()log.info("微信回调金额===比较=== "+"微信端返回的支付总金额"+node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_TOTAL).asInt()+"==========redis缓存中的金额"+redisTotal+"================用户支付总金额计算"+userPayTotal);//只要缓存的金额小于用户实际付款金额 判定成功return wxTotal == userPayTotal && redisTotal == wxTotal;}

2.4.2总体校验

@Overridepublic Boolean verifyCreateOrder(String decryptOrder) {//在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。//实现: 加入一把可重入锁if (reentrantLock.tryLock()) {try {log.info("===================================进入微信支付回调核对订单中========================================");ObjectMapper objectMapper = new ObjectMapper();//微信回调 解密后 信息JsonNode node = objectMapper.readTree(decryptOrder);//获取订单商户号String orderNo = node.get(WXOrderConstant.OUT_TRADE_NO).textValue();//1.获取redis中的订单信息OrderTotalRedisRO totalRedisRO = (OrderTotalRedisRO) redisUtil.get(SystemConstant.ORDER_TOTAL + orderNo);//1.1微信 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。//实现方法: 通过订单状态来 判定是否要进行判定 出未支付以外的 都返回 结果 通过缓存获取到支付状态 防止微信重复调用该方法//如果回调 缓存中记录清除说明 入库判定等等成功 直接返回trueif (ObjectUtil.isEmpty(totalRedisRO)) {return true;}log.info(node.get(WXOrderConstant.OUT_TRADE_NO) + "订单回调信息记录:订单状态:" + orderNo);//2.如果回调 支付类型为成功 核对金额 入数据库//获取支付状态String tradeState = node.get(WXOrderConstant.TRADE_STATE).textValue();if (StrUtil.equals(WXOrderConstant.WX_BACK_OK, tradeState)) {//redis缓存中的金额int redisTotal = totalRedisRO.getTicketOrder().getPayMoney().movePointRight(SystemConstant.NUM_TWO).intValue();//校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。//缓存中存入的用户支付金额 totalRedisRO.getTicketOrder().getTotalMoney().movePointRight(SystemConstant.NUM_TWO).intValue()if (WxPayUtil.verifyMoney(node, redisTotal)) {//3.对应的数据入库log.info("redis入数据库信息======================" + totalRedisRO);if (!ObjectUtil.isEmpty(totalRedisRO)) {//缓存放入一个状态 表明已操作该订单 存放200秒// 支付成功就把redis中缓存记录清除totalRedisRO.getTicketOrder().setOrderStatus(SystemConstant.NUM_ONE);redisUtil.del(SystemConstant.ORDER_TOTAL + orderNo);//订单入库iTicketOrderService.createAllTicket(totalRedisRO, node.get(WXOrderConstant.TRANSACTION_ID).textValue());}}//为什么没有插入成功也返回true?//因为就算数据库没有入成功 但是金额 订单校验等等的都通过//说明数据库入库失败//如果入库失败 让用户联系客服接入管理 [钱一定要收下来]return true;}} catch (Exception e) {log.error("订单支付异常===>订单回调信息记录:订单状态:" + decryptOrder);}finally {//释放锁reentrantLock.unlock();}}return false;}

3. 定时任务 查询处理特殊订单

3.1 get请求 统一配置

   /***构造HttpClient 实现 微信申请接口 调用功能* @param wxConfig 微信支付数据库参数* @param verifier 微信验签器* @return CloseableHttpClient* @author zhangjunrong* @date 2022/5/16 8:54*/public static CloseableHttpClient getHttpClient(ToolWxConfig wxConfig, Verifier verifier) {PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(wxConfig.getPrivateKey().getBytes(StandardCharsets.UTF_8)));//通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create().withMerchant(wxConfig.getMchId(), wxConfig.getMchSerialNo(), merchantPrivateKey).withValidator(new WechatPay2Validator(verifier));return builder.build();}
/*** 调用微信支付 get请求 统一配置* 要微信签名认证* @param url* @return String* @author zhangjunrong* @date 2022/5/9 20:39*/private String getHttpGet(ToolWxConfig wxConfig, String url) throws URISyntaxException, IOException {//1.构造httpGet请求URIBuilder uriBuilder = null;uriBuilder = new URIBuilder(url);HttpGet httpGet = new HttpGet(uriBuilder.build());httpGet.addHeader(WechatPayHttpHeaders.ACCEPT, WechatPayHttpHeaders.APPLICATION_JSON);//2.调起微信查询订单接口CloseableHttpResponse response = WxPayUtil.getHttpClient(wxConfig, WxPayUtil.getVerifier(wxConfig)).execute(httpGet);//3.返回结果信息return EntityUtils.toString(response.getEntity());}

3.2 查询订单service

  /*** 查询订单* 使用场景:* 1.当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知。* 2.调用支付接口后,返回系统错误或未知交易状态情况。* 3.调用付款码支付API,返回USERPAYING(用户付费)的状态。* 4.调用关单或撤销接口API之前,需确认支付状态。* @param wxConfig   微信配置* @param outTradeNo 商户订单号 系统生成* @return String 订单交易状态* @author zhangjunrong* @date 2022/4/14 16:14**/
@Overridepublic JsonNode queryCreateOrder(ToolWxConfig wxConfig, String outTradeNo) {try {//1.查单 微信接口 编辑 微信订单号 + 商户号String url = StrFormatter.format(WxApiType.QUERY_CREATE_ORDER.getValue(), outTradeNo, wxConfig.getMchId());//2.调用微信接口String bodyAsString = getHttpGet(wxConfig, url);log.info("支付查单信息" + bodyAsString);//返回查单结果信息if (ObjectUtil.isNotEmpty(bodyAsString)){ObjectMapper objectMapper = new ObjectMapper();return objectMapper.readTree(bodyAsString);}} catch (Exception e) {log.error("支付查单失败" + outTradeNo);}return null;}

3.3关闭订单

  /*** 关闭订单* 使用场景:* 1、商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;* 2、系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。* 注意:关单没有时间限制,建议在订单生成后间隔几分钟(最短5分钟)再调用关单接口,避免出现订单状态同步不及时导致关单失败** @param wxConfig* @param outTradeNo* @return String* @author zhangjunrong* @date 2022/4/14 17:02*/
@Overridepublic String closeOrder(ToolWxConfig wxConfig, String outTradeNo) {try {//1.微信接口编辑String url = StrFormatter.format(WxApiType.CLOSE_ORDER.getValue(), outTradeNo);HttpPost httpPost = new HttpPost(url);//格式配置httpPost.addHeader(WechatPayHttpHeaders.ACCEPT, WechatPayHttpHeaders.APPLICATION_JSON);httpPost.addHeader(WechatPayHttpHeaders.CONTENT_TYPE, WechatPayHttpHeaders.APPLICATION_JSON_UTF);ByteArrayOutputStream bos = new ByteArrayOutputStream();//2.添加商户idObjectMapper objectMapper = new ObjectMapper();ObjectNode rootNode = objectMapper.createObjectNode();rootNode.put(WXOrderConstant.MCHID, wxConfig.getMchId());objectMapper.writeValue(bos, rootNode);//3.调起微信关单接口httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));CloseableHttpResponse response = WxPayUtil.getHttpClient(wxConfig, WxPayUtil.getVerifier(wxConfig)).execute(httpPost);//无数据(Http状态码为204) 微信返回结果无数据 状态码为204 成功if (response.getStatusLine().getStatusCode() == MessageEnum.NO_CONTENT.getCode()) {return "关单成功";}} catch (Exception e) {log.error("关单失败" + outTradeNo + e);}return null;}

3.4 定时任务 处理订单

3.4.1 金额校验 (和微信回调处理金额校验相同)

 /***验证用户支付金额 场景1.微信回调验证 2.定时任务核对订单* @param node 微信回调json 返回参数* @param redisTotal redis记录金额* @return Boolean* @author zhangjunrong* @date 2022/5/16 8:39*/public static Boolean verifyMoney(JsonNode node,Integer redisTotal){//总金额计数值 用户支付计算int userPayTotal = SystemConstant.NUM_ZERO;//1.验证订单金额//用户支付金额int payerTotal = node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_PAYER_TOTAL).asInt();userPayTotal = userPayTotal + payerTotal;//CASH充值型代金券 要加上优惠金额 银行优惠 获取//排空 如果没有优惠则跳过if (!ObjectUtil.isEmpty(node.get(WXOrderConstant.PROMOTION_DETAIL))) {for (JsonNode objNode : node.get(WXOrderConstant.PROMOTION_DETAIL)) {//如果优惠类型为CASH 则要和 用户支付金额 累加if (WXOrderConstant.WX_DISCOUNT_TYPE.equals(objNode.get(WXOrderConstant.PROMOTION_DETAIL_TYPE).textValue())) {userPayTotal = userPayTotal + objNode.get(WXOrderConstant.AMOUNT).asInt();}}}//2.总金额 预支付时的 金额 与 total 用户支付金额//微信端返回的支付总金额int wxTotal = node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_TOTAL).asInt();//redis缓存中的金额//校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。//缓存中存入的用户支付金额 totalRedisRO.getTicketOrder().getTotalMoney().movePointRight(SystemConstant.NUM_TWO).intValue()log.info("微信回调金额===比较=== "+"微信端返回的支付总金额"+node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_TOTAL).asInt()+"==========redis缓存中的金额"+redisTotal+"================用户支付总金额计算"+userPayTotal);//只要缓存的金额小于用户实际付款金额 判定成功return wxTotal == userPayTotal && redisTotal == wxTotal;}

3.4.2 定时任务处理

/*** 清除过去票 恢复库存** @param order 子订单信息* @return void* @author zhangjunrong* @date 2022/5/16 19:44*/private void dealVoidTicket(WxPayListRO order) {
//微信订单redis2 订单详情OrderTotalRedisRO orderTotalRedisRO = (OrderTotalRedisRO) redisUtil.get(SystemConstant.ORDER_TOTAL + order.getOutTradeNo());orderTotalRedisRO.getTicketOrderItems().stream().filter(Objects::nonNull).forEach(ticketOrderItem -> {//恢复票相应的库存Boolean timeOrder = iTicketOrderService.updateTimeOrder(ticketOrderItem.getTicketId(), ticketOrderItem.getUseStart(), ticketOrderItem.getBranchStart(), ticketOrderItem.getBuyCount());log.info("订单恢复库存{}======订单信息{}===============", timeOrder, ticketOrderItem);});//清除缓存 redis1long lRemove = redisUtil.lRemove(WxRedisKey.WX_PAY_ORDER, SystemConstant.NUM_ONE, order);log.info("清除redis1缓存" + lRemove);//清除缓存 redis2redisUtil.del(SystemConstant.ORDER_TOTAL + order.getOutTradeNo());}/*** 对于下单定时任务核对 每间隔50秒查询5分钟前的订单* 1.防止微信付款成功 订单数据未入库 2.实现定期关单功能** @return void* @author zhangjunrong* @date 2022/5/13 9:59*/@Async@Scheduled(cron = "0/50 * * * * ? ")public void orderTimeCheck() {//redis1 key=>wxPay 设置7分钟有效 一直有效(4分钟更新一次)(redis2key+订单类型+下单时间+支付状态)list<对象>数组redis2 10分钟有效期订单详细信息//redis2 订单详细信息 8分钟有效时间//1.获取出redis1 微信支付订单listList<Object> orderList = redisUtil.lGet(WxRedisKey.WX_PAY_ORDER, SystemConstant.NUM_ZERO, SystemConstant.NUM_NEGATIVE_ONE);if (ObjectUtil.isNotEmpty(orderList)) {log.info("定时任务核销单====处理特殊订单开启====================");List<WxPayListRO> wxPayListROS = redisUtil.castList(orderList, WxPayListRO.class);wxPayListROS.stream()//2.获取 前5分钟的订单信息.filter(order -> DateUtil.between(order.getCreateOrderTime(), DateUtil.date(), DateUnit.MINUTE) >= SystemConstant.NUM_FIVE)//3.过滤掉已处理的订单 redis2中没有的订单 支付成功会删除redis2记录.filter(order ->{//如果redis2中没有该记录 则删除掉redis1对于该记录if (!redisUtil.hasKey(SystemConstant.ORDER_TOTAL + order.getOutTradeNo())) {log.info("定时任务判定是redis否拥有订单====" + order.getOutTradeNo());long lRemove = redisUtil.lRemove(WxRedisKey.WX_PAY_ORDER, SystemConstant.NUM_ONE, order);log.info("清除redis1记录" + lRemove);return false;}return true;}).forEach(order -> {//4.调微信接口判定log.info("定时任务核销单====微信定时任务开始核对订单未支付成功订单====" + order);ToolWxConfig wxConfig = iToolWxConfigService.find();//4.1查询微信那的订单状态JsonNode queryCreateOrder = iToolWxConfigService.queryCreateOrder(wxConfig, order.getOutTradeNo());//4.2如果查询结果为null 说明用户没有调启微信支付 直接清除订单redisif (ObjectUtil.isEmpty(queryCreateOrder.get(WXOrderConstant.TRADE_STATE))) {log.info("定时任务核销单====微信订单信息不存在==============");//恢复票务库存 清除库存dealVoidTicket(order);} else {//交易状态String tradeState = queryCreateOrder.get(WXOrderConstant.TRADE_STATE).textValue();String transactionId = queryCreateOrder.get(WXOrderConstant.TRANSACTION_ID).textValue();log.info("定时任务核销单====微信订单状态: 微信接口 对象" + queryCreateOrder + "redis缓存" + order.getOrderStatus());// 4.3核对支付 状态 如果未支付 关单 redis1和redis2清除缓存if (WxPayStatusEnum.NOTPAY.getValue().equals(tradeState)) {log.info("定时任务核销单====微信订单信息未支付==========");//关闭订单String closeOrder = iToolWxConfigService.closeOrder(wxConfig, order.getOutTradeNo());log.info("定时任务核销单====返回结果" + closeOrder);//恢复票务库存 清除库存dealVoidTicket(order);}// 4.4核对支付 状态 如果已支付 redis1未支付 数据库查单再次判定 如果不存在 则入数据库if (WxPayStatusEnum.SUCCESS.getValue().equals(tradeState)) {//数据库查单判定if (ObjectUtil.isEmpty(iTicketOrderService.queryOrderByTranId(transactionId))) {log.info("定时任务核销单====微信订单信息支付==========数据库未有数据");//获取redis2OrderTotalRedisRO orderTotalRedisRO = (OrderTotalRedisRO) redisUtil.get(SystemConstant.ORDER_TOTAL + order.getOutTradeNo());log.info("微信redis2获取信息===" + orderTotalRedisRO.toString());//订单金额验证 等等 插入数据库//redis缓存中的金额int redisTotal = orderTotalRedisRO.getTicketOrder().getPayMoney().movePointRight(SystemConstant.NUM_TWO).intValue();//只有金额对等 方可入数据库if (WxPayUtil.verifyMoney(queryCreateOrder, redisTotal)) {iTicketOrderService.createAllTicket(orderTotalRedisRO, transactionId);}//清除缓存 redis1long lRemove = redisUtil.lRemove(WxRedisKey.WX_PAY_ORDER, SystemConstant.NUM_ONE, order);log.info("清除redis1缓存" + lRemove);//清除缓存 redis2redisUtil.del(SystemConstant.ORDER_TOTAL + order.getOutTradeNo());}}}});}}

微信支付 APP端 后端 第二弹 微信回调相关推荐

  1. 微信支付 APP端 后端 第一弹 微信下单

    目录 工程总介绍: 第一弹: 微信 支付下单 展示结果截图 1.配置说明 1.1数据库设计 需要拿到微信官方给的一些参数 1.2用到的jar包 1.3信支付接口请求状态枚举 1.3.1接口请求 1.3 ...

  2. 微信支付 APP端 后端 第四-五弹 退款定时任务 账单下载

    目录 第四弹 退款定时任务 成果展示: 1.设计思路 2.代码实现 2.1数据库查询订单 2.2定时任务 检查退款订单 2.3调用微信支付 get请求 统一配置(如果是看了前几篇的友友 前面有一样的 ...

  3. 【微信支付】(亲测可用)对接app微信支付V2版本 后端代码示例

    业务场景:基本上做业务的话,也是逃不开对接各种支付接口的,比如数字人民币支付.农行免密支付.支付宝支付.微信支付等等.在着手开发时候,也是遇到不少阻力,微信官方提供的接口文档很散乱,如果之前没接触过, ...

  4. JAVA对接微信支付和支付宝支付(APP端支付)

    本文主要介绍的是JAVA对接支付宝和微信支付,废话少说上代码(部分业务代码就不上了,例如订单等,根据业务需求自行修改): 用到的工具类: maven依赖: <!-- https://mvnrep ...

  5. php苹果app微信支付 无法返回,微信支付,php_微信支付APP返回-1怎么解决,微信支付,php,移动app - phpStudy...

    微信支付APP返回-1怎么解决 开发文档上面-1"可能的原因:签名错误.未注册APPID.项目设置APPID不正确.注册的APPID与设置的不匹配.其他异常等.",但是我检查过没问 ...

  6. 微信支付 APP支付 Java 服务器端

    微信支付 APP支付 Java 服务器端 本文介绍微信支付中APP支付的java服务端. 微信APP支付文档:https://pay.weixin.qq.com/wiki/doc/api/app/ap ...

  7. 手把手安排 --- JavaH5微信支付(移动端浏览器H5拉起微信支付)

    Java项目接入H5微信支付 开发环境 前期准备 申请微信公众平台及微信支付 准备内网穿透域名 微信支付开发配置 开始撸代码 成功案例 总结 公司项目需要接入微信支付,因为主要是在移动端的网页进行支付 ...

  8. 微信支付-App支付服务端详解

    微信App支付服务端详解 引言 主要实现app支付统一下单.异步通知.调起支付接口.支付订单查询.申请退款.查询退款功能:封装了https对发起退款的证书校验.签名.xml解析等. 支付流程 具体支付 ...

  9. 微信支付APP支付完全攻略

    微信支付接入应用 最近项目中要接入微信支付,所以就去研究了下,发现坑还真不少啊.也就有了这篇博客. 接入前准备 在开始接入微信支付前你的去微信的开发平台上面注册你自己的应用.具体的链接是微信开发平台 ...

最新文章

  1. 使用VS 自带的打包工具,制作winform安装项目
  2. SIMD学习笔记整理(索引贴)
  3. NLPCC:预训练在小米的推理优化落地
  4. 百度语音识别技术负责人李先刚:如何利用Deep CNN大幅提升识别准确率?
  5. shell脚本基本命令1
  6. C++大学教程(第九版)2016-07 保罗·戴特尔 (Paul Deitel)、 哈维·戴特尔 (Harvey Deitel)_cafbe(C++中文版)
  7. 发布一个C#实现的Asterisk的管理系统
  8. 贝叶斯软件genle教程_一文读懂蒙特卡罗方法和应用贝叶斯推理
  9. Linux / Windows应用方案不完全对照表
  10. L1-017. 到底有多二-PAT团体程序设计天梯赛GPLT
  11. 通过jQuery的attr修改onclick
  12. 分段式多级离心泵_溧阳耐磨矿用多级泵水泵厂
  13. 遍历文件夹批量重命名
  14. PDF添加图片(图片透明)
  15. centos7部署rap2
  16. oracle 建索引 00054,ora-00054 表被lock导致资源忙等待不能操作案例
  17. Excel日常遇到的问题整理(持续更新)
  18. 致Emacs初学者+Emacs初学者必知必会
  19. python调用jsonrpc接口_微信小程序通过jsonrpc调用python服务端接口
  20. Elmedia Player GO for Mac中文破解版永久激活教程

热门文章

  1. 思科路由器-配置RIP协议
  2. sap crm button_详解SAP软件S4安装教程之S4 1909安装
  3. 下列python语句的输出结果是_下列Python语句的输出结果是_______________。
  4. Java数据类型系列之BigDecimal
  5. 计算机图形学————绘制动态的行星系
  6. Fundamentals of Power Electronics 中文版译文
  7. Salesforce宣布与阿里巴巴达成战略合作 向全国开放CRM平台
  8. Echarts 做的温度计
  9. 【论文简述】Vis-MVSNet: Visibility-Aware Multi-view Stereo Network(IJCV 2022)
  10. Python实战案例,PIL模块,Python实现自动化生成倒计时图片