热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

微信公众号微信支付

步骤一.首先你要有一个微信公众号和公众号对应的微信商户号1)先申请一个微信公众号https:kf.qq.comfaq120911VrYVrA151013MfYvYV.

 

步骤一.首先 你要有一个微信公众号  和公众号对应的微信商户号 

  1) 先申请一个微信公众号 

    https://kf.qq.com/faq/120911VrYVrA151013MfYvYV.html

    官网教程  做微信支付  我们要的是服务号。  订阅号不能做微信支付

  2) 申请微信商户号

    https://jingyan.baidu.com/article/15622f24d389b3fdfcbea5d1.html

 

步骤二.配置信息 

  1)配置信息  设置网页授权域名  和 JS接口安全域名

     微信公众平台-->公众号设置-->功能设置

 

  

 

 先把这个文件下载过来  放到 你要设置的域名 根目录下  这样才会设置成功 不要带http

  

  2)配置支付目录  

    商户平台-->产品中心-->开发配置(传送门:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3),且最多可以同时设置5个目录

    

 

    好 到这一步  配置信息就完成了

 

步骤三.开发要提供的参数

   公众APPID:wx15*********a8  (开发需要的)

  开发者密码APPSECEPT : c210***************892d7  (开发需要的)

 

  商户ID:14******42  (开发需要的)

  API密钥:5d5************b35b  (开发需要的)

 

   微信公众平台-->基本设置

 

 

 公众APPID 和 APPSECEPT 我们就有了 

 商户平台-->账号中心-->商户信息

 

 商户ID 也有了 我们还差一个 API密钥

商户平台-->账号中心-->API安全

 

 

 

 好了 现在 配置 和参数 我们已经全部都有了  想在开始代码了 

 

 

步骤四:开发流程:

  微信支付 (说白了就是调用官方文档的“统一下单”接口,之后将微信服务器返回的参数做个加工后,返回到前台(JSP页面)) 文档地址 

  https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1

  文档主要讲 请求地址是  

  https://api.mch.weixin.qq.com/pay/unifiedorder

  入参有很多   其中的必填参数有:

  1.        appid APPID (已有)

  2.        mch_id 商户ID (已有)

  3.        nonce_str 随机字符串(可以用UUID生成)

  4.        sign 签名

  5.        body 所支付的名称

  6.        out_trade_no 咱们自己所提供的订单号,需要唯一(可以是时间戳)

  7.        total_fee 支付金额

  8.        spbill_create_ip IP地址(获取ip地址)

  9.        notify_url 回调地址(支付成功后的通知地址)

  10.       trade_type 支付类型(默认写  咱们是公众号支付此处给“JSAPI”)

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

 

好 我们先获取  openid

1.获取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

入参

APPID: 公众号 APPID

redirect_uri: 回调地址 就是访问这个链接后跳转到哪个地址去 

response_type:就直接写 code   

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

 

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

#wechat_redirect:必填不用管

回参

code:返回的 code参数

state:上面传的 state参数

2.获取OpenID  也是请求地址 

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

入参

APPID:  公众号 APPID

secret:开发者密码  APPSECEPT 

code:上面获取的code 参数

grant_type:直接写  authorization_code

回参

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

OpenID 就是我们要 

 

 1.        appid APPID (已有)

  2.        mch_id 商户ID (已有)

  3.        nonce_str 随机字符串(可以用UUID生成)

  4.        sign 签名

  5.        body 所支付的名称 

  6.        out_trade_no 咱们自己所提供的订单号,需要唯一(可以是时间戳)

  7.        total_fee 支付金额   1 为1分钱

  8.        spbill_create_ip IP地址(获取ip地址)

  9.        notify_url 回调地址(支付成功后的通知地址)

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

  11.       openid 支付人的微信公众号对应的唯一标识 (openid 我们也有了)

现在 我们只差 sing了 

用WXPayUtil中的

generateSignature(Map data, String key, SignType signType)

方法,data是将除了sign外,其他10个参数放到map中,key是四大配置参数中的API秘钥(paternerKey)

sign_type 也可以通过 WXPayUtil 中的方法获取 主要是表明 加密方式

WXPayConstants.SignType sign_type = WXPayConstants.SignType.MD5;

这些方法都在 wxpay-sdk-0.0.3.jar 这个jar包里

String sign = WXPayUtil.generateSignature(map, AppMchKey, sign_type);

这就生成了 sing 了 把 sing 也 加到 data 里去
调用 mapToXml(Map data)

会把 map 转换成 xml

String reqestHtml =WXPayUtil.mapToXml(map);

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

String xmlStr = sendPost(url,reqestHtml);


成功放回的数据

