美文网首页
微信公众号JSAPI支付详细开发过程

微信公众号JSAPI支付详细开发过程

作者: 华仔_c656 | 来源:发表于2018-11-26 13:09 被阅读0次

简介:这几天公司有个活动需要用到微信公众号支付,最后成功了完成支付。但第一次使用微信的支付中间遇到一些问题方便以后参考,下面总结整个调用的过程。

  • 开发环境:java
  • 开发系统:win10
  • 开发工具:idea2018
  • 2018-11-26

在开发之前我们要准备以下资料:

  • 开发者ID(AppID) 这个资料在微信公众号开发配置里查看
  • (AppSecret) 这个资料在微信公众号开发配置里查看
  • 接口权限网页服务 网页白名单(这个地方要备案域名)
    支付界面设置这里要开通 JSAPI支付 -https://pay.weixin.qq.com
    产品中心
    -配置好授权的支付页面(此处主要是支付的回调和页面授权)

下面是操作环节和代码code核心部分

  1. 统一下单
    接口地址 URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder
字段名 变量名 必填 类型 描述
公众账号ID appid String(21) 这里就是你公众号appid
商户号 mch_id String(32) 这个是支付商户号
随机字符串 nonce_str String(32) 这可以用自带的例子里面生成
签名 sign String(32) 详见签名生成算法
商品描述 body String(128) 这是简单的描述支持中文
商户订单号 out_trade_no String(32) 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-* 且在同一个商户号下唯一
标价金额 total_fee Int 订单总金额,单位为分
终端IP spbill_create_ip String(16) 提交的IP123.12.12.123
通知地址 notify_url String(256) http://www.weixin.qq.com/wxpay/pay.php这个后面通知用的
交易类型 trade_type String(16) JSAPI JSAPI支付 NATIVE Native支付 APP APP支付https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2

以上参数是必填项目
从上面的格式我们看到很多东西都是自己定义的,唯一的一个东西就是 签名
设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
也就是说 上面你要发送的这些信息都要拼接成一个字符串
比如你要发送这些

mch_id: 10000100 
device_info: 1000 
body: test 
nonce_str: ibuaiVcKdpRxkhJA 

最后拼接后的格式是

string A="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA"; 

按照参数名ASCII码从小到大排序(字典序) 使用下面的函数拼接比较方便

    public static String formatUrlMap(Map<String, String> paramsMap, boolean urlEncode, boolean keyToLower) {

        String buff = "";
        Map<String, String> tmpMap = paramsMap;

        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());

            //对所有传入参数按照字段名的ASCII码从小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });

            //构造URL 键值对的格式
            StringBuffer buf = new StringBuffer();
            for (Map.Entry<String, String> item : infoIds) {
                if (StringUtils.isNotBlank(item.getKey())) {
                    String key = item.getKey();
                    String value = item.getValue();
                    if (urlEncode) {
                        value = URLEncoder.encode(value, "utf-8");
                    }
                    if (keyToLower) {
                        buf.append(key.toLowerCase() + "=" + value);
                    } else {
                        buf.append(key + "=" + value);
                    }
                    buf.append("&");
                }
            }
            buff = buf.toString();

            if (StringUtils.isNotEmpty(buff)) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return buff;
    }

第二步 key 在商户注册里面设置 https://pay.weixin.qq.com

stringSignTemp=stringA+"&key=192006250b4c09247ec02edce69f6a2d" //注:key为商户平台设置的密钥key 

第三步:拼接API密钥: 有二个方式 我用的是md5

string SignTemp=A+"&key=192006250b4c09247ec02edce69f6a2d" //注:key为商户平台设置的密钥key 

