美文网首页iOS 常见问题汇总
iOS-微信支付(二)-了解服务器签名、加密

iOS-微信支付(二)-了解服务器签名、加密

作者: charleswang | 来源:发表于2017-07-26 09:39 被阅读964次

    一、声明:

    一般微信支付签名、加密都在服务器端做的,在iOS中只需要调用服务器的接口获取(partnerid、prepayid、noncestr、timeStamp、sign)数据,然后调用微信支付,为了更好的了解微信支付,此篇文章简单的介绍服务器关于微信支付的加密签名。微信支付流程

    实现的基本的步骤:

    • 第一步:订单信息的签名
      • 1.获取客户端传过来的参数(价钱、名称等)
      • 2.设置访问微信支付服务器请求的数据类型
      • 3.创建请求微信支付服务器的参数集合(组装参数)->调用统一下单借口(URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

    下面是请求微信服务器进行一次签名的一部分的必传的参数,具体的参数见微信的开发文档

    字段名 字段
    应用的ID appid
    商户号 mch_id
    随机字符串 nonce_str
    商品描述 body
    商品详情 detail
    商户订单号 out_trade_no
    总金额 total_fee
    终端IP spbill_create_ip
    通知地址 notify_url
    交易类型 trade_type
    签名 sign
    商户秘钥 key
    • 特别注意:
      • 1.不要忘记了商户秘钥
      • 2.将这些必要的参数按顺序拼接起来(A-Z),key不参与排序,拼接在末尾,再进行MD5加密生成sign
    // 第1步-签名订单信息
    // 第一点:获取客户端传递过来的参数
    // req:客户端请求
    // resp:响应客户端请求
    req.setCharacterEncoding("UTF-8");
    resp.setCharacterEncoding("UTF-8");
    String name = req.getParameter("name");//客户端传的参数
    String price = req.getParameter("price");//客户端传的参数
    // 第二点:设置访问微信支付服务器请求数据类型
    resp.reset();
    resp.setHeader("ContentType", "text/xml");
    // 第三点:创建请求微信支付服务器参数集合// 做了请求封装
    // 微信写好一个封装案例,你可以根据服务器需求,自己定义网络请求框架
    PrepayIdRequestHandler handler = new PrepayIdRequestHandler(req, resp);
    // 统一下单的接口(调用微信支付服务器需要的接口)--->公开的
    handler.setGateUrl(ConstantUtil.URL_UNIFIEDORDER);
    // 设置密钥
    handler.setKey(PARTNER_KEY);
    // 设置应用的ID
    handler.setParameter("appid", APP_ID);
    // 商户号
    handler.setParameter("mch_id", PARTNER_ID);
    // 随机字符串
    handler.setParameter("nonce_str", WXUtil.getNonceStr());
    // 商品描述(例如:天天爱消除-游戏充值)
    handler.setParameter("body", "爱学宝-笔记本");
    // 商户订单号(自己服务器生成订单号)
    String out_trade_no = OrderUtils.getOrderNumber();
    handler.setParameter("out_trade_no", out_trade_no);
    // 总金额
    handler.setParameter("total_fee", price);
    // 终端IP(客户端IP)
    handler.setParameter("spbill_create_ip", req.getRemoteAddr());
    // 通知地址(微信服务器回调商户服务器页面)
    handler.setParameter("notify_url", ConstantUtil.NOTIFY_URL);
    // 交易类型
    handler.setParameter("trade_type", "APP”);
    // 第四点:对我们订单信息进行签名
    //将这些必要的参数按顺序拼接起来(A-Z),key不参与排序,拼接在末尾,再进行MD5加密生成sign
    String sign = handler.createMD5Sign();
    // 设置签名
    handler.setParameter("sign", sign);
    
    • 第二步:调用微信的统一下单的接口(目的:获取prepay_id)
      • 调用成功返回的结果(是个xml):
    <xml>
       <return_code><![CDATA[SUCCESS]]></return_code>
       <return_msg><![CDATA[OK]]></return_msg>
       <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
       <mch_id><![CDATA[10000100]]></mch_id>
       <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
       <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
       <result_code><![CDATA[SUCCESS]]></result_code>
       <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
       <trade_type><![CDATA[APP]]></trade_type>
    </xml>
    

    进行二次签名的必传的参数:

    字段名 字段
    应用ID appid
    商户号 partnerid
    预支付交易会话ID prepayid
    扩展字段 package
    随机字符串 noncestr
    时间戳 timestamp
    签名 sign
    String noncestr = (String) paramsMap.get("nonce_str");
    String timestamp = WXUtil.getTimeStamp();
    // 密钥
    handler.setKey(PARTNER_KEY);//秘钥排在最后
    // 设置应用的ID
    handler.setParameter("appid", APP_ID);
    // 预付单ID
    handler.setParameter("prepayid", prepay_id);
    // 扩展字段
    handler.setParameter("package", "Sign=WXPay");
    // 商户号
    handler.setParameter("partnerid", PARTNER_ID);
    // 随机字符串
    handler.setParameter("noncestr", noncestr);
    // 时间戳
    handler.setParameter("timestamp", timestamp);
    
    // 进行二次签名(签名参数不一样)// 第一次签名:对订单信息签名,获取prepay_id// 第二次签名:对支付信息进行签名
    sign = handler.createMD5Sign();
    
    • 第三步:将服务器的签名的模型返回到客户端:
    // 第4步-将签名信息返回客户端(xml、json都可以)// 采用Json解析(构建json--->返回客户端)
    OrderBean orderBean = new OrderBean();
    orderBean.setAppid(APP_ID);
    orderBean.setNoncestr(noncestr);
    orderBean.setPackageValue("Sign=WXPay");
    orderBean.setPartnerid(PARTNER_ID);
    orderBean.setPrepayid(prepay_id);
    orderBean.setTradeType((String) paramsMap.get("trade_type"));
    orderBean.setSign(sign);
    orderBean.setTimestamp(timestamp);
    orderResult.setOrderBean(orderBean);
    

    下面是在微信支付中遇到的问题和注意事项:

    • APP支付中的常见问题

    • 第一点:服务器订单的签名:(一次签名)

      • 注意事项一:订单号产生,服务器产生
      • 注意事项二:生产订单算法(采用微信提供算法)
      • 注意事项三:生成随机字符串(服务器,同样你也要采用微信API demo提供算法)
      • 注意事项四:商品描述格式(应用名称-商品名称)
      • 注意事项五:商品价格单位(价格:单位分)
    • 第二点:服务器调用统一下单接口,获取prepay_id 下单的地址API

      • 注意事项一:商户密钥必需参与第一次签名
      • 注意事项二:签名这些参数按照顺序进行签名(微信开发文档参数列表进行排序)(A-Z排序,集合自动排序)
      • 注意事项三:拼接基本参数,密钥参数排在最后(key不参与排序)
      • 注意事项四:请求参数时候,格式必需是xml格式 原始数据格式(key-value格式)——>xml格式,然后访问微信支付统一下单接口(微信服务器要求)
      • 注意事项五:拼接xml参数,参数也是有顺序的 官方技术支持邮箱:wepayTS@tencent.com
      • 注意事项六:签名信息放在最后拼接xml文件
      • 注意事项七:return_code和result_code返回都必须是SUCCESS,表示统一下单接口成功
    • 第三点:进行二次签名—-支付签名

      • 注意事项一:支付签名信息随机字符串,必需采用微信返回的随机字符串
      • 注意事项二:二次签名参数名称必需是小写
      • 注意事项三:二次签名,密钥放在最后
      • 注意事项四:返回客户端数据必需是二次签名(支付签名)

    下一章介绍iOS中的客户端的调用

    相关文章

      网友评论

        本文标题:iOS-微信支付(二)-了解服务器签名、加密

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