DELPHI微信支付代码

 

不管是微信支付还是支付宝支付, 3个最棘手的问题是:
1,如何生成签名
2,支付请求如何提交
3, 如何验证签名

下面就围绕这二个问题来讲。

我使用的是XE3.

先看微信支付:
1,微信支付的签名生成

uses IdHashMessageDigest, NatvieXml; //我使用的是NativeXml4.07

function TMicroPayParamBuilder.GetSign: string;
var
Digest: TIdHashMessageDigest5;
utf8: UTF8String;
begin
utf8 := '';

Assert(FAppId <> '', '公众账号ID 不能为空!');
utf8 := utf8 + 'appid=' + FAppId;

if FAttach <> '' then
utf8 := utf8 + '&attach=' + FAttach;

Assert(FAuthCode <> '', '授权码 不能为空!');
utf8 := utf8 + '&auth_code=' + FAuthCode;

Assert(FBody <> '', '商品描述 不能为空!');
utf8 := utf8 + '&body=' + FBody;

if FDetail <> '' then
utf8 := utf8 + '&detail=' + BuildDetail();

Assert(FMchId <> '', '商户号 不能为空!');
utf8 := utf8 + '&mch_id=' + FMchId;

utf8 := utf8 + '&nonce_str=' + FNonceStr;

Assert(FOutTradeNo <> '', '商户订单号 不能为空!');
utf8 := utf8 + '&out_trade_no=' + FOutTradeNo;

Assert(FSpbillCreateIp <> '', '终端IP 不能为空!');
utf8 := utf8 + '&spbill_create_ip=' + FSpbillCreateIp;

Assert(FTotalFee > 0, '订单金额 必须大于0!');
utf8 := utf8 + '&total_fee=' + IntToStr(FTotalFee);

Assert(Fkey <> '', '密钥 不能为空!');
utf8 := utf8 + '&key=' + Fkey;

//计算签名
try
Digest:= TIdHashMessageDigest5.Create;
Result := Digest.HashBytesAsHex(BytesOf(utf8));
finally
Digest.Free;
end;
end;