sign=MD5(SignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7" //注:MD5签名方式

sign=hash_hmac("sha256",SignTemp,key).toUpperCase()="6A9AE1657590FD6257D693A078E1C3E4BB6BA4DC30B23E0EE2496E54170DACD6" //注:HMAC-SHA256签名方式

这里注意都要转成大写

到这里第一大步骤就完成了。可以post数据了,如果post成功会得到类似下面的数据

<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg><appid><![CDATA[wx**********7c26]]></appid><mch_id><![CDATA[14******02]]></mch_id><device_info><![CDATA[WEB]]></device_info><nonce_str><![CDATA[rwo6Cw6mCS3tVeBi]]></nonce_str><sign><![CDATA[CF0D8*******8F56AE8401433]]></sign><result_code><![CDATA[SUCCESS]]></result_code><prepay_id><![CDATA[wx26125**********b3701824863]]></prepay_id><trade_type><![CDATA[JSAPI]]></trade_type></xml>

这里最主要的是 prepay_id=wx26125**********b3701824863 这样的一个类型
然后二次签名
参数需要重新进行签名计算,参与签名的参数为:appId、timeStamp、nonceStr、package、signType,参数区分大小写
下面是我的二次签名代码

Map<String, String> paraMap = new HashMap<String, String>();
paraMap.put("appId",wappId);
paraMap.put("timeStamp", timeStamp);
paraMap.put("nonceStr", nonceStr);
paraMap.put("package",spackage);
paraMap.put("signType",signType);
String SinSring = StringUtil.formatUrlMap(paraMap,false,false);//按照参数名ASCII码从小到大排序(字典序)

String paySign= WXPayUtil.MD5((SinSring+"&key="+key));
paraMap.put("paySign",paySign);

Map<String, Object> mapky = new HashMap<>();
mapky.put("appId", wappId);
mapky.put("timeStamp", timeStamp);
mapky.put("nonceStr", nonceStr);
mapky.put("package", spackage);
mapky.put("signType", signType);
mapky.put("paySign",paySign);

将二次签名的信息发送到客户端
这个是官方给的唤醒 支付界面
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
注:JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。
示例代码如下:


function onBridgeReady(){
   WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
         "appId":"wx2421b1c4370ec43b",     //公众号名称,由商户传入     
         "timeStamp":"1395712654",         //时间戳,自1970年以来的秒数     
         "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串     
         "package":"prepay_id=u802345jgfjsdfgsdg888",     
         "signType":"MD5",         //微信签名方式:     
         "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
      },
      function(res){
      if(res.err_msg == "get_brand_wcpay_request:ok" ){
      // 使用以上方式判断前端返回,微信团队郑重提示:
            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
      } 
   }); 
}
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();
}

最后支付完成你会收到一个 微信支付的 支付结果通知
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8

就是上面 统一下单 那个地址会得到一个通知成功的信息,只要返回 下面格式的代码就可以了

<xml>

<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>

以上是腾讯的微信支付过程

相关文章

  • 微信公众号JSAPI支付详细开发过程

    简介:这几天公司有个活动需要用到微信公众号支付,最后成功了完成支付。但第一次使用微信的支付中间遇到一些问题方便以后...

  • 微信支付JSAPI支付

    记一次微信支付JSAPI支付功能集成。 JSAPI支付前提是必须在微信环境中(公众号、聊天界面打开链接),否则无法...

  • 微信公众号支付

    微信公众号支付使用的是JSAPI支付,后端调用微信支付demo中统一下单的接口获取支付参数返回给前端,在公众号中直...

  • 支付如何调取第三方的sdk--收银台页面描述

    收银台页面微信支付方式:JSAPI(微信公众号支付) 微信里、微信的朋友圈 点开 网址MWEB(微信h5支付) ...

  • 微信公众号开发之推广支持

    微信极速开发系列文章:点击喜欢不迷路 前几篇文章详细介绍了微信App支付、公众号支付、微信红包、微信刷卡以及支付宝...

  • PHP微信公众号支付开发总结

    微信公众号开发是很常见的开发,其中微信支付占有很大的比重。微信公众号分为服务号和订阅号,服务号支持微信支付。 前期...

  • JSAPI 简介

    JSAPI 简介 JSAPI支付是指商户通过调用微信支付提供的JSAPI接口,在支付场景中调起微信支付模块完成收款...

  • 公众号网页对接微信支付

    一、背景 公众号网页对接微信支付,因为该网页会在多端打开,所以需对接H5支付,Native支付以及JSAPI支付,...

  • 【微信支付】公众号支付

    一.公众号支付介绍 公众号支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口...

  • esaywechat 微信公众号jsapi支付

    esaywechat 对应各框架版本laravel =》overtrue/laravel-wechattp ...

网友评论

      本文标题:微信公众号JSAPI支付详细开发过程

      本文链接:https://www.haomeiwen.com/subject/ndtbtqtx.html