一 前言
读本文前请确保商户号已开通免充值立减与折扣。否则请看 微信支付-免充值立减与折扣(上篇)。
本文主要讲述如何创建优惠券,统一下单和支付通知怎样支持使用优惠券。
二 准备
2.1 必要前提
你要有微信公众号支付/小程序支付/H5支付的开发经验(本文以公众号支付为例),否则先看我的上一篇文章 移动支付--微信公众号支付开发;
2.2 必读文档
三 过程
3.1 创建优惠券
3.1.1 哪里创建
步骤:微信商户平台 - 营销中心 - 代金券/立减与折扣
3.1.2 创建一张 立减与折扣 - 全场立减优惠券
1、 设置优惠券规则。
2、设置优惠券规则。
3、高级设置截图 。
4、确认创建。
5、 创建成功,需要激活后才能使用。
3.1.3 创建一张 立减与折扣 - 创建单品立减优惠券
1、设置优惠券规则
2、设置单品优惠规则。
3、设置优惠券规则。
4、创建优惠券。
5、 创建成功,需要激活后才能使用。
3.2 统一下单接口修改
根据文档 统一下单API(支持单品优惠) ,统一下单接口做了以下修改,附修改代码:
//元转分
Double moneyd = Double.parseDouble(money) * 100;
Integer moneyi = moneyd.intValue();
String amount = moneyi.toString();
parameters.put("appid", appId);
parameters.put("mch_id", mchId);
parameters.put("nonce_str", WeixinUtil.create_nonce_str());
parameters.put("body", orderDetail);
parameters.put("out_trade_no", orderId);
parameters.put("total_fee", amount);
parameters.put("spbill_create_ip", spbill_create_ip);
parameters.put("notify_url", notify_url);
parameters.put("trade_type", "JSAPI");
// 微信支付-优惠券-参数配置,start--------------------------------------------------------------
// 单品信息,使用Json数组格式提交
JSONObject goodsDetailObj = new JSONObject();
goodsDetailObj.put("goods_id", goodsId); // 商品编码(必填)
goodsDetailObj.put("wxpay_goods_id", ""); // 微信支付定义的统一商品编号(没有可不传)
goodsDetailObj.put("goods_name", orderDetail); // 商品的实际名称
goodsDetailObj.put("quantity", 1); // 用户购买的数量(必填)
goodsDetailObj.put("price", amount); // 商品单价(必填),单位为:分。如果商户有优惠,需传输商户优惠后的单价(例如:用户对一笔100元的订单使用了商场发的纸质优惠券100-50,则活动商品的单价应为原单价-50)
List<JSONObject> goodsDetailList = new ArrayList<>();
goodsDetailList.add(goodsDetailObj);
// 单品优惠活动该字段
JSONObject detailObj = new JSONObject();
detailObj.put("cost_price", Integer.parseInt(amount)); // (单品优惠必填)1.商户侧一张小票订单可能被分多次支付,订单原价用于记录整张小票的交易金额。2.当订单原价与支付金额不相等,则不享受优惠。3.该字段主要用于防止同一张小票分多次支付,以享受多次优惠的情况,正常支付订单不必上传此参数。
detailObj.put("receipt_id", ""); // 商家小票ID
detailObj.put("goods_detail", goodsDetailList); // 单品信息(必填),使用Json数组格式提交
parameters.put("version", "1.0"); // 接口版本号(必填),区分原接口,默认填写1.0。入参新增version后,则支付通知接口也将返回单品优惠信息字段promotion_detail,请确保支付通知的签名验证能通过。
parameters.put("goods_tag",goodsTag); // 订单优惠标记,用于区分订单是否可以享受优惠
parameters.put("detail", detailObj.toJSONString()); // 单品优惠活动该字段必传(必填)
// 微信支付-优惠券-参数配置,end----------------------------------------------------------------
parameters.put("openid", openid);
注意:对于单品优惠优惠券,单品优惠活动detail字段列表 中 cost_price 字段必填(这个字段文档中为非必填~~),否则无法使用单品优惠。
3.3 支付通知代码修改
为了方便以后统计分析,支付通知代码中增加了记录使用的优惠券信息。下面附上获取这些信息的代码:
String orderId = (String) map.get("out_trade_no"); // 获取订单ID
String transactionId = (String) map.get("transaction_id"); // 获取微信订单号
String totalFee = (String) map.get("total_fee"); // 获取订单总额,单位为分
String timeEnd = (String) map.get("time_end"); // 获取订单支付完成时间
String cashFee = (String) map.get("cash_fee"); // 现金支付金额,单位为分
//String couponFee = (String) map.get("coupon_fee"); // 支付优惠总额,单位为分
String payBank = (String) map.get("bank_type"); // 付款银行,付款方式,详情请看:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2
String promotionDetail = (String) map.get("promotion_detail"); // 营销详情。统一下单API上传参数version后才有返回,返回值为Json格式。
JSONObject marketingObj = new JSONObject();
String promotion_name = ""; // 优惠券名称
String promotion_amount = ""; // 用户享受优惠的金额
String promotion_activityId = ""; // 在微信商户后台配置的批次ID,用于辨别使用的哪张优惠券
// 判断是否使用支付优惠券
if (StringUtils.isNotBlank(promotionDetail)) {
JSONObject promotionObj = JSONObject.parseObject(promotionDetail);
if (promotionObj != null) {
String detail = promotionObj.getString("promotion_detail");
if (StringUtils.isNotBlank(detail)) {
JSONArray promotionDetailArray= JSONArray.parseArray(detail);
if (promotionDetailArray != null && promotionDetailArray.size() > 0) {
// 本业务只有一条子商品信息,故直接获取第一条
JSONObject promotionDetailObj = promotionDetailArray.getJSONObject(0);
promotion_activityId = promotionDetailObj.getString("activity_id");
promotion_name = promotionDetailObj.getString("name");
promotion_amount = promotionDetailObj.getString("amount");
}
}
}
}
四、问题:
1)假如有两张优惠券,分别是 全场立减券A 和 单品立减券B,这两张优惠券设置的订单优惠标记(即goods_tag)一样,不同点是优惠券B同时设置了商品编码(即goods_id),在同一下单接口同时传了 goods_tag 和 goods_id 参数,此时微信在用户支付时会优先使用哪张优惠券?
经测试会优先使用单品立减券B,且在支付界面中不会展示 优惠券A。
2)假如又有两张优惠券,分别是 全场立减券A 和 全场代金券B,这两张优惠券设置的订单优惠标记(即goods_tag)一样,在用户领取了优惠券B的前提下,微信在用户支付时会优先使用哪张券?
经测试会优先使用全场代金券B。
五、补充:
5.1 为方便小伙伴们开发,附上各种优惠券支付通知接收参数:
1)立减与折扣 - 全场立减 通知回调接收参数:
{
"appid": "test",
"bank_type": "CFT",
"cash_fee": "1",
"fee_type": "CNY",
"is_subscribe": "Y",
"mch_id": "1234567890",
"nonce_str": "0b3743772a2a4d8b8b9005c64d47623f",
"openid": "test",
"out_trade_no": "010100032018111400067818",
"promotion_detail": "{\"promotion_detail\":[{\"promotion_id\":\"12345678\",\"name\":\"立减与折扣-全场满减\",\"scope\":\"GLOBAL\",\"type\":\"DISCOUNT\",\"amount\":1000,\"activity_id\":\"1234567\",\"wxpay_contribute\":0,\"merchant_contribute\":1000,\"other_contribute\":0}]}",
"result_code": "SUCCESS",
"return_code": "SUCCESS",
"sign": "6EE6BB2EF05C702FD00C550D82E8DE31",
"time_end": "20181116170811",
"total_fee": "1001",
"trade_type": "JSAPI",
"transaction_id": "4200000206201811165319882354",
"version": "1.0"
}
2)立减与折扣 - 单品立减通知回调接收参数:
{
"appid": "test",
"bank_type": "PSBC_DEBIT",
"cash_fee": "1",
"fee_type": "CNY",
"is_subscribe": "Y",
"mch_id": "test",
"nonce_str": "0bd1e91037834c658b30081241bc6460",
"openid": "test_openid",
"out_trade_no": "0101000320181114000627",
"promotion_detail": "{\"promotion_detail\":[{\"promotion_id\":\"test\",\"name\":\"立减与折扣-单品满减\",\"scope\":\"SINGLE\",
\"type\":\"DISCOUNT\",\"amount\":3000,\"activity_id\":\"test\",\"wxpay_contribute\":0,
\"merchant_contribute\":3000,\"other_contribute\":0,\"goods_detail\":[{\"goods_id\":\"010003\",\"quantity\":1,\"price\":3001,\"discount_amount\":3000}]}]}",
"result_code": "SUCCESS",
"return_code": "SUCCESS",
"sign": "73195D1130F14C3797858BD23883B492",
"time_end": "20181114165912",
"total_fee": "3001",
"trade_type": "JSAPI",
"transaction_id": "4200000215201811145730796824",
"version": "1.0"
}
2)立减与折扣 - 全场折扣通知回调接收参数:
{
"appid": "test",
"bank_type": "CFT",
"cash_fee": "1",
"fee_type": "CNY",
"is_subscribe": "Y",
"mch_id": "1234567890",
"nonce_str": "66f3049df96b4176953911e5bad40f3b",
"openid": "test",
"out_trade_no": "010100032018111400067823",
"promotion_detail": "{\"promotion_detail\":[{\"promotion_id\":\"1234567890\",\"name\":\"全场折扣优惠\",\"scope\":\"GLOBAL\",\"type\":\"DISCOUNT\",\"amount\":99,\"activity_id\":\"1234567\",\"wxpay_contribute\":0,\"merchant_contribute\":99,\"other_contribute\":0}]}",
"result_code": "SUCCESS",
"return_code": "SUCCESS",
"sign": "E59747EACFE5410FEC5205CA292F9D31",
"time_end": "20181116181640",
"total_fee": "100",
"trade_type": "JSAPI",
"transaction_id": "4200000205201811169229040652",
"version": "1.0"
}
4)代金券 - 全场券通知回调接收参数:
{
"appid": "test",
"bank_type": "CFT",
"cash_fee": "1",
"fee_type": "CNY",
"is_subscribe": "Y",
"mch_id": "1234567890",
"nonce_str": "ad3dc6346e894667851a2d6b9d888109",
"openid": "test",
"out_trade_no": "010100032018111400067820",
"promotion_detail": "{\"promotion_detail\":[{\"promotion_id\":\"1234567890\",\"name\":\"代金券-全场券测试\",\"scope\":\"GLOBAL\",\"type\":\"DISCOUNT\",\"amount\":1000,\"activity_id\":\"1234567\",\"wxpay_contribute\":0,\"merchant_contribute\":1000,\"other_contribute\":0}]}",
"result_code": "SUCCESS",
"return_code": "SUCCESS",
"sign": "B557FFD756E05FFA8E6A3DFF216715A5",
"time_end": "20181116175129",
"total_fee": "1001",
"trade_type": "JSAPI",
"transaction_id": "4200000206201811167791965300",
"version": "1.0"
}
5)代金券 - 单品券通知回调接收参数:
{
"appid": "test",
"bank_type": "CFT",
"cash_fee": "1",
"fee_type": "CNY",
"is_subscribe": "Y",
"mch_id": "1234567890",
"nonce_str": "c1caf40c84844af09bb8698fc4193d66",
"openid": "test",
"out_trade_no": "010100032018111400067821",
"promotion_detail": "{\"promotion_detail\":[{\"promotion_id\":\"1234567890\",\"name\":\"单品券测试\",\"scope\":\"SINGLE\",\"type\":\"DISCOUNT\",\"amount\":1000,\"activity_id\":\"1234567\",\"wxpay_contribute\":0,\"merchant_contribute\":1000,\"other_contribute\":0,\"goods_detail\":[{\"goods_id\":\"020001\",\"quantity\":1,\"price\":1001,\"discount_amount\":1000}]}]}",
"result_code": "SUCCESS",
"return_code": "SUCCESS",
"sign": "E04FC81B9D38B0208111F5FDCF18BB5E",
"time_end": "20181116175726",
"total_fee": "1001",
"trade_type": "JSAPI",
"transaction_id": "4200000208201811167067822806",
"version": "1.0"
}