开始之前先让博主吐槽下微信的接口文档与接口规则。一个代金券的模块搞了3个星期。严重怀疑微信的产品经理跟项目经理有病。写文档的程序员也是。吐槽结束。

一、准备

  1. 微信公众号的AppId和密钥Secret
  2. v3接口的证书号和证书(.pem文件)
  3. v3Api密钥(用于解析核销通知)
  4. 耐心和刀!!(可以随时捅死微信的程序员)

ps:如果是商户自己调用api的话(这一步不做的话会报

body={"code":"INVALID_REQUEST","message":"可用商户不符合规则,请检查"})

需要去商家支付平台开启产品--》https://pay.weixin.qq.com/  在产品中心下--》我的产品--》开通免资金代金券

如果是服务商调用需要进入邀请商户授权,当服务商点击发起授权后,需要商户进入商户平台确认邀请(商户的支付平台在上面消息中心确定授权,不授权的话服务商无法帮商户创建代金券)当商户授权完,商户账号下也需要开启免资金代金券的功能。

二、第三方框架导入

在这里感谢   Javen大佬的 IJPay-WxPay框架

Github地址: https://github.com/Javen205/IJPay

Gitee:http://gitee.com/Javen205/IJPay

<dependency><groupId>com.github.javen205</groupId><artifactId>IJPay-WxPay</artifactId><version>2.6.3</version>
</dependency>

本人使用的时候该版本的v3接口还不算太完善,所以我只是使用了这个框架的调用微信v3的请求方法

新的应该已经支持直接调用代金券接口创建了吧。

其他使用到的关键

<!--  阿里json -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version>
</dependency>
lombok
<!-- lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
// 这两个框架可以不加(本人用于测试接口用的,相关配置可以参考对应的文档)
<!-- swagger2 -->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version>
</dependency>
<!-- swagger-ui -->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version>
</dependency>

三、上代码

微信的配置文件

