微信支付——调用微信客户端支付之【服务端】开发详解

原文:http://blog.csdn.net/seven_cm/article/details/41559301

http://blog.csdn.net/seven_cm/article/details/50019927

2015-09-12 更新:

因微信支付已经升级到V3版本,请大家参考官网的帮助文档。

https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=1_2

之前一篇提到微信支付的开发过程,写得有点乱,现在重新整理一下。

好了,说说到底该怎样一步一步分享处理。

解压从官网下载下来的开发说明文档(下载地址:https://mp.weixin.qq.com/htmledition/res/bussiness-faq/wx_app_pay.zip):

先把服务端demo的代码整理到我们的服务端中(注意,此代码的编码格式是GBK,直接复制过去注释都会变乱码。可用文本文件打开后再复制过去)。处理完成后启动;且访问:http://localhost:8080/WeiXinpay/

会得到以下视图:

-------------------------------------------------------------------------------------------------------------

页面跳转调用:
获取支付prepayId

后台调用:

点击链接:

0OK wxd930ea5d5a258f4f 454cecc4829279e64d624cd8a8c9ddf1 Sign=WXPay 1900000109 120100001014112819a3561c0c02c882 eb139e44b8df8ce01b386f7c016defe5b95517791417104896

-------------------------------------------------------------------------------------------------------------

 

返回控制台可以得到以下视图:

好了,到这里,算是成功了一小步了(哈哈哈哈哈哈 yy一下)。

你也许会问,这些参数到底是作什么用的?更可悲的是,居然没有服务端的接口文档。

唯有先看手头上有的资料了。打开《【微信APP支付】接口文档V1.2_For_Android.pdf》

里面有提到微信支付的调用步骤:

1、获取  access_token

2、生成预支付订单

3、调起微信支付

下面说说这几个步骤:

1、access_token的获取

因为access_token的获取有请求频的限制,只能固化到数据库中了。这个不是难题。

2、生成预支付订单

在微信支付android的接口文档开头有提到:

注意:appsecret、appkey、partnerkey 不应硬编码到客户端程序中,建议需要用到这三个字段的过程都在服务器端完成

故此过程所有的信息全部在服务端生成。那么问题来了?挖掘机.... kao, 应该是,如何生成?

在翻看服务端的demo中,有jsp文件夹。打开一看,都几乎可以直接搬运使用了。

实现该过程的文件:payRequest.jsp

如何在JAVA中实现上面jsp的请求?项目中用到了Spring MVC,代码如下:

  1. @Controller  
  2. @RequestMapping("/weixin/")  
  3. public class WeiXinPayController extends ResponsePage  {  
  4.   
  5.     private Logger log = Logger.getLogger(WeiXinPayController.class);  
  6.       
  7.     @RequestMapping("weixin.do")  
  8.     public String doWeinXinRequest(HttpServletRequest request,HttpServletResponse response) throws Exception {  
  9.         Map<Object,Object> resInfo = new HashMap<Object, Object>();  
  10.         //接收财付通通知的URL  
  11.         String notify_url = "http://127.0.0.1:8180/tenpay_api_b2c/payNotifyUrl.jsp";  
  12.   
  13.         //---------------生成订单号 开始------------------------  
  14.         //当前时间 yyyyMMddHHmmss  
  15.         String currTime = TenpayUtil.getCurrTime();  
  16.         //8位日期  
  17.         String strTime = currTime.substring(8, currTime.length());  
  18.         //四位随机数  
  19.         String strRandom = TenpayUtil.buildRandom(4) + "";  
  20.         //10位序列号,可以自行调整。  
  21.         String strReq = strTime + strRandom;  
  22.         //订单号,此处用时间加随机数生成,商户根据自己情况调整,只要保持全局唯一就行  
  23.         String out_trade_no = strReq;  
  24.         //---------------生成订单号 结束------------------------  
  25.   
  26.         PackageRequestHandler packageReqHandler = new PackageRequestHandler(request, response);//生成package的请求类   
  27.         PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);//获取prepayid的请求类  
  28.         ClientRequestHandler clientHandler = new ClientRequestHandler(request, response);//返回客户端支付参数的请求类  
  29.         packageReqHandler.setKey(ConstantUtil.PARTNER_KEY);  
  30.   
  31.         int retcode ;  
  32.         String retmsg = "";  
  33.         String xml_body = "";  
  34.         //获取token值   
  35.           
  36.         String token = AccessTokenRequestHandler.getAccessToken();  
  37.           
  38.         log.info("获取token------值 " + token);  
  39.           
  40.         if (!"".equals(token)) {  
  41.             //设置package订单参数  
  42.             packageReqHandler.setParameter("bank_type", "WX");//银行渠道  
  43.             packageReqHandler.setParameter("body", "测试"); //商品描述     
  44.             packageReqHandler.setParameter("notify_url", notify_url); //接收财付通通知的URL    
  45.             packageReqHandler.setParameter("partner", ConstantUtil.PARTNER); //商户号      
  46.             packageReqHandler.setParameter("out_trade_no", out_trade_no); //商家订单号     
  47.             packageReqHandler.setParameter("total_fee", "1"); //商品金额,以分为单位    
  48.             packageReqHandler.setParameter("spbill_create_ip",request.getRemoteAddr()); //订单生成的机器IP,指用户浏览器端IP    
  49.             packageReqHandler.setParameter("fee_type", "1"); //币种,1人民币   66  
  50.             packageReqHandler.setParameter("input_charset", "GBK"); //字符编码  
  51.   
  52.             //获取package包  
  53.             String packageValue = packageReqHandler.getRequestURL();  
  54.             resInfo.put("package", packageValue);  
  55.               
  56.             log.info("获取package------值 " + packageValue);  
  57.   
  58.             String noncestr = WXUtil.getNonceStr();  
  59.             String timestamp = WXUtil.getTimeStamp();  
  60.             String traceid = "";  
  61.             ////设置获取prepayid支付参数  
  62.             prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID);  
  63.             prepayReqHandler.setParameter("appkey", ConstantUtil.APP_KEY);  
  64.             prepayReqHandler.setParameter("noncestr", noncestr);  
  65.             prepayReqHandler.setParameter("package", packageValue);  
  66.             prepayReqHandler.setParameter("timestamp", timestamp);  
  67.             prepayReqHandler.setParameter("traceid", traceid);  
  68.   
  69.             //生成获取预支付签名  
  70.             String sign = prepayReqHandler.createSHA1Sign();  
  71.             //增加非参与签名的额外参数  
  72.             prepayReqHandler.setParameter("app_signature", sign);  
  73.             prepayReqHandler.setParameter("sign_method",  
  74.                     ConstantUtil.SIGN_METHOD);  
  75.             String gateUrl = ConstantUtil.GATEURL + token;  
  76.             prepayReqHandler.setGateUrl(gateUrl);  
  77.   
  78.             //获取prepayId  
  79.             String prepayid = prepayReqHandler.sendPrepay();  
  80.               
  81.             log.info("获取prepayid------值 " + prepayid);  
  82.               
  83.             //吐回给客户端的参数  
  84.             if (null != prepayid && !"".equals(prepayid)) {  
  85.                 //输出参数列表  
  86.                 clientHandler.setParameter("appid", ConstantUtil.APP_ID);  
  87.                 clientHandler.setParameter("appkey", ConstantUtil.APP_KEY);  
  88.                 clientHandler.setParameter("noncestr", noncestr);  
  89.                 //clientHandler.setParameter("package", "Sign=" + packageValue);  
  90.                 clientHandler.setParameter("package", "Sign=WXPay");  
  91.                 clientHandler.setParameter("partnerid", ConstantUtil.PARTNER);  
  92.                 clientHandler.setParameter("prepayid", prepayid);  
  93.                 clientHandler.setParameter("timestamp", timestamp);  
  94.                 //生成签名  
  95.                 sign = clientHandler.createSHA1Sign();  
  96.                 clientHandler.setParameter("sign", sign);  
  97.   
  98.                 xml_body = clientHandler.getXmlBody();  
  99.                 resInfo.put("entity", xml_body);  
  100.                 retcode = 0;  
  101.                 retmsg = "OK";  
  102.             } else {  
  103.                 retcode = -2;  
  104.                 retmsg = "错误:获取prepayId失败";  
  105.             }  
  106.         } else {  
  107.             retcode = -1;  
  108.             retmsg = "错误:获取不到Token";  
  109.         }  
  110.           
  111.         resInfo.put("retcode", retcode);  
  112.         resInfo.put("retmsg", retmsg);  
  113.         String strJson = JSON.toJSONString(resInfo);  
  114.         return responseAjax(request, strJson);  
  115.     }  
  116.       
  117. }  
