微信支付_微信支付支付宝支付 - CSDN
微信支付 订阅
微信支付是集成在微信客户端的支付功能,用户可以通过手机完成快速的支付流程。微信支付以绑定银行卡的快捷支付为基础,向用户提供安全、快捷、高效的支付服务。 [1]  自2017年11月23日起,微信支付服务功能在中国铁路客户服务中心12306网站上线运行。 [2]  2018年4月1日,消费者在使用微信钱包扫描静态条码支付时,单日使用零钱包支付的上限不超过500元,同时微信关联的所有银行卡还可以再独立获得500元的支付上限。 [3]  2018年3月,车牌=付款码,微信直接推出“高速e行”。 [4]  2018年6月29日,微信支付与米其林指南在广州宣布达成战略合作。 [5]  2020年2月,微信支付取得了尼泊尔央行的运营牌照。 [6] 展开全文
微信支付是集成在微信客户端的支付功能,用户可以通过手机完成快速的支付流程。微信支付以绑定银行卡的快捷支付为基础,向用户提供安全、快捷、高效的支付服务。 [1]  自2017年11月23日起,微信支付服务功能在中国铁路客户服务中心12306网站上线运行。 [2]  2018年4月1日,消费者在使用微信钱包扫描静态条码支付时,单日使用零钱包支付的上限不超过500元,同时微信关联的所有银行卡还可以再独立获得500元的支付上限。 [3]  2018年3月,车牌=付款码,微信直接推出“高速e行”。 [4]  2018年6月29日,微信支付与米其林指南在广州宣布达成战略合作。 [5]  2020年2月,微信支付取得了尼泊尔央行的运营牌照。 [6]
信息
发布时间
2013年8月5日
所属企业
腾讯
平    台
微信第三方平台
所属用户
微信app使用者
中文名
微信支付
注册用户
8亿(2017年12月) [7]
支持系统
IOS,安卓
外文名
WeChat Pay
微信支付发展历程
2013年8月5日,财付通与微信合作推出微信支付。 [8]  微信支付正式上线。 [9]  2014年1月4日,滴滴打车接入微信支付,3天突破10万单。 [10]  2014年1月27日,微信正式推出微信红包,并迅速流行开来。 [8]  2014年08月28日,智慧生活全行业解决方案正式公布。 [11]  2015年02月18日,开创春晚红包,10.1亿次收发创新了春节全民红包互动的新高潮。 [12]  2015年05月,零钱用户突破3亿。 [12]  2016年01月,微信支付接入线下门店超30万家。 [13]  2016年08月8日,提出“无现金生活”理念,打造全球首个移动支付节日“无现金日”,倡导低碳、高效的生活方式。 [14]  2018年6月29日,微信支付与米其林指南在广州宣布达成战略合作。 [5]  2018年10月1日起,微信香港钱包正式为香港用户提供内地移动支付服务。用户于内地商户消费时,微信香港钱包会将所需支付的人民币金额,自动换算为对应的港币金额。服务推广期间,用户使用微信香港钱包在内地商户消费,无需支付手续费。 [15]  2019年10月,微信支付钱包入口上线银行储蓄(仅部分用户可见)服务,点击银行储蓄可跳转至工商银行存款产品。用户同意“工商银行定存相关协议”可免费开通工商银行存款账户,选择存入存款,三年期利率3.85%,随时可取,并且不需要跳转到工商银行就可以操作。 [16]  2019年5月,尼泊尔中央银行出台一项命令:在尼境内使用支付宝支付、微信支付及跨境POS机等国际支付系统(获得尼官方授权的除外)的行为是非法的,有关人员将会根据有关法令受到惩处。2020年2月上旬,微信支付取得了尼泊尔央行的运营牌照。 [6] 
收起全文
  • 微信已经融入到人们的生活中,很多企业也...这是一部中课程,需要有学习的开发者拥有微信开发和PHP的相关基础:微信支付在项目中的位置、微信支付类型、微信支付涉及内容、微信公众号支付功能实现、微信支付安全建议。
  • 让开发者快速学习微信支付功能,本课程基于Java开发工作,通过SpringBoot实现微信支 适用人群 针对互联网项目开发者,实现微信支付功能开发 课程简介 从零讲起微信支付,基于Spring Boot框架...
  • 微信支付时序图 官方文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_51、什么是时序图 是一种UML交互图,描述了对象之间传递消息的时间顺序, 用来表示用例中的行为顺序, 是强调消息时间顺序...



    微信支付时序图 官方文档:

    https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5

    1、什么是时序图
    是一种UML交互图,描述了对象之间传递消息的时间顺序, 用来表示用例中的行为顺序, 是强调消息时间顺序的交互图;
    通俗解释:就是交互流程图 (把大象装冰箱分几步)
    2、时序图包括四个元素 对象(Object), 生命线(Lifeline), 激活(Activation), 消息(Message);
    对象:时序图中的对象在交互中扮演的角色就是对象,使用矩形将对象名称包含起来, 名称下有下划线
    生命线:生命线是一条垂直的虚线, 这条虚线表示对象的存在, 在时序图中, 每个对象都有生命线
    激活:代表时序图中对象执行一项操作的时期, 表示该对象被占用以完成某个任务,当对象处于激活时期, 生命线可以拓宽为矩形
    消息:对象之间的交互是通过相互发消息来实现的,箭头上面标出消息名,一个对象可以请求(要求)另一个对象做某件事件
    消息从源对象指向目标对象,消息一旦发送便将控制从源对象转移到目标对象,息的阅读顺序是严格自上而下的
    消息交互中的实线:请求消息
    消息交互中的虚线:响应返回消息
    自己调用自己的方法:反身消息

    参考:https://www.cnblogs.com/langtianya/p/3825764.html

    统一下单接口介绍:

    商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易会话标识后再按扫码、JSAPI、APP等不同场景生成交易串调起支付。

    2、微信支付订单接口开发之订单增删改查
    简介: 微信扫码支付之统一下单接口开发之订单增删改查

    1、Dao层VideoOrder增删改查开发
    @Insert("")
    @Options(useGeneratedKeys=true, keyProperty="id", keyColumn="id")   //keyProperty java对象的属性;keyColumn表示数据库的字段
    int insert(VideoOrder order);
     
    @Select("SELECT * FROM video_order WHERE id = #{id}")
    VideoOrder findById(int id);


    @Select("SELECT * FROM video_order WHERE id = #{id}")
    VideoOrder findByOutTradeNo(String  outTradeNo);


    @Delete("DELETE FROM video_order WHERE id =#{id}")

     int delete(int  id);

    3、微信统一下单接口开发之CommonUtils和WXpayUtils开发
    简介:封装常用工具类CommonUtils和WXpayUtils


    从微信开发者文档获取部分代码 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1


    1、CommonUtils包含方法 md5,uuid等
    //生成 uuid, 即用来标识一笔单,也用做 nonce_str
    public static String generateUUID() {
    return UUID.randomUUID().toString().replaceAll("-", "")
    .substring(0, 32);
    }


    //MD5工具类
    public static String MD5(String data)  {
    try {
    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();
    } catch (Exception exception) {
    }
    return null;


    }


    2、WXPayUtil包含方法 xmlToMap,mapToXml,createSign,isCorrectPaySign


    4、微信支付Controller下单API接口开发
    简介:讲解下单接口开发,开发技巧和支付配置文件设置


    1、开发controller,开发期间不加入拦截器登录校验
    2、iputils工具类介绍
    3、加入微信支付配置
    #微信商户平台
    wxpay.mer_id=1503808832
    wxpay.key=xdclasss20182018xdclass2018x018d

    wxpay.callback=16web.tunnel.qydev.com/pub/api/v1/wechat/order/callback1

    5.签名测试结果



    XML源串

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>

    <xml>
    <appid>wxt89583oxy157pv6e</appid>
    <body>SpringBoot+Maven整合Websocket课程</body>
    <mch_id>0747785655</mch_id>
    <nonce_str>bd215711233047ba98089bd7d26e8532</nonce_str>
    <notify_url>http://qcsell.natapp1.cc/api/v1/wechat/order/callback</notify_url>

    <out_trade_no>56c0a8ae122b4b7da8f74628534a6108</out_trade_no>

    ---------------------------------------------------------------------------

    商户Key:k66z0230Vf5K22Qj70Q3U8R5460930F1


    6 调用微信统一下单接口,发送post请求,并获取响应转成map,获取交易会话的二维码链接code_url。


    1、配置统一下单接口
    2、发送请求验证
    微信统一下单响应
    <xml><return_code><![CDATA[SUCCESS]]></return_code>
    <return_msg><![CDATA[OK]]></return_msg>
    <appid><![CDATA[wx5beac15ca207c40c]]></appid>
    <mch_id><![CDATA[1503809911]]></mch_id>
    <nonce_str><![CDATA[Go5gDC2CYL5HvizG]]></nonce_str>
    <sign><![CDATA[BC62592B9A94F5C914FAAD93ADE7662B]]></sign>
    <result_code><![CDATA[SUCCESS]]></result_code>
    <prepay_id><![CDATA[wx262207318328044f75c9ebec2216783076]]></prepay_id>
    <trade_type><![CDATA[NATIVE]]></trade_type>
    <code_url><![CDATA[weixin://wxpay/bizpayurl?pr=hFq9fX6]]></code_url>
    </xml>
    3、获取code_url


    遇到问题,根据错误码解决

    https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1


    7谷歌二维码工具生成扫一扫支付二维码
    简介:使用谷歌二维码工具根据code_url生成扫一扫支付二维码

    1、生成二维码返回页端


    加入依赖
    <!-- google二维码生成包 -->
    <dependency>
       <groupId>com.google.zxing</groupId>
       <artifactId>javase</artifactId>
       <version>3.3.0</version>
    </dependency>

    <dependency>
       <groupId>com.google.zxing</groupId>
       <artifactId>core</artifactId>
       <version>2.0</version>
    </dependency>

    2、使用微信扫码完成支付
    参考资料:https://blog.csdn.net/shenfuli/article/details/68923393
    https://www.cnblogs.com/lanxiamo/p/6293580.html

    二维码知识:https://coolshell.cn/articles/10590.html

    简介:使用Ngrock本地接收微信回调,并开发回调接口

    文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3


      1 、开发支付回调接口


      //读取回调输入流   
          StringBuffer sb = new StringBuffer();    
          InputStream inputStream = request.getInputStream();    
          String line ;    
          BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));    
          while ((line = in.readLine()) != null){    
              sb.append(line);  
          }  
          in.close();  
          inputStream.close();  
          
          //解析xml成map    
          //{transaction_id=4200000141201805266700247361, nonce_str=cbb67accd8044c9ea48f3318b99d88e4, bank_type=CFT, openid=oiNKG03vVY4PHlGUEwT-ztFo8K8Y, sign=0575804DBE4E9FFF6545046FA062BC4C, fee_type=CNY, mch_id=1503809911, cash_fee=1, out_trade_no=78902e694bab485b8e7745b61e05dbfe, appid=wx5beac15ca207c40c, total_fee=1, trade_type=NATIVE, result_code=SUCCESS, time_end=20180526162759, is_subscribe=Y, return_code=SUCCESS}
          Map<String, String> callbackMap = WXPayUtil.xmlToMap(sb.toString());    
            
          //获取有序map    
          SortedMap<String, String> sortedMap = CommonUtil.getSortedMap(callbackMap) ;  




          回调数据:
          <xml><appid><![CDATA[wx5beac15ca207c40c]]></appid><bank_type><![CDATA[CFT]]></bank_type><cash_fee><![CDATA[10]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[Y]]></is_subscribe><mch_id><![CDATA[1503809911]]></mch_id><nonce_str><![CDATA[de019d5f1e5d40649cd76de33f18b13e]]></nonce_str><openid><![CDATA[oiNKG03vVY4PHlGUEwT-ztFo8K8Y]]></openid><out_trade_no><![CDATA[4d8cea4a916440368583edaf82488624]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[FA799B7DF70C2BAC558E839E01EF341A]]></sign><time_end><![CDATA[20180626230347]]></time_end><total_fee>10</total_fee><trade_type><![CDATA[NATIVE]]></trade_type><transaction_id><![CDATA[4200000142201806264038572903]]></transaction_id></xml>


          转成map:
          {transaction_id=4200000142201806264038572903, nonce_str=de019d5f1e5d40649cd76de33f18b13e, bank_type=CFT, openid=oiNKG03vVY4PHlGUEwT-ztFo8K8Y, sign=FA799B7DF70C2BAC558E839E01EF341A, fee_type=CNY, mch_id=1503809911, cash_fee=10, out_trade_no=4d8cea4a916440368583edaf82488624, appid=wx5beac15ca207c40c, total_fee=10, trade_type=NATIVE, result_code=SUCCESS, time_end=20180626230347, is_subscribe=Y, return_code=SUCCESS}
           
         
       2、注意点:
       
        回调要用post方式,微信文档没有写回调的通知方式
        可以用这个注解 @RequestMapping


        问题:一定要看日志


    14、微信回调处理之更新订单状态和幂等性讲解
    简介:微信支付回调处理之更新订单状态和讲解什么是接口的幂等性
    微信回调通知规则(通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)


    幂等性: 同样的参数和值,不管调用你的接口多少次,响应结果都和调用一次是一样的
     
    1、校验签名是否正确,防止伪造回调

    2、查询订单是否已经更新


    3、若没更新则更新订单状态


    4、回应微信,SUCCESS 或者 FAIL 
           response.setContentType("text/xml");        
           response.getWriter().println("success");




















    15、微信支付之下单事务处理
    简介:讲解下单接口增加事务和常见的事务选择
    1、springboot开启事务,启动类里面增加 @EnableTransactionManagement
    2、需要事务的方法上加 @Transactional(propagation = Propagation.REQUIRED)
    3、aop的管理事务的好处和选择
    增,删,改  开启事务

    XML源串
    展开全文
  • 微信支付是集成在微信客户端的支付功能,用户可以通过手机完成快速的支付流程。微信支付以绑定银行卡的快捷支付为基础,向用户提供安全、快捷、高效的支付服务。 公众号支付 APP支付 扫码支付 刷卡支付 H5支付 ...

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

    • 公众号支付
    • APP支付
    • 扫码支付
    • 刷卡支付
    • H5支付
    • 小程序支付

    (本文档主要介绍公众号支付和扫码支付)

    注:微信公众号目前必须是服务认证号,且开通微信支付功能。公众号对应的商户号也必须开通支付功能。

    一、公众号支付

    公众号支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。应用场景有:

    • 用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付
    • 用户的好友在朋友圈、聊天窗口等分享商家页面连接,用户点击链接打开商家页面,完成支付
    • 将商户页面转换成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付

    1.  设置JSSDK接口调用域名

    先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。  

    2.  设置授权域名

    开发公众号支付时,在统一下单接口中要求必传用户openid,而获取openid则需要您在公众平台设置获取openid的域名,只有被设置过的域名才是一个有效的获取openid的域名,否则将获取失败。如下图:

     

    3.  设置支付目录

    请确保实际支付时的请求目录与后台配置的目录一致,否则将无法成功唤起微信支付。

      在微信商户平台(pay.weixin.qq.com)设置您的公众号支付支付目录,设置路径:商户平台-->产品中心-->开发配置,如下图所示。公众号支付在请求支付的时候会校验请求来源是否有在商户平台做了配置,所以必须确保支付目录已经正确的被配置,否则将验证失败,请求支付不成功。

    注意:这三个地方的域名需使用字母、数字及“-”的组合,不支持IP地址、端口号及短链域名,且填写的域名须通过ICP备案的验证。

    4.   设置支付密钥app_key

    点击帐户中心——API安全——设置API密钥(用于支付是的验签)

    5.   获取openid

      由于openid必须为当前用户在当前支付公众号内的身份标识,所以在智慧校园项目中采取实时获取的方式获得。

      步骤一:用户同意授权,获取code

      访问以下链接获得带code参数的Url:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

      参数说明

    参数

    是否必须

    说明

    appid

    公众号的唯一标识

    redirect_uri

    授权后重定向的回调链接地址,请使用urlencode对链接进行处理

    response_type

    返回类型,请填写code

    scope

    应用授权作用域,snsapi_base(不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)

    state

    重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节

    #wechat_redirect

    无论直接打开还是做页面302重定向时候,必须带此参数

    注:回调链接一定要urlencode,不然识别不出

      步骤二:通过code换取网页授权access_token

      首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

      获取code后,请求以下链接获取access_token:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

      参数说明

    参数

    是否必须

    说明

    appid

    公众号的唯一标识

    secret

    公众号的appsecret

    code

    填写第一步获取的code参数

    grant_type

    填写为authorization_code

      返回JSON数据包如下:

    复制代码

    {
       "access_token":"ACCESS_TOKEN",
       "expires_in":7200,
       "refresh_token":"REFRESH_TOKEN",
       "openid":"OPENID",
       "scope":"SCOPE",
       "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" 
    }

    复制代码

      附:关于网页授权access_token和普通access_token的区别

      1、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;

      2、其他微信接口,如发微信消息接口,需要通过基础支持中的“获取access_token”接口(https://api.weixin.qq.com/cgi-bin/token)来获取到的普通access_token调用。

    -----------------------------上述5个步骤都为支付的准备步骤。-----------------------------

      支付业务流程及步骤如下图:

     

    6.   微信内H5调起支付

      步骤一:后台统一下单获取jsapi支付参数

      请求地址:https://api.mch.weixin.qq.com/pay/unifiedorder

      请求参数:   appid(公众账号ID),

    mch_id(商户号),

    device_info(设备号),

    nonce_str(随机字符串),

    sign(签名),

    sign_type(签名类型),

    body(商品描述) ,

    detail(商品详情),

    attach(附加数据),

    out_trade_no(商户订单号),

    fee_type(标价币种),

    total_fee(标价金额),

    spbill_create_ip(终端IP),

    time_start(交易起始时间),

    time_expire(交易结束时间),

    notify_url(支付回调地址),

    trade_type(交易类型),

    product_id(商品ID),

    opened(用户标识)

       注:参数值用XML转义即可,CDATA标签用于说明数据不被XML解析器解析。

       具体下单过程可参照微信支付Demo:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

      当请求成功,返回的XML中return_code 和result_code都为SUCCESS时会返回如下:

    复制代码

    <xml>
       <return_code><![CDATA[SUCCESS]]></return_code>
       <return_msg><![CDATA[OK]]></return_msg>
       <appid><![CDATA[wx3556f3b4523gf12r]]></appid>
       <mch_id><![CDATA[10000100]]></mch_id>
       <nonce_str><![CDATA[jfjsdh47fin0jdnv]]></nonce_str>
       <openid><![CDATA[oECxywCpJW8G-ktn3lwZ7MR4Cx2Q]]></openid>
       <sign><![CDATA[8SDVCNKDF89W32SDKCSAA0S32JKSDJJL]]></sign>
       <result_code><![CDATA[SUCCESS]]></result_code>
       <prepay_id><![CDATA[wx201801041172356eidnvnd9qk398324745]]></prepay_id>
       <trade_type><![CDATA[JSAPI]]></trade_type>
    </xml>

    复制代码

      步骤二:H5发起微信支付

      在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。

      注意:WeixinJSBridge内置对象在其他浏览器中无效,参数名区分大小,大小写错误签名验证会失败。

    引用js:http://res.wx.qq.com/open/js/jweixin-1.0.0.js

      调用支付js如下:

    复制代码

    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();
    }

    复制代码

      支付完成后,微信会将订单参数会以XML方式发送给商户系统回调地址,商户在回调地址接收参数并做相应处理。

      回调的XML格式为:

    复制代码

    <xml>
      <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
      <attach><![CDATA[支付测试]]></attach>
      <bank_type><![CDATA[CFT]]></bank_type>
      <fee_type><![CDATA[CNY]]></fee_type>
      <is_subscribe><![CDATA[Y]]></is_subscribe>
      <mch_id><![CDATA[10000100]]></mch_id>
      <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
      <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
      <out_trade_no><![CDATA[1409811653]]></out_trade_no>
      <result_code><![CDATA[SUCCESS]]></result_code>
      <return_code><![CDATA[SUCCESS]]></return_code>
      <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
      <sub_mch_id><![CDATA[10000100]]></sub_mch_id>
      <time_end><![CDATA[20140903131540]]></time_end>
      <total_fee>1</total_fee>
      <trade_type><![CDATA[JSAPI]]></trade_type>
      <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
    </xml>

    复制代码

    推荐技术文档:

    1.https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

    2.https://wenku.baidu.com/view/cebde8a764ce0508763231126edb6f1aff007185.html?re=view

     

    二、扫码支付

      扫码支付可分为两种模式,商户根据支付场景选择相应模式。

      【模式一】:

      商户后台系统根据微信支付规则链接生成二维码,链接中带固定参数productid(可定义为产品标识或订单号)。用户扫码后,微信支付系统将productid和用户唯一标识(openid)回调商户后台系统(需要设置支付回调URL),商户后台系统根据productid生成支付交易,最后微信支付系统发起用户支付流程。

      商户支付回调URL设置指引:进入商户平台-->产品中心-->开发配置,进行配置和修改,如下图所示。

      【模式二】:

      商户后台系统调用微信支付【统一下单API】生成预付交易,将接口返回的链接生成二维码,用户扫码后输入密码完成支付交易。注意:该模式的预付单有效期为2小时,过期后无法支付,不依赖设置的回调支付URL。

      流程图:

      

      业务流程说明:

    (1)商户后台系统根据用户选购的商品生成订单。

    (2)用户确认支付后调用微信支付【统一下单API】生成预支付交易;

    (3)微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。

    (4)商户后台系统根据返回的code_url生成二维码。

    (5)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。

    (6)微信支付系统收到客户端请求,验证链接有效性后发起用户支付,要求用户授权。

    (7)用户在微信客户端输入密码,确认支付后,微信客户端提交授权。

    (8)微信支付系统根据用户授权完成支付交易。

    (9)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。

    (10)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。

    (11)未收到支付通知的情况,商户后台系统调用【查询订单API】。

    (12)商户确认订单已支付后给用户发货。

      附:

      前端页面代码:

    //前端页面
    <img src=" MakeQRCode?code_url=@code_url" alt="二维码"/>

       C#生成二维码后台代码:

    复制代码

        //生成二维码方法  
         public FileResult MakeQRCode(string code_url)
            {
                if (string.IsNullOrEmpty(code_url))
                    throw new ArgumentException("code_url");
                //初始化二维码生成工具
                QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
                qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
                qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
                qrCodeEncoder.QRCodeVersion = 0;
                qrCodeEncoder.QRCodeScale = 4;
                //将字符串生成二维码图片
                Bitmap image = qrCodeEncoder.Encode(code_url, Encoding.Default);
                //保存为PNG到内存流  
                MemoryStream ms = new MemoryStream();
                image.Save(ms, ImageFormat.Jpeg);
                return File(ms.ToArray(), "image/jpeg");
            }

    复制代码

      推荐技术文档:

    1. https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1
    2. http://www.cnblogs.com/vinsonLu/p/5166214.html
    展开全文
  • 微信支付成功回调的代码,尤其要注意官方文档的一句话: 如果不注意这里,支付成功后微信会一直对这个地址进行调用,更新订单的对数据库进行操作,也会一直存在更新:...

    如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人。谢谢大家!❤

    如果解决不了,可以在文末进群交流。

    写微信支付成功回调的代码,尤其要注意官方文档的一句话:

    如果不注意这里,支付成功后微信会一直对这个地址进行调用,更新订单的对数据库进行操作,也会一直存在更新:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7.

    这其实不是坑的主要所在,问题是这个文档,我真的不知道该如何吐槽。一次偶然的意外才看到。这个文档说明。


    好了,其他的没有什么需要特别注意的,直接上代码:

    <?php   
        //获取接口数据,如果$_REQUEST拿不到数据,则使用file_get_contents函数获取
        $post = $_REQUEST;
        if ($post == null) {
            $post = file_get_contents("php://input");
        }
    
        if ($post == null) {
            $post = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
        }
    
        if (empty($post) || $post == null || $post == '') {
            //阻止微信接口反复回调接口  文档地址 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7,下面这句非常重要!!!
            $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';  
            echo $str;
            exit('Notify 非法回调');
        }
    
        /*****************微信回调返回数据样例*******************
         $post = '<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>';
         *************************微信回调返回*****************/
    
        libxml_disable_entity_loader(true); //禁止引用外部xml实体
    
        $xml = simplexml_load_string($post, 'SimpleXMLElement', LIBXML_NOCDATA);//XML转数组
        
        $post_data = (array)$xml;
        
        /** 解析出来的数组
            *Array
            * (
            * [appid] => wx1c870c0145984d30
            * [bank_type] => CFT
            * [cash_fee] => 100
            * [fee_type] => CNY
            * [is_subscribe] => N
            * [mch_id] => 1297210301
            * [nonce_str] => gkq1x5fxejqo5lz5eua50gg4c4la18vy
            * [openid] => olSGW5BBvfep9UhlU40VFIQlcvZ0
            * [out_trade_no] => fangchan_588796
            * [result_code] => SUCCESS
            * [return_code] => SUCCESS
            * [sign] => F6890323B0A6A3765510D152D9420EAC
            * [time_end] => 20180626170839
            * [total_fee] => 100
            * [trade_type] => JSAPI
            * [transaction_id] => 4200000134201806265483331660
            * )
        **/
        //订单号
        $out_trade_no = isset($post_data['out_trade_no']) && !empty($post_data['out_trade_no']) ? $post_data['out_trade_no'] : 0;
    
        //查询订单信息
        $order_info = DB::fetch_first("SELECT * FROM order WHERE order_no = '" .$out_trade_no."'");
    
    
        if(count($order_info) > 0){
            //查询平台信息
            $platform_info = DB::fetch_first("SELECT * FROM pingtaiInfo WHERE `open_pid`= {$order_info['part1']}");
    
            //平台支付key
            $wxpay_key = $platform_info['zhifu_key'];
    
            //接收到的签名
            $post_sign = $post_data['sign'];
            unset($post_data['sign']);
    
            //重新生成签名
            $newSign = MakeSign($post_data,$wxpay_key);
    
            //签名统一,则更新数据库
            if($post_sign == $newSign){
    
                $updateData = array();  
                $updateData['pay_time'] = TIMESTAMP; //支付时间
                $updateData['order_status'] = 2; //订单状态
    
                //更新order数据库
                //Do what you want...
            }
        }
    
        //阻止微信接口反复回调接口  文档地址 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7,下面这句非常重要!!!
        $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';  
        echo $str;
    
        function MakeSign($params,$key){
            //签名步骤一:按字典序排序数组参数
            ksort($params);
            $string = ToUrlParams($params);  //参数进行拼接key=value&k=v
            //签名步骤二:在string后加入KEY
            $string = $string . "&key=".$key;
            //签名步骤三:MD5加密
            $string = md5($string);
            //签名步骤四:所有字符转为大写
            $result = strtoupper($string);
            return $result;
        }
    
        function ToUrlParams( $params ){
            $string = '';
            if( !empty($params) ){
                $array = array();
                foreach( $params as $key => $value ){
                    $array[] = $key.'='.$value;
                }
                $string = implode("&",$array);
            }
            return $string;
        }

     

    废话不多说了,直接上代码,不懂地方可留言,或者进微信群内交流。群二维码如果过期,请加我微信:mengyilingjian.

    展开全文
  • 写这篇文章的目的有2个,一是自己的项目刚开发完微信支付功能,趁热回个炉温习一下,二也是帮助像我这样对微信支付不熟悉,反复看了多天文档还是一知半解,原理都没摸清,更不要说实现了。本以为网上的微信开发教程会和...

    自己的第一篇博客,请各位看官海涵!

    JAVA开发微信支付-公众号支付/微信浏览器支付(JSAPI)

        写这篇文章的目的有2个,一是自己的项目刚开发完微信支付功能,趁热回个炉温习一下,二也是帮助像我这样对微信支付不熟悉,反复看了多天文档还是一知半解,原理都没摸清,更不要说实现了。本以为网上的微信开发教程会和“java的重写与重载”一样铺天盖地,可搜出来的结果,要么是PHP的教程(微信支付官网推荐就是PHP),要么星星点点就那么几篇,想对比的看看思路都成问题,官网下载的JAVA-SDK-DEMO也恕我技术低下,看的糊里糊涂。等自己开发完的那一刻,才豁然开朗,才知道走通完支付这条路的过程走了多少弯路,我是第一次接触支付,想必大部分能看这篇文章的兄弟也是被微信官方文档给绕的出不来才出此下策,内容有误请指正。好了这回真正的正题了:

    步骤一:获取微信支付四大参数

        首先要想支持微信支付,必须拥有两个账号:①微信公众已认证的服务号,并且需要开通微信支付该能(必须是企业才有资格申请,请你找你家产品去申请吧),②微信商户平台账号;这两个账号一个不能少。此处已默认你已有上两个账号。

        此处是账号模板,请参考:

        微信公众平台:账户:con*******om 登录密码 ******

        公众APPID:wx15*********a8

        APPSECEPT : c210***************892d7

        微信商户平台:账户:149**********6742 登录密码:******

        商户ID:14******42

        API密钥:5d5************b35b

    其中比较不好找的是商户的API密钥:在商户平台的账户中心下:需要用户自行下载证书及安装,(略)

        至此我们需要的APPID(appid),APPSECEPT(appsecret),商户ID(mch_id),API密钥(paternerKey),四个重要参数已拿到,括号中是我们代码所用的变量名称请提前熟悉。

    步骤二:平台配置

    1.配置支付目录:商户平台:

        配置此目录是代码中“微信支付”所在页面的地址,可以是目录不一定是全路径-如http://www.wangtao.com/order/-----此一级域名需要ICP备案。

    点击添加

     

    2.配置授权域名:微信公众平台:

        支付过程需要获取用户openid,必须经过网页授权配置才可以,要不然获取不到openid。

    点击设置,按说明设置

    步骤三:开发流程:

        微信支付原理(说白了就是调用官方文档的“统一下单”接口,之后将微信服务器返回的参数做个加工后,返回到前台(JSP页面),就OK了。咱们要做的就是想方设法的凑齐统一下单的所有参数“而已”,“而已”,“而已”,这个而已也就是最大的挑战)。所有参数解释请参考:官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

        咱们只考虑必填参数,其他参数可以就看你的了。

        先来看看所有参数:

    其中的必填参数有:

    1.        appid APPID (已有)

    2.        mch_id 商户ID (已有)

    3.        nonce_str 随机字符串

    4.        sign 签名

    5.        body 所支付的名称

    6.        out_trade_no 咱们自己所提供的订单号,需要唯一

    7.        total_fee 支付金额

    8.        spbill_create_ip IP地址

    9.        notify_url 回调地址

    10.       trade_type 支付类型

    11.       openid 支付人的微信公众号对应的唯一标识

        只要把这11个凑齐就齐活,现在咱们从第3个开始一个一个的获取;在这之前先从官网把公众号支付的sdk下载下来,如图

        主要是用其中的WXPayUtil工具类中的一些方法。当然其他的类我看不懂,要是看懂了,就不至于这么费劲了。

    好了开始咱们的取值之旅了:

    1.        appid APPID (已有)

    2.        mch_id 商户ID (已有)

    3.        nonce_str 随机字符串用WXPayUtil中的generateNonceStr()即可,就是生成UUID的方法;

    4.        sign 签名 用WXPayUtil中的generateSignature(finalMap<String, String> data, String key)方法,data是将除了sign外,其他10个参数放到map中,key是四大配置参数中的API秘钥(paternerKey)(这里不要着急管它,最后处理它);

    5.        body 所支付的名称

    6.        out_trade_no 自己后台生成的订单号,只要保证唯一就好:如“2018013000001”

    7.        total_fee 支付金额 单位:分,为了测试此值给1,表示支付1分钱

    8.        spbill_create_ip IP地址 网上很多ip的方法,自己找,此处测试给“127.0.0.1”

    9.        notify_url 回调地址:这是微信支付成功后,微信那边会带着一大堆参数(XML格式)请求这个地址多次,这个地址做我们业务处理如:修改订单状态,赠送积分等。Ps:支付还没成功还想这么远干嘛,最后再说。地址要公网可以访问。

    10.    trade_type 支付类型 咱们是公众号支付此处给“JSAPI”

    11.    openid 支付人的微信公众号对应的唯一标识,每个人的openid在不同的公众号是不一样的,这11个参数里,最费劲的就是他了,其他的几乎都已经解决,现在开发得到这个参数。

        获得openid的部分内容应该不属于微信支付的范畴,属于微信公众号网页授权的东西,详情请参考微信网页授权:

    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

    获得openid步骤:

    第一步:用户同意授权,获取code

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

    注意:1. redirect_uri参数:授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理。

    2. scope:用snsapi_base 

        通过此链接可以获取code,可以在一个空页面设置一个a标签,链接至其redirect_uri的地址。点击a标签,即可链接到redirect_uri的地址,并携带code。

    <a href="https://open.weixin.qq.com/connect/oauth2/authorize?
    appid=wx15c*********&redirect_uri=http%3a%2f%2fwww.***.com%2fpay.jsp&response_type=code&
    scope=snsapi_base#wechat_redirect">去支付页面pay.jsp并携带code</a>

    第二步:通过code换取网页授权access_token(其实微信支付就没有必要获取access_token,咱们只要其中openid,不是要用户信息,此步结果已经就含有咱们需要的openid了)

    获取code,请求以下链接获取access_token https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

    上一步的code有了,对于此链接的参数就容易了。可是在页面上如何处理是个问题,我是在pay.jsp页面加载完成后将获取code当做参数传异步到后台,在后台中用http相关类发送get请求(可以自行网上查找)。返回的JSON结果为:

    { "access_token":"ACCESS_TOKEN",
    "expires_in":7200,
    "refresh_token":"REFRESH_TOKEN",
    "openid":"OPENID",//就是它,只要这个值
    "scope":"SCOPE" }
    

        好了,access_token是有了,不过咱们不关心它,咱们关心的是openid,有了它一就回到咱们“统一下单”接口里,所有的参数已经就位就等发送了。在回顾下11个必填参数:

    1.        appid APPID (已有)

    2.        mch_id 商户ID (已有)

    3.        nonce_str 随机字符串用WXPayUtil中的generateNonceStr()即可,就是生成UUID的方法;

    4.        sign 签名 用WXPayUtil中的publicstatic String generateSignature(final Map<String, String> data, Stringkey)方法,data是将除了sign外,其他10个参数放到map中,key是四大配置参数中的API秘钥(paternerKey)(此时可以处理它了,不过其他10个参数都有了,它就easy,new一个map,依次put其他10个参数,就可以用generateSignature方法了,得到了sign,不要忘记再将sign put到只有10个参数的map,这样才能凑齐最后的第11个参数。准备召唤神龙吧。);

    5.        body 所支付的名称

    6.        out_trade_no 自己后台生成的订单号,只要保证唯一就好:如“2018013000001”

    7.        total_fee 支付金额 单位:分,为了测试此值给1,表示支付1分钱

    8.        spbill_create_ip IP地址 网上很多ip的方法,自己找,此处测试给“127.0.0.1”

    9.        notify_url 回调地址:这是微信支付成功后,微信那边会带着一大堆参数(XML格式)请求这个地址多次,这个地址做我们业务处理如:修改订单状态,赠送积分等。Ps:支付还没成功还想这么远干嘛,最后再说。地址要公网可以访问。

    10.    trade_type 支付类型 咱们是公众号支付此处给“JSAPI”

    11.    openid (已有)

        好了,准备工作完成,开始发送POST请求吧,上面提到网上找到的get请求的方法,此处用到post请求的方法,请求微信"统一下单接口https://api.mch.weixin.qq.com/pay/unifiedorder。发送前先用WXPayUtil工具类中的public static String mapToXml(Map<String,String> data)方法将有11个参数的map转成XML格式。发送后会返回String类型的返回值,如果你够幸运的话应该会得到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>
      <openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
      <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
      <result_code><![CDATA[SUCCESS]]></result_code>
      <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
      <trade_type><![CDATA[JSAPI]]></trade_type>
    </xml>

        如果你得到了以上的字符串,那么先恭喜你,坚持看到这,说明你的耐心还是不错的,因为“统一下单”接口调用完毕,可是并没有什么实际的效果,因为微信里想出现支付的界面是在前台完成的现在咱们还在后台玩耍,前面提到的我是页面加载完成时异步到后台的,咱们要返回异步的结果了,好了趁热继续吧。“统一下单”这么费劲的完成其实搞那么麻烦,就是为了得到上面红色的prepay_id(丫的,就这么一个参数给咱们搞的都想说***了)。

        先用WXPayUtil类中的public static Map<String, String> xmlToMap(String strXML)方法,将刚才返回的XML格式的字符串转成map(为了方便取值)。map.get(“prepay_id”)就得到了prepay_id的值(比如得到的是:“wx2018…250…9981…666”),记住它,先保留此值。

    看看前台都需要接收哪些值吧。

    6个参数,咱们还是一个一个分析:

    1.        appId:四大参数之一的APPID;

    2.        timestamp:时间戳(newDate()即可)

    3.        nonceStr:随机字符串,再次用WXPayUtil中的generateNonceStr()即可;

    4.        package:就tm是它用到了prepay_id,但是还不是直接取值,还非要固定格式的,值的格式例如:”prepay_id= wx2018…250…9981…666”

    5.        signType:写MD5就好

    6.        paySign:又来了还是签名算法 ,按照上面的方法,用WXPayUtil中的publicstatic String generateSignature(final Map<String, String> data, Stringkey)方法,data是将除了paySign外,其他5个参数放到map中,key是四大配置参数中的API秘钥(paternerKey),得到了paySign,不要忘记再将paySign put到只有5个参数的map,这样才能凑齐最后的第6个参数。);

    注意:此处有个小bug,很多人会被坑的很惨,不注意就掉坑里,我是掉进去了,就是最关键的第4个参数package,眼熟不眼熟,这tm是JAVA的关键字,不能用来当变量名。

    所有的参数有了,返回给前端的方法有很多,简易用springMVC的@ResponseBody注解,即可将这个有6个参数的map按json格式传给前端。好了,后台工作完成。

        前端的工作就容易多了,格式比较固定因为是微信固定格式,所以直接贴出我的代码,你只要更换触发支付的事件和异步的地址即可.

    前端简单来说:1.一个空jsp页面上有个a标签,用来获取code,并跳转到pay.jsp(上面提到过)。

                            2.pay.jsp中需要异步到后台需要带code参数,pay.jsp中页面的地址上带着code,想获取code的方法很多,抛砖引引玉:(定义一个按钮,按钮上绑定一个code的属性值是页面链接的code的值,用EL表达式取的参数值,点击按钮触发点击事件)。

                            3.接收后台传过来值,调用固定方法。

    Pay.jsp中内容只有一个”微信支付”的按钮,和js的代码,以下是js内容(获取code方法可以修改),其它内容不要修改

    <!—pay.jsp中点击”微信支付”按钮执行pay()方法>
    
    <input id="code"type="button" value="微信支付"onclick="pay()" code="${param.code }"/>
    <script type="text/javascript">
    var appId,timeStamp,nonceStr,package,signType,paySign;  
     function pay(){
    	var code = $("#code").attr("code");//页面链接上的code参数
    	if(code){
    		var url = "http://异步地址?code="+code+";
    	  	$.get(url,function(result) {
      				appId = result.appId;
    				timeStamp = result.timeStamp;
    				nonceStr = result.nonceStr;
    				package = result.package;
    				signType = result.signType;
    				paySign = result.paySign;
    				
    				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();
    				}
    			});
    		} else {
    			alert(“服务器错误”)
    		}
    	}
    
    function onBridgeReady(){
    	  WeixinJSBridge.invoke( 'getBrandWCPayRequest', {
    		  "appId":appId,     //公众号名称,由商户传入     
              "timeStamp":timeStamp,         //时间戳,自1970年以来的秒数     
              "nonceStr":nonceStr, //随机串     
              "package":package,     
              "signType":signType,         //微信签名方式:     
              "paySign":paySign //微信签名 
             }, 
             function(res){      
          	   if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                     console.log('支付成功');
                     //支付成功后跳转的页面
                 }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
              	   console.log('支付取消');
                 }else if(res.err_msg == "get_brand_wcpay_request:fail"){
              	   console.log('支付失败');
                     WeixinJSBridge.call('closeWindow');
                 } //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
       });   
    }
    </script>
    

    以下是后台部分

    /**
    	 * @Description 微信浏览器内微信支付/公众号支付(JSAPI)
    	 * @param request
    	 * @param code
    	 * @return Map
    	 */
    	@RequestMapping(value="orders", method = RequestMethod.GET)
    	@ResponseBody
    	public Map orders(HttpServletRequest request,String code) {
    		try {
    			//页面获取openId接口
    			String getopenid_url = https://api.weixin.qq.com/sns/oauth2/access_token;
    			String  param= 
    "appid="+你appid+"&secret="+你secret+"&code="+code+"&grant_type=authorization_code";
    			//向微信服务器发送get请求获取openIdStr
    String openIdStr = HttpRequest.sendGet(getopenid_url, param);
    			JSONObject json = JSONObject.parseObject(openIdStr);//转成Json格式
    			String openId = json.getString("openid");//获取openId
    			
    			//拼接统一下单地址参数
    			Map<String, String> paraMap = new HashMap<String, String>();
    			//获取请求ip地址
    			String ip = request.getHeader("x-forwarded-for");
    		    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
    		        ip = request.getHeader("Proxy-Client-IP");
    		    }
    		    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
    		        ip = request.getHeader("WL-Proxy-Client-IP");
    		    }
    		    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
    		        ip = request.getRemoteAddr();
    		    }
    		    if(ip.indexOf(",")!=-1){
    		    	String[] ips = ip.split(",");
    		    	ip = ips[0].trim();
    		    }
    			
    			paraMap.put("appid", 你appid);  
    			paraMap.put("body", "尧舜商城-订单结算");  
    			paraMap.put("mch_id", 你mchId);  
    			paraMap.put("nonce_str", WXPayUtil.generateNonceStr());  
    			paraMap.put("openid", openId);
    			paraMap.put("out_trade_no", 你的订单号);//订单号
    			paraMap.put("spbill_create_ip", ip);  
    			paraMap.put("total_fee",”1”);  
    			paraMap.put("trade_type", "JSAPI");  
    			paraMap.put("notify_url",www.*******.com/***/**);// 此路径是微信服务器调用支付结果通知路径随意写
    			String sign = WXPayUtil.generateSignature(paraMap, paternerKey);
    			paraMap.put("sign", sign);
    			String xml = WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式
    						
    			// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
    			String unifiedorder_url = https://api.mch.weixin.qq.com/pay/unifiedorder;
    	
    			String xmlStr = HttpRequest.sendPost(unifiedorder_url, xml);//发送post请求"统一下单接口"返回预支付id:prepay_id
    			
    			//以下内容是返回前端页面的json数据
    			String prepay_id = "";//预支付id
    			if (xmlStr.indexOf("SUCCESS") != -1) {  
    				Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);  
    				prepay_id = (String) map.get("prepay_id");  
    			}
    			Map<String, String> payMap = new HashMap<String, String>();
    			payMap.put("appId", appid);  
    			payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");  
    			payMap.put("nonceStr", WXPayUtil.generateNonceStr());  
    			payMap.put("signType", "MD5");  
    			payMap.put("package", "prepay_id=" + prepay_id);  
    			String paySign = WXPayUtil.generateSignature(payMap, paternerKey);  
    			payMap.put("paySign", paySign);
    			return payMap;
    		} catch (Exception e) {  
    			e.printStackTrace();
    		}  
    		return null;
    	}

     

    以下是网上找的一个发送get和post的类.仅供参考:提前导入相关jar包可网上查找(很容易)

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.List;
    import java.util.Map;
    
    public class HttpRequest {
        /**
         * 向指定URL发送GET方法的请求
         * 
         * @param url
         *            发送请求的URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return URL 所代表远程资源的响应结果
         */
        public static String sendGet(String url, String param) {
            String result = "";
            BufferedReader in = null;
            try {
                String urlNameString = url + "?" + param;
                System.out.println(urlNameString);
                URL realUrl = new URL(urlNameString);
                // 打开和URL之间的连接
                URLConnection connection = realUrl.openConnection();
                // 设置通用的请求属性
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("user-agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 建立实际的连接
                connection.connect();
                // 获取所有响应头字段
                Map<String, List<String>> map = connection.getHeaderFields();
                // 遍历所有的响应头字段
                for (String key : map.keySet()) {
                    System.out.println(key + "--->" + map.get(key));
                }
                // 定义 BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(
                        connection.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送GET请求出现异常!" + e);
                e.printStackTrace();
            }
            // 使用finally块来关闭输入流
            finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            return result;
        }
    
        /**
         * 向指定 URL 发送POST方法的请求
         * 
         * @param url
         *            发送请求的 URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return 所代表远程资源的响应结果
         */
        public static String sendPost(String url, String param) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                URL realUrl = new URL(url);
                // 打开和URL之间的连接
                URLConnection conn = realUrl.openConnection();
                // 设置通用的请求属性
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("user-agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 发送POST请求必须设置如下两行
                conn.setDoOutput(true);
                conn.setDoInput(true);
                // 获取URLConnection对象对应的输出流
                out = new PrintWriter(conn.getOutputStream());
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
                // 定义BufferedReader输入流来读取URL的响应
                in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送 POST 请求出现异常!"+e);
                e.printStackTrace();
            }
            //使用finally块来关闭输出流、输入流
            finally{
                try{
                    if(out!=null){
                        out.close();
                    }
                    if(in!=null){
                        in.close();
                    }
                }
                catch(IOException ex){
                    ex.printStackTrace();
                }
            }
            return result;
        }    
    }
    

        ----------------------------------------------------------------------------------

    以下是微信支付成功后,向自己项目发送请求,自己来做一些业务处理。

    /**
     * @ClassName WxPayController
     * @Description 微信支付成功后回调次接口
     * @author wtao wangtao@eyaoshun.com
     * @date 2018年1月11日 下午3:10:59
     */
    //回调路径是自己在之前已经填写过的
    @RequestMapping("/pay/")
    @Controller
    public class WxPayController {
    	@Autowired
    	private OrdersService ordersService;
    	@Autowired
    	private AccountService accountService;
    	@Autowired
    	private PointService pointService;
    	
    	@RequestMapping("callback")
    	public String callBack(HttpServletRequest request,HttpServletResponse response){
    		//System.out.println("微信支付成功,微信发送的callback信息,请注意修改订单信息");
    		InputStream is = null;
    		try {
    			is = request.getInputStream();//获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
    			String xml = WXPayUtil.inputStream2String(is, "UTF-8");
    			Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//将微信发的xml转map
    						
    			if(notifyMap.get("return_code").equals("SUCCESS")){  
    	                if(notifyMap.get("result_code").equals("SUCCESS")){  
    	                String ordersSn = notifyMap.get("out_trade_no");//商户订单号 
    	                String amountpaid = notifyMap.get("total_fee");//实际支付的订单金额:单位 分
    	                BigDecimal amountPay = (new BigDecimal(amountpaid).divide(new BigDecimal("100"))).setScale(2);//将分转换成元-实际支付金额:元
    	                //String openid = notifyMap.get("openid");  //如果有需要可以获取
    	                //String trade_type = notifyMap.get("trade_type");  
    	                
    	                /*以下是自己的业务处理------仅做参考
    	                 * 更新order对应字段/已支付金额/状态码
    	                 */
    	                Orders order = ordersService.selectOrdersBySn(ordersSn);
    	                if(order != null) {
    	                	order.setLastmodifieddate(new Date());
    	                	order.setVersion(order.getVersion().add(BigDecimal.ONE));
    	                	order.setAmountpaid(amountPay);//已支付金额
    	                	order.setStatus(2L);//修改订单状态为待发货
    	                	int num = ordersService.updateOrders(order);//更新order
    	                	
    	                	String amount = amountPay.setScale(0, BigDecimal.ROUND_FLOOR).toString();//实际支付金额向下取整-123.23--123
    	                	/*
    	                	 * 更新用户经验值
    	                	 */
    	                	Member member = accountService.findObjectById(order.getMemberId());
    	                	accountService.updateMemberByGrowth(amount, member);
    	                	
    	                	/*
    	                	 * 添加用户积分数及添加积分记录表记录
    	                	 */
    	                	pointService.updateMemberPointAndLog(amount, member, "购买商品,订单号为:"+ordersSn);
    	                	
    	                }
    	                  
    	            }  
    	        }
    			
    	        //告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
    	        response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");  
    			is.close();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    }
    

     

        以上纯手写,如有疏漏请联系,请大神勿喷.谢谢,以上是公众号支付(在微信里),有时间的话我再写一个H5页面的微信支付,请期待.

     

    展开全文
  • 微信app支付详解

    2018-06-28 17:40:08
    import java.text.SimpleDateFormat;import java.util.Date;import java.util.Random;import java.util.UUID;/** * 随机生成订单号 * @author 张卓 * */public class OrderNumber{ /** ...
  • 在上一篇文章中本人讲述了微信公众号的授权以及获取用户信息,在此基础上今天这篇博客跟大家分享一下微信支付的流程及代码,还有自己在开发时的一些坑。1、在进行微信支付时,除了需要一个公众号之外,你还需要一个...
  • 微信支付

    2018-08-13 10:35:13
    1、微信支付的流程 如下三张手机截图,我们在微信网页端看到的支付,表面上看到的是 “点击支付按钮 - 弹出支付框 - 支付成功后出现提示页面”,实际上的核心处理过程是: 点击支付按钮时,执行一个Ajax到后台 ...
  • 一. 案例介绍这里模拟一个实际业务场景,进行介绍微信支付,业务功能包括:登录、注册、充值、查看充值记录。 页面图: 二. 概要设计1.数据库设计 这里数据库包括两张表:用户表和订单表。...微信支付流程 ...
  • 微信H5支付

    2019-06-22 12:04:44
    微信H5支付
  • 官方文档 JS-SDK说明文档 ... JSAPI支付文档 ... 绑定域名(可在该域名下调用微信开放的JS接口,这里配置前端域名) 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名
  • h5支付的资料还真叫个少,不过找到一个好的方式,按着大神的步骤去实现还真就ok了,话不多说,开始准备吧 ...amp;index=1 微信支付的坑很多,特别在平台的设置上 ...首先需要APPID,微信支付商户号mch_id,API密...
  • 问题来源之前在app中集成过微信支付,当时还写了一篇扫坑贴,此种微信支付方式为app支付,即在我们自己的应用中嵌入微信支付SDK,由Native代码调起微信支付。后来由于业务需要在我们app的WebView中打开第三方店铺的...
  • 本文承接之前发布的博客《 微信支付V3微信公众号支付PHP教程/thinkPHP5公众号支付》必须阅读上篇文章后才可以阅读这篇文章。由于最近一段时间工作比较忙,博客更新比较慢。如果有任何问题大家可以关注以上公众号,...
  • 最近做小程序,涉及到微信支付,看了看微信小程序开发文档,尽管之前做过微信支付,还是有点懵逼,不过好在之前研究过,不然真的是无从下手。对比了一下发现,其实小程序中做支付比公众号支付要省事很多,因为不需要...
  • 之前在app中集成过微信支付,此种微信支付方式为app支付,即在我们自己的应用中嵌入微信支付SDK,由Native代码调起微信支付。 后来由于业务需要在我们app的WebView中打开自己的网页版商城的网页,在商城网页中有...
  • H5移动端支持微信支付 [ 微信支付分为微信内支付(JSAPI支付官方API)和微信外支付(H5支付官方API)] && 支付宝支付 [手机网站支付转 APP 支付 官方API ] 订单生成逻辑:前端请求后端提交订单,后端去和...
  • 微信支付-支付结果通知接收最近在做微信支付功能在微信成功后,微信通过异步方式返回支付结果是遇到了问题:参数接收不到。后来通过查阅资料才将问题解决,现在将解决方法分享一下。官方文档解释如上图所示:通过...
  • 银联支付,支付宝支付,微信支付的三大总结,之前也有写过两篇。&amp;gt; 支付宝植入总结: android 支付宝的植入 《曾经踩过的坑》 微信支付总结: Android 微信支付总结 备注:出于安全考虑...
1 2 3 4 5 ... 20
收藏数 105,601
精华内容 42,240
关键字:

微信支付