一:我们公司的业务场景是,发起咨询之后需要支付,支付有月卡,年卡等,所以需要小程序调起微信支付,下面是实现微信支付的具体步骤
1.发起支付时需要用到的参数有.appid在微信小程序公众平台么能查到
package com.aihelp.api.domain.pay.dto;
import com.aihelp.api.domain.pay.PayClient;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* <p>
* 微信支付参数
* </p>
*/
@Data
public class WechatPayParams {
@NotBlank(message = "appId不能为空")
@ApiModelProperty("appId")
private String appId;
@NotNull(message = "支付类型")
private PayClient payClient;
@ApiModelProperty(value = "支付金额(元)")
@DecimalMin(value = "0.01", message = "支付金额最低为一分")
private BigDecimal money;
@NotBlank(message = "商户订单号不能为空")
@ApiModelProperty("商户订单号")
private String outTradeNo;
@NotBlank(message = "自定义支付回调地址不能为空")
@ApiModelProperty("自定义回调地址")
private String notifyUrl;
@NotBlank(message = "缺少商品描述信息")
@ApiModelProperty("商品描述")
private String description;
@ApiModelProperty("附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段")
private String attach;
@ApiModelProperty("openid, 小程序支付参数")
private String openId;
}
二:支付逻辑,先去查询订单表判断是否重复支付,准备好参数去调用支付接口
WechatPayParams params = new WechatPayParams();
params.setMoney(payWater.getPayAmount());
params.setOutTradeNo(payWater.getOutTradeNo());
params.setDescription("知识链-订单编号".concat(payWater.getOutTradeNo()));
params.setNotifyUrl(kwkdProperties.getServicePrefix().concat(PaymentController.WECHAT_NOTIFY_URL));
// ! 通过支付产品的不同,区分不同的appId
if (PayProductEnum.MINI.equals(payProduct)) {
params.setPayClient(PayClient.WECHAT_MINI_PROGRAM);
params.setOpenId(SecurityUtils.getLoginUser().getOpenId());
params.setAppId(kwkdProperties.getWechatMini().getAppId());
} else if (PayProductEnum.APP.equals(payProduct)) {
params.setPayClient(PayClient.APP_PAY);
params.setAppId(kwkdProperties.getWechatApp().getAppId());
} else {
throw new ServiceException("支付产品错误");
}
R<WechatPayResponse> remoteWechatPayResponse = remotePayService.pay(params);
三:请求支付接口
/**
* 发送微信支付API V3 请求
*
* @param url 接口地址
* @param params 请求参数,参考微信支付文档
* @return
* @throws IOException
*/
public String sendWechatHttpV3PostAPI(String url, Object params) throws IOException {
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
// httpPost.addHeader("Referer","test.alhelp.net");
// extraHeaders.put("Referer", "商户申请H5时提交的授权域名")
//将传入的参数转换为json交给微信那边
httpPost.setEntity(new StringEntity(objectMapper.writeValueAsString(params), StandardCharsets.UTF_8));
CloseableHttpResponse response = httpClient.execute(httpPost);
System.err.println(EntityUtils.toString(response.getEntity()));
return EntityUtils.toString(response.getEntity());
}
四:就是微信支付回调了,和微信退款的差不多,第一步分解回调的参数
private ValidatePayCallbackParams createCallbackParams(HttpServletRequest request) {
ValidatePayCallbackParams validatePayCallbackParams = new ValidatePayCallbackParams();
// 请求报文
String body = ServletUtil.getBody(request);
validatePayCallbackParams.setBody(body);
// 验签请求头
ValidatePayCallbackParams.WechatNotifyHeader wechatNotifyHeader = ValidatePayCallbackParams.WechatNotifyHeader.crateWechatNotifyHeader(request);
validatePayCallbackParams.setWechatNotifyHeader(wechatNotifyHeader);
return validatePayCallbackParams;
}
五回调检验
@ApiOperation("支付回调校验")
@PostMapping("/validatePayCallback")
public R<ValidatePayCallbackResponse> validatePayCallback(@Validated @RequestBody ValidatePayCallbackParams params) throws
ValidationException, ParseException {
log.info("微信支付回调校验 信息:{}", params);
Notification notification = this.parseNotification(params);
ValidatePayCallbackResponse response = new ValidatePayCallbackResponse();
ValidatePayCallbackResponse.PayInfo payInfo = JSON.parseObject(notification.getDecryptData(), ValidatePayCallbackResponse.PayInfo.class);
response.setPayInfo(payInfo);
return R.ok(response);
}
六:一般也是根据交易状态来判断回调是否成功trade_state;