<xml><return_code>SUCCESS]]>return_code><return_msg>OK]]>return_msg><appid>wx2421b1c4370ec43b]]>appid><mch_id>10000100]]>mch_id><nonce_str>IITRi8Iabbblz1Jc]]>nonce_str><openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]>openid><sign>7921E432F65EB8ED0CE9755F0E86D72F]]>sign><result_code>SUCCESS]]>result_code><prepay_id>wx201411101639507cbf6ffd8b0779950874]]>prepay_id><trade_type>JSAPI]]>trade_type>xml>

调用 WXPayUtil.xmlToMap(respondResult) 把 xml 转换成 map

Map map &#61; WXPayUtil.xmlToMap(respondResult);

 

其中 只有 prepay_id 是我们要的 

 

我们要放回个前端的参数是  

1.        appId&#xff1a;四大参数之一的APPID&#xff1b;

2.        timestamp&#xff1a;时间戳&#xff08;newDate()即可&#xff09;

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

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

5.        signType&#xff1a;写MD5就好

6.        paySign&#xff1a;签名 

        if (xmlStr.indexOf("SUCCESS") !&#61; -1) {Map map &#61; WXPayUtil.xmlToMap(xmlStr);prepay_id &#61; (String) map.get("prepay_id");}Map payMap &#61; new HashMap();payMap.put("appId", appID);payMap.put("timeStamp", getCurrentTimestamp()&#43;"");payMap.put("nonceStr", WXPayUtil.generateNonceStr());payMap.put("signType", "MD5");payMap.put("package", "prepay_id&#61;" &#43; prepay_id);String paySign &#61; WXPayUtil.generateSignature(payMap, AppMchKey);// AppMchKey 为api秘钥

       payMap.put("paySign", paySign);
      
return payMap;

这就完成了 代码 

后端代码  有一些方法 可以自己写 

package com.wizrole.hospital.wechat.controller;import com.github.wxpay.sdk.WXPayUtil;
import com.wizrole.hospital.healthCard.util.HttpRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;import static com.wizrole.hospital.wechat.service.WechatService.*;
import static com.wizrole.hospital.wechat.util.XmlUtil.getCurrentTimestamp;
import static com.wizrole.hospital.wechat.util.XmlUtil.getIpAddr;public class Test {&#64;RequestMapping(value &#61; "testPay" , method &#61; {RequestMethod.POST, RequestMethod.GET})&#64;ResponseBodypublic Map orders(HttpServletRequest request) {

    

    String code&#61; request.getParameter("code");

 

    //页面获取openId接口String getopenid_url &#61; https://api.weixin.qq.com/sns/oauth2/access_token;String param&#61;"appid&#61;"&#43;你appid&#43;"&secret&#61;"&#43;你secret&#43;"&code&#61;"&#43;code&#43;"&grant_type&#61;authorization_code";//向微信服务器发送get请求获取openIdStrString openIdStr &#61; HttpRequest.sendGet(getopenid_url, param);JSONObject json &#61; JSONObject.parseObject(openIdStr);//转成Json格式String openId &#61; json.getString("openid");//获取openId


try {Map paraMap &#61; new HashMap();
//获取请求ip地址String ip &#61; getIpAddr(request);String body &#61; request.getParameter("body");String total_fee &#61; request.getParameter("total_fee");//支付金额String out_trade_no &#61; String.valueOf(getCurrentTimestamp()); //订单号
paraMap.put("appid",appID);//公众号ID
paraMap.put("body", "尧舜商城-订单结算");paraMap.put("mch_id",AppMchId);//商户号 ID
paraMap.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
paraMap.put("openid", openid);//OpenID
paraMap.put("out_trade_no", out_trade_no);//订单号
paraMap.put("spbill_create_ip", ip);paraMap.put("total_fee","1");paraMap.put("trade_type", "JSAPI");paraMap.put("notify_url","http://wizrole.natapp1.cc/Wechat/notifyUrl.do");// 此路径是微信服务器调用支付结果通知路径随意写
String sign &#61; WXPayUtil.generateSignature(paraMap, AppMchKey);paraMap.put("sign", sign);String xml &#61; WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
String unifiedorder_url &#61; "https://api.mch.weixin.qq.com/pay/unifiedorder";String xmlStr &#61; HttpRequest.sendPost(unifiedorder_url, xml);//发送post请求"统一下单接口"返回预支付id:prepay_id//以下内容是返回前端页面的json数据
String prepay_id &#61; "";//预支付idif (xmlStr.indexOf("SUCCESS") !&#61; -1) {Map map &#61; WXPayUtil.xmlToMap(xmlStr);prepay_id &#61; (String) map.get("prepay_id");}Map payMap &#61; new HashMap();payMap.put("appId", appID);payMap.put("timeStamp", getCurrentTimestamp()&#43;"");payMap.put("nonceStr", WXPayUtil.generateNonceStr());payMap.put("signType", "MD5");payMap.put("package", "prepay_id&#61;" &#43; prepay_id);String paySign &#61; WXPayUtil.generateSignature(payMap, AppMchKey);payMap.put("paySign", paySign);return payMap;} catch (Exception e) {e.printStackTrace();}return null;}
}

/*** 获取客户端IP地址* &#64;param request* &#64;return*/public static String getIpAddr(HttpServletRequest request) {String ip &#61; request.getHeader("x-forwarded-for");if (ip &#61;&#61; null || ip.length() &#61;&#61; 0 || "unknown".equalsIgnoreCase(ip)) {ip &#61; request.getHeader("Proxy-Client-IP");}if (ip &#61;&#61; null || ip.length() &#61;&#61; 0 || "unknown".equalsIgnoreCase(ip)) {ip &#61; request.getHeader("WL-Proxy-Client-IP");}if (ip &#61;&#61; null || ip.length() &#61;&#61; 0 || "unknown".equalsIgnoreCase(ip)) {ip &#61; request.getRemoteAddr();}return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;}

package com.wizrole.hospital.healthCard.util;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;public class HttpRequest {private static final Logger log &#61; LoggerFactory.getLogger(HttpRequest.class);/*** 发送GET请求* &#64;param url* &#64;param param* &#64;return*/public static String sendGet(String url , String param){String result &#61; "";BufferedReader in &#61; null;HttpURLConnection connection &#61; null;try {log.info("发起请求 URL为[" &#43; url &#43; "], 请求方式 [GET], 参数为: " &#43; param);String urlNameString &#61; url &#43; "?" &#43; param;URL realUrl &#61; new URL(urlNameString.replaceAll(" ",""));connection &#61; (HttpURLConnection)realUrl.openConnection();connection.setRequestProperty("accept" , "*/*");connection.setRequestProperty("connection" , "Keep-Alive");connection.setRequestProperty("user-agent" , "Mozilla/4.0(compatible; MSIE 6.0; Windows NT5.1:SV1");connection.connect();Map> map &#61; connection.getHeaderFields();for (String key : map.keySet()){System.out.println("----------------------------| " &#43; key &#43; "--->" &#43; map.get(key));}in &#61; new BufferedReader(new InputStreamReader(connection.getInputStream()));String line;while ((line &#61; in.readLine()) !&#61; null){result &#43;&#61; line;}}catch (Exception e){log.error("发送GET请求出现异常 &#xff1a; " &#43; e);e.printStackTrace();}finally {try{connection.disconnect();if(in !&#61; null){in.close();}}catch (Exception e1){e1.printStackTrace();}}return result;}/*** 发送POST请求* &#64;param url* &#64;param param* &#64;return* &#64;throws UnsupportedEncodingException */public static String sendPost(String url , String param){BufferedWriter out &#61; null;BufferedReader in &#61; null;HttpURLConnection conn &#61; null;StringBuffer result &#61; new StringBuffer();try {//param &#61; new String(param.getBytes() , "utf-8");log.info("发起请求 URL为[" &#43; url &#43; "], 请求方式 [POST], 参数为: " &#43; param);URL realUrl &#61; new URL(url);conn &#61; (HttpURLConnection)realUrl.openConnection();conn.setRequestProperty("Content-Type","application/json; charset&#61;utf-8");conn.setRequestProperty("accept" , "*/*");conn.setRequestProperty("connection" , "Keep-Alive");conn.setRequestProperty("user-agent" , "Mozilla/4.0(compatible; MSIE 6.0; Windows NT5.1:SV1");conn.setDoInput(true);conn.setDoOutput(true);out &#61; new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(),"UTF-8"));out.write(param);out.flush();in &#61; new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));
// Map> map1 &#61; conn.getRequestProperties();
conn.connect();
// for (String key : map1.keySet()){
// System.out.println("----------------------------> " &#43; key &#43; "--->" &#43; map1.get(key));
// }Map> map &#61; conn.getHeaderFields();for (String key : map.keySet()){System.out.println("----------------------------| " &#43; key &#43; "--->" &#43; map.get(key));}String line &#61; null;while ((line &#61; in.readLine())!&#61;null){result.append(line); }log.info("出参 &#xff1a; " &#43; result.toString());}catch (Exception e){log.error("发送POST请求出现异常 &#xff1a; " &#43; e);e.printStackTrace();}finally {try{conn.disconnect();if(out !&#61; null){out.close();}if(in !&#61; null){in.close();}}catch (Exception e1){e1.printStackTrace();}}return result.toString();}}

 

 

前端代码

 

var a &#61; "https://open.weixin.qq.com/connect/oauth2/authorize?appid&#61;appid&redirect_uri&#61;http://wizrole.natapp1.cc/index.html&response_type&#61;code&scope&#61;snsapi_base&state&#61;STATE#wechat_redirect";location.href &#61; a;

在index.html 页面写 下面这段js

 

function getQueryString(name) {
var reg &#61; new RegExp("(^|&)" &#43; name &#43; "&#61;([^&]*)(&|$)", "i");
var r &#61; window.location.search.substr(1).match(reg);
if (r !&#61; null) return unescape(r[2]);
return null;
}
var code &#61; getQueryString("code");

//调取微信支付
function pay(){openid &#61; $("#openId").text();$.ajax({url:"/testPay",type:"POST",dataType: &#39;json&#39;,data:{code:code,body:"测试",total_fee:"1"},success: function (data) {if (data.return_msg &#61;&#61; "OK") {WeixinJSBridge.invoke(&#39;getBrandWCPayRequest&#39;, {"appId": data.appid, //公众号名称&#xff0c;由商户传入"timeStamp": data.timeStamp, //时间戳&#xff0c;自1970年以来的秒数"nonceStr": data.nonce_str, //随机串"package": "prepay_id&#61;" &#43; data.prepay_id,"signType": "MD5", //微信签名方式&#xff1a;"paySign": data.sign //微信签名},function (res) {if (res.err_msg &#61;&#61; "get_brand_wcpay_request:ok") {alert("支付成功,订单受理中");} else if (res.err_msg &#61;&#61; "get_brand_wcpay_request:cancel") {//取消订单self.cancelOrder(orderdata.order_no, function (status) {if (status &#61;&#61; 1) {alert("支付已取消");} else if (status &#61;&#61; 2) {alert("订单取消失败&#xff0c;请联系管理员")}});} else if (res.err_msg &#61;&#61; "get_brand_wcpay_request:fail") {//取消订单self.cancelOrder(orderdata.order_no, function (status) {if (status &#61;&#61; 1) {alert("支付失败");} else if (status &#61;&#61; 2) {alert("订单取消失败&#xff0c;请联系管理员")}});}});}}})}

 

 

  

 

转:https://www.cnblogs.com/closeIt/p/11046257.html



推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 【Windows】实现微信双开或多开的方法及步骤详解
    本文介绍了在Windows系统下实现微信双开或多开的方法,通过安装微信电脑版、复制微信程序启动路径、修改文本文件为bat文件等步骤,实现同时登录两个或多个微信的效果。相比于使用虚拟机的方法,本方法更简单易行,适用于任何电脑,并且不会消耗过多系统资源。详细步骤和原理解释请参考本文内容。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 20211101CleverTap参与度和分析工具功能平台学习/实践
    1.应用场景主要用于学习CleverTap的使用,该平台主要用于客户保留与参与平台.为客户提供价值.这里接触到的原因,是目前公司用到该平台的服务~2.学习操作 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 小程序自动授权和手动接入的方式及操作步骤
    本文介绍了小程序支持的两种接入方式:自动授权和手动接入,并详细说明了它们的操作步骤。同时还介绍了如何在两种方式之间切换,以及手动接入后如何下载代码包和提交审核。 ... [详细]
  • 2016 linux发行版排行_灵越7590 安装 linux (manjarognome)
    RT之前做了一次灵越7590黑苹果炒作业的文章,希望能够分享给更多不想折腾的人。kawauso:教你如何给灵越7590黑苹果抄作业​zhuanlan.z ... [详细]
  • 手把手教你使用GraphPad Prism和Excel绘制回归分析结果的森林图
    本文介绍了使用GraphPad Prism和Excel绘制回归分析结果的森林图的方法。通过展示森林图,可以更加直观地将回归分析结果可视化。GraphPad Prism是一款专门为医学专业人士设计的绘图软件,同时也兼顾统计分析的功能,操作便捷,可以帮助科研人员轻松绘制出高质量的专业图形。文章以一篇发表在JACC杂志上的研究为例,利用其中的多因素回归分析结果来绘制森林图。通过本文的指导,读者可以学会如何使用GraphPad Prism和Excel绘制回归分析结果的森林图。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 本文介绍了JavaScript进化到TypeScript的历史和背景,解释了TypeScript相对于JavaScript的优势和特点。作者分享了自己对TypeScript的观察和认识,并提到了在项目开发中使用TypeScript的好处。最后,作者表示对TypeScript进行尝试和探索的态度。 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
author-avatar
mobiledu2502876293
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有