首先,你得先有微信开发平台账号密码还需要开通应用,然后还有微信服务商平台商户版账号(这些我都是给产品经理拿的)

其次我认为你先去看一看微信开发平台的文档!  https://pay.weixin.qq.com/wiki/doc/api/index.html

这里有很多种支付,我就采用APP支付来说了(会了APP支付其实H5支付都差不多的!)

进来后是这样的,随便看看'APP支付那几篇文章'讲的流程!,看完后知道大概了就可以看看'API列表了'

我们后台开发需要关注的就是这三个API了!

那我还是简单介绍一下APP支付的一个业务流程吧(其实文档里简述的了,我就直接贴图了!)

这些圈圈起来的流程步骤,就是我们后台要做的了,其他的都是由移动端来实现的,我们可以不理会,还有步骤6查询订单支付结果,这个可做可不做吧,为了系统更安全些更慎重些也可以去实现,不过我就没有实现了

下面就说一下如何对接这个所谓的第三方接口,其实就是跟前端来调用我们后端接口是一样的,我们在写接口文档时,有请求地址,请求参数,返回数据以及返回数据格式这4样!

只要提供这4种东西,前端就可以来对接我们后台接口啦!所以,同个道理的,这次是由我们后台人员去请求微信提供的接口!

所以文档上都有提供的了,我们只需要用httpclient来想微信接口那边发送同步请求获取返回结果数据即可,这样听起来貌似很简单!不过还真不是很简单,很多坑的,毕竟是腾讯的文档!

然后要注意的首先是请求参数,请求参数是否必填这个如果是否的话我就建议不用填上去了,然后签名参数也要去看文档,如何生成签名,还有,参数是要以xml格式形式发送过去,

而且返回结果也是以xml返回回来,所以和微信对接的交互就是xml,这点有点蛋疼呀!

好了,上面说了该怎么去请求第三方接口,想必大家有点懵吧,不知道该如何下手,其实上面的那个请求方式有点难度,小白可以忽略上面那套方式,直接使用微信支付的一个开源jar!

对 你没看错,就这一个,这个jar包里面已经封装好了我们如何获取签名,如何验签等api方法,而且还不需要我们去将参数转化成xml格式,它已经封装好了一切了,所以非常方便!

这个jar包可以在这个地址去下载http://www.mvnjar.com/com.github.liyiorg/weixin-popular/2.8.14/detail.html