import lombok.Data;/*** @Description: 微信配置* @Author: Joshua* @CreateDate: 2020/7/16 12:39* @Version 1.0*/
@Data
public class WxConfig {public static WxConfig wxConfig;/*** 服务商appid*/// 服务号public final static String APPID = "你的AppId";/*** secret*/public final static String SECRET = "你的密钥";/*** v3私钥*/public final static String PRIVATE_KEY = "你的私钥";/*** v3* 证书号(会过期) 40个字符*/public final static String SERIAL_NO = "证书号";/*** 证书路径(我直接放在项目路径下)*/public final static String KEY_PATH = "../../apiclient_key.pem";/*** v3* API密钥(自己设置的32字符)*/public final static String API_V3_KEY = "v3API密钥";/*** 服务商商户号(如果你是服务商,如果是商户着就是商户号)*/public final static String MCH_ID = "服务商商户号";/*** 微信代金券通知地址(必须是https的)*/public final static String COUPON_NOTIFY = "https://...../redirect-anon/wxCouponNotify";}

请求实体(里面有些字段是我自己需要使用的,其他开发者看着需求更改)

import java.io.Serializable;
import java.util.Date;import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import javax.persistence.*;/*** 微信优惠券** @author Joshua* @since 2020-08-01*/
@Data
@Entity
@Table(name = "wx_coupon")
@ApiModel(value = "WxCoupon", description = " 微信优惠券")
public class WxCoupon implements Serializable {private static final long serialVersionUID = 1L;/*** 主鍵Id*/@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@ApiModelProperty(name = "id", value = "id", example = "1")private Integer id;/*** 商户id*/@ApiModelProperty(name = "merchantId", value = "商户id")private Integer merchantId;/*** 子商户号*/@ApiModelProperty(name = "belongMerchant", value = "子商户号")private String belongMerchant;/*** 卡券标题*/@ApiModelProperty(name = "stockName", value = "卡券标题")private String stockName;/*** 开始时间*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@ApiModelProperty(name = "beginTimestamp", value = "开始时间")private Date beginTimestamp;/*** 结束时间*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@ApiModelProperty(name = "endTimestamp", value = "结束时间")private Date endTimestamp;/*** 发行量*/@ApiModelProperty(name = "maxCoupons", value = "发行量")private Integer maxCoupons;/*** 面额(单位:分)*/@Transient@ApiModelProperty(name = "couponAmount", value = "面额(单位:分)")private Integer couponAmount;/*** 门槛(单位:分)*/@Transient@ApiModelProperty(name = "transactionMinimum", value = "门槛(单位:分)")private Integer transactionMinimum;/*** 核销规则*/private String rule;/*** 单个用户可领个数,每个用户最多60张券*/@Transient@ApiModelProperty(name = "maxCouponsPerUser", value = "单个用户可领个数, 0< maxCouponsPerUser <=60")private Integer maxCouponsPerUser;/*** 是否开启自然人限制(默认:false)* 如果开启,则1个自然人有多个微信号,会视为同一个人。* 开启后当一个自然人用户某个微信好享受优惠,使用其他微信号时将无法享受优惠* PS:可能会造成用户投诉*/@Transient@ApiModelProperty(name = "naturalPersonLimit", value = "是否开启自然人限制(默认:false)")private Boolean naturalPersonLimit;/*** api发券防刷(默认:false)*/@Transient@ApiModelProperty(name = "preventApiAbuse", value = "api发券防刷(默认:false)")private Boolean preventApiAbuse;/*** 商家logo*/@Transient@ApiModelProperty(name = "logo", value = "商家logo")private String logo;/*** 可用时间段(0为周日,1为周一以此类推)格式[0,1,2,3,4,5,6]*/@Transient@ApiModelProperty(name = "availableWeekDay", value = "可用时间段")private String availableWeekDay;/*** 卡券类型(0满减券,1折扣券)*/@ApiModelProperty(name = "cardType", value = "卡券类型(0满减券,1折扣券)")private Integer cardType;/*** 最高折扣金额(单位分)*/@Transient@ApiModelProperty(name = "discountAmountMax", value = "最高折扣金额")private Integer discountAmountMax;/*** 折扣百分比*/@Transient@ApiModelProperty(name = "discountPercent", value = "折扣百分比(70=7折)")private Integer discountPercent;/*** 創建時間*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@ApiModelProperty(name = "createTime", value = "創建時間")private Date createTime;/*** 卡券id*/@ApiModelProperty(name = "stockId", value = "卡券id")private String stockId;/*** 卡券状态*/@ApiModelProperty(name = "status", value = "卡券状态(0:已失效,未失效)")private Integer status;/*** 商户名称*/@Transient@ApiModelProperty(name = "merchantName", value = "商户名称")private String merchantName;
}

Controller层(关于ResponseObj这个实体,只是一个普通的三段式相应参数)

import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.Date;
import java.util.Map;/*** @Description: 微信卡券* @Author: Joshua* @CreateDate: 2020/7/31 11:55* @Version 1.0*/
@Slf4j
@RestController
@RequestMapping("/wxCouponController")
@Api(value = "微信卡券", tags = {"微信卡券"})
public class WxCouponController {// 因为使用分布式(所以有些数据需要远程调用拿,如果是本地开发不需要这个)@AutowiredMerchant merchant;// 这两个是存表的实现类,里面只有insert方法(看自己需求更改)@AutowiredWxCouponService wxCouponService;@AutowiredWxCouponUserService wxCouponUserService;/*** 设置回调地址** @return 200*/@ApiOperation("设置回调地址")@GetMapping("/sendCallbacks")public ResponseObj sendCallbacks() {try {Map<String, Object> sendCallbacks = WxUtils.sendCallbacks(WxConfig.MCH_ID);System.out.println(sendCallbacks.toString());JSONObject body = JSONObject.parseObject(sendCallbacks.get("body").toString());if (200 == (Integer) sendCallbacks.get("status")) {System.out.println(body);} else {// 请求异常是打印错误到前台return ResponseObj.createResponse(666, body.get("message").toString());}} catch (Exception e) {e.printStackTrace();}return ResponseObj.createSuccessResponse();}/*** 创建优惠券** @param coupon 创建实体* @return 200*/@ApiOperation("创建优惠券")@PostMapping("/createCoupon")public ResponseObj createCoupon(@RequestBody WxCoupon coupon) {// 因为我是远端调用的方法(一般开放者可以忽略这步)ResponseData wxMchIdByMchId = merchant.getMchNameAndWxMchIdByMchId(Long.valueOf(coupon.getMerchantId()));Map<String, String> data = (Map<String, String>) wxMchIdByMchId.getData();// 服务商调用时需要用到子商户id,如果普通商户调用不需要。coupon.setBelongMerchant(data.get("wxMchId"));// 获取商家名称(可有可无)coupon.setMerchantName(data.get("merchantName"));// 构建请求JsonString createCoupon = ProcessCardData.createCoupon(coupon);System.out.println(createCoupon);try {Map<String, Object> v3Coupon = WxUtils.createV3Coupon(createCoupon);JSONObject body = JSONObject.parseObject(v3Coupon.get("body").toString());System.out.println("创建优惠券:" + body);if (200 == (Integer) v3Coupon.get("status")) {String stockId = String.valueOf(body.get("stock_id"));// 激活代金券Map<String, Object> activationCoupon = WxUtils.activationCoupon(stockId);if (200 == (Integer) activationCoupon.get("status")) {System.out.println("激活代金券:" + activationCoupon.get("body"));coupon.setStatus(1);} else {System.out.println("激活代金券:" + activationCoupon.get("body"));coupon.setStatus(0);}coupon.setCreateTime(new Date());coupon.setStockId(stockId);coupon.setRule(ProcessData.processRule(coupon.getTransactionMinimum(), coupon.getCouponAmount()));wxCouponService.insert(coupon);} else {return ResponseObj.createResponse(666, body.get("message").toString());}} catch (Exception e) {e.printStackTrace();log.error(e.getMessage());}return ResponseObj.createSuccessResponse();}/*** 激活代金券* 防止创建时调用激活接口失败,可重新调用激活* @param id      主键id* @param stockId 卡券id* @return 200*/@ApiOperation("激活代金券")@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "主键id", paramType = "query", dataType = "Integer"),@ApiImplicitParam(name = "stockId", value = "卡券id", paramType = "query", dataType = "Integer")})@GetMapping("/activationCoupon")public ResponseObj activationCoupon(@RequestParam Integer id, @RequestParam String stockId) {try {Map<String, Object> activationCoupon = WxUtils.activationCoupon(stockId);if (200 == (Integer) activationCoupon.get("status")) {System.out.println("激活代金券:" + JSONObject.parseObject(activationCoupon.get("body").toString()));WxCoupon coupon = new WxCoupon();coupon.setId(id);coupon.setStatus(1);wxCouponService.update(coupon);} else {return ResponseObj.createErrResponse(JSONObject.parseObject(activationCoupon.get("body").toString()).get("message").toString());}} catch (Exception e) {e.printStackTrace();}return ResponseObj.createSuccessResponse();}/*** 投放代金券** @param couponUser 实体* @return 200*/@ApiOperation("投放代金券")@PostMapping("/sendCoupon")public ResponseObj sendCoupon(@RequestBody WxCouponUser couponUser) {try {Map<String, Object> sendCoupon = WxUtils.sendCoupon(couponUser.getBelongMerchant(), couponUser.getStockId(), couponUser.getOpenid());JSONObject body = JSONObject.parseObject(sendCoupon.get("body").toString());System.out.println("投放代金券:" + body);if (200 == (Integer) sendCoupon.get("status")) {couponUser.setCouponId(String.valueOf(body.get("coupon_id")));couponUser.setCreateTime(new Date());wxCouponUserService.insert(couponUser);} else {return ResponseObj.createResponse(666, body.get("message").toString());}} catch (Exception e) {e.printStackTrace();}return ResponseObj.createSuccessResponse();}}

构建创建卡券的请求json字符串(body)

