您的位置:首页 > 移动开发 > 微信开发

微信公众号开发---微信支付(JS API) JAVA

2016-09-04 18:20 609 查看
基于微信支付文档V3.3.7进行编码,使用JS API(网页内)并测试通过,应用在项目中。

Form:

[java] view
plain copy

public class PayForm extends BaseForm{

private String code; //通过code换取微信的openid,谁支付的

private Integer transactionID; //交易ID

private String appId; //公众账号ID

private String timeStamp; //时间戳

private String nonceStr; //随机字符串

private String packages; //订单详情扩展字符串

private String paySign; //签名

private String openid; //微信openid

private Integer masterOrderID; //订单ID

//set get

}

请求支付的Action:

[java] view
plain copy

@ParentPackage("main")

@Namespace("/pay")

@Controller

public class PayAction extends BaseAction{

private PayForm form;

@Resource

private TransactionService transactionService;

@Action(value = "weChatPay",

results = {

@Result(name = SUCCESS, location = "/html/transaction/jsp/weChatPay.jsp"),

@Result(name = ERROR , location = "/html/common/errors/sys_error.jsp")}

)

public String weChatPay(){

SystemLogger.info("用户请求支付订单号:"+form.getTransactionID());

if (StringUtils.isNotEmpty(form.getCode())) {

String url = WeixinUtil.getUrl().replace("CODE", form.getCode());

String openid ="";

try {

Map<String, Object> map = JsonUtil.getMapByUrl(url);

openid = map.get("openid").toString();

form.setOpenid(openid);

} catch (Exception e) {

SystemLogger.info("用户请求支付订单号:"+form.getTransactionID()+"时拉取微信用户信息失败");

}

try {

transactionService.createWeChatRequest(form);

return SUCCESS;

} catch (BusinessException e) {

SystemLogger.error(e.getMessage());

form.setMessage(e.getMessage());

return ERROR;

}

}else{

SystemLogger.info("用户请求支付订单号:"+form.getTransactionID()+"的链接为非法链接,已拒绝");

form.setMessage("请通过合法链接进行订单支付");

return ERROR;

}

}

@Override

public Object getModel() {

if(form==null){

form = new PayForm();

}

return form;

}

}

微信支付结果回调请求的Action:

[java] view
plain copy

@ParentPackage("main")

@Namespace("/pay")

@Controller

public class NotifyAction {

@Resource

private TransactionService transactionService;

@Action(value = "notify",

results = {

@Result(name = "success", type = "plainText",params = { "charSet", "UTF-8"})},

interceptorRefs = { @InterceptorRef("defaultStack")}

)

public String weChatNotify(){

Map<String, String> requestMap = null;

SortedMap<String, String> returnMap = new TreeMap<String, String>();

String requestXML = "";

try {

requestMap = TenPayUtil.parseXml(ServletActionContext.getRequest());

SystemLogger.info("接收到的微信支付回调通知:"+requestMap.toString());

SortedMap<String, String> map = new TreeMap<String, String>();

map.putAll(requestMap);

String weixinSign = map.get("sign");

map.remove("sign");

String sign = TenPayUtil.sign(map, WeixinUtil.partnerKey);

if(!sign.equals(weixinSign)){

SystemLogger.info("签名失败");

returnMap.put("return_code", "FAIL");

returnMap.put("return_msg", "签名失败");

requestXML = TenPayUtil.getRequestXml(returnMap);

}else{

try {

//更新订单的状态等等操作...

returnMap.put("return_code", "SUCCESS");

requestXML = TenPayUtil.getRequestXml(returnMap);

} catch (BusinessException e) {

SystemLogger.info(e.getMessage());

returnMap.put("return_code", "FAIL");

returnMap.put("return_msg", "签名失败");

requestXML = TenPayUtil.getRequestXml(returnMap);

}

}

} catch (Exception e) {

SystemLogger.info("转换微信请求参数错误");

returnMap.put("return_code", "FAIL");

returnMap.put("return_msg", "转换微信请求参数错误");

requestXML = TenPayUtil.getRequestXml(returnMap);

}

try{

PrintWriter out = ServletActionContext.getResponse().getWriter();

out.print(requestXML);

out.flush();

out.close();

}catch(Exception ex){

}

return "success";

}

}

Service:

[java] view
plain copy

@Transactional

@Service(value = "transactionService")

