Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

微信公众号支付开发

$
0
0

前段时间公司要求开发微信公众号支付功能,在和XX大学合作的过程中需要帮助推广其精品课程,故开发了对其课程进行打赏的功能。此公众号为服务号。开发过程中遇到了多多少少的问题,虽然不是大问题但是总是浪费时间去排查,所以写了此文作为梳理。 --2016.10

一、微信支付

1.微信支付简介微信支付:

是集成在微信客户端的支付功能,用户可以通过手机完成快速的支付流程。微信支付以绑定银行卡的快捷支付为基础,向用户提供安全、快捷、高效的支付服务。

2.条件:

申请微信公众号支付有2个条件:

一个是已微信认证的服务号

一个是已微信认证的政府、媒体订阅号

3.微信支付模式

刷卡支付: 刷卡支付是用户展示微信钱包内的“刷卡条码/二维码”给商户系统扫描后直接完成支付的模式。主要应用线下面对面收银的场景。

扫码支付: 扫码支付是商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。该模式适用于PC网站支付、实体店单品或订单支付、媒体广告支付等场景。

公众号支付: 公众号支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。应用场景有:用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付用户的好友在朋友圈、聊天窗口等分享商家页面连接,用户点击链接打开商家页面,完成支付将商户页面转换成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付

APP支付: APP支付又称移动端支付,是商户通过在移动端应用APP中集成开放SDK调起微信支付模块完成支付的模式。

二、开发流程

1.开发思路


1.1 配置

图1:申请支付功能


图2: 填写授权回调域名(安全起见,创造一个安全的支付环境)


图3: 填写授权目录


图4: 设置密钥(也是为了支付安全)


1.2 授权(此处针对课程进行打赏,并不要求用户关注公众号,因此使用静默授权)


2. 静默授权

关于网页授权的两种scope的区别说明
1)、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
2)、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
https ://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

3.统一下单

商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI、APP等不同场景生成交易串调起支付。
字段在return_code 和result_code都为SUCCESS的时候有返回prepay_id,微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时。
微信统一下单接口链接:https://api.mch.weixin.qq.com/pay/unifiedorder

4.调起支付API

在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。
注意:WeixinJSBridge内置对象在其他浏览器中无效。
列表中参数名区分大小,大小写错误签名验证会失败。


三、遇到的问题

1.未添加测试者进白名单:需要在公众号里配置


2.body中文编码方式:uft-8


3. 支付完成回调(同步和异步)

/**
 * 提交打赏信息
 */
function subRewardPrice(){
	//获取打赏金额
	var price = $("#rewardPrice").val();
	//获取课程ID
	var courseId = $("#courseId").val();
	if(null==price||price==""||parseFloat(price)<1){
	     $.msgbox({msg:"金额不得小于1元!",icon:"error",time:2000});
	     return;
	}
	// 支付方式: 1支付宝,2微信
	var statement = $("#statement").val();
	var openid = $("#openid").val();
	$.ajax({
    	 type:'post',
    	 url:'shippingBuyCourseMobile/rewardCourseMobile.htm',
    	 data:{
  			 courseId:courseId,
  			 payAmount:price,
  			 statement:statement,
  			 openid:openid
    	 },
    	 dataType:'json',
    	 success:function(data){
    		 if(statement == "1"){
 	    	 	// 处理支付宝支付下单成功
	    	 	$(".warp").after(data);
		           var queryParam = '';
		           Array.prototype.slice.call(document.querySelectorAll('input[type=hidden]')).forEach(function (ele) {
		        	   queryParam += ele.name + '=' + encodeURIComponent(ele.value) + '&';
		           });
		           var gotoUrl = document.querySelector('#alipay_form').getAttribute('action') + queryParam;
		           _AP.pay(gotoUrl);
    		 }else if(statement == "2"){
	    	 	// 处理微信支付下单成功
	    		 var returnCode = data.returnCode;
	    		 var resultCode = data.resultCode;
	    		 // 在return_code 和result_code都为SUCCESS的时候才返回prepay_id
	    		 if(returnCode == "SUCCESS" && resultCode == "SUCCESS"){
		    		if (typeof WeixinJSBridge == "undefined"){
		    		   if(document.addEventListener){
		    		       document.addEventListener('WeixinJSBridgeReady', onBridgeReady(data), false);
		    		   }else if (document.attachEvent){
		    		       document.attachEvent('WeixinJSBridgeReady', onBridgeReady(data)); 
		    		       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady(data));
		    		   }
		    		}else{
		    		   onBridgeReady(data);
		    		}
	    		 }
    		 }
    	}
    });
}

//放重复提交变量
var submitFlag = 0;
//打赏 微信支付
function onBridgeReady(data) {
	if(!submitFlag){
		submitFlag++;
	}else {
		return;
	}
	var orderNo = data.orderNo;
	var courseId = $("#courseId").val();
	WeixinJSBridge.invoke('getBrandWCPayRequest', {
		"appId" : data.appId, // 公众号名称,由商户传入     
		"timeStamp" : data.timeStamp, // 时间戳,自1970年以来的秒数     
		"nonceStr" : data.nonceStr, // 随机串     
		"package" : "prepay_id=" + data.prepayId, // 随机串     
		"signType" : "MD5", // 微信签名方式 
		"paySign" : data.paySign
	// 微信签名 
	}, function(res) {
		submitFlag = 0;
		// 把对象转字符串
		// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。 
		if (res.err_msg == "get_brand_wcpay_request:ok") {
			$.ajax({
				type : 'post',
				url : 'shippingBuyCourseMobile/updateOrderStatus.htm',
				data : {
					orderNo : orderNo
				},
				dataType : 'text',
				success : function(data) {
					window.location.href = "shippingCourseMobileSearch/shippingCourseMobileDetailIndex.htm?courseId="+courseId;
				}
			});
		} else {
			alert("打赏失败!");
		}
	});
}


作者:Yasha009 发表于2016/11/24 16:38:02 原文链接
阅读:66 评论:1 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>