public class WeixinPayConfig {

public static final String appid = "xxxxxxxxxxxx";// 在微信开发平台登记的app应用
public static final String mch_id = "xxxxxx";// 商户号 即微信商户平台 登录号

public static final String paternerKey = "xxxxxxxx";// 密钥
// =>微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置

public static final String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";// 统一下单接口

// openId 是微信用户针对公众号的标识,授权的部分这里不解释
public static final String openId = "";

// 微信支付成功后通知地址 必须要求80端口并且地址不能带参数
// public static String notify_url =
// "http://xxxxxxxxx/wxpay/notify.do";
public static String notify_url = "http://xxxxxx/notify.do";

public static final String ORDER_PAY_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery"; // 支付订单查询

public static final String ORDER_REFUND = "https://api.mch.weixin.qq.com/secapi/pay/refund"; // 申请退款

public static final String ORDER_REFUND_QUERY = "https://api.mch.weixin.qq.com/pay/refundquery"; // 申请退款
}



/**
*
* @param request
* @param response
* @param body
* 商品描述
* @param subject
* 订单标题
* @param out_trade_no
* 商户订单号,商户网站订单系统中唯一订单号,必填
* @param total_amount
* 付款金额,必填
* @param callback
* {"code":-1,"msg":"订单参数不能为空","response":{"cont":null,"list":[]}
* }
*/
@RequestMapping(value = "appbuildOrder")
public void appbuildOrder(HttpServletRequest request,
HttpServletResponse response, String body, String subject,
String out_trade_no, Double total_amount, String callback) {

LOG.info("[/wxpay/pay]");

try {
body = new String(body.getBytes("ISO-8859-1"), "utf-8");
subject = new String(subject.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
;

if (StringUtil.isEmpty(body) || StringUtil.isEmpty(subject)
|| StringUtil.isEmpty(out_trade_no) || total_amount == 0
|| total_amount == null) {
WebUtil.response(response,
WebUtil.packJsonp(callback, JSON.toJSONString(
new JsonResult(-1, "订单参数不能为空", new ResponseData()),
SerializerFeatureUtil.FEATURES)));
return;
}
// else {

// ======================================================
// 创建下单 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
Map<String, String> restmap = null;
boolean flag = true; // 是否订单创建成功
try {
String total_fee = BigDecimal.valueOf(total_amount)
.multiply(BigDecimal.valueOf(100))
.setScale(0, BigDecimal.ROUND_HALF_UP).toString();

Map<String, String> parm = new HashMap<String, String>();
parm.put("appid", WeixinPayConfig.appid);// 应用号
parm.put("mch_id", WeixinPayConfig.mch_id);// 商户号
parm.put("device_info", "WEB");
parm.put("nonce_str", PayUtil.getNonceStr());
parm.put("body", subject);// 商品名称
parm.put("attach", body);// 商户携带订单的自定义数据
parm.put("out_trade_no", out_trade_no);// 商户系统内部订单号
parm.put("total_fee", total_fee);// 订单总金额,单位为分
parm.put("spbill_create_ip", PayUtil.getRemoteAddrIp(request));// 用户端实际ip
parm.put("notify_url", WeixinPayConfig.notify_url); // 微信服务器异步通知支付结果地址
// 下面的order/notify
// 方法
parm.put("trade_type", "APP");// 支付类型
parm.put("sign", PayUtil.getSign(parm, WeixinPayConfig.paternerKey));

String restxml = HttpUtils.post(WeixinPayConfig.createOrderURL,
XmlUtil.xmlFormat(parm, false));
restmap = XmlUtil.xmlParse(restxml);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}

Map<String, String> payMap = new HashMap<String, String>();

// ==========================================================================
// https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12&index=2
// 获取到prepayid后对以下字段进行签名最终发送给app
if (CollectionUtil.isNotEmpty(restmap)
&& "SUCCESS".equals(restmap.get("result_code"))) {
payMap.put("appid", WeixinPayConfig.appid);
payMap.put("partnerid", WeixinPayConfig.mch_id);
payMap.put("prepayid", restmap.get("prepay_id"));// 微信返回的支付交易会话ID
payMap.put("package", "Sign=WXPay");// 固定值Sign=WXPay
payMap.put("noncestr", PayUtil.getNonceStr());// 随机字符串
payMap.put("timestamp", PayUtil.payTimestamp());// 时间戳
try {
payMap.put("sign",
PayUtil.getSign(payMap, WeixinPayConfig.paternerKey));
} catch (Exception e) {
flag = false;
}
} else {
flag = false;
}

if (flag) {
WebUtil.response(response, WebUtil.packJsonp(callback, JSON
.toJSONString(new JsonResult(1, "订单获取成功", new ResponseData(
null, payMap)), SerializerFeatureUtil.FEATURES)));
LOG.info("[/wxpay/pay-success]");
} else {
if (CollectionUtil.isNotEmpty(restmap)) {
LOG.info("订单创建失败:" + restmap.get("err_code") + ":"
+ restmap.get("err_code_des"));
}
WebUtil.response(response,
WebUtil.packJsonp(callback, JSON.toJSONString(
new JsonResult(-1, "订单获取失败", new ResponseData()),
SerializerFeatureUtil.FEATURES)));
}

}


异步回调


/**
* https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3
* 订单支付微信服务器异步通知
*
* @param request
* @param response
*/
@ResponseBody
@RequestMapping("/notify")
public String orderPayNotify(HttpServletRequest request,
HttpServletResponse response) {
LOG.info("[/wxpay/notify]");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/xml");
Map<String, String> parm = new HashMap<String, String>();
try {
ServletInputStream in = request.getInputStream();
String resxml = FileUtil.readInputStream2String(in);
Map<String, String> restmap = XmlUtil.xmlParse(resxml);
LOG.info("支付结果通知:" + restmap);
if ("SUCCESS".equals(restmap.get("return_code"))) {
// 订单支付成功 业务处理
String out_trade_no = restmap.get("out_trade_no"); // 商户订单号
String transaction_id = restmap.get("transaction_id"); // 商户订单号

String cash_fee = restmap.get("cash_fee"); // 商户订单号
cash_fee = new BigDecimal(cash_fee).divide(new BigDecimal(100))
.setScale(2).toString();
// 通过商户订单判断是否该订单已经处理 如果处理跳过 如果未处理先校验sign签名 再进行订单业务相关的处理

String sing = restmap.get("sign"); // 返回的签名
restmap.remove("sign");
String signnow = PayUtil.getSign(restmap,
WeixinPayConfig.paternerKey);
if (signnow.equals(sing)) {
// 进行业务处理
LOG.info("订单支付通知: 支付成功,订单号" + out_trade_no);

PayDevInfo isExist = payDevInfoService
.findPayDevInfoByTradeNo(transaction_id);

if (isExist == null) {// 防止重复处理
// 支付成功业务处理
........
}

parm.put("return_code", "SUCCESS");
parm.put("return_msg", "OK");

} else {
LOG.info("订单支付通知:签名错误");
parm.put("return_code", "FAIL");
parm.put("return_msg", "签名失败");
}
} else {
LOG.info("订单支付通知:支付失败," + restmap.get("err_code") + ":"
+ restmap.get("err_code_des"));
parm.put("return_code", "FAIL");
parm.put("return_msg", "支付失败");
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
parm.put("return_code", "FAIL");
parm.put("return_msg", "商户服务器问题");
}

String xml = XmlUtil.xmlFormat(parm, true);
return xml;

}



双向验证 报错

DerInputStream.getLength(): lengthTag=111, too big.

SSL context may not be null

原因

war 打包后 证书大小变大了,

解决手动复制证书到相应的目录


android 客户端

 

请求前判断有没有安装微信


private boolean isWXAppInstalledAndSupported() {
mWxApi = WXAPIFactory.createWXAPI(this, WX_APPID, true);
mWxApi.registerApp(WX_APPID);

boolean sIsWXAppInstalledAndSupported = mWxApi.isWXAppInstalled()
&& mWxApi.isWXAppSupportAPI();
return sIsWXAppInstalledAndSupported;

}



OkHttpUtils.get().url(url)
.addParams("body", body)
.addParams("subject", subject)
.addParams("out_trade_no", System.currentTimeMillis() + groupId)
.addParams("total_amount", total_amount + "")
.build()
.connTimeOut(20 * 1000)
.readTimeOut(20 * 1000)
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e, int id) {
Toast.makeText(UIUtils.getContext(),
"支付失败,请稍后重试!", Toast.LENGTH_SHORT)
.show();
;
}

@Override
public void onResponse(String response, int id) {
if (!TextUtils.isEmpty(response)) {

final String orderInfo = response;
PayJsonResult jsonResult = new Gson()
.fromJson(orderInfo, PayJsonResult.class);
wxPay(jsonResult);
} else {
Toast.makeText(UIUtils.getContext(),
"支付失败,请稍后重试!", Toast.LENGTH_SHORT)
.show();
}
}
});




private void wxPay(ResponseData response) {
Map<String, Object> json = (Map<String, Object>) response.getCont();

Log.e("get server pay params:", json.toString());

try {


if (null != json) {
PayReq req = new PayReq();
//req.appId = "wxf8b4f85f3a794e77"; // 测试用appId
req.appId = (String) json.get("appid");
req.partnerId = (String) json.get("partnerid");
req.prepayId = (String) json.get("prepayid");
req.nonceStr = (String) json.get("noncestr");
req.timeStamp = (String) json.get("timestamp");
req.packageValue = (String) json.get("package");
req.sign = (String) json.get("sign");
req.extData = "app data"; // optional
Toast.makeText(this, "正常调起支付", Toast.LENGTH_SHORT).show();
// 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
mWxApi.sendReq(req);

finish();

}
} catch (Exception e) {
Log.e("PAY_GET", "异常:" + e.getMessage());
Toast.makeText(this, "支付失败,请稍后重试", Toast.LENGTH_SHORT).show();
}
}