public class TransactionServiceImpl implements TransactionService{

<span style="white-space:pre"> </span>.......

@Override

public void createWeChatRequest(PayForm form) throws BusinessException {

Transaction po = this.getTransactionByID(form.getTransactionID());

String shopOrderIDs = po.getMuiltFlag().equals("1") ? po.getRelateIDs() : po.getRelateID().toString();

MasterOrder order = masterorderService.getMasterOrderByShopOrderIDs(shopOrderIDs);

if(order.getPayFlag() == 1){

throw new BusinessException("该笔订单已支付");

}else{

form.setMasterOrderID(order.getMasterOrderID());

String payTypeID = po.getPayTypeID().toString();

if(AppKeys.PAY_TYPE_ID_WECHAT.equals(payTypeID)){

//请求参数按参数名称大小进行排序

SortedMap<String, String> params = createSortedMap(form,po);

//签名

String sign = TenPayUtil.sign(params, WeixinUtil.partnerKey);

params.put("sign", sign);

//生成xml格式

String requestXML = TenPayUtil.getRequestXml(params);

//获取证书

HttpServletRequest request = ServletActionContext.getRequest();

InputStream instream = request.getSession().getServletContext().getResourceAsStream("/WEB-INF/weixinCert/apiclient_cert.p12");

String responseXML;

try {

//创建微信订单返回结果

responseXML = TenPayUtil.post(WeixinUtil.CREATE_ORDER_URL,WeixinUtil.partner,requestXML,instream);

Map<String,String> resultMap = XmlUtil.parseXml(responseXML);

String return_code = resultMap.get("return_code").toString();

if(return_code.equals("SUCCESS")){

//创建微信订单成功,获取微信预支付订单ID

String prepay_id = (String) resultMap.get("prepay_id");

SortedMap<String, String> finalpackage = new TreeMap<String, String>();

String prepay_id2 = "prepay_id="+prepay_id;

String packages = prepay_id2;

String timeStamp = TenPayUtil.getTimeStamp();

String nonceStr = TenPayUtil.createNonceStr();

finalpackage.put("appId", WeixinUtil.appId);

finalpackage.put("timeStamp", timeStamp);

finalpackage.put("nonceStr", nonceStr);

finalpackage.put("package", packages);

finalpackage.put("signType", "MD5");

//签名

sign = TenPayUtil.sign(finalpackage, WeixinUtil.partnerKey);

form.setAppId(WeixinUtil.appId);

form.setTimeStamp(timeStamp);

form.setPaySign(sign);

form.setNonceStr(nonceStr);

form.setPackages(packages);

}else{

throw new BusinessException("统一支付接口获取预支付订单出错");

}

}catch (Exception e) {

e.printStackTrace();

SystemLogger.info(e.getMessage());

throw new BusinessException("支付异常");

}

}else{

throw new BusinessException("手机端仅支持微信支付");

}

}

}

private SortedMap<String, String> createSortedMap(PayForm form,Transaction po){

//公众账号ID

String appId = WeixinUtil.appId;

//商户号

String partner = WeixinUtil.partner;

//当前时间

String currTime = TenPayUtil.getCurrTime();

//8位日期

String strTime = currTime.substring(8, currTime.length());

//四位随机数

String strRandom = TenPayUtil.getRandomNum(4);

//10位序列号,可以自行调整。

String strReq = strTime + strRandom;

//商户号

String mch_id = partner;

//子商户号 非必输

String sub_mch_id="";

//设备号 非必输

String device_info="";

//随机字符串

String nonce_str = strReq;

//商品描述

String body = po.getTitle();

//附加数据

String attach = "测试";

//商户订单号

String out_trade_no = po.getTransactionID().toString();

int intMoney = (int)(po.getAmount()*100);

//总金额以分为单位,不带小数点

int total_fee = intMoney;

//订单生成的机器 IP

String spbill_create_ip = ServletActionContext.getRequest().getRemoteAddr();

//订 单 生 成 时 间 非必输

String time_start = currTime;

//订单失效时间 非必输

String time_expire = "";

//商品标记 非必输

String goods_tag = "";

//这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。

String notify_url =WeixinUtil.notifyURL;

//交易类型

String trade_type = "JSAPI";

//用户标识

String openid = form.getOpenid();

//非必输

String product_id = "";

SortedMap<String, String> packageParams = new TreeMap<String, String>();

packageParams.put("appid", appId);

packageParams.put("mch_id", mch_id);

packageParams.put("nonce_str", nonce_str);

packageParams.put("body", body);

packageParams.put("attach", attach);

packageParams.put("out_trade_no", out_trade_no);

packageParams.put("total_fee", total_fee+"");

packageParams.put("spbill_create_ip", spbill_create_ip);

packageParams.put("notify_url", notify_url);

packageParams.put("trade_type", trade_type);

packageParams.put("openid", openid);

return packageParams;

}

<span style="white-space:pre"> </span>......

}

TenPayUtil:

[java] view
plain copy

