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

微信支付(JS API) JAVA

2015-07-06 14:36 567 查看
基于微信支付文档V3.3.7进行编码,使用JS API(网页内)并测试通过,应用在项目中。

Form:

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:

@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:

@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:

@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:

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

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