1. 调起微信支付的域名要和微信支付配置的一致,导致无法本地测试
解决方案: 修改本地host文件将配置的域名指向本机, 手机wifi使用本机代理上网。
1. maven中引入开发包
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-WxPay</artifactId>
<version>2.4.0</version>
</dependency>
2. 创建请求需要的参数类。配置信息在application中
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
public class WxPayProperties {
@Value("${wx.pay.appId}")
private String appId;
@Value("${wx.pay.mchId}")
private String mchId;
@Value("${wx.pay.mchKey}")
private String mchKey;
@Value("${wx.pay.notifyUrl}")
private String notifyUrl;
}
application配置文件 如下
wx:
pay:
appId: wx123223342341
mchId: 123423123
mchKey: U6gG1CqAqwedrfgfffrvfXFBokr
notifyUrl: http://169b91h550.imwork.net:35084/wx/wxPayNotice
3. 封装JsApi支付工具
package com.jyl.shop.config.wx;
import com.ijpay.core.model.BaseModel;
public class JsApiOrderModel extends BaseModel {
private String appid;
private String sub_appid;
private String mch_id;
private String sub_mch_id;
private String nonce_str;
private String sign;
private String body;
private String attach;
private String out_trade_no;
private String fee_type;
private String total_fee;
private String spbill_create_ip;
private String time_start;
private String time_expire;
private String limit_pay;
private String contract_code;
private String promotion_tag;
private String trade_type;
private String notify_url;
private String device_info;
private String mini_app_param;
private String openid;
public static JsApiOrderModelBuilder builder() {
return new JsApiOrderModelBuilder();
}
private JsApiOrderModel(String appid, String sub_appid, String mch_id, String sub_mch_id, String nonce_str, String sign, String body, String attach, String out_trade_no, String fee_type, String total_fee, String spbill_create_ip, String time_start, String time_expire, String limit_pay, String contract_code, String promotion_tag, String trade_type, String notify_url, String device_info, String mini_app_param, String openid) {
this.appid = appid;
this.sub_appid = sub_appid;
this.mch_id = mch_id;
this.sub_mch_id = sub_mch_id;
this.nonce_str = nonce_str;
this.sign = sign;
this.body = body;
this.attach = attach;
this.out_trade_no = out_trade_no;
this.fee_type = fee_type;
this.total_fee = total_fee;
this.spbill_create_ip = spbill_create_ip;
this.time_start = time_start;
this.time_expire = time_expire;
this.limit_pay = limit_pay;
this.contract_code = contract_code;
this.promotion_tag = promotion_tag;
this.trade_type = trade_type;
this.notify_url = notify_url;
this.device_info = device_info;
this.mini_app_param = mini_app_param;
this.openid = openid;
}
public String getAppid() {
return this.appid;
}
public String getSub_appid() {
return this.sub_appid;
}
public String getMch_id() {
return this.mch_id;
}
public String getSub_mch_id() {
return this.sub_mch_id;
}
public String getNonce_str() {
return this.nonce_str;
}
public String getSign() {
return this.sign;
}
public String getBody() {
return this.body;
}
public String getAttach() {
return this.attach;
}
public String getOut_trade_no() {
return this.out_trade_no;
}
public String getFee_type() {
return this.fee_type;
}
public String getTotal_fee() {
return this.total_fee;
}
public String getSpbill_create_ip() {
return this.spbill_create_ip;
}
public String getTime_start() {
return this.time_start;
}
public String getTime_expire() {
return this.time_expire;
}
public String getLimit_pay() {
return this.limit_pay;
}
public String getContract_code() {
return this.contract_code;
}
public String getPromotion_tag() {
return this.promotion_tag;
}
public String getTrade_type() {
return this.trade_type;
}
public String getNotify_url() {
return this.notify_url;
}
public String getDevice_info() {
return this.device_info;
}
public String getMini_app_param() {
return this.mini_app_param;
}
public String getOpenid() {
return openid;
}
public static class JsApiOrderModelBuilder {
private String appid;
private String sub_appid;
private String mch_id;
private String sub_mch_id;
private String nonce_str;
private String sign;
private String body;
private String attach;
private String out_trade_no;
private String fee_type;
private String total_fee;
private String spbill_create_ip;
private String time_start;
private String time_expire;
private String limit_pay;
private String contract_code;
private String promotion_tag;
private String trade_type;
private String notify_url;
private String device_info;
private String mini_app_param;
private String openid;
JsApiOrderModelBuilder() {
}
public JsApiOrderModelBuilder appid(String appid) {
this.appid = appid;
return this;
}
public JsApiOrderModelBuilder sub_appid(String sub_appid) {
this.sub_appid = sub_appid;
return this;
}
public JsApiOrderModelBuilder mch_id(String mch_id) {
this.mch_id = mch_id;
return this;
}
public JsApiOrderModelBuilder sub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_mch_id;
return this;
}
public JsApiOrderModelBuilder nonce_str(String nonce_str) {
this.nonce_str = nonce_str;
return this;
}
public JsApiOrderModelBuilder sign(String sign) {
this.sign = sign;
return this;
}
public JsApiOrderModelBuilder body(String body) {
this.body = body;
return this;
}
public JsApiOrderModelBuilder attach(String attach) {
this.attach = attach;
return this;
}
public JsApiOrderModelBuilder out_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
return this;
}
public JsApiOrderModelBuilder fee_type(String fee_type) {
this.fee_type = fee_type;
return this;
}
public JsApiOrderModelBuilder total_fee(String total_fee) {
this.total_fee = total_fee;
return this;
}
public JsApiOrderModelBuilder spbill_create_ip(String spbill_create_ip) {
this.spbill_create_ip = spbill_create_ip;
return this;
}
public JsApiOrderModelBuilder time_start(String time_start) {
this.time_start = time_start;
return this;
}
public JsApiOrderModelBuilder time_expire(String time_expire) {
this.time_expire = time_expire;
return this;
}
public JsApiOrderModelBuilder limit_pay(String limit_pay) {
this.limit_pay = limit_pay;
return this;
}
public JsApiOrderModelBuilder contract_code(String contract_code) {
this.contract_code = contract_code;
return this;
}
public JsApiOrderModelBuilder promotion_tag(String promotion_tag) {
this.promotion_tag = promotion_tag;
return this;
}
public JsApiOrderModelBuilder trade_type(String trade_type) {
this.trade_type = trade_type;
return this;
}
public JsApiOrderModelBuilder notify_url(String notify_url) {
this.notify_url = notify_url;
return this;
}
public JsApiOrderModelBuilder device_info(String device_info) {
this.device_info = device_info;
return this;
}
public JsApiOrderModelBuilder mini_app_param(String mini_app_param) {
this.mini_app_param = mini_app_param;
return this;
}
public JsApiOrderModelBuilder openid(String openid) {
this.openid = openid;
return this;
}
public JsApiOrderModel build() {
return new JsApiOrderModel(this.appid, this.sub_appid, this.mch_id, this.sub_mch_id, this.nonce_str, this.sign, this.body, this.attach, this.out_trade_no, this.fee_type, this.total_fee, this.spbill_create_ip, this.time_start, this.time_expire, this.limit_pay, this.contract_code, this.promotion_tag, this.trade_type, this.notify_url, this.device_info, this.mini_app_param, this.openid);
}
@Override
public String toString() {
return "JsApiOrderModel.JsApiOrderModelBuilder(appid=" + this.appid + ", sub_appid=" + this.sub_appid + ", mch_id=" + this.mch_id + ", sub_mch_id=" + this.sub_mch_id + ", nonce_str=" + this.nonce_str + ", sign=" + this.sign + ", body=" + this.body + ", attach=" + this.attach + ", out_trade_no=" + this.out_trade_no + ", fee_type=" + this.fee_type + ", total_fee=" + this.total_fee + ", spbill_create_ip=" + this.spbill_create_ip + ", time_start=" + this.time_start + ", time_expire=" + this.time_expire + ", limit_pay=" + this.limit_pay + ", contract_code=" + this.contract_code + ", promotion_tag=" + this.promotion_tag + ", trade_type=" + this.trade_type + ", notify_url=" + this.notify_url + ", device_info=" + this.device_info + ", mini_app_param=" + this.mini_app_param+ ", openid=" + this.openid + ")";
}
}
}
3. 请求示例
public Map<String,Object> wxJsApiPay(ShopOrders shopOrders) {
ShopMember shopMember = shopMemberService.getMember();
String ip = getIpAddr();
Map<String, String> params = JsApiOrderModel
.builder()
.appid(wxPayProperties.getAppId())
.mch_id(wxPayProperties.getMchId())
.nonce_str(shopOrders.getOrderNo())
.body("微信支付")
.out_trade_no(shopOrders.getOrderNo())
.total_fee(String.valueOf((shopOrders.getRealTotalMoney().multiply(new BigDecimal("100"))).intValue()))
.spbill_create_ip(ip)
.notify_url(wxPayProperties.getNotifyUrl())
.trade_type(TradeType.JSAPI.getTradeType())
.openid("99999999999")
.build()
.createSign(wxPayProperties.getMchKey(), SignType.MD5);
String xmlResult = WxPayApi.pushOrder(false, params);
Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
if (StringUtils.equals(resultMap.get("return_code"), "SUCCESS")) {
String prepayId = resultMap.get("prepay_id");
Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxPayProperties.getAppId(),
wxPayProperties.getMchKey(), SignType.MD5);
return packageParams;
}
return null;
}
获取客户端IP地址
private String getIpAddr() {
String ip = request.getHeader("x-forwarded-for");
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
if (ip.indexOf(",") != -1) {
ip = ip.split(",")[0];
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip != null ? ip : "192.168.0.1";
}
异步通知
@PostMapping("/notifyUrl")
public void notifyUrl(@RequestBody String xmlData) {
Map<String, String> resultMap = WxPayKit.xmlToMap(xmlData);
String platformOrderNumber = resultMap.get("out_trade_no");
BigDecimal paymentAmount = new BigDecimal(resultMap.get("cash_fee"));
String transactionId = resultMap.get("transaction_id");
String timeEnd = resultMap.get("timeEnd");
....
}