微信支付

This commit is contained in:
joylink_zhangsai 2021-01-15 09:59:01 +08:00
parent 39482d6b1d
commit 1567647be2
13 changed files with 1135 additions and 3 deletions

View File

@ -98,6 +98,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.2.1</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,24 @@
package club.joylink.rtss.controller.pay;
import club.joylink.rtss.services.pay.wechat.WechatPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/api/wechatPay")
public class WechatPayController {
@Autowired
private WechatPayService wechatPayService;
@PostMapping("/receive")
public void receive(@RequestBody String data) {
log.info(String.format("微信回调信息:%s", data));
wechatPayService.receive(data);
}
}

View File

@ -53,7 +53,10 @@ public enum BusinessExceptionAssertEnum implements BusinessExceptionAssert {
WECHAT_CODE_EXPIRED(40029, "wechat code expired"),
INVALID_CLIENT(40031, "invalid client"),
INCORRECT_VERIFICATION_CODE(40051, "incorrect verification code"),
THIRD_SERVICE_CALL_EXCEPTION(40071, "the third service call exception")
THIRD_SERVICE_CALL_EXCEPTION(40071, "the third service call exception"),
//支付异常
PAY_ERROR(50000, "pay error")
;
int code;

View File

@ -0,0 +1,39 @@
package club.joylink.rtss.services.pay.bean;
import club.joylink.rtss.vo.client.order.OrderDetailVO;
import lombok.Getter;
import lombok.Setter;
import java.time.OffsetDateTime;
import java.util.List;
@Getter
@Setter
public class OrderPay {
/**
* 订单编号*
*/
private String orderNo;
/**
* 订单描述*
*/
private String description;
/**
* 订单总价*
*/
private Integer totalFee;
/**
* 交易结束时间
*/
private OffsetDateTime timeExpire;
/**
* 订单中包含的商品详情
*/
private List<OrderDetailVO> orderDetail;
}

View File

@ -0,0 +1,129 @@
package club.joylink.rtss.services.pay.wechat;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.services.IOrderService;
import club.joylink.rtss.services.pay.bean.OrderPay;
import club.joylink.rtss.services.pay.wechat.bean.WxUnifiedOrder;
import club.joylink.rtss.util.JsonUtils;
import club.joylink.rtss.vo.client.order.OrderDetailVO;
import club.joylink.rtss.websocket.StompMessageService;
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;
import lombok.extern.slf4j.Slf4j;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.PrivateKey;
import java.time.OffsetDateTime;
import java.util.List;
import static club.joylink.rtss.services.pay.wechat.constant.WechatConstants.*;
@Service
@Slf4j
public class WechatPayService {
@Autowired
private IOrderService iorderService;
@Autowired
private StompMessageService stompMessageService;
private CloseableHttpClient httpClient;
/**
* 统一下单
* @param orderPay
* @return 支付二维码url
* @throws IOException
*/
public String unifiedOrder(OrderPay orderPay) throws IOException {
CloseableHttpResponse response = null;
try {
if (httpClient == null)
buildHttpClient();
//构建并发送请求
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
httpPost.setHeader("Accept", "application/json");
WxUnifiedOrder wxUnifiedOrder = new WxUnifiedOrder(orderPay, "http://2i38984j47.qicp.vip/api/wechatPay/receive");
String json = JsonUtils.writeValueAsString(wxUnifiedOrder);
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
entity.setContentType("application/json");
httpPost.setEntity(entity);
response = httpClient.execute(httpPost);
//处理请求结果
int statusCode = response.getStatusLine().getStatusCode();
String result = EntityUtils.toString(response.getEntity());
if (statusCode == 200) { //处理成功
log.info("微信支付下单成功,return body = " + result);
return result;
} else if (statusCode == 204) { //处理成功无返回Body
System.out.println("微信支付下单成功");
return result;
} else {
log.error("failed,resp code = " + statusCode+ ",return body = " + result);
throw BusinessExceptionAssertEnum.PAY_ERROR.exception();
}
} catch (Exception e) {
throw BusinessExceptionAssertEnum.PAY_ERROR.exception("微信Native支付异常", e);
} finally {
if (httpClient != null)
httpClient.close();
if (response != null)
response.close();
}
}
private void buildHttpClient() {
try {
PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(MCH_PRIVATE_KEY.getBytes("utf-8")));
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(MCH_ID, new PrivateKeySigner(MCH_SERIAL_NO, privateKey)), APIV3_KEY.getBytes("utf-8"));
httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(MCH_ID, MCH_SERIAL_NO, privateKey)
.withValidator(new WechatPay2Validator(verifier))
.build();
} catch (Exception e) {
throw BusinessExceptionAssertEnum.PAY_ERROR.exception("微信支付httpClient构建异常", e);
}
}
public static void main(String[] args) throws Exception {
OrderPay pay = new OrderPay();
pay.setOrderNo("2018081400001");
pay.setDescription("标准1号线ATS现地工作站实操");
pay.setTotalFee(1);
pay.setTimeExpire(OffsetDateTime.now().plusMinutes(10));
OrderDetailVO orderDetailVO = new OrderDetailVO();
orderDetailVO.setGoodsId(1L);
orderDetailVO.setGoodsName("测试");
orderDetailVO.setGoodsAmount(1);
orderDetailVO.setPrice(1L);
pay.setOrderDetail(List.of(orderDetailVO));
WechatPayService wps = new WechatPayService();
String result = wps.unifiedOrder(pay);
System.out.println(result);
}
/**
* 支付结果处理
*/
public String receive(String data) {
String result = "支付结果:" + data;
log.info(result);
return result;
}
}