好了,那上面的介绍看完还有微信jar拿到手后,现在就可以开始来实现了! 我就直接亮代码了!

  1 /**
2 * @description:微信支付JAVA-SDK: APP支付,退款
3 * @author:小黑
4 */
5 @Service
6 public class WechatPayService {
7 private static final Logger LOGGER = LoggerFactory.getLogger(WechatPayService.class);
8
9 /************ 微信开放平台配置 ***************/
10
11 /** APPID */
12 private static final String APPID = "";
13
14 /** 商户号 */
15 private static final String MCH_ID = "";
16
17 /** 密钥 */
18 private static final String PRIVATE_KEY = "";
19
20 /** 用户订单支付结果异步通知url */
21 private static final String NOTIFY_URL = "";
22
23 /** 商户支付证书路径 */
24 private static final String API_CLIENT_CERT_PATH = "";
25
26 // 加载商户支付证书文件;
27 static {
28 LocalHttpClient.initMchKeyStore(MCH_ID, API_CLIENT_CERT_PATH);
29 }
30
31 /**
32 * @description:使用微信支付-APP支付方式-统一下单;
33 * @return 支付参数,如果支付失败则返回null
34 * @author:Fanhaojian
35 */
36 public MchPayApp orderAppPay(PayLog payLog) {
37
38 Unifiedorder unifiedorder = new Unifiedorder();
39
40 /** APPID */
41 unifiedorder.setAppid(APPID);
42
43 /** 商户号 */
44 unifiedorder.setMch_id(MCH_ID);
45
46 /** 随机字符串 */
47 unifiedorder.setNonce_str(UUID.randomUUID().toString().replaceAll("-", ""));
48
49 /** 商品描述 */
50 unifiedorder.setBody(payLog.getPayCode());
51
52 /** 商户订单号 */
53 unifiedorder.setOut_trade_no(payLog.getPayCode());
54
55 /** 订单总金额 */
56 unifiedorder.setTotal_fee(payLog.getPayPrice().multiply(new BigDecimal(100)).intValue() + ""); // 订单总金额,单位为分;
57
58 /** 用户端请求IP地址 */
59 unifiedorder.setSpbill_create_ip(IpUtils.getClientIp());
60
61 /** 异步通知回调地址 */
62 unifiedorder.setNotify_url(NOTIFY_URL);
63
64 /** 交易类型 */
65 unifiedorder.setTrade_type("APP");
66
67 LOGGER.warn("微信APP支付--(签名前):" + XMLConverUtil.convertToXML(unifiedorder));
68
69 /** 获取签名 */
70 UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder, PRIVATE_KEY);
71
72 LOGGER.warn("微信APP支付--支付统一下单接口请求状态(return_code):" + unifiedorderResult.getReturn_code());
73 LOGGER.warn("微信APP支付--支付统一下单接口请求状态(return_msg):" + unifiedorderResult.getReturn_msg());
74 LOGGER.warn("微信APP支付--支付统一下单接口请求状态(result_code):" + unifiedorderResult.getResult_code());
75 LOGGER.warn("微信APP支付--支付请求参数封装(签名后):" + XMLConverUtil.convertToXML(unifiedorder));
76 LOGGER.warn("微信APP支付--支付统一下单接口返回数据:" + FastJSONUtils.getJsonHelper().toJSONString(unifiedorderResult));
77
78 // 下单结果验签;
79 if(unifiedorderResult.getSign_status() != null && unifiedorderResult.getSign_status()) {
80 LOGGER.warn("微信APP支付验签成功");
81 return PayUtil.generateMchAppData(unifiedorderResult.getPrepay_id(), APPID, MCH_ID, PRIVATE_KEY);
82 }
83 return null;
84 }
85
86 /**
87 * @description:微信退款业务封装(支付押金退还);
88 * @param   PayLog order:支付订单信息
89 * Double refundAmount:退款金额
90 * @return 微信退款接口返回数据 true 退款成功 false 退款失败
91 * @author:FanHaoJian
92 */
93 public Boolean refundOrder(PayLog order, Double refundAmount) {
94
95 // 调用微信支付退款接口;
96 SecapiPayRefund payRefund = new SecapiPayRefund();
97 payRefund.setAppid(APPID);
98 payRefund.setMch_id(MCH_ID);
99 payRefund.setNonce_str(UUID.randomUUID().toString().replaceAll("-", ""));
100 payRefund.setOut_trade_no(order.getPayCode());//支付订单号
101 payRefund.setOut_refund_no(order.getRefundCode());//退款单号
102 payRefund.setTotal_fee(order.getPayPrice().multiply(new BigDecimal(100)).intValue());//原订单金额,单位:分;
103 payRefund.setRefund_fee(new BigDecimal(refundAmount).multiply(new BigDecimal(100)).intValue());//退款订单金额,单位:分;
104
105 SecapiPayRefundResult refundResult = PayMchAPI.secapiPayRefund(payRefund, PRIVATE_KEY);
106
107 // 微信支付退款接口返回数据验签;
108 if(refundResult.getSign_status() != null && refundResult.getSign_status()) {
109 LOGGER.warn("微信退款接口--接口请求状态(return_code):" + refundResult.getReturn_code());
110 LOGGER.warn("微信退款接口--接口请求状态(return_msg):" + refundResult.getReturn_msg());
111
112 // 退款信息提交成功;
113 if("SUCCESS".equals(refundResult.getReturn_code())) {
114 LOGGER.warn("微信退款接口--接口请求状态(result_code):" + refundResult.getResult_code());
115 LOGGER.warn("微信退款接口--接口请求状态(err_code):" + refundResult.getErr_code());
116 LOGGER.warn("微信退款接口--接口请求状态(err_code_des):" + refundResult.getErr_code_des());
117
118 return Boolean.TRUE;
119 }
120 }
121
122 return Boolean.FALSE;
123 }
124 }

在项目建一个sdk包,然后统一放入sdk,类似这样!

然后创建一个微信支付SDK,将上面代码复制过去,然后看一遍代码里的方法流程,看明白后在改改里面的代码!

然后我简单介绍一下上面的微信支付SDK吧,里面有两个方法,一个是统一下单,一个是退款!

统一下单返回的数据就是要拿给移动端的签名数据,退款返回的数据就是true和false,没什么判断成功还是失败就行了,成功该做什么,失败该做什么!

OK! 现在说完了统一下单和退款后,还有一个支付通知结果的API,也就是异步通知了!如果你看完了那篇流程图,你就会知道,当移动端调起支付并且支付成功后,微信后台那边会向我们这边后台发送一个请求过来!

