`

Java微信公众平台开发之扫码支付模式一

阅读更多

官方文档点击查看
准备工作:已通过微信认证的公众号,必须通过ICP备案域名(否则会报支付失败)

借鉴了很多大神的文章,在此先谢过了

大体过程:先扫码(还没有确定实际要支付的金额),这个码是商品的二维码,再生成订单,适用于自动贩卖机之类固定金额的。

模式一支付的流程如下图,稍微有点复杂

详细源码,整合了H5和两种扫码方式点击查看

原生支付接口模式一时序图

 

业务流程说明:

(1)商户后台系统根据微信支付规定格式生成二维码(规则见下文),展示给用户扫码。
(2)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。
(3)微信支付系统收到客户端请求,发起对商户后台系统支付回调URL的调用。调用请求将带productid和用户的openid等参数,并要求商户系统返回交数据包

(4)商户后台系统收到微信支付系统的回调请求,根据productid生成商户系统的订单。

(5)商户系统调用微信支付【统一下单API】请求下单,获取交易会话标识(prepay_id)。
(6)微信支付系统根据商户系统的请求生成预支付交易,并返回交易会话标识(prepay_id)。
(7)商户后台系统得到交易会话标识prepay_id(2小时内有效)。
(8)商户后台系统将prepay_id返回给微信支付系统。
(9)微信支付系统根据交易会话标识,发起用户端授权支付流程。
(10)用户在微信客户端输入密码,确认支付后,微信客户端提交支付授权。
(11)微信支付系统验证后扣款,完成支付交易。
(12)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。
(13)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。
(14)未收到支付通知的情况,商户后台系统调用【查询订单API】。
(15)商户确认订单已支付后给用户发货。

一、设置回调地址

商户后台系统根据微信支付规则链接生成二维码,链接中带固定参数productid(可定义为产品标识或订单号)。用户扫码后,微信支付系统将productid和用户唯一标识(openid)回调商户后台系统(需要设置支付回调URL),商户后台系统根据productid生成支付交易,最后微信支付系统发起用户支付流程
商户支付回调URL设置指引:进入公众平台-->微信支付-->开发配置-->扫码支付-->修改,如下图所示。

 

这个支付回调的URL设置的作用是接收用户扫码后微信支付系统发送的数据,根据接收的数据生成商户系统的支付订单返回给微信支付系统,调用【统一下单API】提交支付交易。

扫码支付参数设置栏目入口

 

二、生成微信支付二维码

参考文档https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_6

二维码长链接示例:

weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX

 

这样太冗长了,转换成短链接 weixin://wxpay/bizpayurl?pr=XXXX

 

/**
	 * 扫码支付模式一生成二维码
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping("qrcode")
	public String createPayImage(HttpServletRequest request, HttpServletResponse response) {
		String nonce_str = PayUtil.createNonceStr();
		String product_id = "product_001"; // 推荐根据商品ID生成
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		packageParams.put("appid", WechatConfig.APP_ID);
		packageParams.put("mch_id", WechatConfig.MCH_ID);
		packageParams.put("product_id", product_id);
		packageParams.put("time_stamp", PayUtil.createTimeStamp());
		packageParams.put("nonce_str", nonce_str);
		String str = PayUtil.createPayImageUrl(packageParams);
		String sign = SignatureUtil.createSign(packageParams,WechatConfig.API_KEY, SystemConfig.CHARACTER_ENCODING);
		packageParams.put("sign", sign);
		String payurl = "weixin://wxpay/bizpayurl?sign=" + sign + str;
		logger.info("payurl is " + payurl);	
		/**** 转成短链接 ****/
		PayShortUrlParams payShortUrlParams = new PayShortUrlParams();
		payShortUrlParams.setAppid(WechatConfig.APP_ID);
		payShortUrlParams.setMch_id(WechatConfig.MCH_ID);
		payShortUrlParams.setLong_url(payurl);
		payShortUrlParams.setNonce_str(nonce_str);
		String urlSign = SignatureUtil.createSign(payShortUrlParams,WechatConfig.API_KEY, SystemConfig.CHARACTER_ENCODING);
		payShortUrlParams.setSign(urlSign);
		String longXml = XmlUtil.toSplitXml(payShortUrlParams);
		String shortResult = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.POST_METHOD, WechatConfig.PAY_SHORT_URL, null, longXml);
		PayShortUrlResult payShortUrlResult = XmlUtil.getObjectFromXML(shortResult, PayShortUrlResult.class);
		if("SUCCESS".equals(payShortUrlResult.getReturn_code())){
			payurl = payShortUrlResult.getShort_url();
		}else{
			logger.debug("错误信息"+payShortUrlResult.getReturn_msg());
		}
		/**** 生成 二维码图片自己实现****/
		return null;
	}

 

/**
	 * 生成支付二维码URL
	 * 
	 * @param params
	 * @return
	 */
	public static String createPayImageUrl(SortedMap<Object, Object> params) {
		StringBuffer buffer = new StringBuffer();
		for (Map.Entry<Object, Object> entry : params.entrySet()) {
			if (entry.getValue() != null) {
				buffer.append("&" + entry.getKey() + "=" + entry.getValue());
			}
		}
		return buffer.toString();
	}

三、回调商户支付URL

接收用户扫码后微信支付系统发送的数据,根据接收的数据生成商户系统的支付订单返回给微信支付系统,调用统一下单API提交支付交易

 

package com.phil.wechatpay.controller;

import java.io.BufferedOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.phil.common.config.SystemConfig;
import com.phil.common.config.WeChatConfig;
import com.phil.common.util.HttpReqUtil;
import com.phil.common.util.PayUtil;
import com.phil.common.util.SignatureUtil;
import com.phil.common.util.XmlUtil;
import com.phil.wechatpay.model.rep.PayCallBackParams;
import com.phil.wechatpay.model.rep.UnifiedOrderParams;
import com.phil.wechatpay.model.resp.PayCallBackResult;
import com.phil.wechatpay.model.resp.UnifiedOrderResult;

/**
 * 扫码模式一回调
 * 
 * @author phil
 * @date 2017年6月27日
 *
 */
@Controller
@RequestMapping("/wxpay/")
public class WechatPayCallBackController {

	private static final Logger logger = Logger.getLogger(WechatPayCallBackController.class);

	@RequestMapping("/callback")//payone
	public void callBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String resXml = "";// 反馈给微信服务器
		// 微信支付系统发送的数据(<![CDATA[product_001]]>格式)
		String xml = HttpReqUtil.inputStreamToStrFromByte(request.getInputStream());
		// logger.info("微信支付系统发送的数据"+xml);
		/**** 微信支付系统发送的数据其实就是回调地址输入的参数Xml****/
		// 验证签名
		if (SignatureUtil.checkIsSignValidFromWeiXin(xml, WeChatConfig.API_KEY, SystemConfig.CHARACTER_ENCODING)) {
			// 转换成输入参数,
			PayCallBackParams payCallBackParams = XmlUtil.getObjectFromXML(xml, PayCallBackParams.class);
			// appid openid mch_id is_subscribe nonce_str product_id sign
			// 统一下单
			String openid = payCallBackParams.getOpenid();
			String product_id = payCallBackParams.getProduct_id();
			/**** product_id 等 生成自己系统的订单****/
			int total_fee = 1; // 根据product_id算出价格
			String out_trade_no = PayUtil.createOutTradeNo(); //生成订单号	
			String body = product_id; // 商品名称设置为product_id
			String attach = "XXX店"; // 附加数据
			String nonce_str = PayUtil.createNonceStr();
			String spbill_create_ip = HttpReqUtil.getRemortIP(request);
			// 组装统一下单的请求参数
			UnifiedOrderParams unifiedOrderParams = new UnifiedOrderParams();
			unifiedOrderParams.setAppid(WeChatConfig.APP_ID);// 必须
			unifiedOrderParams.setMch_id(WeChatConfig.MCH_ID);// 必须
			unifiedOrderParams.setOut_trade_no(out_trade_no);
			unifiedOrderParams.setBody(body);
			unifiedOrderParams.setAttach(attach);
			unifiedOrderParams.setTotal_fee(total_fee);// 必须
			unifiedOrderParams.setNonce_str(nonce_str); // 必须
			unifiedOrderParams.setSpbill_create_ip(spbill_create_ip); // 必须
			unifiedOrderParams.setTrade_type("NATIVE");// 必须
			unifiedOrderParams.setOpenid(openid);
			unifiedOrderParams.setNotify_url(WeChatConfig.NOTIFY_URL); // 异步通知URL
			// 签名
			String sign = SignatureUtil.createSign(unifiedOrderParams, WeChatConfig.API_KEY, SystemConfig.CHARACTER_ENCODING);
			unifiedOrderParams.setSign(sign);
			// 统一下单 请求的Xml
			String unifiedXmL = XmlUtil.toSplitXml(unifiedOrderParams);
			// 统一下单 返回的xml
			String unifiedOrderResultXmL = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.POST_METHOD,WeChatConfig.UNIFIED_ORDER_URL, null, unifiedXmL);
			// 统一下单返回 验证签名
			if (SignatureUtil.checkIsSignValidFromWeiXin(unifiedOrderResultXmL, WeChatConfig.API_KEY,SystemConfig.CHARACTER_ENCODING)) {
				UnifiedOrderResult unifiedOrderResult = (UnifiedOrderResult) XmlUtil.getObjectFromXML(unifiedOrderResultXmL, UnifiedOrderResult.class);
				if("SUCCESS".equals(unifiedOrderResult.getReturn_code()) && "SUCCESS".equals(unifiedOrderResult.getResult_code())){
					PayCallBackResult payCallBackResult = new PayCallBackResult();
					payCallBackResult.setReturn_code(unifiedOrderResult.getReturn_code());
					payCallBackResult.setAppid(WeChatConfig.APP_ID);
					payCallBackResult.setMch_id(WeChatConfig.MCH_ID);
					payCallBackResult.setNonce_str(unifiedOrderResult.getNonce_str());//直接用微信返回的
					/**** prepay_id 2小时内都有效,根据product_id再次支付方法自己写 ****/
					payCallBackResult.setPrepay_id(unifiedOrderResult.getPrepay_id());
					payCallBackResult.setResult_code(unifiedOrderResult.getResult_code());
					String callsign = SignatureUtil.createSign(payCallBackResult, WeChatConfig.API_KEY, SystemConfig.CHARACTER_ENCODING);
					payCallBackResult.setSign(callsign);
					resXml = XmlUtil.toXml(payCallBackResult).replace("__", "_");
					//将数据包返回给微信支付系统处理
				}
			} else {
				logger.info("签名验证错误");
				resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"+ "<return_msg><![CDATA[签名验证错误]]></return_msg>" + "</xml> ";
			}
		} else {
			logger.info("签名验证错误");
			resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"+ "<return_msg><![CDATA[签名验证错误]]></return_msg>" + "</xml> ";
		}
		BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
		out.write(resXml.getBytes());
		out.flush();
		IOUtils.closeQuietly(out);
	}
}

 

四、完成支付并通知支付结果

可以参考下我这篇写的 详情点击
分享到:
评论

相关推荐

    微信扫码支付,公众号支付

    本demo 实现微信自定义菜单,自定义信息回复等功能,以及微信扫码支付,公众号支付,资源不易,欢迎反馈

    微信公众平台开发视频

    3. 微信公众平台开发之Struts2 (免费) 25:31 4. 微信公众平台开发之Spring MVC 27:12 5. 识别微信浏览器 24:40 6. 限制只允许微信浏览器访问 23:30 7. 一套程序服务多个账号---原始ID 17:46 8. 一套程序服务多个账号...

    java 微信扫描二维码支付demo

    微信提供了公众平台支付API,开发者可以调用这些接口来实现支付功能。在Java中,我们需要使用微信官方提供的SDK,如`wxpay-sdk-java`,来与微信服务器进行交互。 2. **生成二维码** - **QRCodeEncoder**: 生成...

    微信公众平台 客服接口发消息的实现代码(Java接口开发)

    微信公众平台技术文档:客服消息 一、接口说明 当用户和公众号产生特定动作的交互时(具体动作列表请见下方说明),微信将会把消息数据推送给开发者,开发者可以在一段时间内(目前修改为48小时)调用客服接口,通过...

    微信扫码支付接口开发总结

    1.申请微信服务号300元;微信公众号分类:订阅号,服务号,小程序。 2.开通微信支付认证权限300元; 3.开通过后,你会收到一封邮件:即可获取: appid:appid是微信...6.客户端通过打开微信扫码工具,即可完成支付。

    微信扫码支付代码

    本文档主要介绍了一段实现微信扫码支付功能的前端与后端代码示例。通过这段代码,用户可以通过扫描生成的二维码来完成支付流程。该功能涉及到了前端页面展示、定时轮询检查支付状态以及后端处理支付请求等关键环节。...

    微信开发获取地理位置实例(java)

    微信开发获取地理位置实例(java),使用环境 eclipse + maven + springmvc,虽然项目名是first_maven_project,但是确实是微信开发实例哈,不要有任何怀疑,免费分享啦,哈哈。实例讲解欢迎访问博主博客...

    微信小程序 微信扫码一键连接wifi小程序源码

    本源码是专门针对微信小程序设计的,用于实现“微信扫码一键连接WiFi”的功能,这在公共场所如咖啡馆、商场等场景下非常实用,能帮助用户快速、方便地接入WiFi网络。 一、微信小程序开发基础 1. 小程序框架:微信小...

    基于springboot2.x的Oauth2.0一键授权登录和微信网页扫码支付测试开发案例(含源码)

    使用idea开发工具,基于springboot2.x、jwt鉴权、nginx集群,前后端分离的微信Oauth2.0一键登录和微信网页扫码支付测试开发demo

    微信扫一扫支付

    微信扫一扫支付是微信支付的一种便捷方式,用户只需打开微信应用,使用“扫一扫”功能扫描商家提供的二维码,即可完成支付过程。这一技术的核心在于二维码生成与识别,以及与微信支付平台的交互。在这个过程中,涉及...

    微信支付微信扫码支付java版

    现在所有的web端网页商城常用的支付方式之一。web网站开发课程,web网站要实现支付的话,必须学习微信扫码支付。内容逻辑清晰,包你一会就会

    java实现微信扫码支付功能

    在Java中实现微信扫码支付功能涉及多个步骤,主要包括配置微信支付SDK、创建支付请求和处理支付结果。以下是对这些关键步骤的详细说明: 1. **引入依赖**: 在Java项目中,通常使用Maven来管理依赖。在`pom.xml`...

    微信支付技术文档

    包括:微信支付(APP)、微信支付(web扫码)、微信支付(公众账号)、【微信公众号支付】SDKV1.1、【微信支付】退款及对账demo、【微信公众号支付】接口文档V2.5.pdf、【微信公众号支付】收货地址共享接口文档V1.4.pdf、...

    Java调用微信支付接口

    在Java开发中,微信支付接口的调用是一个常见的任务,特别是在电商或者服务类应用程序中。SSM框架(Spring、SpringMVC和MyBatis)是Java Web开发中的主流选择,它提供了一个完整的后端解决方案。下面我们将深入探讨...

    解密第三方登录-微信扫码登录

    1. 基于微信公众平台的扫码登录:让第三方应用投入微信的怀抱而设计的,这第三方应用指的是比如 android、ios、网站、系统等。 2. 基于微信开放平台的扫码登录:为了让程序员小伙伴利用微信自家技术(公众号、小程序...

    支付对接Java开发工具包.rar

    (1)微信公众平台 微信公众平台是微信公众账号申请入口和管理后台。商户可以在公众平台提交基本资料、业务资料、财务资料申请开通微信支付功能。 (2) 微信开放平台 微信开放平台是商户APP接入微信支付开放接口...

    JAVA版微信连wifi

    1. **Java编程**:Java是一种广泛使用的面向对象的编程语言,具有跨平台性、安全性、稳定性和可维护性。在这个项目中,Java作为主要开发工具,用于实现程序的逻辑处理和接口调用。开发者需要对Java的基本语法、类库...

    微信服务号java版开发教程

    微信服务号是一个为企业和组织提供更强大的业务服务与用户管理能力的公众平台,它允许开发者通过API接口实现各种功能,例如自定义菜单、消息推送、用户管理等。本教程将深入探讨如何利用Java实现这些功能。 首先,...

    微信小程序扫码点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端) java毕业设计 完整源码+论文

    对此,微信点餐小程序的应用就很关键,近几年微信小程序兴起,利用微信公众平台,顾客可以快速地浏览菜品,另外,在餐桌上贴好对应的桌号,顾客扫码即可进行点餐,还可以进行备注留言,无需服务员服务,不仅给顾客...

Global site tag (gtag.js) - Google Analytics