public class TenPayUtil {

/**

* 对请求参数名ASCII码从小到大排序后签名

* @param openid

* @param userId

* @return

*/

public static String sign(SortedMap<String, String> params,String KEY){

Set<Entry<String,String>> entrys=params.entrySet();

Iterator<Entry<String,String>> it=entrys.iterator();

StringBuffer result = new StringBuffer();

while(it.hasNext())

{

Entry<String,String> entry=it.next();

result.append(entry.getKey())

.append("=")

.append(entry.getValue())

.append("&");

}

result.append("key=").append(KEY);

SystemLogger.info(result.toString());

String sign = "";

try {

sign = MD5Util.MD5(result.toString());

} catch (Exception e) {

e.printStackTrace();

}

return sign.toString().toUpperCase();

}

public static String getRequestXml(SortedMap<String,String> params){

StringBuffer sb = new StringBuffer();

sb.append("<xml>");

Set es = params.entrySet();

Iterator it = es.iterator();

while(it.hasNext()) {

Map.Entry entry = (Map.Entry)it.next();

String k = (String)entry.getKey();

String v = (String)entry.getValue();

if ("body".equalsIgnoreCase(k)||"attach".equalsIgnoreCase(k)||"goodstag".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {

sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");

}else {

sb.append("<"+k+">"+v+"</"+k+">");

}

}

sb.append("</xml>");

return sb.toString();

}

/**

* 生成随机字符串

* @return

*/

public static String createNonceStr() {

return UUID.randomUUID().toString().toUpperCase().replace("-", "");

}

/**

* 获取当前日期 yyyyMMdd

*

* @param date

* @return String

*/

public static String getCurrTime() {

SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");

String strDate = formatter.format(new Date());

return strDate;

}

/**

* 生成特定位数的随机数字

* @param length

* @return

*/

public static String getRandomNum(int length) {

String val = "";

Random random = new Random();

for (int i = 0; i < length; i++) {

val += String.valueOf(random.nextInt(10));

}

return val;

}

/**

* 获取时间戳

* @return

*/

public static String getTimeStamp() {

return String.valueOf(System.currentTimeMillis() / 1000);

}

/**

*

* @param url 请求URL

* @param MCH_ID 商户号

* @param requestXML 请求参数

* @param instream 证书流

* @return

* @throws NoSuchAlgorithmException

* @throws CertificateException

* @throws IOException

* @throws KeyManagementException

* @throws UnrecoverableKeyException

* @throws KeyStoreException

*/

public static String post(String url,String MCH_ID,String requestXML,InputStream instream) throws NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, UnrecoverableKeyException, KeyStoreException{

KeyStore keyStore = KeyStore.getInstance("PKCS12");

try {

keyStore.load(instream, MCH_ID.toCharArray());

} finally {

instream.close();

}

SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, MCH_ID.toCharArray()).build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(

sslcontext,

new String[] { "TLSv1" },

null,

SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

String result = "";

try {

HttpPost httpPost = new HttpPost(url);

StringEntity reqEntity = new StringEntity(requestXML,"UTF-8");

reqEntity.setContentType("application/x-www-form-urlencoded");

httpPost.setEntity(reqEntity);

CloseableHttpResponse response = httpclient.execute(httpPost);

try {

HttpEntity entity = response.getEntity();

if (entity != null) {

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));

String text;

while ((text = bufferedReader.readLine()) != null) {

result +=text;

}

}

EntityUtils.consume(entity);

} finally {

response.close();

}

} finally {

httpclient.close();

}

return result;

}

/**

* 解析微信发来的请求(XML)

*

* @param request

* @return

* @throws Exception

*/

@SuppressWarnings("unchecked")

public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {

// 将解析结果存储在HashMap中

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

// 从request中取得输入流

InputStream inputStream = request.getInputStream();

// 读取输入流

SAXReader reader = new SAXReader();

Document document = reader.read(inputStream);

// 得到xml根元素

Element root = document.getRootElement();

// 得到根元素的所有子节点

List<Element> elementList = root.elements();

// 遍历所有子节点

for (Element e : elementList)

map.put(e.getName(), e.getText());

// 释放资源

inputStream.close();

inputStream = null;

return map;

}

}

weChatPay.jsp

[html] view
plain copy

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%@ include file="/html/common/taglibs.jsp"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" >

<title>订单支付</title>

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

<meta name="apple-mobile-web-app-capable" content="yes">

<meta name="apple-mobile-web-app-status-bar-style" content="black">

<link rel="stylesheet" href="<s:url value='/html/css/common/common.css' />" >

<link rel="stylesheet" href="<s:url value='/html/css/index.css' />" >

</head>

<body>

<div class="content">

<a href="javascript:callpay();" class="payment">微信支付</a>

<hr>

<img src="<s:url value='/html/images/logo.svg' />" class="logo">

</div>

<script type="text/javascript">

var clicked = !1; // false

function callpay() {

if (clicked) return false;

clicked = !0; // true

WeixinJSBridge.invoke('getBrandWCPayRequest', {

"appId" : "${appId}",

"timeStamp" : "${timeStamp}",

"nonceStr" : "${nonceStr}",

"package" : "${packages}",

"signType" : "MD5",

"paySign" : "${paySign}"

}, function(res) {

WeixinJSBridge.log(res.err_msg);

if (res.err_msg == "get_brand_wcpay_request:ok") {

window.location.href = "../pay/payResult.action?transactionID=${transactionID}&masterOrderID=${masterOrderID}";

} else if (res.err_msg == "get_brand_wcpay_request:cancel") {

clicked = !1; // false

window.location.href = "../pay/payResult.action?message=crm.pay.cancel";

} else {

clicked = !1; // false

window.location.href = "../pay/payResult.action?message=crm.pay.error";

}

})

}

</script>

</body>

</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: