マイクロチャネル支払いのスキャンコード、APP、支払いアプレットのアクセス説明

小さなパートナーを行うには、電子ビジネスプラットフォーム決済サービスは、我々は決済サービスと実装へのアクセスについて話し始める今日の本質的な部分であることを知っています。中国では、中小企業の90%近くは、少額決済システムアリペイの支払いや手紙なしで行うことはできません。マイクロチャネル支払いとアリペイは、ほとんどの企業のための最初の選択肢として使用することができますなぜ私たちが考えなければならない、それへのアクセス?実は、これは、アリペイはまた、約800百万近い小さなパートナーは白の人々は巨大なユーザトラフィックを持っていること、国内のユーザーの現在のマイクロチャネルは10億を超えている、非常に明確にする必要があり、大部分である、このような大規模なユーザーベース、あなたが選択されます他のサードパーティ決済は、他のサービスが、あなたは彼を与えるかしない限りためのプラットフォームをダウンロードまたは開くために何かを買うでしょう、通常の顧客として、我々はすべて簡単かつ迅速にできるようにしたいん、(財布、速いお金を通じて支払ったお金などをマイクロブログ)魅惑的な利点があります。今日では、アクセスおよびマイクロチャネルを実装するには、私たちについての最初の話を支払います。

 
画像

マイクロチャネルの有料アクセス

私たちは、好適なマイクロチャンネルの公式ウェブサイトを支払う用意公式ドキュメントの開発を見てみることを行ってきました。リンクアドレス:https://pay.weixin.qq.com/wiki/doc/api/index.html

 
画像

我々は(上図のように)現在利用可能なマイクロチャネルの有料支払いを見て、ネイティブの支払い(支払いにスキャンコード)、アプリケーションの支払いと支払いアプレット3については、この話。まず、準備作業

開発前に、マイクロチャネルのマ​​イクロチャネル公共番号や小さなプログラム(現在はマイクロチャネルの企業が数を開くことができる唯一の公共のバージョンを支払う)のビジネス版を申請する必要があり、その後、マイクロチャネル決済機能を立ち上げて、適切な設定を行います。

 
画像

公共のマイクロチャネル番号とマイクロチャネル支払い(事業)の開口部に購読を検討し、一般的に約5営業日する必要があります。成功のオープニングの後、我々は、構成情報を取得する必要があります。

wx.pay.appid=***
wx.pay.mchid=***
wx.pay.key=***
wx.pay.secret=***

注:appid是公众号ID,mchid是支付的商户ID,其中appid和secret可以在公众平台找着,mchid和key则在商户平台找到,特别是key(即API_KEY)要在商户平台设置好。本项目中这些配置通过properties文件放在-payment-service工程的resource根路径下。
在编码之前,还需要登录微信商户平台配置支付回调URL,此配置作为支付成功后回调接口的域名。如果配置的URL为:http://www.abc.com/, 你的支付回调路径则可设置为:http://www.abc.com/api/payment/notify。二,编码阶段
*在开始编码前,我们必须先了解清楚微信支付的对接及支付的业务流程。

  • 扫码支付的业务流程:
 
image
  • App支付的业务流程:
 
image
  • 小程序支付的业务流程:
 
image

从官方提供的业务流程图我们可以大致总结对接流程如下:

1,在发起支付前,先在自己的商户后台下单,生成商户订单信息;

2,根据对应支付方式的参数需求,封装对应所需参数,并调用微信官方提供的统一下单Api接口下单;

3,统一下单成功,微信后台返回对应的响应数据。返回数据类型如下:

  • 扫码支付统一下单后会返回生成二维码图片的链接code_url;
  • app和小程序支付统一下单后会返回预支付id,即:prepay_id;

4,如果扫码支付,你要用code_url生成一个二维码展示在前端页面供客户扫码付款;如果是app和小程序支付,后端只需将prepay_id及需要的参数传给app和小程序端。app会通过调用SDK、小程序会通过调用微信的JS发起支付。5,客户付款成功后,客户的微信端会展示付款结果信息,同时微信后台会异步调用商户后台的回调接口(回调的api接口在统一下单作为下单参数),更新商户系统的支付单状态。

看到这里,大家会发现这三种方式的基本业务流程都差不多,只是由于不同支付方式调起微信应用支付功能的方式不同,所以统一下单成功后返回的参数有所不同。

Controller接口层:


