https://mpweixinn://wxpay/bizpayurl?pr=biqc8j7

微信支付V3集成过程(Native)
微信支付V3集成过程(Native)
[摘要:少话短道,微疑领取V3版原形比V2版本,简化很多接心,大大下降了商户的接进价值,只不外因为相干的散成解释文档写的过于笼统,细节描绘不敷详细,demo版本不敷美满等等缘由,被]
长话短说,微信支付V3版本相比V2版本,简化许多接口,大大降低了商户的接入代价,只不过由于相关的集成说明文档写的过于笼统,细节描述不够具体,demo版本不够完善等等原因,被大家诟病。最近基于业务需要,完成了微信支付的接入,选择的是公众号扫码支付(Native模式)。在此把集成的大致过程贴出来,希望能对正在困扰的各位有所帮助。整个交互过程分为四步:1、商户:生成微信支付二维码2、微信:扫描二维码,获取商户订单信息3、微信:确认支付,调起微信支付模块,完成支付,回调商户通知接口4、商户:接收微信支付成功后的通知信息,根据通知结果进行业务处理交互时序图如下(参考微信官方说明):650) this.width=650;" src="/uploads/u/14/0a/140accd454ade66fd4659d.jpg" title="QQ截图41.png" alt="wKiom1UD4UjjPlohAAIe39NQ3ZI853.jpg" />这四步中,商户需要做的有三块工作,明确指出的1和4需要商户完成,还有一块工作隐藏在2中,提供微信回调接口,将商户订单信息返回给微信,该接口在申请微信支付后需要在公众平台进行配置。在进行详细说明之前,先做几点说明:1、涉及传参及返回结果,均为xml格式2、默认编码为UTF-83、签名算法重点说下签名算法,官方文档中对签名算法做了比较详细的说明,可以直接参考。不过没有说明每次交互中用到的签名sign,都有哪些字段参与生成了签名。这里明确下:微信支付每次交互中的签名字段sign,由本次交互所有参数(sign和空值除外)参与签名生成,这点也是经常多次尝试后确认的。贴出源码:/**&* 创建签名&*&&* @param packageParams&* @return&*/@SuppressWarnings({ "rawtypes", "unchecked" })public static String createSign(SortedMap packageParams) {StringBuffer sb = new StringBuffer();Set&Entry& es = packageParams.entrySet();Iterator&Entry& it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = entry.getValue() != null ? entry.getValue().toString() :if (null != v&&& !"".equals(v)&&& !"sign".equals(k)&& !"key".equals(k)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + WxPayConfig.APP_KEY);return MD5Util.MD5Encode(sb.toString(), WxPayConfig.CHAR_SET).toUpperCase();}/**&* 签名校验&*&&* @return&* @throws UnsupportedEncodingException&*/@SuppressWarnings("rawtypes")public static boolean verifyPaySign(SortedMap paras, String sign) throws UnsupportedEncodingException {String paySign = Tools.createSign(paras);return StringUtil.isNotEmpty(paySign) ? paySign.equalsIgnoreCase(sign) :}下面对每一步进行详细说明:1、商户:生成微信支付二维码微信支付链接格式为:weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXX&time_stamp=XXXXX&nonce_str=XXXXXsign为签名字段,参与签名的字段为appid、mch_id、product_id、time_stamp、nonce_str其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库(zxing 、qrcode)生成二维码图片。举例:weixin://wxpay/bizpayurl?appid=wx0ec43b&mch_id=&nonce_str=f5ec87a8c&product_id=1&time_stamp=&sign=512F6DA4A45DA79CC7EFE9D贴出源码:略2、微信:扫描二维码,获取商户订单信息这里商户需要做的是,给微信提供获取订单信息的接口。接口需要完成三部分工作:获取微信回调接口时传过来的参数,进行签名校验输入参数说明如下:名称变量名类型必填示例值描述公众账号IDappidString(32)是wx8888微信分配的公众账号ID用户标识openidString(128)是o8GeHuLAsgefS_80exEr1cTqekUs用户在商户appid下的唯一标识商户号mch_idString(32)是微信支付分配的商户号是否关注公众账号is_subscribeString(1)是Y用户是否关注公众账号,仅在公众账号类型支付有效,取值范围:Y或N;Y-关注;N-未关注随机字符串nonce_strString(32)是5K8264ILTKCH16CQ2502SI8ZNMTM67VS随机字符串,不长于32位商品IDproduct_idString(32)是88888商户定义的商品id 或者订单号签名signString(32)是C380BEC2BFD727A4BF3AD6返回数据签名sign为签名字段,参与签名的字段为appid、openid、mch_id、is_subscribe、nonce_str、product_id。调用微信统一下单接口,生成预支付订单,获取预支付订单prepay_id统一下单URL地址:https://api.mch./pay/unifiedorder输入参数说明如下:字段名变量名必填类型示例值描述公众账号IDappid是String(32)wx8888微信分配的公众账号ID商户号mch_id是String(32)微信支付分配的商户号设备号device_info否String(32)764微信支付分配的终端设备号,商户自定义随机字符串nonce_str是String(32)5K8264ILTKCH16CQ2502SI8ZNMTM67VS随机字符串,不长于32位签名sign是String(32)C380BEC2BFD727A4BF3AD6签名商品描述body是String(32)Ipad&mini&&16G&&白色商品或支付单简要描述商品详情detail否String(8192)Ipad&mini&&16G&&白色商品名称明细列表附加数据attach否String(127)说明附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据商户订单号out_trade_no是String(32)8018商户系统内部的订单号,32个字符内、可包含字母货币类型fee_type否String(16)CNY符合ISO&4217标准的三位字母代码,默认人民币:CNY总金额total_fee是Int888订单总金额,只能为整数,精确到分终端IPspbill_create_ip是String(16)8.8.8.8APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。交易起始时间time_start否String(14)10订单生成时间,格式为yyyyMMddHHmmss,如日9点10分10秒表示为10交易结束时间time_expire否String(14)10订单失效时间,格式为yyyyMMddHHmmss,如日9点10分10秒表示为10商品标记goods_tag否String(32)WXG商品标记,代金券或立减优惠功能的参数通知地址notify_url是String(256)/接收微信支付异步通知回调地址交易类型trade_type是String(16)JSAPI取值如下:JSAPI,NATIVE,APP商品IDproduct_id否String(32)trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。用户标识openid否String(128)oUpF8uMuAJO_M2pxb1Q9zNjWeS6otrade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。sign为签名字段,参与签名的字段包括上面除sign之外的所有非空字段。返回结果说明如下:字段名变量名必填类型示例值描述返回状态码return_code是String(16)SUCCESSSUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断返回信息return_msg否String(128)签名失败&返回信息,如非空,为错误原因签名失败参数格式校验错误以下字段在return_code为SUCCESS的时候有返回字段名变量名必填类型示例值描述公众账号IDappid是String(32)wx8888调用接口提交的公众账号ID商户号mch_id是String(32)调用接口提交的商户号设备号device_info否String(32)764调用接口提交的终端设备号,随机字符串nonce_str是String(32)5K8264ILTKCH16CQ2502SI8ZNMTM67VS微信返回的随机字符串签名sign是String(32)C380BEC2BFD727A4BF3AD6微信返回的签名业务结果result_code是String(16)SUCCESSSUCCESS/FAIL错误代码err_code否String(32)SYSTEMERROR详细参见第6节错误列表错误代码描述err_code_des否String(128)系统错误错误返回的信息描述以下字段在return_code&和result_code都为SUCCESS的时候有返回字段名变量名必填类型示例值描述交易类型trade_type是String(16)JSAPI调用接口提交的交易类型,取值如下:JSAPI,NATIVE,APP预支付交易会话标识prepay_id是String(64)wx&微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时二维码链接code_url否String(64)URl:weixin://wxpay/s/An4baqwtrade_type为NATIVE是有返回,可将该参数值生成二维码展示出来进行扫码支付向微信回写商户订单信息参数说明如下:名称变量名类型必填示例值描述返回状态码return_codeString(16)是SUCCESSSUCCESS/FAIL,此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断返回信息return_msgString(128)否签名失败返回信息,如非空,为错误原因;签名失败;具体某个参数格式校验错误.公众账号IDappidString(32)是wx8888微信分配的公众账号ID商户号mch_idString(32)是微信支付分配的商户号随机字符串nonce_strString(32)是5K8264ILTKCH16CQ2502SI8ZNMTM67VS微信返回的随机字符串预支付IDprepay_idString(64)是wx调用统一下单接口生成的预支付ID业务结果result_codeString(16)是SUCCESSSUCCESS/FAIL错误描述err_code_desString(128)否当result_code为FAIL时,商户展示给用户的错误提签名signString(32)是C380BEC2BFD727A4BF3AD6返回数据签名sign为签名字段,参与签名的字段包括上面除sign之外的所有非空字段。贴出源码:// ************************************************************************************// 1、参数校验// 微信版本&支付签名&订单信息// ************************************************************************************// 预定义订单信息Order order =// 解析微信post过来的xml数据Map&String, Object& postData = Tools.getXmlDataFromWx(request);if (postData != null&& postData.get("product_id") != null) {// 校验支付签名是否一致boolean isPaySignValid = Tools.verifyPaySign(Tools.convertMap2SortedMap(postData),&postData.get("sign").toString());if (isPaySignValid) {// 获取订单信息order = orderService.get(postData.get("product_id").toString());if (order == null) {RetCode = WxPayRetCodeEnum.ORDERNOTEXIST.getCode();RetErrMsg = WxPayRetCodeEnum.ORDERNOTEXIST.getMsg();} else if (order.getOrderStatus() == OrderStatus.CANCELED.getStatus()) {RetCode = WxPayRetCodeEnum.ORDEREXPIRED.getCode();RetErrMsg = WxPayRetCodeEnum.ORDEREXPIRED.getMsg();} else if (order.getPayStatus() == PayStatus.PAID.getStatus()|| order.getPayAmount() &= order.getBalanceAmount()) {RetCode = WxPayRetCodeEnum.ORDERPAYED.getCode();RetErrMsg = WxPayRetCodeEnum.ORDERPAYED.getMsg();}} else {RetCode = WxPayRetCodeEnum.PAYSIGNWRONG.getCode();RetErrMsg = WxPayRetCodeEnum.PAYSIGNWRONG.getMsg();}} else {RetCode = WxPayRetCodeEnum.WXPOSTXMLERROR.getCode();RetErrMsg = WxPayRetCodeEnum.WXPOSTXMLERROR.getMsg();}// ************************************************************************************// 2、调用微信统一下单接口,生成预支付订单// ************************************************************************************// 计算商品总金额,精确到分,取整String totalFee = order != null ? String.valueOf(NumberCaculator.multiply(NumberCaculator.substract(order.getPayAmount(), order.getBalanceAmount()), 100)) : "0";totalFee = totalFee.indexOf(".") & -1 ? totalFee.substring(0, totalFee.indexOf(".")) : totalFString outTradeNo = order != null ? order.getOrderSn() :// 调用微信统一下单接口,生成微信预支付订单,获取交易会话标识RequestHandler reqHandler = new RequestHandler();reqHandler.setParameter("appid", WxPayConfig.APP_ID);reqHandler.setParameter("mch_id", WxPayConfig.MCH_ID);reqHandler.setParameter("nonce_str", Tools.getNonceStr());reqHandler.setParameter("body", PurchaseTypeEnum.Course.getName());reqHandler.setParameter("detail", PurchaseTypeEnum.Course.getDesc());reqHandler.setParameter("out_trade_no", outTradeNo);reqHandler.setParameter("total_fee", totalFee);reqHandler.setParameter("spbill_create_ip", InetAddress.getLocalHost().getHostAddress().toString());reqHandler.setParameter("notify_url", WxPayConfig.NOTIFY_URL);reqHandler.setParameter("trade_type", WxPayTradeTypeEnum.NATIVE.getMsg());reqHandler.setParameter("sign", Tools.createSign(reqHandler.getParameters()));// 发起请求,调用统一下单接口,获取统一下单接口返回结果String result = reqHandler.sendReq(WxPayConfig.UNIFIED_ORDER_API, reqHandler.getRequestParams4Xml());Map&String, String& apiResult = XMLUtil.doXMLParse(result);// ************************************************************************************// 3、向微信回写订单信息// ************************************************************************************// 设置支付参数-为了返回Package 数据,回调URL 必须返回一个xml 格式的返回数据SortedMap&String, Object& signParams = new TreeMap&String, Object&();signParams.put("return_code", apiResult != null ? apiResult.get("return_code") : "FAIL");&signParams.put("return_msg", apiResult != null ? apiResult.get("return_msg") : "下单失败");&signParams.put("appid", WxPayConfig.APP_ID);signParams.put("mch_id", WxPayConfig.MCH_ID);signParams.put("nonce_str", Tools.getNonceStr());signParams.put("prepay_id", apiResult != null ? apiResult.get("prepay_id") : "");signParams.put("result_code", RetCode);signParams.put("err_code_des", RetErrMsg);signParams.put("sign", Tools.createSign(signParams));// 回写订单信息PrintWriter writer =response.setHeader("ContentType", "text/xml");response.setHeader("Pragma", "No-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);try {writer = response.getWriter();writer.flush();writer.print(XMLUtil.parseXML(signParams));// & writer.print(JSONObject.fromObject(signParams).toString());} catch (IOException e) {e.printStackTrace();} finally {writer.close();}3、微信:确认支付,调起微信支付模块,完成支付,回调商户通知接口这一步不涉及商户4、商户:接收微信支付成功后的通知信息,根据通知结果进行业务处理微信支付成功后,会将支付结果通过统一下单接口中的notify_url参数回传通知给商户。商户需要在通知接口中完成签名校验、业务处理、回写处理结果等操作。输入参数说明如下:字段名变量名必填类型示例值描述返回状态码return_code是String(16)SUCCESSSUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断返回信息return_msg否String(128)签名失败&返回信息,如非空,为错误原因签名失败参数格式校验错误以下字段在return_code为SUCCESS的时候有返回字段名变量名必填类型示例值描述公众账号IDappid是String(32)wx8888微信分配的公众账号ID商户号mch_id是String(32)微信支付分配的商户号设备号device_info否String(32)764微信支付分配的终端设备号,随机字符串nonce_str是String(32)5K8264ILTKCH16CQ2502SI8ZNMTM67VS随机字符串,不长于32位签名sign是String(32)C380BEC2BFD727A4BF3AD6签名业务结果result_code是String(16)SUCCESSSUCCESS/FAIL错误代码err_code否String(32)SYSTEMERROR详细参见第6节错误列表错误代码描述err_code_des否String(128)系统错误错误返回的信息描述用户标识openid是String(128)wxd930ea5d5a258f4f用户在商户appid下的唯一标识是否关注公众账号is_subscribe是String(1)Y用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效交易类型trade_type是String(16)JSAPIJSAPI、NATIVE、APP付款银行bank_type是String(16)CMC银行类型,采用字符串类型的银行标识,银行类型见附表总金额total_fee是Int100订单总金额,单位为分货币种类fee_type否String(8)CNY货币类型,符合ISO&4217标准的三位字母代码,默认人民币:CNY现金支付金额cash_fee是Int100现金支付金额订单现金支付金额现金支付货币类型cash_fee_type否String(16)CNY货币类型,符合ISO&4217标准的三位字母代码,默认人民币:CNY代金券或立减优惠金额coupon_fee否Int10代金券或立减优惠金额&=订单总金额,订单总金额-代金券或立减优惠金额=现金支付金额代金券或立减优惠使用数量coupon_count否Int1代金券或立减优惠使用数量代金券或立减优惠批次IDcoupon_batch_id_$n否String(20)100代金券或立减优惠批次ID&,$n为下标,从1开始编号代金券或立减优惠IDcoupon_id_$n否String(20)10000&代金券或立减优惠ID,&$n为下标,从1开始编号单个代金券或立减优惠支付金额coupon_fee_$n否Int100单个代金券或立减优惠支付金额,&$n为下标,从1开始编号微信支付订单号transaction_id是String(32)8018微信支付订单号商户订单号out_trade_no是String(32)2322商户系统的订单号,与请求一致。商家数据包attach否String(128)123456商家数据包,原样返回支付完成时间time_end是String(14)25支付完成时间,格式为yyyyMMddHHmmss,如日9点10分10秒表示为10sign为签名字段,参与签名的字段包括上面除sign之外的所有非空字段。贴出源码:// 1、验证返回通知的合法性Map&String, String& params = paymentService.getNotifyParamsMap(request);// 解析返回参数boolean verifyStatus = paymentService.isNotifyLegal(params, null);if (log.isInfoEnabled()) {</("************WxpayNotifyAction**********Wxpay params Log: " + params.toString());</("************WxpayNotifyAction**********verifyStatus: " + verifyStatus);}// 2、根据验证结果进行业务逻辑的操作String returnCode = WxpayTradeStateEnum.FAIL.getCode();String returnMsg = WxpayTradeStateEnum.FAIL.getMsg();if (verifyStatus) {// *****************************************************// TODO:业务处理// *****************************************************// 向支付平台返回returnCode = WxpayTradeStateEnum.SUCCESS.getCode();returnMsg = WxpayTradeStateEnum.SUCCESS.getMsg();} else {returnCode = WxpayTradeStateEnum.FAIL.getCode();returnMsg = "无效签名";}// 3、向微信回写处理结果SortedMap&String, Object& resMap = new TreeMap&String, Object&();resMap.put("return_code", returnCode);resMap.put("return_msg", returnMsg);PrintWriter writer =response.setHeader("ContentType", "text/xml");response.setHeader("Pragma", "No-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);try {writer = response.getWriter();writer.flush();writer.print(XMLUtil.parseXML(resMap));} catch (IOException e) {e.printStackTrace();} finally {writer.close();}OK,可以系统联调了,祝你顺利!
感谢关注 Ithao123精品文库频道,是专门为互联网人打造的学习交流平台,全面满足互联网人工作与学习需求,更多互联网资讯尽在 IThao123!
Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。
用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。
Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。
Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。
产品设计是互联网产品经理的核心能力,一个好的产品经理一定在产品设计方面有扎实的功底,本专题将从互联网产品设计的几个方面谈谈产品设计
随着国内互联网的发展,产品经理岗位需求大幅增加,在国内,从事产品工作的大部分岗位为产品经理,其实现实中,很多从事产品工作的岗位是不能称为产品经理,主要原因是对产品经理的职责不明确,那产品经理的职责有哪些,本专题将详细介绍产品经理的主要职责
IThao123周刊微信支付开发关键点技术解析 - 推酷
微信支付开发关键点技术解析
【编者按】由CSDN和《程序员》杂志联合举办的2014微信开发者大会,在经历了北京站的成功后,应广大微信开发者的强烈要求,主办方将于11月15日在
,不仅有南航微信服务号、&招商银行信用卡服务号,还有长安汽车微信企业号等众多知名微信开发领域技术专家和典型开发商都将带来精彩演讲(点击报名)。
目前报名处于特惠票价阶段,通过申请加入CSDN CTO俱乐部即可享受8折购票价格(票款中均含豪华午餐),在10月28日之前完成购票和付款流程的同学均将获赠微信技术开发图书一本+北京站讲师演讲视频和讲义(PDF)+全套深圳站讲师讲义(PDF)。
微信支付是由微信及财付通联合推出的移动支付创新产品。如今,随着微信支付的全面开放,相关需求也越来越多,很多开发人员进行微信支付开发及商家申请微信支付时,面临着诸多疑惑。本文将结合微信支付接口开发的实践,从支付申请到各主要接口的使用方法等方面介绍微信支付的关键点技术。
目前,微信支付只能由通过微认证的服务号进行申请,订阅号及未认证的服务号均无法申请。登录微信公众平台后台,在左侧的栏目中可找到“微信支付”,点击进入申请界面,可以看到第一项中的“商户基本资料”,点击右侧的“填写”按钮后就进入了微信支付设置界面。
微信支付的目录及URL没有固定的设置方法,具体还需要根据自己的需求来定,表1是方倍工作室的方案。
表1 微信支付目录及URL设置
需要注意的是,如果使用上述方法,要将域名换成自己的域名,其他的结构及层次可不变。这里所有的URL没有填写实际的文件名,目的是为了兼容不同的开发语言或框架。比如目录下的默认文件既可能是index.php,也可能是index.aspx。微信支付申请完成后,便进入了微信支付测试阶段,需要填写支付测试目录,测试目录可以填写为:/wxpay/test/。
JS API支付
JS API支付的实现比较简单,官方也提供了Demo,在此基础上修改部分参数即可。修改后的
一个示例如下:
include_once(&WxPayHelper.php&);
$commonUtil = new CommonUtil();
$wxPayHelper = new WxPayHelper();
$wxPayHelper-&setParameter(&bank_type&, &WX&);
$wxPayHelper-&setParameter(&body&, &微信支付开发教程&);
$wxPayHelper-&setParameter(&partner&, PARTNERID);
$wxPayHelper-&setParameter(&out_trade_no&, $commonUtil-&create_noncestr());
$wxPayHelper-&setParameter(&total_fee&, &1&);
$wxPayHelper-&setParameter(&fee_type&, &1&);
$wxPayHelper-&setParameter(&notify_url&,
&/wxpay/notify/&);
$wxPayHelper-&setParameter(&spbill_create_ip&, $_SERVER['REMOTE_ADDR']);
$wxPayHelper-&setParameter(&input_charset&, &GBK&);
$biz_package=$wxPayHelper-&create_biz_package();
上述代码中,主要修改了两个参数:notify_url为接收交易通知的路径,这个一定要改为自己服务器上的一个路径;spbill_create_ip为用户客户端的IP,不改关系也不大,不过改一下更规范些。
JS API支付是网页内的支付,通过调用微信支付控件来实现支付。如果要用作真实产品场景的支付,只需要修改一下产品名称及费用即可,对于涉及到快递费用的交易,需要注意订单的总金额为商品费用和物流费用的和。
如果微信支付时提示Access Denied,通常有以下原因:参数填写不正确、支付目录结构不正确、没有加入白名单权限。需要对照检查一下,才能找到具体原因并进行纠正。
Native支付
Native(原生)支付就是常说的扫描二维码支付。这种支付首先需要商户定义符合Native支付规范的URL,也就是Native支付URL,同时在微信后台POST商户后台时需要提供package内容。
Native支付的开发分为三步。
生成Native支付的URL
Native支付URL是一系列具有“weixin://wxpay/bizpayurl?”前缀的URL,同时后面紧跟着一系列辨别商户的键值对。
原生URL由wxPayHelper类中的create_native_url()方法实现,实现代码如下:
&p&&?php&/p&&p&include_once(&WxPayHelper.php&);$wxPayHelper = new WxPayHelper();&/p&&p&$productid = &&;echo $wxPayHelper-&create_native_url($productid);?&&/p&
其中productid是商品唯一ID,开发人员需要定义并维护自己的商品ID,这个ID与一张订单等价,微信后台凭借该ID通过POST商户后台获取交易信息。上述代码生成的URL如下所示:
weixin://wxpay/bizpayurl?appid=wxb489e8caeabcdefg&noncestr=BBvdr5atZ9D7s08X&produc
tid=&sign=e15db530e2f2f67ccb5&timestamp=
生成URL的二维码有了上述支付链接后,还要把它转成二维码,PHP QR Code是一个开源的二维码生成类库,可使用它来生成上述Native URL,代码如下:
include 'phpqrcode.php';$productid = &&;
$filename = $productid.&.png&;
$nativeurl = &weixin://wxpay/bizpayurl?ap
pid=wxb489e8caeabcdefg&noncestr=BBvdr5atZ9D7s08X&productid=&sign=e15db530e2f2f67ccb5&timestamp=&;QRcode::png($nativeurl, $filename, &L&, &5&, 2);
PHP QR Code的使用很简单,配置一下URL和文件名就可以了。执行上述代码,就会在当前目录下生成一个.png的二维码图片文件。
Navive支付回调URL
在前面说过,Native支付的回调URL设置为/wxpay/native/,当用户扫描上述二维码时,会调用该回调URL。URL需要调用订单信息Package返回给用户,而该Package是由WxPayHelper类的create_native_package()实现,调用代码如下:
include_once(&WxPayHelper.php&);$commonUtil = new CommonUtil();
$wxPayHelper = new WxPayHelper();
$wxPayHelper-&setParameter(&bank_type&, &WX&);
$wxPayHelper-&setParameter(&body&, &微信支付开发教程&);
$wxPayHelper-&setParameter(&partner&, PARTNERID);
$wxPayHelper-&setParameter(&out_trade_no&, $commonUtil-&create_noncestr());
$wxPayHelper-&setParameter(&total_fee&, &1&);
$wxPayHelper-&setParameter(&fee_type&, &1&);
$wxPayHelper-&setParameter(&notify_url&, &/wxpay/notify/&);
$wxPayHelper-&setParameter(&spbill_create_ip&, $_SERVER['REMOTE_ADDR']);
$wxPayHelper-&setParameter(&input_charset&, &GBK&);
$native_package = $wxPayHelper-&create_native_package();
echo $native_
上述代码中,参数的配置和JS API支付一样,只是最后调用的支付方式不一样。
与此同时,微信公众平台将会向回调URL推送XML格式的数据。这些数据中包含签名字段,可以用来验证是否是真正的支付二维码,但这个验证的必要性不是很大。而回调URL也会返回一个XML格式的数据给微用户,用户才能看到他所交易的商品信息的内容,这个XML的格式如下:
&AppId&&![CDATA[wxb489e8caeabcdefg]]&&/AppId&
&Package&&![CDATA[bank_type=WX&body=%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B&fee_type=1&input_charset=GBK&notify_
u r l = h t t p % 3 A % 2 F % 2 F w w w . d o u c u b e .
com%2Fwxpay%2Fnotify%2F&out_trade_no=RaurRyM00lk9JZ8H&partner=&spbill_create_ip=58.60.3.185&total_fee=1&sign=C580FDA6E31AA89549DEB494]]&&/Package&
&TimeStamp&&/TimeStamp&&NonceStr&&![CDATA[7omKw6AMZOq8022u]]&&/NonceStr&
&RetCode&0&/RetCode&&RetErrMsg&&![CDATA[ok]]&&/RetErrMsg&
&AppSignature&&![CDATA[e01aa37f19aedcd472882]]&&/AppSignature&
&SignMethod&&![CDATA[sha1]]&&/SignMethod&
如果商品已过期或有其他错误,则可以在上述返回XML数据中的RetCode和RetErrMsg中体现出来。例如:RetCode为其他非0值,RetErrMsg为“该商品已下架”。
在上述JS API或Native支付完成后,将向/wxpay/notify/发送交易通知,并且带上URL参数,一个完整的带参数URL如下:
&a href=&/wxpay/notify/index.php?discount=0&fee_type=1&input_charset=GBK&notify_id=xhLwKoKHzIQeMSQrEMJ7WXJNxyPKaUmxsn--xLtq4FT7LkAeFe-IHd_ARlj7kdyYUavoFfz5v2We9P6GEIv7zGgoVlT4gP2I&out_trade_no=omeDreZkCTQOuZSB&partner=&product_fee=1&sign=D18E640BDECB18CDBA88C2&sign_type=MD5&time_end=55&total_fee=1(TM)_mode=1(TM)_state=0&transaction_id=12012&&
&a href=&/wxpay/notify/index.php?discount=0&fee_type=1&input_charset=GBK&notify_id=xhLwKoKHzIQeMSQrEMJ7WXJNxyPKaUmxsn--xLtq4FT7LkAeFe-IHd_ARlj7kdyYUavoFfz5v2We9P6GEIv7zGgoVlT4gP2I&out_trade_no=omeDreZkCTQOuZSB&partner=&product_fee=1&sign=D18E640BDECB18CDBA88C2&sign_type=MD5&time_end=55&total_fee=1(TM)_mode=1(TM)_state=0&transaction_id=12012&/a&&/wxpay/notify/index.php?discount=0&fee_type=1&input_charset=GBK&notify_id=xhLwKoKHzIQeMSQrEMJ7WXJNxyPKaUmxsn--xLtq4FT7LkAeFe-IHd_ARlj7kdyYUavoFfz5v2We9P6GEIv7zGgoVlT4gP2I&out_trade_no=omeDreZkCTQOuZSB&partner=&product_fee=1&sign=D18E640BDECB18CDBA88C2&sign_type=MD5&time_end=55&total_fee=1(TM)_mode=1(TM)_state=0&transaction_id=12012&/a&/a&&
&transport_fee=0
同时,微信还发送POST数据,XML格式如下:
&OpenId&&![CDATA[oWWVStzuQl6Gz-pj39_Gk1lvnfoY]]&&/OpenId&
&AppId&&![CDATA[wxb489e8caeabcdefg]]&&/AppId&
&IsSubscribe&1&/IsSubscribe&
&TimeStamp&&/TimeStamp&
&NonceStr&&![CDATA[WW8xQ6th6ybgy0lF]]&&/NonceStr&
&AppSignature&&![CDATA[30ecacd2f6c1caac95727]]&&/AppSignature&
&SignMethod&&![CDATA[sha1]]&&/SignMethod&
注意,URL和XML中包含了此次交易的很多重要信息,其中有三项参数,分别是商户订单号out_trade_no,交易号transaction_id及XML数据中的OpenID,这几个参数将在后续很多接口中使用到。
订单查询API的URL为:
h t t p s : / / a p i . w e i x i n . q q . c o m / p a y /orderquery?access_token=xxxxxx
URL中的参数只包含微信公众平台凭证access_token,而订单查询的真正数据是放在PostData中的,格式如下:
&appid&:&wwwwb4f85f3a797777&,
&package&:&out_trade_no=11122&partner=&sign=4e8d0df3da0c3d0df38f&,
&timestamp&:&&,
&app_signature&:&53cca9d47b883bd4a5c85acb48565c&,
&sign_method&:&sha1&
订单查询这一接口,开发文档中并没有给出Demo,所以需要自己来实现。其中关键点是生成参数package中的sign和app_signature。其中,sign是对参数字典序排序并使用“&”联合起来,最后加上&key=partnerkey(唯一分配),进行md5运算,再转成全大写,最终得到sign。而app_signature则是根据支付签名(paySign)生成方法中所讲的签名方式生成,参加签名字段为:appid、appkey、package、timestamp。相关代码实现如下所示:
$sign= strtoupper(md5(&out_trade_no=JfuKdiBig4zZnE4n&partner=&key=asdfas
dfasdfasdfasdfasdfasdfasdf&));
$package = &out_trade_no=JfuKdiBig4zZnE4n&partner=&sign=&.$
$obj['appid'] = &wx0000&;
$obj['appkey'] = &8mruTNOGeX8OVUlIYxIyw6kxCRvdJENpWpw8mruTNOGeX8OVUlIYxIyw6kxCRvd
JENpWpw8mruTNOGeX8OVUlIYxIyw6kxCRvdJENpWpw8mruTNOGeX8OVUlIYxIyw6k&;
$obj['package'] = $
$obj['timestamp'] = time();
$WxPayHelper = new WxPayHelper();//get_biz_sign函数为protected类型,可改为public
$app_signature = $WxPayHelper-&get_biz_sign($obj);
发货通知API的URL为:
h t t p s : / / a p i . w e i x i n . q q . c o m / p a y /delivernotify?access_token=xxxxxx
URL中的参数只包含微信公众平台凭证access_token,而发货通知的真正数据放在PostData中,格式如下:
&appid&:&wwwwb4f85f3a797777&,&openid&:&oX99MDgNcgwnz3zFN3DNmo8uwa-w&,
&transid&:&333&,
&out_trade_no&:&555666uuu&,
&deliver_timestamp&:&&,
&deliver_status&:&1&,
&deliver_msg&:&ok&,
&app_signature&:&53cca9d47b883bd4a5c8
&span style=&font-family: Helvetica, Tahoma, Arial, sans- font-size: 14&&5acb48565c&,&/span&&p& &sign_method&:&sha1&
发货通知也没有Demo,需要自己开发实现,其中的关键点也是生成app_signature,它根据支付签名(paySign)生成方法中所讲的签名方式生成,参加签名字段为:appid、appkey、openid、transid、out_trade_no、deliver_timestamp、deliver_status、deliver_msg。实现代码如下所示:
$deliver_timestamp = time();
$obj['appid'] = APPID;
$obj['appkey'] = APPKEY;
$obj['openid'] = &oWWVStzuQl6Gz-pj39_Gk1lvnfoY&; //交易通
知XML中获得$obj['transid'] = &5725&; //jsapi中生成,交易通
知URL中获得$obj['out_trade_no'] = &omeDreZkCTQOuZSB&; //jsapi中生成,交易通
知URL中获得$obj['deliver_timestamp'] = $deliver_
$obj['deliver_status'] = &1&;
$obj['deliver_msg'] = &ok&;
$WxPayHelper = new WxPayHelper();
$app_signature = $WxPayHelper-&get_biz_
sign($obj);
告警通知的URL为申请微信支付时设置的/wxpay/alarm/,微信后台将向
该URL推送包含PostData的XML数据,数据中包含错误类型、错误描述、错误详情等信息。告警数据在接收后需要写入到系统告警模块中,并要求商户尽快做出处理,以免影响线上经营。
维权通知的URL为申请微信支付时设置的/wxpay/rights/,用户在新增投诉单及确认处理完毕投诉后,微信后台都会向该URL推送包含PostData的XML数据, 数据中包含维权内容信息。维权通知是被动接收到的通知,接收到后,最好能使用模版消息提醒自己,以免错过处理时限。
标记投诉处理
标记客户投诉处理状态API的URL为:https://api./payfeedback/update?access_token=xxxxx&openid=XXXX&feedbackid=xxxx
URL中的参数包含微信公众平台凭证access_token,客户投诉对应的单号feedbackid,以及OpenID。填好参数后访问该URL即可返回“标记成功”的通知。
收货地址共享
收货地址共享的开发是微信支付开发中最复杂的部分,主要原因有:官方没有Demo;开发文档含糊不清;签名算法与之前的不一致,需要自己新实现;JS API回调后不能给出错误原因提示,调试没有方向感,需要开发者对高级接口中的OAuth2.0过程非常精通。收货地址共享的完整实现步骤如下。
设置授权回调域名
OAuth2.0授权页面域名的配置在公众平台网站→开发者中心→接口权限表→高级接口→OAuth2.0网页授权中设置,将域名设置成微信支付授权目录中的域名,如。
构造请求授权回调URL
请求OAuth2.0授权的URL如下:
请求授权参数说明如表2所示。
这里,构造请求接口如下:
其中,/wxpay/getAddress.php是获取共享收获地址的页面。作用域使用snsapi_base,用户访问上述请求接口之后,将会跳转到页面/wxpay/getAddress.php?code=02feabc395c1b2e0451547&state=1。
获取共享收货地址
在getAddress.php页面,首先需要获取授权Access Token,这个Access Token是OAuth2.0授权时获得的,不是自定义菜单实现时的那个Access Toekn。实现代码如下:
$appid = APPID;
$appsecret = APPSERCERT;
$code = $_GET[&code&];
$access_token_url = &https://api.weixin.
qq.com/sns/oauth2/access_token?appid=$ap
pid&secret=$appsecret&code=$code&grant_
type=authorization_code&;
$access_token_json = file_get_
contents($access_token_url);
$ a c c e s s _ t o k e n _ a r r a y = j s o n _
decode($access_token_json, true);
$access_token = $access_token_
array['access_token'];
然后需要计算出地址签名,参与addrSign签名的字段包括:appid、url(当前网页URL,包含code和state参数)、timestamp、noncestr、accessToken(用户OAuth2.0授权凭证)。这里scope、signType不参与签名。这是共享收获地址中最关键的一步,它对所有待签名参数按照字段名ASCII码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2……)拼接成字符串string1。然后对string1作签名算法,字段名和字段值都采用原始值,并进行URL转义。具体签名算法为addrSign = SHA1(string1)。其代码如下:
$commonUtil = new CommonUtil();
$noncestr = $commonUtil-&create_noncestr();
$timestamp = time();
$url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$wxPayHelper = new WxPayHelper();
$obj['appId'] = $
$obj['url'] = $
$obj['timestamp'] = $
$obj['noncestr'] = $
$obj['accessToken'] = $access_//参数小写
foreach ($obj as $k =& $v){ $obj2[strtolower($k)] = $v; }//字典序排序
ksort($obj2);//URL键值对拼成字符串
$ b i z S t r i n g = $ c o m m o n U t i l -&formatBizQueryParaMap($obj2, false);//sha1签名
$signature = sha1($bizString);
所有字段的值都获取成功以后,就赋值成收货地址接口的JS API中的变量值。
其他接口还有退款接口、退款查询接口、对账单下载等,他们都有Demo,配置好后即可使用。其中唯一要注意的就是退款接口的开发中pem证书的生成方法。在退款接口的开发中,需要把pfx证书转换pem证书,转换后将pem文件作为私钥。这需要用到OpenSSL这一工具,一般Linux已自带该功能。在Linux下的转换命令如下:
[root@FANGBEI wxpay]# openssl pkcs12 -in .pfx -out .pem
Enter Import Password:MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
[root@FANGBEI wxpay]# lltotal 8-rw-r--r-- 1 root root 4011 Aug 14 15:31 .pem-rw-r--r-- 1 root root 2717 Aug 14 15:28 .pfx
[root@FANGBEI wxpay]#
转换过程中需要输入商户ID来解密旧证书,然后设置新密码来加密新证书,新密码将在退款程序中配置使用。
微信支付的开发文档中对部分关键技术阐述不详,不利于开发者快速理解上手。本文从申请微信支付时目录及URL设置到各种接口开发中的核心部分都做了讲解,希望能为微信支付的开发人员提供帮助,加快开发速度。
的持续更新
如果您不想错过与他们的交流机会,请点击报名,3人以上团购可享受优惠价。主办方还特别开通了微信开发者QQ群:,欢迎加入交流。
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 下载微信 的文章

 

随机推荐