    /*** 创建代金券** @param coupon 创建实体* @return createCoupon*/public static String createCoupon(WxCoupon coupon) {String createCoupon;// 卡券类型String couponType;if (0 == coupon.getCardType()) {// 面额和门槛(单位都是分)couponType = "\"fixed_normal_coupon\":{\"coupon_amount\":" + coupon.getCouponAmount() + ",\"transaction_minimum\":" + coupon.getTransactionMinimum() + "},";} else if (1 == coupon.getCardType()) {// 折扣券(单位都是分)couponType = "\"disscount_coupon\":{\"discount_amount_max\":" + coupon.getDiscountAmountMax() + ",\"discount_percent\":" + coupon.getDiscountPercent() + ",\"transaction_minimum\":" + coupon.getTransactionMinimum() + "},";} else {couponType = "";}String merchantLogo = "";if (null != coupon.getLogo()) {merchantLogo = "\"merchant_logo\":\"" + coupon.getLogo() + "\",";}// 这个值可以随意创建,只要保证唯一即可(不用在意我的创建方法)// 商户创建批次凭据号(格式:商户id+日期+流水号),可包含英文字母,数字,|,_,*,-等内容,不允许出现其他不合法符号,商户侧需保持唯一性 (9856886520200811174644kk6tclE)String outRequestNo = coupon.getBelongMerchant() + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + CommonUtil.getRandomString2(7);createCoupon = "{"+ "\"stock_name\":\"" + coupon.getStockName() + "\","// 商户号(1600907583)
//                + "\"belong_merchant\":\"" + coupon.getBelongMerchant() + "\","+ "\"belong_merchant\":\"" + WxConfig.MCH_ID + "\","// 开始与结束时间(2015-05-20T13:29:35.120+08:00)+ "\"available_begin_time\":\"" + DateUtil.getRfc3339(coupon.getBeginTimestamp()) + "\",\"available_end_time\":\"" + DateUtil.getRfc3339(coupon.getEndTimestamp()) + "\","+ "\"stock_use_rule\":{"// 发行量+ "\"max_coupons\":" + coupon.getMaxCoupons() + ","// 总预算[单位:分  coupon_amount(面额) * max_coupons(发放总上限)]+ "\"max_amount\":" + (coupon.getCouponAmount() * coupon.getMaxCoupons()) + ","// 限制当天的发放上限金额(单位:分)+ "\"max_amount_by_day\":" + (coupon.getCouponAmount() * coupon.getMaxCoupons()) + ","// 单个用户可领取的上限+ "\"max_coupons_per_user\":" + coupon.getMaxCouponsPerUser() + ","// 是否开启自然人限制+ "\"natural_person_limit\":" + coupon.getNaturalPersonLimit() + ","// 是否开启Api防刷+ "\"prevent_api_abuse\":" + coupon.getPreventApiAbuse() + "},"// stock_use_rule 结束+ "\"pattern_info\":{"// 使用说明+ "\"description\":\"代金券\","// 商家图标(可空)+ merchantLogo// 卡券商家名称+ "\"merchant_name\":\"" + coupon.getMerchantName() + "\""
//                + ",\"background_color\":\"Color010\""+ "},"// pattern_info 结束+ "\"coupon_use_rule\":{"// TODO 如果开启下面的在激活的时候会报“卡包信息尚未注册完成,请稍后重试” ,具体问题未知。// 券生效时间
//                + "\"coupon_available_time\":{"
//                // 固定时间段
//                + "\"fix_available_time\":{"
//                // 可用时间段(0为周日,1为周一)
//                + "\"available_week_day\":" + coupon.getAvailableWeekDay() + ","
//                // 当天开始与结束时间
//                + "\"begin_time\":0,\"end_time\":3600},"
//                // fix_available_time 结束
//                // 领取第二天生效
//                + "\"second_day_available\":false"
//                // 领取后有效时间+ ",\"available_time_after_receive\":1440"
//                + "},"// coupon_available_time 结束// 卡券类型+ couponType// 支付方式 (微信的官方文档是错误的,这里应传数组)+ "\"trade_type\":[\"MICROAPP\",\"APPPAY\",\"PPAY\",\"CARD\",\"FACE\",\"OTHER\"],"// 是否可叠加其他优惠+ "\"combine_use\":false,"// 可核销商户号(多个商户共同核销时可传入多个商户号["子商户号A","子商户号B"])+ " \"available_merchants\":[\"" + coupon.getBelongMerchant() + "\"]"+ "},"// coupon_use_rule 结束// 是否无资金流+ "\"no_cash\":true,"// 卡券类型+ "\"stock_type\":\"NORMAL\","// 自定义单据号+ "\"out_request_no\":\"" + outRequestNo + "\""+ "}";return createCoupon;}

该createCoupon方法会使用到工具方法(其他的方法基本都是jdk自带的,不会涉及导包的)

    /*** 转换rfc3339格式时间** @param date 时间* @return rfc3339Date*/public static String getRfc3339(Date date) {DateTime rfc3339Date = new DateTime(date, DateTimeZone.forTimeZone(TimeZone.getTimeZone("Asia/Shanghai")));return rfc3339Date.toString();}/*** 生成随机字符串** @param length* @return*/public static String getRandomString2(int length) {Random random = new Random();StringBuilder sb = new StringBuilder();for (int i = 0; i < length; ++i) {int number = random.nextInt(3);long ResponseObj = 0;switch (number) {case 0:ResponseObj = Math.round(Math.random() * 25 + 65);sb.append((char) ResponseObj);break;case 1:ResponseObj = Math.round(Math.random() * 25 + 97);sb.append((char) ResponseObj);break;case 2:sb.append(new Random().nextInt(10));break;default:}}return sb.toString();}

请求微信的方法

import com.ijpay.wxpay.WxPayApi;
import lombok.extern.slf4j.Slf4j;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;import static com.ijpay.core.enums.RequestMethod.*;
import static com.ijpay.wxpay.enums.WxApiType.*;
import static com.ijpay.wxpay.enums.WxDomain.*;/*** @Description: 微信相关工具类* @Author: Joshua* @CreateDate: 2020/8/10 18:58* @Version 1.0*/
@Slf4j
public class WxUtils {/*** 创建代金券** @param requestJson 请求参数* @return map*/public static Map<String, Object> createV3Coupon(String requestJson) throws Exception {return WxPayApi.v3Execution(POST, CHINA.toString(), CREATE_COUPON_STOCKS.toString(), WxConfig.MCH_ID, WxConfig.SERIAL_NO, WxConfig.KEY_PATH, requestJson);}/*** 激活代金券** @param stockId 卡券批号* @return map* @throws Exception 异常*/public static Map<String, Object> activationCoupon(String stockId) throws Exception {String requestJson = "{\"stock_creator_mchid\":\"" + WxConfig.MCH_ID + "\"}";String urlSuffix = "/v3/marketing/favor/stocks/" + stockId + "/start";return WxPayApi.v3Execution(POST, CHINA.toString(), urlSuffix, WxConfig.MCH_ID, WxConfig.SERIAL_NO, WxConfig.KEY_PATH, requestJson);}/*** 放代金券** @param belongMerchant 商户号* @param stockId        卡券批号* @param openid         用户id* @return map* @throws Exception 异常*/public static Map<String, Object> sendCoupon(String belongMerchant, String stockId, String openid) throws Exception {String outRequestNo = belongMerchant + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + CommonUtil.getRandomString2(7);String requestJson = "{"+ "\"stock_id\": \"" + stockId + "\","+ "\"out_request_no\": \"" + outRequestNo + "\","+ "\"appid\": \"" + WxConfig.APPID + "\","+ "\"stock_creator_mchid\": \"" + WxConfig.MCH_ID + "\""+ "}";String urlSuffix = "/v3/marketing/favor/users/" + openid + "/coupons";return WxPayApi.v3Execution(POST, CHINA.toString(), urlSuffix, WxConfig.MCH_ID, WxConfig.SERIAL_NO, WxConfig.KEY_PATH, requestJson);}/*** 设置代金券回调地址** @param wxMchId 商户号* @return 200* @throws Exception 异常*/public static Map<String, Object> sendCallbacks(String wxMchId) throws Exception {String requestJson = "{"+ "\"mchid\": \"" + wxMchId + "\","+ "\"notify_url\": \"" + WxConfig.COUPON_NOTIFY + "\","+ "\"switch\":true"+ "}";return WxPayApi.v3Execution(POST, CHINA.toString(), SETTING_COUPON_CALLBACKS.toString(), WxConfig.MCH_ID, WxConfig.SERIAL_NO, WxConfig.KEY_PATH, requestJson);}
}

这样就可以创建代金券,激活代金券,发放代金券了

因为本人使用swagger做请求测试,下面是请求实例

创建代金券
{"merchantId": 22,//这个可以忽略"stockName": "测试券", //卡券名称"beginTimestamp": "2020-08-17 17:52:48", //开始时间"endTimestamp": "2020-08-18 23:59:59", //结束时间"maxCoupons": 10, //发放数量"maxCouponsPerUser": 1, //每个用户可以领取几次"naturalPersonLimit": false, //自然人限制(我一般不开,因为会影响用户的使用)"preventApiAbuse": false, //api防刷(同上)"cardType": 0, //卡券类型(可以忽略)"couponAmount": 100,(面额,单位:分 )"transactionMinimum": 101(门槛,单位:分 )
}
//这里有两个地方要注意:发放数量必须大于5,门槛必须比面额高,面额和门槛都需大于1元投放代金券
{"merchantId": 22, //这个可以忽略"belongMerchant": "子商户号", //如果是服务商调用需要子商户号,普通商户调用填写自己的商户号"openid": "app下对应的用户openId","stockId": "模板id"
}

关于卡券核销通知:

开启通知功能(如果是服务商自己使用,只需要服务商开启通知即可,如果服务商要为商户的公众号创建,这商户也需要开启此功能)(普通商户也需要开启此功能才能接收到卡券消息)
https://pay.weixin.qq.com/index.php/xphp/cmkt_product/index#/pages/index/index

开发流程就此结束,再次吐槽微信的接口与文档真垃圾

微信免资金代金券(V3版)java代码相关推荐

  1. 微信免充值代金券与免充值立减券与单品券活动验收流程

    功能介绍 为支持商户免充值营销经费开展运营活动,提升运营效率,微信支付特开发免充值营销产品功能.商户开通该产品功能后,可免费使用微信支付提供的免充值代金券.立减.折扣等营销工具.商户配置使用免充值代金 ...

  2. 微信服务商开通免充值代金券接口升级验收

    微信服务号开通免充值代金券接口升级验收 一.获取沙箱验签秘钥API 准备参数: 1.服务商商户号:mch_id 2.32位随机字符串:nonce_str 3.微信支付商户32位秘钥:key(获取签名s ...

  3. 微信支付--代金券免充值代金券:接口升级

    微信支付–代金券免充值代金券 开通免充值代金券需 进行接口升级: https://pay.weixin.qq.com/wiki/doc/api/download/mczyscsyl.pdf 接口升级组 ...

  4. 微信支付免充值代金券接口升级免费开通步骤

    无论是微信支付服务商还是普通商户,在创建代金券或立减折扣时,都希望能够实现免充值,在交易发生时直接抵扣,毕竟充值过程太啰嗦. 但是在微信支付商户平台上开通免充值相关产品(包括微信支付免充值代金券和微信 ...

  5. php微信支付商户免充值代金券接口升级

    //todo 如果没安装该插件可删除该行,并使用参数requestType改为'1' use GuzzleHttp\Client;/*** Class Demo* @package ShopEM\Se ...

  6. 视频教程-微信生活缴费商业项目标准版-Java

    微信生活缴费商业项目标准版 19年软件开发经验,设计开发40多个大型软件,10年从事高等教育,主要为java系列课程,带你轻松进入java生涯. 赖国荣 ¥399.00 立即订阅 扫码下载「CSDN程 ...

  7. 关于微信卡券与代金券的一些事

    最近公司有个项目需要在H5上面发放代金券,研究了好几天微信公众平台和商户平台的文档,梳理下微信卡券和代金券之间的联系.以下微信公众平台简称mp平台,商户平台简称pay平台. mp平台开发文档 pay平 ...

  8. 剑指Offer第二版Java代码实现

    剑指Offer第二版Java代码实现 A.单例模式 面试题 2:实现Singleton模式 B.面试需要的基础知识 面试题 3:数组中重复的数字 面试题 4:二维数组的查找 面试题 5:替换空格 面试 ...

  9. 微信支付V3版 java

    微信支付V3版 1.引入依赖 2.创建时间工具类 DateTimeZoneUtil.class 3.解密工具类 AesUtil.class 4.对外暴露方法 公共参数 4-1.支付下单 V3PayGe ...

最新文章

  1. 如何在一个程序集中序列化在另一个中反序列化
  2. 远望资本田鸿飞:中国产业互联网的关键是AI赋能
  3. 【Linux网络编程】IP地址分类和介绍
  4. 面试指南|GO高性能编程精华PDF
  5. ftp获取远程Pdf文件
  6. 新浪微博推出具有中国特色的“关注但屏蔽”功能
  7. 递归算法(python),汉诺塔问题,斐波那契数列,一个简单的递归实例,用递归实现阶乘,用递归查看目录及文件
  8. PS零基础自学笔记:常见操作方法记录(去水印、抠图、调色调)
  9. 微信支付对账单的详细说明
  10. 如何xp计算机每天定时关机,xp定时关机,教您xp系统怎么设置定时关机
  11. 管理者如何抓绩效管理?
  12. 交换游戏(记忆化搜索,状态压缩,位运算)
  13. 【java毕业设计】基于javaEE+SSM+MySql的个人博客系统设计与实现(毕业论文+程序源码)——个人博客系统
  14. 高德地图看各省分界线_从高德采集最新的省市区三级坐标和行政区域边界,用js在浏览器中运行...
  15. 论天龙八部和程序员的关系
  16. php查询google pr值接口api介绍,最新 google pr值查询 接口 php版 示例
  17. 绝对零度!冷原子量子计算机技术的6大优势
  18. DJ音乐培训展示类网站织梦模板
  19. 如何学习新概念英语第四册
  20. EggDrop Problem(扔鸡蛋问题)

热门文章

  1. 数据库实验二之数据查询
  2. Oracle19c中SQL分开跑很快UNION ALL之后变慢分析
  3. Word文档目录自动生成和页码设置
  4. 基于android的母婴商城app系统
  5. XenDesktop测试小结
  6. 2021计通网项目一问题记录
  7. border属性 php,使用CSS的border属性构建变形边框的方法总结
  8. 带上传进度的文件上传
  9. 毕业后的项目经历1-项目名称 HIS微服务 类型 医院系统
  10. xampp下载太慢了,这里有下载好的(mac)