微信发放指定批次的代金券。
接口:https://api.mch.weixin.qq.com/v3/marketing/favor/users/{openid}/coupons
测试环境:JDK1.8
完整代码:
package com.weixin;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
public class WeixinCoupons {
String mchId="XXXXXXX";//商户号
String mchSerialNo="XXXXXXXXXXXXXXXXXX";//证书序列号
String merchantPrivateKeyFile="D:/apiclient_key.pem";//证书地址
String appId = "wxXXXXXXXXXXXXXXXXXXX";//公众号appid
String apiV3Key="XXXXXXXXXXXXXXXXXXXXXXXXXX";//APIv3密钥-32个字符,支持数字和大小写字母组合
private static Logger log = LoggerFactory.getLogger(WeixinCoupons.class);
/**
* 发放微信代金券
* @param stock_id 批次ID
* @param openid openid
*/
public String sendCoupon(String stock_id, String openid) {
FileInputStream privateKeyInputStream = null;
try {
privateKeyInputStream = new FileInputStream(new File(merchantPrivateKeyFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
//log.error("read merchantPrivateKeyFile or certificateFile faild, errmsg:" + e.getMessage());
return null;
}
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(privateKeyInputStream);
// 加载商户私钥
PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, merchantPrivateKey);
WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);
// 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,merchantPrivateKey:商户私钥,apiV3Key:V3秘钥)
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(wechatPay2Credentials, apiV3Key.getBytes(StandardCharsets.UTF_8));
CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(mchId, mchSerialNo, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier))
.build();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String nowTime = sdf.format(new Date());
String out_request_no= mchId + "" + nowTime + getRandomString(5);//【商户单据号】 商户此次发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性
String sendCouponUrl = String.format("https://api.mch.weixin.qq.com/v3/marketing/favor/users/%s/coupons", openid );
HashMap<String, String> paraMap = new HashMap<>();
paraMap.put("stock_id", stock_id );
paraMap.put("out_request_no", out_request_no );
paraMap.put("appid", appId);
paraMap.put("stock_creator_mchid", mchId);
//log.info("request url=" + sendCouponUrl);
//log.info("request params=" + JSONObject.toJSONString(paraMap));
HttpPost httpPost = new HttpPost(sendCouponUrl);
StringEntity reqEntity = new StringEntity(JSONObject.toJSONString(paraMap),
ContentType.create("application/json", "utf-8"));
httpPost.setEntity(reqEntity);
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-Type", "application/json");
CloseableHttpResponse response = null;
try {
//log.info("微信发券接口地址:"+sendCouponUrl+",入参:"+JSONObject.toJSONString(httpPost));
response = httpClient.execute(httpPost);
//log.info("微信发券接口返回结果code:"+response.getStatusLine().getStatusCode()+",内容:"+ EntityUtils.toString(response.getEntity()));
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String result = EntityUtils.toString(response.getEntity());
log.info("response=" + result);
return result;
} else {
String result = EntityUtils.toString(response.getEntity());
log.error("status_code=" + response.getStatusLine().getStatusCode() + ", response=" + result);
return result;
}
} catch (Exception e) {
//log.error("excepiton:" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public String getRandomString(int length){
String str = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for(int i=0;i<length;i++){
int number=random.nextInt(str.length());
sb.append(str.charAt(number));
}
return sb.toString();
}
public static void main(String[] args) {
WeixinCoupons weixinCoupons = new WeixinCoupons();
String stock_id = "XXXXX";//stock_id-代金券【批次id】 微信为每个批次分配的唯一id。 校验规则:必须为代金券(全场券或单品券)批次号
String openid = "XXXXXXXXXXX";
weixinCoupons.sendCoupon(stock_id, openid);
}
`}`
log4j.properties:
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
#log4j.appender.console.Threshold=DEBUG
log4j.appender.console.Threshold=INFO
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=\[%c\]-%m%n
#文件输出的相关设置- 10mb
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=d:/logs/log.log
log4j.appender.file.MaxFileSize=1mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=\[%p\]\[%d{yy-MM-dd HH:mm:ss}\]\[%c\]%m%n
`#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG`
maven依赖:
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.5</version>
</dependency>
- commons-logging-1.1.1.jar
- fastjson-1.2.71.jar
- httpclient-4.5.13.jar
- httpcore-4.4.16.jar
- httpmime-4.5.13.jar
- jackson-annotations-2.14.0.jar
- jackson-core-2.14.0.jar
- jackson-databind-2.14.0.jar
- log4j-1.2.16.jar
- slf4j-api-1.7.25.jar
- slf4j-log4j12-1.7.25.jar
- wechatpay-apache-httpclient-0.4.5.jar
更多
发放指定批次的代金券API
:https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/coupon/send-coupon.html
什么是APIv3密钥?如何设置?
:https://kf.qq.com/faq/180830E36vyQ180830AZFZvu.html
什么是商户API证书?如何获取商户API证书?
:https://kf.qq.com/faq/161222NneAJf161222U7fARv.html