精华内容
下载资源
问答
  • 微信小程序支付回调 java后台

    千次阅读 热门讨论 2019-03-29 13:56:44
    这里接着上一篇微信支付开始 ...其实微信支付回调的验签就是讲微信回调返回给你的全部数据除去sign外中心加密一次和微信回调返回的sign进行对比,一致就通过,不...

    这里接着上一篇微信支付开始 (https://blog.csdn.net/qq_39897814/article/details/88890484

    以下是微信支付的回调,可能有人在这里的回调中的验签不通过也可以看一下,因为我也是一开始没通过,经过各种查资料最终成功

    其实微信支付回调的验签就是讲微信回调返回给你的全部数据除去sign外中心加密一次和微信回调返回的sign进行对比,一致就通过,不一致说明有风险有可能被改过,所以有回调验签不通过的朋友可以将微信回调的sign先提出来 然后从返回的数据中心去掉在重新加密对比 也可以继续往下看

        /**
        *微信支付回调
        */
        @RequestMapping("notify")
        public String notify(HttpServletRequest request) {
            log.info("================================================开始处理微信小程序发送的异步通知");
    
            //1 获取微信支付异步回调结果
            String xmlResult = WeiXinPayUtil.getPostStr(request);
    
            Map<String, String> resultMap = null;
            try {
                //将结果转成map
                resultMap = WXPayUtil.xmlToMap(xmlResult);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            //订单号
            String orderNo = resultMap.get("out_trade_no");
            log.info("订单号:------------------"+orderNo+"结束----------");
            String result_code = resultMap.get("result_code");
            //回调返回的加密签名 保存下来 下面会进行对比
            String sign = resultMap.get("sign");
            //去掉sign和利用微信回调回来的信息重新加密
            resultMap.remove("sign");
            String sign1="";
            try {
                //重新加密 获取加密的签名
                 sign1=WXPayUtil.generateSignature(resultMap, WXMiniPayConfig.KEY); //签名
            }catch (Exception e){
    
            }
    
     
            String resultCode;
            String resultMsg;
            //对比微信回调的加密与重新加密是否一致  一致即为通过 不一致说明呗改动过 加密不通过
            log.info("==============================================开始对比加密++++++++++++++++++++++++++++++++++++++");
            if (sign.equals(sign1)) { //验签通过
                log.info("==============================================验签通过++++++++++++++++++++++++++++++++++++++");
              
                    if (WXPayEnum.isPaymentSuccess(result_code)) {//业务结果为SUCCESS
                        /**
                         * 这里写你要处理的逻辑
                         */
                        resultCode = "SUCCESS";
                        resultMsg = "成功";
                    } else { // 业务结果为FALL
                        resultCode = "FAIL"
                        resultMsg = "业务结果为FAIL";
                    }
             
            } else {
                resultCode = "FAIL";
                resultMsg = "验签未通过";
            }
    
            Map<String, String> returnMap = new HashMap<>();
            returnMap.put("return_code", resultCode);
            returnMap.put("return_msg", resultMsg);
            try {
                String s = WXPayUtil.mapToXml(returnMap);
                return s;
            } catch (Exception e) {
                e.printStackTrace();
                return "";
            }
        }
    

    这样结果就通过了,有回调前名验证没通过的朋友 要好好看看代码中的注释

    所需工具类

    public class WeiXinPayUtil {
    
    
        /**
         * 微信回调参数解析
         *
         * @param request
         * @return
         */
        public static String getPostStr(HttpServletRequest request) {
            StringBuffer sb = new StringBuffer();
            try {
                InputStream is = request.getInputStream();
                InputStreamReader isr = new InputStreamReader(is, "UTF-8");
                BufferedReader br = new BufferedReader(isr);
                String s = "";
    
                while ((s = br.readLine()) != null) {
                    sb.append(s);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            String xml = sb.toString(); //次即为接收到微信端发送过来的xml数据
            return xml;
    
        }
    public class WXMiniPayConfig {
    
        //api秘钥  从微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 获取
        public static final String KEY = "";
        //    微信支付分配的公众账号ID(企业号corpid即为此appId)
        public static final String APP_ID = "";
        //微信支付分配的商户号
        public static final String MCH_ID = "";
    
    }
    
    
    import java.io.ByteArrayInputStream;
    import java.io.InputStream;
    import java.io.StringWriter;
    import java.util.*;
    import java.security.MessageDigest;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.transform.OutputKeys;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import com.github.wxpay.sdk.WXPayConstants.SignType;
    
    
    public class WXPayUtil {
    
        /**
         * XML格式字符串转换为Map
         *
         * @param strXML XML字符串
         * @return XML数据转换后的Map
         * @throws Exception
         */
        public static Map<String, String> xmlToMap(String strXML) throws Exception {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx=0; idx<nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            try {
                stream.close();
            }
            catch (Exception ex) {
    
            }
            return data;
        }
    
        /**
         * 将Map转换为XML格式的字符串
         *
         * @param data Map类型数据
         * @return XML格式的字符串
         * @throws Exception
         */
        public static String mapToXml(Map<String, String> data) throws Exception {
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
            org.w3c.dom.Document document = documentBuilder.newDocument();
            org.w3c.dom.Element root = document.createElement("xml");
            document.appendChild(root);
            for (String key: data.keySet()) {
                String value = data.get(key);
                if (value == null) {
                    value = "";
                }
                value = value.trim();
                org.w3c.dom.Element filed = document.createElement(key);
                filed.appendChild(document.createTextNode(value));
                root.appendChild(filed);
            }
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            DOMSource source = new DOMSource(document);
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StringWriter writer = new StringWriter();
            StreamResult result = new StreamResult(writer);
            transformer.transform(source, result);
            String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
            try {
                writer.close();
            }
            catch (Exception ex) {
            }
            return output;
        }
    
    
        /**
         * 生成带有 sign 的 XML 格式字符串
         *
         * @param data Map类型数据
         * @param key API密钥
         * @return 含有sign字段的XML
         */
        public static String generateSignedXml(final Map<String, String> data, String key) throws Exception {
            return generateSignedXml(data, key, SignType.MD5);
        }
    
        /**
         * 生成带有 sign 的 XML 格式字符串
         *
         * @param data Map类型数据
         * @param key API密钥
         * @param signType 签名类型
         * @return 含有sign字段的XML
         */
        public static String generateSignedXml(final Map<String, String> data, String key, SignType signType) throws Exception {
            String sign = generateSignature(data, key, signType);
            data.put(WXPayConstants.FIELD_SIGN, sign);
            return mapToXml(data);
        }
    
    
        /**
         * 判断签名是否正确
         *
         * @param xmlStr XML格式数据
         * @param key API密钥
         * @return 签名是否正确
         * @throws Exception
         */
        public static boolean isSignatureValid(String xmlStr, String key) throws Exception {
            Map<String, String> data = xmlToMap(xmlStr);
            if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {
                return false;
            }
            String sign = data.get(WXPayConstants.FIELD_SIGN);
            return generateSignature(data, key).equals(sign);
        }
    
        /**
         * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。
         *
         * @param data Map类型数据
         * @param key API密钥
         * @return 签名是否正确
         * @throws Exception
         */
        public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception {
            return isSignatureValid(data, key, SignType.MD5);
        }
    
        /**
         * 判断签名是否正确,必须包含sign字段,否则返回false。
         *
         * @param data Map类型数据
         * @param key API密钥
         * @param signType 签名方式
         * @return 签名是否正确
         * @throws Exception
         */
        public static boolean isSignatureValid(Map<String, String> data, String key, SignType signType) throws Exception {
            if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {
                return false;
            }
            String sign = data.get(WXPayConstants.FIELD_SIGN);
            return generateSignature(data, key, signType).equals(sign);
        }
    
        /**
         * 生成签名
         *
         * @param data 待签名数据
         * @param key API密钥
         * @return 签名
         */
        public static String generateSignature(final Map<String, String> data, String key) throws Exception {
            return generateSignature(data, key, SignType.MD5);
        }
    
        /**
         * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
         *
         * @param data 待签名数据
         * @param key API密钥
         * @param signType 签名方式
         * @return 签名
         */
        public static String generateSignature(final Map<String, String> data, String key, SignType signType) throws Exception {
            Set<String> keySet = data.keySet();
            String[] keyArray = keySet.toArray(new String[keySet.size()]);
            Arrays.sort(keyArray);
            StringBuilder sb = new StringBuilder();
            for (String k : keyArray) {
                if (k.equals(WXPayConstants.FIELD_SIGN)) {
                    continue;
                }
                if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
                    sb.append(k).append("=").append(data.get(k).trim()).append("&");
            }
            sb.append("key=").append(key);
            if (SignType.MD5.equals(signType)) {
                return MD5(sb.toString()).toUpperCase();
            }
            else if (SignType.HMACSHA256.equals(signType)) {
                return HMACSHA256(sb.toString(), key);
            }
            else {
                throw new Exception(String.format("Invalid sign_type: %s", signType));
            }
        }
    
    
        /**
         * 获取随机字符串 Nonce Str
         *
         * @return String 随机字符串
         */
        public static String generateNonceStr() {
            return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
        }
    
    
        /**
         * 生成 MD5
         *
         * @param data 待处理数据
         * @return MD5结果
         */
        public static String MD5(String data) throws Exception {
            java.security.MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        }
    
        /**
         * 生成 HMACSHA256
         * @param data 待处理数据
         * @param key 密钥
         * @return 加密结果
         * @throws Exception
         */
        public static String HMACSHA256(String data, String key) throws Exception {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        }
    }

     

    展开全文
  • 1、回调地址必须是80端,也就是http地址 2、复制网址到浏览器上能访问即可

    1、回调地址必须是80端,也就是http地址

    2、复制网址到浏览器上能访问即可

    展开全文
  • 在做小程序支付回调时,先调用【统一下单】接口,notify_url可以是http,也可以是https。然后出现支付成功没有自动执行notify_url里的方法这个问题:解决方法:首先测试 $test=fopen('/data/wx/modules/xcx/...

    在做小程序支付回调时,先调用【统一下单】接口,notify_url可以是http,也可以是https。

    然后出现支付成功没有自动执行notify_url里的方法这个问题:

    解决方法:首先测试

          $test=fopen('/data/wx/modules/xcx/controllers/test.txt','w') or die("Unable to open file!");
         if(file_exists('/data/wx/modules/xcx/controllers/test.txt')){
               fwrite($test, $GLOBALS["HTTP_RAW_POST_DATA"]);

          }        

           fclose($test);

    手动访问,看是否能新建文件,不能的话检查权限。

    最后问题原因是yii框架的csfr验证卡住的,这个框架自带post验证,所有禁止了微信那边传递支付成功信息!

    在controller里加public $enableCsrfValidation = false;来禁止这个验证就好了

    展开全文
  • 微信相关-微信小程序支付后,微信回调我们接口的签名验证 1.微信小程序的支付流程 点击这里移步去观看我的上一篇文章:微信相关-微信小程序支付的实现(详细的一批版) 2.为什么对微信回调我们的接口进行签名验证 ...

    微信相关-微信小程序支付后,微信回调我们接口的签名验证

    目录

    微信相关-微信小程序支付后,微信回调我们接口的签名验证

    1.微信小程序的支付流程

    2.为什么对微信回调我们的接口进行签名验证

    3.讲思路

    4.重要点的代码


    1.微信小程序的支付流程

    点击这里移步去观看我的上一篇文章:微信相关-微信小程序支付的实现(详细的一批版)

    2.为什么对微信回调我们的接口进行签名验证

    因为微信的支付的回调接口是涉及到金钱的,非常重要的一个对外接口,这就导致这个接口很容易被人攻击,我们就需要对是谁在调用接口进行验证,确保百分百是微信在调用我们的接口。

    3.讲思路

    先不上代码,因为每个人写的代码都不相同,直接看代码可能会出现各种问题

    (1).第一步,在回调接口里面,把微信返回的数据全部的解析出来,存放在一个map集合里。

    (2).第二步,把微信返给我们的 sign 里的值取出来,这个就是微信那边生成的一个签名,具体的生成规则就自己去看微信的文档了。

    (3).第三步,把 sign 从map里面去除掉,因为我们本地解密时所用到的参数是微信返回给我们的全部参数,但是不包括 sign。

    (4).第四步,将mao集合所有内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA(这是非常官方的说法)

    (5).第五步,在stringA最后拼接上key得到stringSignTemp字符串,key是当前小程序的商户秘钥,注意:是商户秘钥,而不是小程序秘钥,拼接的格式是字符串stringA+“&key=商户秘钥”

    (6).第六步,将拼接好的字符串,进行md5运算(这里运算的格式默认是md5,但是还有HMAC-SHA256格式)

    (7).第七部,把最后我们运算出来的签名跟微信返回给我们的签名对比,如果相同,就证明是微信在调用我们的接口,就可以继续下列的任务

    4.重要点的代码

    代码里面使用到的工具类,看我的上一篇文章,里面的

    WXPayUtil 和 WxPayApi

    这2个工具类,由于代码太长了,就不在重复的贴在这个帖子里面了

            //准备一个map集合
            Map<String, String> stringStringMap = null;
            try {
            //使用工具类,把微信返给我们的数据用key,value的格式放入到map集合里面
                stringStringMap = wxPayApi.payCallBack(request);
            } catch (Exception e) {
                e.printStackTrace();
            }
            SysUser user = null;
            //判断是不是支付成功,因为很多参数是支付成功才会返回的
            if(stringStringMap.get("return_code").equals("SUCCESS")){
                //回调返回的加密签名 保存下来 下面会进行对比
                String wxSign = stringStringMap.get("sign");
                String mySign="";
                //去掉sign和利用微信回调回来的信息重新加密,这一步非常的主要
                stringStringMap.remove("sign");
                try {
                    //重新加密 获取加密的签名,StaticValue.MERCHANT_SECRET是你的商户秘钥
                    mySign=WXPayUtil.generateSignature(stringStringMap, StaticValue.MERCHANT_SECRET); //签名
                }catch (Exception e){
                }
              }

    代码很少,因为大部分代码其实都是应用到的我写的支付相关的那个帖子里面的工具类。

    但是主要不是看代码,而是分享思路。

    展开全文
  • springboot对接微信小程序支付以及回调详细代码 非常详细,完整流程代码 拿走不谢 亲测可用
  • 踩坑: 微信小程序支付流程(统一下单, 支付回调)

    万次阅读 多人点赞 2018-07-30 16:15:55
    众所周知,微信小程序目前只能使用微信支付,而且微信小程序支付相对于app支付,h5支付都要简单一些,但是该支付文档对java这语言是非常不友好的,居然没有demo,网上虽说有很多博客,但是找了好多都是跑不通,乱七八糟的很...
  • 3. 微信小程序调支付完成支付1. 小程序发起请求预支付 2. 服务端调用接口发起预支付信息 服务端接收到请求后,调用微信的api接口,调用成功会得到一个prepay_id 这个就是相当于小程序的预支付id 过程中会生成签名...
  • SpringBoot2.0微信小程序支付多次回调问题 WxJava - 微信开发 Java SDK(开发工具包); 支持包括微信支付、开放平台、公众号、企业微信/企业号、小程序等微信功能的后端开发。 第一步: 支付回调问题 微信小...
  • 在使用微信小程序开发微信支付功能时,使用云开发中的微信支付云调用,将商品信息、支付价格等信息传入云函数中,并在返回的字段payment获取wx.requestPayment接口所需要的所有信息。通过此方法完成微信支付,在wx....
  • 最近做了微信小程序支付,支付成功之后发现notify_url回调地址竟然没有访问。 检查了无数次代码,下单结果里面的回调地址看了又看,都没有错啊。 把回调地址复制出来到浏览器上面,外网也是可以访问的啊。 然后我再...
  • * 微信支付完成,回调地址url方法 */ public function PaymentCallback(){ $sKey = PAY_KEY; $arrPostData = $this->input->post(); //接受POST数据 $arrXmlData = $this->xml_to_array($arrPostData)...
  • JSPAI微信支付,支持H5、微信小程序支付SKD 微信支付代码包含回调逻辑,只需要把appid、密钥、回调地址等一些信息做好配置即可飞快跑起来。
  • 下面是控制器Pay.php <?php namespace app\wechatapi\controller; use app\wechatapi\controller\Base; use think\Db; use think\Controller; use \app\wechatapi\model;... //吊起微信支付 ...
  • 小程序登录,获取openid后端调用微信支付统一下单得到预支付交易会话标识prepay_id组装小程序支付所需的几个参数,并进行签名支付成功,主动查询订单支付状态接收微信支付回调通知微信小程序支付:...
  • 又为大家带来简单的c#后台支付结果回调方法,首先还是要去微信官网下载模板(WxPayAPI),将模板(WxPayAPI)添加到服务器上,然后在打开WxPayAPI项目中的example文件下的 NativeNotifyPage.aspx打开网页中的代码页...
  • 微信小程序支付

    2018-03-20 20:15:30
    微信小程序支付核心: 1、小程序向服务端发送获取openid 2、服务端向微信统一下单 3、服务器收到返回信息二次签名发回给小程序 4、小程序发起支付 5、服务端收到回调说明:下面是小程序代码&lt;!--index....
  • 1:微信发起支付请求,向后端请求数据 2:后台处理请求,配置支付,返回小程序...4:支付完成,失败进行回调,处理数据 //支付 pay() { // console.log(123) if (this.data.count.num == 0) { this.show_hint({...
  • 微信小程序支付的主要逻辑集中在后端,前端只需携带支付所需的数据请求后端接口然后根据返回结果做相应成功失败处理即可。我在后端使用的是php,当然在这篇博客里我不打算贴一堆代码来说明支付的具体实现,而主要会...
  • Php微信小程序支付

    2020-03-23 11:07:34
    微信小程序支付官方参数小程序中代码后端发起支付代码支付回调 官方参数 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html 小程序中代码 如果说你的小...
  • 微信小程序支付案例

    千次阅读 2018-09-21 10:48:06
    过程为:先触发微信小程序支付后台得到预付款ID(prepare_id),然后小程序前台会自动弹出一个对应金额的支付窗口,然后用户输入正确密码,支付成功,触发用户的回调函数做业务操作。   更多分布式微服务课程关注:...
  • 首先说明一下,微信小程序支付的主要逻辑集中在后端,前端只需携带支付所需的数据请求后端接口然后根据返回结果做相应成功失败处理即可。我在后端使用的是php,当然在这篇博客里我不打算贴一堆代码来说明支付的具体...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 338
精华内容 135
关键字:

微信小程序支付回调

微信小程序 订阅