@RestController
@RequestMapping(value = "/api/payment/")
public class PaymentController { private static Logger logger = LoggerFactory.getLogger(PaymentController.class); @Autowired private PaymentService paymentService; /** * App支付接口 * 微信和支付宝统一下单入口 * * @param request * @return * @throws Exception */ @ResponseBody @RequestMapping(value="toPay", method=RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) public JSONObject toPay(HttpServletRequest request) throws Exception { String requestStr = RequestStr.getRequestStr(request); if (StringUtils.isEmpty(requestStr)) { throw new ParamException(); } JSONObject jsonObj = JSONObject.parseObject(requestStr); if(StringUtils.isEmpty(jsonObj.getString("orderNo")) || StringUtils.isEmpty(jsonObj.getString("payAmount"))){ throw new ParamException(); } //验证订单是否存在 String orderNo = jsonObj.getString("orderNo"); double payAmount = jsonObj.getDouble("payAmount"); if(payAmount < 0.01){ return AjaxUtil.renderFailMsg("订单有误,请确认!"); } else { //微信支付 Map<String, String> resMap = paymentService.wxAppPayment(orderInfo.getOrderNo(),orderInfo.getPayPrice(),null); //判断微信统一下单是否成功 if("SUCCESS".equals(resMap.get("returnCode")) && "OK".equals(resMap.get("returnMsg"))){ //统一下单成功 resMap.remove("returnCode"); resMap.remove("returnMsg"); logger.info("【App支付服务】微信支付下单成功!"); return AjaxUtil.renderSuccessMsg(resMap); }else{ logger.info("【App支付服务】微信支付下单失败!原因:"+resMap.get("returnMsg")); return AjaxUtil.renderFailMsg(resMap.get("returnMsg")); } } } 

PaymentService接口方法:

 
image

PaymentService实现类部分代码(微信App支付):

@Service(value = "paymentService")
public class PaymentServiceImpl implements PaymentService { private static Logger LOGGER = LoggerFactory.getLogger(PaymentServiceImpl.class); @Value("${spring.profiles.active}") private String PROJECT_ENV; @Value("${hcc.pay.domain}") private String payDomain; @Autowired private PaymentRecordMapper paymentRecordMapper; @Override @Transactional(readOnly=false,rollbackFor={Exception.class}) public Map<String,String> wxAppPayment(String orderId, double money,Long customerId) throws Exception { LOGGER.info("【微信App支付】 统一下单开始, 订单编号="+orderId); SortedMap<String, String> resultMap = new TreeMap<String, String>(); //生成支付金额 double payAmount = PayUtils.getPayAmountByEnv(PROJECT_ENV, money); //TODO 操作数据库,添加或更新支付记录 //this.addOrUpdatePaymentRecord(......); //微信统一下单 Map<String,String> resMap = this.wxUnifieldOrder(orderId, PayConfig.TRADE_TYPE_APP, payAmount, null); if(PayConstant.SUCCESS.equals(resMap.get("return_code")) && PayConstant.OK.equals(resMap.get("return_msg"))){ //封装参数返回 resultMap.put("appid", PayConfig.WX_APP_ID); resultMap.put("partnerid", PayConfig.WX_MCH_ID); resultMap.put("prepayid", resMap.get("prepay_id")); resultMap.put("package", "Sign=WXPay"); resultMap.put("noncestr", PayUtils.makeUUID(32)); resultMap.put("timestamp", PayUtils.getCurrentTimeStamp()); resultMap.put("sign", PayUtils.createSign(resultMap,PayConfig.WX_KEY)); resultMap.put("returnCode", "SUCCESS"); resultMap.put("returnMsg", "OK"); LOGGER.info("【微信App支付】统一下单成功,返回参数:"+resultMap); }else{ resultMap.put("returnCode", resMap.get("return_code")); resultMap.put("returnMsg", resMap.get("return_msg")); LOGGER.info("【微信App支付】统一下单失败,失败原因:"+resMap.get("return_msg")); } return resultMap; } 

统一下单方法(在PaymentService实现类里):


/**
     * <p>微信支付统一下单</p>
     *
     * @param orderId 订单编号
     * @param tradeType 支付类型
     * @param payAmount 支付金额
     * @param openid
     * @return
     * @throws Exception
     */
    private Map<String,String> wxUnifieldOrder(String orderId, String tradeType, double payAmount, String openid) throws Exception{ //封装参数 SortedMap<String,String> paramMap = new TreeMap<String,String>(); String appid = PayConfig.WX_APP_ID; String mchid = PayConfig.WX_MCH_ID; if(PayConstant.WX_TRADE_TYPE_JSAPI.equals(tradeType)){ appid = PayConfig.XCX_APP_ID; mchid = PayConfig.XCX_MCH_ID; } paramMap.put("appid", appid); paramMap.put("mch_id", mchid); paramMap.put("nonce_str", PayUtils.makeUUID(32)); paramMap.put("body", BaseConstants.PLATFORM_COMPANY_NAME); paramMap.put("out_trade_no", orderId); paramMap.put("total_fee", PayUtils.moneyToIntegerStr(payAmount)); paramMap.put("spbill_create_ip", PayUtils.getLocalIp()); paramMap.put("notify_url", this.getNotifyUrl(PayConstant.PAY_TYPE_WX)); paramMap.put("trade_type", tradeType); if(PayConstant.WX_TRADE_TYPE_JSAPI.equals(tradeType)){ paramMap.put("openid",openid); } paramMap.put("sign", PayUtils.createSign(paramMap,PayConfig.WX_KEY)); //转换为xml String xmlData = PayUtils.mapToXml(paramMap); //请求微信后台 String resXml = HttpUtils.postData(PayConfig.WX_PAY_UNIFIED_ORDER, xmlData); LOGGER.info("【微信支付】 统一下单响应:\n"+resXml); return PayUtils.xmlStrToMap(resXml); } 

统一下单完成,微信后台将相应的参数以xml的形式返回,统一下单成功后返回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> 

因此我们需要将统一下单后的xml解析成map(上面的统一下单方法里已经转换成map),并判断下单状态。如果返回的return_code为SUCCESS并return_msg为OK,那么表示统一下单成功,然后封装对应的参数返回给前端。前端根据下单成功后Java后端返回的参数,进行相应的处理并唤起微信应用的支付服务。注意,扫码支付是用统一下单成功后微信后台返回的code_url生成二维码展示给客户。二维码的生成可以前端也可Java后端生成然后以输出流的形式输出到网页上(坚决不建议Java端生成二维码图片保存到文件服务器然后再展示)。

客户在手机调起微信支付服务并输入密码成功付款后,客户手机的微信里会收到支付成功的付款信息,同时微信后台也在异步调用商户的后台接口。这个回调地址就是在统一下单方法里我们传的notify_url字段的参数值。

下面是回调接口代码:

/**
   * 微信支付完成回调Api
   * 
   * @param request
   * @param response
   * @throws Exception
   */
    @RequestMapping(value="notify")
  public void wxNotify(HttpServletRequest request,HttpServletResponse response) throws Exception {
     InputStream inputStream =  request.getInputStream();
     //获取请求输入流
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len=inputStream.read(buffer))!=-1){
            outputStream.write(buffer,0,len);
        }
        outputStream.close();
        inputStream.close();
        Map<String,Object> map = BeanToMap.getMapFromXML(new String(outputStream.toByteArray(),"utf-8"));
        logger.info("【微信支付回调】 回调数据:\n"+map);
        String resXml = "";
        String returnCode = (String) map.get("return_code");
        if ("SUCCESS".equalsIgnoreCase(returnCode)) {
            String returnmsg = (String) map.get("result_code");
            if("SUCCESS".equals(returnmsg)){
              //更新支付单状态信息
              int result = paymentService.wxNotify(map);
              if(result > 0){
                //支付成功
                  resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>"+"</xml>"; } }else{ resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]></return_msg>" + "</xml>"; logger.info("支付失败:"+resXml); } }else{ resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]></return_msg>" + "</xml>"; logger.info("【订单支付失败】"); } logger.info("【微信支付回调响应】 响应内容:\n"+resXml); //做出响应 response.getWriter().print(resXml); } 

到此为止,所有的编码工作已完成。

三,测试(用扫码支付)

选择要购买的商品,然后下单,再去发起支付。

 
image

单击“去支付”按钮,跳转到二维码支付页面:

 
image

扫码支付完成后,显示二维码的页面会跳转到支付成功页面(带微信支付成功logo),并有3s的倒计时,然后跳转到“订单详情”页。

 
image

本文章只是给大家讲解原理和接入思路及实现,所以文章里只放了核心业务代码。还有好多工具类及配置等代码,全放到这里来肯定也不现实,如果有需要完整代码的可关注公众号获取。

获取方式

扫码关注公众号;找到“关于我”>>>"联系我" ;添加我个人微信获取;

 
 

おすすめ

転載: www.cnblogs.com/lyn20141231/p/11465124.html