@Controller
@RequestMapping("/weixin/")
public class WeiXinPayController extends ResponsePage  {

	private Logger log = Logger.getLogger(WeiXinPayController.class);
	
	@RequestMapping("weixin.do")
	public String doWeinXinRequest(HttpServletRequest request,HttpServletResponse response) throws Exception {
		Map<Object,Object> resInfo = new HashMap<Object, Object>();
		//接收财付通通知的URL
		String notify_url = "http://127.0.0.1:8180/tenpay_api_b2c/payNotifyUrl.jsp";

		//---------------生成订单号 开始------------------------
		//当前时间 yyyyMMddHHmmss
		String currTime = TenpayUtil.getCurrTime();
		//8位日期
		String strTime = currTime.substring(8, currTime.length());
		//四位随机数
		String strRandom = TenpayUtil.buildRandom(4) + "";
		//10位序列号,可以自行调整。
		String strReq = strTime + strRandom;
		//订单号,此处用时间加随机数生成,商户根据自己情况调整,只要保持全局唯一就行
		String out_trade_no = strReq;
		//---------------生成订单号 结束------------------------

		PackageRequestHandler packageReqHandler = new PackageRequestHandler(request, response);//生成package的请求类 
		PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);//获取prepayid的请求类
		ClientRequestHandler clientHandler = new ClientRequestHandler(request, response);//返回客户端支付参数的请求类
		packageReqHandler.setKey(ConstantUtil.PARTNER_KEY);