//生成Http Post请求的数据
function TMicroPayParamBuilder.BuildParam: string;
var
xml : TNativeXml;
Node: TXmlNode;
begin
xml := TNativeXml.CreateEx(nil, False, False, True, 'xml');
try
Node:= xml.NodeNewTextType('appid', FAppId , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('mch_id', FMchId , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('nonce_str', FNonceStr , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('sign', Sign , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('body', FBody , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('out_trade_no', FOutTradeNo , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewIntType('total_fee', FTotalFee , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('spbill_create_ip', FSpbillCreateIp , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('auth_code', FAuthCode , xeElement);
xml.Root.NodeAdd(Node);

if FAttach <> '' then
begin
Node:= xml.NodeNewTextType('attach', FAttach , xeElement);
xml.Root.NodeAdd(Node);
end;

if FDetail <> '' then
begin
Node:= xml.NodeNewTextType('detail', BuildDetail() , xeElement);
xml.Root.NodeAdd(Node);
end;

Result := xml.WriteToString;

finally
xml.Free;
end;
end;

2, 微信支付请求如何提交 
class function TTencentSSLHttpPost.Post(URL: string;
Builder: TBaseParamBuilder): string;
var
ssl:TIdSSLIOHandlerSocketOpenSSL;
http: TIdHttp;
inStrm, outStrm: TStringStream;
begin
http:= TIdHttp.Create(nil);
ssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
ssl.SSLOptions.Method := sslvSSLv23;
http.IOHandler := ssl;
inStrm:= TStringStream.Create(Builder.BuildParam, TEncoding.UTF8);
outStrm:= TStringStream.Create('', TEncoding.UTF8);
try
try
http.Post(URL, inStrm, outStrm);
Result := outStrm.DataString;

except
Result := '';
end;
finally
ssl.Free;
http.Free;
outStrm.Free;
inStrm.Free;
end;
end;

const URL_MicroPay = 'https://api.mch.weixin.qq.com/pay/micropay';

class function TMicroPayHttpUtils.PostRequest( Builder: TMicroPayParamBuilder): string;
begin Result := TTencentSSLHttpPost.Post(URL_MicroPay, Builder);
end;

微信如何验证签名:

TStringsHelper = class helper for TStrings
function Join(const Splitter: string): string;
end;

{ TMyStrings}

function TStringsHelper.Join(const Splitter: string): string;
var
I : Integer;
begin
Result := '';
for I := 0 to Self.Count - 1 do
Result := Result + Splitter + Self.Names[I] + '=' + Self.ValueFromIndex[I];

if Result <> '' then System.Delete(result, 1, Length(Splitter));
end;

function MyStringListSort(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := CompareStr(List.Names[Index1], List.Names[Index2]);
end;

function VerifyResponseSign(xml: TNativeXml; Key: string): Boolean; overload;
var
sign: string;
I : Integer;
List : TStringList;
utf8: UTF8String;
Digest: TIdHashMessageDigest5;
begin
Result := False;

if xml.Root.FindNode('sign') = nil then Exit;
sign := xml.Root.FindNode('sign').ValueUnicode;

List := TStringList.Create;
try
for I := 0 to xml.Root.NodeCount - 1 do
begin
if (xml.Root.Nodes[I].NameUnicode <> 'sign') and (xml.Root.Nodes[I].NameUnicode <> 'WhiteSpace')
and (xml.Root.Nodes[I].ValueUnicode <> '') then
List.Add(xml.Root.Nodes[I].NameUnicode + '=' + xml.Root.Nodes[I].ValueUnicode);
end;
List.CustomSort(MyStringListSort);

utf8 := List.Join('&') + '&key=' + key;

try
Digest:= TIdHashMessageDigest5.Create;
Result := SameText(Digest.HashBytesAsHex(BytesOf(utf8)), sign);
finally
Digest.Free;
end;
finally
List.Free;
end;
end;

function VerifyResponseSign(xml: TNativeXml): Boolean; overload;
begin
Result := VerifyResponseSign(xml, GetKey());
end;

function VerifyResponseSign(Response: string; Key: string): Boolean; overload;
var
xml: TNativeXml;
begin
Result := False;
xml := TNativeXml.Create(nil);
try
try
xml.ReadFromString(Response);
except
Exit;
end;

Result := VerifyResponseSign(xml, Key);
finally
xml.Free;
end;
end;

那么如何发送一个刷卡支付请求呢?
procedure TForm4.btn4Click(Sender: TObject);
var
Param: TMicroPayParamBuilder;
Response: string;
begin
Param:= TMicroPayParamBuilder.Create;
try
if edBody.Text <> '' then
Param.Body := edBody.Text;
Param.OutTradeNo:= edTradeNo.Text;
Param.SpbillCreateIp:=idpwtch1.LocalIP;
param.AuthCode:= edAuthCode.Text;
Param.Attach := edAttach.Text;
Param.TotalFee := 10;

param.AppId := edAppId.Text;
Param.MchId := edMch_id.Text;
Param.Key := edKey.Text;

mmo1.Lines.Append(Param.BuildParam);
mmo1.Lines.Append('-------------------------------------------');

Response := TMicroPayHttpUtils.PostRequest(Param);

if Response = '' then
begin
ShowMessage('请求出错! 可能是网络不通!');
Exit;
end;

mmo1.Lines.Append(Response);

if not VerifyResponseSign(Response, GetKey()) then 
showmessage('签名验证不通过!');

finally
Param.Free;
end;
end;

DELPHI微信支付代码的更多相关文章

  1. asp微信支付代码证书文件post_url.aspx和post_url.aspx.cs源码下载

    很多朋友在网上找的asp支付代码中都没有这两个证书文件,只能是用别人的,但是如果别人把他的网站这个文件删了,你的支付也就不能用了,今天我就把大家需要的这两个asp微信支付代码证书文件post_url. ...

  2. Delphi微信支付【支持MD5和HMAC-SHA256签名与验签】

    作者QQ:(648437169) 点击下载➨微信支付            微信支付api文档 [Delphi 微信支付]支持付款码支付.二维码支付.订单查询.申请退款.退款查询.撤销订单.关闭订单. ...

  3. DELPHI支付宝支付代码

    真实业务场景的考虑 按照支付宝或者微信支付的开发手册的说法,一个标准的客户端接入支付业务模型应该是这样的,我忽略时序图,只用文字描述: 用户登录客户端,选择商品,然后点击客户端支付. 客户端收集商品信 ...

  4. asp微信支付代码v4.1无需证书版,带回调入库的asp支付源码

    昨天帮一个客户写的,他的程序是老的asp,想实现微信在手机上下单付款,让帮忙给写一份asp微信支付的接口代码,昨天晚上闲着没事,搞了一个晚上才搞好,其实asp支付并不需要安装证书,其实asp支付也很好 ...

  5. asp.net mvc 微信支付代码分析(根据沐雪微信平台3.1商城业务来分析)

    开发微信应用,微信支付是永远要面对的.现在的微信支付相对以往已经很稳定,很少出现诡异情况.再加上无数人开发的经验分享,现在开发微信支付已经没什么难度了. 我这次主要是想基于沐雪微信平台的微商城业务来分 ...

  6. JAVA微信支付代码(WeChatPay.java 才是调用类)

    微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html MD5Util.java package weixin; import java.se ...

  7. vue-cli中进行微信支付代码详解

    最近做微信支付,颇经历一番波折,这里总结一下,便于以后少走弯路: 在进行微信支付,除了需要公众号之外,你还需要一个微信商户.根据商户规则进行商户申请 这是公众号的基本开发配置,这里在微信授权的时候就已 ...

  8. ecshop增加pc扫描二维码微信支付功能代码

    ecshop开发网站,如果没有手机版,又想通过微信支付,可以加入pc二维码扫描微信支付功能 工具/原料 ecshop商城系统,phpqrcode,WxPayPubHelper 公众号已申请微信支付 方 ...

  9. 集成微信支付的代码。兼容小程序,扫码,app,公众号。h5 支付 ,以及 服务商提现

      /** * 因为微信总是很多个商户号很多和appid.很多个密钥文件,所以全部改成手动传值的方式,就可以支持多商户调用 * * @param appId 商户的appid * @param mch ...

随机推荐

  1. Latex基本用法

    空格 需要使用 \qquad,\quad,\,应该是占位符和变量之间需要有{}相隔. $$ C_{1} \qquad {C_2} $$ $$ C_{1} \quad {C_2} $$ $$ C_{1} ...

  2. PHP编程时的规范化命名

    要想成为一名“合格”的程序员,就必须要有良好的编程习惯和规范,这样做的好处有很多,诸如:可以提高代码质量,提高程序的可维护性,提高开发速度和效率等.以下就简要的列出几条日常编写程序时大概要注意的一些“ ...

  3. Luogu 2051[AHOI2009]中国象棋 - DP

    Description 在 $n * m$ 的格子上放若干个炮, 使得每个炮都不能攻击到其他炮 Solution 定义数组f[ i ][ j ][ k ] 表示到了第 i 行, 已经有2个炮的列数为 ...

  4. jquery纯数字验证

    $(document).ready(function(){  //纯数字验证,只让输入数字,比如-号等都不然输入.  $('#user-defined').unbind();  $('#user-de ...

  5. 【Web】网页字体图标的使用

    字体图标介绍 网页中图片有很多优点,但也有很多缺点,会增加文件的大小以及增加http请求.这时候就需要用的字体图标(iconfont).字体图标的优点,可以跟图片一样改变透明度.旋转等,本质上是文字, ...

  6. Python之内置函数一

    一:绝对值,abs i = abs(-123) print(i) # 打印结果 123 二:判断真假,all,与any 对于all # 每个元素都为真,才是True # 假,0,None," ...

  7. Time.fixedDeltaTime和Time.DeltaTime

    在Update中使用 Time.deltaTime,获取到的是这一帧的时间,如果游戏卡,帧率低,那这个值就大.如果游戏流畅,帧率高,这个值就小,Time.deltaTime = 1.0f / 帧率 在 ...

  8. HTML 内 meta标签

    <!-- 是否删除默认的苹果工具栏和菜单栏 --> <meta name="apple-mobile-web-app-capable" content=" ...

  9. html-day04

    html-day04 1.html属性的弊端 1.完成相同的功能需要不同的属性支持 2.可维护性不高2.CSS 1.什么是CSS Cascading Style Sheet 层叠样式表.级联样式表.样 ...

  10. 2018.11.06 bzoj1097: [POI2007]旅游景点atr(最短路+状压dp)

    传送门 预处理出不能在每个点停留之后才停留的点的状态. 对kkk个点都跑一次最短路存下来之后只需要简单状压一下就能过了吐槽原题空间64MB蒟蒻无能为力 然后用fillfillfill赋极大值的时候当m ...