简单对支付封装,
使用到maven 依赖,版本依照自己项目情况自行添加
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
1、请求参数实体基类,
因用于微信app支付、小程序支付、h5支付
首先创建基类BasePayEntity 实现Serializable 接口
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class BasePayEntity implements Serializable {
@JSONField(name = "appid")
@ApiModelProperty(name = "appId" , required = true , value = "应用ID")
protected String appId ;
@JSONField(name = "mchid")
@ApiModelProperty(name = "mchId" , required = true , value = "直连商户号")
protected String mchId ;
@JSONField(name = "description")
@ApiModelProperty(name = "description" , required = true , value = "商品描述")
protected String description ;
@JSONField(name = "out_trade_no")
@ApiModelProperty(name = "outTradeNo" , required = true , value = "商户订单号")
protected String outTradeNo ;
@JSONField(name = "time_expire")
@ApiModelProperty(name = "timeExpire" , value = "交易结束时间")
protected String timeExpire ;
@JSONField(name = "attach")
@ApiModelProperty(name = "attach" , value = "附加数据")
protected String attach ;
@JSONField(name = "notify_url")
@ApiModelProperty(name = "notifyUrl" , required = true , value = "通知地址")
protected String notifyUrl ;
@JSONField(name = "amount")
@ApiModelProperty(name = "amount" , required = true , value = "订单金额")
protected Amount amount ;
@JSONField(name = "detail")
@ApiModelProperty(name = "detail" , value = "优惠功能")
protected Detail detail ;
@JSONField(name = "settle_info")
@ApiModelProperty(name = "settleInfo" , value = "结算信息")
protected SettleInfo settleInfo ;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Amount implements Serializable {
@ApiModelProperty(name = "total" , required = true , value = "总金额")
protected Integer total ;
@ApiModelProperty(name = "currency" , required = true , value = "CNY:人民币,境内商户号仅支持人民币。")
protected String currency ;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Detail implements Serializable{
@JSONField(name = "cost_price")
@ApiModelProperty(name = "costPrice" , value = "总金额")
protected Integer costPrice ;
@JSONField(name = "invoice_id")
@ApiModelProperty(name = "invoiceId" , value = "商品小票ID")
protected String invoiceId ;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class SettleInfo implements Serializable{
@JSONField(name = "profit_sharing")
@ApiModelProperty(name = "profitSharing" , value = "是否指定分账")
protected Boolean profitSharing ;
}
public BasePayEntity(String appId, String mchId, String description, String outTradeNo, String timeExpire, String attach, String notifyUrl, Amount amount, Detail detail, SettleInfo settleInfo) {
this.appId = appId;
this.mchId = mchId;
this.description = description;
this.outTradeNo = outTradeNo;
this.timeExpire = timeExpire;
this.attach = attach;
this.notifyUrl = notifyUrl;
this.amount = amount;
this.detail = detail;
this.settleInfo = settleInfo;
}
}
2、定义Jsapi下单
创建实体类继承BasePayEntity
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("Jsapi下单")
@Accessors(chain = true)
@Url("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi")
public class JsApiPay extends BasePayEntity {
@JSONField(name = "scene_info")
@ApiModelProperty(name = "sceneInfo" , value = "支付场景描述")
private SceneInfo sceneInfo ;
@JSONField(name = "payer")
@ApiModelProperty(name = "payer" , required = true , value = "支付者信息")
private Payer payer ;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Payer implements Serializable{
@ApiModelProperty(name = "openid" , required = true , value = "用户标识")
private String openid ;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class SceneInfo implements Serializable{
@JSONField(name = "payer_client_ip")
@ApiModelProperty(name = "payerClientIp" , value = "用户的客户端IP,支持IPv4和IPv6两种格式的IP地址")
private String payerClientIp ;
@JSONField(name = "device_id")
@ApiModelProperty(name = "deviceId" , value = "商户端设备号(门店号或收银设备ID)")
private String deviceId ;
@JSONField(name = "store_info")
@ApiModelProperty(name = "storeInfo" , value = "商户门店信息")
private StoreInfo storeInfo ;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class StoreInfo implements Serializable{
@JSONField(name = "id")
@ApiModelProperty(name = "id" , value = "商户侧门店编号")
private String id ;
@JSONField(name = "name")
@ApiModelProperty(name = "name" , value = "商户侧门店名称")
private String name ;
@JSONField(name = "area_code")
@ApiModelProperty(name = "areaCode" , value = "地区编码,详细请见省市区编号对照表。")
private String areaCode ;
@JSONField(name = "address")
@ApiModelProperty(name = "address" , value = "详细的商户门店地址")
private String address ;
}
}
@Builder(toBuilder = true)
public JsApiPay(String appId, String mchId, String description, String outTradeNo, String timeExpire, String attach, String notifyUrl, Amount amount, Detail detail, SettleInfo settleInfo, SceneInfo sceneInfo, Payer payer) {
super(appId, mchId, description, outTradeNo, timeExpire, attach, notifyUrl, amount, detail, settleInfo);
this.sceneInfo = sceneInfo;
this.payer = payer;
}
}
3、创建工具MiniPayUtils
public class MiniPayUtils {
private WechatProperties wechatProperties ;
public static MiniPayUtils newInstance(WechatProperties wechatProperties){
MiniPayUtils miniPayUtils = new MiniPayUtils();
miniPayUtils.wechatProperties = wechatProperties ;
return miniPayUtils ;
}
public MiniPayResult pay(JsApiPay jsApiPay) {
BasePayEntity.Amount amount = jsApiPay.getAmount();
jsApiPay = jsApiPay.toBuilder().appId(wechatProperties.getMini().getAppid()).amount(ObjectUtils.isEmpty(amount) ? BasePayEntity.Amount.builder().currency("CNY").build() : amount.setCurrency("CNY")).notifyUrl(wechatProperties.getNotifyUrl()).mchId(wechatProperties.getMerchant().getMchId()).build();
String nonceStr = SignUtils.getRandom() , timeStamp = String.valueOf(System.currentTimeMillis() / 1000) ;
MiniPayResult miniPayResult = MiniPayResult.builder().appId(jsApiPay.getAppId())
.timeStamp(timeStamp)
.nonceStr(nonceStr)
.packages(prepayId(jsApiPay , nonceStr , timeStamp))
.signType("RSA")
.build();
miniPayResult.setPaySign(SignUtils.sign(miniPayResult.toJsonString().getBytes() , wechatProperties.getMerchant().getCertPath() , ProjectStatus.windows操作系统.getValue().equals(wechatProperties.getEnvironment())));
return miniPayResult ;
}
public String prepayId(JsApiPay jsapiPay , String nonceStr , String timeStamp){
try{
String url = jsapiPay.getClass().getAnnotation(Url.class).value() , body = JSONObject.toJSONString(jsapiPay);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.AUTHORIZATION , SignUtils.getToken(HttpMethod.POST.name()
, new URL(url)
, body
, nonceStr
, timeStamp
, jsapiPay.getMchId()
, wechatProperties.getMerchant().getSerialNo()
, wechatProperties.getMerchant().getCertPath()
, ProjectStatus.windows操作系统.getValue().equals(wechatProperties.getEnvironment())));
httpHeaders.add(HttpHeaders.CONTENT_TYPE , MediaType.APPLICATION_JSON_VALUE);
ResponseEntity<String> exchange = getRestTemplate().exchange(url , HttpMethod.POST , new HttpEntity(body , httpHeaders), String.class );
if(HttpStatus.OK.equals(exchange.getStatusCode())) {
JSONObject jsonObject = JSONObject.parseObject(exchange.getBody());
return "prepay_id=" + jsonObject.getString("prepay_id");
}
throw BaseException.throwEx(JSONObject.parseObject(exchange.getBody()).getString("message"));
}catch (Exception e){
String message = e.getMessage();
if(e instanceof HttpClientErrorException){
HttpClientErrorException exception = (HttpClientErrorException)e;
if(403 == exception.getRawStatusCode()) throw BaseException.throwEx(JSONObject.parseObject(message.substring(message.indexOf("[") + 1 , message.lastIndexOf("]"))).getString("message"));
}
throw BaseException.throwEx(message);
}
}
}
以上的代码基本上可以完成项目的微信支付