​前一篇文章的时序图中说了,app端调用微信支付必须先由后台调用微信后台生成预付单,再构建参数给手机端,而数据的构建要以xml形式,那么看看代码具体实现吧,代码已经精简过了,自己的业务已经除去,精简的代码附上注释是可以直接调用微信后台的

这个是微信所要接受的参数,咱们可以把它构建成一个entity

public class WXPrepay {
private static String unifiedorder = "https://api.mch.weixin.qq.com/pay/unifiedorder";
private static String orderquery = "https://api.mch.weixin.qq.com/pay/orderquery";
private String appid; // 应用ID 微信开放平台审核通过的应用APPID
private String mch_id; // 商户号 微信支付分配的商户号
private String nonce_str = OrderUtil.CreateNoncestr(); // 随机字符串 随机字符串,不长于32位
private String sign; // 签名
private String body; // 商品描述 商品描述交易字段格式根据不同的应用场景按照以下格式:APP——需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。
private String out_trade_no; // 商户订单号 商户系统内部的订单号,32个字符内、可包含字母
private String total_fee; // 总金额 订单总金额,单位为分
private String spbill_create_ip; // 终端IP 用户端实际ip
private String notify_url; // 通知地址 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
private String trade_type; // 交易类型 支付类型
private String partnerKey;
private String attach; // 附加数据 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 private String prepay_id; // 预支付订单号

controller作为一个restful接口供手机端调用,这个接口可以被ios,安卓等调用,只要微信提供了相应手机端的sdk,那就没有问题

@RequestMapping("/wxpay")
@ResponseBody
public LeeJSONResult wxpay(HttpServletRequest request, Model model) {
try {
// TODO 根据你的业务逻辑计算你需要支付的订单总额
double totalFee = 1;
// 生成交易流水,流水id需要传给微信,这个流水ID可以作为你的订单ID,由于我们的业务是多订单的,流水ID仅仅只是作为表关联
// 需要保存货源id,需要的车辆数,订单id在通知成功后保存
String payFlowId = sid.nextShort();
SpPayFlowCargoSource payFlowCargoSource = new SpPayFlowCargoSource();
payFlowCargoSource.setId(payFlowId);
payFlowCargoSource.setFee(new BigDecimal(totalFee));
payFlowCargoSource.setPayStatus(PayStatusEnum.NOT_PAID.value); // 支付状态:未支付 // 构建微信参数
String spbill_create_ip = request.getRemoteAddr(); // 用户IP
WXPrepay prePay = new WXPrepay();
prePay.setAppid(WXPayContants.appId);
prePay.setMch_id(WXPayContants.partnerId);
prePay.setBody("demo - 微信支付");
prePay.setOut_trade_no(payFlowId);
// 这里要注意,微信支付是以分为单位,而系统是以元为单位,所以需要金额转换。题外话:曾经看到过京东和苏宁都有类似的bug,就是一个台手机和耳机都是要十几元,估计是金额转换出的问题
prePay.setTotal_fee(String.valueOf(new BigDecimal(totalFee).multiply(new BigDecimal(100)).intValue()));
// prePay.setTotal_fee("1");
prePay.setSpbill_create_ip(spbill_create_ip);
prePay.setNotify_url(notifyUrl); // 异步通知,这个下篇文章讲
prePay.setTrade_type("APP");
prePay.setAttach(payFlowId); // 存入交易流水id prePay.setPartnerKey(WXPayContants.partnerKey); // 获取预支付订单号
String prepayId = prePay.submitXmlGetPrepayId();
logger.info("获取的预支付订单是:" + prepayId);
if (prepayId != null && prepayId.length() > 10) {
// 生成微信支付参数,此处拼接为完整的JSON格式,符合支付调起传入格式
String jsParam = WXPay.createPackageValue(WXPayContants.appId, WXPayContants.partnerKey, prepayId);
System.out.println("jsParam=" + jsParam);
// 此处可以添加订单的处理逻辑
model.addAttribute("jsParam", jsParam);
logger.info("生成的微信调起JS参数为:" + jsParam); payFlowCargoSource.setPrepayId(prepayId);
spPayFlowCargoSourceService.savePayFlow(payFlowCargoSource); return LeeJSONResult.ok();
} else {
return LeeJSONResult.errorMsg("微信支付接口调用失败");
}
} catch (Exception e) {
e.printStackTrace();
return LeeJSONResult.errorException(e.getMessage());
}
}

需要注意的是,微信后台接受的参数都是xml格式的,所以咱们的bean需要转换为xml再传给微信,最后调用成功,微信会封装一个xml传过来,咱们同样再解析一下获取预付单号就OK了

public String submitXmlGetPrepayId() {
// 创建HttpClientBuilder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// HttpClient
CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
HttpPost httpPost = new HttpPost(unifiedorder);
String xml = getPackage();
StringEntity entity;
try {
entity = new StringEntity(xml, "utf-8");
httpPost.setEntity(entity);
HttpResponse httpResponse;
// post请求
httpResponse = closeableHttpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
// 打印响应内容
String result = EntityUtils.toString(httpEntity, "UTF-8");
System.out.println(result);
// 过滤
result = result.replaceAll("<![CDATA[|]]>", "");
String prepay_id = Jsoup.parse(result).select("prepay_id").html();
this.prepay_id = prepay_id;
if (prepay_id != null) {
return prepay_id;
}
}
// 释放资源
closeableHttpClient.close();
} catch (Exception e) {
e.printStackTrace();
}
return prepay_id;
}

其实不用这样的方式也行,把bean通过json的方式封装,最后让它自动转为xml,也是没有问题的,或者直接使用 restful webservice标准协议来接受xml和发送xml

最新文章

  1. USACO翻译:USACO 2012 JAN三题(2)
  2. VS调试技巧,提高调试效率(转):
  3. apache限制同一ip大并发访问及下载
  4. 基于s5pv210嵌入式linux系统sqlite3数据库移植
  5. 黑马程序员——Objective-c特性
  6. web前端—工作周报
  7. 本地化web开发的一个例子-jquery.i18n.properties
  8. UVALive 5903 Piece it together
  9. iptables/mysql设置指定主机访问指定端口
  10. 我想要革命想要解脱——bootstrap常见问题及解决方式
  11. [EXP]Memu Play 6.0.7 - Privilege Escalation
  12. 【微信公众号开发】【13】批量导出公众号所有用户信息到Excel
  13. scala 学习笔记二 方法与函数
  14. java timer timertask mark
  15. sort给文件按照大小排序
  16. 查看mysql的版本和端口号
  17. PIE SDK栅格拉伸渲染
  18. 数据库 简单查询 Sql Server 学生表 课程表 选课表
  19. 剑指Offer的学习笔记(C#篇)-- 求1+2+3+...+n
  20. hihoCoder 扩展二进制数

热门文章

  1. jQuery css3鼠标悬停图片显示遮罩层动画特效
  2. [WCF编程]11.错误:错误类型
  3. C#模拟Http请求时出现 基础连接已经关闭 未能为 SSLTLS 安全通道建立信任关系
  4. 编程模式之模板方法模式(Template Method)
  5. 如何寻找&ldquo;真爱&rdquo;型合伙人
  6. 为什么你不应该使用 MongoDB
  7. .NET破解之百度云盘分享工具(批量)
  8. 两种方法设置disabled属性
  9. Linux常用命令:文件与目录
  10. IOS RunLoop浅析 二