精华内容
下载资源
问答
  • jsapi支付

    2020-05-22 09:20:05
    套餐充值 微信支付 123
    
    
    
    
    
    
    套餐充值
    
    
    
    
    <div class="xbt-page">
    	<div class="xbt-page bc-f2 has-header" style="background: #FFFFFF;">
    
    		<div class="weui-cells"
    			style="margin-top: 0px; font-weight: 500; position: static;">
    			<div class="weui-cell title_name"
    				style="background: #edf1f3; border-top: 1px solid #dddfe3;">
    			</div>
    
    			<div id="jiaoyilist" class="weui-panel weui-panel_access"
    				style="margin-top: 0px; position: static;">
    				<!-- js页面显示-->
    			</div>
    
    			<div align="center" style="margin-top: 10px;">
    				<a href="javascript:doPostMoney();" class="recharge"><span id="spanPos">微信支付</span></a>
    			</div>
    		</div>
    
    	</div>
    </div>
    
    <div>
    	<span id="spanCode">123</span>
    </div>
    
    <script type="text/javascript" src="http://web.qingmoukeji.com/js/teacher/js/common.min.js"></script>
    <script type="text/javascript">
    //获取地址栏参数
    function GetQueryString(name) {
    	var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    	var r = window.location.search.substr(1).match(reg);
    	if (r != null) {
    		return unescape(r[2]);
    	}
    	return null;
    }
    
    function doPostMoney(){
    	$.ajax({
    			type: 'get',
    			url: 'http://www.dui1688.com/payByWx?upPayOrderKey=safdsfds&upId=4&openId=oXsfnwZS0uqJZqRdU-KgF0wa61jg',
    			data: {
    			},
    			async: false,
    			success: function(data) {
    				alert(data.appId);
    				alert(data.timeStamp);
    				alert(data.nonceStr);
    				alert(data.package);
    				alert(data.signType);
    				alert(data.paySign);
    				
    				function jsApiCall(){
    					WeixinJSBridge.invoke(
    						'getBrandWCPayRequest',{
    							"appId" : data.appId,
    							"timeStamp":data.timeStamp,
    							"nonceStr" : data.nonceStr,
    							"package" : data.package,
    							"signType" : data.signType,
    							"paySign" : data.paySign
    						},
    						function(res){
    							if(res.err_msg == "get_brand_wcpay_request:ok" ) {
    								alert('支付成功');
    							}
    						}
    					);
    				}
    				function callpay(){
    					if (typeof WeixinJSBridge == "undefined"){
    						if(document.addEventListener){
    							document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
    						}else if (document.attachEvent){
    							document.attachEvent('WeixinJSBridgeReady', jsApiCall);
    							document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
    						}
    					}else{
    						jsApiCall();
    					}
    				}
    				callpay()
    
    			},
    			error: function(jqXHR, textStatus, errorThrown) {
    
    			}
    		});
    }
    	</script>
    
    展开全文
  • JSAPI支付(公众号支付)流程:1.先通过聚合支付提供的获取openid接口获取待支付用户的openid2.将聚合支付返回的openid和订单信息组合3.请求聚合支付提供的API接口4.聚合支付将返回jsapi支付相关参数5.调用微信jsapi...

    JSAPI支付(公众号支付)

    流程:

    1.先通过聚合支付提供的获取openid接口获取待支付用户的openid

    2.将聚合支付返回的openid和订单信息组合

    3.请求聚合支付提供的API接口

    4.聚合支付将返回jsapi支付相关参数

    5.调用微信jsapi支付相关js服务发起支付

    请求方式: POST

    请求参数:

    字段

    字段类型

    是否必填

    说明

    app_id

    string(32)

    聚合支付平台的app_key

    sub_mch_id

    string(32)

    在聚合支付申请的微信商户号

    openid

    string(128)

    openid,可以通过 获取openid接口 获取

    body

    string(128)

    自定义商品名

    out_trade_no

    string(64)

    自定义订单编号

    total_fee

    int

    订单总金额,单位:分

    notify_url

    string(255)

    支付结果的异步回调地址

    attach

    string(200)

    自定义参数,在回调的时候原样返回,不超过200个字符

    sign

    string(32)

    签名,具体请看 签名规则

    响应(失败):

    {

    "code": 1002,

    "msg": "签名必填",

    "data": []

    }

    响应(成功):

    {

    "code": 1000,

    "msg": "成功",

    "data": {

    "sub_msg": "success",

    "body": "test",

    "out_trade_no": "202001011429594092",

    "total_fee": "1",

    "attach": "{\"name\": \"test\"}",

    "app_id": "eZfQaZGXhjepbEkmM2KMEg48MDAwMlRP",

    "sub_mch_id": "1571727441",

    "openid": "oDIJ5uNfFlH6JruAjoaRRCWylVwE",

    "jsapi_app_id": "wx7db7649eedb1443e",

    "jsapi_timeStamp": "1577860225",

    "jsapi_nonceStr": "104f299d11ba2e34b68c438a52698fbc",

    "jsapi_package": "prepay_id=wx011430257970342f5db60e761721827700",

    "jsapi_signType": "MD5",

    "jsapi_paySign": "8A9CF04736323D1344ADB5903207E42D",

    "sign": "7F3B5EC8177693AE366649A076BC9D4E"

    }

    }

    响应参数:

    字段

    类型

    必须

    说明

    code

    int

    状态码,1000为成功,其它均为失败

    msg

    string(32)

    状态文本

    下面参数是请求成功之后返回的:

    字段

    类型

    必须

    说明

    data.sub_msg

    string(32)

    业务提示信息

    data.out_trade_no

    string(64)

    自定义订单号

    data.body

    string(128)

    自定义商品名

    data.total_fee

    int

    订单总金额,单位:分

    data.attach

    string(200)

    自定义参数,在回调的时候原样返回

    data.app_id

    string(32)

    聚合支付平台的app_key

    data.sub_mch_id

    string(32)

    在聚合支付申请的微信商户号

    data.openid

    string(18)

    openid

    data.jsapi_app_id

    string(16)

    jsapi支付参数

    data.jsapi_timeStamp

    string(32)

    jsapi支付参数

    data.jsapi_nonceStr

    string(32)

    jsapi支付参数

    data.jsapi_package

    string(128)

    jsapi支付参数

    data.jsapi_signType

    string(32)

    jsapi支付参数

    data.jsapi_paySign

    string(64)

    jsapi支付参数

    data.sign

    string(32)

    签名

    具体使用

    在您成功创建订单之后,你会获取到一系列jsapi_开头的参数,这些参数是用来在微信端发起支付用的,如下:

    注意在聚合支付后台配置jsapi支付目录哦。

    function onBridgeReady(){

    WeixinJSBridge.invoke(

    'getBrandWCPayRequest', {

    "appId":"wx25db1b0b82771257", //公众号名称,由商户传入

    "timeStamp":"1554216889", //时间戳,自1970年以来的秒数

    "nonceStr":"cCtowhreO39YzzAW", //随机串

    "package":"prepay_id=wx022254476291111977dc395f0711456116",

    "signType":"MD5",

    "paySign":"ACD6C908CCBE6FE5CA32B180AE5B6740" //微信签名

    },

    function(res){

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

    alert('支付成功');

    }

    });

    }

    if (typeof WeixinJSBridge == "undefined"){

    if( document.addEventListener ){

    document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);

    }else if (document.attachEvent){

    document.attachEvent('WeixinJSBridgeReady', onBridgeReady);

    document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);

    }

    }else{

    onBridgeReady();

    }

    上面的代码是jsapi支付的js代码,我们需要做的就是拿我们创建订单后返回的参数替换其中的参数即可。

    展开全文
  • 这次给大家带来ThinkPHP实现微信支付(jsapi支付)步骤详解,ThinkPHP实现微信支付(jsapi支付)的注意事项有哪些,下面就是实战案例,一起来看一下。当时的环境是没有使用框架的,直接在一个域名指向的目录下边新建目录...

    这次给大家带来ThinkPHP实现微信支付(jsapi支付)步骤详解,ThinkPHP实现微信支付(jsapi支付)的注意事项有哪些,下面就是实战案例,一起来看一下。

    当时的环境是没有使用框架的,直接在一个域名指向的目录下边新建目录之后访问该目录实现的,但应用到框架中,还是有一些问题,在ThinkPHP中,由于路由规则与支付授权目录有出入,所以会报错。本篇讲讲在TP中集成微信支付的流程。

    鹅厂出的SDK和文档,就是让你看不懂,使劲绕,这酸爽用了就知道。文档和SDK不是应该越简单通俗易懂越好么?难道只有使劲重构才能显示出鹅厂程序猿技术的高超咩?额...是不是暴露了我菜鸟的属性...其实SDK蛮好用,只是上一篇文章中也看到了,在支付完成回调函数中,着实让人绕的晕头转向。

    对于不想被官方绕的,想在TP中使用微信支付的可以看看一个大神自己根据官方文档重构精简打造而成的适用于TP的支付SDK,源码我下载下来看过了,代码写的很优雅简介,流程也很简单,通俗易懂。详见博文:http://baijunyao.com/article/78

    我自己还是皱着眉头,使用了官方的SDK,也成功实现了支付,下面跟大家分享一下流程:

    1.SDK下载和修改

    这个就不过多讲了,不知道的可以看看我的上一篇文章:PHP实现微信支付(jsapi支付)流程,里边详细详述了下载下来的文件哪些是需要修改的。

    2.公众号设置

    A. 还是需要设置网页授权域名,这个没啥特殊的;

    B. 这里要注意一下支付授权目录,使用TP很多人都使用的是重写模式(REWRITE模式)或者在使用REWRITE模式的同时,使用伪静态模式,这时候生成的链接为: http://serverName/Home/Blog/read/id/1 ;

    如果使用的是PATHINFO模式的话,生成的链接就是:http://serverName/index.php/Home/Blog/read/id/1,比如在Home模块下的Blog控制器中的某个方法进行支付,我们支付的授权目录应该是 http://serverName/Home/Blog/ 或者 http://serverName/index.php/Home/Blog/,这个根据自己的TP的设置的URL模式而定。

    3.支付流程

    (1)统一下单

    下单的支付参数配置,这个跟上一篇讲的基本不变,重点注意的是支付回调验证链接,因为要多次调用,我就直接在Application/Common/Common/function.php中将参数配置封装起来了,我的SDK放在项目根目录下的Api目录下,所以引入SDK的时候不是使用Vendor函数。/**

    * 微信支付

    * @param string $openId openid

    * @param string $goods 商品名称

    * @param string $attach 附加参数,我们可以选择传递一个参数,比如订单ID

    * @param string $order_sn 订单号

    * @param string $total_fee 金额

    */

    function wxpay($openId,$goods,$order_sn,$total_fee,$attach){

    require_once APP_ROOT."/Api/wxpay/lib/WxPay.Api.php";

    require_once APP_ROOT."/Api/wxpay/payment/WxPay.JsApiPay.php";

    require_once APP_ROOT.'/Api/wxpay/payment/log.php';

    //初始化日志

    $logHandler= new CLogFileHandler(APP_ROOT."/Api/wxpay/logs/".date('Y-m-d').'.log');

    $log = Log::Init($logHandler, 15);

    $tools = new JsApiPay();

    if(empty($openId)) $openId = $tools->GetOpenid();

    $input = new WxPayUnifiedOrder();

    $input->SetBody($goods); //商品名称

    $input->SetAttach($attach); //附加参数,可填可不填,填写的话,里边字符串不能出现空格

    $input->SetOut_trade_no($order_sn); //订单号

    $input->SetTotal_fee($total_fee); //支付金额,单位:分

    $input->SetTime_start(date("YmdHis")); //支付发起时间

    $input->SetTime_expire(date("YmdHis", time() + 600));//支付超时

    $input->SetGoods_tag("test3");

    //$input->SetNotify_url("http://".$_SERVER['HTTP_HOST']."/payment.php"); //支付回调验证地址

    $input->SetNotify_url("http://".$_SERVER['HTTP_HOST']."/payment.php/WexinApi/WeixinPay/notify");

    $input->SetTrade_type("JSAPI"); //支付类型

    $input->SetOpenid($openId); //用户openID

    $order = WxPayApi::unifiedOrder($input); //统一下单

    $jsApiParameters = $tools->GetJsApiParameters($order);

    return $jsApiParameters;

    }

    注意,注意,敲黑板划重点了:

    支付回调验证链接,必须是没有权限验证的,如果你自己访问那个链接,还需要登录注册验证的,就不要尝试了,必须要可以无障碍访问的链接,而且也不要有一连串的参数传递。

    最好就是简单粗暴的 http://serverName/xxx.php ,我在跟目录下,类似于index.php,重新写了一个专门的供支付回调的入口文件payment.php,和它对应的Application/目录下的模块(WexinApi)、控制器(WeixinPay)及方法(notify):// 检测PHP环境

    if(version_compare(PHP_VERSION,'5.3.0',' 5.3.0 !');

    // $_GET['m']='Admin';

    // 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false

    define('APP_DEBUG',True);

    //指定模块控制器和方法

    $_GET['m']='WexinApi';

    $_GET['c']='WeixinPay';

    $_GET['a']='notify';

    // 定义应用目录

    define('APP_PATH','./Application/');

    define("APP_ROOT",dirname(FILE));

    // 引入ThinkPHP入口文件

    require './ThinkCore/ThinkCore.php';

    // 亲^_^ 后面不需要任何代码了 就是如此简单

    现在访问 http://serverName/payment.php ,就会直接进入到 http://serverName/payment.php/WexinApi/WeixinPay/notify ,这样回调验证链接可以写 http://serverName/payment.php ,也可以写 http://serverName/payment.php/WexinApi/WeixinPay/notify 。

    (2)发起支付

    照样很简单:/**

    * 支付测试

    * 微信访问:http://daoshi.sdxiaochengxu.com/payment.php/WexinApi/WeixinPay/pay

    */

    public function pay(){

    $order_sn = getrand_num(true);

    $openId = '';

    $jsApiParameters = wxpay($openId,'江南极客',$order_sn,1);

    $this->assign(array(

    'data' => $jsApiParameters

    ));

    $this->display();

    }

    小尤支付测试

    //调用微信JS api 支付

    function jsApiCall()

    {

    var data={$data};

    WeixinJSBridge.invoke(

    'getBrandWCPayRequest', data,

    function(res){

    WeixinJSBridge.log(res.err_msg);

    //alert('err_code:'+res.err_code+'err_desc:'+res.err_desc+'err_msg:'+res.err_msg);

    //alert(res.err_code+res.err_desc+res.err_msg);

    //alert(res);

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

    alert("支付成功!");

    window.location.href="http://m.blog.csdn.net/article/details?id=72765676" rel="external nofollow" ;

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

    alert("用户取消支付!");

    }else{

    alert("支付失败!");

    }

    }

    );

    }

    function callpay()

    {

    if (typeof WeixinJSBridge == "undefined"){

    if( document.addEventListener ){

    document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);

    }else if (document.attachEvent){

    document.attachEvent('WeixinJSBridgeReady', jsApiCall);

    document.attachEvent('onWeixinJSBridgeReady', jsApiCall);

    }

    }else{

    jsApiCall();

    }

    }

    该笔订单支付金额为1分

    1分钱也是爱

    果断买买买^_^

    不过支付页面的URL要注意了,因为支付页面的URL肯定带有不少参数,刚才说了TP中使用的REWRITE模式,你的链接为类似[ http://serverName/Home/Blog/read/id/1 ]这样的,可能带有更多参数,这时候微信支付会认为你的支付授权目录是[ http://serverName/Home/Blog/read/id/ ],但是你真实的授权目录是[ http://serverName/Home/Blog/],所以就会报错。处理方法就是,在进入支付页面的时候,重构URL,写成普通模式,即为[ http://serverName/Home/Blog/read?id=1],这样就可以了。

    9f6924ebd8933c404012e702ee31d9bc.png

    (3)支持成功回调

    现在支付完成,就会进入到之前写好的链接对应的方法,即[ http://serverName/payment.php/WexinApi/WeixinPay/notify]://微信支付回调验证

    public function notify(){

    $xml = $GLOBALS['HTTP_RAW_POST_DATA'];

    // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了

    file_put_contents('./Api/wxpay/logs/log.txt',$xml,FILE_APPEND);

    //将服务器返回的XML数据转化为数组

    //$data = json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true);

    $data = xmlToArray($xml);

    // 保存微信服务器返回的签名sign

    $data_sign = $data['sign'];

    // sign不参与签名算法

    unset($data['sign']);

    $sign = $this->makeSign($data);

    // 判断签名是否正确 判断支付状态

    if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) {

    $result = $data;

    // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了

    file_put_contents('./Api/wxpay/logs/log1.txt',$xml,FILE_APPEND);

    //获取服务器返回的数据

    $order_sn = $data['out_trade_no']; //订单单号

    $order_id = $data['attach']; //附加参数,选择传递订单ID

    $openid = $data['openid']; //付款人openID

    $total_fee = $data['total_fee']; //付款金额

    //更新数据库

    $this->updateDB($order_id,$order_sn,$openid,$total_fee);

    }else{

    $result = false;

    }

    // 返回状态给微信服务器

    if ($result) {

    $str='';

    }else{

    $str='';

    }

    echo $str;

    return $result;

    }

    为了安全起见,对返回过来的签名,要重新验证:/**

    * 生成签名

    * @return 签名,本函数不覆盖sign成员变量

    */

    protected function makeSign($data){

    //获取微信支付秘钥

    require_once APP_ROOT."/Api/wxpay/lib/WxPay.Api.php";

    $key = \WxPayConfig::KEY;

    // 去空

    $data=array_filter($data);

    //签名步骤一:按字典序排序参数

    ksort($data);

    $string_a=http_build_query($data);

    $string_a=urldecode($string_a);

    //签名步骤二:在string后加入KEY

    //$config=$this->config;

    $string_sign_temp=$string_a."&key=".$key;

    //签名步骤三:MD5加密

    $sign = md5($string_sign_temp);

    // 签名步骤四:所有字符转为大写

    $result=strtoupper($sign);

    return $result;

    }

    至此,TP中微信支付也就搞定了。这是集成了官方的SDK实现的,如果不使用SDK,可以使用更简单的方法,见:PHP实现微信支付(jsapi支付)和退款(无需集成支付SDK)

    ed3184aa948a7c37328a2fc04f60f9c4.png

    相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

    推荐阅读:

    展开全文
  • 微信jsapi支付

    2015-12-09 19:39:20
    微信的jsapi支付,可以实现jsapi支付
  • 前言微信APP支付,微信授权,微信JSAPI支付,微信退款,支付宝APP支付,支付宝手机网站支付,支付宝退款。笔者都放到公众号: JAVA大贼船。微信搜一搜,方便以后开发用哦!官方文档JS-SDK说明文档JSAPI支付文档准备...

    前言

    微信APP支付,微信授权,微信JSAPI支付,微信退款,支付宝APP支付,支付宝手机网站支付,支付宝退款。笔者都放到公众号: JAVA大贼船。微信搜一搜,方便以后开发用哦!

    官方文档

    JS-SDK说明文档

    JSAPI支付文档

    准备工作

    公众号配置绑定域名(可在该域名下调用微信开放的JS接口,这里配置前端域名) 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。

    填写接口配置信息(用于配合微信服务器认证)

    开发-基本配置,配置URL,Token和生成EncodingAESKey,配置完了这时候点击提交是不行的,需要后端写好接口与配合微信认证,如下代码。

    @ApiOperation("微信认证地址")

    @GetMapping("/baseCallback")

    public String baseCallback(String signature,String timestamp,String nonce,String echostr) throws Exception {

    return echostr;

    }

    配置ip白名单

    获取普通accessToken时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,否则将无法调用成功

    商户平台配置设置支付目录(配置了才能拉起微信收银台,配置前端域名,否则会报当前页面的Url未注册的错误)

    登录微信支付商户平台(http://pay.weixin.qq.com)-->产品中心-->开发配置,设置后一般5分钟内生效。支付授权目录校验说明如下:

    1、如果支付授权目录设置为顶级域名(例如:https://www.weixin.com/ ),那么只校验顶级域名,不校验后缀;

    2、如果支付授权目录设置为多级目录,就会进行全匹配,例如设置支付授权目录为https://www.weixin.com/abc/123/,则实际请求页面目录不能为https://www.weixin.com/abc/,也不能为https://www.weixin.com/abc/123/pay/,必须为https://www.weixin.com/abc/123/

    流程步骤

    JSSDK使用步骤这个文档主要看 1概述和14微信支付,如下图;

    主要步骤前端获取注入参数

    前端支付前请求后台获取上图步骤三所需参数,并注入成功,前端最好配置全局,因为业务可能会扩展,其他接口会需要,如分享接口

    前端获取唤起微信收银台所需参数

    注入成功后->前端点击微信支付->后端向微信下单->下单成功后得到prepay_id->返回所需参数给前端->唤起收银台

    后端代码实现

    引入依赖

    com.github.wxpay

    wxpay-sdk

    0.0.3

    配置参数

    application.yml

    # 微信相关配置

    wx:

    #商户 ID(微信支付平台-账户中心-个人信息)

    MCH_ID:

    # APP_ID(微信开放平台或公众号查找)

    H_APP_ID:

    # 秘钥(微信开放平台或公众号查找)

    H_APP_SECRET:

    # 消息加解密所用到的解密串(微信公众号-基本配置查找)

    H_ENCODINGAESKEY:

    # token(微信公众号-基本配置查找)

    H_TOKEN:

    # 支付秘钥KEY(微信支付平台-账户中心-api安全-api秘钥)

    H_KEY:

    # 支付商户证书所载目录(微信支付平台-账户中心-api安全-API证书)

    H_CERT_PATH:

    #支付成功回调地址

    WX_CALLBACK_URL:

    YmlParament

    @Component

    @Data

    public class YmlParament {

    /*微信相关字段*/

    @Value("${wx.H_APP_ID}")

    private String h_app_id;

    @Value("${wx.H_APP_SECRET}")

    private String h_app_secret;

    @Value("${wx.H_ENCODINGAESKEY}")

    private String h_encodingaeskey;

    @Value("${wx.H_TOKEN}")

    private String h_token;

    @Value("${wx.MCH_ID}")

    private String mch_id;

    @Value("${wx.H_KEY}")

    private String h_key;

    @Value("${wx.H_CERT_PATH}")

    private String h_cert_path;

    @Value("${wx.WX_CALLBACK_URL}")

    private String wx_callback_url;

    获取前端config接口配置参数(查看jssdk文档附录1)生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。Application 开启计划任务,用于定时刷新

    @EnableScheduling//开启计划任务 表达式参考http://cron.qqe2.com/配置全局缓存

    WxParament

    /**

    * 获取ACCESS_TOKEN

    * 刷新规则:

    * 1、启动设置该值

    * 2、一小时刷新一次

    */

    public static String ACCESS_TOKEN;

    /**

    * 获取JSAPI_TICKET

    * 刷新规则:

    * 1、启动设置该值

    * 2、一小时刷新一次

    */

    public static String JSAPI_TICKET;定时刷新

    InitServiceImpl

    @Autowired

    private YmlParament ymlParament;

    @PostConstruct

    @Override

    public void init() {

    initAccessToken();

    initJsapiTicket();

    }

    /**

    * 初始化AccessToken 一小时执行一次

    *cron表达式可在线生成:https://cron.qqe2.com/

    */

    @Scheduled(cron = "0 0 0/1 * * ?")

    @Override

    public void initAccessToken() {

    try {

    WxParament.ACCESS_TOKEN = GetToken.getAccessToken(ymlParament.getH_app_id(), ymlParament.getH_app_secret());

    } catch (Exception e) {

    log.error("<====initAccessToken初始化失败!==>" + e);

    e.printStackTrace();

    }

    log.info("<====初始化initAccessToken成功,值为==>" + WxParament.ACCESS_TOKEN);

    }

    /**

    * 初始化JSAPI_TICKET 一小时执行一次

    */

    @Scheduled(cron = "0 0 0/1 * * ?")

    @Override

    public void initJsapiTicket() {

    try {

    log.info("<====正在刷新 JSAPI_TICKET ==>");

    WxParament.JSAPI_TICKET = GetToken.getTicket(ymlParament.getH_app_id(), ymlParament.getH_app_secret(),

    WxParament.ACCESS_TOKEN);

    } catch (Exception e) {

    log.error("<====initJsapiTicket初始化失败!==>" + e);

    e.printStackTrace();

    }

    log.info("<====刷新 JSAPI_TICKET 成功,值为 ==>" + WxParament.JSAPI_TICKET);

    }

    GetToken

    /**

    * ~~~~~~~~~ 第一步 ~~~~~~~~~

    * 有效期两个小时,注意缓存 获取access_token,记得配置ip白名单

    * 参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):

    * https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

    * @param appid

    * @param secret

    * @throws Exception

    */

    public static String getAccessToken(String appid, String secret) throws Exception {

    String res=HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token",

    "grant_type=client_credential&appid=" + appid + "&secret=" + secret);

    String access_token=JSON.parseObject(res).getString("access_token");

    if(IsNull.isNull(access_token)) {

    throw new Exception(res);

    }

    return access_token;

    }

    /**

    * ~~~~~~~~~ 第二步 ~~~~~~~~~

    * 有效期两个小时,注意缓存 用第一步拿到的access_token 采用http

    * GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):

    * https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

    * @param appid

    * @param secret

    * @param accessToken 如果 accessToken 传null 则重新获取 access_token,如果accessToken有值,则直接获取Ticket

    * @throws Exception

    */

    public static String getTicket(String appid, String secret,String accessToken) throws Exception {

    String token=IsNull.isNull(accessToken)?getAccessToken(appid, secret):accessToken;

    String res=HttpUtil.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket",

    "access_token=" + token + "&type=jsapi");

    String ticket=JSON.parseObject(res).getString("ticket");

    if(IsNull.isNull(ticket)) {

    throw new Exception(res);

    }

    return ticket;

    }

    /**

    *

    * jsapi_ticket是公众号用于调用微信JS接口的临时票据

    * 前台统一js签名,参考说明如下

    * 1、业务说明:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#3

    * 2、签名算法:1-JS-SDK使用权限签名算法:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#62

    * @param jsapi_ticket,必须传入,每次有效时间两小时,如果频繁获取会报错

    * @param url url(当前支付页面的URL,不包含#及其后面部分)

    * @return

    */

    public static Map getJsSignature(String jsapi_ticket, String url) {

    return sign(jsapi_ticket, url);

    }

    /*签名算法*/

    private static Map sign(String jsapi_ticket, String url) {

    Map ret = new HashMap();

    String nonce_str = UUID.randomUUID().toString();;

    String timestamp = Long.toString(System.currentTimeMillis() / 1000);

    String signature = null;

    // 注意这里参数名必须全部小写,且必须有序

    String string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;

    try {

    MessageDigest crypt = MessageDigest.getInstance("SHA-1");

    crypt.reset();

    crypt.update(string1.getBytes("UTF-8"));

    signature = byteToHex(crypt.digest());

    } catch (NoSuchAlgorithmException e) {

    e.printStackTrace();

    } catch (UnsupportedEncodingException e) {

    e.printStackTrace();

    }

    ret.put("url", url);

    ret.put("jsapi_ticket", jsapi_ticket);

    ret.put("nonceStr", nonce_str);

    ret.put("timestamp", timestamp);

    ret.put("signature", signature);

    return ret;

    }

    private static String byteToHex(final byte[] hash) {

    Formatter formatter = new Formatter();

    for (byte b : hash) {

    formatter.format("%02x", b);

    }

    String result = formatter.toString();

    formatter.close();

    return result;

    }

    HttpUtil

    public static String get(String urlStr, Map parameters) throws IOException {

    URL url = new URL(urlStr);

    HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

    httpURLConnection.setDoInput(true);

    httpURLConnection.setDoOutput(true); // 设置该连接是可以输出的

    httpURLConnection.setRequestMethod("GET"); // 设置请求方式

    httpURLConnection.setRequestProperty("charset", "utf-8");

    PrintWriter pw = new PrintWriter(new BufferedOutputStream(httpURLConnection.getOutputStream()));

    StringBuffer parameter = new StringBuffer();

    parameter.append("1=1");

    for (Entry entry : parameters.entrySet()) {

    parameter.append("&" + entry.getKey() + "=" + entry.getValue());

    }

    pw.write(parameter.toString());// 向连接中写数据(相当于发送数据给服务器)

    pw.flush();

    pw.close();

    BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), "utf-8"));

    String line = null;

    StringBuilder sb = new StringBuilder();

    while ((line = br.readLine()) != null) { // 读取数据

    sb.append(line + "\n");

    }

    br.close();

    return sb.toString();

    }

    JacksonUtil

    public class JacksonUtil {

    public static String parseString(String body, String field) {

    ObjectMapper mapper = new ObjectMapper();

    JsonNode node;

    try {

    node = mapper.readTree(body);

    JsonNode leaf = node.get(field);

    if (leaf != null) {

    return leaf.asText();

    }

    } catch (IOException e) {

    e.printStackTrace();

    }

    return null;

    }

    }

    微信支付初始化参数

    @ApiOperation("微信支付初始化参数")

    @PostMapping("getJsSignature")

    public R getJsSignature(@RequestBody String body){

    //(当前支付页面的URL,不包含#及其后面部分)

    String url = JacksonUtil.parseString(body, "url");

    if(IsNull.isNull(url)) {

    return R.error("参数不能为空!");

    }

    Map res = new HashMap<>();

    Map jsSignature = GetToken.getJsSignature(WxParament.JSAPI_TICKET, url);

    res.put("appId", ymlParament.getH_app_id());

    res.put("timestamp",jsSignature.get("timestamp"));

    res.put("nonceStr",jsSignature.get("nonceStr"));

    res.put("signature",jsSignature.get("signature"));

    return R.ok(res);

    }

    获取openid

    微信统一下单初始化微信支付配置

    @Component

    public class WxConfig {

    @Autowired

    private YmlParament ymlParament;

    /**

    * 初始化微信支付配置

    * @throws Exception

    */

    @Bean(autowire = Autowire.BY_NAME,value = WxParament.H5_WX_PAY)

    public WXPay setH5WXPay() throws Exception {

    return new WXPay(new WxPayConfig(

    ymlParament.getH_cert_path(),

    ymlParament.getH_app_id(),

    ymlParament.getMch_id(),

    ymlParament.getH_key()));

    }

    }

    WxPayConfig

    public class WxPayConfig implements WXPayConfig {

    private byte[] certData;

    private String appID;

    private String mchID;

    private String key;

    public WxPayConfig(String certPath, String appID,String mchID,String key) throws Exception {

    File file = new File(certPath);

    InputStream certStream = new FileInputStream(file);

    this.certData = new byte[(int) file.length()];

    certStream.read(this.certData);

    certStream.close();

    this.appID = appID;

    this.mchID = mchID;

    this.key = key;

    }

    }微信下单接口,关键代码(服务层)

    @Resource(name = WxParament.H5_WX_PAY)

    private WXPay wxH5Pay;

    /* 微信统一下单 */

    private Map wxUnifiedOrder(String orderNo, String orderFee, String requestIp, String openid) throws RuntimeException {

    Map data = new HashMap();

    data.put("nonce_str", WXPayUtil.generateNonceStr());

    data.put("body", "我来下单啦");

    data.put("out_trade_no", orderNo);

    data.put("sign_type", "MD5");

    data.put("total_fee", orderFee);

    data.put("spbill_create_ip", requestIp);

    data.put("openid", openid);

    data.put("notify_url",ymlParament.getWx_callback_url());

    data.put("trade_type", "JSAPI"); // 此处指定为JSAPI支付

    Map wxOrderResult = WxPay.unifiedorder(data,wxH5Pay);

    if("FAIL".equals(wxOrderResult.get("return_code"))){

    throw new RuntimeException(wxOrderResult.get("return_msg"));

    }

    /* IsNull自定义,主要判断非空 */

    if (IsNull.isNull(wxOrderResult.get("prepay_id"))) {

    throw new RuntimeException("微信支付下单成功后,返回的prepay_id为空");

    }

    return wxOrderResult;

    }

    @Override

    public Map insertWxH5Pay(String orderNo,String orderFee, String requestIp, String openid) {

    try {

    /* 微信下单 */

    Map wxOrderResult = wxUnifiedOrder(orderNo, orderFee, requestIp, openid);

    Map chooseWXPay = new HashMap<>();

    /* 这里我遇到一个大坑,这里的key值是要驼峰式写法,而APP支付却不用!!! */

    chooseWXPay.put("appId", ymlParament.getH_app_id());

    chooseWXPay.put("timeStamp", WxUtils.create_timestamp());

    chooseWXPay.put("nonceStr", wxOrderResult.get("nonce_str"));

    chooseWXPay.put("package", "prepay_id=" + wxOrderResult.get("prepay_id"));

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

    String signature = WXPayUtil.generateSignature(chooseWXPay, ymlParament.getH_key());

    chooseWXPay.put("paySign", signature);

    return chooseWXPay;

    } catch (Exception e) {

    e.printStackTrace();

    throw new RuntimeException(e.getMessage());

    }

    }controller层(略)

    微信支付成功回调关键代码

    @Resource(name = WxParament.H5_WX_PAY)

    private WXPay wxH5Pay;

    @ApiOperation("微信支付回调")

    @PostMapping("callback")

    public String callback(HttpServletRequest request) throws Exception {

    try {

    // 1、获取参数

    Map params = getMapByRequest(request);

    log.info("微信回调回来啦!!!!" + params);

    // 2、校验

    checkCallbackWxPay(params);

    //业务逻辑

    return wxPaySuccess();

    } catch (Exception e) {

    e.printStackTrace();

    return wxPayFail(e.getMessage());

    }

    }

    /**

    * 获取微信过来的请求参数

    * @param request

    * @return

    * @throws Exception

    */

    private static Map getMapByRequest(HttpServletRequest request) throws Exception{

    InputStream inStream = request.getInputStream();

    ByteArrayOutputStream outSteam = new ByteArrayOutputStream();

    byte[] buffer = new byte[1024];

    int len = 0;

    while ((len = inStream.read(buffer)) != -1) {

    outSteam.write(buffer, 0, len);

    }

    Map ret= WXPayUtil.xmlToMap(new String(outSteam.toByteArray(), "utf-8"));

    outSteam.close();

    inStream.close();

    return ret;

    }

    /*校验 */

    private void checkCallbackWxPayAircraft(Map params)

    throws Exception {

    if ("FAIL".equals(params.get("result_code"))) {

    throw new Exception("微信支付失败");

    }

    if (!checkWxCallbackSing(params, wxH5Pay)) {

    throw new Exception("微信支付回调签名认证失败");

    }

    //校验金额

    //判断订单是否重复

    //....业务逻辑

    }

    /**

    * 检查微信回调签名 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7

    *

    * @param wp 传入:@Autowired WXPay

    */

    private static boolean checkWxCallbackSing(Map notifyMap, WXPay wp) throws Exception {

    return wp.isPayResultNotifySignatureValid(notifyMap);

    }

    /**

    * 微信支付返回参数结果封装

    */

    private static String wxPaySuccess() throws Exception {

    Map succResult = new HashMap();

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

    succResult.put("return_msg", "OK");

    return WXPayUtil.mapToXml(succResult);

    }

    /**

    * @param mess 错误消息提示

    * @return 微信返回错我的提示

    * @throws Exception

    */

    private static String wxPayFail(String mess) throws Exception {

    Map succResult = new HashMap();

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

    succResult.put("return_msg", IsNull.isNull(mess)?"自定义异常错误!":mess);

    return WXPayUtil.mapToXml(succResult);

    }

    补充如果不想验证签名,还有一种方式判断是否支付成功,就是调用微信查询订单接口查看是否支付成功关键代码

    /*调用微信查询订单接口*/

    Map orderqueryRes = orderquery(wXH5Pay,params.get("out_trade_no"));

    /*交易成功*/

    if (!"SUCCESS".equals(orderqueryRes.get("trade_state"))){

    throw new Exception("<===微信支付失败====>订单号为【"+ params.get("out_trade_no")+ "】的订单");

    }

    /**

    * 查询支付结果 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2

    */

    private static Map orderquery(WXPay wxpay, String outTradeNo) throws Exception {

    Map parament = new HashMap();

    parament.put("out_trade_no", outTradeNo);

    return wxpay.orderQuery(parament);

    }

    展开全文
  • 这次给大家带来ThinkPHP实现jsapi支付详解,ThinkPHP实现jsapi支付的注意事项有哪些,下面就是实战案例,一起来看一下。当时的环境是没有使用框架的,直接在一个域名指向的目录下边新建目录之后访问该目录实现的,但...
  • 商户已有H5商城网站,用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程 广泛应用微信商城的支付 完成微信网页授权以及微信JSAPI支付的实现,涉及到https,xml的生成与解析,MD5的...
  • 微信JSAPI支付

    2020-03-21 08:55:42
    JSAPI支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。 2.基本设置 2.1 支付授权目录 请确保实际支付时的请求目录与后台配置的目录一致,否则将无法...
  • 微信支付V3版系列课程详细讲解微信支付的JSAPI支付、H5支付、Native支付、申请退款、支付结果通知、退款结果通知、申请交易账单、申请资金账单、下载账单、关闭订单。提供java版、c#版、python3版课程。按照课程体系...
  • 微信支付V3版系列课程详细讲解微信支付的JSAPI支付、H5支付、Native支付、申请退款、支付结果通知、退款结果通知、申请交易账单、申请资金账单、下载账单、关闭订单。提供java版、c#版、python3版课程。按照课程体系...
  • 微信支付V3版系列课程详细讲解微信支付的JSAPI支付、H5支付、Native支付、申请退款、支付结果通知、退款结果通知、申请交易账单、申请资金账单、下载账单、关闭订单。 提供java版、c#版、python3版课程。 按照课程...
  • 微信点金计划公众号支付JSAPI支付后页面自动关闭 https://www.huilianpay.com/forum.php?mod=viewthread&tid=8&fromuid=1
  • 这篇文章主要介绍了ThinkPHP实现微信支付(jsapi支付)流程教程详解,需要的朋友可以参考下之前写过一篇文章讲了PHP实现微信支付(jsapi支付)流程 ,详见文章:PHP实现微信支付(jsapi支付)流程。当时的环境是没有使用...
  • 微信支付JSAPI支付

    2019-07-05 16:31:00
    JSAPI支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。应用场景有: ◆ 用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付 ◆ 用户的好友...
  • jsapi支付和退款.zip

    2019-06-03 21:07:02
    jsapi支付和退款
  • 支付demo,集成了支付宝网站支付,微信jsapi支付,银联网页支付
  • 微信支付之JSAPI支付

    千次阅读 2018-12-06 16:10:22
    JSAPI支付 JSAPI支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付 使用场景 用户在微信公众账号(必须是服务号)内进入商家公众号,打开某个H5页面,...
  • 微信支付工具类,包含了微信 JSAPI支付、扫码支付代码。
  • 支付demo,集成了支付宝网站支付,微信jsapi支付,银联网页支付
  • php微信支付插件,包含Native扫码和JSAPI支付
  • 主要介绍了ThinkPHP实现微信支付(jsapi支付)流程教程详解,需要的朋友可以参考下
  • 主要介绍了PHP实现微信支付(jsapi支付)流程步骤详解,需要的朋友可以参考下
  • 微信JSAPI支付——WePay

    2016-06-02 18:43:05
    Java编写的微信JSAPI支付
  • 本站收录这篇文章公众号微信支付遭遇:微信支付JSAPI报错:支付验证签名失败 错误排坑文章,详细解说文章中相关公众号 微信支付 JSAPI 支付验证 签名 技术与知识,欢迎能给大家一些在这方面的支持和帮助!...
  • 主要介绍了微信支付java版本之JSAPI支付,发送模板消息,感兴趣的小伙伴们可以参考一下
  • ecshop微信JSAPI支付

    2015-12-21 14:26:32
    ecshop微信JSAPI支付,从线上网站中拿下来的,可以完美使用,不清楚的可以浏览,只支持在微信内置浏览器中使用,WAP浏览器要申请微信WAP支付
  • 微信 JSAPI 支付

    2020-05-23 20:21:14
    一、申请微信公众号、开通微信支付,通过【APPID】将两者关联,具体操作步骤参考:点击查看 二、在公众号管理后台设置...七、生成 JSAPI 支付需要的参数 八、用户输完支付密码,前台轮询订单状态,后台在 NOTIFY_U...
  • 微信支付Jsapi支付

    2016-10-24 09:34:45
    Jsapi支付在微信内调用微信支付的时候使用,文档直接参考微信提供的 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1 需要四个参数  APPID:绑定支付的APPID(必须配置)  MCHID:商户号(必须...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,398
精华内容 959
关键字:

jsapi支付