|
@@ -9,7 +9,9 @@ import com.ruoyi.common.core.redis.RedisCache;
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
|
import com.ruoyi.common.utils.http.HttpUtils;
|
|
|
import com.ruoyi.common.utils.sign.Base64;
|
|
|
+import com.ruoyi.system.domain.DoumuProductInfo;
|
|
|
import com.ruoyi.system.domain.wx.*;
|
|
|
+import com.ruoyi.system.mapper.DoumuProductInfoMapper;
|
|
|
import com.ruoyi.system.service.IWxPayService;
|
|
|
import com.wechat.pay.java.core.Config;
|
|
|
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
|
@@ -25,6 +27,7 @@ import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
|
|
|
import org.apache.commons.lang3.ObjectUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.omg.CORBA.TIMEOUT;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Configurable;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
@@ -61,8 +64,12 @@ public class WxPayServiceImpl implements IWxPayService {
|
|
|
private static final String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
|
|
|
//文本内容安全识别
|
|
|
private static final String MSGSECCHECK = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=ACCESS_TOKEN";
|
|
|
+ //公众号发送模板消息
|
|
|
+ private static final String TEMPLATE_MESSAGE = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private DoumuProductInfoMapper doumuProductInfoMapper;
|
|
|
/**
|
|
|
* 小程序appId
|
|
|
*/
|
|
@@ -111,8 +118,9 @@ public class WxPayServiceImpl implements IWxPayService {
|
|
|
request.setMchid(wxPayV3Bean.getMchId());
|
|
|
request.setDescription(req.getGoodsName());
|
|
|
request.setNotifyUrl(wxPayV3Bean.getNotifyUrl());
|
|
|
- request.setOutTradeNo("DMGT" + System.currentTimeMillis());
|
|
|
- request.setAttach(req.getOrderType());
|
|
|
+ request.setOutTradeNo(req.getOrderSn());
|
|
|
+ //自定义数据设置为商品名称
|
|
|
+ request.setAttach(req.getGoodsName());
|
|
|
Payer payer = new Payer();
|
|
|
payer.setOpenid(req.getOpenId());
|
|
|
request.setPayer(payer);
|
|
@@ -120,16 +128,17 @@ public class WxPayServiceImpl implements IWxPayService {
|
|
|
PrepayResponse response = service.prepay(request);
|
|
|
WxPayRespVo vo = new WxPayRespVo();
|
|
|
Long timeStamp = System.currentTimeMillis() / 1000;
|
|
|
- vo.setTimeStamp(timeStamp);
|
|
|
+ vo.setTimeStamp(timeStamp.toString());
|
|
|
String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
|
|
|
vo.setNonceStr(substring);
|
|
|
String signatureStr = Stream.of(wxPayV3Bean.getAppId(), String.valueOf(timeStamp), substring, "prepay_id=" + response.getPrepayId())
|
|
|
.collect(Collectors.joining("\n", "", "\n"));
|
|
|
String sign = WxPayUtil.getSign(signatureStr, wxPayV3Bean.getKeyPath());
|
|
|
vo.setPaySign(sign);
|
|
|
- vo.setPrepayId(response.getPrepayId());
|
|
|
+ vo.setPrepayId("prepay_id="+response.getPrepayId());
|
|
|
vo.setAppId(wxPayV3Bean.getAppId());
|
|
|
vo.setSignType("RSA");
|
|
|
+ //TemplateMessageZhiFu(req,request);
|
|
|
//todo 存储预支付订单信息
|
|
|
return AjaxResult.success(vo);
|
|
|
} catch (ServiceException e) {
|
|
@@ -200,13 +209,185 @@ public class WxPayServiceImpl implements IWxPayService {
|
|
|
.body(s1)
|
|
|
.build();
|
|
|
Transaction parse = parser.parse(requestParam, Transaction.class);
|
|
|
- //todo 存储支付结果
|
|
|
+ /**
|
|
|
+ * trade_state
|
|
|
+ * 必填
|
|
|
+ * string(32)
|
|
|
+ * 交易状态,枚举值:
|
|
|
+ * SUCCESS:支付成功
|
|
|
+ * REFUND:转入退款
|
|
|
+ * NOTPAY:未支付
|
|
|
+ * CLOSED:已关闭
|
|
|
+ * REVOKED:已撤销(付款码支付)
|
|
|
+ * USERPAYING:用户支付中(付款码支付)
|
|
|
+ * PAYERROR:支付失败(其他原因,如银行返回失败)
|
|
|
+ */
|
|
|
+ //todo 存储支付结果 支付成功需要修改订单状态
|
|
|
+ Transaction.TradeStateEnum tradeState = parse.getTradeState();
|
|
|
+ if (Transaction.TradeStateEnum.SUCCESS.equals(tradeState)){
|
|
|
+ String outTradeNo = parse.getOutTradeNo();
|
|
|
+ //订单支付成功
|
|
|
+ DoumuProductInfo doumuProductInfo = new DoumuProductInfo();
|
|
|
+ doumuProductInfo.setOrderNumber(outTradeNo);
|
|
|
+ doumuProductInfo.setStatus("2");
|
|
|
+ doumuProductInfoMapper.updateDoumuProductInfo(doumuProductInfo);
|
|
|
+ }
|
|
|
+ TemplateMessage(parse);
|
|
|
System.out.println("parse = " + parse);
|
|
|
} catch (Exception e) {
|
|
|
System.out.println("获取微信支付回调失败");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 给微信公共号下发消息
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void TemplateMessage(Transaction parse ) {
|
|
|
+ /**
|
|
|
+ * {
|
|
|
+ * "touser":"OPENID",
|
|
|
+ * "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
|
|
|
+ * "url":"http://weixin.qq.com/download",
|
|
|
+ * "miniprogram":{
|
|
|
+ * "appid":"xiaochengxuappid12345",
|
|
|
+ * "pagepath":"index?foo=bar"
|
|
|
+ * },
|
|
|
+ * "client_msg_id":"MSG_000001",
|
|
|
+ * "data":{
|
|
|
+ *
|
|
|
+ * "keyword1":{
|
|
|
+ * "value":"巧克力"
|
|
|
+ * },
|
|
|
+ * "keyword2": {
|
|
|
+ * "value":"39.8元"
|
|
|
+ * },
|
|
|
+ * "keyword3": {
|
|
|
+ * "value":"2014年9月22日"
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ */
|
|
|
+ Object accessToken = null;
|
|
|
+ try {
|
|
|
+ //todo 需要根据公众号的appid和秘钥获取token
|
|
|
+ //公众号appid:wxb581c5d48ffa6327
|
|
|
+ //从redis中获取
|
|
|
+ accessToken = redisCache.getCacheObject(Constants.WX_ACCESS_TOKEN);
|
|
|
+ if (ObjectUtils.isEmpty(accessToken)) {
|
|
|
+ String result = HttpClientUtils.doGet(ACCESS_TOKEN.replace("APPID", appId)
|
|
|
+ .replace("APPSECRET", appSecret)
|
|
|
+ );
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(result);
|
|
|
+ accessToken = jsonObject.get("access_token");
|
|
|
+ redisCache.setCacheObject(Constants.WX_ACCESS_TOKEN, accessToken, Constants.CAPTCHA_EXPIRATION, TimeUnit.HOURS);
|
|
|
+ }
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ JSONObject jsonObjectData = new JSONObject();
|
|
|
+ //接收者openid sp_openid 用户在服务商应用下的用户标示 sub_appid 子商户应用载体的AppID,
|
|
|
+ jsonObject.put("touser", parse.getPayer().getSpOpenid());
|
|
|
+ //模板ID
|
|
|
+ jsonObject.put("template_id", "rtYn3Mjepo8TSeCwabgbln3TEiWXYcfPQmAiFP9V5PU");
|
|
|
+ //所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)
|
|
|
+ jsonObject.put("appid", appId);
|
|
|
+ /**
|
|
|
+ * {{first.DATA}}
|
|
|
+ * 订单编号:{{keyword1.DATA}}
|
|
|
+ * 商品名称:{{keyword2.DATA}}
|
|
|
+ * 订单总价:{{keyword3.DATA}}
|
|
|
+ * 订单状态:{{keyword4.DATA}}
|
|
|
+ * 下单时间:{{keyword5.DATA}}
|
|
|
+ * {{remark.DATA}}
|
|
|
+ */
|
|
|
+ jsonObjectData.put("first","恭喜您!购买的商品已支付成功。");
|
|
|
+ jsonObjectData.put("keyword1",parse.getOutTradeNo());
|
|
|
+ jsonObjectData.put("keyword2",parse.getAttach());
|
|
|
+ jsonObjectData.put("keyword3",parse.getAmount());
|
|
|
+ jsonObjectData.put("keyword4",parse.getTradeStateDesc());
|
|
|
+ jsonObjectData.put("keyword5",parse.getOutTradeNo());
|
|
|
+ jsonObjectData.put("remark","欢迎您的到来!");
|
|
|
+ //模板数据
|
|
|
+ jsonObject.put("data", jsonObjectData);
|
|
|
+ String msgsecCheck = HttpUtil.post(TEMPLATE_MESSAGE.replace("ACCESS_TOKEN", (String) accessToken), jsonObject.toJSONString());
|
|
|
+ System.out.println("消息模板通知结果:"+msgsecCheck);
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 给微信公共号下发消息预支付测试
|
|
|
+ */
|
|
|
+ public void TemplateMessageZhiFu(WxPayOrderReqVo req,PrepayRequest request ) {
|
|
|
+ /**
|
|
|
+ * {
|
|
|
+ * "touser":"OPENID",
|
|
|
+ * "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
|
|
|
+ * "url":"http://weixin.qq.com/download",
|
|
|
+ * "miniprogram":{
|
|
|
+ * "appid":"xiaochengxuappid12345",
|
|
|
+ * "pagepath":"index?foo=bar"
|
|
|
+ * },
|
|
|
+ * "client_msg_id":"MSG_000001",
|
|
|
+ * "data":{
|
|
|
+ *
|
|
|
+ * "keyword1":{
|
|
|
+ * "value":"巧克力"
|
|
|
+ * },
|
|
|
+ * "keyword2": {
|
|
|
+ * "value":"39.8元"
|
|
|
+ * },
|
|
|
+ * "keyword3": {
|
|
|
+ * "value":"2014年9月22日"
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ */
|
|
|
+ Object accessToken = null;
|
|
|
+ try {
|
|
|
+ //从redis中获取
|
|
|
+ accessToken = redisCache.getCacheObject(Constants.WX_ACCESS_TOKEN);
|
|
|
+ if (ObjectUtils.isEmpty(accessToken)) {
|
|
|
+ String result = HttpClientUtils.doGet(ACCESS_TOKEN.replace("APPID", appId)
|
|
|
+ .replace("APPSECRET", appSecret)
|
|
|
+ );
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(result);
|
|
|
+ accessToken = jsonObject.get("access_token");
|
|
|
+ redisCache.setCacheObject(Constants.WX_ACCESS_TOKEN, accessToken, Constants.CAPTCHA_EXPIRATION, TimeUnit.HOURS);
|
|
|
+ }
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ JSONObject jsonObjectData = new JSONObject();
|
|
|
+ //接收者openid sp_openid 用户在服务商应用下的用户标示 sub_appid 子商户应用载体的AppID,
|
|
|
+ jsonObject.put("touser", req.getOpenId());
|
|
|
+ //模板ID
|
|
|
+ jsonObject.put("template_id", "rtYn3Mjepo8TSeCwabgbln3TEiWXYcfPQmAiFP9V5PU");
|
|
|
+ //所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)
|
|
|
+ jsonObject.put("appid", appId);
|
|
|
+ /**
|
|
|
+ * {{first.DATA}}
|
|
|
+ * 订单编号:{{keyword1.DATA}}
|
|
|
+ * 商品名称:{{keyword2.DATA}}
|
|
|
+ * 订单总价:{{keyword3.DATA}}
|
|
|
+ * 订单状态:{{keyword4.DATA}}
|
|
|
+ * 下单时间:{{keyword5.DATA}}
|
|
|
+ * {{remark.DATA}}
|
|
|
+ */
|
|
|
+ jsonObjectData.put("first","恭喜您!购买的商品等待支付。");
|
|
|
+ jsonObjectData.put("keyword1",request.getOutTradeNo());
|
|
|
+ jsonObjectData.put("keyword2",request.getAttach());
|
|
|
+ jsonObjectData.put("keyword3",request.getAmount());
|
|
|
+ jsonObjectData.put("keyword4","待支付");
|
|
|
+ jsonObjectData.put("keyword5",request.getOutTradeNo());
|
|
|
+ jsonObjectData.put("remark","欢迎您的到来!");
|
|
|
+ //模板数据
|
|
|
+ jsonObject.put("data", jsonObjectData);
|
|
|
+ String msgsecCheck = HttpUtil.post(TEMPLATE_MESSAGE.replace("ACCESS_TOKEN", (String) accessToken), jsonObject.toJSONString());
|
|
|
+ System.out.println("消息模板通知结果:"+msgsecCheck);
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 根据code获取小程序openid和unionid
|
|
|
*
|