进入官网文档:> 微信支付官网文档
根据官网文档能够很详细的需要做的事
接下来,采用的是JSAPI的方式
在小程序嵌入H5页面中
实现微信支付,直接拉起支付页面
一:需要在微信公众号平台和微信支付商家平台获取的配置的关键参数如下:
1,
openid:需要实现微信登录才能获取
2,
微信公众号绑定的appid
3,
微信商家号绑定对应的appid的商家号id
4,
商家号密钥
5,
商家号拉起支付的授权目录
6,
支付完成通知的回调地址:这个地址是后端自定义的回调接口地址
准备以上参数之后,开始写代码:根据官网文档编写
二:简单总结需要做的事儿
1,创建sdk客户端
.
2,构造请求的参数
.
3,封装前端需要的响应参数
.
4,前端获取参数,直接拉起支付界面
.
5,支付完成完成后,请求回调地址,处理结果
.
注意:这里签名的类型有两种md5和HMACSHA256需要注意一下这个地方,出错概率大
controller层如下 :
请求实体
@Data
@ApiModel("微信下单请求实体")
public class WxPayOrderDTO {
@ApiModelProperty(value = "用户openid")
@NotBlank(message = "openid不能未空")
private String openId;
@ApiModelProperty(value = "收费类型")
@NotNull(message = "商品标识标识不能未空")
private Integer type;
}
常量封装
public class WxPayConstant {
// 回调地址
public static final String NOTIFY_URL = "https://gpt.xiaomon.com/api2/base/wx/callback";
// 商家号密钥
public static final String API_KEY = "Tunda123Tunda123Tunda123Tunda123";
// appid
public static final String APP_ID = "wx27599519b337b629";
// 商家号id
public static final String PAY_MCH_ID = "1618043632";
}
serviceImpl层:
/**
* 微信JSAPI支付
* @param payDTO
* @return
*/
public Map<String, String> wxPayForJSAPI(WxPayOrderDTO payDTO) {
// 创建订单
SaveOrderVO order = orderService.createOrder(payDTO);
try {
//创建sdk客户端
WXPay wxPay = new WXPay(new WXPayConfigCustom());
//构造请求的参数
Map<String, String> data = new HashMap<>();
data.put("openid",payDTO.getOpenId());
data.put("body",order.getRemark()); // 商品描述
// 金额处理一下
BigDecimal fee = order.getFee().multiply(new BigDecimal(100));
log.info("金额:{}",fee.setScale(0, BigDecimal.ROUND_DOWN).toString());
data.put("total_fee", fee.setScale(0, BigDecimal.ROUND_DOWN).toString()); // 订单金额, 单位分
data.put("nonce_str",WXPayUtil.generateNonceStr());// 随机字符串
data.put("spbill_create_ip", AddressUtils.getIp()); // 下单ip
log.info("微信下单ip->{}",AddressUtils.getIp());
data.put("notify_url", WxPayConstant.NOTIFY_URL); // 订单结果通知, 微信主动回调此接口
data.put("out_trade_no", order.getOrderNo()); // 订单唯一编号, 不允许重复
data.put("trade_type", "JSAPI"); // 交易类型 MWEB--H5支付、JSAPI--小程序支付-类型不同则参数不同
String sign = WXPayUtil.generateSignature(data, WxPayConstant.API_KEY, WXPayConstants.SignType.HMACSHA256);
data.put("sign",sign);
Map<String, String> map = wxPay.unifiedOrder(data);
log.info("微信平台下订单情况->{}",map);
String prepayId = map.get("prepay_id");
if(null==prepayId){
orderService.updateOrder(order.getOrderNo(),"", OrderStatusEnum.FAIL_PAY);
throw new BusinessException("获取预支付id异常");
}
// 封装前端需要的响应参数
Map<String, String> resultMap = new HashMap<String, String>();
resultMap.put("appId", WxPayConstant.APP_ID);
resultMap.put("timeStamp", String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000));
resultMap.put("nonceStr", WXPayUtil.generateNonceStr());
resultMap.put("package", "prepay_id=" + prepayId);
// 注意:下单默认的是h256方式,校验默认是MD5方式,前端默认采用MD5校验
resultMap.put("signType", "MD5");
// 将map按照ASCILL码排序
Map<String, String> sortMap = new TreeMap<String,String>(resultMap);
log.info("排序之后:{}",sortMap);
sign = WXPayUtil.generateSignature(sortMap, WxPayConstant.API_KEY,WXPayConstants.SignType.HMACSHA256);
resultMap.put("paySign", sign);
resultMap.put("orderNo",order.getOrderNo());
return resultMap;
}catch (Exception e){
orderService.updateOrder(order.getOrderNo(),"", OrderStatusEnum.FAIL_PAY);
throw new BusinessException("微信支付下单异常,请重试");
}
}
微信回调
/**
* 微信回调
* @param request
* @return
*/
@Override
public String wxPayCallBack(HttpServletRequest request) {
log.info("微信支付-成功回调");
// 校验结果、XML
Map<String, String> back = new HashMap();
String result = "";
try {
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
result = new String(outSteam.toByteArray());
//xml转map 微信SDK自带
Map<String, String> map = WXPayUtil.xmlToMap(result);
// 判断签名是否正确、记得指定加密方式,因为下单默认的是h256方式,校验默认是MD5方式
if (WXPayUtil.isSignatureValid(map, WxPayConstant.API_KEY, WXPayConstants.SignType.HMACSHA256)) {
back.put("return_code", "SUCCESS");
if ("SUCCESS".equalsIgnoreCase(map.get("result_code")));{
log.info("支付成功,回调成功");
// 拿到订单号,修改订单状态
String orderNo = map.get("out_trade_no");
String payTime = map.get("time_end");
orderService.updateOrder(orderNo, payTime,OrderStatusEnum.SUCESS_PAY);
}
} else {
back.put("return_code", "FAIL");
back.put("return_msg", "参数格式校验错误");
}
// WX响应格式是xml的字符串
result = WXPayUtil.mapToXml(back);
} catch (Exception e) {
throw new BusinessException("支付回调用异常");
}finally {
// 必须响应给WX服务器
return result;
}
}