1.借鉴
微信支付开发者文档,还有很多其他的博客,十分感谢。
2. 开始
【
具体的流程:
1.小程序调用我们自己的创建订单接口,然后拼接参数发给微信,微信会返回给我们成功或失败,如果成功,按照微信开发文档拼接map参数返回给小程序[①]
2:请求1中的接口返回给小程序一个map集合,[②]
3.小程序将map发送到微信,[③]
4.等待和处理微信回调[④]
】
以上序号在下面有用到[①,②,③,④],谢谢搜狗输入法的支持.......
1. 搭建一个springboot项目
2. 几个依赖包
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
3. 后端准备
3.1 配置信息
# =============================================================================
# ========================= 微信小程序支付 ========================
# =============================================================================
# 小程序[mp -> mini program]
# 小程序ID
wx.pay.mp.appid=
# 商户号
wx.pay.mp.mch_id=
# 加密ID - 商户
wx.pay.mp.partnerkey=
# 加密ID - 小程序
wx.pay.mp.partnerkeyMp=
# 终端IP
wx.pay.mp.spbill_create_ip=127.0.0.1
# 用户支付时的回调URL【 TODO 这里需要变更】
wx.pay.mp.notify_url=http://ruihong.frpgz1.idcfengye.com/notify/wxNotify
# 统一下单URL
wx.pay.mp.wechatUnifiedOrderURL=https://api.mch.weixin.qq.com/pay/unifiedorder
# 查询订单URL
wx.pay.mp.wechatOrderQueryURL=https://api.mch.weixin.qq.com/pay/orderquery
# 企业付款URL【用户提现】
wx.pay.mp.wechatTransfersUrl=https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
# 申请退款【取消订单】
wx.pay.mp.wechatRefundUrl=https://api.mch.weixin.qq.com/secapi/pay/refund
# =============================================================================
3.2 springboot 配置类
@Component
@ConfigurationProperties(value = "wx.pay.mp")
@Getter @Setter
public class WeixinMiniProgramPayProperties
{
private String appid;
private String mchId;
private String spbillCreateIp;
private String notifyUrl;
private String refundUrl;
private String partnerkey;
private String partnerkeyMp;
private String wechatUnifiedOrderURL;
private String wechatOrderQueryURL;
private String wechatTransfersUrl;
private String wechatRefundUrl;
}
3.3 创建订单
[①,②][service] 返回的map就是要返给小程序的参数,控制器随意
public interface WeixinService
{
/*** * 创建小程序订单 */
Map createMiniProgramOrder(String logKey, /** 日志key */
String orderNumber, /** 订单号 */
String openId, /** 微信用户的openId */
String fee, /** 费用,单位分*/
String body /** 商品描述 */) throws Exception;
/*** * 企业向个人付款【提现】 */
Map enterprice2User(String logKey, String orderNumber, String openId, String fee, String body) throws Exception;
/** * 申请退款 */
Map refund(String logKey,
String refundOrderNumber, /** 申请退款时自己创建的订单号 */
String transactionId, /** 微信返回的交易ID */
String openId, /** 微信用户openId */
String fee /** 费用,单位分*/) throws Exception;
}
[impl][这里面有个httpclient,放后面吧part2中]
import com.github.wxpay.sdk.WXPayUtil;
import WeixinMiniProgramPayProperties;
import WeixinService;
import HttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.*;
@Service("weixinService")
public class WeixinServiceImpl implements WeixinService
{
private static final Logger logger = LoggerFactory.getLogger(WeixinServiceImpl.class);
@Autowired WeixinMiniProgramPayProperties weixinPayProperties;
@Override
public Map createMiniProgramOrder(String logKey,
String orderNumber,
String openId,
String fee,
String body) throws Exception
{
//1.参数封装
Map param = new HashMap();
param.put("appid", weixinPayProperties.getAppid());// 公众账号ID
param.put("mch_id", weixinPayProperties.getMchId());// 商户
param.put("nonce_str", WXPayUtil.generateNonceStr());// 随机字符串
param.put("body", body); // 商品描述
param.put("out_trade_no", orderNumber);// 交易订单号
param.put("total_fee", fee); // 金额(分)
param.put("spbill_create_ip", weixinPayProperties.getSpbillCreateIp()); // 终端IP
param.put("notify_url", weixinPayProperties.getNotifyUrl()); // 通知地址
param.put("openid", openId); // 用户openid
param.put("trade_type", "JSAPI"); // 交易类型
param.put("attach", body); // 附件说明
logger.info(logKey + " weixinPayProperties" + weixinPayProperties);
String sign = WXPayUtil.generateSignature(param, weixinPayProperties.getPartnerkey());
param.put("sign", sign);
logger.info(logKey + " weixinService#createMiniProgramOrder:" + param);
HttpClient httpClient = new HttpClient(weixinPayProperties.getWechatUnifiedOrderURL());
httpClient.setHttps(true);
httpClient.setXmlParam(xml2String(param));
httpClient.post(); String xmlResult = httpClient.getContent();
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
logger.info(logKey + " weixinService#createMiniProgramOrder.wxpay.mp.result:" + mapResult);
return reSigned(logKey, mapResult.get("prepay_id"));
}
private String xml2String(Map parameters)
{
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext())
{
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = entry.getValue()+"";
if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k))
{
sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
} else {
sb.append("<" + k + ">" + v + "</" + k + ">");
}
}
sb.append("</xml>");
return sb.toString();
}
private Map reSigned(String logKey, String prepay_id) throws Exception
{
Map map = new HashMap();
map.put("appId", weixinPayProperties.getAppid());
map.put("timeStamp", (System.currentTimeMillis()+"").substring(0, 10));
map.put("nonceStr", WXPayUtil.generateNonceStr());
map.put("package", "prepay_id=" + prepay_id);
map.put("signType", "MD5");
String sign = addSign(logKey, map);
map.put("paySign", sign);
logger.info(logKey + " weixinService#reSigned:" + map);
return map;
}
private String addSign(String logKey, Map hashMap2Sign) throws Exception
{
StringBuffer sign = new StringBuffer();
List<Map.Entry<Object, Object>> infoIds = new ArrayList<Map.Entry<Object, Object>>(hashMap2Sign.entrySet());
Collections.sort(infoIds, new Comparator<Map.Entry<Object, Object>>()
{
public int compare(Map.Entry<Object, Object> o1, Map.Entry<Object, Object> o2)
{
return (o1.getKey()).toString().compareTo((String) o2.getKey());
}
});
for(int i = 0;i < infoIds.size();i ++)
{
String key = (String) infoIds.get(i).getKey();
if(sign.length() == 0)
{
sign.append(key).append("=")
.append(hashMap2Sign.get(key).toString().toLowerCase());
}
else
{
sign.append("&").append(key)
.append("=").append(hashMap2Sign.get(key));
}
}
sign.append("&key="+weixinPayProperties.getPartnerkey());
logger.info(logKey + " addSign:" + sign.toString()); return
WXPayUtil.MD5(sign.toString()).toUpperCase();
}
}
3.4 微信回调类
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;import java.util.SortedMap;
import java.util.TreeMap;
@RestController
@RequestMapping(value = "/notify")
public class NotifyController
{
@RequestMapping("/wxNotify")
public String wxNotify(HttpServletRequest request,
HttpServletResponse response) throws Exception
{
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8"); r
esponse.setContentType("text/html;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", "*");
StringBuilder sb = new StringBuilder();
String line = "";
try
{
while ((line = request.getReader().readLine()) != null)
{
sb.append(line);
}
request.getReader().close();
} catch (Exception e)
{
e.printStackTrace();
return xml("fail","xml获取失败");
}
String result = sb.toString();
if (StringUtils.isEmpty(result))
{
return xml("fail","xml为空");
}
Map<String, String> stringStringMap = WXPayUtil.xmlToMap(result);
String total_fee = stringStringMap.get("total_fee");// 获取订单金额
String trade_type = stringStringMap.get("trade_type");//交易类型
String return_code = stringStringMap.get("return_code");// SUCCESS/FAIL
String attach = stringStringMap.get("attach");// 附件说明(消费,充值)
String transaction_id = stringStringMap.get("transaction_id");//微信支付订单号
String out_trade_no = stringStringMap.get("out_trade_no");// 获取商户订单号
if (!"SUCCESS".equalsIgnoreCase(return_code))
{
return xml("fail", "支付失败!");
}
// 尤其要注意的是要保证幂等性
// 从订单表中查询出数据
// 更新订单状态等等操作
// 操作用户积分,余额
return xml("SUCCESS", "OK");
}
//通过xml 发给微信消息
public String xml(String return_code, String return_msg)
{
SortedMap<String, String> parameters = new TreeMap<String, String>();
parameters.put("return_code", return_code);
parameters.put("return_msg", return_msg); return "<xml><return_code><![CDATA[" + return_code + "]]>" + "</return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
}
}
网友评论