打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
使用Delphi Xe8 开发微信功能 -- (四)微信支付商户平台之申请退款
接上篇。这次是商户平台的申请退款功能。此功能要点是商户平台退款功能要求使用HTTPS双向证书,所以通过TIdSSLIOHandlerSocketOpenSSL.SSLOptions.CertFile加载微信颁发的证书文件,TIdSSLIOHandlerSocketOpenSSL.SSLOptions.KeyFile加载证书密钥文件。需要注意的是,该接口在收到客户端发送的正确(格式、数据、证书等)请求后,会立即执行退款操作,没有审核环节,执行成功及开始退款流程,所以需要客户端应用程序把好审核关,防止错退的情况发生。代码如下:
  1. unit weixinapi;

  2. interface
  3. uses  IdHTTP,//indy HttpClient
  4.       //使用RealThinClientSDK_v628中的rtcInfo的Utf8Decode函数来消除中文乱码问题,
  5.       //System中自带的Utf8Decode有问题
  6.       rtcInfo,
  7.       IWNativeXml,//NativeXML
  8.       System.Classes,//FileStream
  9.       System.Variants,//使用随机数初始化函数Randomize
  10.       System.SysUtils,Xml.XMLDoc,Data.Win.ADODB,//使用XMLDocument、AdoConnection、AdoQuery
  11.       //退款功能要求使用颁发的证书文件和密钥文件
  12.       IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL;
  13.       function weixinapi_refund(op_user_id,out_refund_no,out_trade_no,refund_fee,
  14.                               total_fee,transaction_id:string):string;
  15.       function MD5_encrypt(str_TEMP:string):string;
  16.       const api_id='你的公众账号ID';//你的公众账号ID
  17.             mch_id='你的商户号';//你的商户号
  18.             api_key='你的API密钥';//你的API密钥
  19.             refund_url='https://api.mch.weixin.qq.com/secapi/pay/refund';//申请退款网址

  20. implementation

  21. //微信商户对账功能-申请退款
  22. //op_user_id:操作员,out_refund_no:商户退款单号,out_trade_no商户订单号,
  23. //refund_fee:退款金额,total_fee:总金额, transaction_id:微信订单号
  24. function weixinapi_refund(op_user_id,out_refund_no,out_trade_no,refund_fee,
  25.     total_fee,transaction_id:string):string;
  26. var xmldd:TNativeXml;
  27.     fsparams:TFileStream;
  28.     idhttp_refund:TIdHTTP;
  29.     //Nativexml中没有发现如何赋值已有的xml,只好重新加入系统自带的xml
  30.     sRe_XML:TXMLDocument;
  31.     stringA:string;
  32.     stringTEMP:string;
  33.     nonce_str:string;
  34.     sign:string;
  35.     sResponse:string;
  36.     iohandssl:TIdSSLIOHandlerSocketOpenSSL;
  37. begin
  38.   Randomize;
  39.   nonce_str:=IntToStr(Random(1000000));//得到随机数nonce_str
  40.   stringA:='appid='+api_id+'&mch_id='+mch_id+'&nonce_str='+nonce_str+
  41.           '&op_user_id='+op_user_id+'&out_refund_no='+out_refund_no+
  42.           '&out_trade_no='+out_trade_no+'&refund_fee='+refund_fee+
  43.           '&total_fee='+total_fee+'&transaction_id='+transaction_id;
  44.   stringTEMP:=stringA+'&key='+api_key;
  45.   sign:=MD5_encrypt(stringTEMP);//使用MD5加密函数对stringTEMP进行加密,得到sign签名
  46.   try
  47.     //创建通过idhttp POST 的xml文件
  48.     xmldd:=TNativeXml.CreateName('xml');
  49.     xmldd.EncodingString:='utf-8';
  50.     xmldd.XmlFormat:=xfReadable;
  51.     xmldd.Root.WriteString('appid',api_id);
  52.     xmldd.Root.WriteString('mch_id',mch_id);
  53.     xmldd.Root.WriteString('nonce_str',nonce_str);
  54.     xmldd.Root.WriteString('op_user_id',op_user_id);
  55.     xmldd.Root.WriteString('out_refund_no',out_refund_no);
  56.     xmldd.Root.WriteString('out_trade_no',out_trade_no);
  57.     xmldd.Root.WriteString('refund_fee',refund_fee);
  58.     xmldd.Root.WriteString('total_fee',total_fee);
  59.     xmldd.Root.WriteString('transaction_id',transaction_id);
  60.     xmldd.Root.WriteString('sign',sign);
  61.     xmldd.SaveToFile('weixin_refundd_'+out_trade_no+'.xml');
  62.   except
  63.     on e: Exception do
  64.       Result:=e.Message;
  65.   end;
  66.   //根据创建的xml文件创建fsparams文件流,
  67.   //试验过多种格式的post内容,string、TStrings、标准xml文件,
  68.   //最后发现使用TFileStream POST过去的内容
  69.   //微信接口才识别为xml格式,其他格式都会报XML Format Error等错误
  70.   fsparams:=TFileStream.Create('.\weixin_refundd_'+out_trade_no+'.xml',fmOpenRead or fmShareDenyWrite);
  71.   try
  72.     sRe_XML:=TXMLDocument.Create(nil);
  73.     //对于不同版本的SSL库需要加上TIdSSLIOHandlerSocketOpenSSL,
  74.     //不然会报IOHandler value is not valid错误
  75.     //同时退款功能要求使用颁发的证书文件和密钥文件   
  76.     iohandssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  77.     idhttp_refund:=tIdHTTP.Create();
  78.     idhttp_refund.Request.ContentType:='text/xml';
  79.     idhttp_refund.Request.CharSet:='UTF-8';
  80.     idhttp_refund.IOHandler:=iohandssl;
  81.     //加载微信支付商户平台颁发的证书文件
  82.     iohandssl.SSLOptions.CertFile:='cert_api/apiclient_cert.pem';
  83.     //加载微信支付商户平台颁发的密钥文件
  84.     iohandssl.SSLOptions.KeyFile:='cert_api/apiclient_key.pem';
  85.     idhttp_refund.HandleRedirects:=True;
  86. //    idhttp_refund.IOHandler.Close;
  87.     //使用的UTF8Decode函数是rtcInfo里面的,不是system里面的,system中的还是会乱码
  88.     sRe_XML.XML.Text:=Utf8Decode(idhttp_refund.Post(refund_url,fsparams));
  89.     sRe_XML.XML.SaveToFile('weixin_refunddetial_'+out_trade_no+'.xml');
  90.     Result:=sRe_XML.XML.Text;//返回从微信接口收到的数据
  91.     FreeAndNil(fsparams);
  92.     FreeAndNil(idhttp_refund);
  93.     FreeAndNil(sre_XML);
  94.   except
  95.     on e: Exception do
  96.       Result:=e.Message;
  97.   end;
  98. end;

  99. //MD5加密,试过多种方法包括 SQLServer、MD5单元来进行MD5加密,却都得不到正确的MD5加密值,
  100. //无奈使用了mysql的MD5函数来进行,有更好更简洁的方法吗
  101. function MD5_encrypt(str_TEMP:string):string;
  102. var adoc_md5:TADOConnection;
  103.     adoq_md5:TADOQuery;
  104. begin
  105.   try
  106.     adoc_md5:=TADOConnection.Create(nil);
  107.     adoc_md5.ConnectionString:='Provider=MSDASQL.1;Persist Security Info=False;Data Source=my;';
  108.     adoc_md5.LoginPrompt:=False;
  109.     adoc_md5.Connected;
  110.     adoq_md5:=TADOQuery.Create(nil);
  111.     adoq_md5.Connection:=adoc_md5;
  112.     adoq_md5.SQL.Text:='select upper(md5('''+str_TEMP+''')) as sign_str';
  113.     adoq_md5.Open;
  114.     Result:=adoq_md5.FieldByName('sign_str').AsString;
  115.   finally
  116.     FreeAndNil(adoc_md5);
  117.     FreeAndNil(adoq_md5);
  118.   end;
  119. end;
  120. end.
复制代码
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Delphi IDHTTP控件:GET/POST 请求 json xml
beego 获取字符串中的数据
SSH实现的增删改查实例
教你如何修改qq登录界面
工作流引擎Activiti使用总结
C#常用的加密算法:MD5、Base64、SHA1、SHA256、HmacSHA256、DES、AES、RSA
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服