View File

@ -0,0 +1,355 @@
package club.joylink.rtss.services.pay.wechat.bean;
public class WxPayResult {
/**
* 返回状态码
*/
private String returnCode;
/**
* 返回信息
*/
private String returnMsg;
/**
* 公众账号ID*
*/
private String appId;
/**
* 商户号*
*/
private String mchId;
/**
* 设备号
*/
private String deviceInfo;
/**
* 随机字符串*
*/
private String nonceStr;
/**
* 签名*
*/
private String sign;
/**
* 签名类型
*/
private String signType;
/**
* 业务结果
*/
private String resultCode;
/**
* 错误代码
*/
private String errCode;
/**
* 错误代码描述
*/
private String errCodeDes;
/**
* 用户标识
*/
private String openId;
/**
* 是否关注公众账号
*/
private String isSubscribe;
/**
* 交易类型*
*/
private String tradeType;
/**
* 付款银行
*/
private String bankType;
/**
* 订单金额
*/
private Integer totalFee;
/**
* 应结订单金额
*/
private Integer settlementTotalFee;
/**
* 货币种类
*/
private String feeType;
/**
* 现金支付金额
*/
private Integer cashFee;
/**
* 现金支付货币类型
*/
private String cashFeeType;
/**
* 总代金券金额
*/
private Integer couponFee;
/**
* 代金券使用数量
*/
private Integer couponCount;
/**
* 微信支付订单号
*/
private String transactionId;
/**
* 商户订单号
*/
private String outTradeNo;
/**
* 商家数据包
*/
private String attach;
/**
* 支付完成时间
*/
private String timeEnd;
public String getReturnCode() {
return returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getMchId() {
return mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getSignType() {
return signType;
}
public void setSignType(String signType) {
this.signType = signType;
}
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrCodeDes() {
return errCodeDes;
}
public void setErrCodeDes(String errCodeDes) {
this.errCodeDes = errCodeDes;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getIsSubscribe() {
return isSubscribe;
}
public void setIsSubscribe(String isSubscribe) {
this.isSubscribe = isSubscribe;
}
public String getTradeType() {
return tradeType;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getBankType() {
return bankType;
}
public void setBankType(String bankType) {
this.bankType = bankType;
}
public Integer getTotalFee() {
return totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public Integer getSettlementTotalFee() {
return settlementTotalFee;
}
public void setSettlementTotalFee(Integer settlementTotalFee) {
this.settlementTotalFee = settlementTotalFee;
}
public String getFeeType() {
return feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getCashFee() {
return cashFee;
}
public void setCashFee(Integer cashFee) {
this.cashFee = cashFee;
}
public String getCashFeeType() {
return cashFeeType;
}
public void setCashFeeType(String cashFeeType) {
this.cashFeeType = cashFeeType;
}
public Integer getCouponFee() {
return couponFee;
}
public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}
public Integer getCouponCount() {
return couponCount;
}
public void setCouponCount(Integer couponCount) {
this.couponCount = couponCount;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getTimeEnd() {
return timeEnd;
}
public void setTimeEnd(String timeEnd) {
this.timeEnd = timeEnd;
}
@Override
public String toString() {
return "WxPayResult [returnCode=" + returnCode + ", returnMsg=" + returnMsg + ", appId=" + appId + ", mchId="
+ mchId + ", deviceInfo=" + deviceInfo + ", nonceStr=" + nonceStr + ", sign=" + sign + ", signType="
+ signType + ", resultCode=" + resultCode + ", errCode=" + errCode + ", errCodeDes=" + errCodeDes
+ ", openId=" + openId + ", isSubscribe=" + isSubscribe + ", tradeType=" + tradeType + ", bankType="
+ bankType + ", totalFee=" + totalFee + ", settlementTotalFee=" + settlementTotalFee + ", feeType="
+ feeType + ", cashFee=" + cashFee + ", cashFeeType=" + cashFeeType + ", couponFee=" + couponFee
+ ", couponCount=" + couponCount + ", transactionId=" + transactionId + ", outTradeNo=" + outTradeNo
+ ", attach=" + attach + ", timeEnd=" + timeEnd + "]";
}
}

View File

@ -0,0 +1,36 @@
package club.joylink.rtss.services.pay.wechat.bean;
public class WxPayResultReply {
/**
* 返回状态码
*/
private String returnCode;
/**
* 返回信息
*/
private String returnMsg;
public String getReturnCode() {
return returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
@Override
public String toString() {
return "WxPayResultReply [returnCode=" + returnCode + ", returnMsg=" + returnMsg + "]";
}
}

View File

@ -0,0 +1,221 @@
package club.joylink.rtss.services.pay.wechat.bean;
import club.joylink.rtss.services.pay.bean.OrderPay;
import club.joylink.rtss.services.pay.wechat.constant.WechatConstants;
import club.joylink.rtss.vo.client.order.OrderDetailVO;
import lombok.Getter;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
@Getter
public class WxUnifiedOrder {
/**
* 公众账号ID*
*/
private String appid;
/**
* 商户号*
*/
private String mchid;
/**
* 商品描述
*/
private String description;
/**
* 商户订单号
*/
private String out_trade_no;
/**
* 交易结束时间
*/
private String time_expire;
/**
* 附加数据
*/
private String attach;
/**
* 通知地址
*/
private String notify_url;
/**
* 订单优惠标记
*/
private String goods_tag;
/**
* 订单金额信息
*/
private WxPayOrderAmountInfo amount;
/**
* 优惠功能没懂为啥这个参数要叫优惠功能
*/
private WxPayOrderDetail detail;
/**
* 场景信息支付场景描述
*/
private WxPaySceneInfo scene_info;
public WxUnifiedOrder(OrderPay orderPay, String notify_url) {
this.appid = WechatConstants.APP_ID;
this.mchid = WechatConstants.MCH_ID;
this.description = orderPay.getDescription();
this.out_trade_no = orderPay.getOrderNo();
if (orderPay.getTimeExpire() != null) {
this.time_expire = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(orderPay.getTimeExpire().withNano(0));
}
// this.attach =
this.notify_url = notify_url;
// this.goods_tag =
this.amount = new WxPayOrderAmountInfo(orderPay.getTotalFee());
// this.detail = new WxPayOrderDetail(out_trade_no, orderPay.getOrderDetail());
// this.scene_info = new WxPaySceneInfo();
}
/**
* 订单金额信息
*/
@Getter
class WxPayOrderAmountInfo {
/**
* 订单总金额单位/
*/
private int total;
/**
* 货币类型
*/
private String currency = "CNY";
public WxPayOrderAmountInfo(int total) {
this.total = total;
}
}
@Getter
class WxPayOrderDetail {
/**
* 订单原价
* 该字段主要用于防止同一张小票分多次支付以享受多次优惠的情况正常支付订单不必上传此参数
*/
private int cost_price;
/**
* 商家小票ID
*/
private String invoice_id;
/**
* 单品列表
*/
private List<GoodsDetail> goods_detail;
public WxPayOrderDetail(String invoice_id, List<OrderDetailVO> orderDetailVOS) {
this.invoice_id = invoice_id;
this.goods_detail = orderDetailVOS.stream().map(GoodsDetail::new).collect(Collectors.toList());
}
@Getter
class GoodsDetail {
/**
* 商户侧商品编码
* 由半角的大小写字母数字中划线下划线中的一种或几种组成
*/
private String merchant_goods_id;
/**
* 微信侧商品编码
* 微信支付定义的统一商品编号没有可不传
*/
private String wechatpay_goods_id;
/**
* 商品名称
*/
private String goods_name;
/**
* 商品数量
*/
private int quantity;
/**
* 商品单价单位为分
*/
private int unit_price;
public GoodsDetail(OrderDetailVO orderDetail) {
this.merchant_goods_id = orderDetail.getGoodsId().toString();
this.goods_name = orderDetail.getGoodsName();
this.quantity = orderDetail.getGoodsAmount();
this.unit_price = orderDetail.getPrice().intValue();
}
}
}
/**
* 场景信息
*/
@Getter
class WxPaySceneInfo {
/**
* 用户终端ip调用微信支付API的机器IP支持IPv4和IPv6两种格式的IP地址
*/
private String payer_client_ip;
/**
* 商户端设备号商户端设备号门店号或收银设备ID
*/
private String device_id;
/**
* 商户门店信息
*/
private StoreInfo store_info;
public WxPaySceneInfo() {
this.payer_client_ip = WechatConstants.SPBILL_CREATE_IP;
this.device_id = "1";
this.store_info = new StoreInfo();
}
@Getter
class StoreInfo {
/**
* 门店编号商户侧门店编号
*/
private String id;
/**
* 门店名称商户侧门店名称
*/
private String name;
/**
* 地区编码地区编码详细请见省市区编号对照表
*/
private String area_code;
/**
* 详细地址详细的商户门店地址
*/
private String address;
public StoreInfo() {
}
}
}
}

View File

@ -0,0 +1,183 @@
package club.joylink.rtss.services.pay.wechat.bean;
public class WxUnifiedOrderResult {
/**
* 返回状态码*
*/
private String returnCode;
/**
* 返回信息*
*/
private String returnMsg;
/**
* 公众账号ID*
*/
private String appId;
/**
* 商户号*
*/
private String mchId;
/**
* 设备号
*/
private String deviceInfo;
/**
* 随机字符串*
*/
private String nonceStr;
/**
* 签名*
*/
private String sign;
/**
* 业务结果*
*/
private String resultCode;
/**
* 错误代码
*/
private String errCode;
/**
* 错误代码描述
*/
private String errCodeDes;
/**
* 交易类型*
*/
private String tradeType;
/**
* 预支付交易会话标识*
*/
private String prepayId;
/**
* 二维码链接
*/
private String codeUrl;
public String getReturnCode() {
return returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getMchId() {
return mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrCodeDes() {
return errCodeDes;
}
public void setErrCodeDes(String errCodeDes) {
this.errCodeDes = errCodeDes;
}
public String getTradeType() {
return tradeType;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getPrepayId() {
return prepayId;
}
public void setPrepayId(String prepayId) {
this.prepayId = prepayId;
}
public String getCodeUrl() {
return codeUrl;
}
public void setCodeUrl(String codeUrl) {
this.codeUrl = codeUrl;
}
@Override
public String toString() {
return "WxUnifiedOrderResult [returnCode=" + returnCode + ", returnMsg=" + returnMsg + ", appId=" + appId
+ ", mchId=" + mchId + ", deviceInfo=" + deviceInfo + ", nonceStr=" + nonceStr + ", sign=" + sign
+ ", resultCode=" + resultCode + ", errCode=" + errCode + ", errCodeDes=" + errCodeDes + ", tradeType="
+ tradeType + ", prepayId=" + prepayId + ", codeUrl=" + codeUrl + "]";
}
}

View File

@ -0,0 +1,73 @@
package club.joylink.rtss.services.pay.wechat.constant;
public interface WechatConstants {
public static interface PayUrl {
/** 统一下单接口地址 */
String UNIFIED_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
}
String DATE_FORMAT_STR = "yyyyMMddHHmmss";
/** 公众账号ID */
String APP_ID = "wx41cb66db5faf330f";
/** 商户号 */
String MCH_ID = "1511854231";
/** 机器IP */
String SPBILL_CREATE_IP = "58.87.66.250";
/** 商户平台设置的密钥key应该已经没用了 */
String MCH_KEY = "a6502d608c64fb2f7e6dbcf854cda32a";
/** 商户证书序列号 */
String MCH_SERIAL_NO = "40980EBE9204E4D8956215FE72A1C89A8480FA27";
/** APIv3密钥用于解密接口返回的数据平台证书公钥 */
String APIV3_KEY = "c0666cec1cb15d915f802ce5a3df5c2d";
/** 商户证书私钥 */
String MCH_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" +
"MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDAzmBwXZX7p+bl\n" +
"IiSl/5CukfAxOmYTVgCbLQ1SBJMd9c52VsPgWED4o/llkvwWXY9EUTDX09qOBroF\n" +
"+iCQBu9iWvStfN2VTmy7ECC3ROv1HzAK2U/aWOsCxv/svpqUoWImqAVaUtOd+kQK\n" +
"RtMVvz/kE+BUZO1RFA3YS7dmYPtAuZQOhLXTvg7uS5k/PaSg39Bx+ZNcymUQtHHs\n" +
"6nH0RmneY2LBtmLZHw3aeb2VCydEPY9tON/vhBbLXe/+Lq3C8Lx8R2IdURCcR2Wl\n" +
"92UlLwR5nBK/kKcgOPA7DjBf4zPGBHgFovytW5gKRY+UscrPgSEHxa9fmRy/SLQS\n" +
"k7AjGZC5AgMBAAECggEBALGIFiLA+Y5sbt3DD43OAbHMbSdXB5B8WziHRkGkNraa\n" +
"lI5AnEHh4YlQqx7NNdN+OKIGRHwm9ZJbPUStqPgVeqzM5YktdXa6bMHeOtGl48Kk\n" +
"Af+rU6zQvSykghjC9OEwrIi9o5gktfg77hSsXEck/7aKWsA64o4KcikcpvXdDNzt\n" +
"qrLumHzJ32WLN6q5JClc4zPfpc3CuRUH3SJevDC7b0E+BFth8c1cX1QDbSl1v8kA\n" +
"anolAIcHqhFvJHzpY+WjHqGVdN4RbPXl+xsOoo3mXsTHybSWgHd2ZJGAAqtQlaSV\n" +
"Y9dRLSU4MQBITNGe5j+rngyRowDkrYqbtAfFqtYQhwUCgYEA5iDlSqu69pr50xf4\n" +
"oQmyOk7ep9U8JOTH+C+OOtbVzpS51oLnq95wJ8cu/QV8qhOUVSZ6KKhD37o7XWhZ\n" +
"vGjBGrlv/C0anAsZ4S10GmL/gbqpCckSe4ITz4VI03oy/fdRK+VtulgMFvjKEr9F\n" +
"cYOkct4IkKAclAECYLhX7VUEKrMCgYEA1ntX1kA4objy7+bgfmxmFkAk50otHJwR\n" +
"huCEOMe9MlgAAc9NYk+GEF1tQPzTQVdVL6jovtrZ+L5HP1SXJGQWY6N06XJThN9+\n" +
"oks027gQWBoXnTQJ8/wXPQpXq3EIgCThzKNkTLq4fsnGIUgRUH2/W+IjlNEThw26\n" +
"KqmuBiXjfOMCgYEAxe6lSIRMWq8RES8c+eWNFfmgKFqPUGw2UpEUlCcT3oqtDIOr\n" +
"H3hCnvQCxj1h7CbK/jIJ/846EsPrK3wFMrgm3wV//DYPHQevSq39nnRnrv0NRw1a\n" +
"iEBpKaRJ7xq7oRSHDGpY5l20iE2UAGvjHq9LUkEGvN35tpLnqKjld4wX+WECgYEA\n" +
"urCwGzDZWoOXCpTHMaP/FD0PIjehnraGVwWUcawClhCdKPYdoIYh5pq734ZyB/0R\n" +
"jCOVO5NZibduYsSprqZkCqSbvhuicRTssC2QO/QyXc2QYmiKhVIXlC0tdHA1+vyf\n" +
"grVyN4uLzeipygxl7c8Wws7LM9ztB3A+bKY3cOiH5AsCgYEA4XOMKmJeucNOrXTY\n" +
"3NdHCb8Yx5JgCYqgdq5uIY7MQ8f3+OlXNwdhh/ftjk8DejWzyY7jpqgj2W3qZFu+\n" +
"BxGJZfCDzAqUS9OufMY8tOO/PaIABzSkU4gliBAuxovj9sU6oSSa7aYD+34QW2UU\n" +
"L83fUdwBuNbwX6vZM45hIASP6C8=\n" +
"-----END PRIVATE KEY-----";
/**
* 支付类型
* @author sheng
*/
public static interface TradeType {
/** 扫码支付 */
String NATIVE = "NATIVE";
/** 公众号支付 */
String JSAPI = "JSAPI";
/** APP支付 */
String APP = "APP";
}
}

View File

@ -0,0 +1,25 @@
package club.joylink.rtss.services.pay.wechat.controller;
import club.joylink.rtss.services.pay.wechat.WechatPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/wechatpay")
@Slf4j
public class PayResultController {
@Autowired
private WechatPayService wechatPayService;
@RequestMapping(path="/receive", method= {RequestMethod.POST})
public String receive(@RequestBody String data) {
log.info("支付结果通知:" + data);
return this.wechatPayService.receive(data);
}
}

View File

@ -0,0 +1,39 @@
package club.joylink.rtss.services.pay.wechat.util;
import club.joylink.rtss.util.EncryptUtil;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
public class SignUtil {
public static String sign(Map<String, String> map, String mchKey) {
Set<String> keysSet = map.keySet();
Object[] keys = keysSet.toArray();
// 排序
Arrays.sort(keys);
StringBuffer temp = new StringBuffer();
boolean first = true;
for (Object key : keys) {
Object value = map.get(key);
if(null != value) {
if (first) {
first = false;
} else {
temp.append("&");
}
temp.append(key).append("=");
String valueString = "";
if (null != value) {
valueString = value.toString();
}
temp.append(valueString);
}
}
String tempStr = temp.toString()+"&key="+mchKey;
System.out.println(tempStr);
return EncryptUtil.md5(tempStr).toUpperCase();
}
}

View File

@ -31,7 +31,7 @@ public class OrderDetailVO {
private Integer monthAmount;
private Float price;
private Long price;
public OrderDetailVO(SaleOrderDetail detail) {
id = detail.getId();
@ -41,7 +41,7 @@ public class OrderDetailVO {
startTime = detail.getStartTime();
goodsAmount = detail.getGoodsAmount();
monthAmount = detail.getMonthAmount();
price = (float) detail.getPrice() / 100;
price = detail.getPrice();
}
}