		int retcode ;
		String retmsg = "";
		String xml_body = "";
		//获取token值 
		
		String token = AccessTokenRequestHandler.getAccessToken();
		
		log.info("获取token------值 " + token);
		
		if (!"".equals(token)) {
			//设置package订单参数
			packageReqHandler.setParameter("bank_type", "WX");//银行渠道
			packageReqHandler.setParameter("body", "测试"); //商品描述   
			packageReqHandler.setParameter("notify_url", notify_url); //接收财付通通知的URL  
			packageReqHandler.setParameter("partner", ConstantUtil.PARTNER); //商户号    
			packageReqHandler.setParameter("out_trade_no", out_trade_no); //商家订单号   
			packageReqHandler.setParameter("total_fee", "1"); //商品金额,以分为单位  
			packageReqHandler.setParameter("spbill_create_ip",request.getRemoteAddr()); //订单生成的机器IP,指用户浏览器端IP  
			packageReqHandler.setParameter("fee_type", "1"); //币种,1人民币   66
			packageReqHandler.setParameter("input_charset", "GBK"); //字符编码

			//获取package包
			String packageValue = packageReqHandler.getRequestURL();
			resInfo.put("package", packageValue);
			
			log.info("获取package------值 " + packageValue);

			String noncestr = WXUtil.getNonceStr();
			String timestamp = WXUtil.getTimeStamp();
			String traceid = "";
			////设置获取prepayid支付参数
			prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID);
			prepayReqHandler.setParameter("appkey", ConstantUtil.APP_KEY);
			prepayReqHandler.setParameter("noncestr", noncestr);
			prepayReqHandler.setParameter("package", packageValue);
			prepayReqHandler.setParameter("timestamp", timestamp);
			prepayReqHandler.setParameter("traceid", traceid);

			//生成获取预支付签名
			String sign = prepayReqHandler.createSHA1Sign();
			//增加非参与签名的额外参数
			prepayReqHandler.setParameter("app_signature", sign);
			prepayReqHandler.setParameter("sign_method",
					ConstantUtil.SIGN_METHOD);
			String gateUrl = ConstantUtil.GATEURL + token;
			prepayReqHandler.setGateUrl(gateUrl);

			//获取prepayId
			String prepayid = prepayReqHandler.sendPrepay();
			
			log.info("获取prepayid------值 " + prepayid);
			
			//吐回给客户端的参数
			if (null != prepayid && !"".equals(prepayid)) {
				//输出参数列表
				clientHandler.setParameter("appid", ConstantUtil.APP_ID);
				clientHandler.setParameter("appkey", ConstantUtil.APP_KEY);
				clientHandler.setParameter("noncestr", noncestr);
				//clientHandler.setParameter("package", "Sign=" + packageValue);
				clientHandler.setParameter("package", "Sign=WXPay");
				clientHandler.setParameter("partnerid", ConstantUtil.PARTNER);
				clientHandler.setParameter("prepayid", prepayid);
				clientHandler.setParameter("timestamp", timestamp);
				//生成签名
				sign = clientHandler.createSHA1Sign();
				clientHandler.setParameter("sign", sign);

				xml_body = clientHandler.getXmlBody();
				resInfo.put("entity", xml_body);
				retcode = 0;
				retmsg = "OK";
			} else {
				retcode = -2;
				retmsg = "错误:获取prepayId失败";
			}
		} else {
			retcode = -1;
			retmsg = "错误:获取不到Token";
		}
		
		resInfo.put("retcode", retcode);
		resInfo.put("retmsg", retmsg);
		String strJson = JSON.toJSONString(resInfo);
		return responseAjax(request, strJson);
	}
	
}


好了此时,客户端需要的参数都已经可以通过请求:http://localhost:8080/WeiXinpay/weixin/weixin.do 来获取

3、调起微信支付

这步就不需要我们服务端处理了。客户端的兄弟,来接力。

示例的完整代码可以在此链接下载:https://github.com/seven-cm/weixinpay

最后,微信回调:可以参考jsp文件夹中的payNotifyUrl.jsp来处理,处理过程和上面第二步差不多。

原文地址:https://www.cnblogs.com/itclw/p/5732338.html