当然微信那边发送请求过来我们这边的接口,我也直接亮代码了!

 1 /**
2 * @description:微信支付异步通知请求URL
3 * @author:小黑
4 */
5 public class WechatOrderNotify extends ActionSupport {
6 private static final Logger LOGGER = LoggerFactory.getLogger(WechatOrderNotify.class);
7 private static final long serialVersionUID = 1L;
8
9 /** 密钥 */
10 private static final String PRIVATE_KEY = "";
11
12 /** 定义应答变量 */
13 private String xml;
14
15 @Override
16 public String wechatOrderNotify() throws Exception {
17
18 // 解析微信支付异步通知请求参数;
19 HttpServletRequest request = ServletActionContext.getRequest();
20 String xml = StreamUtils.copyToString(request.getInputStream(), Charset.forName("utf-8"));
21 Map<String, String> params = XMLConverUtil.convertToMap(xml);
22 MchPayNotify payNotify = XMLConverUtil.convertToObject(MchPayNotify.class, xml);
23
24 /** 打印日志信息 */
25 LOGGER.warn("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$---进入微信支付异步通知请求接口---$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
26 LOGGER.warn("微信支付用户订单支付结果异步通知请求参数(xml):" + params);
27 LOGGER.warn("微信支付用户订单支付结果异步通知请求参数(map):" + params);
28 LOGGER.warn("return_code:" + payNotify.getReturn_code());
29 LOGGER.warn("return_msg:" + params.get("return_msg"));
30
31 /** 校验支付成功还是失败 */
32 if("SUCCESS".equals(payNotify.getReturn_code())) {
33
34 /** 获取微信后台返回来的异步通知参数 */
35 String outTradeNo = payNotify.getOut_trade_no(); // 用户订单号;
36 String tradeNo = payNotify.getTransaction_id(); // 微信交易号;
37 String tradeStatus = payNotify.getResult_code(); // 微信支付状态;
38 Integer totalFee = payNotify.getTotal_fee(); // 支付金额
39
40 /** 获取验签结果 true说明验签成功 false说明验签失败 */
41 boolean flag = SignatureUtil.validateSign(params, PRIVATE_KEY);
42
43 /** 打印日志信息 */
44 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知订单号(out_trade_no):" + outTradeNo);
45 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知交易号(trade_no):" + tradeNo);
46 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知交易状态(result_code):" + tradeStatus);
47 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知支付金额(total_fee):" + totalFee);
48 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知验签状态:" + flag);
49
50 /** 根据订单号获取订单支付信息: 支付状态为 '未支付' */
51 ...此处省略 根据订单号去查订单 我用hibernate的 你们可能用mybatis或者其他,所以自己去查吧!
52
53 /** 支付成功/处理订单业务信息 */
54 if(flag && "SUCCESS".equals(tradeStatus) && order != null) {
55
56 /** 更新订单支付信息: */
57 ...此处省略 根据自己项目的业务去处理逻辑!
58
59 /** 封装通知信息 */
60 MchBaseResult baseResult = new MchBaseResult();
61 baseResult.setReturn_code("SUCCESS");
62 baseResult.setReturn_msg("OK");
63 xml = XMLConverUtil.convertToXML(baseResult);
64
65 /** 支付成功 */
66 }else if(flag && "SUCCESS".equals(tradeStatus)){
67 MchBaseResult baseResult = new MchBaseResult();
68 baseResult.setReturn_code("SUCCESS");
69 baseResult.setReturn_msg("OK");
70 xml = XMLConverUtil.convertToXML(baseResult);
71
72 /** 支付失败 */
73 }else {
74 MchBaseResult baseResult = new MchBaseResult();
75 baseResult.setReturn_code("FAIL");
76 baseResult.setReturn_msg("FAIL");
77 xml = XMLConverUtil.convertToXML(baseResult);
78 }
79
80 /** 支付失败 */
81 }else {
82 MchBaseResult baseResult = new MchBaseResult();
83 baseResult.setReturn_code("FAIL");
84 baseResult.setReturn_msg("FAIL");
85 xml = XMLConverUtil.convertToXML(baseResult);
86 }
87 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知返回数据:" + xml);
88 return Results.XML;
89 }
90
91 public String getXml() {
92 return xml;
93 }
94
95 public void setXml(String xml) {
96 this.xml = xml;
97 }
98 }

这里也是直接招搬过去,然后改改代码即可!需要注意的就是这个返回数据xml,你可能要自己定义一下,应答是要这种格式的:

APP支付 + 退款(JAVA实现)的更多相关文章

  1. 微信APP支付(基于Java实现微信APP支付)

    步骤: 导入maven依赖 <!--微信支付--> <dependency> <groupId>com.github.wxpay</groupId> & ...

  2. 支付宝APP支付之Java后台生成签名具体步骤

    /** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoB ...

  3. 微信APP支付(Java后台生成签名具体步骤)

    public class PayCommonUtil { //定义签名,微信根据参数字段的ASCII码值进行排序 加密签名,故使用SortMap进行参数排序 public static String ...

  4. 支付宝APP支付(基于Java实现支付宝APP支付)

    贴一下支付核心代码,以供后续参考: 业务层 import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; ...

  5. 支付宝APP支付(Java后台生成签名具体步骤)

    /** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoB ...

  6. JAVA支付宝和微信(APP支付,提现,退款)

    公共参数图表:       接口 需要参数 通知方式 支付宝APP支付 应用公钥,应用私钥 异步 支付宝APP提现 应用公钥,应用私钥,支付宝公钥 同步 支付宝APP退款 应用公钥,应用私钥,支付宝公 ...

  7. Java 支付宝支付,退款,单笔转账到支付宝账户(支付宝支付)

    最近一直在接触第三方,刚接入完支付宝的API做一下总结,个人能力薄弱有不对的地方望指教.  做的是一个小型电商项目,所以会接入第三方的支付和登入功能, 第一次接入第三方撸了很多官方文档. 进入主题, ...

  8. 微信支付(公众号支付APIJS、app支付)服务端统一下单接口java版

    一.微信公众号支付APIJS: 要完整的实现微信支付功能,需要前后端一起实现,还需要微信商户平台的配置.这里只是涉及服务端的代码. jar包:pom.xml <!-- ↓↓↓↓↓↓↓↓ 支付相关 ...

  9. 支付宝app支付java后台流程、原理分析(含nei wang chuan tou)

    java版支付宝app支付流程及原理分析 本实例是基于springmvc框架编写     一.流程步骤         1.执行流程           当手机端app(就是你公司开发的app)在支付 ...

随机推荐

  1. July 21st 2017 Week 29th Friday

    If you want to fly too high in relation to the horizon forget. 要想飞得高,就该把地平线忘掉. Always keep our eyes ...

  2. python 时间和时间戳的转化

    时间戳与时间之间的转换,需要一个中间过程,即将先将时间或时间戳先转为时间元组! 1.时间转时间戳: import datetime, time s = datetime.datetime(2016,6 ...

  3. PHP时间戳和日期相互转换(转载)

    在php中我们要把时间戳转换日期可以直接使用date函数来实现,如果要把日期转换成时间戳可以使用strtotime()函数实现,下面我来给大家举例说明. 1.php中时间转换函数 strtotime ...

  4. jquery分页例子

    先看效果图: 实现原理很简单,使用了jquery.pagination这个插件,每当点击页码时异步去服务器去取该页的数据,简单介绍如下: 一.数据库表结构:很简单  就四个字段 分别是News_id  ...

  5. CssSelector之selenium元素定位

    CssSelector是我最喜欢的元素定位方法,Selenium官网的Document里极力推荐使用CSS locator,而不是XPath来定位元素,原因是CSS locator比XPath loc ...

  6. 自定义属性之LinearLayout ImageView TextView模拟图片文字按钮

    一.资源文件: 1.文字选择器: <?xml version="1.0" encoding="utf-8"?> <selector xmlns ...

  7. HDU 2031 进制转换(10进制转R进制)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=2031 进制转换 Time Limit: 2000/1000 MS (Java/Others)    M ...

  8. 关于ligerui grid 行内编辑 combobox 只能选择的问题

    这个貌似是天然的不支持,修复方案,在ligerGridOrd.js中添加一行代码,如下,跟了一下午的源码,发现在这里的时候,options中只保留了combobox中的一部分属性,所以可能combob ...

  9. Notes 20180308 : 语句

    在讲解流程控制语句之前,我们先来说一下语句的问题.Java中的语句分为声明和赋值语句,条件和循环语句,调用和返回语句:我们之所以每两个放在一起是有深意的,我们大致将语句分为这三块,并以此为纲来说一下, ...

  10. DQL-常见的函数

    一.概述功能:类似于java中的方法好处:提高重用性和隐藏实现细节调用:select 函数名(实参列表); 二:常用的函数: ① 单行函数 1.分组函数 1.sum(),avg(),max(),min ...